Breaking Down The USB Keyboard Interface With Old-Fashioned Pen And Paper

What is better for gaming, old PS/2 style keyboards, or modern USB devices? [Ben Eater] sets out to answer this question, but along the way he ends up breaking down the entire USB keyboard interface.

It turns out that PS/2 and USB are very, very different. A PS/2 keyboard sends your keystroke every time you press a key, as long as it has power. A USB keyboard is more polite, it won’t send your keystrokes to the PC until it asks for them.

To help us make sense of USB’s more complicated transactions, [Ben] prints out the oscilloscope trace of a USB exchange between a PC and keyboard and deciphers it using just a pen and the USB specification. We were surprised to see that USB D+ and D- lines are not just a differential pair but also have more complicated signaling behavior. To investigate how USB handles multi-key rollover, [Ben] even borrowed a fancy oscilloscope that automatically decodes the USB data packets.

It turns out that newer isn’t always better—the cheap low-speed USB keyboard [Ben] tested is much slower than his trusty PS/2 model, and even a much nicer keyboard that uses the faster full-speed USB protocol is still only just about as fast as PS/2.

If you’d like to delve deeper into keyboard protocols, check out [Ben]’s guide to the PS/2 keyboard interface, complete with a breadboarded hardware decoder. If these keyboards have too many keys for your taste, you might consider this USB Morse code keyboard. Thanks to Peter Martin for the Tip!

37 thoughts on “Breaking Down The USB Keyboard Interface With Old-Fashioned Pen And Paper

  1. > even a much nicer keyboard that uses the faster full-speed USB protocol is still only just about as fast as PS/2.

    Humans are only so fast, so it doesn’t make sense to make keyboards faster. The USB HID protocol is horrible, but speed is not the problem.

    1. And at this point, certain kinds of “elite pro gamers” would begin frothing at the mouth and yelling in your face. I mean, I’ve seen dozens of these kinds of people seriously claiming that they can tell the difference between single milliseconds of latency! Obviously impossible, but you’d be surprised by how convinced they are of their magical abilities and how convinced their fans are as well!

      1. But it is not ‘single milliseconds’. it is ‘minimum transaction time – 1ms’. (that is – for low speed device). If there are more than one device – things get complicated.
        Also – USB is polled by host. PS/2 is interrupt driven.

        PS. Can’t see the difference in response time. But most certainly have seen the difference with key rollover.

      2. A few milliseconds might seem unperceivable, but to draw on a related subject, when I’m working in my DAW (digital audio) on some music, a few miliseconds lag on track can make profound difference on the overall sound. For example shifting the snare track a couple of milliseconds later is obviously almost impossible perceive when listening to just that track alone, but if there are other sounds around it, then even just a couple of milliseconds can actually completely change the whole feel of the song.

        To be more parallel, another example is the difference between performing live on an acoustic instrument and playing live through the DAW, just the smallest lag of only a few miliseconds is not just noticable, it’s frustrating! Even with a really good computer tweaked for audio applications combined with a really good audio interface there is still lag. I can get my input latency on my system’s audio down to 6-8ms and I can still notice it.
        So even though I’m not a gamer I could totally understand that within an immersive environment a few millisecond delay could actually be quite noticeable.

      1. Well this data means still there’s a giant gap: even though the ps/2 is faster in sending the data, does that also mean it’s always processed, while usb is waits for the request it’s it’s still in the buffer what you typed, knowing the old days the just send anyway approach didn’t work that well. Sometimes you pressed, but because of the mismatched timing the pc dismissed the key.
        Yes usb is maybe on the keyboard side slower, but because of this synced data it doesn’t miss any pressing of button.
        I understand that realtime sounds better, but for gaming it’s more than ever necessary to record every press.
        For those who played killer instinct, i’m sure they know how annoying it is if your combo was actual done correct but the game missed one button press.

        1. Yes, I wondered about that. Originally the keyboard interface was a shift register, but the move to AT meant a microcontroller. Which means the main CPU doesn’t have to be waiting when a character comes in. But upstream if that, is there a delay?

    2. >but speed is not the problem
      No one can see the difference between 24fps and 240! Its humanly impossible! Everyone has a 1 second reaction time, its impossible to be faster!

    3. its the u in usb, it comes at a cost.

      i wouldn’t say hid is horrible, it certainly removes the need to create drivers for a lot of hardware. much of the setup is handled on device with descriptors. the hid stack on the pc side will convert that into a device with the correct specification. this is a huge improvement over old skool serial which only really cared about data and you had to handle implementation driver side. that or deal with a dedicated port like ps/2. or any of the myriad of midiport hax that enabled pre-usb joysticks and game controllers. compared to what we had before, usb is pretty awesome.

  2. I once started up Sigrok/Pulseview with one of those EUR10 CY7C68013A Salaeaaeaea “clones” to sniff a bit around on low-speed USB, just out of curiosity if it would work, and was overwhelmed with information. T-states, checksums, bit-stuffing, keep-alive messages and a whole lot of other things I had never heard off before.

    PC based scopes are always a bit awkward to operate because of the missing panel with buttons. For a logic analyzer though, using a mouse and a keyboard is a quite good interface. The normally much higher resolution of a PC monitor is also a big help in interpreting long streams of data from a logic analyzer.

    Such a logic analyzer should be included in every “beginners kit” for starting to learn microcontroller stuff. Unfortunately most beginners do not know how valuable such a tool is. When working with microcontrollers, I make more use of such a EUR10 logic analyzer, then my EUR400 oscilloscope!

      1. I’m hoping Ben Eater will also read this.
        Such a USD10 Logic Analyzer is quite a good fit for his target audience, while the DSOX1204G, which costs over USD1200 is unlikely to fit with his target audience. Such a small logic analyzer with Dupont wires also fit very well with all the breadboard work he does. I scanned though his older video’s but there is no hint of it.

        Sigrok / Pulseview is in much more need than those big brands, but Open Source projects generally have no advertising budget whatsoever. If it’s being used by a Youtuber with 3/4 million subscribers, that would give some hard needed visibility to Sigrok / Pulseview.

        I think these small logic analyzers started from China, but I’m not sure. I do like however that these days sites like Adafruit are also selling them.

        You can also buy a generic CY7C68013A development board, and then you can even use 16 channels with Pulseview. This is bandwidth limited, so with all channels the max sample rate is lower. These generic development boards also lack input protection

      2. The few times I tried to use sigrok, it would only work for first capture, BUT fail after that. Needless to say, it isn’t usable for me. May be it is my set up, but certainly the software is part of the issue. Thankfully I have better analyzer.

  3. “A USB keyboard is more polite” It may be more polite than PS2 but does not seem well thought out. We have had session based communication systems for decades now. A session provides a reliable connection with error checking, re transmissions, a system for breaking up large blocks of data into smaller chunks and keep alive signals. Very Importantly, sessions freed you from the tedious, and never time optimal task of polling for changes. I expected more from a protocol that has so much horsepower at each end. Then again, I suppose it is a “master-slave” system, not peer to peer. But imagine the hordes of polls that has to return with no key pressed in order to keep the latency acceptable. It may work, but seems like a bad design choice to me. As good as asynchronous session based communications can be, we are just using a single differential channel, so a polled system at least resolves the media access control.

    1. Maybe you should take over the USB standards committee and rewrite the USB spec, and while you are at it, you can replace all of those billions of USB devices out there with your design. Seriously, complaining about USB is like complaining about the weather.

      1. Fair enough. The post suffered from comment creep. To source was, I would not call it “more polite”. Expecting others to ask repeatedly when you have the data, where time is of the essence, is not being polite, its shirking responsibility.

        1. I’d rather let my USB flash drive monopolize the bus and make the keyboard wait. Allowing the keyboard to interrupt a big data transfer is not a good design. “When time is of the essence”??? Did humans develop microsecond level response time and I just missed it?

          1. Unless you are using a physical HUB, each of the connectors from your PCB motherboard come from a Root HUB and are independent of each other. The peripherals on different motherboard connectors do not interfere with each other.

            BTW USB 3.x is a separate interface all together from the 2.0 even when they share the same connector. So there isn’t a chance for keyboard fighting with USB drive even if you were on the same external HUB.

            I wish they would remove some of the old limitations due to bandwidth sharing when you only get 2 USB ports from a PC, but not much of it happening.

          2. “unless you are using a physical hub…” Yeah so any professional hacker is going to be using a KVM switch to switch between the different machines necessary to do their jobs, so we all have our keyboards and mice plugged into the USB hub in the KVM switch. I’m also switching my web cam through the switch. I type like a madman and I certainly don’t notice any delay in keystrokes even when the webcam is blasting 1080p live video through the same USB connection as my keyboard. The proof is in the pudding.

          3. Even though USB 2 and USB 3 are using separate wires, they are both going to the same controller chip, which can only be accessed by one kernel thread at a time, so there will still be contention. Any latency here is well below our puny human powers to detect, but nevertheless your USB 2 webcam will slow down the data transfers from your USB 3 flash drive. It’s a minor issue, USB rules OK.

          4. It’s not the latency, it’s the unnecessary polling overhead required to keep within the latency that I don’t like. I prefer something closer resembling a stripped down TCP session, open and waiting, with only the occasional keep alive packets flowing during quiet times. And events at the keyboard triggering transmissions from the keyboard. Instead we have massive amounts of continuous polling. What were stuck with, may be simple to code, but it’s heavy on processing and bandwidth. We anyway need session based system transfers for larger data sets somewhere, so what we have here, in terms of total code base, it is not simpler, it’s more code. Multiple sets of code. In practice it really doesn’t matter, but it’s ugly. And having to deal with ugliness, to accept it, fosters future ugly solutions in other systems. I suppose what I am arguing for if more often used in peer to peer systems. And low and behold what do we have in USBOTG? Although it’s not real peer to peer, peer to peer would entirely remove it’s necessity. Yet another exception to deal with because of the initial ugly implementation. Now we multiple sets of code to use depending on the mode implemented, where a single asynchronous session supporting code base would have sufficed. Hindsight, I understand.

          5. @X:
            I was talking about keyboard vs USB FLASH… Not a high bandwidth device on USB 2.0 vs another 0n USB 3.x. xHCI uses scatter/gather DMA which will be used for these high bandwidth on Bulk transfer. There shouldn’t be much of CPU overheads.

            Keyboard runs on HID which are restricted to transferring 1 packet per interrupt per frame. It is not going to slow down your FLASH transfer even if you have a brain dead controller with a slow processor.

    2. >A session provides a reliable connection with error checking, re transmissions, a system for breaking up large blocks of data into smaller chunks and keep alive signals.

      USB packets has error checking, retransmission. HID uses interrupt transfer. Interrupt transfer is meant to be a low latency/low bandwidth/low bus occupancy, so you are limited to sending a packet at a time. The other transfer modes (e.g. Control, bulk, Iso) have segmentation/reassembly.

  4. Getting the data onto the wire is only part of the story. On a PC to reading each character from the keyboard FIFO requires handling an interrupt, then reading the status and data from the I/O port. Since the I/O port is the far side of the LPC port, for each I/O read the core / hyperthread will stall for about 250uS waiting for the data, during which it can do nothing else, irrespective of the clock speed, because an LPC I/O read takes at least 8 clocks at 33MHz.

    With USB, the report descriptor will be DMA’d into system memory where it can be manipulated with low latency. Also can contain information about several key presses.

    So avoiding a slow bus, reading from which can waste significant CPU cycles, seems far more important than sub-frame-time latencies on pressing keys. Especially if your game isn’t processing input at a higher rate than it is generating display frames.

    1. you also have to consider the way game engines handle input. usually through several layers of protocol fluff and usually rolled into an event system. any changes to input state will just create a new event to be handled. games operate in discreet time slices on the order of 10s of miliseconds (16.6ms @ 60 hz). you just have to beat the game tick interval for keypresses to arrive on time, and in computer time, that’s an eternity. whether you neatly stuff your interrupt generated keypresses from the super i/o or the messy and convoluted usb controller and hid stack, the game really doesn’t care. either way updates are going to post on time. also in multiplayer games its not unusual for the input to be handled in server time, which may be significantly slower than the render frequency client side, so even if you are rendering at 120hz, you controls might only be handled at 60hz, or even 30hz. we also ignore the fact that depending on the game design itself, a twitch shooter is going to be significantly more impacted by latency than an rts or some kind of simulation (sims may even have simulated control system latency to make things more realistic).

    2. >will stall for about 250uS waiting for the data …. because an LPC I/O read takes at least 8 clocks at 33MHz.

      Wrong unit! 33MHz has 30ns periods, not 30us. So you are looking at around 240ns or ~1/4 us.
      CPU core execution units these days can do other things while waiting for memory thanks to out of order execution, so it won’t stall.
      Interrupt handling for PS/2 has a lot more overhead than the LPC access.

  5. > BTW USB 3.x is a separate interface all together from the 2.0 even when they share the same connector. So there isn’t a chance for keyboard fighting with USB drive even if you were on the same external HUB.

    …yes, because the hub’s USB 2.0 interface instantly upgrades itself to 3.0 when I plug in a USB 3.0 storage device.

  6. For those micros short on pins, you can use a PS2 keyboard using only a single pin. However there seems to be a wide range of frequencies so you either have to time your specific keyboard to set the speed or send a where you can time the keyboard before running.

    BTW I’ve done it and it works :)

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.