UNPKG

node-hid-stream

Version:

Stream data from HID device in Node.js

237 lines (209 loc) 7.94 kB
'use strict'; const HidKeyboardPacket = require('./hid-keyboard-packet'); function keyboard(rawData) { const packet = new HidKeyboardPacket(); const data = rawData.toJSON().data; parseModifiers(packet, data.shift()); // parse modifiers (bit field) data.shift(); // the next element is always 0 (I think...) parseKeyCodes(packet, data); // parse keycodes from the rest parseCharCodes(packet, data); // parse charcodes from keycodes parseErrorState(packet, data); // detect rollover error return packet; } /** * Convert modifier key bits into * array of human-readable identifiers */ function parseModifiers(packet, bits) { /* eslint-disable no-bitwise */ /* eslint-disable no-param-reassign */ packet.modifiers.l_control = ((bits & 1) !== 0); packet.modifiers.l_shift = ((bits & 2) !== 0); packet.modifiers.l_alt = ((bits & 4) !== 0); packet.modifiers.l_meta = ((bits & 8) !== 0); packet.modifiers.r_control = ((bits & 16) !== 0); packet.modifiers.r_shift = ((bits & 32) !== 0); packet.modifiers.r_alt = ((bits & 64) !== 0); packet.modifiers.r_meta = ((bits & 128) !== 0); /* eslint-enable no-bitwise */ /* eslint-enable no-param-reassign */ } /** * Slice HID keycodes into separate array */ function parseKeyCodes(arr, keys) { if (typeof keys !== 'object') { return false; } keys.forEach((key) => { if (key > 3) { arr.keyCodes.push(key); } }); return true; } function parseCharCodes(packet, keys) { if (typeof keys !== 'object') { return false; } const shift = packet.shift(); function push(a, A) { packet.charCodes.push(shift ? A : a); } function parse(key) { switch (key) { // Note: codes are available here: http://www.usb.org/developers/hidpage/Hut1_12v2.pdf // See page 53 case 4: push('a', 'A'); break; case 5: push('b', 'B'); break; case 6: push('c', 'C'); break; case 7: push('d', 'D'); break; case 8: push('e', 'E'); break; case 9: push('f', 'F'); break; case 10: push('g', 'G'); break; case 11: push('h', 'H'); break; case 12: push('i', 'I'); break; case 13: push('j', 'J'); break; case 14: push('k', 'K'); break; case 15: push('l', 'L'); break; case 16: push('m', 'M'); break; case 17: push('n', 'N'); break; case 18: push('o', 'O'); break; case 19: push('p', 'P'); break; case 20: push('q', 'Q'); break; case 21: push('r', 'R'); break; case 22: push('s', 'S'); break; case 23: push('t', 'T'); break; case 24: push('u', 'U'); break; case 25: push('v', 'V'); break; case 26: push('w', 'W'); break; case 27: push('x', 'X'); break; case 28: push('y', 'Y'); break; case 29: push('z', 'Z'); break; case 30: push('1', '!'); break; case 31: push('2', '@'); break; case 32: push('3', '#'); break; case 33: push('4', '$'); break; case 34: push('5', '%'); break; case 35: push('6', '^'); break; case 36: push('7', '&'); break; case 37: push('8', '*'); break; case 38: push('9', '('); break; case 39: push('0', ')'); break; case 40: push('\n', '\n'); break; case 41: push('', ''); break; // escape case 42: push('', ''); break; // delete case 43: push('\t', '\t'); break; case 44: push(' ', ' '); break; case 45: push('-', '_'); break; case 46: push('=', '+'); break; case 47: push('[', '{'); break; case 48: push(']', '}'); break; case 49: push('\\', '|'); break; case 50: push('#', '~'); break; case 51: push(';', ':'); break; case 52: push('\'', '"'); break; case 53: push('`', '~'); break; case 54: push(',', '<'); break; case 55: push('.', '>'); break; case 56: push('/', '?'); break; case 57: push('', ''); break; // caps lock case 58: push('', ''); break; // F1 case 59: push('', ''); break; // F2 case 60: push('', ''); break; // F3 case 61: push('', ''); break; // F4 case 62: push('', ''); break; // F5 case 63: push('', ''); break; // F6 case 64: push('', ''); break; // F7 case 65: push('', ''); break; // F8 case 66: push('', ''); break; // F9 case 67: push('', ''); break; // F10 case 68: push('', ''); break; // F11 case 69: push('', ''); break; // F12 case 70: push('', ''); break; // Print screen case 71: push('', ''); break; // Scroll lock case 72: push('', ''); break; // Pause case 73: push('', ''); break; // Insert case 74: push('', ''); break; // Home case 75: push('', ''); break; // PageUp case 76: push('', ''); break; // Delete forward case 77: push('', ''); break; // End case 78: push('', ''); break; // PageDown case 79: push('', ''); break; // RightArrow case 80: push('', ''); break; // LeftArrow case 81: push('', ''); break; // DownArrow case 82: push('', ''); break; // UpArrow // Keypad case 83: push('', ''); break; // NumLock / clear case 84: push('/', '/'); break; // case 85: push('*', '*'); break; // case 86: push('-', '-'); break; // case 87: push('+', '+'); break; // case 88: push('\n', '\n'); break; // // Keypad numbers case 89: push('1', '1'); break; // case 90: push('2', '2'); break; // case 91: push('3', '3'); break; // case 92: push('4', '4'); break; // case 93: push('5', '5'); break; // case 94: push('6', '6'); break; // case 95: push('7', '7'); break; // case 96: push('8', '8'); break; // case 97: push('9', '9'); break; // case 98: push('0', '0'); break; // case 99: push('.', '.'); break; // case 100: push('\\', '|'); break; // Non-US case 101: push('', ''); break; // Application case 102: push('', ''); break; // Power case 103: push('=', '='); break; // Keypad = case 104: push('', ''); break; // F13 case 105: push('', ''); break; // F14 case 106: push('', ''); break; // F15 case 107: push('', ''); break; // F16 case 108: push('', ''); break; // F17 case 109: push('', ''); break; // F18 case 110: push('', ''); break; // F19 case 111: push('', ''); break; // F20 case 112: push('', ''); break; // F21 case 113: push('', ''); break; // F22 case 114: push('', ''); break; // F23 case 115: push('', ''); break; // F24 // Misc actions omitted below... case 133: push(',', ','); break; // case 134: push('=', '='); break; // case 158: push('\n', '\n'); break; // case 182: push('(', '('); break; // case 183: push(')', ')'); break; // case 184: push('{', '{'); break; // case 185: push('}', '}'); break; // case 186: push('\t', '\t'); break; // case 187: push('', ''); break; // Backspace case 188: push('A', 'A'); break; // case 189: push('B', 'B'); break; // case 190: push('C', 'C'); break; // case 191: push('D', 'D'); break; // case 192: push('E', 'E'); break; // case 193: push('F', 'F'); break; // case 195: push('^', '^'); break; // case 196: push('%', '%'); break; // case 197: push('<', '<'); break; // case 198: push('>', '>'); break; // case 199: push('&', '&'); break; // default: // There are many codes that are not currently handled here. push('', ''); break; } } keys.forEach(parse); return true; } /** * Detect keyboard rollover error * This occurs when the user has pressed too many keys for the * particular device to handle */ function parseErrorState(packet, state) { let states = 0; state.forEach((s) => { if (s === 1) { states += 1; } }); if (states >= 6) { packet.errorStatus = true; // eslint-disable-line no-param-reassign } } module.exports = keyboard;