aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/rc/redrat3.c
diff options
context:
space:
mode:
authorSean Young <sean@mess.org>2013-07-30 18:00:04 -0400
committerMauro Carvalho Chehab <m.chehab@samsung.com>2013-08-22 10:48:02 -0400
commitbf139726892c3e81538dd33d96cdf18eba6c1e53 (patch)
tree28b5a6dff08960c5cd0590eb5ada445ebd84df16 /drivers/media/rc/redrat3.c
parent153a60bb0faca59bfde313d4c713d9420e475b75 (diff)
[media] redrat3: wire up rc feedback led
Signed-off-by: Sean Young <sean@mess.org> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/rc/redrat3.c')
-rw-r--r--drivers/media/rc/redrat3.c83
1 files changed, 80 insertions, 3 deletions
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index ccd267f131fa..094484fac94c 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -47,6 +47,7 @@
47 47
48#include <asm/unaligned.h> 48#include <asm/unaligned.h>
49#include <linux/device.h> 49#include <linux/device.h>
50#include <linux/leds.h>
50#include <linux/module.h> 51#include <linux/module.h>
51#include <linux/slab.h> 52#include <linux/slab.h>
52#include <linux/usb.h> 53#include <linux/usb.h>
@@ -186,6 +187,13 @@ struct redrat3_dev {
186 struct rc_dev *rc; 187 struct rc_dev *rc;
187 struct device *dev; 188 struct device *dev;
188 189
190 /* led control */
191 struct led_classdev led;
192 atomic_t flash;
193 struct usb_ctrlrequest flash_control;
194 struct urb *flash_urb;
195 u8 flash_in_buf;
196
189 /* save off the usb device pointer */ 197 /* save off the usb device pointer */
190 struct usb_device *udev; 198 struct usb_device *udev;
191 199
@@ -480,9 +488,9 @@ static inline void redrat3_delete(struct redrat3_dev *rr3,
480{ 488{
481 rr3_ftr(rr3->dev, "%s cleaning up\n", __func__); 489 rr3_ftr(rr3->dev, "%s cleaning up\n", __func__);
482 usb_kill_urb(rr3->read_urb); 490 usb_kill_urb(rr3->read_urb);
483 491 usb_kill_urb(rr3->flash_urb);
484 usb_free_urb(rr3->read_urb); 492 usb_free_urb(rr3->read_urb);
485 493 usb_free_urb(rr3->flash_urb);
486 usb_free_coherent(udev, le16_to_cpu(rr3->ep_in->wMaxPacketSize), 494 usb_free_coherent(udev, le16_to_cpu(rr3->ep_in->wMaxPacketSize),
487 rr3->bulk_in_buf, rr3->dma_in); 495 rr3->bulk_in_buf, rr3->dma_in);
488 496
@@ -850,6 +858,44 @@ out:
850 return ret; 858 return ret;
851} 859}
852 860
861static void redrat3_brightness_set(struct led_classdev *led_dev, enum
862 led_brightness brightness)
863{
864 struct redrat3_dev *rr3 = container_of(led_dev, struct redrat3_dev,
865 led);
866
867 if (brightness != LED_OFF && atomic_cmpxchg(&rr3->flash, 0, 1) == 0) {
868 int ret = usb_submit_urb(rr3->flash_urb, GFP_ATOMIC);
869 if (ret != 0) {
870 dev_dbg(rr3->dev, "%s: unexpected ret of %d\n",
871 __func__, ret);
872 atomic_set(&rr3->flash, 0);
873 }
874 }
875}
876
877static void redrat3_led_complete(struct urb *urb)
878{
879 struct redrat3_dev *rr3 = urb->context;
880
881 switch (urb->status) {
882 case 0:
883 break;
884 case -ECONNRESET:
885 case -ENOENT:
886 case -ESHUTDOWN:
887 usb_unlink_urb(urb);
888 return;
889 case -EPIPE:
890 default:
891 dev_dbg(rr3->dev, "Error: urb status = %d\n", urb->status);
892 break;
893 }
894
895 rr3->led.brightness = LED_OFF;
896 atomic_dec(&rr3->flash);
897}
898
853static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3) 899static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3)
854{ 900{
855 struct device *dev = rr3->dev; 901 struct device *dev = rr3->dev;
@@ -993,10 +1039,35 @@ static int redrat3_dev_probe(struct usb_interface *intf,
993 /* default.. will get overridden by any sends with a freq defined */ 1039 /* default.. will get overridden by any sends with a freq defined */
994 rr3->carrier = 38000; 1040 rr3->carrier = 38000;
995 1041
1042 /* led control */
1043 rr3->led.name = "redrat3:red:feedback";
1044 rr3->led.default_trigger = "rc-feedback";
1045 rr3->led.brightness_set = redrat3_brightness_set;
1046 retval = led_classdev_register(&intf->dev, &rr3->led);
1047 if (retval)
1048 goto error;
1049
1050 atomic_set(&rr3->flash, 0);
1051 rr3->flash_urb = usb_alloc_urb(0, GFP_KERNEL);
1052 if (!rr3->flash_urb) {
1053 retval = -ENOMEM;
1054 goto led_free_error;
1055 }
1056
1057 /* setup packet is 'c0 b9 0000 0000 0001' */
1058 rr3->flash_control.bRequestType = 0xc0;
1059 rr3->flash_control.bRequest = RR3_BLINK_LED;
1060 rr3->flash_control.wLength = cpu_to_le16(1);
1061
1062 usb_fill_control_urb(rr3->flash_urb, udev, usb_rcvctrlpipe(udev, 0),
1063 (unsigned char *)&rr3->flash_control,
1064 &rr3->flash_in_buf, sizeof(rr3->flash_in_buf),
1065 redrat3_led_complete, rr3);
1066
996 rr3->rc = redrat3_init_rc_dev(rr3); 1067 rr3->rc = redrat3_init_rc_dev(rr3);
997 if (!rr3->rc) { 1068 if (!rr3->rc) {
998 retval = -ENOMEM; 1069 retval = -ENOMEM;
999 goto error; 1070 goto led_free_error;
1000 } 1071 }
1001 setup_timer(&rr3->rx_timeout, redrat3_rx_timeout, (unsigned long)rr3); 1072 setup_timer(&rr3->rx_timeout, redrat3_rx_timeout, (unsigned long)rr3);
1002 1073
@@ -1006,6 +1077,8 @@ static int redrat3_dev_probe(struct usb_interface *intf,
1006 rr3_ftr(dev, "Exiting %s\n", __func__); 1077 rr3_ftr(dev, "Exiting %s\n", __func__);
1007 return 0; 1078 return 0;
1008 1079
1080led_free_error:
1081 led_classdev_unregister(&rr3->led);
1009error: 1082error:
1010 redrat3_delete(rr3, rr3->udev); 1083 redrat3_delete(rr3, rr3->udev);
1011 1084
@@ -1027,6 +1100,7 @@ static void redrat3_dev_disconnect(struct usb_interface *intf)
1027 1100
1028 usb_set_intfdata(intf, NULL); 1101 usb_set_intfdata(intf, NULL);
1029 rc_unregister_device(rr3->rc); 1102 rc_unregister_device(rr3->rc);
1103 led_classdev_unregister(&rr3->led);
1030 del_timer_sync(&rr3->rx_timeout); 1104 del_timer_sync(&rr3->rx_timeout);
1031 redrat3_delete(rr3, udev); 1105 redrat3_delete(rr3, udev);
1032 1106
@@ -1037,7 +1111,9 @@ static int redrat3_dev_suspend(struct usb_interface *intf, pm_message_t message)
1037{ 1111{
1038 struct redrat3_dev *rr3 = usb_get_intfdata(intf); 1112 struct redrat3_dev *rr3 = usb_get_intfdata(intf);
1039 rr3_ftr(rr3->dev, "suspend\n"); 1113 rr3_ftr(rr3->dev, "suspend\n");
1114 led_classdev_suspend(&rr3->led);
1040 usb_kill_urb(rr3->read_urb); 1115 usb_kill_urb(rr3->read_urb);
1116 usb_kill_urb(rr3->flash_urb);
1041 return 0; 1117 return 0;
1042} 1118}
1043 1119
@@ -1047,6 +1123,7 @@ static int redrat3_dev_resume(struct usb_interface *intf)
1047 rr3_ftr(rr3->dev, "resume\n"); 1123 rr3_ftr(rr3->dev, "resume\n");
1048 if (usb_submit_urb(rr3->read_urb, GFP_ATOMIC)) 1124 if (usb_submit_urb(rr3->read_urb, GFP_ATOMIC))
1049 return -EIO; 1125 return -EIO;
1126 led_classdev_resume(&rr3->led);
1050 return 0; 1127 return 0;
1051} 1128}
1052 1129