From: Vojtech Pavlik <vojtech@suse.cz>
To: torvalds@osdl.org, dtor_core@ameritech.net,
linux-kernel@vger.kernel.org, vojtech@suse.cz
Subject: [PATCH 15/26] HID - handle multi-transascion reports
Date: Sun, 11 Sep 2005 00:34:13 +0200 [thread overview]
Message-ID: <11263916532510@midnight.ucw.cz> (raw)
In-Reply-To: <1126391653526@midnight.ucw.cz>
Subject: [PATCH] Input: HID - handle multi-transascion reports
From: Michael Haboustak <mike-@cinci.rr.com>
Date: 1125897121 -0500
Fixes handling of multi-transaction reports for HID devices. New
function hid_size_buffers() that calculates the longest report
for each endpoint and stores the result in the hid_device object.
These lengths are used to allocate buffers that are large enough
to store any report on the endpoint. For compatibility, the minimum
size for an endpoint buffer set to HID_BUFFER_SIZE rather than the
known optimal case (the longest report length).
It fixes bug #3063 in bugzilla.
Signed-off-by: Michael Haboustak <mike-@cinci.rr.com>
I simplified the patch a bit to use just a single buffer size.
Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---
drivers/usb/input/hid-core.c | 62 ++++++++++++++++++++++++++++++------------
drivers/usb/input/hid.h | 5 +++
2 files changed, 48 insertions(+), 19 deletions(-)
bf0964dcda97e42964d312d0ff73a832171e080a
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -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
*/
/*
@@ -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"
@@ -1058,8 +1059,8 @@ static int hid_submit_ctrl(struct hid_de
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;
@@ -1284,13 +1285,8 @@ void hid_init_reports(struct hid_device
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);
@@ -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;
@@ -1581,13 +1594,13 @@ static int hid_alloc_buffers(struct usb_
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)
@@ -1598,7 +1611,7 @@ static struct hid_device *usb_hid_config
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)) &&
@@ -1652,6 +1665,19 @@ static struct hid_device *usb_hid_config
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;
@@ -1682,7 +1708,7 @@ static struct hid_device *usb_hid_config
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);
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
--- a/drivers/usb/input/hid.h
+++ b/drivers/usb/input/hid.h
@@ -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
@@ -389,6 +390,8 @@ struct hid_device { /* device repo
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 */
next prev parent reply other threads:[~2005-09-10 22:43 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-09-10 22:32 [GIT PULL 0/26] Input update Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 1/26] psmouse - add support for IBM TrackPoint devices Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 2/26] rework psmouse attributes to reduce module size Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 3/26] ALPS - fix wheel decoding Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 4/26] psmouse - add new Logitech wheel mouse model Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 5/26] fix checking whether new keycode fits size-wise Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 6/26] i8042 - clean up initialization code; abort if we Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 7/26] make i8042_platform_init return 'real' error code Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 8/26] i8042 - fix IRQ printing when either KBD or AUX port Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 9/26] i8042 - add i8042.nokbd module option to allow supressing Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 10/26] i8042 - add Lifebook E4010 to MUX blacklist Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 11/26] recognize and ignore Logitech vendor usages in HID Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 12/26] add HID simulation mappings Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 13/26] HID - add more consumer usages Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 14/26] atkbd - handle keyboards generating scancode 0x7f Vojtech Pavlik
2005-09-10 22:34 ` Vojtech Pavlik [this message]
2005-09-10 22:34 ` [PATCH 16/26] HID - add support for Logitech UltraX Media Remote control Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 17/26] iforce - use wait_event_interruptible_timeout Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 18/26] sunkbd - extend mapping to handle Type-6 Sun keyboards Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 19/26] HID - fix URB success status handling Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 20/26] HID - add a quirk for the Apple Powermouse Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 21/26] HID - add the Trust Predator TH 400 gamepad to the badpad list Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 22/26] HID - add mapping for Powerbook USB keyboard Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 23/26] HID - add Wireless Security Lock to HID blacklist Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 24/26] HIDDEV - make HIDIOCSREPORT wait IO completion Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 25/26] clean up whitespace and formatting in drivers/char/keyboard.c Vojtech Pavlik
2005-09-10 22:34 ` [PATCH 26/26] i8042 - use kzalloc instead of kcalloc Vojtech Pavlik
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=11263916532510@midnight.ucw.cz \
--to=vojtech@suse.cz \
--cc=dtor_core@ameritech.net \
--cc=linux-kernel@vger.kernel.org \
--cc=torvalds@osdl.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox