an adapter from any connected PS/2 keyboard to USB HID output
Translates PS/2 scancodes from keyboard to USB HID output. Keyboard LEDs not working for now, but key are handled.
main.cpp@7:7ece3804edf5, 2020-06-07 (annotated)
- Committer:
- pilzm
- Date:
- Sun Jun 07 15:20:11 2020 +0000
- Revision:
- 7:7ece3804edf5
- Parent:
- 5:61ad1a6be0fd
Link to helpfull website added
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
shintamainjp | 0:aabf6427c82e | 1 | /** |
pilzm | 5:61ad1a6be0fd | 2 | * |
shintamainjp | 0:aabf6427c82e | 3 | * |
pilzm | 5:61ad1a6be0fd | 4 | * PS/2 Code from : https://os.mbed.com/cookbook/PS2 |
pilzm | 5:61ad1a6be0fd | 5 | * Conversion code from: https://gist.github.com/Slumber86/4439a6a5f2fcb5ece61a5c24b962535d |
pilzm | 5:61ad1a6be0fd | 6 | * https://github.com/keyboardio/KeyboardioHID/blob/master/src/BootKeyboard/BootKeyboard.cpp |
pilzm | 5:61ad1a6be0fd | 7 | * Explantion of PS/2 protocol: https://web.archive.org/web/20070321032851/https://www.beyondlogic.org/keyboard/keybrd.htm |
pilzm | 7:7ece3804edf5 | 8 | * Explanation of keycodes of different layouts: http://www.quadibloc.com/comp/scan.htm |
pilzm | 5:61ad1a6be0fd | 9 | * Source with LED command on arduino: https://playground.arduino.cc/PS2Keyboard/Cpp/ |
shintamainjp | 0:aabf6427c82e | 10 | */ |
shintamainjp | 0:aabf6427c82e | 11 | |
shintamainjp | 0:aabf6427c82e | 12 | #include "mbed.h" |
pilzm | 5:61ad1a6be0fd | 13 | #include "USBKeyboard.h" |
shintamainjp | 2:b06d5cea5b11 | 14 | #include "PS2Keyboard.h" |
pilzm | 5:61ad1a6be0fd | 15 | #include "Keymaps.h" |
shintamainjp | 0:aabf6427c82e | 16 | |
pilzm | 5:61ad1a6be0fd | 17 | DigitalOut myled2(LED2); |
pilzm | 5:61ad1a6be0fd | 18 | DigitalOut myled4(LED4); |
pilzm | 5:61ad1a6be0fd | 19 | PS2Keyboard ps2kb(p22, p23); //PS/2 keyboard (Clock, Data) |
pilzm | 5:61ad1a6be0fd | 20 | USBKeyboard keyboard; |
pilzm | 5:61ad1a6be0fd | 21 | LAYOUTS layo = LO_DE; //Layout of connected PS/2 keyboard, important only when additional keys are used |
pilzm | 5:61ad1a6be0fd | 22 | bool ext, brk; |
pilzm | 5:61ad1a6be0fd | 23 | int skip; |
pilzm | 5:61ad1a6be0fd | 24 | uint8_t report[9]; //array with data for USB HID report |
pilzm | 5:61ad1a6be0fd | 25 | Keymaps Kmap(layo, false); //keymap for normal keys |
pilzm | 5:61ad1a6be0fd | 26 | Keymaps KmapE(layo, true); //keymap for keys with E0 prefix |
pilzm | 5:61ad1a6be0fd | 27 | uint8_t leds; |
pilzm | 5:61ad1a6be0fd | 28 | bool send_leds; |
shintamainjp | 3:a3ba8d3e3958 | 29 | |
pilzm | 5:61ad1a6be0fd | 30 | |
pilzm | 5:61ad1a6be0fd | 31 | void report_add(uint8_t k); //add USB keycode to report array |
pilzm | 5:61ad1a6be0fd | 32 | void report_remove(uint8_t k); //remove USB keycode from report array |
shintamainjp | 1:e5eac8a97060 | 33 | |
pilzm | 5:61ad1a6be0fd | 34 | int main() |
pilzm | 5:61ad1a6be0fd | 35 | { |
pilzm | 5:61ad1a6be0fd | 36 | myled2=1; |
pilzm | 5:61ad1a6be0fd | 37 | PS2Keyboard::keyboard_event_t evt_kb; |
pilzm | 5:61ad1a6be0fd | 38 | while (!keyboard.configured()) { // wait until keyboard is configured |
pilzm | 5:61ad1a6be0fd | 39 | } |
pilzm | 5:61ad1a6be0fd | 40 | wait(1.0); |
pilzm | 5:61ad1a6be0fd | 41 | myled2=0; |
pilzm | 5:61ad1a6be0fd | 42 | myled4=1; |
shintamainjp | 0:aabf6427c82e | 43 | while (1) { |
pilzm | 5:61ad1a6be0fd | 44 | if (ps2kb.processing(&evt_kb)) { |
pilzm | 5:61ad1a6be0fd | 45 | uint8_t k = evt_kb.scancode; //scancode of PS/2 keyboard |
pilzm | 5:61ad1a6be0fd | 46 | uint8_t k2 = 0; //translated keycode in USB format |
pilzm | 5:61ad1a6be0fd | 47 | |
pilzm | 5:61ad1a6be0fd | 48 | if (k) { |
pilzm | 5:61ad1a6be0fd | 49 | if (skip) { |
pilzm | 5:61ad1a6be0fd | 50 | --skip; |
pilzm | 5:61ad1a6be0fd | 51 | } else { |
pilzm | 5:61ad1a6be0fd | 52 | if (k == 0xE0) { //special key, lookup in KE konversion table |
pilzm | 5:61ad1a6be0fd | 53 | ext = true; |
pilzm | 5:61ad1a6be0fd | 54 | } else if (k == 0xF0) { //breakcode, following scancode will be removed from report |
pilzm | 5:61ad1a6be0fd | 55 | brk = true; |
pilzm | 5:61ad1a6be0fd | 56 | } else if (k == 0xFA) { //acknowledgement from keyboard |
pilzm | 5:61ad1a6be0fd | 57 | if (send_leds) { |
pilzm | 5:61ad1a6be0fd | 58 | send_leds = false; |
pilzm | 5:61ad1a6be0fd | 59 | //send_msg(leds); //send LED status to keyboard, not functional |
pilzm | 5:61ad1a6be0fd | 60 | } |
pilzm | 5:61ad1a6be0fd | 61 | } else { |
pilzm | 5:61ad1a6be0fd | 62 | if (k == 0xE1) { //only one multibyte scancode uses this prefix |
pilzm | 5:61ad1a6be0fd | 63 | k2 = 72; |
pilzm | 5:61ad1a6be0fd | 64 | skip = 7; //following scancodes not nesessary for indentification, are skiped |
pilzm | 5:61ad1a6be0fd | 65 | brk = true; //no longpress of this key possible |
pilzm | 5:61ad1a6be0fd | 66 | report_add(k2); |
pilzm | 5:61ad1a6be0fd | 67 | keyboard.scanCodeRep(report); |
pilzm | 5:61ad1a6be0fd | 68 | } else { |
pilzm | 5:61ad1a6be0fd | 69 | k2 = ext ? KmapE.K[k] : Kmap.K[k]; // konvesion from PS/2 to USB HID keycode |
pilzm | 5:61ad1a6be0fd | 70 | } |
pilzm | 5:61ad1a6be0fd | 71 | |
pilzm | 5:61ad1a6be0fd | 72 | if (k2) { |
pilzm | 5:61ad1a6be0fd | 73 | if (brk) { |
pilzm | 5:61ad1a6be0fd | 74 | report_remove(k2); |
pilzm | 5:61ad1a6be0fd | 75 | if (k2 == 83 || k2 == 71 || k2 == 57) { //keys relevant for keyboard LEDs |
pilzm | 5:61ad1a6be0fd | 76 | send_leds = true; |
pilzm | 5:61ad1a6be0fd | 77 | if (k2 == 83) { |
pilzm | 5:61ad1a6be0fd | 78 | leds ^= 2; |
pilzm | 5:61ad1a6be0fd | 79 | } else if (k2 == 71) { |
pilzm | 5:61ad1a6be0fd | 80 | leds ^= 1; |
pilzm | 5:61ad1a6be0fd | 81 | } else if (k2 == 57) { |
pilzm | 5:61ad1a6be0fd | 82 | leds ^= 4; |
pilzm | 5:61ad1a6be0fd | 83 | } |
pilzm | 5:61ad1a6be0fd | 84 | //send_msg(0xED); //send LED status to keyboard, not functional |
pilzm | 5:61ad1a6be0fd | 85 | } |
pilzm | 5:61ad1a6be0fd | 86 | } else { |
pilzm | 5:61ad1a6be0fd | 87 | report_add(k2); |
pilzm | 5:61ad1a6be0fd | 88 | } |
pilzm | 5:61ad1a6be0fd | 89 | keyboard.scanCodeRep(report); |
pilzm | 5:61ad1a6be0fd | 90 | brk = false; |
pilzm | 5:61ad1a6be0fd | 91 | ext = false; |
pilzm | 5:61ad1a6be0fd | 92 | } |
pilzm | 5:61ad1a6be0fd | 93 | } |
shintamainjp | 3:a3ba8d3e3958 | 94 | } |
shintamainjp | 2:b06d5cea5b11 | 95 | } |
shintamainjp | 1:e5eac8a97060 | 96 | } |
shintamainjp | 0:aabf6427c82e | 97 | } |
shintamainjp | 0:aabf6427c82e | 98 | } |
pilzm | 5:61ad1a6be0fd | 99 | |
pilzm | 5:61ad1a6be0fd | 100 | |
pilzm | 5:61ad1a6be0fd | 101 | void report_remove(uint8_t k) |
pilzm | 5:61ad1a6be0fd | 102 | { |
pilzm | 5:61ad1a6be0fd | 103 | uint8_t i; |
pilzm | 5:61ad1a6be0fd | 104 | if (k >= 224) { //is modifier key |
pilzm | 5:61ad1a6be0fd | 105 | report[1] &= ~(1 << (k - 224)); |
pilzm | 5:61ad1a6be0fd | 106 | } else { |
pilzm | 5:61ad1a6be0fd | 107 | for (i = 3; i < 9; ++i) { //loop only normal key places |
pilzm | 5:61ad1a6be0fd | 108 | if (report[i] == k) { //if key in report |
pilzm | 5:61ad1a6be0fd | 109 | report[i] = 0; |
pilzm | 5:61ad1a6be0fd | 110 | break; |
pilzm | 5:61ad1a6be0fd | 111 | } |
pilzm | 5:61ad1a6be0fd | 112 | } |
pilzm | 5:61ad1a6be0fd | 113 | } |
pilzm | 5:61ad1a6be0fd | 114 | } |
pilzm | 5:61ad1a6be0fd | 115 | |
pilzm | 5:61ad1a6be0fd | 116 | void report_add(uint8_t k) |
pilzm | 5:61ad1a6be0fd | 117 | { |
pilzm | 5:61ad1a6be0fd | 118 | uint8_t i; |
pilzm | 5:61ad1a6be0fd | 119 | if (k >= 224) { //is modifier key |
pilzm | 5:61ad1a6be0fd | 120 | report[1] |= 1 << (k - 224); |
pilzm | 5:61ad1a6be0fd | 121 | } else if (report[3] != k && report[4] != k && |
pilzm | 5:61ad1a6be0fd | 122 | report[5] != k && report[6] != k && |
pilzm | 5:61ad1a6be0fd | 123 | report[7] != k && report[8] != k) { //not already set in report |
pilzm | 5:61ad1a6be0fd | 124 | for (i = 3; i < 9; ++i) { //loop only normal key |
pilzm | 5:61ad1a6be0fd | 125 | if (report[i] == 0) { //first free place is set |
pilzm | 5:61ad1a6be0fd | 126 | report[i] = k; |
pilzm | 5:61ad1a6be0fd | 127 | break; |
pilzm | 5:61ad1a6be0fd | 128 | } |
pilzm | 5:61ad1a6be0fd | 129 | } |
pilzm | 5:61ad1a6be0fd | 130 | } |
pilzm | 5:61ad1a6be0fd | 131 | } |