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

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

 



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
<dmitry.torokhov@xxxxxxxxx> wrote:
>
> 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.

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?


> 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...
>
> > 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.

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)  <-- *** WRONG ***
        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

> Thanks.
>
> --
> Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-input" 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 Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux