(no subject)

Paul Mackerras (paulus@samba.org)
Fri, 20 Apr 2001 17:15:34 +1000 (EST)


Linus,

This patch fixes some bugs in drivers/usb/hid.c. Johannes Erdfelt
(the maintainer) sent it to you previously but it got missed. Could
it go in 2.4.4 please? Here are the comments explaining the patch
that I wrote originally:

> The first hunk just fixes some typos in s32ton. For example, with
> n == 8, the code as it was would return 0x80 if value > 127 but 0xff
> if value < -128. With my change it returns 0x7f for value > 127 and
> 0x80 for value < -128.
>
> The second hunk fixes the "cdcd" problem that we see on apple
> keyboards that can only handle 2-key rollover. If you type "c" "d"
> <space> quickly on these keyboards, you get a report with the
> error-rollover code (1) in bytes 2 - 7 (instead of the codes for the
> keys that are down). Without this patch the code thinks that all the
> keys that were down are now up. When you release one key you get a
> normal report again and the code thinks that the remaining keys have
> been pressed again. The patch makes the code just discard the report
> once it sees the error-rollover code.
>
> The remaining hunks fix some endianness problems in the code that sets
> the keyboard leds.

Thanks,
Paul.

diff -urN linux/drivers/usb/hid.c linuxppc_2_4/drivers/usb/hid.c
--- linux/drivers/usb/hid.c Thu Feb 22 14:25:27 2001
+++ linuxppc_2_4/drivers/usb/hid.c Mon Feb 12 13:35:00 2001
@@ -698,7 +698,7 @@
static __inline__ __u32 s32ton(__s32 value, unsigned n)
{
__s32 a = value >> (n - 1);
- if (a && a != -1) return value > 0 ? 1 << (n - 1) : (1 << n) - 1;
+ if (a && a != -1) return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1;
return value & ((1 << n) - 1);
}

@@ -1016,9 +1016,15 @@
__s32 max = field->logical_maximum;
__s32 value[count]; /* WARNING: gcc specific */

- for (n = 0; n < count; n++)
+ for (n = 0; n < count; n++) {
value[n] = min < 0 ? snto32(extract(data, offset + n * size, size), size) :
extract(data, offset + n * size, size);
+ /* Handle the ErrorRollOver code (1) by simply ignoring this report */
+ if (!(field->flags & HID_MAIN_ITEM_VARIABLE)
+ && value[n] >= min && value[n] <= max
+ && field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1)
+ return;
+ }

for (n = 0; n < count; n++) {

@@ -1231,7 +1237,7 @@

static int hid_submit_out(struct hid_device *hid)
{
- hid->urbout.transfer_buffer_length = hid->out[hid->outtail].dr.length;
+ hid->urbout.transfer_buffer_length = le16_to_cpup(&hid->out[hid->outtail].dr.length);
hid->urbout.transfer_buffer = hid->out[hid->outtail].buffer;
hid->urbout.setup_packet = (void *) &(hid->out[hid->outtail].dr);
hid->urbout.dev = hid->dev;
@@ -1271,8 +1277,8 @@
hid_set_field(field, offset, value);
hid_output_report(field->report, hid->out[hid->outhead].buffer);

- hid->out[hid->outhead].dr.value = 0x200 | field->report->id;
- hid->out[hid->outhead].dr.length = ((field->report->size - 1) >> 3) + 1;
+ hid->out[hid->outhead].dr.value = cpu_to_le16(0x200 | field->report->id);
+ hid->out[hid->outhead].dr.length = cpu_to_le16((field->report->size + 7) >> 3);

hid->outhead = (hid->outhead + 1) & (HID_CONTROL_FIFO_SIZE - 1);

@@ -1445,7 +1451,7 @@
for (n = 0; n < HID_CONTROL_FIFO_SIZE; n++) {
hid->out[n].dr.requesttype = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
hid->out[n].dr.request = USB_REQ_SET_REPORT;
- hid->out[n].dr.index = hid->ifnum;
+ hid->out[n].dr.index = cpu_to_le16(hid->ifnum);
}

hid->input.name = hid->name;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/