

USB HID Keyboard scan codes
source link: https://gist.github.com/MightyPork/6da26e382a7ad91b5496ee55fdc73db2
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

vv20 commented on Apr 20, 2020
niceeeee thanks
Thanks for the list!
But, I have a quick question on why are the key codes are different than the listed IDs in the table? For example, Left Shift is listed as 0xE1, but it's 0x02 here.
Author
MightyPork commented on Oct 9, 2020
@amosgwa modifiers and scan codes are a different thing, presumably you get 0xE1 when shift is pressed or released and the 0x02 modifier for keys pressed while the shift is held. though, I have not verified this.
I wrote a small Python script to parse this header file, to use its content in other programming languages.
Thanks!
I would need to send the ":" I see #define KEY_SEMICOLON 0x33 // Keyboard ; and :
but when using it it always sends ";". How can I send the ":"?
Author
MightyPork commented on Nov 5, 2020
@wiwa1978 key codes are not the same as symbols. Apparently, you need to hold shift while the key is pressed. Try using the shift modifier or shift press and release events (also please comment here if you find a solution, it may help others)
benfmiller commented on Dec 4, 2020 •
From what I understand, each time a key is pressed or released, the keyboard sends an 8 byte signal saying which keys are currently down.
# press ctrl, press w, release w, then release all
# These are all char's of the hex value
press_key(KEY_MOD_LCTRL + KEY_NONE*7)
press_key(KEY_MOD_LCTRL + KEY_NONE + KEY_W + KEY_NONE*5)
press_key(KEY_MOD_LCTRL + KEY_NONE*7)
press_key(KEY_NONE*8)
This works for my raspberry pi that I set up as a keyboard
My .org incest was stolen and ???
I converted them all to decimals.
It's useful for Arduino, etc.
Link
This is pretty useful!
Thank you! @MightyPork
I created a python script using the key data in this gist.
It takes some hex data from a packet capture and decodes it to output the input text.
thaolt commented on Nov 13, 2021 •
Thank you for the sharing.
I want to share this array in case of anyone needed
#include "usb_hid_keys.h"
const char ascii_to_hid_key_map[95][2] = {
{0, KEY_SPACE}, {KEY_MOD_LSHIFT, KEY_1}, {KEY_MOD_LSHIFT, KEY_APOSTROPHE},
{KEY_MOD_LSHIFT, KEY_3}, {KEY_MOD_LSHIFT, KEY_4}, {KEY_MOD_LSHIFT, KEY_5},
{KEY_MOD_LSHIFT, KEY_7}, {0, KEY_APOSTROPHE}, {KEY_MOD_LSHIFT, KEY_9},
{KEY_MOD_LSHIFT, KEY_0}, {KEY_MOD_LSHIFT, KEY_8}, {KEY_MOD_LSHIFT, KEY_EQUAL},
{0, KEY_COMMA}, {0, KEY_MINUS}, {0, KEY_DOT}, {0, KEY_SLASH}, {0, KEY_0},
{0, KEY_1}, {0, KEY_2}, {0, KEY_3}, {0, KEY_4}, {0, KEY_5}, {0, KEY_6},
{0, KEY_7}, {0, KEY_8}, {0, KEY_9}, {KEY_MOD_LSHIFT, KEY_SEMICOLON},
{0, KEY_SEMICOLON}, {KEY_MOD_LSHIFT, KEY_COMMA}, {0, KEY_EQUAL},
{KEY_MOD_LSHIFT, KEY_DOT}, {KEY_MOD_LSHIFT, KEY_SLASH}, {KEY_MOD_LSHIFT, KEY_2},
{KEY_MOD_LSHIFT, KEY_A}, {KEY_MOD_LSHIFT, KEY_B}, {KEY_MOD_LSHIFT, KEY_C},
{KEY_MOD_LSHIFT, KEY_D}, {KEY_MOD_LSHIFT, KEY_E}, {KEY_MOD_LSHIFT, KEY_F},
{KEY_MOD_LSHIFT, KEY_G}, {KEY_MOD_LSHIFT, KEY_H}, {KEY_MOD_LSHIFT, KEY_I},
{KEY_MOD_LSHIFT, KEY_J}, {KEY_MOD_LSHIFT, KEY_K}, {KEY_MOD_LSHIFT, KEY_L},
{KEY_MOD_LSHIFT, KEY_M}, {KEY_MOD_LSHIFT, KEY_N}, {KEY_MOD_LSHIFT, KEY_O},
{KEY_MOD_LSHIFT, KEY_P}, {KEY_MOD_LSHIFT, KEY_Q}, {KEY_MOD_LSHIFT, KEY_R},
{KEY_MOD_LSHIFT, KEY_S}, {KEY_MOD_LSHIFT, KEY_T}, {KEY_MOD_LSHIFT, KEY_U},
{KEY_MOD_LSHIFT, KEY_V}, {KEY_MOD_LSHIFT, KEY_W}, {KEY_MOD_LSHIFT, KEY_X},
{KEY_MOD_LSHIFT, KEY_Y}, {KEY_MOD_LSHIFT, KEY_Z}, {0, KEY_LEFTBRACE},
{0, KEY_BACKSLASH}, {0, KEY_RIGHTBRACE}, {KEY_MOD_LSHIFT, KEY_6},
{KEY_MOD_LSHIFT, KEY_MINUS}, {0, KEY_GRAVE}, {0, KEY_A}, {0, KEY_B},
{0, KEY_C}, {0, KEY_D}, {0, KEY_E}, {0, KEY_F}, {0, KEY_G}, {0, KEY_H},
{0, KEY_I}, {0, KEY_J}, {0, KEY_K}, {0, KEY_L}, {0, KEY_M}, {0, KEY_N},
{0, KEY_O}, {0, KEY_P}, {0, KEY_Q}, {0, KEY_R}, {0, KEY_S}, {0, KEY_T},
{0, KEY_U}, {0, KEY_V}, {0, KEY_W}, {0, KEY_X}, {0, KEY_Y}, {0, KEY_Z},
{KEY_MOD_LSHIFT, KEY_LEFTBRACE}, {KEY_MOD_LSHIFT, KEY_BACKSLASH},
{KEY_MOD_LSHIFT, KEY_RIGHTBRACE}, {KEY_MOD_LSHIFT, KEY_GRAVE},
};
Example usage
void hid_sendch(uint8_t c)
{
uint8_t buffer[8] = {0};
if (c > 127) return;
if (c < 32) return;
c -= 32; // offset ignore the first 32 symbols in ascii table
buffer[0] = ascii_to_hid_key_map[c][0];
buffer[2] = ascii_to_hid_key_map[c][1];
FILE* f = fopen("/dev/hidg0", "wb");
fwrite(buffer, sizeof (char), 8, f);
fclose(f);
usleep(10000);
buffer[0] = 0;
buffer[2]= 0;
f = fopen("/dev/hidg0", "wb");
fwrite(buffer, sizeof (char), 8, f);
fclose(f);
usleep(50000);
}
void hid_sendstr(char* str)
{
uint8_t l = strlen(str);
for (uint8_t i = 0; i < l; i++) {
hid_sendch(str[i]);
}
}
hid_sendstr("Hello World!");
That's a handy array! ...The implicit casts between char
and uint8_t
are probably going to be safe in most cases (so long as you don't enable compiler warnings) ...but be careful if you call sendkey(31)
...I'm curious: Why you close the device and immediately reopen it for the second keystroke?
Thank @csBlueChip for your suggestion, I've updated it into a safer function. My application only handles printable ASCII string, thus <32 and >127 indexes is not supported. In my actual application source, there is a delay between writes. The function simulates key-press and key-release. The reason for close and reopen the before second writing is because of tried and true. I think the written buffer isn't sent until the device is closed, I'm not sure. For more information: https://randomnerdtutorials.com/raspberry-pi-zero-usb-keyboard-hid/
Okay, on closer look after the 'g' the transmission got cut. i.e \x00\x00\x0a\x00\x00\x00\x00\x00
would result in \x00\x00\x0a
. Fix was to position the 'g' in the last spot of the sequence so \x00\x00\x00\x00\x00\x00\x00\x0a
. In case anyone has the same problem :)
Hi @wiwa1978 @MightyPork ,
I am interested in using the key combination of alt + f4
. But I am not able to find the required solution. Any kind of help is appreciated
Thanks
I am interested in using the key combination of
alt + f4
. But I am not able to find the required solution. Any kind of help is appreciated
You need to do the check in two parts ...first check the modifier keys to see that KEY_MOD_LALT is (the only modifier) being pressed ...then check to see if KEY_F4 is (the only key) being pressed
This video may help you understand why: https://youtu.be/wdgULBpRoXk?t=1545
So maybe I can help with this. A string send over by a keyboard or for instance a rubber ducky consists of 8 bytes. The first byte is the modifier key. This value can be everything you see in the first post of this thread @line 19 - 26. You can also use combinations of modifiers by simply adding them together (LALT + LSHIFT = 0x06
). So the first value of your string would be 0x04, because this is the value of left Alt. The second byte is reserved, so we'll leave it 0. Now the keys will follow. In your case the next key would be F4 (0x3d
). Throwing everything into a sequence of 8 bytes and you'll get \04\0\3d\0\0\0\0\0
. Don't forget to let go of all the keys by sending a string full of 0's. :))
I have made a project where I turn a linux phone into a rubber ducky using exactly this. You may have a look :)
https://github.com/Sherknob/PineDucky
Hey @Sherknob
Thanks for your response
I am currently using this library from Github. I am also using the key_code
function as given here. As it is given that, the arguments to the key_code
function is only integers. But the solution that you have given contains strings. How can I use that?
Thanks and regards
Hey @suburban-daredevil
Since the code you provided in your latest comment is pretty much uncommented and I don't have much time at hand, I think it would be great to have a look at your existing code. Is this possible?
Have a nice day :)
Hello @suburban-daredevil :)
Good news I think. I found the function that does, what I've been explaining in my initial comment.
int USBKeyboard::_putc(int c)
{
return key_code(c, keymap[c].modifier);
}
Above is the function that calls key_code and returns a boolean if it was successful or not. You are using the key_code function directly, and that is okay I guess.
bool USBKeyboard::key_code(uint8_t key, uint8_t modifier)
{
_mutex.lock();
// Send a simulated keyboard keypress. Returns true if successful.
HID_REPORT report;
report.data[0] = REPORT_ID_KEYBOARD;
report.data[1] = modifier;
report.data[2] = 0;
report.data[3] = keymap[key].usage;
report.data[4] = 0;
report.data[5] = 0;
report.data[6] = 0;
report.data[7] = 0;
report.data[8] = 0;
report.length = 9;
if (!send(&report)) {
_mutex.unlock();
return false;
}
report.data[1] = 0;
report.data[3] = 0;
if (!send(&report)) {
_mutex.unlock();
return false;
}
_mutex.unlock();
return true;
}
The function shown above it doing the thing I was explaining earlier. It is expecting a key code (in your case MY_SHUTDOWN) and a modifier value (in your case KEY_LALT). Then it is inserting these values into an array of ints. This array is the "string" I was talking of. One more thing, as you can see, keymap[key].usage
is written to report.data[3]
. Since you are not using a keymap you could just change keymap[key].usage
to key
. And this function seems to send a "let go of all keys" afterwards, so you don't need your key.key_code(KEY_NONE);
.
For now, to make it simplest, you could define your key separate from your modifier. So this would be
#define KEY_LALT 0x04
#define MY_SHUTDOWN 0x3d
and then call the function with key_code(MY_SHUTDOWN, KEY_LALT);
.
Note: I did not test any of this :)
Hope this helps
Hey @Sherknob
Thank you so much for your guidance
I actually found the fix through your guidance. We must actually use the index of the key that is required, f4
in our case, from the keymap table
in the USBKeyboard.cpp
file. The index of f4
was 131. Giving that along with the predefined KEY_ALT
as modifier works as expected.
#define MY_KEY_F4 131
key.key_code(MY_KEY_F4, KEY_ALT);
Similarly any other key combinations can be used. Just find the index of the required key in the USBKeyboard.cpp file and replace the first parameter of key_code
with that value and second parameter with that of the required modifier.
The predefined modifiers are KEY_CTRL
, KEY_SHIFT
, KEY_ALT
. Please take a look here for further clarity!
Thanks to @Sherknob
Thanks and regards
@suburban-daredevil
Your welcome. Happy to hear that you got it working :)
Have a nice day :))
Is there no key code for the Context Menu key (or would that be the "Props" key?)
Is there no key code for the Context Menu key (or would that be the "Props" key?)
It is #define KEY_COMPOSE 0x65 // Keyboard Application
.
tomek-szczesny commented on May 3 •
@PaddleStroke the page this came from doesn't list anything. If you have a keyboard with them, you can try catching them with xev here's something about the Fn key, maybe it'll work. https://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html
Hi, this link leads to extra information about PS/2 keyboard if I'm not mistaken. I found this page as I too am seeking the keycode for display brightness and others under Fn combo.
So if anyone knows the answer, please share. :)
EDIT: Okay, found it. USB HID Usage Tables defines "Display Brightness Increment/Decrement" codes as 0x6F and 0x70 respectively, but on Consumer Page (0x0C) rather than Keyboard Page (0x07).
QQ: is this hid actions limited to android or will apply to ios as well?
I made a JSON dict version for anyone working on CTFs using Python/Javascript:
{
"0x00":"KEY_NONE",
"0x01":"KEY_ERR_OVF",
"0x04":"KEY_A",
"0x05":"KEY_B",
"0x06":"KEY_C",
"0x07":"KEY_D",
"0x08":"KEY_E",
"0x09":"KEY_F",
"0x0a":"KEY_G",
"0x0b":"KEY_H",
"0x0c":"KEY_I",
"0x0d":"KEY_J",
"0x0e":"KEY_K",
"0x0f":"KEY_L",
"0x10":"KEY_M",
"0x11":"KEY_N",
"0x12":"KEY_O",
"0x13":"KEY_P",
"0x14":"KEY_Q",
"0x15":"KEY_R",
"0x16":"KEY_S",
"0x17":"KEY_T",
"0x18":"KEY_U",
"0x19":"KEY_V",
"0x1a":"KEY_W",
"0x1b":"KEY_X",
"0x1c":"KEY_Y",
"0x1d":"KEY_Z", "0x1e":"KEY_1",
"0x1f":"KEY_2",
"0x20":"KEY_3",
"0x21":"KEY_4",
"0x22":"KEY_5",
"0x23":"KEY_6",
"0x24":"KEY_7",
"0x25":"KEY_8",
"0x26":"KEY_9",
"0x27":"KEY_0", "0x28":"KEY_ENTER",
"0x29":"KEY_ESC",
"0x2a":"KEY_BACKSPACE",
"0x2b":"KEY_TAB",
"0x2c":"KEY_SPACE",
"0x2d":"KEY_MINUS",
"0x2e":"KEY_EQUAL",
"0x2f":"KEY_LEFTBRACE",
"0x30":"KEY_RIGHTBRACE",
"0x31":"KEY_BACKSLASH",
"0x32":"KEY_HASHTILDE",
"0x33":"KEY_SEMICOLON",
"0x34":"KEY_APOSTROPHE",
"0x35":"KEY_GRAVE",
"0x36":"KEY_COMMA",
"0x37":"KEY_DOT",
"0x38":"KEY_SLASH",
"0x39":"KEY_CAPSLOCK", "0x3a":"KEY_F1",
"0x3b":"KEY_F2",
"0x3c":"KEY_F3",
"0x3d":"KEY_F4",
"0x3e":"KEY_F5",
"0x3f":"KEY_F6",
"0x40":"KEY_F7",
"0x41":"KEY_F8",
"0x42":"KEY_F9",
"0x43":"KEY_F10",
"0x44":"KEY_F11",
"0x45":"KEY_F12", "0x46":"KEY_SYSRQ",
"0x47":"KEY_SCROLLLOCK",
"0x48":"KEY_PAUSE",
"0x49":"KEY_INSERT",
"0x4a":"KEY_HOME",
"0x4b":"KEY_PAGEUP",
"0x4c":"KEY_DELETE",
"0x4d":"KEY_END",
"0x4e":"KEY_PAGEDOWN",
"0x4f":"KEY_RIGHT",
"0x50":"KEY_LEFT",
"0x51":"KEY_DOWN",
"0x52":"KEY_UP", "0x53":"KEY_NUMLOCK",
"0x54":"KEY_KPSLASH",
"0x55":"KEY_KPASTERISK",
"0x56":"KEY_KPMINUS",
"0x57":"KEY_KPPLUS",
"0x58":"KEY_KPENTER",
"0x59":"KEY_KP1",
"0x5a":"KEY_KP2",
"0x5b":"KEY_KP3",
"0x5c":"KEY_KP4",
"0x5d":"KEY_KP5",
"0x5e":"KEY_KP6",
"0x5f":"KEY_KP7",
"0x60":"KEY_KP8",
"0x61":"KEY_KP9",
"0x62":"KEY_KP0",
"0x63":"KEY_KPDOT", "0x64":"KEY_102ND",
"0x65":"KEY_COMPOSE",
"0x66":"KEY_POWER",
"0x67":"KEY_KPEQUAL", "0x68":"KEY_F13",
"0x69":"KEY_F14",
"0x6a":"KEY_F15",
"0x6b":"KEY_F16",
"0x6c":"KEY_F17",
"0x6d":"KEY_F18",
"0x6e":"KEY_F19",
"0x6f":"KEY_F20",
"0x70":"KEY_F21",
"0x71":"KEY_F22",
"0x72":"KEY_F23",
"0x73":"KEY_F24", "0x74":"KEY_OPEN",
"0x75":"KEY_HELP",
"0x76":"KEY_PROPS",
"0x77":"KEY_FRONT",
"0x78":"KEY_STOP",
"0x79":"KEY_AGAIN",
"0x7a":"KEY_UNDO",
"0x7b":"KEY_CUT",
"0x7c":"KEY_COPY",
"0x7d":"KEY_PASTE",
"0x7e":"KEY_FIND",
"0x7f":"KEY_MUTE",
"0x80":"KEY_VOLUMEUP",
"0x81":"KEY_VOLUMEDOWN", "0x85":"KEY_KPCOMMA", "0x87":"KEY_RO",
"0x88":"KEY_KATAKANAHIRAGANA",
"0x89":"KEY_YEN",
"0x8a":"KEY_HENKAN",
"0x8b":"KEY_MUHENKAN",
"0x8c":"KEY_KPJPCOMMA", "0x90":"KEY_HANGEUL",
"0x91":"KEY_HANJA",
"0x92":"KEY_KATAKANA",
"0x93":"KEY_HIRAGANA",
"0x94":"KEY_ZENKAKUHANKAKU", "0xb6":"KEY_KPLEFTPAREN",
"0xb7":"KEY_KPRIGHTPAREN", "0xe0":"KEY_LEFTCTRL",
"0xe1":"KEY_LEFTSHIFT",
"0xe2":"KEY_LEFTALT",
"0xe3":"KEY_LEFTMETA",
"0xe4":"KEY_RIGHTCTRL",
"0xe5":"KEY_RIGHTSHIFT",
"0xe6":"KEY_RIGHTALT",
"0xe7":"KEY_RIGHTMETA", "0xe8":"KEY_MEDIA_PLAYPAUSE",
"0xe9":"KEY_MEDIA_STOPCD",
"0xea":"KEY_MEDIA_PREVIOUSSONG",
"0xeb":"KEY_MEDIA_NEXTSONG",
"0xec":"KEY_MEDIA_EJECTCD",
"0xed":"KEY_MEDIA_VOLUMEUP",
"0xee":"KEY_MEDIA_VOLUMEDOWN",
"0xef":"KEY_MEDIA_MUTE",
"0xf0":"KEY_MEDIA_WWW",
"0xf1":"KEY_MEDIA_BACK",
"0xf2":"KEY_MEDIA_FORWARD",
"0xf3":"KEY_MEDIA_STOP",
"0xf4":"KEY_MEDIA_FIND",
"0xf5":"KEY_MEDIA_SCROLLUP",
"0xf6":"KEY_MEDIA_SCROLLDOWN",
"0xf7":"KEY_MEDIA_EDIT",
"0xf8":"KEY_MEDIA_SLEEP",
"0xf9":"KEY_MEDIA_COFFEE",
"0xfa":"KEY_MEDIA_REFRESH",
"0xfb":"KEY_MEDIA_CALC",
}
QQ: is this hid actions limited to android or will apply to ios as well?
I've had success with the same keymap on MacOS. Can't say anything on IOS.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK