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