From 6026ce07dca045a9edf4fb651a805b4574186d80 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Mon, 8 Jul 2013 17:33:08 -0300 Subject: [media] redrat3: errors on unplug In an usb disconnect handler, the urbs have already been cancelled so the attempt to disable the IR receiver just results in errors: [ 899.638862] redrat3 7-2:1.0: redrat3_send_cmd: Error sending rr3 cmd res -110, data 0 [ 899.638870] redrat3 7-2:1.0: redrat3_disable_detector: detector status: 251, should be 0 Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/redrat3.c | 27 --------------------------- 1 file changed, 27 deletions(-) (limited to 'drivers/media/rc/redrat3.c') diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c index 12167a6b5472..37494433dc9f 100644 --- a/drivers/media/rc/redrat3.c +++ b/drivers/media/rc/redrat3.c @@ -206,8 +206,6 @@ struct redrat3_dev { struct timer_list rx_timeout; u32 hw_timeout; - /* is the detector enabled*/ - bool det_enabled; /* Is the device currently transmitting?*/ bool transmitting; @@ -472,32 +470,11 @@ static int redrat3_enable_detector(struct redrat3_dev *rr3) return -EIO; } - rr3->det_enabled = true; redrat3_issue_async(rr3); return 0; } -/* Disables the rr3 long range detector */ -static void redrat3_disable_detector(struct redrat3_dev *rr3) -{ - struct device *dev = rr3->dev; - u8 ret; - - rr3_ftr(dev, "Entering %s\n", __func__); - - ret = redrat3_send_cmd(RR3_RC_DET_DISABLE, rr3); - if (ret != 0) - dev_err(dev, "%s: failure!\n", __func__); - - ret = redrat3_send_cmd(RR3_RC_DET_STATUS, rr3); - if (ret != 0) - dev_warn(dev, "%s: detector status: %d, should be 0\n", - __func__, ret); - - rr3->det_enabled = false; -} - static inline void redrat3_delete(struct redrat3_dev *rr3, struct usb_device *udev) { @@ -788,7 +765,6 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf, count = min_t(unsigned, count, RR3_MAX_SIG_SIZE - RR3_TX_TRAILER_LEN); /* rr3 will disable rc detector on transmit */ - rr3->det_enabled = false; rr3->transmitting = true; sample_lens = kzalloc(sizeof(int) * RR3_DRIVER_MAXLENS, GFP_KERNEL); @@ -868,7 +844,6 @@ out: rr3->transmitting = false; /* rr3 re-enables rc detector because it was enabled before */ - rr3->det_enabled = true; return ret; } @@ -1048,8 +1023,6 @@ static void redrat3_dev_disconnect(struct usb_interface *intf) if (!rr3) return; - redrat3_disable_detector(rr3); - usb_set_intfdata(intf, NULL); rc_unregister_device(rr3->rc); del_timer_sync(&rr3->rx_timeout); -- cgit v1.2.3 From 671ea6707b3fb051ec1bae8e7aa0a91f90e178e0 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Mon, 8 Jul 2013 17:33:09 -0300 Subject: [media] lirc: make transmit interface consistent All lirc drivers that can transmit, return EINVAL when they are passed more than IR data than they can send. That is, except for two drivers which I touched. Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/lirc_device_interface.xml | 4 +++- drivers/media/rc/iguanair.c | 4 ++-- drivers/media/rc/redrat3.c | 7 ++++--- 3 files changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/media/rc/redrat3.c') diff --git a/Documentation/DocBook/media/v4l/lirc_device_interface.xml b/Documentation/DocBook/media/v4l/lirc_device_interface.xml index 8d7eb6bf6312..34cada2ca710 100644 --- a/Documentation/DocBook/media/v4l/lirc_device_interface.xml +++ b/Documentation/DocBook/media/v4l/lirc_device_interface.xml @@ -46,7 +46,9 @@ describing an IR signal are read from the chardev. values. Pulses and spaces are only marked implicitly by their position. The data must start and end with a pulse, therefore, the data must always include an uneven number of samples. The write function must block until the data has -been transmitted by the hardware. +been transmitted by the hardware. If more data is provided than the hardware +can send, the driver returns EINVAL. +
diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c index a4ab2e6b3f82..19632b1c2190 100644 --- a/drivers/media/rc/iguanair.c +++ b/drivers/media/rc/iguanair.c @@ -364,8 +364,8 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count) periods = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000); bytes = DIV_ROUND_UP(periods, 127); if (size + bytes > ir->bufsize) { - count = i; - break; + rc = -EINVAL; + goto out; } while (periods > 127) { ir->packet->payload[size++] = 127 | space; diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c index 37494433dc9f..0042367b060c 100644 --- a/drivers/media/rc/redrat3.c +++ b/drivers/media/rc/redrat3.c @@ -762,7 +762,8 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf, return -EAGAIN; } - count = min_t(unsigned, count, RR3_MAX_SIG_SIZE - RR3_TX_TRAILER_LEN); + if (count > RR3_MAX_SIG_SIZE - RR3_TX_TRAILER_LEN) + return -EINVAL; /* rr3 will disable rc detector on transmit */ rr3->transmitting = true; @@ -801,8 +802,8 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf, &irdata->lens[curlencheck]); curlencheck++; } else { - count = i - 1; - break; + ret = -EINVAL; + goto out; } } irdata->sigdata[i] = lencheck; -- cgit v1.2.3 From 38e35a85284b9cce271ff43a849d3676a46f8512 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Tue, 30 Jul 2013 19:00:00 -0300 Subject: [media] redrat3: ensure whole packet is read The length in the header excludes the header itself, so we're getting spurious readings. Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/redrat3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/media/rc/redrat3.c') diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c index 0042367b060c..ccd267f131fa 100644 --- a/drivers/media/rc/redrat3.c +++ b/drivers/media/rc/redrat3.c @@ -663,7 +663,8 @@ static int redrat3_get_ir_data(struct redrat3_dev *rr3, unsigned len) goto out; } - if (rr3->bytes_read < be16_to_cpu(rr3->irdata.header.length)) + if (rr3->bytes_read < be16_to_cpu(rr3->irdata.header.length) + + sizeof(struct redrat3_header)) /* we're still accumulating data */ return 0; -- cgit v1.2.3 From bf139726892c3e81538dd33d96cdf18eba6c1e53 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Tue, 30 Jul 2013 19:00:04 -0300 Subject: [media] redrat3: wire up rc feedback led Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/Kconfig | 2 ++ drivers/media/rc/redrat3.c | 83 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 82 insertions(+), 3 deletions(-) (limited to 'drivers/media/rc/redrat3.c') diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 5a79c333d45e..0bf4ac7276d6 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -223,6 +223,8 @@ config IR_REDRAT3 tristate "RedRat3 IR Transceiver" depends on USB_ARCH_HAS_HCD depends on RC_CORE + select NEW_LEDS + select LEDS_CLASS select USB ---help--- Say Y here if you want to use a RedRat3 Infrared Transceiver. 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 @@ #include #include +#include #include #include #include @@ -186,6 +187,13 @@ struct redrat3_dev { struct rc_dev *rc; struct device *dev; + /* led control */ + struct led_classdev led; + atomic_t flash; + struct usb_ctrlrequest flash_control; + struct urb *flash_urb; + u8 flash_in_buf; + /* save off the usb device pointer */ struct usb_device *udev; @@ -480,9 +488,9 @@ static inline void redrat3_delete(struct redrat3_dev *rr3, { rr3_ftr(rr3->dev, "%s cleaning up\n", __func__); usb_kill_urb(rr3->read_urb); - + usb_kill_urb(rr3->flash_urb); usb_free_urb(rr3->read_urb); - + usb_free_urb(rr3->flash_urb); usb_free_coherent(udev, le16_to_cpu(rr3->ep_in->wMaxPacketSize), rr3->bulk_in_buf, rr3->dma_in); @@ -850,6 +858,44 @@ out: return ret; } +static void redrat3_brightness_set(struct led_classdev *led_dev, enum + led_brightness brightness) +{ + struct redrat3_dev *rr3 = container_of(led_dev, struct redrat3_dev, + led); + + if (brightness != LED_OFF && atomic_cmpxchg(&rr3->flash, 0, 1) == 0) { + int ret = usb_submit_urb(rr3->flash_urb, GFP_ATOMIC); + if (ret != 0) { + dev_dbg(rr3->dev, "%s: unexpected ret of %d\n", + __func__, ret); + atomic_set(&rr3->flash, 0); + } + } +} + +static void redrat3_led_complete(struct urb *urb) +{ + struct redrat3_dev *rr3 = urb->context; + + switch (urb->status) { + case 0: + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + usb_unlink_urb(urb); + return; + case -EPIPE: + default: + dev_dbg(rr3->dev, "Error: urb status = %d\n", urb->status); + break; + } + + rr3->led.brightness = LED_OFF; + atomic_dec(&rr3->flash); +} + static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3) { struct device *dev = rr3->dev; @@ -993,10 +1039,35 @@ static int redrat3_dev_probe(struct usb_interface *intf, /* default.. will get overridden by any sends with a freq defined */ rr3->carrier = 38000; + /* led control */ + rr3->led.name = "redrat3:red:feedback"; + rr3->led.default_trigger = "rc-feedback"; + rr3->led.brightness_set = redrat3_brightness_set; + retval = led_classdev_register(&intf->dev, &rr3->led); + if (retval) + goto error; + + atomic_set(&rr3->flash, 0); + rr3->flash_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!rr3->flash_urb) { + retval = -ENOMEM; + goto led_free_error; + } + + /* setup packet is 'c0 b9 0000 0000 0001' */ + rr3->flash_control.bRequestType = 0xc0; + rr3->flash_control.bRequest = RR3_BLINK_LED; + rr3->flash_control.wLength = cpu_to_le16(1); + + usb_fill_control_urb(rr3->flash_urb, udev, usb_rcvctrlpipe(udev, 0), + (unsigned char *)&rr3->flash_control, + &rr3->flash_in_buf, sizeof(rr3->flash_in_buf), + redrat3_led_complete, rr3); + rr3->rc = redrat3_init_rc_dev(rr3); if (!rr3->rc) { retval = -ENOMEM; - goto error; + goto led_free_error; } setup_timer(&rr3->rx_timeout, redrat3_rx_timeout, (unsigned long)rr3); @@ -1006,6 +1077,8 @@ static int redrat3_dev_probe(struct usb_interface *intf, rr3_ftr(dev, "Exiting %s\n", __func__); return 0; +led_free_error: + led_classdev_unregister(&rr3->led); error: redrat3_delete(rr3, rr3->udev); @@ -1027,6 +1100,7 @@ static void redrat3_dev_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); rc_unregister_device(rr3->rc); + led_classdev_unregister(&rr3->led); del_timer_sync(&rr3->rx_timeout); redrat3_delete(rr3, udev); @@ -1037,7 +1111,9 @@ static int redrat3_dev_suspend(struct usb_interface *intf, pm_message_t message) { struct redrat3_dev *rr3 = usb_get_intfdata(intf); rr3_ftr(rr3->dev, "suspend\n"); + led_classdev_suspend(&rr3->led); usb_kill_urb(rr3->read_urb); + usb_kill_urb(rr3->flash_urb); return 0; } @@ -1047,6 +1123,7 @@ static int redrat3_dev_resume(struct usb_interface *intf) rr3_ftr(rr3->dev, "resume\n"); if (usb_submit_urb(rr3->read_urb, GFP_ATOMIC)) return -EIO; + led_classdev_resume(&rr3->led); return 0; } -- cgit v1.2.3