Hacker News new | past | comments | ask | show | jobs | submit login
Myths about USB NKRO and how USB HID works (devever.net)
118 points by panic on April 25, 2020 | hide | past | favorite | 59 comments



> Yes, this means you could theoretically make an analog keyboard which reports the level of key depression.

There is at least one company making analog keyboards, mainly for gaming: https://wooting.io/


The Realforce 108UH-ANLG [1] can also do that and can even emulate the analog sticks and buttons used on gaming controllers. Here's a demo video of one being used as a piano [2]. You can tell that harder keypresses result in louder notes. I don't think it's been released outside of Japan yet but they have some keyboards with customizable actuation points using the same Topre switches [3].

[1] https://www.realforce.co.jp/products/108UH-ANLG_AFAX01/index...

[2] https://www.youtube.com/watch?v=mhCSIy-Qt0M

[3] https://www.realforce.co.jp/en/products/R2A-US4G-BK/index.ht...


The Steelseries Apex Pro has keys that can detect depth, but they too use it for actuation points. They keys are omnipoint.

I really (really) like my topre realforce rgb although the apex pro is very close in terms of solid feel, and has much more interesting electronics.


First thing I thought of when I read that line was a keyboard with no shift key. If you want capital letters you really have to MASH THOSE KEYS TO MAKE YOUR POINT!


AFAIK most USB keyboards with nkro implement it by emulating multiple USB keyboards, which I guess is also within the hid spec? The manufacturers probably figured that approach was more reliable than using one hid device with a custom reporting format.


It's cheaper to reuse the same USB 1.0 controller chip than update. That's it, the dirty secret.

Some keyboards also do that to support OSes that have broken HID drivers, like Mac.


No, and it makes no sense. There are no fixed function USB HID controller chips. They are all microcontrollers with USB interface. Makes no difference from chip point of view if it reports being basic HID profile or a custom one. Besides you can even bitbang being 10 hid devices on a good old Arduino.


A cent here and there on manufacturing several hundred thousand units quickly adds up. And that's just the MCU used.

The cost of replacing the MCU with something that can run USB1.1 instead of 1.0, cost of programming, cost of dealing with broken cases that don't support HID properly (for example BIOSes that don't send "boot proto only" command, or every Mac) quickly increase the total cost. And the margins are thin.

And then there's the fact that even people who should know better often believe myths about USB being unable to report more than 6 keys - even if they are keyboard vendors who should know better and are making a high-enough margin to use better controller.


>cent here and there

someone counting cents will not use several microcontrollers + separate usb hub chip, where did you get that idea from anyway?

>cost of replacing the MCU with something that can run USB1.1 instead of 1.0

http://www.os2museum.com/wp/how-fast-again/ there is no hardware difference between 1.0 and 1.1.


What I found was that in Low Speed mode, the maximum packet size made it impractical to use anything but the Boot Protocol.

As for counting cents - for majority of keyboards made, you'll get as little work done on the keyboard controller as possible. If they add a separate USB chip, it's usually logically separate from the keyboard anyway.

When you reach the more fancy keyboards, you deal with another problem.

Namely, what to do with all the broken software involved. Your priority for reducing costs is removing support calls, angry gamers calling when they can't change their overclocking parameters in BIOS, Macintosh users complaining the keyboard doesn't work at all, corporate/OEM clients returning keyboards because it is not possible to input password to McBuggy Disk Encryption and Employee Spyware v6.66 when the computer starts.

Those limit your options when the budget for your fancy keyboard would provide for better microcontroller.


Yes, but for most keyboard makers, they come preflashed, and are indistinguishable from dumb asics


> It's cheaper to reuse the same USB 1.0 controller chip than update. That's it, the dirty secret.

How can this be for high end gaming keyboards that retail for $150-$200 or more?


The only thing "high end" in there are the switches, and even that not necessarily.


Believe it or not, there is a very small number of keyboards that use custom USB 3.0 controllers purely for isosynchronous mode, to get "PS/2 port interrupt"-like behavior.

However, if you have a modern USB 2.0 "gaming keyboard controller" polling at 1000ms, who cares. Job done, go home.


Do you mean Endpoint Ready (ERDY)? That is only available for non-isochronous endpoints.


No, I think they're just constantly streaming out updates over a custom isochronous endpoint so the driver doesn't have to go out and request it at all like you do even with ERDY.


Wouldnt that swamp CPU with interrupts?


I mean, as much as a USB microphone does. That'd be isochronous too, and about the same bitrate and latency.


That would be awful for a keyboard. With sound, either the CPU wakes up to process sound very frequently or it processed sound in big chunks with high latency. Neither choice is reasonable for a keyboard.


If you're the kind of person that gets that keyboard, you don't really care about power consumption on your CPU. Handling it as it's streamed in really isn't that big of a deal.

It's not even like sound where you'd be doing a bunch of DSP on it right after.


More margins make for more profit. It's always good to reduce costs regardless of how much you charge.


There's some other factor surely. We're talking pennies on a BoM, and I'm certain some high end keyboard manufacturer would love to tout a better usb controller, etc.


Consider the support costs involved in dealing with things like broken BIOSes that don't send "switch to boot protocol" command and similar.

Cost of electronics is not everything.


> Some keyboards also do that to support OSes that have broken HID drivers, like Mac.

What's broken on macOS?


Don't remember full details, but essentially something was broken in handling of HID reports for keyboards combined with how input events were handled in upper layers.

Resulted in some keyboards having special cases for dealing with "NKRO" on Mac.


On top of that, its usually two: often, the WASD+QE cluster, the most pressed buttons in gaming, with everything else on the other.


> the WASD+QE cluster, the most pressed buttons in gaming

It's been a long time since I've gamed, but when I did I always used ESDF (which I picked up from Tribes). It seems kinda silly to hyper-optimize solely to a default like WSAD.


In modern competitive gaming, I believe it’s fairly rare to remap away from WASD. Other keys get remapped, but not those ones. Since these expensive keyboards are catering to the (wannabe-)pro-gamer crowd, they tend to focus on that cluster.


Yeah, as I understand it there were some fairly nasty BIOS compatibility issues with keyboards that try and do full spec-compliant NKRO, and some older OSes might have had issues too. The specification says that software which requires the special boot protocol need to request it, but in practice it often doesn't, so most keyboards only support that format and are limited to 6-key rollover plus modifiers. A few hobbyist keyboard designers have tried doing this the proper way and quickly regretted it once they sold enough keyboards to be exposed to real-world systems and their behaviour.


Yeah, I implemented it too. Many years ago, I didn't read spec or really think about custom report desc. Solution to pretend to be multiple keyboards seemed to be obvious ))


Having multiple report formats is also obvious, but generally so from reading the spec, which addresses the subject. (-:


The cheap Chinese keyboard I have over here emulates NKRO by simply reporting 5 different keyboards. Although the idea makes me cringe from a engineering pov I've to admit it works really well.


I wonder if USB HID compliant keyboard can report their key map (like QWERTY vs AZERTY)? If yes is there some OS taking advantage of it and how?

In 2020 keyboard mapping is still a mess IMHO but may be I'm missing something :)


You're missing the fact that keyboards do not have key maps to report. The wire protocol and the device do not remap keys. It's all done in software on the host.

* https://news.ycombinator.com/item?id=22207431


I think the GP's idea is that a keyboard could report to the host how its keys are labeled so that the host could automatically select the correct keymap. This is indeed a very cool idea, but would certainly be a big effort to get implemented across all platforms.

This would be somewhat similar the more boutique input devices which are configurable in hardware.


That is not the keyboard map. It's the engraving, which has zero effect on the keyboard, neither electrical nor mechanical. Keyboards can be re-labelled with little bits of paper and sticky tape or by swapping keytops, and that does nothing. There is no keyboard map here.


Of course keyboards can be relabeled. But they usually aren't. If, hypothetically, keyboards came with knowledge of their original labeling, that would be meaningful information. If computers used it to set a default key layout, that would make for a better default if the goal is to make key behavior match the labeling. It would fail to match the labeling if you changed the labeling, but it would still be accurate much more often than the current default.

That said, I question whether most people actually want key behavior to match the labeling. I think any touch typist would rather use their preferred layout regardless of labeling.


As a recovering Dvorak user, I would very much like the match-the-legends behavior, because for quite a long time I used a keymap which was not the default. At one job I had an Advantage2 that I carried around with me because the keys were internally remapped (when you pressed a key it reported the scancode for that letter on QWERTY) because of how time consuming it is to add a keyboard layout in most operating systems. Unfortunately that kind of internal remapping is mostly only found in some very expensive keyboards. There's at least one vendor that sells a USB dongle that does the same remapping to a pass-through USB keyboard for the same reason.

This problem would be infrequently encountered in the US (mostly just Dvorak and Colemak addicts) but is a lot more common in Europe due to AZERTY.


Yeah, but for 99% of keyboards the legends were put there by the manufacturer who could also burn into the controller firmware what scheme of legends was used. This way the OS could autodetect whether the keyboard was e.g. QWERTY or AZERTY without having to do a user-involved discovery process like OS X or assuming keyboard matches locality like Windows.


One could imagine that the keytops were identifiable by the keyboard, so that it could actually detect that you swapped two keys and adjust what it sends to the host based on this.


Thanks for the link!

But that does not tell me why there is no standard way for a key map / layout to be transmitted by the hardware to the software.

When the vendor makes the keyboard, he's the one choosing both the physical layout (A vs Q) and the USB microcontroller behaviour, so nothing prevents transmission of physical layout in some way to the software.

In 2020 we do not have to tell the software what the screen resolution is, what the drive size is, but we still have to manually tell software AZERTY vs QWERTY ...


[flagged]


You aren’t answering the question. Sure, keyboards don’t currently report a mapping from button to label, and software doesn’t expect such a report. This doesn’t mean it has to be this way.

A keyboard could tell the host “here is how I think I’m labeled”, and the host could make use of this information.


The trick to get not-exactly-standard BIOS and OS working (with NKRO for the OS) is not at all obvious ... I first read about it in https://static.wongcornall.com/ibm-capsense-usb-web/ibm-caps...


Pretty clever trick using the padding to get the boot info there for compatibility.


If I remember correctly, the good old PS/2 keyboards used to send "key down" and "key up" events - so no limit on number of simultaneous keypresses. Why was this not reflected in USB HID?


My guess is that the problem with sending events is that if you miss one you're in trouble (in this case it's especially bad if you miss/lose the "key up" message). Given the potential complexity of USB topologies making the protocol stateful might have caused more problem than it would've solved.

Besides is there any use for NKRO besides being a meme feature for overpriced keyboards? The only use case I can think of is if you play two player games on the same keyboard but doesn't seem very common these days (and you can probably buy a decent gamepad for the price of a NKRO keyboard).


Stenography!

When stroking a chord you can have 6+ keys held down easily. I design and write firmware for QMK powered writers/ergonomic keyboards, and NKRO is absolutely vital if you don't want to resort to serial devices [1]. Plover uses this technique to allow for use of gaming keyboards as a low cost stenographic writer powered by FOSS.

[1] https://www.gboards.ca/


Would it be that expensive to put ~4K of RAM in the keyboard’s microcontroller to act as an event queue? Write keydowns/keyups into the buffer; then push (or respond to a poll with) the complete contents of the buffer as a single USB packet; and flush the buffer on ACK. (I presume USB does ACKs?) 4K would be more than enough to buffer all possible key events a pair of human hands could create in a reasonable polling interval (~16ms, i.e. 1 frame for a 60Hz game.)

Add a clock chip to the HID device as well, and you could even get finer event-reporting granularity than the OS cares to poll for (i.e. the buffer delivered at (Polling Interval x N)ms, would contain events timestamped for (Interval x (N-1)) ms, (Interval x (N-1) + 1)ms, etc.) The timestamps could just be relative to the beginning of the interval, so they wouldn’t need to take up that many bits at all.


> then push (or respond to a poll with) the complete contents of the buffer as a single USB packet; and flush the buffer on ACK

Two issues. Unless you use USB 2.0 high speed, USB "packets" (transactions) are small[1]. For low speed they can have 8 bytes of data, full speed 64 bytes. USB 2.0 HS is a lot more costly of course.

Secondly, keycodes that are sent in the same report have no defined order[2]. Thus if two keys were not present in previous report and are present in current report, the order in which those two keys are pressed are indeterminate to the OS.

So that would not be very helpful I think.

[1]: http://www.usbmadesimple.co.uk/ums_3.htm (Interrupt Transfers)

[2]: https://www.usb.org/document-library/device-class-definition... (Appendix C)


Some games run their physics engines at a higher framerate than 60, but also any added latency is not going to be acceptable.


While I can't reproduce it at-will I've definitely had occasional input problems in competitive shooter games with 6KRO + 125Hz. A depress would be processed "too late" to accidentally fall into the next window and affect movement then (e.g.: jump in wrong direction).

Yes, the key combination probably doesn't go over 6 keys at once and I don't always have ~8-16ms presses but switching over to NKRO + 1000Hz (which are coupled on QMK) would stop this from happening.


PS/2 key reports are initiated by the keyboard, whereas USB HID reports are polled. Since (as the article describes) they wanted a fixed-size report for the ‘boot protocol’, the best they could do is report the current state, rather than a log of events since the previous poll. (Well, I guess you could drop the oldest paired non-modifier events, but that would be more complicated. HID just does a bunch of stuff that seems weird now to minimize device-side resources — e.g. HID descriptors aren't a structure defining a report, they're a bytecode for building a structure defining a report on the host.)


It was. HID is a depressingly complicated specification though, and split the keyboard protocol in half: there is a "boot" protocol, which is designed to be simpler for firmware to implement, and a full event protocol. The latter looks exactly like you'd expect such a thing to look like, with arbitrary up/down events reportable independently for as many keys as you want to declare.

But the boot protocol has a six key limit, so that's what many devices support.


> with arbitrary up/down events reportable independently for as many keys as you want to declare

In "Appendix C - Keyboard Implementation" in the "USB Device Class Definition" document[1], it says:

"The following are the design requirements for USB keyboards:

- Non-modifier keys must be reported in Input (Array, Absolute) items. Reports must contain a list of keys currently pressed and not make/break codes (relative data)."

Of course you could make some HID device which has relative key events, but would the OS then recognize it as a keyboard?

[1]: https://www.usb.org/document-library/device-class-definition...


Because the PS/2 keyboard interface is a mess.

The "good old" PC/XT keyboards worked that way. By the time of the PS/2, there were two different ways to signal break scancodes, three scancode sets only some of which were supported by any given keyboard, a mapping system to make one set of new scancodes look like the PC/XT, fake modifiers so that the system still thought that pause was Control+Numlock, and keys that for similar XT compatibility emitted a complete make+break sequence for several scancodes on press. And multimedia keyboards that threatened to exceed the limit on 7-bit scancodes were just around the corner.

The USB HID protocol is a lot less messy. No scancode set switching. No prefix bytes. No translation. No XT backwards compatibility. And conversely: A well-defined mechanism for vendor extensions. Well-defined usages for a whole bunch of extra keys that one might want to add, from media players to more complete calculator keypads.

It also places no limit on the number of simultaneous keypresses. A USB HID keyboard report is a very simple concept. It is a big bitmap of the instantaneous state of every key on the keyboard. The boot report format is constrained, by (mostly) using an inverted-array form for that bitmap, 8 bytes only permitting 64 keys in normal bitmap form; but a 16-byte report transmitted as a straight bitmap could handle a keyboard with 128 simultaneous keys if that were desired.


I’ve noticed this on my keyboard. It has a “BIOS mode”, but it works fine in “regular mode” in the BIOS anyways. Maybe because it’s actually UEFI?


It means that either your firmware has more complete HID driver (doubtful) or, or likely, it properly sends "switch to boot proto" command.


Today I learned. Thanks for this!


This is my kind of post. Respect.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: