Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] redrat3: enable carrier reports using wideband receiver

The wideband receiver is a little awkward on the redrat3. Data arrives
on a different endpoint, and the learning command must be reissued
every time data is learned.

Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>

authored by

Sean Young and committed by
Mauro Carvalho Chehab
c49fcdde 8a21ec9b

+140 -46
+140 -46
drivers/media/rc/redrat3.c
··· 81 81 #define RR3_RC_DET_ENABLE 0xbb 82 82 /* Stop capture with the RC receiver */ 83 83 #define RR3_RC_DET_DISABLE 0xbc 84 + /* Start capture with the wideband receiver */ 85 + #define RR3_MODSIG_CAPTURE 0xb2 84 86 /* Return the status of RC detector capture */ 85 87 #define RR3_RC_DET_STATUS 0xbd 86 88 /* Reset redrat */ ··· 107 105 #define RR3_CLK_PER_COUNT 12 108 106 /* (RR3_CLK / RR3_CLK_PER_COUNT) */ 109 107 #define RR3_CLK_CONV_FACTOR 2000000 110 - /* USB bulk-in IR data endpoint address */ 111 - #define RR3_BULK_IN_EP_ADDR 0x82 108 + /* USB bulk-in wideband IR data endpoint address */ 109 + #define RR3_WIDE_IN_EP_ADDR 0x81 110 + /* USB bulk-in narrowband IR data endpoint address */ 111 + #define RR3_NARROW_IN_EP_ADDR 0x82 112 112 113 113 /* Size of the fixed-length portion of the signal */ 114 114 #define RR3_DRIVER_MAXLENS 128 ··· 211 207 struct urb *flash_urb; 212 208 u8 flash_in_buf; 213 209 210 + /* learning */ 211 + bool wideband; 212 + struct usb_ctrlrequest learn_control; 213 + struct urb *learn_urb; 214 + u8 learn_buf; 215 + 214 216 /* save off the usb device pointer */ 215 217 struct usb_device *udev; 216 218 217 219 /* the receive endpoint */ 218 - struct usb_endpoint_descriptor *ep_in; 220 + struct usb_endpoint_descriptor *ep_narrow; 219 221 /* the buffer to receive data */ 220 222 void *bulk_in_buf; 221 223 /* urb used to read ir data */ 222 - struct urb *read_urb; 224 + struct urb *narrow_urb; 225 + struct urb *wide_urb; 223 226 224 227 /* the send endpoint */ 225 228 struct usb_endpoint_descriptor *ep_out; ··· 246 235 char name[64]; 247 236 char phys[64]; 248 237 }; 249 - 250 - /* 251 - * redrat3_issue_async 252 - * 253 - * Issues an async read to the ir data in port.. 254 - * sets the callback to be redrat3_handle_async 255 - */ 256 - static void redrat3_issue_async(struct redrat3_dev *rr3) 257 - { 258 - int res; 259 - 260 - res = usb_submit_urb(rr3->read_urb, GFP_ATOMIC); 261 - if (res) 262 - dev_dbg(rr3->dev, 263 - "%s: receive request FAILED! (res %d, len %d)\n", 264 - __func__, res, rr3->read_urb->transfer_buffer_length); 265 - } 266 238 267 239 static void redrat3_dump_fw_error(struct redrat3_dev *rr3, int code) 268 240 { ··· 361 367 362 368 mod_freq = redrat3_val_to_mod_freq(&rr3->irdata); 363 369 dev_dbg(dev, "Got mod_freq of %u\n", mod_freq); 370 + if (mod_freq && rr3->wideband) { 371 + DEFINE_IR_RAW_EVENT(ev); 372 + 373 + ev.carrier_report = 1; 374 + ev.carrier = mod_freq; 375 + 376 + ir_raw_event_store(rr3->rc, &ev); 377 + } 364 378 365 379 /* process each rr3 encoded byte into an int */ 366 380 sig_size = be16_to_cpu(rr3->irdata.sig_size); ··· 451 449 return -EIO; 452 450 } 453 451 454 - redrat3_issue_async(rr3); 452 + ret = usb_submit_urb(rr3->narrow_urb, GFP_KERNEL); 453 + if (ret) { 454 + dev_err(rr3->dev, "narrow band urb failed: %d", ret); 455 + return ret; 456 + } 455 457 456 - return 0; 458 + ret = usb_submit_urb(rr3->wide_urb, GFP_KERNEL); 459 + if (ret) 460 + dev_err(rr3->dev, "wide band urb failed: %d", ret); 461 + 462 + return ret; 457 463 } 458 464 459 465 static inline void redrat3_delete(struct redrat3_dev *rr3, 460 466 struct usb_device *udev) 461 467 { 462 - usb_kill_urb(rr3->read_urb); 468 + usb_kill_urb(rr3->narrow_urb); 469 + usb_kill_urb(rr3->wide_urb); 463 470 usb_kill_urb(rr3->flash_urb); 464 - usb_free_urb(rr3->read_urb); 471 + usb_kill_urb(rr3->learn_urb); 472 + usb_free_urb(rr3->narrow_urb); 473 + usb_free_urb(rr3->wide_urb); 465 474 usb_free_urb(rr3->flash_urb); 466 - usb_free_coherent(udev, le16_to_cpu(rr3->ep_in->wMaxPacketSize), 475 + usb_free_urb(rr3->learn_urb); 476 + usb_free_coherent(udev, le16_to_cpu(rr3->ep_narrow->wMaxPacketSize), 467 477 rr3->bulk_in_buf, rr3->dma_in); 468 478 469 479 kfree(rr3); ··· 708 694 switch (urb->status) { 709 695 case 0: 710 696 ret = redrat3_get_ir_data(rr3, urb->actual_length); 697 + if (!ret && rr3->wideband && !rr3->learn_urb->hcpriv) { 698 + ret = usb_submit_urb(rr3->learn_urb, GFP_ATOMIC); 699 + if (ret) 700 + dev_err(rr3->dev, "Failed to submit learning urb: %d", 701 + ret); 702 + } 703 + 711 704 if (!ret) { 712 705 /* no error, prepare to read more */ 713 - redrat3_issue_async(rr3); 706 + ret = usb_submit_urb(urb, GFP_ATOMIC); 707 + if (ret) 708 + dev_err(rr3->dev, "Failed to resubmit urb: %d", 709 + ret); 714 710 } 715 711 break; 716 712 ··· 880 856 } 881 857 } 882 858 859 + static int redrat3_wideband_receiver(struct rc_dev *rcdev, int enable) 860 + { 861 + struct redrat3_dev *rr3 = rcdev->priv; 862 + int ret = 0; 863 + 864 + rr3->wideband = enable != 0; 865 + 866 + if (enable) { 867 + ret = usb_submit_urb(rr3->learn_urb, GFP_KERNEL); 868 + if (ret) 869 + dev_err(rr3->dev, "Failed to submit learning urb: %d", 870 + ret); 871 + } 872 + 873 + return ret; 874 + } 875 + 876 + static void redrat3_learn_complete(struct urb *urb) 877 + { 878 + struct redrat3_dev *rr3 = urb->context; 879 + 880 + switch (urb->status) { 881 + case 0: 882 + break; 883 + case -ECONNRESET: 884 + case -ENOENT: 885 + case -ESHUTDOWN: 886 + usb_unlink_urb(urb); 887 + return; 888 + case -EPIPE: 889 + default: 890 + dev_err(rr3->dev, "Error: learn urb status = %d", urb->status); 891 + break; 892 + } 893 + } 894 + 883 895 static void redrat3_led_complete(struct urb *urb) 884 896 { 885 897 struct redrat3_dev *rr3 = urb->context; ··· 968 908 rc->s_timeout = redrat3_set_timeout; 969 909 rc->tx_ir = redrat3_transmit_ir; 970 910 rc->s_tx_carrier = redrat3_set_tx_carrier; 911 + rc->s_carrier_report = redrat3_wideband_receiver; 971 912 rc->driver_name = DRIVER_NAME; 972 913 rc->rx_resolution = US_TO_NS(2); 973 914 rc->map_name = RC_MAP_HAUPPAUGE; ··· 994 933 struct usb_host_interface *uhi; 995 934 struct redrat3_dev *rr3; 996 935 struct usb_endpoint_descriptor *ep; 997 - struct usb_endpoint_descriptor *ep_in = NULL; 936 + struct usb_endpoint_descriptor *ep_narrow = NULL; 937 + struct usb_endpoint_descriptor *ep_wide = NULL; 998 938 struct usb_endpoint_descriptor *ep_out = NULL; 999 939 u8 addr, attrs; 1000 940 int pipe, i; ··· 1009 947 addr = ep->bEndpointAddress; 1010 948 attrs = ep->bmAttributes; 1011 949 1012 - if ((ep_in == NULL) && 1013 - ((addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && 950 + if (((addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && 1014 951 ((attrs & USB_ENDPOINT_XFERTYPE_MASK) == 1015 952 USB_ENDPOINT_XFER_BULK)) { 1016 953 dev_dbg(dev, "found bulk-in endpoint at 0x%02x\n", 1017 954 ep->bEndpointAddress); 1018 - /* data comes in on 0x82, 0x81 is for other data... */ 1019 - if (ep->bEndpointAddress == RR3_BULK_IN_EP_ADDR) 1020 - ep_in = ep; 955 + /* data comes in on 0x82, 0x81 is for learning */ 956 + if (ep->bEndpointAddress == RR3_NARROW_IN_EP_ADDR) 957 + ep_narrow = ep; 958 + if (ep->bEndpointAddress == RR3_WIDE_IN_EP_ADDR) 959 + ep_wide = ep; 1021 960 } 1022 961 1023 962 if ((ep_out == NULL) && ··· 1031 968 } 1032 969 } 1033 970 1034 - if (!ep_in || !ep_out) { 1035 - dev_err(dev, "Couldn't find both in and out endpoints\n"); 971 + if (!ep_narrow || !ep_out || !ep_wide) { 972 + dev_err(dev, "Couldn't find all endpoints\n"); 1036 973 retval = -ENODEV; 1037 974 goto no_endpoints; 1038 975 } ··· 1043 980 goto no_endpoints; 1044 981 1045 982 rr3->dev = &intf->dev; 1046 - rr3->ep_in = ep_in; 983 + rr3->ep_narrow = ep_narrow; 1047 984 rr3->ep_out = ep_out; 1048 985 rr3->udev = udev; 1049 986 1050 987 /* set up bulk-in endpoint */ 1051 - rr3->read_urb = usb_alloc_urb(0, GFP_KERNEL); 1052 - if (!rr3->read_urb) 988 + rr3->narrow_urb = usb_alloc_urb(0, GFP_KERNEL); 989 + if (!rr3->narrow_urb) 990 + goto redrat_free; 991 + 992 + rr3->wide_urb = usb_alloc_urb(0, GFP_KERNEL); 993 + if (!rr3->wide_urb) 1053 994 goto redrat_free; 1054 995 1055 996 rr3->bulk_in_buf = usb_alloc_coherent(udev, 1056 - le16_to_cpu(ep_in->wMaxPacketSize), GFP_KERNEL, &rr3->dma_in); 997 + le16_to_cpu(ep_narrow->wMaxPacketSize), 998 + GFP_KERNEL, &rr3->dma_in); 1057 999 if (!rr3->bulk_in_buf) 1058 1000 goto redrat_free; 1059 1001 1060 - pipe = usb_rcvbulkpipe(udev, ep_in->bEndpointAddress); 1061 - usb_fill_bulk_urb(rr3->read_urb, udev, pipe, rr3->bulk_in_buf, 1062 - le16_to_cpu(ep_in->wMaxPacketSize), redrat3_handle_async, rr3); 1063 - rr3->read_urb->transfer_dma = rr3->dma_in; 1064 - rr3->read_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 1002 + pipe = usb_rcvbulkpipe(udev, ep_narrow->bEndpointAddress); 1003 + usb_fill_bulk_urb(rr3->narrow_urb, udev, pipe, rr3->bulk_in_buf, 1004 + le16_to_cpu(ep_narrow->wMaxPacketSize), 1005 + redrat3_handle_async, rr3); 1006 + rr3->narrow_urb->transfer_dma = rr3->dma_in; 1007 + rr3->narrow_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 1008 + 1009 + pipe = usb_rcvbulkpipe(udev, ep_wide->bEndpointAddress); 1010 + usb_fill_bulk_urb(rr3->wide_urb, udev, pipe, rr3->bulk_in_buf, 1011 + le16_to_cpu(ep_narrow->wMaxPacketSize), 1012 + redrat3_handle_async, rr3); 1013 + rr3->wide_urb->transfer_dma = rr3->dma_in; 1014 + rr3->wide_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 1065 1015 1066 1016 redrat3_reset(rr3); 1067 1017 redrat3_get_firmware_rev(rr3); ··· 1086 1010 rr3->flash_urb = usb_alloc_urb(0, GFP_KERNEL); 1087 1011 if (!rr3->flash_urb) 1088 1012 goto redrat_free; 1013 + 1014 + /* learn urb */ 1015 + rr3->learn_urb = usb_alloc_urb(0, GFP_KERNEL); 1016 + if (!rr3->learn_urb) 1017 + goto redrat_free; 1018 + 1019 + /* setup packet is 'c0 b2 0000 0000 0001' */ 1020 + rr3->learn_control.bRequestType = 0xc0; 1021 + rr3->learn_control.bRequest = RR3_MODSIG_CAPTURE; 1022 + rr3->learn_control.wLength = cpu_to_le16(1); 1023 + 1024 + usb_fill_control_urb(rr3->learn_urb, udev, usb_rcvctrlpipe(udev, 0), 1025 + (unsigned char *)&rr3->learn_control, 1026 + &rr3->learn_buf, sizeof(rr3->learn_buf), 1027 + redrat3_learn_complete, rr3); 1089 1028 1090 1029 /* setup packet is 'c0 b9 0000 0000 0001' */ 1091 1030 rr3->flash_control.bRequestType = 0xc0; ··· 1161 1070 struct redrat3_dev *rr3 = usb_get_intfdata(intf); 1162 1071 1163 1072 led_classdev_suspend(&rr3->led); 1164 - usb_kill_urb(rr3->read_urb); 1073 + usb_kill_urb(rr3->narrow_urb); 1074 + usb_kill_urb(rr3->wide_urb); 1165 1075 usb_kill_urb(rr3->flash_urb); 1166 1076 return 0; 1167 1077 } ··· 1171 1079 { 1172 1080 struct redrat3_dev *rr3 = usb_get_intfdata(intf); 1173 1081 1174 - if (usb_submit_urb(rr3->read_urb, GFP_ATOMIC)) 1082 + if (usb_submit_urb(rr3->narrow_urb, GFP_ATOMIC)) 1083 + return -EIO; 1084 + if (usb_submit_urb(rr3->wide_urb, GFP_ATOMIC)) 1175 1085 return -EIO; 1176 1086 led_classdev_resume(&rr3->led); 1177 1087 return 0;