an adapter from any connected PS/2 keyboard to USB HID output

Dependencies:   mbed

Translates PS/2 scancodes from keyboard to USB HID output. Keyboard LEDs not working for now, but key are handled.

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?

UserRevisionLine numberNew 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 }