Lines Matching +full:detector +full:- +full:enable

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * USB RedRat3 IR Transceiver rc-core driver
9 * This driver began life based on an old version of the first-generation
14 * The driver was then ported to rc-core and significantly rewritten again,
15 * by Jarod, using the in-kernel mceusb driver as a guide, after an initial
19 * - fix lirc not showing repeats properly
20 * --
23 * with 2 separate sensors available for receive to enable
31 * --
41 #include <media/rc-core.h>
57 /* Send encoded signal bulk-sent earlier*/
72 /* Return the status of RC detector capture */
90 /* Clock freq. of EZ-USB chip */
96 /* USB bulk-in wideband IR data endpoint address */
98 /* USB bulk-in narrowband IR data endpoint address */
101 /* Size of the fixed-length portion of the signal */
127 MODULE_PARM_DESC(length_fuzz, "Length Fuzz (0-127)");
138 MODULE_PARM_DESC(minimum_pause, "Minimum Pause in ms (2-30)");
149 MODULE_PARM_DESC(periods_measure_carrier, "Number of Periods to Measure Carrier (1-255)");
182 /* Second Version/release of the RedRat3 - RetRat3-II */
238 if (!rr3->transmitting && (code != 0x40)) in redrat3_dump_fw_error()
239 dev_info(rr3->dev, "fw error code 0x%02x: ", code); in redrat3_dump_fw_error()
276 if (!rr3->transmitting) in redrat3_dump_fw_error()
295 u16 mod_freq_count = be16_to_cpu(irdata->mod_freq_count); in redrat3_val_to_mod_freq()
298 mod_freq = (RR3_CLK * be16_to_cpu(irdata->num_periods)) / in redrat3_val_to_mod_freq()
319 * ------------- = ---------------- = micro
323 * ----- = 4 ----- = 6 -------------- = len ---------------------
346 dev = rr3->dev; in redrat3_process_ir_data()
348 mod_freq = redrat3_val_to_mod_freq(&rr3->irdata); in redrat3_process_ir_data()
350 if (mod_freq && rr3->wideband) { in redrat3_process_ir_data()
356 ir_raw_event_store(rr3->rc, &ev); in redrat3_process_ir_data()
360 sig_size = be16_to_cpu(rr3->irdata.sig_size); in redrat3_process_ir_data()
362 offset = rr3->irdata.sigdata[i]; in redrat3_process_ir_data()
363 val = get_unaligned_be16(&rr3->irdata.lens[offset]); in redrat3_process_ir_data()
378 ir_raw_event_store_with_filter(rr3->rc, &rawir); in redrat3_process_ir_data()
384 rawir.duration = rr3->rc->timeout; in redrat3_process_ir_data()
387 ir_raw_event_store_with_filter(rr3->rc, &rawir); in redrat3_process_ir_data()
390 ir_raw_event_handle(rr3->rc); in redrat3_process_ir_data()
402 return -ENOMEM; in redrat3_send_cmd()
404 udev = rr3->udev; in redrat3_send_cmd()
410 dev_err(rr3->dev, "%s: Error sending rr3 cmd res %d, data %d", in redrat3_send_cmd()
412 res = -EIO; in redrat3_send_cmd()
421 /* Enables the long range detector and starts async receive */
424 struct device *dev = rr3->dev; in redrat3_enable_detector()
434 dev_err(dev, "%s: detector status: %d, should be 1\n", in redrat3_enable_detector()
436 return -EIO; in redrat3_enable_detector()
439 ret = usb_submit_urb(rr3->narrow_urb, GFP_KERNEL); in redrat3_enable_detector()
441 dev_err(rr3->dev, "narrow band urb failed: %d", ret); in redrat3_enable_detector()
445 ret = usb_submit_urb(rr3->wide_urb, GFP_KERNEL); in redrat3_enable_detector()
447 dev_err(rr3->dev, "wide band urb failed: %d", ret); in redrat3_enable_detector()
455 usb_kill_urb(rr3->narrow_urb); in redrat3_delete()
456 usb_kill_urb(rr3->wide_urb); in redrat3_delete()
457 usb_kill_urb(rr3->flash_urb); in redrat3_delete()
458 usb_kill_urb(rr3->learn_urb); in redrat3_delete()
459 usb_free_urb(rr3->narrow_urb); in redrat3_delete()
460 usb_free_urb(rr3->wide_urb); in redrat3_delete()
461 usb_free_urb(rr3->flash_urb); in redrat3_delete()
462 usb_free_urb(rr3->learn_urb); in redrat3_delete()
463 usb_free_coherent(udev, le16_to_cpu(rr3->ep_narrow->wMaxPacketSize), in redrat3_delete()
464 rr3->bulk_in_buf, rr3->dma_in); in redrat3_delete()
480 pipe = usb_rcvctrlpipe(rr3->udev, 0); in redrat3_get_timeout()
481 ret = usb_control_msg(rr3->udev, pipe, RR3_GET_IR_PARAM, in redrat3_get_timeout()
485 dev_warn(rr3->dev, "Failed to read timeout from hardware\n"); in redrat3_get_timeout()
489 dev_dbg(rr3->dev, "Got timeout of %d ms\n", timeout / 1000); in redrat3_get_timeout()
499 struct redrat3_dev *rr3 = rc_dev->priv; in redrat3_set_timeout()
500 struct usb_device *udev = rr3->udev; in redrat3_set_timeout()
501 struct device *dev = rr3->dev; in redrat3_set_timeout()
507 return -ENOMEM; in redrat3_set_timeout()
520 ret = -EIO; in redrat3_set_timeout()
529 struct usb_device *udev = rr3->udev; in redrat3_reset()
530 struct device *dev = rr3->dev; in redrat3_reset()
554 *val = (65536 - (minimum_pause * 2000)) / 256; in redrat3_reset()
585 rc = usb_control_msg(rr3->udev, usb_rcvctrlpipe(rr3->udev, 0), in redrat3_get_firmware_rev()
591 dev_info(rr3->dev, "Firmware rev: %s", buffer); in redrat3_get_firmware_rev()
593 dev_err(rr3->dev, "Problem fetching firmware ID\n"); in redrat3_get_firmware_rev()
600 struct redrat3_header *header = rr3->bulk_in_buf; in redrat3_read_packet_start()
604 pktlen = be16_to_cpu(header->length); in redrat3_read_packet_start()
605 pkttype = be16_to_cpu(header->transfer_type); in redrat3_read_packet_start()
607 if (pktlen > sizeof(rr3->irdata)) { in redrat3_read_packet_start()
608 dev_warn(rr3->dev, "packet length %u too large\n", pktlen); in redrat3_read_packet_start()
615 struct redrat3_error *error = rr3->bulk_in_buf; in redrat3_read_packet_start()
616 unsigned fw_error = be16_to_cpu(error->fw_error); in redrat3_read_packet_start()
622 memcpy(&rr3->irdata, rr3->bulk_in_buf, len); in redrat3_read_packet_start()
623 rr3->bytes_read = len; in redrat3_read_packet_start()
624 dev_dbg(rr3->dev, "bytes_read %d, pktlen %d\n", in redrat3_read_packet_start()
625 rr3->bytes_read, pktlen); in redrat3_read_packet_start()
629 dev_dbg(rr3->dev, "ignoring packet with type 0x%02x, len of %d, 0x%02x\n", in redrat3_read_packet_start()
637 void *irdata = &rr3->irdata; in redrat3_read_packet_continue()
639 if (len + rr3->bytes_read > sizeof(rr3->irdata)) { in redrat3_read_packet_continue()
640 dev_warn(rr3->dev, "too much data for packet\n"); in redrat3_read_packet_continue()
641 rr3->bytes_read = 0; in redrat3_read_packet_continue()
645 memcpy(irdata + rr3->bytes_read, rr3->bulk_in_buf, len); in redrat3_read_packet_continue()
647 rr3->bytes_read += len; in redrat3_read_packet_continue()
648 dev_dbg(rr3->dev, "bytes_read %d, pktlen %d\n", rr3->bytes_read, in redrat3_read_packet_continue()
649 be16_to_cpu(rr3->irdata.header.length)); in redrat3_read_packet_continue()
655 struct device *dev = rr3->dev; in redrat3_get_ir_data()
659 if (rr3->bytes_read == 0 && len >= sizeof(struct redrat3_header)) { in redrat3_get_ir_data()
661 } else if (rr3->bytes_read != 0) { in redrat3_get_ir_data()
663 } else if (rr3->bytes_read == 0) { in redrat3_get_ir_data()
665 ret = -ENODATA; in redrat3_get_ir_data()
669 if (rr3->bytes_read < be16_to_cpu(rr3->irdata.header.length) + in redrat3_get_ir_data()
675 pkttype = be16_to_cpu(rr3->irdata.header.transfer_type); in redrat3_get_ir_data()
679 dev_dbg(dev, "discarding non-signal data packet (type 0x%02x)\n", in redrat3_get_ir_data()
683 rr3->bytes_read = 0; in redrat3_get_ir_data()
690 struct redrat3_dev *rr3 = urb->context; in redrat3_handle_async()
693 switch (urb->status) { in redrat3_handle_async()
695 ret = redrat3_get_ir_data(rr3, urb->actual_length); in redrat3_handle_async()
696 if (!ret && rr3->wideband && !rr3->learn_urb->hcpriv) { in redrat3_handle_async()
697 ret = usb_submit_urb(rr3->learn_urb, GFP_ATOMIC); in redrat3_handle_async()
699 dev_err(rr3->dev, "Failed to submit learning urb: %d", in redrat3_handle_async()
707 dev_err(rr3->dev, "Failed to resubmit urb: %d", in redrat3_handle_async()
712 case -ECONNRESET: in redrat3_handle_async()
713 case -ENOENT: in redrat3_handle_async()
714 case -ESHUTDOWN: in redrat3_handle_async()
718 case -EPIPE: in redrat3_handle_async()
720 dev_warn(rr3->dev, "Error: urb status = %d\n", urb->status); in redrat3_handle_async()
721 rr3->bytes_read = 0; in redrat3_handle_async()
731 return 65536 - (mult / mod_freq); in mod_freq_to_val()
736 struct redrat3_dev *rr3 = rcdev->priv; in redrat3_set_tx_carrier()
737 struct device *dev = rr3->dev; in redrat3_set_tx_carrier()
741 return -EINVAL; in redrat3_set_tx_carrier()
743 rr3->carrier = carrier; in redrat3_set_tx_carrier()
751 struct redrat3_dev *rr3 = rcdev->priv; in redrat3_transmit_ir()
752 struct device *dev = rr3->dev; in redrat3_transmit_ir()
760 if (rr3->transmitting) { in redrat3_transmit_ir()
762 return -EAGAIN; in redrat3_transmit_ir()
765 if (count > RR3_MAX_SIG_SIZE - RR3_TX_TRAILER_LEN) in redrat3_transmit_ir()
766 return -EINVAL; in redrat3_transmit_ir()
768 /* rr3 will disable rc detector on transmit */ in redrat3_transmit_ir()
769 rr3->transmitting = true; in redrat3_transmit_ir()
775 return -ENOMEM; in redrat3_transmit_ir()
779 ret = -ENOMEM; in redrat3_transmit_ir()
802 &irdata->lens[curlencheck]); in redrat3_transmit_ir()
805 ret = -EINVAL; in redrat3_transmit_ir()
809 irdata->sigdata[i] = lencheck; in redrat3_transmit_ir()
812 irdata->sigdata[count] = RR3_END_OF_SIGNAL; in redrat3_transmit_ir()
813 irdata->sigdata[count + 1] = RR3_END_OF_SIGNAL; in redrat3_transmit_ir()
818 irdata->header.length = cpu_to_be16(sendbuf_len - in redrat3_transmit_ir()
820 irdata->header.transfer_type = cpu_to_be16(RR3_MOD_SIGNAL_OUT); in redrat3_transmit_ir()
821 irdata->pause = cpu_to_be32(redrat3_len_to_us(100)); in redrat3_transmit_ir()
822 irdata->mod_freq_count = cpu_to_be16(mod_freq_to_val(rr3->carrier)); in redrat3_transmit_ir()
823 irdata->no_lengths = curlencheck; in redrat3_transmit_ir()
824 irdata->sig_size = cpu_to_be16(count + RR3_TX_TRAILER_LEN); in redrat3_transmit_ir()
826 pipe = usb_sndbulkpipe(rr3->udev, rr3->ep_out->bEndpointAddress); in redrat3_transmit_ir()
827 ret = usb_bulk_msg(rr3->udev, pipe, irdata, in redrat3_transmit_ir()
832 pipe = usb_rcvctrlpipe(rr3->udev, 0); in redrat3_transmit_ir()
833 ret = usb_control_msg(rr3->udev, pipe, RR3_TX_SEND_SIGNAL, in redrat3_transmit_ir()
846 rr3->transmitting = false; in redrat3_transmit_ir()
847 /* rr3 re-enables rc detector because it was enabled before */ in redrat3_transmit_ir()
858 if (brightness != LED_OFF && atomic_cmpxchg(&rr3->flash, 0, 1) == 0) { in redrat3_brightness_set()
859 int ret = usb_submit_urb(rr3->flash_urb, GFP_ATOMIC); in redrat3_brightness_set()
861 dev_dbg(rr3->dev, "%s: unexpected ret of %d\n", in redrat3_brightness_set()
863 atomic_set(&rr3->flash, 0); in redrat3_brightness_set()
868 static int redrat3_wideband_receiver(struct rc_dev *rcdev, int enable) in redrat3_wideband_receiver() argument
870 struct redrat3_dev *rr3 = rcdev->priv; in redrat3_wideband_receiver()
873 rr3->wideband = enable != 0; in redrat3_wideband_receiver()
875 if (enable) { in redrat3_wideband_receiver()
876 ret = usb_submit_urb(rr3->learn_urb, GFP_KERNEL); in redrat3_wideband_receiver()
878 dev_err(rr3->dev, "Failed to submit learning urb: %d", in redrat3_wideband_receiver()
887 struct redrat3_dev *rr3 = urb->context; in redrat3_learn_complete()
889 switch (urb->status) { in redrat3_learn_complete()
892 case -ECONNRESET: in redrat3_learn_complete()
893 case -ENOENT: in redrat3_learn_complete()
894 case -ESHUTDOWN: in redrat3_learn_complete()
897 case -EPIPE: in redrat3_learn_complete()
899 dev_err(rr3->dev, "Error: learn urb status = %d", urb->status); in redrat3_learn_complete()
906 struct redrat3_dev *rr3 = urb->context; in redrat3_led_complete()
908 switch (urb->status) { in redrat3_led_complete()
911 case -ECONNRESET: in redrat3_led_complete()
912 case -ENOENT: in redrat3_led_complete()
913 case -ESHUTDOWN: in redrat3_led_complete()
916 case -EPIPE: in redrat3_led_complete()
918 dev_dbg(rr3->dev, "Error: urb status = %d\n", urb->status); in redrat3_led_complete()
922 rr3->led.brightness = LED_OFF; in redrat3_led_complete()
923 atomic_dec(&rr3->flash); in redrat3_led_complete()
928 struct device *dev = rr3->dev; in redrat3_init_rc_dev()
931 u16 prod = le16_to_cpu(rr3->udev->descriptor.idProduct); in redrat3_init_rc_dev()
937 snprintf(rr3->name, sizeof(rr3->name), in redrat3_init_rc_dev()
939 prod == USB_RR3IIUSB_PRODUCT_ID ? "-II" : ""); in redrat3_init_rc_dev()
941 usb_make_path(rr3->udev, rr3->phys, sizeof(rr3->phys)); in redrat3_init_rc_dev()
943 rc->device_name = rr3->name; in redrat3_init_rc_dev()
944 rc->input_phys = rr3->phys; in redrat3_init_rc_dev()
945 usb_to_input_id(rr3->udev, &rc->input_id); in redrat3_init_rc_dev()
946 rc->dev.parent = dev; in redrat3_init_rc_dev()
947 rc->priv = rr3; in redrat3_init_rc_dev()
948 rc->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER; in redrat3_init_rc_dev()
949 rc->min_timeout = MS_TO_US(RR3_RX_MIN_TIMEOUT); in redrat3_init_rc_dev()
950 rc->max_timeout = MS_TO_US(RR3_RX_MAX_TIMEOUT); in redrat3_init_rc_dev()
951 rc->timeout = redrat3_get_timeout(rr3); in redrat3_init_rc_dev()
952 rc->s_timeout = redrat3_set_timeout; in redrat3_init_rc_dev()
953 rc->tx_ir = redrat3_transmit_ir; in redrat3_init_rc_dev()
954 rc->s_tx_carrier = redrat3_set_tx_carrier; in redrat3_init_rc_dev()
955 rc->s_carrier_report = redrat3_wideband_receiver; in redrat3_init_rc_dev()
956 rc->driver_name = DRIVER_NAME; in redrat3_init_rc_dev()
957 rc->rx_resolution = 2; in redrat3_init_rc_dev()
958 rc->map_name = RC_MAP_HAUPPAUGE; in redrat3_init_rc_dev()
977 struct device *dev = &intf->dev; in redrat3_dev_probe()
986 int retval = -ENOMEM; in redrat3_dev_probe()
988 uhi = intf->cur_altsetting; in redrat3_dev_probe()
990 /* find our bulk-in and bulk-out endpoints */ in redrat3_dev_probe()
991 for (i = 0; i < uhi->desc.bNumEndpoints; ++i) { in redrat3_dev_probe()
992 ep = &uhi->endpoint[i].desc; in redrat3_dev_probe()
993 addr = ep->bEndpointAddress; in redrat3_dev_probe()
994 attrs = ep->bmAttributes; in redrat3_dev_probe()
999 dev_dbg(dev, "found bulk-in endpoint at 0x%02x\n", in redrat3_dev_probe()
1000 ep->bEndpointAddress); in redrat3_dev_probe()
1002 if (ep->bEndpointAddress == RR3_NARROW_IN_EP_ADDR) in redrat3_dev_probe()
1004 if (ep->bEndpointAddress == RR3_WIDE_IN_EP_ADDR) in redrat3_dev_probe()
1012 dev_dbg(dev, "found bulk-out endpoint at 0x%02x\n", in redrat3_dev_probe()
1013 ep->bEndpointAddress); in redrat3_dev_probe()
1020 retval = -ENODEV; in redrat3_dev_probe()
1029 rr3->dev = &intf->dev; in redrat3_dev_probe()
1030 rr3->ep_narrow = ep_narrow; in redrat3_dev_probe()
1031 rr3->ep_out = ep_out; in redrat3_dev_probe()
1032 rr3->udev = udev; in redrat3_dev_probe()
1034 /* set up bulk-in endpoint */ in redrat3_dev_probe()
1035 rr3->narrow_urb = usb_alloc_urb(0, GFP_KERNEL); in redrat3_dev_probe()
1036 if (!rr3->narrow_urb) in redrat3_dev_probe()
1039 rr3->wide_urb = usb_alloc_urb(0, GFP_KERNEL); in redrat3_dev_probe()
1040 if (!rr3->wide_urb) in redrat3_dev_probe()
1043 rr3->bulk_in_buf = usb_alloc_coherent(udev, in redrat3_dev_probe()
1044 le16_to_cpu(ep_narrow->wMaxPacketSize), in redrat3_dev_probe()
1045 GFP_KERNEL, &rr3->dma_in); in redrat3_dev_probe()
1046 if (!rr3->bulk_in_buf) in redrat3_dev_probe()
1049 pipe = usb_rcvbulkpipe(udev, ep_narrow->bEndpointAddress); in redrat3_dev_probe()
1050 usb_fill_bulk_urb(rr3->narrow_urb, udev, pipe, rr3->bulk_in_buf, in redrat3_dev_probe()
1051 le16_to_cpu(ep_narrow->wMaxPacketSize), in redrat3_dev_probe()
1053 rr3->narrow_urb->transfer_dma = rr3->dma_in; in redrat3_dev_probe()
1054 rr3->narrow_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; in redrat3_dev_probe()
1056 pipe = usb_rcvbulkpipe(udev, ep_wide->bEndpointAddress); in redrat3_dev_probe()
1057 usb_fill_bulk_urb(rr3->wide_urb, udev, pipe, rr3->bulk_in_buf, in redrat3_dev_probe()
1058 le16_to_cpu(ep_narrow->wMaxPacketSize), in redrat3_dev_probe()
1060 rr3->wide_urb->transfer_dma = rr3->dma_in; in redrat3_dev_probe()
1061 rr3->wide_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; in redrat3_dev_probe()
1067 rr3->carrier = 38000; in redrat3_dev_probe()
1069 atomic_set(&rr3->flash, 0); in redrat3_dev_probe()
1070 rr3->flash_urb = usb_alloc_urb(0, GFP_KERNEL); in redrat3_dev_probe()
1071 if (!rr3->flash_urb) in redrat3_dev_probe()
1075 rr3->learn_urb = usb_alloc_urb(0, GFP_KERNEL); in redrat3_dev_probe()
1076 if (!rr3->learn_urb) in redrat3_dev_probe()
1080 rr3->learn_control.bRequestType = 0xc0; in redrat3_dev_probe()
1081 rr3->learn_control.bRequest = RR3_MODSIG_CAPTURE; in redrat3_dev_probe()
1082 rr3->learn_control.wLength = cpu_to_le16(1); in redrat3_dev_probe()
1084 usb_fill_control_urb(rr3->learn_urb, udev, usb_rcvctrlpipe(udev, 0), in redrat3_dev_probe()
1085 (unsigned char *)&rr3->learn_control, in redrat3_dev_probe()
1086 &rr3->learn_buf, sizeof(rr3->learn_buf), in redrat3_dev_probe()
1090 rr3->flash_control.bRequestType = 0xc0; in redrat3_dev_probe()
1091 rr3->flash_control.bRequest = RR3_BLINK_LED; in redrat3_dev_probe()
1092 rr3->flash_control.wLength = cpu_to_le16(1); in redrat3_dev_probe()
1094 usb_fill_control_urb(rr3->flash_urb, udev, usb_rcvctrlpipe(udev, 0), in redrat3_dev_probe()
1095 (unsigned char *)&rr3->flash_control, in redrat3_dev_probe()
1096 &rr3->flash_in_buf, sizeof(rr3->flash_in_buf), in redrat3_dev_probe()
1100 rr3->led.name = "redrat3:red:feedback"; in redrat3_dev_probe()
1101 rr3->led.default_trigger = "rc-feedback"; in redrat3_dev_probe()
1102 rr3->led.brightness_set = redrat3_brightness_set; in redrat3_dev_probe()
1103 retval = led_classdev_register(&intf->dev, &rr3->led); in redrat3_dev_probe()
1107 rr3->rc = redrat3_init_rc_dev(rr3); in redrat3_dev_probe()
1108 if (!rr3->rc) { in redrat3_dev_probe()
1109 retval = -ENOMEM; in redrat3_dev_probe()
1124 led_classdev_unregister(&rr3->led); in redrat3_dev_probe()
1126 redrat3_delete(rr3, rr3->udev); in redrat3_dev_probe()
1138 rc_unregister_device(rr3->rc); in redrat3_dev_disconnect()
1139 led_classdev_unregister(&rr3->led); in redrat3_dev_disconnect()
1147 led_classdev_suspend(&rr3->led); in redrat3_dev_suspend()
1148 usb_kill_urb(rr3->narrow_urb); in redrat3_dev_suspend()
1149 usb_kill_urb(rr3->wide_urb); in redrat3_dev_suspend()
1150 usb_kill_urb(rr3->flash_urb); in redrat3_dev_suspend()
1158 if (usb_submit_urb(rr3->narrow_urb, GFP_NOIO)) in redrat3_dev_resume()
1159 return -EIO; in redrat3_dev_resume()
1160 if (usb_submit_urb(rr3->wide_urb, GFP_NOIO)) in redrat3_dev_resume()
1161 return -EIO; in redrat3_dev_resume()
1162 led_classdev_resume(&rr3->led); in redrat3_dev_resume()