From d2d1d1b4a6576e90db0491e29c936543efc083a4 Mon Sep 17 00:00:00 2001 From: Michael Dreher Date: Sat, 13 Jul 2013 16:55:33 +0200 Subject: [PATCH] Added Keyboard.pressRaw(), releaseRaw() and writeRaw() to make it possible to send other keys than just ASCII --- hardware/keyboardio/cores/keyboardio/HID.cpp | 128 ++++++++++-------- hardware/keyboardio/cores/keyboardio/USBAPI.h | 3 + .../keyboardio/cores/keyboardio/USBCore.cpp | 50 +++++-- 3 files changed, 115 insertions(+), 66 deletions(-) diff --git a/hardware/keyboardio/cores/keyboardio/HID.cpp b/hardware/keyboardio/cores/keyboardio/HID.cpp index f216a85e..84870c0a 100644 --- a/hardware/keyboardio/cores/keyboardio/HID.cpp +++ b/hardware/keyboardio/cores/keyboardio/HID.cpp @@ -90,6 +90,7 @@ const u8 _hidReportDescriptor[] = { 0x85, HID_REPORTID_KEYBOARD, // REPORT_ID (2) 0x05, 0x07, // USAGE_PAGE (Keyboard) + // Keyboard Modifiers (shift, alt, ...) 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) 0x15, 0x00, // LOGICAL_MINIMUM (0) @@ -102,14 +103,14 @@ const u8 _hidReportDescriptor[] = { 0x75, 0x08, // REPORT_SIZE (8) 0x81, 0x03, // INPUT (Cnst,Var,Abs) + // Keyboard keys 0x95, 0x06, // REPORT_COUNT (6) 0x75, 0x08, // REPORT_SIZE (8) 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x65, // LOGICAL_MAXIMUM (101) + 0x26, 0xDF, 0x00, // LOGICAL_MAXIMUM (239) 0x05, 0x07, // USAGE_PAGE (Keyboard) - 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) - 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) + 0x29, 0xDF, // USAGE_MAXIMUM (Left Control - 1) 0x81, 0x00, // INPUT (Data,Ary,Abs) 0xc0, // END_COLLECTION @@ -571,9 +572,33 @@ uint8_t USBPutChar(uint8_t c); // to the persistent key report and sends the report. Because of the way // USB HID works, the host acts like the key remains pressed until we // call release(), releaseAll(), or otherwise clear the report and resend. -size_t Keyboard_::press(uint8_t k) +size_t Keyboard_::pressRaw(uint8_t k) { uint8_t i; + // Add k to the key report only if it's not already present + // and if there is an empty slot. + if (_keyReport.keys[0] != k && _keyReport.keys[1] != k && + _keyReport.keys[2] != k && _keyReport.keys[3] != k && + _keyReport.keys[4] != k && _keyReport.keys[5] != k) { + + for (i=0; i<6; i++) { + if (_keyReport.keys[i] == 0x00) { + _keyReport.keys[i] = k; + break; + } + } + if (i == 6 || (k >= 0xE0)) { + setWriteError(); + return 0; + } + } + sendReport(&_keyReport); + return 1; +} + +// translates ASCII characters to usage +size_t Keyboard_::press(uint8_t k) +{ if (k >= 136) { // it's a non-printing key (not a modifier) k = k - 136; } else if (k >= 128) { // it's a modifier key @@ -590,28 +615,48 @@ size_t Keyboard_::press(uint8_t k) k &= 0x7F; } } - - // Add k to the key report only if it's not already present - // and if there is an empty slot. - if (_keyReport.keys[0] != k && _keyReport.keys[1] != k && - _keyReport.keys[2] != k && _keyReport.keys[3] != k && - _keyReport.keys[4] != k && _keyReport.keys[5] != k) { - - for (i=0; i<6; i++) { - if (_keyReport.keys[i] == 0x00) { - _keyReport.keys[i] = k; - break; - } + return pressRaw(k); +} + +// release() takes the specified key out of the persistent key report and +// sends the report. This tells the OS the key is no longer pressed and that +// it shouldn't be repeated any more. +size_t Keyboard_::releaseRaw(uint8_t k) +{ + uint8_t i; + // Test the key report to see if k is present. Clear it if it exists. + // Check all positions in case the key is present more than once (which it shouldn't be) + for (i=0; i<6; i++) { + if (0 != k && _keyReport.keys[i] == k) { + _keyReport.keys[i] = 0x00; } - if (i == 6) { - setWriteError(); - return 0; - } } + sendReport(&_keyReport); return 1; } +// translates ASCII characters to usage +size_t Keyboard_::release(uint8_t k) +{ + if (k >= 136) { // it's a non-printing key (not a modifier) + k = k - 136; + } else if (k >= 128) { // it's a modifier key + _keyReport.modifiers &= ~(1<<(k-128)); + k = 0; + } else { // it's a printing key + k = pgm_read_byte(_asciimap + k); + if (!k) { + return 0; + } + if (k & 0x80) { // it's a capital letter or other character reached with shift + _keyReport.modifiers &= ~(0x02); // the left shift modifier + k &= 0x7F; + } + } + return releaseRaw(k); +} + // System Control // k is one of the SYSTEM_CONTROL defines which come from the HID usage table "Generic Desktop Page (0x01)" // in "HID Usage Tables" (HUT1_12v2.pdf) @@ -644,40 +689,6 @@ size_t Keyboard_::systemControl(uint8_t k) } } -// release() takes the specified key out of the persistent key report and -// sends the report. This tells the OS the key is no longer pressed and that -// it shouldn't be repeated any more. -size_t Keyboard_::release(uint8_t k) -{ - uint8_t i; - if (k >= 136) { // it's a non-printing key (not a modifier) - k = k - 136; - } else if (k >= 128) { // it's a modifier key - _keyReport.modifiers &= ~(1<<(k-128)); - k = 0; - } else { // it's a printing key - k = pgm_read_byte(_asciimap + k); - if (!k) { - return 0; - } - if (k & 0x80) { // it's a capital letter or other character reached with shift - _keyReport.modifiers &= ~(0x02); // the left shift modifier - k &= 0x7F; - } - } - - // Test the key report to see if k is present. Clear it if it exists. - // Check all positions in case the key is present more than once (which it shouldn't be) - for (i=0; i<6; i++) { - if (0 != k && _keyReport.keys[i] == k) { - _keyReport.keys[i] = 0x00; - } - } - - sendReport(&_keyReport); - return 1; -} - void Keyboard_::releaseAll(void) { _keyReport.keys[0] = 0; @@ -690,10 +701,17 @@ void Keyboard_::releaseAll(void) sendReport(&_keyReport); } +size_t Keyboard_::writeRaw(uint8_t c) +{ + uint8_t p = pressRaw(c); // Keydown + releaseRaw(c); // Keyup + return (p); // just return the result of press() since release() almost always returns 1 +} + size_t Keyboard_::write(uint8_t c) { uint8_t p = press(c); // Keydown - uint8_t r = release(c); // Keyup + release(c); // Keyup return (p); // just return the result of press() since release() almost always returns 1 } diff --git a/hardware/keyboardio/cores/keyboardio/USBAPI.h b/hardware/keyboardio/cores/keyboardio/USBAPI.h index bd205097..2a6d72b8 100644 --- a/hardware/keyboardio/cores/keyboardio/USBAPI.h +++ b/hardware/keyboardio/cores/keyboardio/USBAPI.h @@ -155,8 +155,11 @@ public: void begin(void); void end(void); virtual size_t write(uint8_t k); + virtual size_t writeRaw(uint8_t c); virtual size_t press(uint8_t k); + virtual size_t pressRaw(uint8_t k); virtual size_t release(uint8_t k); + virtual size_t releaseRaw(uint8_t k); virtual void releaseAll(void); virtual size_t systemControl(uint8_t k); }; diff --git a/hardware/keyboardio/cores/keyboardio/USBCore.cpp b/hardware/keyboardio/cores/keyboardio/USBCore.cpp index 558a57ab..fc867f31 100644 --- a/hardware/keyboardio/cores/keyboardio/USBCore.cpp +++ b/hardware/keyboardio/cores/keyboardio/USBCore.cpp @@ -24,13 +24,13 @@ #if defined(USBCON) -#define EP_TYPE_CONTROL 0x00 -#define EP_TYPE_BULK_IN 0x81 -#define EP_TYPE_BULK_OUT 0x80 -#define EP_TYPE_INTERRUPT_IN 0xC1 -#define EP_TYPE_INTERRUPT_OUT 0xC0 -#define EP_TYPE_ISOCHRONOUS_IN 0x41 -#define EP_TYPE_ISOCHRONOUS_OUT 0x40 +#define EP_TYPE_CONTROL (0x00) +#define EP_TYPE_BULK_IN ((1<