diff options
author | Sean Young <sean@mess.org> | 2013-07-30 18:00:04 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2013-08-22 10:48:02 -0400 |
commit | bf139726892c3e81538dd33d96cdf18eba6c1e53 (patch) | |
tree | 28b5a6dff08960c5cd0590eb5ada445ebd84df16 /drivers/media/rc/redrat3.c | |
parent | 153a60bb0faca59bfde313d4c713d9420e475b75 (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.c | 83 |
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 | ||
861 | static 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 | |||
877 | static 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 | |||
853 | static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3) | 899 | static 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 | ||
1080 | led_free_error: | ||
1081 | led_classdev_unregister(&rr3->led); | ||
1009 | error: | 1082 | error: |
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 | ||