Discussion:
Busted keyboard, fix, and Question about default HID device plumbing
Terry Lambert
2011-10-07 20:44:29 UTC
Permalink
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. =A0It 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=
=2E

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=
=2E11
+ * 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 =3D 2; i < 8; i++) {
+ if (kbd->new[i] >=3D 0xE0 && kbd->new[i] <=3D 0xE7) {
+ kbd->new[0] |=3D (1 >> (kbd->new[i] - 0xE0));
+ kbd->new[i] =3D 0;
+ }
+ }
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Dmitry Torokhov
2011-10-07 22:07:45 UTC
Permalink
Hi Terry,
Post by Terry Lambert
I have a USB keyboard that needs a workaround. I know what the
workaround is, but not where to plumb it in.
=20
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.
=20
I'm perfectly able to write the workaround, and have done so using th=
e
Post by Terry Lambert
boot protocol, but now I want to fix the issue in the default stack
used for the console.
=20
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 end=
s
Post by Terry Lambert
up getting turned into a keyboard key. =A0It appears to be lost in
callbacks I'm having a hard time tracing through.
=20
I've read three books on the Linux USB system, two of them very out o=
f
Post by Terry Lambert
date, and they're all written from the perspective of "So, you want t=
o
Post by Terry Lambert
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".
=20
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 al=
l
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.
Post by Terry Lambert
so I can figure out where I need to hack on the
events.
=20
I just need to know the correct place/method to interpose the events.
=20
Any help would be appreciated.
=20
Thanks,
-- Terry
=20
=20
I put a USB protocol analyzer on this thing, and discovered the probl=
em.
Post by Terry Lambert
=20
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, an=
d
Post by Terry Lambert
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 sequenc=
e
Post by Terry Lambert
after processing by the (unknown to me -- that's what I'm trying to
=20
Event: time 1318019769.922534, type 4 (Misc), code 4 (ScanCode), valu=
e 700e1
Post by Terry Lambert
Event: time 1318019769.922550, type 1 (Key), code 42 (LeftShift), val=
ue 1
Post by Terry Lambert
Event: time 1318019769.922554, -------------- Report Sync -----------=
-
Post by Terry Lambert
Event: time 1318019770.082521, type 4 (Misc), code 4 (ScanCode), valu=
e
Post by Terry Lambert
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...
Post by Terry Lambert
Event: time 1318019770.082549, type 4 (Misc), code 4 (ScanCode), valu=
e 7001e
Post by Terry Lambert
Event: time 1318019770.082553, type 1 (Key), code 2 (1), value 1
Event: time 1318019770.082555, -------------- Report Sync -----------=
-
Post by Terry Lambert
1Event: time 1318019770.242541, type 4 (Misc), code 4 (ScanCode), val=
ue 7001e
Post by Terry Lambert
Event: time 1318019770.242552, type 1 (Key), code 2 (1), value 0
Event: time 1318019770.242555, -------------- Report Sync -----------=
-
Post by Terry Lambert
=20
This is a shift-1.
=20
=20
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.=
c
Post by Terry Lambert
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
Post by Terry Lambert
+ * Section 8.3 describes the report formant.
+ * http://www.usb.org/developers/devclass_docs/HID1_11.pdf
*/
=20
/*
@@ -97,6 +101,16 @@ static void usb_kbd_irq(struct urb *urb)
goto resubmit;
}
=20
+ /* Convert in-band modifier keys to modifier bits */
+ for (i =3D 2; i < 8; i++) {
+ if (kbd->new[i] >=3D 0xE0 && kbd->new[i] <=3D 0xE7) {
+ kbd->new[0] |=3D (1 >> (kbd->new[i] - 0xE0));
+ kbd->new[i] =3D 0;
+ }
+ }
Wait, why are you using usbkbd? Unless you have very compelling reason
you should be using hid & hid-input.

Thanks.

--=20
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-input" =
in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Terry Lambert
2011-10-07 23:01:19 UTC
Permalink
Thanks for replying, Dmitry...

I guess I need to clarify a point or two.

On Fri, Oct 7, 2011 at 3:07 PM, Dmitry Torokhov
Post by Dmitry Torokhov
Hi Terry,
I have a USB keyboard that needs a workaround. =A0I know what the
workaround is, but not where to plumb it in.
This is apparently an issue with a number of keyboards from a numbe=
r
Post by Dmitry Torokhov
of vendors, and Mac OS X and Windows both work around it. =A0It imp=
acts
Post by Dmitry Torokhov
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
Post by Dmitry Torokhov
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=
;
Post by Dmitry Torokhov
but from there it gets murky as to how an event in the raw driver e=
nds
Post by Dmitry Torokhov
up getting turned into a keyboard key. =A0It 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
Post by Dmitry Torokhov
date, and they're all written from the perspective of "So, you want=
to
Post by Dmitry Torokhov
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 wi=
th
Post by Dmitry Torokhov
input core as separate input devices. The legacy console registers a
separate input handler (see drivers/tty/vt/keyboard.c) that binds to =
all
Post by Dmitry Torokhov
keyboard-like devices, listens to input events and converts them to
keystrokes and sends them to tty.
My question is "who processes USB report packets from a USB keyboard
into EV_KEY events?"

I understand that there's a separate evdev handler that publishes raw
events as /dev/input/eventX. It's handling the events from somewhere,
but it's not clear to me how a hidraw1 event turns into a console
input event.

Somewhere someone is translating a USB 1.11 section 8.3 report into an
EV_KEY, and I need to do the modifier magic to alter the contents of
the reports before it gets to whoever that is.
You seem to be saying hid-input.c ... but I'm not seeing the modifier
bits being processed out of the report?
Post by Dmitry Torokhov
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 event=
s.
Post by Dmitry Torokhov
Any help would be appreciated.
Thanks,
-- Terry
I put a USB protocol analyzer on this thing, and discovered the pro=
blem.
Post by Dmitry Torokhov
The issue is that modifier keys are not reported in the bitmap on t=
he
Post by Dmitry Torokhov
keyboard, and are instead signaled as in-band key events themselves=
=2E
Post by Dmitry Torokhov
The Mac OS X and Windows drivers work around the issue by
pre-processing the event stream looking for in-band modifier keys, =
and
Post by Dmitry Torokhov
then converting them into bit-sets in the (0'ed) bitmap of modifier
keys, and then dropping them from the key event stream. =A0Without =
the
Post by Dmitry Torokhov
workaround, the report order is such that it looks like a modifier =
up
Post by Dmitry Torokhov
report followed by a keystroke. =A0Here's evtest output for the seq=
uence
Post by Dmitry Torokhov
after processing by the (unknown to me -- that's what I'm trying to
Event: time 1318019769.922534, type 4 (Misc), code 4 (ScanCode), va=
lue 700e1
Post by Dmitry Torokhov
Event: time 1318019769.922550, type 1 (Key), code 42 (LeftShift), v=
alue 1
Post by Dmitry Torokhov
Event: time 1318019769.922554, -------------- Report Sync ---------=
---
Post by Dmitry Torokhov
Event: time 1318019770.082521, type 4 (Misc), code 4 (ScanCode), va=
lue
Post by Dmitry Torokhov
700e1 XXXX
Event: time 1318019770.082534, type 1 (Key), code 42 (LeftShift),
value 0 =A0 =A0 =A0 =A0 =A0XXXX
Hmm, so the shift is reported as released before we get the next key.=
=2E.
Post by Dmitry Torokhov
Wierd...
Event: time 1318019770.082549, type 4 (Misc), code 4 (ScanCode), va=
lue 7001e
Post by Dmitry Torokhov
Event: time 1318019770.082553, type 1 (Key), code 2 (1), value 1
Event: time 1318019770.082555, -------------- Report Sync ---------=
---
Post by Dmitry Torokhov
1Event: time 1318019770.242541, type 4 (Misc), code 4 (ScanCode), v=
alue 7001e
Post by Dmitry Torokhov
Event: time 1318019770.242552, type 1 (Key), code 2 (1), value 0
Event: time 1318019770.242555, -------------- Report Sync ---------=
---
Post by Dmitry Torokhov
This is a shift-1.
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkb=
d.c
Post by Dmitry Torokhov
index 0658173..d22ecdb 100644
--- a/drivers/hid/usbhid/usbkbd.c
+++ b/drivers/hid/usbhid/usbkbd.c
@@ -2,6 +2,10 @@
=A0 * =A0Copyright (c) 1999-2001 Vojtech Pavlik
=A0 *
=A0 * =A0USB HIDBP Keyboard support
+ *
+ * Device Class Definition for Human Interface Devices (HID) Versi=
on 1.11
Post by Dmitry Torokhov
+ * Section 8.3 describes the report formant.
+ * http://www.usb.org/developers/devclass_docs/HID1_11.pdf
=A0 */
=A0/*
@@ -97,6 +101,16 @@ static void usb_kbd_irq(struct urb *urb)
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto resubmit;
=A0 =A0 =A0 =A0 }
+ =A0 =A0 =A0 /* Convert in-band modifier keys to modifier bits */
+ =A0 =A0 =A0 for (i =3D 2; i < 8; i++) {
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (kbd->new[i] >=3D 0xE0 && kbd->new=
[i] <=3D 0xE7) {
Post by Dmitry Torokhov
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 kbd->new[0] |=3D (1 >=
(kbd->new[i] - 0xE0));
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 kbd->new[i] =3D 0;
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
+ =A0 =A0 =A0 }
Wait, why are you using usbkbd? Unless you have very compelling reaso=
n
Post by Dmitry Torokhov
you should be using hid & hid-input.
I fixed it there because it was accessible and a way to test the fix.
I'm also going to have to do something similar for coreboot/u-boot to
allow the keyboard to be used in the boot loader, so it's not wasted
effort, and it was an OK proof of concept. So there was a good
reason.

I'm getting the impression from the above that the file I should be
looking in is:

drivers/hid/hid-input.c

Where are the modifier bits being decoded there? Maybe I'm just not
seeing something in front of me...

The analyzer reports the USB over the wire report as:

<-- left shift key down -->
00 00 E1 00 00 00 00 00 <- transaction
69 82 18 <- input packet
48 00 00 E1 00 00 00 00 00 A8 45 <-- breakout : <--
Keyboard LeftControl : 0b0
Keyboard LeftShift : 0b0 <-- ***WRONG ***
Keyboard LeftAlt : 0b0
Keyboard LeftGUI : 0b0
Keyboard RightControl : 0b0
Keyboard RightShiftl : 0b0
Keyboard RightAlt : 0b0
Keyboard RightGUI : 0b0
Keyboard/Keypad Array : Keyboard LeftShift (225) <-- ***WRONG *=
**
Keyboard/Keypad Array :
Keyboard/Keypad Array :
Keyboard/Keypad Array :
Keyboard/Keypad Array :
Keyboard/Keypad Array :
-->
<-- 1 key down -->
00 00 E1 1E 00 00 00 00 <- transaction
69 82 18 <- input packet
C3 00 00 E1 1E 00 00 00 00 A8 45 <-- breakout : <--
Keyboard LeftControl : 0b0
Keyboard LeftShift : 0b0 <-- ***WRONG ***
Keyboard LeftAlt : 0b0
Keyboard LeftGUI : 0b0
Keyboard RightControl : 0b0
Keyboard RightShiftl : 0b0
Keyboard RightAlt : 0b0
Keyboard RightGUI : 0b0
Keyboard/Keypad Array : Keyboard LeftShift (d225) <-- *** WRON=
G ***
Keyboard/Keypad Array : Keyboard 1 and ! (d30)
Keyboard/Keypad Array : 00
Keyboard/Keypad Array : 00
Keyboard/Keypad Array : 00
Keyboard/Keypad Array : 00
-->
<-- 1 key up -- >
00 00 E1 00 00 00 00 00 <- transaction
69 82 18 <- input packet
48 00 00 E1 00 00 00 00 00 A8 45 <-- breakout : <--
Keyboard LeftControl : 0b0
Keyboard LeftShift : 0b0
Keyboard LeftAlt : 0b0
Keyboard LeftGUI : 0b0
Keyboard RightControl : 0b0
Keyboard RightShiftl : 0b0
Keyboard RightAlt : 0b0
Keyboard RightGUI : 0b0
Keyboard/Keypad Array : 00
Keyboard/Keypad Array : 00
Keyboard/Keypad Array : 00
Keyboard/Keypad Array : 00
Keyboard/Keypad Array : 00
Keyboard/Keypad Array : 00
-->
<-- left shift key up -->
00 00 00 00 00 00 00 00 <- transaction
69 82 18 <- input packet
48 00 00 00 00 00 00 00 00 BF F4 <-- breakout : <--
Keyboard LeftControl : 0b0
Keyboard LeftShift : 0b0 <-- ***WRONG ***
Keyboard LeftAlt : 0b0
Keyboard LeftGUI : 0b0
Keyboard RightControl : 0b0
Keyboard RightShiftl : 0b0
Keyboard RightAlt : 0b0
Keyboard RightGUI : 0b0
Keyboard/Keypad Array : Keyboard LeftShift (225) <-- ***WRONG *=
**
Keyboard/Keypad Array :
Keyboard/Keypad Array :
Keyboard/Keypad Array :
Keyboard/Keypad Array :
Keyboard/Keypad Array :
-->

I just need to know where in the code to stomp the report into
correctness. Should make a bunch of people happy. 8-)

Thanks,
-- Terry
Post by Dmitry Torokhov
Thanks.
--
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-input" =
in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Terry Lambert
2011-10-07 23:09:35 UTC
Permalink
Whoops. Flip those last two bit decodes!

-- Terry
Post by Terry Lambert
Thanks for replying, Dmitry...
I guess I need to clarify a point or two.
On Fri, Oct 7, 2011 at 3:07 PM, Dmitry Torokhov
Post by Dmitry Torokhov
Hi Terry,
I have a USB keyboard that needs a workaround. =A0I know what the
workaround is, but not where to plumb it in.
This is apparently an issue with a number of keyboards from a num=
ber
Post by Terry Lambert
Post by Dmitry Torokhov
of vendors, and Mac OS X and Windows both work around it. =A0It i=
mpacts
Post by Terry Lambert
Post by Dmitry Torokhov
all Linux desktops, Android, and Chrome OS for a number of popula=
r
Post by Terry Lambert
Post by Dmitry Torokhov
folding keyboards, as well as other keyboards.
I'm perfectly able to write the workaround, and have done so usin=
g the
Post by Terry Lambert
Post by Dmitry Torokhov
boot protocol, but now I want to fix the issue in the default sta=
ck
Post by Terry Lambert
Post by Dmitry Torokhov
used for the console.
I don't care about the UHCI/EHCI plumbing, or anything up to hidd=
ev;
Post by Terry Lambert
Post by Dmitry Torokhov
but from there it gets murky as to how an event in the raw driver=
ends
Post by Terry Lambert
Post by Dmitry Torokhov
up getting turned into a keyboard key. =A0It appears to be lost i=
n
Post by Terry Lambert
Post by Dmitry Torokhov
callbacks I'm having a hard time tracing through.
I've read three books on the Linux USB system, two of them very o=
ut of
Post by Terry Lambert
Post by Dmitry Torokhov
date, and they're all written from the perspective of "So, you wa=
nt to
Post by Terry Lambert
Post by Dmitry Torokhov
write a device driver", rather than the perspective of "This book
documents the plumbing between the driver and userspace and how t=
o
Post by Terry Lambert
Post by Dmitry Torokhov
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
Post by Terry Lambert
Post by Dmitry Torokhov
input core as separate input devices. The legacy console registers =
a
Post by Terry Lambert
Post by Dmitry Torokhov
separate input handler (see drivers/tty/vt/keyboard.c) that binds t=
o all
Post by Terry Lambert
Post by Dmitry Torokhov
keyboard-like devices, listens to input events and converts them to
keystrokes and sends them to tty.
My question is "who processes USB report packets from a USB keyboard
into EV_KEY events?"
I understand that there's a separate evdev handler that publishes raw
events as /dev/input/eventX. =A0It's handling the events from somewhe=
re,
Post by Terry Lambert
but it's not clear to me how a hidraw1 event turns into a console
input event.
Somewhere someone is translating a USB 1.11 section 8.3 report into a=
n
Post by Terry Lambert
EV_KEY, and I need to do the modifier magic to alter the contents of
the reports before it gets to whoever that is.
You seem to be saying hid-input.c ... but I'm not seeing the modifier
bits being processed out of the report?
Post by Dmitry Torokhov
There is also a evdev input handler (that's where evtest utility ge=
ts
Post by Terry Lambert
Post by Dmitry Torokhov
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=
=2E
Post by Terry Lambert
Post by Dmitry Torokhov
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 eve=
nts.
Post by Terry Lambert
Post by Dmitry Torokhov
Any help would be appreciated.
Thanks,
-- Terry
I put a USB protocol analyzer on this thing, and discovered the p=
roblem.
Post by Terry Lambert
Post by Dmitry Torokhov
The issue is that modifier keys are not reported in the bitmap on=
the
Post by Terry Lambert
Post by Dmitry Torokhov
keyboard, and are instead signaled as in-band key events themselv=
es.
Post by Terry Lambert
Post by Dmitry Torokhov
The Mac OS X and Windows drivers work around the issue by
pre-processing the event stream looking for in-band modifier keys=
, and
Post by Terry Lambert
Post by Dmitry Torokhov
then converting them into bit-sets in the (0'ed) bitmap of modifi=
er
Post by Terry Lambert
Post by Dmitry Torokhov
keys, and then dropping them from the key event stream. =A0Withou=
t the
Post by Terry Lambert
Post by Dmitry Torokhov
workaround, the report order is such that it looks like a modifie=
r up
Post by Terry Lambert
Post by Dmitry Torokhov
report followed by a keystroke. =A0Here's evtest output for the s=
equence
Post by Terry Lambert
Post by Dmitry Torokhov
after processing by the (unknown to me -- that's what I'm trying =
to
Post by Terry Lambert
Post by Dmitry Torokhov
Event: time 1318019769.922534, type 4 (Misc), code 4 (ScanCode), =
value 700e1
Post by Terry Lambert
Post by Dmitry Torokhov
Event: time 1318019769.922550, type 1 (Key), code 42 (LeftShift),=
value 1
Post by Terry Lambert
Post by Dmitry Torokhov
Event: time 1318019769.922554, -------------- Report Sync -------=
-----
Post by Terry Lambert
Post by Dmitry Torokhov
Event: time 1318019770.082521, type 4 (Misc), code 4 (ScanCode), =
value
Post by Terry Lambert
Post by Dmitry Torokhov
700e1 XXXX
Event: time 1318019770.082534, type 1 (Key), code 42 (LeftShift),
value 0 =A0 =A0 =A0 =A0 =A0XXXX
Hmm, so the shift is reported as released before we get the next ke=
y...
Post by Terry Lambert
Post by Dmitry Torokhov
Wierd...
Event: time 1318019770.082549, type 4 (Misc), code 4 (ScanCode), =
value 7001e
Post by Terry Lambert
Post by Dmitry Torokhov
Event: time 1318019770.082553, type 1 (Key), code 2 (1), value 1
Event: time 1318019770.082555, -------------- Report Sync -------=
-----
Post by Terry Lambert
Post by Dmitry Torokhov
1Event: time 1318019770.242541, type 4 (Misc), code 4 (ScanCode),=
value 7001e
Post by Terry Lambert
Post by Dmitry Torokhov
Event: time 1318019770.242552, type 1 (Key), code 2 (1), value 0
Event: time 1318019770.242555, -------------- Report Sync -------=
-----
Post by Terry Lambert
Post by Dmitry Torokhov
This is a shift-1.
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usb=
kbd.c
Post by Terry Lambert
Post by Dmitry Torokhov
index 0658173..d22ecdb 100644
--- a/drivers/hid/usbhid/usbkbd.c
+++ b/drivers/hid/usbhid/usbkbd.c
@@ -2,6 +2,10 @@
=A0 * =A0Copyright (c) 1999-2001 Vojtech Pavlik
=A0 *
=A0 * =A0USB HIDBP Keyboard support
+ *
+ * Device Class Definition for Human Interface Devices (HID) Ver=
sion 1.11
Post by Terry Lambert
Post by Dmitry Torokhov
+ * Section 8.3 describes the report formant.
+ * http://www.usb.org/developers/devclass_docs/HID1_11.pdf
=A0 */
=A0/*
@@ -97,6 +101,16 @@ static void usb_kbd_irq(struct urb *urb)
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto resubmit;
=A0 =A0 =A0 =A0 }
+ =A0 =A0 =A0 /* Convert in-band modifier keys to modifier bits *=
/
Post by Terry Lambert
Post by Dmitry Torokhov
+ =A0 =A0 =A0 for (i =3D 2; i < 8; i++) {
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (kbd->new[i] >=3D 0xE0 && kbd->n=
ew[i] <=3D 0xE7) {
Post by Terry Lambert
Post by Dmitry Torokhov
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 kbd->new[0] |=3D (1=
(kbd->new[i] - 0xE0));
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 kbd->new[i] =3D 0;
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
+ =A0 =A0 =A0 }
Wait, why are you using usbkbd? Unless you have very compelling rea=
son
Post by Terry Lambert
Post by Dmitry Torokhov
you should be using hid & hid-input.
I fixed it there because it was accessible and a way to test the fix.
I'm also going to have to do something similar for coreboot/u-boot to
allow the keyboard to be used in the boot loader, so it's not wasted
effort, and it was an OK proof of concept. =A0So there was a good
reason.
I'm getting the impression from the above that the file I should be
=A0 =A0drivers/hid/hid-input.c
Where are the modifier bits being decoded there? =A0Maybe I'm just no=
t
Post by Terry Lambert
seeing something in front of me...
<-- left shift key down -->
=A0 =A000 00 E1 00 00 00 00 00 =A0<- transaction
=A0 =A069 82 18 =A0<- input packet
=A0 =A048 00 00 E1 00 00 00 00 00 A8 45 <-- breakout : <--
=A0 =A0 =A0 =A0Keyboard LeftControl : 0b0
=A0 =A0 =A0 =A0Keyboard LeftShift : 0b0 =A0<-- ***WRONG ***
=A0 =A0 =A0 =A0Keyboard LeftAlt : 0b0
=A0 =A0 =A0 =A0Keyboard LeftGUI : 0b0
=A0 =A0 =A0 =A0Keyboard RightControl : 0b0
=A0 =A0 =A0 =A0Keyboard RightShiftl : 0b0
=A0 =A0 =A0 =A0Keyboard RightAlt : 0b0
=A0 =A0 =A0 =A0Keyboard RightGUI : 0b0
=A0 =A0 =A0 =A0Keyboard/Keypad Array : Keyboard LeftShift (225) <-- *=
**WRONG ***
Post by Terry Lambert
=A0 =A0-->
<-- 1 key down -->
=A0 =A000 00 E1 1E 00 00 00 00 =A0<- transaction
=A0 =A069 82 18 =A0<- input packet
=A0 =A0C3 00 00 E1 1E 00 00 00 00 A8 45 <-- breakout : <--
=A0 =A0 =A0 =A0Keyboard LeftControl : 0b0
=A0 =A0 =A0 =A0Keyboard LeftShift : 0b0 =A0<-- ***WRONG ***
=A0 =A0 =A0 =A0Keyboard LeftAlt : 0b0
=A0 =A0 =A0 =A0Keyboard LeftGUI : 0b0
=A0 =A0 =A0 =A0Keyboard RightControl : 0b0
=A0 =A0 =A0 =A0Keyboard RightShiftl : 0b0
=A0 =A0 =A0 =A0Keyboard RightAlt : 0b0
=A0 =A0 =A0 =A0Keyboard RightGUI : 0b0
=A0 =A0 =A0 =A0Keyboard/Keypad Array : Keyboard LeftShift (d225) =A0<=
-- *** WRONG ***
Post by Terry Lambert
=A0 =A0 =A0 =A0Keyboard/Keypad Array : Keyboard 1 and ! (d30)
=A0 =A0 =A0 =A0Keyboard/Keypad Array : 00
=A0 =A0 =A0 =A0Keyboard/Keypad Array : 00
=A0 =A0 =A0 =A0Keyboard/Keypad Array : 00
=A0 =A0 =A0 =A0Keyboard/Keypad Array : 00
=A0 =A0-->
<-- 1 key up -- >
=A0 =A000 00 E1 00 00 00 00 00 =A0<- transaction
=A0 =A069 82 18 =A0<- input packet
=A0 =A048 00 00 E1 00 00 00 00 00 A8 45 <-- breakout : <--
=A0 =A0 =A0 =A0Keyboard LeftControl : 0b0
=A0 =A0 =A0 =A0Keyboard LeftShift : 0b0
=A0 =A0 =A0 =A0Keyboard LeftAlt : 0b0
=A0 =A0 =A0 =A0Keyboard LeftGUI : 0b0
=A0 =A0 =A0 =A0Keyboard RightControl : 0b0
=A0 =A0 =A0 =A0Keyboard RightShiftl : 0b0
=A0 =A0 =A0 =A0Keyboard RightAlt : 0b0
=A0 =A0 =A0 =A0Keyboard RightGUI : 0b0
=A0 =A0 =A0 =A0Keyboard/Keypad Array : 00
=A0 =A0 =A0 =A0Keyboard/Keypad Array : 00
=A0 =A0 =A0 =A0Keyboard/Keypad Array : 00
=A0 =A0 =A0 =A0Keyboard/Keypad Array : 00
=A0 =A0 =A0 =A0Keyboard/Keypad Array : 00
=A0 =A0 =A0 =A0Keyboard/Keypad Array : 00
=A0 =A0-->
<-- left shift key up -->
=A0 =A000 00 00 00 00 00 00 00 =A0<- transaction
=A0 =A069 82 18 =A0<- input packet
=A0 =A048 00 00 00 00 00 00 00 00 BF F4 <-- breakout : <--
=A0 =A0 =A0 =A0Keyboard LeftControl : 0b0
=A0 =A0 =A0 =A0Keyboard LeftShift : 0b0 =A0<-- ***WRONG ***
=A0 =A0 =A0 =A0Keyboard LeftAlt : 0b0
=A0 =A0 =A0 =A0Keyboard LeftGUI : 0b0
=A0 =A0 =A0 =A0Keyboard RightControl : 0b0
=A0 =A0 =A0 =A0Keyboard RightShiftl : 0b0
=A0 =A0 =A0 =A0Keyboard RightAlt : 0b0
=A0 =A0 =A0 =A0Keyboard RightGUI : 0b0
=A0 =A0 =A0 =A0Keyboard/Keypad Array : Keyboard LeftShift (225) <-- *=
**WRONG ***
Post by Terry Lambert
=A0 =A0-->
I just need to know where in the code to stomp the report into
correctness. Should make a bunch of people happy. 8-)
Thanks,
-- Terry
Post by Dmitry Torokhov
Thanks.
--
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-input" =
in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Dmitry Torokhov
2011-10-08 00:25:24 UTC
Permalink
Post by Terry Lambert
Thanks for replying, Dmitry...
=20
I guess I need to clarify a point or two.
=20
On Fri, Oct 7, 2011 at 3:07 PM, Dmitry Torokhov
Post by Dmitry Torokhov
Hi Terry,
I have a USB keyboard that needs a workaround. =A0I know what the
workaround is, but not where to plumb it in.
This is apparently an issue with a number of keyboards from a num=
ber
Post by Terry Lambert
Post by Dmitry Torokhov
of vendors, and Mac OS X and Windows both work around it. =A0It i=
mpacts
Post by Terry Lambert
Post by Dmitry Torokhov
all Linux desktops, Android, and Chrome OS for a number of popula=
r
Post by Terry Lambert
Post by Dmitry Torokhov
folding keyboards, as well as other keyboards.
I'm perfectly able to write the workaround, and have done so usin=
g the
Post by Terry Lambert
Post by Dmitry Torokhov
boot protocol, but now I want to fix the issue in the default sta=
ck
Post by Terry Lambert
Post by Dmitry Torokhov
used for the console.
I don't care about the UHCI/EHCI plumbing, or anything up to hidd=
ev;
Post by Terry Lambert
Post by Dmitry Torokhov
but from there it gets murky as to how an event in the raw driver=
ends
Post by Terry Lambert
Post by Dmitry Torokhov
up getting turned into a keyboard key. =A0It appears to be lost i=
n
Post by Terry Lambert
Post by Dmitry Torokhov
callbacks I'm having a hard time tracing through.
I've read three books on the Linux USB system, two of them very o=
ut of
Post by Terry Lambert
Post by Dmitry Torokhov
date, and they're all written from the perspective of "So, you wa=
nt to
Post by Terry Lambert
Post by Dmitry Torokhov
write a device driver", rather than the perspective of "This book
documents the plumbing between the driver and userspace and how t=
o
Post by Terry Lambert
Post by Dmitry Torokhov
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
Post by Terry Lambert
Post by Dmitry Torokhov
input core as separate input devices. The legacy console registers =
a
Post by Terry Lambert
Post by Dmitry Torokhov
separate input handler (see drivers/tty/vt/keyboard.c) that binds t=
o all
Post by Terry Lambert
Post by Dmitry Torokhov
keyboard-like devices, listens to input events and converts them to
keystrokes and sends them to tty.
=20
My question is "who processes USB report packets from a USB keyboard
into EV_KEY events?"
drivers/hid/hid-input.c
Post by Terry Lambert
=20
I understand that there's a separate evdev handler that publishes raw
events as /dev/input/eventX. It's handling the events from somewhere=
,
Post by Terry Lambert
but it's not clear to me how a hidraw1 event turns into a console
input event.
=20
Somewhere someone is translating a USB 1.11 section 8.3 report into a=
n
Post by Terry Lambert
EV_KEY, and I need to do the modifier magic to alter the contents of
the reports before it gets to whoever that is.
You seem to be saying hid-input.c ... but I'm not seeing the modifier
bits being processed out of the report?
I do not believe we pay attention to these modifier bits as we keep
track of keys pressed ourselves (and keys could be remapped anyway).

Anyway, it looks like the devicde should not be reportign LeftShift
together with 1 in the 2nd report as it makes hhid-input think that
(accounding to the rules of 8.3) it is being released.

I wonder if the fix is to not replrt released when we get newly pressed
keys in the report.

Thanks.

--=20
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-input" =
in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Terry Lambert
2011-10-08 02:56:54 UTC
Permalink
You make a very good point on the key remapping.

=2E..

Are we sure that there isn't a field in the keyboard information in
the USB that reports the keyboard does this?

The only other alternative seems to be to quirk the keyboard as
reporting keys down when they are down, up when they are up, and
generating pseudo events for "keycode not present in report".

I guess I'm willing to write a "hosed keyboard driver" driver if
necessary. This apparently effects about 5-10% of keyboards,
predominantly laptops with internal USB (some dell inspiron, some
samsung), and the folding keyboards people like to use with android
tablets.

I'm willing to take any advice about where I can get a handle on all
the keys in a given report to implement a general quirk on this
hardware.

If necessary, we can always write a driver, I suppose, if you can
point me at an example?

Thanks,
-- Terry



On Fri, Oct 7, 2011 at 5:25 PM, Dmitry Torokhov
Post by Terry Lambert
Post by Terry Lambert
Thanks for replying, Dmitry...
I guess I need to clarify a point or two.
On Fri, Oct 7, 2011 at 3:07 PM, Dmitry Torokhov
Post by Dmitry Torokhov
Hi Terry,
I have a USB keyboard that needs a workaround. =A0I know what t=
he
Post by Terry Lambert
Post by Terry Lambert
Post by Dmitry Torokhov
workaround is, but not where to plumb it in.
This is apparently an issue with a number of keyboards from a n=
umber
Post by Terry Lambert
Post by Terry Lambert
Post by Dmitry Torokhov
of vendors, and Mac OS X and Windows both work around it. =A0It=
impacts
Post by Terry Lambert
Post by Terry Lambert
Post by Dmitry Torokhov
all Linux desktops, Android, and Chrome OS for a number of popu=
lar
Post by Terry Lambert
Post by Terry Lambert
Post by Dmitry Torokhov
folding keyboards, as well as other keyboards.
I'm perfectly able to write the workaround, and have done so us=
ing the
Post by Terry Lambert
Post by Terry Lambert
Post by Dmitry Torokhov
boot protocol, but now I want to fix the issue in the default s=
tack
Post by Terry Lambert
Post by Terry Lambert
Post by Dmitry Torokhov
used for the console.
I don't care about the UHCI/EHCI plumbing, or anything up to hi=
ddev;
Post by Terry Lambert
Post by Terry Lambert
Post by Dmitry Torokhov
but from there it gets murky as to how an event in the raw driv=
er ends
Post by Terry Lambert
Post by Terry Lambert
Post by Dmitry Torokhov
up getting turned into a keyboard key. =A0It appears to be lost=
in
Post by Terry Lambert
Post by Terry Lambert
Post by Dmitry Torokhov
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
Post by Terry Lambert
Post by Terry Lambert
Post by Dmitry Torokhov
date, and they're all written from the perspective of "So, you =
want to
Post by Terry Lambert
Post by Terry Lambert
Post by Dmitry Torokhov
write a device driver", rather than the perspective of "This bo=
ok
Post by Terry Lambert
Post by Terry Lambert
Post by Dmitry Torokhov
documents the plumbing between the driver and userspace and how=
to
Post by Terry Lambert
Post by Terry Lambert
Post by Dmitry Torokhov
figure it out".
So the question is: how are things plumbed between hiddev and t=
he
Post by Terry Lambert
Post by Terry Lambert
Post by Dmitry Torokhov
console driver,
They aren't. Or maybe we are talking about different "hiddev"s. T=
he
Post by Terry Lambert
Post by Terry Lambert
Post by Dmitry Torokhov
generic HID driver binds devices to hid-input which registers the=
m with
Post by Terry Lambert
Post by Terry Lambert
Post by Dmitry Torokhov
input core as separate input devices. The legacy console register=
s a
Post by Terry Lambert
Post by Terry Lambert
Post by Dmitry Torokhov
separate input handler (see drivers/tty/vt/keyboard.c) that binds=
to all
Post by Terry Lambert
Post by Terry Lambert
Post by Dmitry Torokhov
keyboard-like devices, listens to input events and converts them =
to
Post by Terry Lambert
Post by Terry Lambert
Post by Dmitry Torokhov
keystrokes and sends them to tty.
My question is "who processes USB report packets from a USB keyboar=
d
Post by Terry Lambert
Post by Terry Lambert
into EV_KEY events?"
drivers/hid/hid-input.c
Post by Terry Lambert
I understand that there's a separate evdev handler that publishes r=
aw
Post by Terry Lambert
Post by Terry Lambert
events as /dev/input/eventX. =A0It's handling the events from somew=
here,
Post by Terry Lambert
Post by Terry Lambert
but it's not clear to me how a hidraw1 event turns into a console
input event.
Somewhere someone is translating a USB 1.11 section 8.3 report into=
an
Post by Terry Lambert
Post by Terry Lambert
EV_KEY, and I need to do the modifier magic to alter the contents o=
f
Post by Terry Lambert
Post by Terry Lambert
the reports before it gets to whoever that is.
You seem to be saying hid-input.c ... but I'm not seeing the modifi=
er
Post by Terry Lambert
Post by Terry Lambert
bits being processed out of the report?
I do not believe we pay attention to these modifier bits as we keep
track of keys pressed ourselves (and keys could be remapped anyway).
Anyway, it looks like the devicde should not be reportign LeftShift
together with 1 in the 2nd report as it makes hhid-input think that
(accounding to the rules of 8.3) it is being released.
I wonder if the fix is to not replrt released when we get newly press=
ed
Post by Terry Lambert
keys in the report.
Thanks.
--
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-input" =
in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Jiri Kosina
2011-10-08 06:19:01 UTC
Permalink
Post by Terry Lambert
You make a very good point on the key remapping.
...
Are we sure that there isn't a field in the keyboard information in
the USB that reports the keyboard does this?
The only other alternative seems to be to quirk the keyboard as
reporting keys down when they are down, up when they are up, and
generating pseudo events for "keycode not present in report".
I guess I'm willing to write a "hosed keyboard driver" driver if
necessary. This apparently effects about 5-10% of keyboards,
predominantly laptops with internal USB (some dell inspiron, some
samsung), and the folding keyboards people like to use with android
tablets.
I'm willing to take any advice about where I can get a handle on all
the keys in a given report to implement a general quirk on this
hardware.
If necessary, we can always write a driver, I suppose, if you can
point me at an example?
So if I understood the situation correctly (Dmitry, thanks for adding me
to CC), what you want to do is to write a very simple driver that has a
hook called every time HID event occurs on the keyboard, and have it do
modifier magic before it's reported to the input subsystem.

There are various existing drivers which are doing exactly this that can
serve as an example. The simplest one probably is hid-microsoft, the more
sophisticated one is hid-apple. These two are registering ->event
callback, so they are obtaining already pre-parsed information.

If you'd need to receive information that hasn't been parsed yet by the
HID parser, you'd rather register ->raw_event callback. There are various
drivers that to this as well -- hid-zydacron being a really simple one and
hid-magicmouse being a sophisticated one.

I believe those drivers should serve as a perfect example for what you
need.
--
Jiri Kosina
SUSE Labs
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Terry Lambert
2011-10-09 00:31:00 UTC
Permalink
Thanks!

Working on it now...

-- Terry
Post by Terry Lambert
You make a very good point on the key remapping.
...
Are we sure that there isn't a field in the keyboard information in
the USB that reports the keyboard does this?
The only other alternative seems to be to quirk the keyboard as
reporting keys down when they are down, up when they are up, and
generating pseudo events for "keycode not present in report".
I guess I'm willing to write a "hosed keyboard driver" driver if
necessary. =A0This apparently effects about 5-10% of keyboards,
predominantly laptops with internal USB (some dell inspiron, some
samsung), and the folding keyboards people like to use with android
tablets.
I'm willing to take any advice about where I can get a handle on all
the keys in a given report to implement a general quirk on this
hardware.
If necessary, we can always write a driver, I suppose, if you can
point me at an example?
So if I understood the situation correctly (Dmitry, thanks for adding=
me
to CC), what you want to do is to write a very simple driver that has=
a
hook called every time HID event occurs on the keyboard, and have it =
do
modifier magic before it's reported to the input subsystem.
There are various existing drivers which are doing exactly this that =
can
serve as an example. The simplest one probably is hid-microsoft, the =
more
sophisticated one is hid-apple. These two are registering ->event
callback, so they are obtaining already pre-parsed information.
If you'd need to receive information that hasn't been parsed yet by t=
he
HID parser, you'd rather register ->raw_event callback. There are var=
ious
drivers that to this as well -- hid-zydacron being a really simple on=
e and
hid-magicmouse being a sophisticated one.
I believe those drivers should serve as a perfect example for what yo=
u
need.
--
Jiri Kosina
SUSE Labs
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Loading...