diff options
-rw-r--r-- | drivers/usb/input/hid-core.c | 62 | ||||
-rw-r--r-- | drivers/usb/input/hid.h | 5 |
2 files changed, 48 insertions, 19 deletions
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index b2cb2b35892e..376b6043bbff 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c | |||
@@ -2,7 +2,8 @@ | |||
2 | * USB HID support for Linux | 2 | * USB HID support for Linux |
3 | * | 3 | * |
4 | * Copyright (c) 1999 Andreas Gal | 4 | * Copyright (c) 1999 Andreas Gal |
5 | * Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@suse.cz> | 5 | * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> |
6 | * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc | ||
6 | */ | 7 | */ |
7 | 8 | ||
8 | /* | 9 | /* |
@@ -38,7 +39,7 @@ | |||
38 | * Version Information | 39 | * Version Information |
39 | */ | 40 | */ |
40 | 41 | ||
41 | #define DRIVER_VERSION "v2.01" | 42 | #define DRIVER_VERSION "v2.6" |
42 | #define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik" | 43 | #define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik" |
43 | #define DRIVER_DESC "USB HID core driver" | 44 | #define DRIVER_DESC "USB HID core driver" |
44 | #define DRIVER_LICENSE "GPL" | 45 | #define DRIVER_LICENSE "GPL" |
@@ -1058,8 +1059,8 @@ static int hid_submit_ctrl(struct hid_device *hid) | |||
1058 | if (maxpacket > 0) { | 1059 | if (maxpacket > 0) { |
1059 | padlen = (len + maxpacket - 1) / maxpacket; | 1060 | padlen = (len + maxpacket - 1) / maxpacket; |
1060 | padlen *= maxpacket; | 1061 | padlen *= maxpacket; |
1061 | if (padlen > HID_BUFFER_SIZE) | 1062 | if (padlen > hid->bufsize) |
1062 | padlen = HID_BUFFER_SIZE; | 1063 | padlen = hid->bufsize; |
1063 | } else | 1064 | } else |
1064 | padlen = 0; | 1065 | padlen = 0; |
1065 | hid->urbctrl->transfer_buffer_length = padlen; | 1066 | hid->urbctrl->transfer_buffer_length = padlen; |
@@ -1284,13 +1285,8 @@ void hid_init_reports(struct hid_device *hid) | |||
1284 | struct hid_report *report; | 1285 | struct hid_report *report; |
1285 | int err, ret; | 1286 | int err, ret; |
1286 | 1287 | ||
1287 | list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list) { | 1288 | list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list) |
1288 | int size = ((report->size - 1) >> 3) + 1 + hid->report_enum[HID_INPUT_REPORT].numbered; | ||
1289 | if (size > HID_BUFFER_SIZE) size = HID_BUFFER_SIZE; | ||
1290 | if (size > hid->urbin->transfer_buffer_length) | ||
1291 | hid->urbin->transfer_buffer_length = size; | ||
1292 | hid_submit_report(hid, report, USB_DIR_IN); | 1289 | hid_submit_report(hid, report, USB_DIR_IN); |
1293 | } | ||
1294 | 1290 | ||
1295 | list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list) | 1291 | list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list) |
1296 | hid_submit_report(hid, report, USB_DIR_IN); | 1292 | hid_submit_report(hid, report, USB_DIR_IN); |
@@ -1564,15 +1560,32 @@ static struct hid_blacklist { | |||
1564 | { 0, 0 } | 1560 | { 0, 0 } |
1565 | }; | 1561 | }; |
1566 | 1562 | ||
1563 | /* | ||
1564 | * Traverse the supplied list of reports and find the longest | ||
1565 | */ | ||
1566 | static void hid_find_max_report(struct hid_device *hid, unsigned int type, int *max) | ||
1567 | { | ||
1568 | struct hid_report *report; | ||
1569 | int size; | ||
1570 | |||
1571 | list_for_each_entry(report, &hid->report_enum[type].report_list, list) { | ||
1572 | size = ((report->size - 1) >> 3) + 1; | ||
1573 | if (type == HID_INPUT_REPORT && hid->report_enum[type].numbered) | ||
1574 | size++; | ||
1575 | if (*max < size) | ||
1576 | *max = size; | ||
1577 | } | ||
1578 | } | ||
1579 | |||
1567 | static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid) | 1580 | static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid) |
1568 | { | 1581 | { |
1569 | if (!(hid->inbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->inbuf_dma))) | 1582 | if (!(hid->inbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->inbuf_dma))) |
1570 | return -1; | 1583 | return -1; |
1571 | if (!(hid->outbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->outbuf_dma))) | 1584 | if (!(hid->outbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->outbuf_dma))) |
1572 | return -1; | 1585 | return -1; |
1573 | if (!(hid->cr = usb_buffer_alloc(dev, sizeof(*(hid->cr)), SLAB_ATOMIC, &hid->cr_dma))) | 1586 | if (!(hid->cr = usb_buffer_alloc(dev, sizeof(*(hid->cr)), SLAB_ATOMIC, &hid->cr_dma))) |
1574 | return -1; | 1587 | return -1; |
1575 | if (!(hid->ctrlbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->ctrlbuf_dma))) | 1588 | if (!(hid->ctrlbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->ctrlbuf_dma))) |
1576 | return -1; | 1589 | return -1; |
1577 | 1590 | ||
1578 | return 0; | 1591 | return 0; |
@@ -1581,13 +1594,13 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid) | |||
1581 | static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) | 1594 | static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) |
1582 | { | 1595 | { |
1583 | if (hid->inbuf) | 1596 | if (hid->inbuf) |
1584 | usb_buffer_free(dev, HID_BUFFER_SIZE, hid->inbuf, hid->inbuf_dma); | 1597 | usb_buffer_free(dev, hid->bufsize, hid->inbuf, hid->inbuf_dma); |
1585 | if (hid->outbuf) | 1598 | if (hid->outbuf) |
1586 | usb_buffer_free(dev, HID_BUFFER_SIZE, hid->outbuf, hid->outbuf_dma); | 1599 | usb_buffer_free(dev, hid->bufsize, hid->outbuf, hid->outbuf_dma); |
1587 | if (hid->cr) | 1600 | if (hid->cr) |
1588 | usb_buffer_free(dev, sizeof(*(hid->cr)), hid->cr, hid->cr_dma); | 1601 | usb_buffer_free(dev, sizeof(*(hid->cr)), hid->cr, hid->cr_dma); |
1589 | if (hid->ctrlbuf) | 1602 | if (hid->ctrlbuf) |
1590 | usb_buffer_free(dev, HID_BUFFER_SIZE, hid->ctrlbuf, hid->ctrlbuf_dma); | 1603 | usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma); |
1591 | } | 1604 | } |
1592 | 1605 | ||
1593 | static struct hid_device *usb_hid_configure(struct usb_interface *intf) | 1606 | static struct hid_device *usb_hid_configure(struct usb_interface *intf) |
@@ -1598,7 +1611,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
1598 | struct hid_device *hid; | 1611 | struct hid_device *hid; |
1599 | unsigned quirks = 0, rsize = 0; | 1612 | unsigned quirks = 0, rsize = 0; |
1600 | char *buf, *rdesc; | 1613 | char *buf, *rdesc; |
1601 | int n; | 1614 | int n, insize = 0; |
1602 | 1615 | ||
1603 | for (n = 0; hid_blacklist[n].idVendor; n++) | 1616 | for (n = 0; hid_blacklist[n].idVendor; n++) |
1604 | if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) && | 1617 | if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) && |
@@ -1652,6 +1665,19 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
1652 | kfree(rdesc); | 1665 | kfree(rdesc); |
1653 | hid->quirks = quirks; | 1666 | hid->quirks = quirks; |
1654 | 1667 | ||
1668 | hid->bufsize = HID_MIN_BUFFER_SIZE; | ||
1669 | hid_find_max_report(hid, HID_INPUT_REPORT, &hid->bufsize); | ||
1670 | hid_find_max_report(hid, HID_OUTPUT_REPORT, &hid->bufsize); | ||
1671 | hid_find_max_report(hid, HID_FEATURE_REPORT, &hid->bufsize); | ||
1672 | |||
1673 | if (hid->bufsize > HID_MAX_BUFFER_SIZE) | ||
1674 | hid->bufsize = HID_MAX_BUFFER_SIZE; | ||
1675 | |||
1676 | hid_find_max_report(hid, HID_INPUT_REPORT, &insize); | ||
1677 | |||
1678 | if (insize > HID_MAX_BUFFER_SIZE) | ||
1679 | insize = HID_MAX_BUFFER_SIZE; | ||
1680 | |||
1655 | if (hid_alloc_buffers(dev, hid)) { | 1681 | if (hid_alloc_buffers(dev, hid)) { |
1656 | hid_free_buffers(dev, hid); | 1682 | hid_free_buffers(dev, hid); |
1657 | goto fail; | 1683 | goto fail; |
@@ -1682,7 +1708,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
1682 | if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL))) | 1708 | if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL))) |
1683 | goto fail; | 1709 | goto fail; |
1684 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); | 1710 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); |
1685 | usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, 0, | 1711 | usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, insize, |
1686 | hid_irq_in, hid, interval); | 1712 | hid_irq_in, hid, interval); |
1687 | hid->urbin->transfer_dma = hid->inbuf_dma; | 1713 | hid->urbin->transfer_dma = hid->inbuf_dma; |
1688 | hid->urbin->transfer_flags |=(URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK); | 1714 | hid->urbin->transfer_flags |=(URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK); |
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h index ca3e170ce0b3..d76bbc81f6a8 100644 --- a/drivers/usb/input/hid.h +++ b/drivers/usb/input/hid.h | |||
@@ -351,7 +351,8 @@ struct hid_report_enum { | |||
351 | 351 | ||
352 | #define HID_REPORT_TYPES 3 | 352 | #define HID_REPORT_TYPES 3 |
353 | 353 | ||
354 | #define HID_BUFFER_SIZE 64 /* use 64 for compatibility with all possible packetlen */ | 354 | #define HID_MIN_BUFFER_SIZE 64 /* make sure there is at least a packet size of space */ |
355 | #define HID_MAX_BUFFER_SIZE 4096 /* 4kb */ | ||
355 | #define HID_CONTROL_FIFO_SIZE 256 /* to init devices with >100 reports */ | 356 | #define HID_CONTROL_FIFO_SIZE 256 /* to init devices with >100 reports */ |
356 | #define HID_OUTPUT_FIFO_SIZE 64 | 357 | #define HID_OUTPUT_FIFO_SIZE 64 |
357 | 358 | ||
@@ -389,6 +390,8 @@ struct hid_device { /* device report descriptor */ | |||
389 | 390 | ||
390 | unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ | 391 | unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ |
391 | 392 | ||
393 | unsigned int bufsize; /* URB buffer size */ | ||
394 | |||
392 | struct urb *urbin; /* Input URB */ | 395 | struct urb *urbin; /* Input URB */ |
393 | char *inbuf; /* Input buffer */ | 396 | char *inbuf; /* Input buffer */ |
394 | dma_addr_t inbuf_dma; /* Input buffer dma */ | 397 | dma_addr_t inbuf_dma; /* Input buffer dma */ |