* [PATCH 0/9] Various IR fixes
@ 2016-10-31 17:52 Sean Young
2016-10-31 17:52 ` [PATCH 1/9] [media] winbond-cir: use name without space for pnp driver Sean Young
` (8 more replies)
0 siblings, 9 replies; 12+ messages in thread
From: Sean Young @ 2016-10-31 17:52 UTC (permalink / raw)
To: Mauro Carvalho Chehab; +Cc: linux-media
Teach the redrat3 driver how to use the wideband receiver, also fix
some very nasty crashes if you disconnect a lirc device while
reading from it.
Sean Young (9):
[media] winbond-cir: use name without space for pnp driver
[media] redrat3: don't include vendor/product id in name
[media] redrat3: remove dead code and pointless messages
[media] redrat3: fix error paths in probe
[media] redrat3: enable carrier reports using wideband receiver
[media] redrat3: increase set size for lengths to maximum
[media] lirc: might sleep error in lirc_dev_fop_read
[media] lirc: prevent use-after free
[media] lirc: use-after free while reading from device and unplugging
drivers/media/rc/lirc_dev.c | 18 +--
drivers/media/rc/redrat3.c | 283 +++++++++++++++++++++++++----------------
drivers/media/rc/winbond-cir.c | 2 +-
3 files changed, 181 insertions(+), 122 deletions(-)
--
2.7.4
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/9] [media] winbond-cir: use name without space for pnp driver
2016-10-31 17:52 [PATCH 0/9] Various IR fixes Sean Young
@ 2016-10-31 17:52 ` Sean Young
2016-10-31 17:52 ` [PATCH 2/9] [media] redrat3: don't include vendor/product id in name Sean Young
` (7 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Sean Young @ 2016-10-31 17:52 UTC (permalink / raw)
To: Mauro Carvalho Chehab; +Cc: linux-media
Rename the pnp driver in sysfs from /sys/bus/pnp/drivers/Winbond CIR
to /sys/bus/pnp/drivers/winbond-cir
Signed-off-by: Sean Young <sean@mess.org>
---
drivers/media/rc/winbond-cir.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c
index cdcd6e3..1ccb6bb 100644
--- a/drivers/media/rc/winbond-cir.c
+++ b/drivers/media/rc/winbond-cir.c
@@ -1185,7 +1185,7 @@ static const struct pnp_device_id wbcir_ids[] = {
MODULE_DEVICE_TABLE(pnp, wbcir_ids);
static struct pnp_driver wbcir_driver = {
- .name = WBCIR_NAME,
+ .name = DRVNAME,
.id_table = wbcir_ids,
.probe = wbcir_probe,
.remove = wbcir_remove,
--
2.7.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/9] [media] redrat3: don't include vendor/product id in name
2016-10-31 17:52 [PATCH 0/9] Various IR fixes Sean Young
2016-10-31 17:52 ` [PATCH 1/9] [media] winbond-cir: use name without space for pnp driver Sean Young
@ 2016-10-31 17:52 ` Sean Young
2016-10-31 17:52 ` [PATCH 3/9] [media] redrat3: remove dead code and pointless messages Sean Young
` (6 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Sean Young @ 2016-10-31 17:52 UTC (permalink / raw)
To: Mauro Carvalho Chehab; +Cc: linux-media
No need to duplicate these in the rc name.
Signed-off-by: Sean Young <sean@mess.org>
---
drivers/media/rc/redrat3.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index 3b0ed1c..de40e58 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -912,9 +912,9 @@ static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3)
goto out;
}
- snprintf(rr3->name, sizeof(rr3->name), "RedRat3%s Infrared Remote Transceiver (%04x:%04x)",
- prod == USB_RR3IIUSB_PRODUCT_ID ? "-II" : "",
- le16_to_cpu(rr3->udev->descriptor.idVendor), prod);
+ snprintf(rr3->name, sizeof(rr3->name),
+ "RedRat3%s Infrared Remote Transceiver",
+ prod == USB_RR3IIUSB_PRODUCT_ID ? "-II" : "");
usb_make_path(rr3->udev, rr3->phys, sizeof(rr3->phys));
--
2.7.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 3/9] [media] redrat3: remove dead code and pointless messages
2016-10-31 17:52 [PATCH 0/9] Various IR fixes Sean Young
2016-10-31 17:52 ` [PATCH 1/9] [media] winbond-cir: use name without space for pnp driver Sean Young
2016-10-31 17:52 ` [PATCH 2/9] [media] redrat3: don't include vendor/product id in name Sean Young
@ 2016-10-31 17:52 ` Sean Young
2016-10-31 17:52 ` [PATCH 4/9] [media] redrat3: fix error paths in probe Sean Young
` (5 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Sean Young @ 2016-10-31 17:52 UTC (permalink / raw)
To: Mauro Carvalho Chehab; +Cc: linux-media
No need to log kmalloc failures.
Signed-off-by: Sean Young <sean@mess.org>
---
drivers/media/rc/redrat3.c | 42 ++++++------------------------------------
1 file changed, 6 insertions(+), 36 deletions(-)
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index de40e58..23180ec 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -363,11 +363,6 @@ static void redrat3_process_ir_data(struct redrat3_dev *rr3)
unsigned int i, sig_size, single_len, offset, val;
u32 mod_freq;
- if (!rr3) {
- pr_err("%s called with no context!\n", __func__);
- return;
- }
-
dev = rr3->dev;
mod_freq = redrat3_val_to_mod_freq(&rr3->irdata);
@@ -480,10 +475,8 @@ static u32 redrat3_get_timeout(struct redrat3_dev *rr3)
len = sizeof(*tmp);
tmp = kzalloc(len, GFP_KERNEL);
- if (!tmp) {
- dev_warn(rr3->dev, "Memory allocation faillure\n");
+ if (!tmp)
return timeout;
- }
pipe = usb_rcvctrlpipe(rr3->udev, 0);
ret = usb_control_msg(rr3->udev, pipe, RR3_GET_IR_PARAM,
@@ -544,10 +537,8 @@ static void redrat3_reset(struct redrat3_dev *rr3)
txpipe = usb_sndctrlpipe(udev, 0);
val = kmalloc(len, GFP_KERNEL);
- if (!val) {
- dev_err(dev, "Memory allocation failure\n");
+ if (!val)
return;
- }
*val = 0x01;
rc = usb_control_msg(udev, rxpipe, RR3_RESET,
@@ -589,10 +580,8 @@ static void redrat3_get_firmware_rev(struct redrat3_dev *rr3)
char *buffer;
buffer = kzalloc(sizeof(char) * (RR3_FW_VERSION_LEN + 1), GFP_KERNEL);
- if (!buffer) {
- dev_err(rr3->dev, "Memory allocation failure\n");
+ if (!buffer)
return;
- }
rc = usb_control_msg(rr3->udev, usb_rcvctrlpipe(rr3->udev, 0),
RR3_FW_VERSION,
@@ -699,19 +688,9 @@ static int redrat3_get_ir_data(struct redrat3_dev *rr3, unsigned len)
/* callback function from USB when async USB request has completed */
static void redrat3_handle_async(struct urb *urb)
{
- struct redrat3_dev *rr3;
+ struct redrat3_dev *rr3 = urb->context;
int ret;
- if (!urb)
- return;
-
- rr3 = urb->context;
- if (!rr3) {
- pr_err("%s called with invalid context!\n", __func__);
- usb_unlink_urb(urb);
- return;
- }
-
switch (urb->status) {
case 0:
ret = redrat3_get_ir_data(rr3, urb->actual_length);
@@ -999,10 +978,8 @@ static int redrat3_dev_probe(struct usb_interface *intf,
/* allocate memory for our device state and initialize it */
rr3 = kzalloc(sizeof(*rr3), GFP_KERNEL);
- if (rr3 == NULL) {
- dev_err(dev, "Memory allocation failure\n");
+ if (rr3 == NULL)
goto no_endpoints;
- }
rr3->dev = &intf->dev;
@@ -1014,10 +991,8 @@ static int redrat3_dev_probe(struct usb_interface *intf,
rr3->ep_in = ep_in;
rr3->bulk_in_buf = usb_alloc_coherent(udev,
le16_to_cpu(ep_in->wMaxPacketSize), GFP_KERNEL, &rr3->dma_in);
- if (!rr3->bulk_in_buf) {
- dev_err(dev, "Read buffer allocation failure\n");
+ if (!rr3->bulk_in_buf)
goto error;
- }
pipe = usb_rcvbulkpipe(udev, ep_in->bEndpointAddress);
usb_fill_bulk_urb(rr3->read_urb, udev, pipe, rr3->bulk_in_buf,
@@ -1081,8 +1056,6 @@ static int redrat3_dev_probe(struct usb_interface *intf,
redrat3_delete(rr3, rr3->udev);
no_endpoints:
- dev_err(dev, "%s: retval = %x", __func__, retval);
-
return retval;
}
@@ -1091,9 +1064,6 @@ static void redrat3_dev_disconnect(struct usb_interface *intf)
struct usb_device *udev = interface_to_usbdev(intf);
struct redrat3_dev *rr3 = usb_get_intfdata(intf);
- if (!rr3)
- return;
-
usb_set_intfdata(intf, NULL);
rc_unregister_device(rr3->rc);
led_classdev_unregister(&rr3->led);
--
2.7.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 4/9] [media] redrat3: fix error paths in probe
2016-10-31 17:52 [PATCH 0/9] Various IR fixes Sean Young
` (2 preceding siblings ...)
2016-10-31 17:52 ` [PATCH 3/9] [media] redrat3: remove dead code and pointless messages Sean Young
@ 2016-10-31 17:52 ` Sean Young
2016-10-31 17:52 ` [PATCH 5/9] [media] redrat3: enable carrier reports using wideband receiver Sean Young
` (4 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Sean Young @ 2016-10-31 17:52 UTC (permalink / raw)
To: Mauro Carvalho Chehab; +Cc: linux-media
If redrat3_delete() is called, ensure ep_in and udev members are set
up so we don't dereference null in the error path. Also ensure that
rc dev device exists before we enable the receiver and that the
led urb exists before we create the led device.
Signed-off-by: Sean Young <sean@mess.org>
---
drivers/media/rc/redrat3.c | 49 ++++++++++++++++++++++------------------------
1 file changed, 23 insertions(+), 26 deletions(-)
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index 23180ec..eaf374d 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -982,17 +982,19 @@ static int redrat3_dev_probe(struct usb_interface *intf,
goto no_endpoints;
rr3->dev = &intf->dev;
+ rr3->ep_in = ep_in;
+ rr3->ep_out = ep_out;
+ rr3->udev = udev;
/* set up bulk-in endpoint */
rr3->read_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!rr3->read_urb)
- goto error;
+ goto redrat_free;
- rr3->ep_in = ep_in;
rr3->bulk_in_buf = usb_alloc_coherent(udev,
le16_to_cpu(ep_in->wMaxPacketSize), GFP_KERNEL, &rr3->dma_in);
if (!rr3->bulk_in_buf)
- goto error;
+ goto redrat_free;
pipe = usb_rcvbulkpipe(udev, ep_in->bEndpointAddress);
usb_fill_bulk_urb(rr3->read_urb, udev, pipe, rr3->bulk_in_buf,
@@ -1000,34 +1002,16 @@ static int redrat3_dev_probe(struct usb_interface *intf,
rr3->read_urb->transfer_dma = rr3->dma_in;
rr3->read_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- rr3->ep_out = ep_out;
- rr3->udev = udev;
-
redrat3_reset(rr3);
redrat3_get_firmware_rev(rr3);
- /* might be all we need to do? */
- retval = redrat3_enable_detector(rr3);
- if (retval < 0)
- goto error;
-
/* 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;
- }
+ if (!rr3->flash_urb)
+ goto redrat_free;
/* setup packet is 'c0 b9 0000 0000 0001' */
rr3->flash_control.bRequestType = 0xc0;
@@ -1039,20 +1023,33 @@ static int redrat3_dev_probe(struct usb_interface *intf,
&rr3->flash_in_buf, sizeof(rr3->flash_in_buf),
redrat3_led_complete, rr3);
+ /* 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 redrat_free;
+
rr3->rc = redrat3_init_rc_dev(rr3);
if (!rr3->rc) {
retval = -ENOMEM;
- goto led_free_error;
+ goto led_free;
}
+ /* might be all we need to do? */
+ retval = redrat3_enable_detector(rr3);
+ if (retval < 0)
+ goto led_free;
+
/* we can register the device now, as it is ready */
usb_set_intfdata(intf, rr3);
return 0;
-led_free_error:
+led_free:
led_classdev_unregister(&rr3->led);
-error:
+redrat_free:
redrat3_delete(rr3, rr3->udev);
no_endpoints:
--
2.7.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 5/9] [media] redrat3: enable carrier reports using wideband receiver
2016-10-31 17:52 [PATCH 0/9] Various IR fixes Sean Young
` (3 preceding siblings ...)
2016-10-31 17:52 ` [PATCH 4/9] [media] redrat3: fix error paths in probe Sean Young
@ 2016-10-31 17:52 ` Sean Young
2016-10-31 19:06 ` kbuild test robot
2016-10-31 17:52 ` [PATCH 6/9] [media] redrat3: increase set size for lengths to maximum Sean Young
` (3 subsequent siblings)
8 siblings, 1 reply; 12+ messages in thread
From: Sean Young @ 2016-10-31 17:52 UTC (permalink / raw)
To: Mauro Carvalho Chehab; +Cc: linux-media
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>
---
drivers/media/rc/redrat3.c | 184 ++++++++++++++++++++++++++++++++++-----------
1 file changed, 140 insertions(+), 44 deletions(-)
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index eaf374d..4370d21 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -81,6 +81,8 @@
#define RR3_RC_DET_ENABLE 0xbb
/* Stop capture with the RC receiver */
#define RR3_RC_DET_DISABLE 0xbc
+/* Start capture with the wideband receiver */
+#define RR3_MODSIG_CAPTURE 0xb2
/* Return the status of RC detector capture */
#define RR3_RC_DET_STATUS 0xbd
/* Reset redrat */
@@ -105,8 +107,10 @@
#define RR3_CLK_PER_COUNT 12
/* (RR3_CLK / RR3_CLK_PER_COUNT) */
#define RR3_CLK_CONV_FACTOR 2000000
-/* USB bulk-in IR data endpoint address */
-#define RR3_BULK_IN_EP_ADDR 0x82
+/* USB bulk-in wideband IR data endpoint address */
+#define RR3_WIDE_IN_EP_ADDR 0x81
+/* USB bulk-in narrowband IR data endpoint address */
+#define RR3_NARROW_IN_EP_ADDR 0x82
/* Size of the fixed-length portion of the signal */
#define RR3_DRIVER_MAXLENS 128
@@ -207,15 +211,22 @@ struct redrat3_dev {
struct urb *flash_urb;
u8 flash_in_buf;
+ /* learning */
+ bool wideband;
+ struct usb_ctrlrequest learn_control;
+ struct urb *learn_urb;
+ u8 learn_buf;
+
/* save off the usb device pointer */
struct usb_device *udev;
/* the receive endpoint */
- struct usb_endpoint_descriptor *ep_in;
+ struct usb_endpoint_descriptor *ep_narrow;
/* the buffer to receive data */
void *bulk_in_buf;
/* urb used to read ir data */
- struct urb *read_urb;
+ struct urb *narrow_urb;
+ struct urb *wide_urb;
/* the send endpoint */
struct usb_endpoint_descriptor *ep_out;
@@ -236,23 +247,6 @@ struct redrat3_dev {
char phys[64];
};
-/*
- * redrat3_issue_async
- *
- * Issues an async read to the ir data in port..
- * sets the callback to be redrat3_handle_async
- */
-static void redrat3_issue_async(struct redrat3_dev *rr3)
-{
- int res;
-
- res = usb_submit_urb(rr3->read_urb, GFP_ATOMIC);
- if (res)
- dev_dbg(rr3->dev,
- "%s: receive request FAILED! (res %d, len %d)\n",
- __func__, res, rr3->read_urb->transfer_buffer_length);
-}
-
static void redrat3_dump_fw_error(struct redrat3_dev *rr3, int code)
{
if (!rr3->transmitting && (code != 0x40))
@@ -367,6 +361,14 @@ static void redrat3_process_ir_data(struct redrat3_dev *rr3)
mod_freq = redrat3_val_to_mod_freq(&rr3->irdata);
dev_dbg(dev, "Got mod_freq of %u\n", mod_freq);
+ if (mod_freq && rr3->wideband) {
+ DEFINE_IR_RAW_EVENT(ev);
+
+ ev.carrier_report = 1;
+ ev.carrier = mod_freq;
+
+ ir_raw_event_store(rr3->rc, &ev);
+ }
/* process each rr3 encoded byte into an int */
sig_size = be16_to_cpu(rr3->irdata.sig_size);
@@ -449,19 +451,31 @@ static int redrat3_enable_detector(struct redrat3_dev *rr3)
return -EIO;
}
- redrat3_issue_async(rr3);
+ ret = usb_submit_urb(rr3->narrow_urb, GFP_KERNEL);
+ if (ret) {
+ dev_err(rr3->dev, "narrow band urb failed: %d", ret);
+ return ret;
+ }
- return 0;
+ ret = usb_submit_urb(rr3->wide_urb, GFP_KERNEL);
+ if (ret)
+ dev_err(rr3->dev, "wide band urb failed: %d", ret);
+
+ return ret;
}
static inline void redrat3_delete(struct redrat3_dev *rr3,
struct usb_device *udev)
{
- usb_kill_urb(rr3->read_urb);
+ usb_kill_urb(rr3->narrow_urb);
+ usb_kill_urb(rr3->wide_urb);
usb_kill_urb(rr3->flash_urb);
- usb_free_urb(rr3->read_urb);
+ usb_kill_urb(rr3->learn_urb);
+ usb_free_urb(rr3->narrow_urb);
+ usb_free_urb(rr3->wide_urb);
usb_free_urb(rr3->flash_urb);
- usb_free_coherent(udev, le16_to_cpu(rr3->ep_in->wMaxPacketSize),
+ usb_free_urb(rr3->learn_urb);
+ usb_free_coherent(udev, le16_to_cpu(rr3->ep_narrow->wMaxPacketSize),
rr3->bulk_in_buf, rr3->dma_in);
kfree(rr3);
@@ -694,9 +708,19 @@ static void redrat3_handle_async(struct urb *urb)
switch (urb->status) {
case 0:
ret = redrat3_get_ir_data(rr3, urb->actual_length);
+ if (!ret && rr3->wideband && !rr3->learn_urb->hcpriv) {
+ ret = usb_submit_urb(rr3->learn_urb, GFP_ATOMIC);
+ if (ret)
+ dev_err(rr3->dev, "Failed to submit learning urb: %d",
+ ret);
+ }
+
if (!ret) {
/* no error, prepare to read more */
- redrat3_issue_async(rr3);
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret)
+ dev_err(rr3->dev, "Failed to resubmit urb: %d",
+ ret);
}
break;
@@ -856,6 +880,43 @@ static void redrat3_brightness_set(struct led_classdev *led_dev, enum
}
}
+static int redrat3_wideband_receiver(struct rc_dev *rcdev, int enable)
+{
+ struct redrat3_dev *rr3 = rcdev->priv;
+ int ret = 0;
+
+ rr3->wideband = enable != 0;
+
+ if (enable) {
+ ret = usb_submit_urb(rr3->learn_urb, GFP_KERNEL);
+ if (ret)
+ dev_err(rr3->dev, "Failed to submit learning urb: %d",
+ ret);
+ }
+
+ return ret;
+}
+
+static void redrat3_learn_complete(struct urb *urb)
+{
+ struct redrat3_dev *rr3 = urb->context;
+ int ret;
+
+ switch (urb->status) {
+ case 0:
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ usb_unlink_urb(urb);
+ return;
+ case -EPIPE:
+ default:
+ dev_err(rr3->dev, "Error: learn urb status = %d", urb->status);
+ break;
+ }
+}
+
static void redrat3_led_complete(struct urb *urb)
{
struct redrat3_dev *rr3 = urb->context;
@@ -910,6 +971,7 @@ static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3)
rc->s_timeout = redrat3_set_timeout;
rc->tx_ir = redrat3_transmit_ir;
rc->s_tx_carrier = redrat3_set_tx_carrier;
+ rc->s_carrier_report = redrat3_wideband_receiver;
rc->driver_name = DRIVER_NAME;
rc->rx_resolution = US_TO_NS(2);
rc->map_name = RC_MAP_HAUPPAUGE;
@@ -935,7 +997,8 @@ static int redrat3_dev_probe(struct usb_interface *intf,
struct usb_host_interface *uhi;
struct redrat3_dev *rr3;
struct usb_endpoint_descriptor *ep;
- struct usb_endpoint_descriptor *ep_in = NULL;
+ struct usb_endpoint_descriptor *ep_narrow = NULL;
+ struct usb_endpoint_descriptor *ep_wide = NULL;
struct usb_endpoint_descriptor *ep_out = NULL;
u8 addr, attrs;
int pipe, i;
@@ -949,15 +1012,17 @@ static int redrat3_dev_probe(struct usb_interface *intf,
addr = ep->bEndpointAddress;
attrs = ep->bmAttributes;
- if ((ep_in == NULL) &&
+ if ((ep_narrow == NULL) &&
((addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
((attrs & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_BULK)) {
dev_dbg(dev, "found bulk-in endpoint at 0x%02x\n",
ep->bEndpointAddress);
/* data comes in on 0x82, 0x81 is for other data... */
- if (ep->bEndpointAddress == RR3_BULK_IN_EP_ADDR)
- ep_in = ep;
+ if (ep->bEndpointAddress == RR3_NARROW_IN_EP_ADDR)
+ ep_narrow = ep;
+ if (ep->bEndpointAddress == RR3_WIDE_IN_EP_ADDR)
+ ep_wide = ep;
}
if ((ep_out == NULL) &&
@@ -970,8 +1035,8 @@ static int redrat3_dev_probe(struct usb_interface *intf,
}
}
- if (!ep_in || !ep_out) {
- dev_err(dev, "Couldn't find both in and out endpoints\n");
+ if (!ep_narrow || !ep_out || !ep_wide) {
+ dev_err(dev, "Couldn't find all endpoints\n");
retval = -ENODEV;
goto no_endpoints;
}
@@ -982,25 +1047,38 @@ static int redrat3_dev_probe(struct usb_interface *intf,
goto no_endpoints;
rr3->dev = &intf->dev;
- rr3->ep_in = ep_in;
+ rr3->ep_narrow = ep_narrow;
rr3->ep_out = ep_out;
rr3->udev = udev;
/* set up bulk-in endpoint */
- rr3->read_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!rr3->read_urb)
+ rr3->narrow_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!rr3->narrow_urb)
+ goto redrat_free;
+
+ rr3->wide_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!rr3->wide_urb)
goto redrat_free;
rr3->bulk_in_buf = usb_alloc_coherent(udev,
- le16_to_cpu(ep_in->wMaxPacketSize), GFP_KERNEL, &rr3->dma_in);
+ le16_to_cpu(ep_narrow->wMaxPacketSize),
+ GFP_KERNEL, &rr3->dma_in);
if (!rr3->bulk_in_buf)
goto redrat_free;
- pipe = usb_rcvbulkpipe(udev, ep_in->bEndpointAddress);
- usb_fill_bulk_urb(rr3->read_urb, udev, pipe, rr3->bulk_in_buf,
- le16_to_cpu(ep_in->wMaxPacketSize), redrat3_handle_async, rr3);
- rr3->read_urb->transfer_dma = rr3->dma_in;
- rr3->read_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ pipe = usb_rcvbulkpipe(udev, ep_narrow->bEndpointAddress);
+ usb_fill_bulk_urb(rr3->narrow_urb, udev, pipe, rr3->bulk_in_buf,
+ le16_to_cpu(ep_narrow->wMaxPacketSize),
+ redrat3_handle_async, rr3);
+ rr3->narrow_urb->transfer_dma = rr3->dma_in;
+ rr3->narrow_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ pipe = usb_rcvbulkpipe(udev, ep_wide->bEndpointAddress);
+ usb_fill_bulk_urb(rr3->wide_urb, udev, pipe, rr3->bulk_in_buf,
+ le16_to_cpu(ep_narrow->wMaxPacketSize),
+ redrat3_handle_async, rr3);
+ rr3->wide_urb->transfer_dma = rr3->dma_in;
+ rr3->wide_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
redrat3_reset(rr3);
redrat3_get_firmware_rev(rr3);
@@ -1013,6 +1091,21 @@ static int redrat3_dev_probe(struct usb_interface *intf,
if (!rr3->flash_urb)
goto redrat_free;
+ /* learn urb */
+ rr3->learn_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!rr3->learn_urb)
+ goto redrat_free;
+
+ /* setup packet is 'c0 b2 0000 0000 0001' */
+ rr3->learn_control.bRequestType = 0xc0;
+ rr3->learn_control.bRequest = RR3_MODSIG_CAPTURE;
+ rr3->learn_control.wLength = cpu_to_le16(1);
+
+ usb_fill_control_urb(rr3->learn_urb, udev, usb_rcvctrlpipe(udev, 0),
+ (unsigned char *)&rr3->learn_control,
+ &rr3->learn_buf, sizeof(rr3->learn_buf),
+ redrat3_learn_complete, rr3);
+
/* setup packet is 'c0 b9 0000 0000 0001' */
rr3->flash_control.bRequestType = 0xc0;
rr3->flash_control.bRequest = RR3_BLINK_LED;
@@ -1072,7 +1165,8 @@ static int redrat3_dev_suspend(struct usb_interface *intf, pm_message_t message)
struct redrat3_dev *rr3 = usb_get_intfdata(intf);
led_classdev_suspend(&rr3->led);
- usb_kill_urb(rr3->read_urb);
+ usb_kill_urb(rr3->narrow_urb);
+ usb_kill_urb(rr3->wide_urb);
usb_kill_urb(rr3->flash_urb);
return 0;
}
@@ -1081,7 +1175,9 @@ static int redrat3_dev_resume(struct usb_interface *intf)
{
struct redrat3_dev *rr3 = usb_get_intfdata(intf);
- if (usb_submit_urb(rr3->read_urb, GFP_ATOMIC))
+ if (usb_submit_urb(rr3->narrow_urb, GFP_ATOMIC))
+ return -EIO;
+ if (usb_submit_urb(rr3->wide_urb, GFP_ATOMIC))
return -EIO;
led_classdev_resume(&rr3->led);
return 0;
--
2.7.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 6/9] [media] redrat3: increase set size for lengths to maximum
2016-10-31 17:52 [PATCH 0/9] Various IR fixes Sean Young
` (4 preceding siblings ...)
2016-10-31 17:52 ` [PATCH 5/9] [media] redrat3: enable carrier reports using wideband receiver Sean Young
@ 2016-10-31 17:52 ` Sean Young
2016-10-31 17:52 ` [PATCH 7/9] [media] lirc: might sleep error in lirc_dev_fop_read Sean Young
` (2 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Sean Young @ 2016-10-31 17:52 UTC (permalink / raw)
To: Mauro Carvalho Chehab; +Cc: linux-media
In learning mode, you can get much longer messages which can run out
of lengths. The usb message will slightly larger.
Signed-off-by: Sean Young <sean@mess.org>
---
drivers/media/rc/redrat3.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index 4370d21..12e299f 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -113,7 +113,7 @@
#define RR3_NARROW_IN_EP_ADDR 0x82
/* Size of the fixed-length portion of the signal */
-#define RR3_DRIVER_MAXLENS 128
+#define RR3_DRIVER_MAXLENS 255
#define RR3_MAX_SIG_SIZE 512
#define RR3_TIME_UNIT 50
#define RR3_END_OF_SIGNAL 0x7f
--
2.7.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 7/9] [media] lirc: might sleep error in lirc_dev_fop_read
2016-10-31 17:52 [PATCH 0/9] Various IR fixes Sean Young
` (5 preceding siblings ...)
2016-10-31 17:52 ` [PATCH 6/9] [media] redrat3: increase set size for lengths to maximum Sean Young
@ 2016-10-31 17:52 ` Sean Young
2016-10-31 17:52 ` [PATCH 8/9] [media] lirc: prevent use-after free Sean Young
2016-10-31 17:52 ` [PATCH 9/9] [media] lirc: use-after free while reading from device and unplugging Sean Young
8 siblings, 0 replies; 12+ messages in thread
From: Sean Young @ 2016-10-31 17:52 UTC (permalink / raw)
To: Mauro Carvalho Chehab; +Cc: linux-media
[ 101.457944] ------------[ cut here ]------------
[ 101.457954] WARNING: CPU: 3 PID: 1819 at kernel/sched/core.c:7708 __might_sleep+0x7e/0x80
[ 101.457960] do not call blocking ops when !TASK_RUNNING; state=1 set at [<ffffffffc0364bc2>] lirc_dev_fop_read+0x292/0x4e0 [lirc_dev]
Signed-off-by: Sean Young <sean@mess.org>
---
drivers/media/rc/lirc_dev.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 91f9bb8..bf4309f 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -684,7 +684,6 @@ ssize_t lirc_dev_fop_read(struct file *file,
* between while condition checking and scheduling)
*/
add_wait_queue(&ir->buf->wait_poll, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
/*
* while we didn't provide 'length' bytes, device is opened in blocking
@@ -709,13 +708,13 @@ ssize_t lirc_dev_fop_read(struct file *file,
}
mutex_unlock(&ir->irctl_lock);
- schedule();
set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ set_current_state(TASK_RUNNING);
if (mutex_lock_interruptible(&ir->irctl_lock)) {
ret = -ERESTARTSYS;
remove_wait_queue(&ir->buf->wait_poll, &wait);
- set_current_state(TASK_RUNNING);
goto out_unlocked;
}
@@ -735,7 +734,6 @@ ssize_t lirc_dev_fop_read(struct file *file,
}
remove_wait_queue(&ir->buf->wait_poll, &wait);
- set_current_state(TASK_RUNNING);
out_locked:
mutex_unlock(&ir->irctl_lock);
--
2.7.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 8/9] [media] lirc: prevent use-after free
2016-10-31 17:52 [PATCH 0/9] Various IR fixes Sean Young
` (6 preceding siblings ...)
2016-10-31 17:52 ` [PATCH 7/9] [media] lirc: might sleep error in lirc_dev_fop_read Sean Young
@ 2016-10-31 17:52 ` Sean Young
2016-10-31 17:52 ` [PATCH 9/9] [media] lirc: use-after free while reading from device and unplugging Sean Young
8 siblings, 0 replies; 12+ messages in thread
From: Sean Young @ 2016-10-31 17:52 UTC (permalink / raw)
To: Mauro Carvalho Chehab; +Cc: linux-media
If you unplug an lirc device while reading from it, you will get an
use after free as the cdev is freed while still in use.
Signed-off-by: Sean Young <sean@mess.org>
---
drivers/media/rc/lirc_dev.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index bf4309f..60fd106 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -164,15 +164,15 @@ static int lirc_cdev_add(struct irctl *ir)
struct lirc_driver *d = &ir->d;
struct cdev *cdev;
- cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
+ cdev = cdev_alloc();
if (!cdev)
goto err_out;
if (d->fops) {
- cdev_init(cdev, d->fops);
+ cdev->ops = d->fops;
cdev->owner = d->owner;
} else {
- cdev_init(cdev, &lirc_dev_fops);
+ cdev->ops = &lirc_dev_fops;
cdev->owner = THIS_MODULE;
}
retval = kobject_set_name(&cdev->kobj, "lirc%d", d->minor);
@@ -190,7 +190,7 @@ static int lirc_cdev_add(struct irctl *ir)
return 0;
err_out:
- kfree(cdev);
+ cdev_del(cdev);
return retval;
}
@@ -420,7 +420,6 @@ int lirc_unregister_driver(int minor)
} else {
lirc_irctl_cleanup(ir);
cdev_del(cdev);
- kfree(cdev);
kfree(ir);
irctls[minor] = NULL;
}
@@ -521,7 +520,6 @@ int lirc_dev_fop_close(struct inode *inode, struct file *file)
lirc_irctl_cleanup(ir);
cdev_del(cdev);
irctls[ir->d.minor] = NULL;
- kfree(cdev);
kfree(ir);
}
--
2.7.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 9/9] [media] lirc: use-after free while reading from device and unplugging
2016-10-31 17:52 [PATCH 0/9] Various IR fixes Sean Young
` (7 preceding siblings ...)
2016-10-31 17:52 ` [PATCH 8/9] [media] lirc: prevent use-after free Sean Young
@ 2016-10-31 17:52 ` Sean Young
8 siblings, 0 replies; 12+ messages in thread
From: Sean Young @ 2016-10-31 17:52 UTC (permalink / raw)
To: Mauro Carvalho Chehab; +Cc: linux-media
Many lirc drivers have their own receive buffers which are freed on
unplug (e.g. ir_lirc_unregister). This means that ir->buf->wait_poll
will be freed directly after unplug so do not remove yourself from the
wait queue.
Signed-off-by: Sean Young <sean@mess.org>
---
drivers/media/rc/lirc_dev.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 60fd106..b0c79a5 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -718,7 +718,7 @@ ssize_t lirc_dev_fop_read(struct file *file,
if (!ir->attached) {
ret = -ENODEV;
- break;
+ goto out_locked;
}
} else {
lirc_buffer_read(ir->buf, buf);
--
2.7.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 5/9] [media] redrat3: enable carrier reports using wideband receiver
2016-10-31 17:52 ` [PATCH 5/9] [media] redrat3: enable carrier reports using wideband receiver Sean Young
@ 2016-10-31 19:06 ` kbuild test robot
2016-10-31 21:13 ` Sean Young
0 siblings, 1 reply; 12+ messages in thread
From: kbuild test robot @ 2016-10-31 19:06 UTC (permalink / raw)
To: Sean Young; +Cc: kbuild-all, Mauro Carvalho Chehab, linux-media
[-- Attachment #1: Type: text/plain, Size: 1841 bytes --]
Hi Sean,
[auto build test WARNING on linuxtv-media/master]
[also build test WARNING on next-20161028]
[cannot apply to v4.9-rc3]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
[Suggest to use git(>=2.9.0) format-patch --base=<commit> (or --base=auto for convenience) to record what (public, well-known) commit your patch series was built on]
[Check https://git-scm.com/docs/git-format-patch for more information]
url: https://github.com/0day-ci/linux/commits/Sean-Young/Various-IR-fixes/20161101-023658
base: git://linuxtv.org/media_tree.git master
config: x86_64-randconfig-x014-201644 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All warnings (new ones prefixed by >>):
drivers/media/rc/redrat3.c: In function 'redrat3_learn_complete':
>> drivers/media/rc/redrat3.c:903:6: warning: unused variable 'ret' [-Wunused-variable]
int ret;
^~~
vim +/ret +903 drivers/media/rc/redrat3.c
887
888 rr3->wideband = enable != 0;
889
890 if (enable) {
891 ret = usb_submit_urb(rr3->learn_urb, GFP_KERNEL);
892 if (ret)
893 dev_err(rr3->dev, "Failed to submit learning urb: %d",
894 ret);
895 }
896
897 return ret;
898 }
899
900 static void redrat3_learn_complete(struct urb *urb)
901 {
902 struct redrat3_dev *rr3 = urb->context;
> 903 int ret;
904
905 switch (urb->status) {
906 case 0:
907 break;
908 case -ECONNRESET:
909 case -ENOENT:
910 case -ESHUTDOWN:
911 usb_unlink_urb(urb);
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 33953 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 5/9] [media] redrat3: enable carrier reports using wideband receiver
2016-10-31 19:06 ` kbuild test robot
@ 2016-10-31 21:13 ` Sean Young
0 siblings, 0 replies; 12+ messages in thread
From: Sean Young @ 2016-10-31 21:13 UTC (permalink / raw)
To: Mauro Carvalho Chehab; +Cc: linux-media, Chris Dodge
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>
---
drivers/media/rc/redrat3.c | 186 ++++++++++++++++++++++++++++++++++-----------
1 file changed, 140 insertions(+), 46 deletions(-)
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index eaf374d..1882712 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -81,6 +81,8 @@
#define RR3_RC_DET_ENABLE 0xbb
/* Stop capture with the RC receiver */
#define RR3_RC_DET_DISABLE 0xbc
+/* Start capture with the wideband receiver */
+#define RR3_MODSIG_CAPTURE 0xb2
/* Return the status of RC detector capture */
#define RR3_RC_DET_STATUS 0xbd
/* Reset redrat */
@@ -105,8 +107,10 @@
#define RR3_CLK_PER_COUNT 12
/* (RR3_CLK / RR3_CLK_PER_COUNT) */
#define RR3_CLK_CONV_FACTOR 2000000
-/* USB bulk-in IR data endpoint address */
-#define RR3_BULK_IN_EP_ADDR 0x82
+/* USB bulk-in wideband IR data endpoint address */
+#define RR3_WIDE_IN_EP_ADDR 0x81
+/* USB bulk-in narrowband IR data endpoint address */
+#define RR3_NARROW_IN_EP_ADDR 0x82
/* Size of the fixed-length portion of the signal */
#define RR3_DRIVER_MAXLENS 128
@@ -207,15 +211,22 @@ struct redrat3_dev {
struct urb *flash_urb;
u8 flash_in_buf;
+ /* learning */
+ bool wideband;
+ struct usb_ctrlrequest learn_control;
+ struct urb *learn_urb;
+ u8 learn_buf;
+
/* save off the usb device pointer */
struct usb_device *udev;
/* the receive endpoint */
- struct usb_endpoint_descriptor *ep_in;
+ struct usb_endpoint_descriptor *ep_narrow;
/* the buffer to receive data */
void *bulk_in_buf;
/* urb used to read ir data */
- struct urb *read_urb;
+ struct urb *narrow_urb;
+ struct urb *wide_urb;
/* the send endpoint */
struct usb_endpoint_descriptor *ep_out;
@@ -236,23 +247,6 @@ struct redrat3_dev {
char phys[64];
};
-/*
- * redrat3_issue_async
- *
- * Issues an async read to the ir data in port..
- * sets the callback to be redrat3_handle_async
- */
-static void redrat3_issue_async(struct redrat3_dev *rr3)
-{
- int res;
-
- res = usb_submit_urb(rr3->read_urb, GFP_ATOMIC);
- if (res)
- dev_dbg(rr3->dev,
- "%s: receive request FAILED! (res %d, len %d)\n",
- __func__, res, rr3->read_urb->transfer_buffer_length);
-}
-
static void redrat3_dump_fw_error(struct redrat3_dev *rr3, int code)
{
if (!rr3->transmitting && (code != 0x40))
@@ -367,6 +361,14 @@ static void redrat3_process_ir_data(struct redrat3_dev *rr3)
mod_freq = redrat3_val_to_mod_freq(&rr3->irdata);
dev_dbg(dev, "Got mod_freq of %u\n", mod_freq);
+ if (mod_freq && rr3->wideband) {
+ DEFINE_IR_RAW_EVENT(ev);
+
+ ev.carrier_report = 1;
+ ev.carrier = mod_freq;
+
+ ir_raw_event_store(rr3->rc, &ev);
+ }
/* process each rr3 encoded byte into an int */
sig_size = be16_to_cpu(rr3->irdata.sig_size);
@@ -449,19 +451,31 @@ static int redrat3_enable_detector(struct redrat3_dev *rr3)
return -EIO;
}
- redrat3_issue_async(rr3);
+ ret = usb_submit_urb(rr3->narrow_urb, GFP_KERNEL);
+ if (ret) {
+ dev_err(rr3->dev, "narrow band urb failed: %d", ret);
+ return ret;
+ }
- return 0;
+ ret = usb_submit_urb(rr3->wide_urb, GFP_KERNEL);
+ if (ret)
+ dev_err(rr3->dev, "wide band urb failed: %d", ret);
+
+ return ret;
}
static inline void redrat3_delete(struct redrat3_dev *rr3,
struct usb_device *udev)
{
- usb_kill_urb(rr3->read_urb);
+ usb_kill_urb(rr3->narrow_urb);
+ usb_kill_urb(rr3->wide_urb);
usb_kill_urb(rr3->flash_urb);
- usb_free_urb(rr3->read_urb);
+ usb_kill_urb(rr3->learn_urb);
+ usb_free_urb(rr3->narrow_urb);
+ usb_free_urb(rr3->wide_urb);
usb_free_urb(rr3->flash_urb);
- usb_free_coherent(udev, le16_to_cpu(rr3->ep_in->wMaxPacketSize),
+ usb_free_urb(rr3->learn_urb);
+ usb_free_coherent(udev, le16_to_cpu(rr3->ep_narrow->wMaxPacketSize),
rr3->bulk_in_buf, rr3->dma_in);
kfree(rr3);
@@ -694,9 +708,19 @@ static void redrat3_handle_async(struct urb *urb)
switch (urb->status) {
case 0:
ret = redrat3_get_ir_data(rr3, urb->actual_length);
+ if (!ret && rr3->wideband && !rr3->learn_urb->hcpriv) {
+ ret = usb_submit_urb(rr3->learn_urb, GFP_ATOMIC);
+ if (ret)
+ dev_err(rr3->dev, "Failed to submit learning urb: %d",
+ ret);
+ }
+
if (!ret) {
/* no error, prepare to read more */
- redrat3_issue_async(rr3);
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret)
+ dev_err(rr3->dev, "Failed to resubmit urb: %d",
+ ret);
}
break;
@@ -856,6 +880,42 @@ static void redrat3_brightness_set(struct led_classdev *led_dev, enum
}
}
+static int redrat3_wideband_receiver(struct rc_dev *rcdev, int enable)
+{
+ struct redrat3_dev *rr3 = rcdev->priv;
+ int ret = 0;
+
+ rr3->wideband = enable != 0;
+
+ if (enable) {
+ ret = usb_submit_urb(rr3->learn_urb, GFP_KERNEL);
+ if (ret)
+ dev_err(rr3->dev, "Failed to submit learning urb: %d",
+ ret);
+ }
+
+ return ret;
+}
+
+static void redrat3_learn_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_err(rr3->dev, "Error: learn urb status = %d", urb->status);
+ break;
+ }
+}
+
static void redrat3_led_complete(struct urb *urb)
{
struct redrat3_dev *rr3 = urb->context;
@@ -910,6 +970,7 @@ static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3)
rc->s_timeout = redrat3_set_timeout;
rc->tx_ir = redrat3_transmit_ir;
rc->s_tx_carrier = redrat3_set_tx_carrier;
+ rc->s_carrier_report = redrat3_wideband_receiver;
rc->driver_name = DRIVER_NAME;
rc->rx_resolution = US_TO_NS(2);
rc->map_name = RC_MAP_HAUPPAUGE;
@@ -935,7 +996,8 @@ static int redrat3_dev_probe(struct usb_interface *intf,
struct usb_host_interface *uhi;
struct redrat3_dev *rr3;
struct usb_endpoint_descriptor *ep;
- struct usb_endpoint_descriptor *ep_in = NULL;
+ struct usb_endpoint_descriptor *ep_narrow = NULL;
+ struct usb_endpoint_descriptor *ep_wide = NULL;
struct usb_endpoint_descriptor *ep_out = NULL;
u8 addr, attrs;
int pipe, i;
@@ -949,15 +1011,16 @@ static int redrat3_dev_probe(struct usb_interface *intf,
addr = ep->bEndpointAddress;
attrs = ep->bmAttributes;
- if ((ep_in == NULL) &&
- ((addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
+ if (((addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
((attrs & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_BULK)) {
dev_dbg(dev, "found bulk-in endpoint at 0x%02x\n",
ep->bEndpointAddress);
- /* data comes in on 0x82, 0x81 is for other data... */
- if (ep->bEndpointAddress == RR3_BULK_IN_EP_ADDR)
- ep_in = ep;
+ /* data comes in on 0x82, 0x81 is for learning */
+ if (ep->bEndpointAddress == RR3_NARROW_IN_EP_ADDR)
+ ep_narrow = ep;
+ if (ep->bEndpointAddress == RR3_WIDE_IN_EP_ADDR)
+ ep_wide = ep;
}
if ((ep_out == NULL) &&
@@ -970,8 +1033,8 @@ static int redrat3_dev_probe(struct usb_interface *intf,
}
}
- if (!ep_in || !ep_out) {
- dev_err(dev, "Couldn't find both in and out endpoints\n");
+ if (!ep_narrow || !ep_out || !ep_wide) {
+ dev_err(dev, "Couldn't find all endpoints\n");
retval = -ENODEV;
goto no_endpoints;
}
@@ -982,25 +1045,38 @@ static int redrat3_dev_probe(struct usb_interface *intf,
goto no_endpoints;
rr3->dev = &intf->dev;
- rr3->ep_in = ep_in;
+ rr3->ep_narrow = ep_narrow;
rr3->ep_out = ep_out;
rr3->udev = udev;
/* set up bulk-in endpoint */
- rr3->read_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!rr3->read_urb)
+ rr3->narrow_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!rr3->narrow_urb)
+ goto redrat_free;
+
+ rr3->wide_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!rr3->wide_urb)
goto redrat_free;
rr3->bulk_in_buf = usb_alloc_coherent(udev,
- le16_to_cpu(ep_in->wMaxPacketSize), GFP_KERNEL, &rr3->dma_in);
+ le16_to_cpu(ep_narrow->wMaxPacketSize),
+ GFP_KERNEL, &rr3->dma_in);
if (!rr3->bulk_in_buf)
goto redrat_free;
- pipe = usb_rcvbulkpipe(udev, ep_in->bEndpointAddress);
- usb_fill_bulk_urb(rr3->read_urb, udev, pipe, rr3->bulk_in_buf,
- le16_to_cpu(ep_in->wMaxPacketSize), redrat3_handle_async, rr3);
- rr3->read_urb->transfer_dma = rr3->dma_in;
- rr3->read_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ pipe = usb_rcvbulkpipe(udev, ep_narrow->bEndpointAddress);
+ usb_fill_bulk_urb(rr3->narrow_urb, udev, pipe, rr3->bulk_in_buf,
+ le16_to_cpu(ep_narrow->wMaxPacketSize),
+ redrat3_handle_async, rr3);
+ rr3->narrow_urb->transfer_dma = rr3->dma_in;
+ rr3->narrow_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ pipe = usb_rcvbulkpipe(udev, ep_wide->bEndpointAddress);
+ usb_fill_bulk_urb(rr3->wide_urb, udev, pipe, rr3->bulk_in_buf,
+ le16_to_cpu(ep_narrow->wMaxPacketSize),
+ redrat3_handle_async, rr3);
+ rr3->wide_urb->transfer_dma = rr3->dma_in;
+ rr3->wide_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
redrat3_reset(rr3);
redrat3_get_firmware_rev(rr3);
@@ -1013,6 +1089,21 @@ static int redrat3_dev_probe(struct usb_interface *intf,
if (!rr3->flash_urb)
goto redrat_free;
+ /* learn urb */
+ rr3->learn_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!rr3->learn_urb)
+ goto redrat_free;
+
+ /* setup packet is 'c0 b2 0000 0000 0001' */
+ rr3->learn_control.bRequestType = 0xc0;
+ rr3->learn_control.bRequest = RR3_MODSIG_CAPTURE;
+ rr3->learn_control.wLength = cpu_to_le16(1);
+
+ usb_fill_control_urb(rr3->learn_urb, udev, usb_rcvctrlpipe(udev, 0),
+ (unsigned char *)&rr3->learn_control,
+ &rr3->learn_buf, sizeof(rr3->learn_buf),
+ redrat3_learn_complete, rr3);
+
/* setup packet is 'c0 b9 0000 0000 0001' */
rr3->flash_control.bRequestType = 0xc0;
rr3->flash_control.bRequest = RR3_BLINK_LED;
@@ -1072,7 +1163,8 @@ static int redrat3_dev_suspend(struct usb_interface *intf, pm_message_t message)
struct redrat3_dev *rr3 = usb_get_intfdata(intf);
led_classdev_suspend(&rr3->led);
- usb_kill_urb(rr3->read_urb);
+ usb_kill_urb(rr3->narrow_urb);
+ usb_kill_urb(rr3->wide_urb);
usb_kill_urb(rr3->flash_urb);
return 0;
}
@@ -1081,7 +1173,9 @@ static int redrat3_dev_resume(struct usb_interface *intf)
{
struct redrat3_dev *rr3 = usb_get_intfdata(intf);
- if (usb_submit_urb(rr3->read_urb, GFP_ATOMIC))
+ if (usb_submit_urb(rr3->narrow_urb, GFP_ATOMIC))
+ return -EIO;
+ if (usb_submit_urb(rr3->wide_urb, GFP_ATOMIC))
return -EIO;
led_classdev_resume(&rr3->led);
return 0;
--
2.7.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
end of thread, other threads:[~2016-10-31 21:13 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-31 17:52 [PATCH 0/9] Various IR fixes Sean Young
2016-10-31 17:52 ` [PATCH 1/9] [media] winbond-cir: use name without space for pnp driver Sean Young
2016-10-31 17:52 ` [PATCH 2/9] [media] redrat3: don't include vendor/product id in name Sean Young
2016-10-31 17:52 ` [PATCH 3/9] [media] redrat3: remove dead code and pointless messages Sean Young
2016-10-31 17:52 ` [PATCH 4/9] [media] redrat3: fix error paths in probe Sean Young
2016-10-31 17:52 ` [PATCH 5/9] [media] redrat3: enable carrier reports using wideband receiver Sean Young
2016-10-31 19:06 ` kbuild test robot
2016-10-31 21:13 ` Sean Young
2016-10-31 17:52 ` [PATCH 6/9] [media] redrat3: increase set size for lengths to maximum Sean Young
2016-10-31 17:52 ` [PATCH 7/9] [media] lirc: might sleep error in lirc_dev_fop_read Sean Young
2016-10-31 17:52 ` [PATCH 8/9] [media] lirc: prevent use-after free Sean Young
2016-10-31 17:52 ` [PATCH 9/9] [media] lirc: use-after free while reading from device and unplugging Sean Young
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.