How to identify key code sent by keyboard from host side?

Hello. For debugging some code I wrote, I need to check which key code actually gets sent to my host. I’m running Kubuntu Linux Bionic.

By seeing this webpage I tried running showkeys and pressing my a and I got:

keycode  30 press
keycode  30 release

whereas with the --scancodes option it gives:

0x1e 0x9e

whereas since I’m not able to decipher those values, what I want to see is something like the value defined in the USB HID spec HIDTables.h:

#define HID_KEYBOARD_A_AND_A	0x04

What other software do people use on Linux for this purpose?

That ‘keycode 30’ that you’re seeing is the Linux kernel keyboard event code, as produced by the device driver interpreting the reports.

When I’ve wanted to see a copy of the actual USB report I’ve had to look at the actual input device directly, but first you have to identify which one that is.

In /proc/bus/input/devices look for the “Keyboardio Model 01” that lists kbd in the handlers. On my system (Gentoo) that line also contains an “event” entry, event10 on my system right now.

Then, as root I can do

cat /dev/input/event10 | hexdump

to produce a hex dump in real time of the data sent by the keyboard.

Decoding the raw report is left as an exercise for the reader. :wink:

Aw come on…

0000000 3982 5b72 0000 0000 2fd8 0006 0000 0000
0000010 0004 0004 0004 0007 3982 5b72 0000 0000
0000020 2fd8 0006 0000 0000 0001 001e 0001 0000
0000030 3982 5b72 0000 0000 2fd8 0006 0000 0000
a0000040 0000 0000 0000 0000 3982 5b72 0000 0000
0000050 396a 0007 0000 0000 0004 0004 0004 0007
0000060 3982 5b72 0000 0000 396a 0007 0000 0000
0000070 0001 001e 0000 0000 3982 5b72 0000 0000
0000080 396a 0007 0000 0000 0000 0000 0000 0000
0000090 3988 5b72 0000 0000 8ace 0006 0000 0000
00000a0 0004 0004 0045 0007 3988 5b72 0000 0000
00000b0 8ace 0006 0000 0000 0001 0058 0001 0000
00000c0 3988 5b72 0000 0000 8ace 0006 0000 0000
00000d0 0000 0000 0000 0000 3988 5b72 0000 0000
00000e0 8ea4 0006 0000 0000 0004 0004 0045 0007
00000f0 3988 5b72 0000 0000 8ea4 0006 0000 0000
0000100 0001 0058 0000 0000 3988 5b72 0000 0000
0000110 8ea4 0006 0000 0000 0000 0000 0000 0000
0000120 398f 5b72 0000 0000 8ce9 000d 0000 0000
0000130 0004 0004 0045 0007 398f 5b72 0000 0000
0000140 8ce9 000d 0000 0000 0001 0058 0001 0000
0000150 398f 5b72 0000 0000 8ce9 000d 0000 0000
0000160 0000 0000 0000 0000 398f 5b72 0000 0000
0000170 90ae 000d 0000 0000 0004 0004 0045 0007
0000180 398f 5b72 0000 0000 90ae 000d 0000 0000
0000190 0001 0058 0000 0000 398f 5b72 0000 0000
00001a0 90ae 000d 0000 0000 0000 0000 0000 0000
00001b0 3995 5b72 0000 0000 0651 000b 0000 0000
00001c0 0004 0004 0014 0007 3995 5b72 0000 0000
00001d0 0651 000b 0000 0000 0001 0010 0001 0000
00001e0 3995 5b72 0000 0000 0651 000b 0000 0000
q00001f0 0000 0000 0000 0000 3995 5b72 0000 0000
0000200 f05e 000d 0000 0000 0004 0004 0014 0007
0000210 3995 5b72 0000 0000 f05e 000d 0000 0000
0000220 0001 0010 0000 0000 3995 5b72 0000 0000
0000230 f05e 000d 0000 0000 0000 0000 0000 0000
0000240 3996 5b72 0000 0000 3ed2 000a 0000 0000
0000250 0004 0004 00e0 0007 3996 5b72 0000 0000
0000260 3ed2 000a 0000 0000 0001 001d 0001 0000
0000270 3996 5b72 0000 0000 3ed2 000a 0000 0000
0000280 0000 0000 0000 0000 3996 5b72 0000 0000
0000290 e09e 000b 0000 0000 0004 0004 0019 0007
00002a0 3996 5b72 0000 0000 e09e 000b 0000 0000
00002b0 0001 002f 0001 0000 3996 5b72 0000 0000
00002c0 e09e 000b 0000 0000 0000 0000 0000 0000

I give up! :pensive:

When I replied earlier I didn’t know offhand how to decode that information, although when I knew what I was looking for I thought I could see it. I figured that it wouldn’t be too hard to find a good description of the structure of a USB HID report and decode it.

Now I still don’t yet know how to decode that information and that it isn’t as simple as I expected it to be, but I’m working on it.

OK, I’ve done some more research and I’ve found that I was completely off base with regard to /dev/input/event*. It does seem to be related to the USB events and contain a version of the HID report, but it definitely isn’t the raw report.

What I have found is a pair of utilities, usbhid-dump and rd.rex that can be used to see and understand the raw reports.

usbhid-dump may have a package already for your distribution.

rd.rex is a rexx script that I found at https://github.com/abend0c1/hidrdd

The basics of all of this is that a USB device sends a “report descriptor” to the host telling the host what types of data will be sent and how it will be structured.

The command usbhid-dump --address=bus[:dev] -ed will produce the list of descriptors the device provides (my Model01 provides three), where you need to supply the bus and device number for your keyboard. Note that I’ve had this effectively disconnect my keyboard, requiring me to unplug it and plug it back in.

The descriptor sent by my Model01 for the primary device is:

 05 01 09 80 A1 01 85 05 15 00 26 FF 00 19 00 29
 FF 95 01 75 08 81 00 C0 05 01 09 06 A1 01 85 08
 05 07 19 E0 29 E7 15 00 25 01 75 01 95 08 81 02
 05 08 19 01 29 08 95 08 75 01 91 02 05 07 75 04
 95 01 81 01 19 04 29 31 15 00 25 01 75 01 95 2E
 81 02 75 01 95 01 81 01 19 33 29 9B 15 00 25 01
 75 01 95 69 81 02 75 01 95 01 81 01 19 9D 29 DD
 15 00 25 01 75 01 95 41 81 02 75 02 95 01 81 01
 C0 05 0C 09 01 A1 01 85 04 15 00 26 FF 03 19 00
 2A FF 03 95 04 75 10 81 00 C0 05 01 09 02 A1 01
 85 01 05 09 19 01 29 08 15 00 25 01 95 08 75 01
 81 02 05 01 09 30 09 31 09 38 15 81 25 7F 75 08
 95 03 81 06 05 0C 0A 38 02 15 81 25 7F 75 08 95
 01 81 06 C0

The secondary interface seems to be the other mouse, while the interface device seems very odd.

rd.rex can then decode that descriptor information into something easier for a person to read, both as a structured interpretation of the numbers and as a C struct. The interpretation of that descriptor is 439 lines long, so I won’t include it here.

Armed with this information, you can use usbhid-dump --address=bus[:dev] -es to show you the reports in the same format as promised by the descriptor (hopefully). Note that this disconnects the keyboard from all other input sources (such as X and the kernel) for the duration of the capture so it is advised to have a second keyboard. Note also that sometimes my keyboard doesn’t reconnect automatically afterwards, requiring replugging.

I’m very sorry for the initial wrong information.

Edit: I initially pasted in some other descriptor besides the main one for the KeyboardIO Model01 - now corrected.