diff --git a/USBHost_t36.h b/USBHost_t36.h index cfbe277..c3ec10b 100644 --- a/USBHost_t36.h +++ b/USBHost_t36.h @@ -56,7 +56,7 @@ // your best effort to read chapter 4 before asking USB questions! -// #define USBHOST_PRINT_DEBUG +//#define USBHOST_PRINT_DEBUG /************************************************/ /* Data Types */ @@ -88,6 +88,31 @@ typedef struct Transfer_struct Transfer_t; class USBDriver; class USBDriverTimer; +/************************************************/ +/* Added Defines */ +/************************************************/ +#define KEYD_UP 0xDA +#define KEYD_DOWN 0xD9 +#define KEYD_LEFT 0xD8 +#define KEYD_RIGHT 0xD7 +#define KEYD_INSERT 0xD1 +#define KEYD_DELETE 0xD4 +#define KEYD_PAGE_UP 0xD3 +#define KEYD_PAGE_DOWN 0xD6 +#define KEYD_HOME 0xD2 +#define KEYD_END 0xD5 +#define KEYD_F1 0xC2 +#define KEYD_F2 0xC3 +#define KEYD_F3 0xC4 +#define KEYD_F4 0xC5 +#define KEYD_F5 0xC6 +#define KEYD_F6 0xC7 +#define KEYD_F7 0xC8 +#define KEYD_F8 0xC9 +#define KEYD_F9 0xCA +#define KEYD_F10 0xCB +#define KEYD_F11 0xCC +#define KEYD_F12 0xCD /************************************************/ /* Data Structure Definitions */ @@ -508,7 +533,7 @@ public: static void driver_ready_for_hid_collection(USBHIDInput *driver); protected: enum { TOPUSAGE_LIST_LEN = 4 }; - enum { USAGE_LIST_LEN = 12 }; + enum { USAGE_LIST_LEN = 24 }; virtual bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len); virtual void control(const Transfer_t *transfer); virtual void disconnect(); @@ -763,6 +788,7 @@ protected: private: uint8_t collections_claimed = 0; volatile bool mouseEvent = false; + volatile bool hid_input_begin_ = false; uint8_t buttons = 0; int mouseX = 0; int mouseY = 0; @@ -792,4 +818,33 @@ private: int16_t axis[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; }; + +class KeyboardHIDExtrasController : public USBHIDInput { +public: + KeyboardHIDExtrasController(USBHost &host) { USBHIDParser::driver_ready_for_hid_collection(this); } + void clear() { event_ = false;} + bool available() { return event_; } + void attachPress(void (*f)(uint32_t top, uint16_t code)) { keyPressedFunction = f; } + void attachRelease(void (*f)(uint32_t top, uint16_t code)) { keyReleasedFunction = f; } + enum {MAX_KEYS_DOWN=4}; +// uint32_t buttons() { return buttons_; } +protected: + virtual bool claim_collection(Device_t *dev, uint32_t topusage); + virtual void hid_input_begin(uint32_t topusage, uint32_t type, int lgmin, int lgmax); + virtual void hid_input_data(uint32_t usage, int32_t value); + virtual void hid_input_end(); + virtual void disconnect_collection(Device_t *dev); +private: + void (*keyPressedFunction)(uint32_t top, uint16_t code); + void (*keyReleasedFunction)(uint32_t top, uint16_t code); + uint32_t topusage_ = 0; // What top report am I processing? + uint8_t collections_claimed_ = 0; + volatile bool event_ = false; + volatile bool hid_input_begin_ = false; + volatile bool hid_input_data_ = false; // did we receive any valid data with report? + uint8_t count_keys_down_ = 0; + uint16_t keys_down[MAX_KEYS_DOWN]; +}; + + #endif diff --git a/examples/Mouse/Mouse.ino b/examples/Mouse/Mouse.ino index 0a72fff..a5836dd 100644 --- a/examples/Mouse/Mouse.ino +++ b/examples/Mouse/Mouse.ino @@ -10,6 +10,7 @@ USBHub hub2(myusb); USBHub hub3(myusb); KeyboardController keyboard1(myusb); KeyboardController keyboard2(myusb); +KeyboardHIDExtrasController hidextras(myusb); USBHIDParser hid1(myusb); USBHIDParser hid2(myusb); USBHIDParser hid3(myusb); @@ -25,6 +26,8 @@ void setup() myusb.begin(); keyboard1.attachPress(OnPress); keyboard2.attachPress(OnPress); + hidextras.attachPress(OnHIDExtrasPress); + hidextras.attachRelease(OnHIDExtrasRelease); } @@ -68,16 +71,70 @@ void loop() } + void OnPress(int key) { - Serial.print("key '"); - Serial.print((char)key); - Serial.print("' "); - Serial.println(key); - //Serial.print("key "); - //Serial.print((char)keyboard1.getKey()); - //Serial.print(" "); - //Serial.print((char)keyboard2.getKey()); - //Serial.println(); + Serial.print("key '"); + switch (key) { + case KEYD_UP : Serial.print("UP"); break; + case KEYD_DOWN : Serial.print("DN"); break; + case KEYD_LEFT : Serial.print("LEFT"); break; + case KEYD_RIGHT : Serial.print("RIGHT"); break; + case KEYD_INSERT : Serial.print("Ins"); break; + case KEYD_DELETE : Serial.print("Del"); break; + case KEYD_PAGE_UP : Serial.print("PUP"); break; + case KEYD_PAGE_DOWN: Serial.print("PDN"); break; + case KEYD_HOME : Serial.print("HOME"); break; + case KEYD_END : Serial.print("END"); break; + case KEYD_F1 : Serial.print("F1"); break; + case KEYD_F2 : Serial.print("F2"); break; + case KEYD_F3 : Serial.print("F3"); break; + case KEYD_F4 : Serial.print("F4"); break; + case KEYD_F5 : Serial.print("F5"); break; + case KEYD_F6 : Serial.print("F6"); break; + case KEYD_F7 : Serial.print("F7"); break; + case KEYD_F8 : Serial.print("F8"); break; + case KEYD_F9 : Serial.print("F9"); break; + case KEYD_F10 : Serial.print("F10"); break; + case KEYD_F11 : Serial.print("F11"); break; + case KEYD_F12 : Serial.print("F12"); break; + default: Serial.print((char)key); break; + } + Serial.print("' "); + Serial.print(key); + Serial.print(" MOD: "); + if (keyboard1) { + Serial.print(keyboard1.getModifiers(), HEX); + Serial.print(" OEM: "); + Serial.print(keyboard1.getOemKey(), HEX); + Serial.print(" LEDS: "); + Serial.println(keyboard1.LEDS(), HEX); + } else { + Serial.print(keyboard2.getModifiers(), HEX); + Serial.print(" OEM: "); + Serial.print(keyboard2.getOemKey(), HEX); + Serial.print(" LEDS: "); + Serial.println(keyboard2.LEDS(), HEX); + } + + //Serial.print("key "); + //Serial.print((char)keyboard1.getKey()); + //Serial.print(" "); + //Serial.print((char)keyboard2.getKey()); + //Serial.println(); +} +void OnHIDExtrasPress(uint32_t top, uint16_t key) +{ + Serial.print("HID ("); + Serial.print(top, HEX); + Serial.print(") key press:"); + Serial.println(key, HEX); } +void OnHIDExtrasRelease(uint32_t top, uint16_t key) +{ + Serial.print("HID ("); + Serial.print(top, HEX); + Serial.print(") key release:"); + Serial.println(key, HEX); +} diff --git a/hid.cpp b/hid.cpp index 94f855f..829052d 100644 --- a/hid.cpp +++ b/hid.cpp @@ -57,6 +57,10 @@ bool USBHIDParser::claim(Device_t *dev, int type, const uint8_t *descriptors, ui // do not claim boot protocol keyboards if (descriptors[6] == 1 && descriptors[7] == 1) return false; + print("HID Parser Claim: "); + print_hexbytes(descriptors, len); + + // hid interface descriptor uint32_t hidlen = descriptors[9]; if (hidlen < 9) return false; @@ -198,6 +202,14 @@ void USBHIDParser::disconnect() // Called when the HID device sends a report void USBHIDParser::in_data(const Transfer_t *transfer) { + /*Serial.print("HID: "); + uint8_t *pb = (uint8_t*)transfer->buffer; + for (uint8_t i = 0; i < transfer->length; i++) { + Serial.print(pb[i], HEX); + Serial.print(" "); + } + Serial.println(); */ + print("HID: "); print_hexbytes(transfer->buffer, transfer->length); const uint8_t *buf = (const uint8_t *)transfer->buffer; @@ -531,6 +543,10 @@ void USBHIDParser::parse(uint16_t type_and_report_id, const uint8_t *data, uint3 print(" usage = ", u, HEX); println(" data = 1"); driver->hid_input_data(u, 1); + } else { + print (" usage =", u, HEX); + print(" out of range: ", logical_min, HEX); + println(" ", logical_max, HEX); } bitindex += report_size; } diff --git a/keyboard.cpp b/keyboard.cpp index 4fddb9a..d3850c2 100644 --- a/keyboard.cpp +++ b/keyboard.cpp @@ -44,7 +44,29 @@ typedef struct { keycode_extra_t keycode_extras[] = { {M(KEY_ENTER), '\n'}, {M(KEY_ESC), 0x1b}, - {M(KEY_TAB), 0x9 } + {M(KEY_TAB), 0x9 }, + {M(KEY_UP), KEYD_UP }, + {M(KEY_DOWN), KEYD_DOWN }, + {M(KEY_LEFT), KEYD_LEFT }, + {M(KEY_RIGHT), KEYD_RIGHT }, + {M(KEY_INSERT), KEYD_INSERT }, + {M(KEY_DELETE), KEYD_DELETE }, + {M(KEY_PAGE_UP), KEYD_PAGE_UP }, + {M(KEY_PAGE_DOWN), KEYD_PAGE_DOWN }, + {M(KEY_HOME), KEYD_HOME }, + {M(KEY_END), KEYD_END }, + {M(KEY_F1), KEYD_F1 }, + {M(KEY_F2), KEYD_F2 }, + {M(KEY_F3), KEYD_F3 }, + {M(KEY_F4), KEYD_F4 }, + {M(KEY_F5), KEYD_F5 }, + {M(KEY_F6), KEYD_F6 }, + {M(KEY_F7), KEYD_F7 }, + {M(KEY_F8), KEYD_F8 }, + {M(KEY_F9), KEYD_F9 }, + {M(KEY_F10), KEYD_F10 }, + {M(KEY_F11), KEYD_F11 }, + {M(KEY_F12), KEYD_F12 } }; // Some of these mapped to key + shift. @@ -242,9 +264,10 @@ void KeyboardController::key_release(uint32_t mod, uint32_t key) uint16_t KeyboardController::convert_to_unicode(uint32_t mod, uint32_t key) { - // TODO: special keys - // TODO: caps lock + // WIP: special keys // TODO: dead key sequences + + if (key & SHIFT_MASK) { // Many of these keys will look like they are other keys with shift mask... // Check for any of our mapped extra keys @@ -261,11 +284,19 @@ uint16_t KeyboardController::convert_to_unicode(uint32_t mod, uint32_t key) } } } - - // If we made it here without doing something then return 0; - if (key & SHIFT_MASK) return 0; } + // Check for any of our mapped extra keys - Done early as some of these keys are + // above and some below the SHIFT_MASK value + for (uint8_t i = 0; i < (sizeof(keycode_extras)/sizeof(keycode_extras[0])); i++) { + if (keycode_extras[i].code == key) { + return keycode_extras[i].ascii; + } + } + + // If we made it here without doing something then return 0; + if (key & SHIFT_MASK) return 0; + if ((mod & 0x02) || (mod & 0x20)) key |= SHIFT_MASK; if (leds_.capsLock) key ^= SHIFT_MASK; // Caps lock will switch the Shift; for (int i=0; i < 96; i++) { @@ -275,12 +306,6 @@ uint16_t KeyboardController::convert_to_unicode(uint32_t mod, uint32_t key) } } - // Check for any of our mapped extra keys - for (uint8_t i = 0; i < (sizeof(keycode_extras)/sizeof(keycode_extras[0])); i++) { - if (keycode_extras[i].code == key) { - return keycode_extras[i].ascii; - } - } #ifdef ISO_8859_1_A0 for (int i=0; i < 96; i++) { diff --git a/keyboardHIDExtras.cpp b/keyboardHIDExtras.cpp new file mode 100644 index 0000000..0ccc2b3 --- /dev/null +++ b/keyboardHIDExtras.cpp @@ -0,0 +1,118 @@ +/* USB keyboard power Host for Teensy 3.6 + * Copyright 2017 Paul Stoffregen (paul@pjrc.com) + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "USBHost_t36.h" // Read this header first for key info + +#define TOPUSAGE_SYS_CONTROL 0x10080 +#define TOPUSAGE_CONSUMER_CONTROL 0x0c0001 + +bool KeyboardHIDExtrasController::claim_collection(Device_t *dev, uint32_t topusage) +{ + // Lets try to claim a few specific Keyboard related collection/reports + if ((topusage != TOPUSAGE_SYS_CONTROL) && (topusage != TOPUSAGE_CONSUMER_CONTROL)) return false; + // only claim from one physical device + //Serial.println("KeyboardHIDExtrasController claim collection"); + if (mydevice != NULL && dev != mydevice) return false; + mydevice = dev; + collections_claimed_++; + return true; +} + +void KeyboardHIDExtrasController::disconnect_collection(Device_t *dev) +{ + if (--collections_claimed_ == 0) { + mydevice = NULL; + } +} + +void KeyboardHIDExtrasController::hid_input_begin(uint32_t topusage, uint32_t type, int lgmin, int lgmax) +{ + //Serial.printf("KPC:hid_input_begin TUSE: %x TYPE: %x Range:%x %x\n", topusage, type, lgmin, lgmax); + topusage_ = topusage; // remember which report we are processing. + hid_input_begin_ = true; + hid_input_data_ = false; +} + +void KeyboardHIDExtrasController::hid_input_data(uint32_t usage, int32_t value) +{ + //Serial.printf("KeyboardHIDExtrasController: usage=%X, value=%d\n", usage, value); + + // See if the value is in our keys_down list + usage &= 0xffff; // only keep the actual key + if (usage == 0) return; // lets not process 0, if only 0 happens, we will handle it on the end to remove existing pressed items. + + // Remember if we have received any logical key up events. Some keyboard appear to send them + // others do no... + hid_input_data_ = true; + + uint8_t key_index; + for (key_index = 0; key_index < count_keys_down_; key_index++) { + if (keys_down[key_index] == usage) { + if (value) return; // still down + + if (keyReleasedFunction) { + keyReleasedFunction(topusage_, usage); + } + + // Remove from list + count_keys_down_--; + for (;key_index < count_keys_down_; key_index++) { + keys_down[key_index] = keys_down[key_index+1]; + } + return; + } + } + // Was not in list + if (!value) return; // still 0 + if (keyPressedFunction) { + keyPressedFunction(topusage_, usage); + } + if (count_keys_down_ < MAX_KEYS_DOWN) { + keys_down[count_keys_down_++] = usage; + } +} + +void KeyboardHIDExtrasController::hid_input_end() +{ + //Serial.println("KPC:hid_input_end"); + if (hid_input_begin_) { + + // See if we received any data from parser if not, assume all keys released... + if (!hid_input_data_ ) { + if (keyPressedFunction) { + while (count_keys_down_) { + count_keys_down_--; + keyReleasedFunction(topusage_, keys_down[count_keys_down_]); + } + } + count_keys_down_ = 0; + } + + event_ = true; + hid_input_begin_ = false; + } +} + + + diff --git a/mouse.cpp b/mouse.cpp index 46ef496..8ab1219 100644 --- a/mouse.cpp +++ b/mouse.cpp @@ -47,6 +47,7 @@ void MouseController::disconnect_collection(Device_t *dev) void MouseController::hid_input_begin(uint32_t topusage, uint32_t type, int lgmin, int lgmax) { // TODO: check if absolute coordinates + hid_input_begin_ = true; } void MouseController::hid_input_data(uint32_t usage, int32_t value) @@ -84,7 +85,10 @@ void MouseController::hid_input_data(uint32_t usage, int32_t value) void MouseController::hid_input_end() { - mouseEvent = true; + if (hid_input_begin_) { + mouseEvent = true; + hid_input_begin_ = false; + } } void MouseController::mouseDataClear() {