diff options
Diffstat (limited to 'drivers/media/usb/dvb-usb/dib0700_core.c')
| -rw-r--r-- | drivers/media/usb/dvb-usb/dib0700_core.c | 64 |
1 files changed, 46 insertions, 18 deletions
diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c index ef87229de6a..c14285fa827 100644 --- a/drivers/media/usb/dvb-usb/dib0700_core.c +++ b/drivers/media/usb/dvb-usb/dib0700_core.c @@ -561,10 +561,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) } } - if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) { - err("could not acquire lock"); - return -EINTR; - } + mutex_lock(&adap->dev->usb_mutex); st->buf[0] = REQUEST_ENABLE_VIDEO; /* this bit gives a kind of command, @@ -605,7 +602,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) return ret; } -int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) +int dib0700_change_protocol(struct rc_dev *rc, u64 *rc_type) { struct dvb_usb_device *d = rc->priv; struct dib0700_state *st = d->priv; @@ -621,17 +618,19 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) st->buf[2] = 0; /* Set the IR mode */ - if (rc_type == RC_TYPE_RC5) + if (*rc_type & RC_BIT_RC5) { new_proto = 1; - else if (rc_type == RC_TYPE_NEC) + *rc_type = RC_BIT_RC5; + } else if (*rc_type & RC_BIT_NEC) { new_proto = 0; - else if (rc_type == RC_TYPE_RC6) { + *rc_type = RC_BIT_NEC; + } else if (*rc_type & RC_BIT_RC6_MCE) { if (st->fw_version < 0x10200) { ret = -EINVAL; goto out; } - new_proto = 2; + *rc_type = RC_BIT_RC6_MCE; } else { ret = -EINVAL; goto out; @@ -645,7 +644,7 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) goto out; } - d->props.rc.core.protocol = rc_type; + d->props.rc.core.protocol = *rc_type; out: mutex_unlock(&d->usb_mutex); @@ -707,7 +706,7 @@ static void dib0700_rc_urb_completion(struct urb *purb) purb->actual_length); switch (d->props.rc.core.protocol) { - case RC_TYPE_NEC: + case RC_BIT_NEC: toggle = 0; /* NEC protocol sends repeat code as 0 0 0 FF */ @@ -755,17 +754,20 @@ resubmit: usb_submit_urb(purb, GFP_ATOMIC); } -int dib0700_rc_setup(struct dvb_usb_device *d) +int dib0700_rc_setup(struct dvb_usb_device *d, struct usb_interface *intf) { struct dib0700_state *st = d->priv; struct urb *purb; - int ret; + const struct usb_endpoint_descriptor *e; + int ret, rc_ep = 1; + unsigned int pipe = 0; /* Poll-based. Don't initialize bulk mode */ - if (st->fw_version < 0x10200) + if (st->fw_version < 0x10200 || !intf) return 0; /* Starting in firmware 1.20, the RC info is provided on a bulk pipe */ + purb = usb_alloc_urb(0, GFP_KERNEL); if (purb == NULL) { err("rc usb alloc urb failed"); @@ -780,9 +782,35 @@ int dib0700_rc_setup(struct dvb_usb_device *d) } purb->status = -EINPROGRESS; - usb_fill_bulk_urb(purb, d->udev, usb_rcvbulkpipe(d->udev, 1), - purb->transfer_buffer, RC_MSG_SIZE_V1_20, - dib0700_rc_urb_completion, d); + + /* + * Some devices like the Hauppauge NovaTD model 52009 use an interrupt + * endpoint, while others use a bulk one. + */ + e = &intf->altsetting[0].endpoint[rc_ep].desc; + if (usb_endpoint_dir_in(e)) { + if (usb_endpoint_xfer_bulk(e)) { + pipe = usb_rcvbulkpipe(d->udev, rc_ep); + usb_fill_bulk_urb(purb, d->udev, pipe, + purb->transfer_buffer, + RC_MSG_SIZE_V1_20, + dib0700_rc_urb_completion, d); + + } else if (usb_endpoint_xfer_int(e)) { + pipe = usb_rcvintpipe(d->udev, rc_ep); + usb_fill_int_urb(purb, d->udev, pipe, + purb->transfer_buffer, + RC_MSG_SIZE_V1_20, + dib0700_rc_urb_completion, d, 1); + } + } + + if (!pipe) { + err("There's no endpoint for remote controller"); + kfree(purb->transfer_buffer); + usb_free_urb(purb); + return 0; + } ret = usb_submit_urb(purb, GFP_ATOMIC); if (ret) { @@ -821,7 +849,7 @@ static int dib0700_probe(struct usb_interface *intf, else dev->props.rc.core.bulk_mode = false; - dib0700_rc_setup(dev); + dib0700_rc_setup(dev, intf); return 0; } |
