Re: Busted keyboard, fix, and Question about default HID device plumbing
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Date: 2011-10-07 22:07:54
Hi Terry, On Fri, Oct 07, 2011 at 01:44:29PM -0700, Terry Lambert wrote:
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,
They aren't. Or maybe we are talking about different "hiddev"s. The generic HID driver binds devices to hid-input which registers them with input core as separate input devices. The legacy console registers a separate input handler (see drivers/tty/vt/keyboard.c) that binds to all keyboard-like devices, listens to input events and converts them to keystrokes and sends them to tty. There is also a evdev input handler (that's where evtest utility gets its data from) that provides input event data to userspace via /dev/input/eventX nodes where X picks it does its own thing with it.
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
Hmm, so the shift is reported as released before we get the next key... Wierd...
quoted hunk
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; + } + }
Wait, why are you using usbkbd? Unless you have very compelling reason you should be using hid & hid-input. Thanks. -- Dmitry -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html