twitchyliquid64 / usbd-hid

MIT License
87 stars 37 forks source link

Is there an issue with the generated keyboard descriptor? #44

Open bschwind opened 2 years ago

bschwind commented 2 years ago

Hi, I'm building a keyboard and am currently using this crate. I'm currently using it on MacOS.

I noticed I'm receiving phantom key inputs when I hold down 4 or more keys. Normally this would sound like ghosting, but my keyboard has diodes on every switch, and I verified with probe-run and defmt that I'm not adding these characters to the KeyboardReport struct.

For example:

I eventually narrowed this down to the keyboard HID descriptor. I swapped it out for one from another project, and now the keyboard works properly with the scenarios above:

https://github.com/bschwind/key-ripper/pull/10

I don't yet know enough about USB HID descriptors to say what's going on, but it feels like a byte is out of place somewhere.

twitchyliquid64 commented 2 years ago

How are you filling in the descriptor? There should be 6 slots for scancodes:

https://github.com/twitchyliquid64/usbd-hid/blob/d0a80008476d74ef2017908ce256dc56bfc396b1/src/descriptor.rs#L83

bschwind commented 2 years ago

I start with an array of 6 zeroes. Then as I walk over my key matrix I push up to 6 keycodes into that keycodes array.

You can see the code for that here:

https://github.com/bschwind/key-ripper/blob/main/firmware/src/main.rs#L222

twitchyliquid64 commented 2 years ago

Gotcha!

I've got two possible theories right now:

  1. The OSX HID parser is hardcoded or being needy - unfortunately stub HID implementations are all too common. Do you see the same behavior on Linux? The Linux parser is the only one i trust not to get all uppity.
  2. The descriptor or the report is subtly malformed. Can you dump the bytes for the descriptor + a report-with-4-keys-pressed, and we can go through it manually to verify?
bschwind commented 2 years ago

I'll test this on a linux machine this Thursday when I have access to one, currently sitting out the rest of a quarantine period after covid 😅

Here's the descriptor I currently get from KeyboardReport::desc():

0x05,0x01
0x09,0x06
0xa1,0x01
0x05,0x07
0x19,0xe0
0x29,0xe7
0x15,0x00
0x25,0x01
0x75,0x01
0x95,0x08
0x81,0x02
0x19,0x00
0x29,0xff
0x26,0xff
0x00,0x75
0x08,0x95
0x01,0x81
0x03,0x05
0x08,0x19
0x01,0x29
0x05,0x25
0x01,0x75
0x01,0x95
0x05,0x91
0x02,0x95
0x03,0x91
0x03,0x05
0x07,0x19
0x00,0x29
0xdd,0x26
0xff,0x00
0x75,0x08
0x95,0x06
0x81,0x00
0xc0

Here's a report with 4 keys pressed:

INFO  Descriptor: modifier=0, reserved=0, leds=0, keycodes=[20, 26, 8, 21, 0, 0]

INFO  serialized: [0, 0, 20, 26, 8, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

With a different HID (specified here), I get:

INFO  Descriptor: modifier=0, reserved=0, leds=0, keycodes=[20, 26, 8, 21, 0, 0]

INFO  serialized: [0, 0, 20, 26, 8, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
bschwind commented 2 years ago

Hi @twitchyliquid64, sorry to get back to you so late on this.

I tested the keyboard with your descriptor on a linux machine and it functioned correctly, so this seems to be a quirk with macos.