diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index 1e08c7dc0e82758928292658df9b84c8a5fe04c6..4530237cbb672a2182fd2a6b21393ade107d2f92 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -419,6 +419,7 @@ struct mceusb_dev { struct urb *urb_in; unsigned int pipe_in; struct usb_endpoint_descriptor *usb_ep_out; + unsigned int pipe_out; /* buffers and dma */ unsigned char *buf_in; @@ -739,6 +740,11 @@ static void mce_async_callback(struct urb *urb) break; case -EPIPE: + dev_err(ir->dev, "Error: request urb status = %d (TX HALT)", + urb->status); + mceusb_defer_kevent(ir, EVENT_TX_HALT); + break; + default: dev_err(ir->dev, "Error: request urb status = %d", urb->status); break; @@ -753,7 +759,7 @@ static void mce_async_callback(struct urb *urb) static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data, int size) { - int res, pipe; + int res; struct urb *async_urb; struct device *dev = ir->dev; unsigned char *async_buf; @@ -771,19 +777,14 @@ static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data, } /* outbound data */ - if (usb_endpoint_xfer_int(ir->usb_ep_out)) { - pipe = usb_sndintpipe(ir->usbdev, - ir->usb_ep_out->bEndpointAddress); - usb_fill_int_urb(async_urb, ir->usbdev, pipe, async_buf, - size, mce_async_callback, ir, + if (usb_endpoint_xfer_int(ir->usb_ep_out)) + usb_fill_int_urb(async_urb, ir->usbdev, ir->pipe_out, + async_buf, size, mce_async_callback, ir, ir->usb_ep_out->bInterval); - } else { - pipe = usb_sndbulkpipe(ir->usbdev, - ir->usb_ep_out->bEndpointAddress); - usb_fill_bulk_urb(async_urb, ir->usbdev, pipe, - async_buf, size, mce_async_callback, - ir); - } + else + usb_fill_bulk_urb(async_urb, ir->usbdev, ir->pipe_out, + async_buf, size, mce_async_callback, ir); + memcpy(async_buf, data, size); dev_dbg(dev, "send request called (size=%#x)", size); @@ -1222,16 +1223,24 @@ static void mceusb_deferred_kevent(struct work_struct *work) if (status < 0) { dev_err(ir->dev, "rx clear halt error %d", status); - return; } clear_bit(EVENT_RX_HALT, &ir->kevent_flags); - status = usb_submit_urb(ir->urb_in, GFP_KERNEL); - if (status < 0) { - dev_err(ir->dev, "rx unhalt submit urb error %d", - status); - return; + if (status == 0) { + status = usb_submit_urb(ir->urb_in, GFP_KERNEL); + if (status < 0) { + dev_err(ir->dev, + "rx unhalt submit urb error %d", + status); + } } } + + if (test_bit(EVENT_TX_HALT, &ir->kevent_flags)) { + status = usb_clear_halt(ir->usbdev, ir->pipe_out); + if (status < 0) + dev_err(ir->dev, "tx clear halt error %d", status); + clear_bit(EVENT_TX_HALT, &ir->kevent_flags); + } } static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir) @@ -1386,6 +1395,12 @@ static int mceusb_dev_probe(struct usb_interface *intf, /* Saving usb interface data for use by the transmitter routine */ ir->usb_ep_out = ep_out; + if (usb_endpoint_xfer_int(ep_out)) + ir->pipe_out = usb_sndintpipe(ir->usbdev, + ep_out->bEndpointAddress); + else + ir->pipe_out = usb_sndbulkpipe(ir->usbdev, + ep_out->bEndpointAddress); if (dev->descriptor.iManufacturer && usb_string(dev, dev->descriptor.iManufacturer,