Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 8466
b: refs/heads/master
c: bf0964d
h: refs/heads/master
v: v3
  • Loading branch information
Michael Haboustak authored and Dmitry Torokhov committed Sep 5, 2005
1 parent 539af78 commit 617326b
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 20 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 903b126bffb77dc313b7c2971880df408bf41a9e
refs/heads/master: bf0964dcda97e42964d312d0ff73a832171e080a
62 changes: 44 additions & 18 deletions trunk/drivers/usb/input/hid-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
* USB HID support for Linux
*
* Copyright (c) 1999 Andreas Gal
* Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
*/

/*
Expand Down Expand Up @@ -38,7 +39,7 @@
* Version Information
*/

#define DRIVER_VERSION "v2.01"
#define DRIVER_VERSION "v2.6"
#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik"
#define DRIVER_DESC "USB HID core driver"
#define DRIVER_LICENSE "GPL"
Expand Down Expand Up @@ -1058,8 +1059,8 @@ static int hid_submit_ctrl(struct hid_device *hid)
if (maxpacket > 0) {
padlen = (len + maxpacket - 1) / maxpacket;
padlen *= maxpacket;
if (padlen > HID_BUFFER_SIZE)
padlen = HID_BUFFER_SIZE;
if (padlen > hid->bufsize)
padlen = hid->bufsize;
} else
padlen = 0;
hid->urbctrl->transfer_buffer_length = padlen;
Expand Down Expand Up @@ -1284,13 +1285,8 @@ void hid_init_reports(struct hid_device *hid)
struct hid_report *report;
int err, ret;

list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list) {
int size = ((report->size - 1) >> 3) + 1 + hid->report_enum[HID_INPUT_REPORT].numbered;
if (size > HID_BUFFER_SIZE) size = HID_BUFFER_SIZE;
if (size > hid->urbin->transfer_buffer_length)
hid->urbin->transfer_buffer_length = size;
list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list)
hid_submit_report(hid, report, USB_DIR_IN);
}

list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
hid_submit_report(hid, report, USB_DIR_IN);
Expand Down Expand Up @@ -1564,15 +1560,32 @@ static struct hid_blacklist {
{ 0, 0 }
};

/*
* Traverse the supplied list of reports and find the longest
*/
static void hid_find_max_report(struct hid_device *hid, unsigned int type, int *max)
{
struct hid_report *report;
int size;

list_for_each_entry(report, &hid->report_enum[type].report_list, list) {
size = ((report->size - 1) >> 3) + 1;
if (type == HID_INPUT_REPORT && hid->report_enum[type].numbered)
size++;
if (*max < size)
*max = size;
}
}

static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
{
if (!(hid->inbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->inbuf_dma)))
if (!(hid->inbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->inbuf_dma)))
return -1;
if (!(hid->outbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->outbuf_dma)))
if (!(hid->outbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->outbuf_dma)))
return -1;
if (!(hid->cr = usb_buffer_alloc(dev, sizeof(*(hid->cr)), SLAB_ATOMIC, &hid->cr_dma)))
return -1;
if (!(hid->ctrlbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->ctrlbuf_dma)))
if (!(hid->ctrlbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->ctrlbuf_dma)))
return -1;

return 0;
Expand All @@ -1581,13 +1594,13 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
{
if (hid->inbuf)
usb_buffer_free(dev, HID_BUFFER_SIZE, hid->inbuf, hid->inbuf_dma);
usb_buffer_free(dev, hid->bufsize, hid->inbuf, hid->inbuf_dma);
if (hid->outbuf)
usb_buffer_free(dev, HID_BUFFER_SIZE, hid->outbuf, hid->outbuf_dma);
usb_buffer_free(dev, hid->bufsize, hid->outbuf, hid->outbuf_dma);
if (hid->cr)
usb_buffer_free(dev, sizeof(*(hid->cr)), hid->cr, hid->cr_dma);
if (hid->ctrlbuf)
usb_buffer_free(dev, HID_BUFFER_SIZE, hid->ctrlbuf, hid->ctrlbuf_dma);
usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma);
}

static struct hid_device *usb_hid_configure(struct usb_interface *intf)
Expand All @@ -1598,7 +1611,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
struct hid_device *hid;
unsigned quirks = 0, rsize = 0;
char *buf, *rdesc;
int n;
int n, insize = 0;

for (n = 0; hid_blacklist[n].idVendor; n++)
if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) &&
Expand Down Expand Up @@ -1652,6 +1665,19 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
kfree(rdesc);
hid->quirks = quirks;

hid->bufsize = HID_MIN_BUFFER_SIZE;
hid_find_max_report(hid, HID_INPUT_REPORT, &hid->bufsize);
hid_find_max_report(hid, HID_OUTPUT_REPORT, &hid->bufsize);
hid_find_max_report(hid, HID_FEATURE_REPORT, &hid->bufsize);

if (hid->bufsize > HID_MAX_BUFFER_SIZE)
hid->bufsize = HID_MAX_BUFFER_SIZE;

hid_find_max_report(hid, HID_INPUT_REPORT, &insize);

if (insize > HID_MAX_BUFFER_SIZE)
insize = HID_MAX_BUFFER_SIZE;

if (hid_alloc_buffers(dev, hid)) {
hid_free_buffers(dev, hid);
goto fail;
Expand Down Expand Up @@ -1682,7 +1708,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
goto fail;
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, 0,
usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, insize,
hid_irq_in, hid, interval);
hid->urbin->transfer_dma = hid->inbuf_dma;
hid->urbin->transfer_flags |=(URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK);
Expand Down
5 changes: 4 additions & 1 deletion trunk/drivers/usb/input/hid.h
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,8 @@ struct hid_report_enum {

#define HID_REPORT_TYPES 3

#define HID_BUFFER_SIZE 64 /* use 64 for compatibility with all possible packetlen */
#define HID_MIN_BUFFER_SIZE 64 /* make sure there is at least a packet size of space */
#define HID_MAX_BUFFER_SIZE 4096 /* 4kb */
#define HID_CONTROL_FIFO_SIZE 256 /* to init devices with >100 reports */
#define HID_OUTPUT_FIFO_SIZE 64

Expand Down Expand Up @@ -389,6 +390,8 @@ struct hid_device { /* device report descriptor */

unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */

unsigned int bufsize; /* URB buffer size */

struct urb *urbin; /* Input URB */
char *inbuf; /* Input buffer */
dma_addr_t inbuf_dma; /* Input buffer dma */
Expand Down

0 comments on commit 617326b

Please sign in to comment.