usb/181425: USB keyboard with full N-key rollover not working

Andrey Zholos aaz at q-fu.com
Tue Aug 20 11:10:00 UTC 2013


>Number:         181425
>Category:       usb
>Synopsis:       USB keyboard with full N-key rollover not working
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-usb
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Aug 20 11:10:00 UTC 2013
>Closed-Date:
>Last-Modified:
>Originator:     Andrey Zholos
>Release:        FreeBSD 10.0-CURRENT #0 r254515
>Organization:
>Environment:
FreeBSD ukbd-test 10.0-CURRENT FreeBSD 10.0-CURRENT #0 r254515: Mon Aug 19 15:58:40 EEST 2013     root at ukbd-test:/usr/obj/usr/src/sys/GENERIC  amd64
>Description:
The keyboard I am using is a Max Keyboard Nighthawk X9. It features
full N-key rollover, which is supposed to allow pressing all keys at
once, so it reports all keys as a bitmap, rather than the usual 6-byte
array of keycodes. This confuses the ukbd driver.

The relevant part of dmesg with hw.usb.ukbd.debug=1:

    ugen0.4: <EST> at usbus0
    ukbd0: <EST Gaming keyboard, class 0/0, rev 2.00/0.97, addr 3> on usbus0
    ukbd_attach: Parsing HID descriptor of 65 bytes
    ukbd_parse_hid: Found left control
    ukbd_parse_hid: Found right control
    ukbd_parse_hid: Found left shift
    ukbd_parse_hid: Found right shift
    ukbd_parse_hid: Found left alt
    ukbd_parse_hid: Found right alt
    ukbd_parse_hid: Found left GUI
    ukbd_parse_hid: Found right GUI
    ukbd_parse_hid: Found keyboard events
    ukbd_parse_hid: Found keyboard numlock
    ukbd_parse_hid: Found keyboard capslock
    ukbd_parse_hid: Found keyboard scrolllock
    ukbd_set_leds: leds=0x00
    ukbd_set_leds: leds=0x00
    kbd2 at ukbd0
    ukbd_set_leds_callback: len=1, id=0
    ukbd1: <EST Gaming keyboard, class 0/0, rev 2.00/0.97, addr 3> on usbus0
    ukbd_intr_callback: actlen=8 bytes
    ukbd_intr_callback: modifiers = 0x0000
    ukbd_attach: Parsing HID descriptor of 37 bytes
    ukbd_parse_hid: Found left control
    ukbd_parse_hid: Found right control
    ukbd_parse_hid: Found left shift
    ukbd_parse_hid: Found right shift
    ukbd_parse_hid: Found left alt
    ukbd_parse_hid: Found right alt
    ukbd_parse_hid: Found left GUI
    ukbd_parse_hid: Found right GUI
    ukbd_parse_hid: Found keyboard events
    ukbd_set_leds: leds=0x00
    ukbd_set_leds: leds=0x00
    kbd3 at ukbd1

Most keys don't work and show this:

    ukbd_intr_callback: actlen=15 bytes
    ukbd_intr_callback: modifiers = 0x0000
    ukbd_intr_callback: actlen=15 bytes
    ukbd_intr_callback: modifiers = 0x0000

Modifier keys (e.g. Ctrl) appear to work:

    ukbd_intr_callback: actlen=15 bytes
    ukbd_intr_callback: modifiers = 0x0001
    ukbd_put_key: 0xe0 (224) pressed
    ukbd_intr_callback: actlen=15 bytes
    ukbd_intr_callback: modifiers = 0x0000
    ukbd_put_key: 0x4e0 (1248) released

Multimedia keys don't do anything at all.

Special profile keys (e.g. Fn+PF1) also appear to work:

    ukbd_intr_callback: actlen=8 bytes
    ukbd_intr_callback: modifiers = 0x0000
    ukbd_intr_callback: [0] = 0xf1
    ukbd_put_key: 0xf1 (241) pressed
    ukbd_intr_callback: actlen=8 bytes
    ukbd_intr_callback: modifiers = 0x0000
    ukbd_put_key: 0x4f1 (1265) released
    ukbd_intr_callback: actlen=8 bytes
    ukbd_intr_callback: modifiers = 0x0000

There are three HID descriptors:

    # uhidd -D /dev/ugen0.4
    ugen0.4[0]-> Report descriptor dump:
            USAGE PAGE Generic Desktop(0x1)
            USAGE Keyboard(0x6)[Generic Desktop(0x1)]
            COLLECTION Application(1)
              USAGE PAGE Keyboard(0x7)
              USAGE MINIMUM Keyboard LeftControl(224)
              USAGE MAXIMUM Keyboard Right GUI(231)
              LOGICAL MINIMUM 0
              LOGICAL MAXIMUM 1
              REPORT SIZE 1
              REPORT COUNT 8
              INPUT ( Data Variable Absolute ) (2)
              REPORT SIZE 8
              REPORT COUNT 1
              INPUT ( Const Array Absolute ) (1)
              USAGE PAGE Keyboard(0x7)
              USAGE MINIMUM Reserved (no event indicated)(0)
              USAGE MAXIMUM Unknown Usage(255)
              LOGICAL MINIMUM 0
              LOGICAL MAXIMUM 255
              REPORT SIZE 8
              REPORT COUNT 6
              INPUT ( Data Array Absolute ) (0)
              USAGE PAGE LEDs(0x8)
              USAGE MINIMUM Num Lock(1)
              USAGE MAXIMUM Scroll Lock(3)
              LOGICAL MAXIMUM 1
              REPORT SIZE 1
              REPORT COUNT 3
              OUTPUT ( Data Variable Absolute ) (2)
              REPORT COUNT 5
              OUTPUT ( Const Array Absolute ) (1)
            END COLLECTION
    ugen0.4[0]-> Kernel driver is active
    ugen0.4[0]-> Abort attach since kernel driver is active
    ugen0.4[0]-> Please try running uhidd with option '-u' to detach the kernel drivers
    ugen0.4[1]-> Report descriptor dump:
            USAGE PAGE Consumer(0xc)
            USAGE Consumer Control(0x1)[Consumer(0xc)]
            COLLECTION Application(1)
              USAGE PAGE Consumer(0xc)
              USAGE MINIMUM Unassigned(0)
              USAGE MAXIMUM Unknown Usage(4095)
              LOGICAL MINIMUM 0
              LOGICAL MAXIMUM 4095
              REPORT SIZE 16
              REPORT COUNT 2
              INPUT ( Data Array Absolute ) (0)
            END COLLECTION
    ugen0.4[1]-> Kernel driver is active
    ugen0.4[1]-> Abort attach since kernel driver is active
    ugen0.4[1]-> Please try running uhidd with option '-u' to detach the kernel drivers
    ugen0.4[2]-> Report descriptor dump:
            USAGE PAGE Generic Desktop(0x1)
            USAGE Keyboard(0x6)[Generic Desktop(0x1)]
            COLLECTION Application(1)
              USAGE PAGE Keyboard(0x7)
              USAGE MINIMUM Keyboard LeftControl(224)
              USAGE MAXIMUM Keyboard Right GUI(231)
              LOGICAL MINIMUM 0
              LOGICAL MAXIMUM 1
              REPORT SIZE 1
              REPORT COUNT 8
              INPUT ( Data Variable Absolute ) (2)
              USAGE MINIMUM Reserved (no event indicated)(0)
              USAGE MAXIMUM Keyboard F20(111)
              LOGICAL MINIMUM 0
              LOGICAL MAXIMUM 1
              REPORT SIZE 1
              REPORT COUNT 112
              INPUT ( Data Variable Absolute ) (2)
            END COLLECTION
    ugen0.4[2]-> Kernel driver is active
    ugen0.4[2]-> Abort attach since kernel driver is active
    ugen0.4[2]-> Please try running uhidd with option '-u' to detach the kernel drivers

Note the 112-count bitmap in descriptor number 2. This is what is in
the 15-byte report used for most keys. There is a 6-byte array in
descriptor number 0, but that is only used to report the special
profile keys. Descriptor number 1 is used for multimedia keys.

>How-To-Repeat:
Plug in a Max Keyboard Nighthawk X9 keyboard. It works in BIOS and in
the FreeBSD boot loader menu, but stops working after boot.
>Fix:
The keyboard works fine in boot protocol. Running this

    # usbconfig -d 0.4 add_quirk UQ_KBD_BOOTPROTO

and unplugging and plugging the keyboard back in fixes it, as does
adding the quirk for vendor 0x0665 product 0x6000 in usb_quirk.c.

However, I think it's better to detect this type of HID descriptor,
rather than to enumerate all the products that have it, so I propose
the attached patch.

Without UKBD_FLAG_EVENTS the keyboard gets forced into boot protocol in
ukbd_attach(). I have tested this and it works. Ordinary USB keyboard
should continue working in normal protocol as before, but I haven't
tested this.

I suspect this patch also obviates the need for the Corsair Vengeance
K60 keyboard quirk in usb_quirk.c, because that keyboard has 20-key
rollover and so probably the same sort of descriptor, but I don't have
one to test.

Ideally I would like to get this keyboard to work in normal protocol
with full rollover for perfectionist reasons, but I guess that would
require too many changes to ukbd.c and introduce overhead for the
majority of keyboards.


Patch attached with submission follows:

--- sys/dev/usb/input/ukbd.c	(revision 254515)
+++ sys/dev/usb/input/ukbd.c	(working copy)
@@ -1130,8 +1130,12 @@
 	    HID_USAGE2(HUP_KEYBOARD, 0x00),
 	    hid_input, 0, &sc->sc_loc_events, &flags,
 	    &sc->sc_id_events)) {
-		sc->sc_flags |= UKBD_FLAG_EVENTS;
-		DPRINTFN(1, "Found keyboard events\n");
+		if (flags & HIO_VARIABLE)
+			DPRINTFN(1, "Ignoring key bitmap\n");
+		else {
+			sc->sc_flags |= UKBD_FLAG_EVENTS;
+			DPRINTFN(1, "Found keyboard events\n");
+		}
 	}
 
 	/* figure out leds on keyboard */


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-usb mailing list