aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Engelmayer <christian.engelmayer@frequentis.com>2013-11-26 21:16:17 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2013-12-02 01:18:04 -0500
commit4ef38351d770cc421f4a0c7a849fd13207fc5741 (patch)
treea367b5f06d4448aa9b5d172fd7cad6715a810390
parentb884eb8c8502ca1fea497a02433c2b41de851f62 (diff)
Input: usbtouchscreen - separate report and transmit buffer size handling
This patch supports the separate handling of the USB transfer buffer length and the length of the buffer used for multi packet support. For devices supporting multiple report or diagnostic packets, the USB transfer size is now limited to the USB endpoints wMaxPacketSize - otherwise it defaults to the configured report packet size as before. This fixes an issue where event reporting can be delayed for an arbitrary time for multi packet devices. For instance the report size for eGalax devices is defined to the 16 byte maximum diagnostic packet size as opposed to the 5 byte report packet size. In case the driver requests 16 byte from the USB interrupt endpoint, the USB host controller driver needs to split up the request into 2 accesses according to the endpoints wMaxPacketSize of 8 byte. When the first transfer is answered by the eGalax device with not less than the full 8 byte requested, the host controller has got no way of knowing whether the touch controller has got additional data queued and will issue the second transfer. If per example a liftoff event finishes at such a wMaxPacketSize boundary, the data will not be available to the usbtouch driver until a further event is triggered and transfered to the host. From user perspective the BTN_TOUCH release event in this case is stuck until the next touch down event. Signed-off-by: Christian Engelmayer <christian.engelmayer@frequentis.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r--drivers/input/touchscreen/usbtouchscreen.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
index 721fdb3597ca..819fb21ae58d 100644
--- a/drivers/input/touchscreen/usbtouchscreen.c
+++ b/drivers/input/touchscreen/usbtouchscreen.c
@@ -106,6 +106,7 @@ struct usbtouch_device_info {
106struct usbtouch_usb { 106struct usbtouch_usb {
107 unsigned char *data; 107 unsigned char *data;
108 dma_addr_t data_dma; 108 dma_addr_t data_dma;
109 int data_size;
109 unsigned char *buffer; 110 unsigned char *buffer;
110 int buf_len; 111 int buf_len;
111 struct urb *irq; 112 struct urb *irq;
@@ -1523,7 +1524,7 @@ static int usbtouch_reset_resume(struct usb_interface *intf)
1523static void usbtouch_free_buffers(struct usb_device *udev, 1524static void usbtouch_free_buffers(struct usb_device *udev,
1524 struct usbtouch_usb *usbtouch) 1525 struct usbtouch_usb *usbtouch)
1525{ 1526{
1526 usb_free_coherent(udev, usbtouch->type->rept_size, 1527 usb_free_coherent(udev, usbtouch->data_size,
1527 usbtouch->data, usbtouch->data_dma); 1528 usbtouch->data, usbtouch->data_dma);
1528 kfree(usbtouch->buffer); 1529 kfree(usbtouch->buffer);
1529} 1530}
@@ -1568,7 +1569,20 @@ static int usbtouch_probe(struct usb_interface *intf,
1568 if (!type->process_pkt) 1569 if (!type->process_pkt)
1569 type->process_pkt = usbtouch_process_pkt; 1570 type->process_pkt = usbtouch_process_pkt;
1570 1571
1571 usbtouch->data = usb_alloc_coherent(udev, type->rept_size, 1572 usbtouch->data_size = type->rept_size;
1573 if (type->get_pkt_len) {
1574 /*
1575 * When dealing with variable-length packets we should
1576 * not request more than wMaxPacketSize bytes at once
1577 * as we do not know if there is more data coming or
1578 * we filled exactly wMaxPacketSize bytes and there is
1579 * nothing else.
1580 */
1581 usbtouch->data_size = min(usbtouch->data_size,
1582 usb_endpoint_maxp(endpoint));
1583 }
1584
1585 usbtouch->data = usb_alloc_coherent(udev, usbtouch->data_size,
1572 GFP_KERNEL, &usbtouch->data_dma); 1586 GFP_KERNEL, &usbtouch->data_dma);
1573 if (!usbtouch->data) 1587 if (!usbtouch->data)
1574 goto out_free; 1588 goto out_free;
@@ -1628,12 +1642,12 @@ static int usbtouch_probe(struct usb_interface *intf,
1628 if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT) 1642 if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT)
1629 usb_fill_int_urb(usbtouch->irq, udev, 1643 usb_fill_int_urb(usbtouch->irq, udev,
1630 usb_rcvintpipe(udev, endpoint->bEndpointAddress), 1644 usb_rcvintpipe(udev, endpoint->bEndpointAddress),
1631 usbtouch->data, type->rept_size, 1645 usbtouch->data, usbtouch->data_size,
1632 usbtouch_irq, usbtouch, endpoint->bInterval); 1646 usbtouch_irq, usbtouch, endpoint->bInterval);
1633 else 1647 else
1634 usb_fill_bulk_urb(usbtouch->irq, udev, 1648 usb_fill_bulk_urb(usbtouch->irq, udev,
1635 usb_rcvbulkpipe(udev, endpoint->bEndpointAddress), 1649 usb_rcvbulkpipe(udev, endpoint->bEndpointAddress),
1636 usbtouch->data, type->rept_size, 1650 usbtouch->data, usbtouch->data_size,
1637 usbtouch_irq, usbtouch); 1651 usbtouch_irq, usbtouch);
1638 1652
1639 usbtouch->irq->dev = udev; 1653 usbtouch->irq->dev = udev;