Busted keyboard, fix, and Question about default HID device plumbing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I have a USB keyboard that needs a workaround.  I know what the
workaround is, but not where to plumb it in.

This is apparently an issue with a number of keyboards from a number
of vendors, and Mac OS X and Windows both work around it.  It impacts
all Linux desktops, Android, and Chrome OS for a number of popular
folding keyboards, as well as other keyboards.

I'm perfectly able to write the workaround, and have done so using the
boot protocol, but now I want to fix the issue in the default stack
used for the console.

I don't care about the UHCI/EHCI plumbing, or anything up to hiddev;
but from there it gets murky as to how an event in the raw driver ends
up getting turned into a keyboard key.  It appears to be lost in
callbacks I'm having a hard time tracing through.

I've read three books on the Linux USB system, two of them very out of
date, and they're all written from the perspective of "So, you want to
write a device driver", rather than the perspective of "This book
documents the plumbing between the driver and userspace and how to
figure it out".

So the question is: how are things plumbed between hiddev and the
console driver, so I can figure out where I need to hack on the
events.

I just need to know the correct place/method to interpose the events.

Any help would be appreciated.

Thanks,
-- Terry

PS: For the curious:

I put a USB protocol analyzer on this thing, and discovered the problem.

The issue is that modifier keys are not reported in the bitmap on the
keyboard, and are instead signaled as in-band key events themselves.
The Mac OS X and Windows drivers work around the issue by
pre-processing the event stream looking for in-band modifier keys, and
then converting them into bit-sets in the (0'ed) bitmap of modifier
keys, and then dropping them from the key event stream.  Without the
workaround, the report order is such that it looks like a modifier up
report followed by a keystroke.  Here's evtest output for the sequence
after processing by the (unknown to me -- that's what I'm trying to
find out) code:

Event: time 1318019769.922534, type 4 (Misc), code 4 (ScanCode), value 700e1
Event: time 1318019769.922550, type 1 (Key), code 42 (LeftShift), value 1
Event: time 1318019769.922554, -------------- Report Sync ------------
Event: time 1318019770.082521, type 4 (Misc), code 4 (ScanCode), value
700e1 XXXX
Event: time 1318019770.082534, type 1 (Key), code 42 (LeftShift),
value 0          XXXX
Event: time 1318019770.082549, type 4 (Misc), code 4 (ScanCode), value 7001e
Event: time 1318019770.082553, type 1 (Key), code 2 (1), value 1
Event: time 1318019770.082555, -------------- Report Sync ------------
1Event: time 1318019770.242541, type 4 (Misc), code 4 (ScanCode), value 7001e
Event: time 1318019770.242552, type 1 (Key), code 2 (1), value 0
Event: time 1318019770.242555, -------------- Report Sync ------------

This is a shift-1.

The patch for usbkbd.c looks like this:

diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c
index 0658173..d22ecdb 100644
--- a/drivers/hid/usbhid/usbkbd.c
+++ b/drivers/hid/usbhid/usbkbd.c
@@ -2,6 +2,10 @@
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
  *  USB HIDBP Keyboard support
+ *
+ * Device Class Definition for Human Interface Devices (HID) Version 1.11
+ * Section 8.3 describes the report formant.
+ * http://www.usb.org/developers/devclass_docs/HID1_11.pdf
  */

 /*
@@ -97,6 +101,16 @@ static void usb_kbd_irq(struct urb *urb)
                goto resubmit;
        }

+       /* Convert in-band modifier keys to modifier bits */
+       for (i = 2; i < 8; i++) {
+               if (kbd->new[i] >= 0xE0 && kbd->new[i] <= 0xE7) {
+                       kbd->new[0] |= (1 >> (kbd->new[i] - 0xE0));
+                       kbd->new[i] = 0;
+               }
+       }
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux