|
|
@@ -23,6 +23,7 @@ |
|
|
|
|
|
|
|
#include <Arduino.h> |
|
|
|
#include "USBHost_t36.h" // Read this header first for key info |
|
|
|
#include "keylayouts.h" // from Teensyduino core library |
|
|
|
|
|
|
|
|
|
|
|
void KeyboardController::init() |
|
|
@@ -74,25 +75,110 @@ void KeyboardController::control(const Transfer_t *transfer) |
|
|
|
|
|
|
|
void KeyboardController::callback(const Transfer_t *transfer) |
|
|
|
{ |
|
|
|
println("KeyboardController Callback (static)"); |
|
|
|
//println("KeyboardController Callback (static)"); |
|
|
|
if (transfer->driver) { |
|
|
|
((KeyboardController *)(transfer->driver))->new_data(transfer); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void KeyboardController::disconnect() |
|
|
|
{ |
|
|
|
// TODO: free resources |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Arduino defined this static weak symbol callback, and their |
|
|
|
// examples use it as the only way to detect new key presses, |
|
|
|
// so unfortunate as static weak callbacks are, it probably |
|
|
|
// needs to be supported for compatibility |
|
|
|
extern "C" { |
|
|
|
void __keyboardControllerEmptyCallback() { } |
|
|
|
} |
|
|
|
void keyPressed() __attribute__ ((weak, alias("__keyboardControllerEmptyCallback"))); |
|
|
|
void keyReleased() __attribute__ ((weak, alias("__keyboardControllerEmptyCallback"))); |
|
|
|
|
|
|
|
static bool contains(uint8_t b, const uint8_t *data) |
|
|
|
{ |
|
|
|
if (data[2] == b || data[3] == b || data[4] == b) return true; |
|
|
|
if (data[5] == b || data[6] == b || data[7] == b) return true; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
void KeyboardController::new_data(const Transfer_t *transfer) |
|
|
|
{ |
|
|
|
println("KeyboardController Callback (member)"); |
|
|
|
print(" KB Data: "); |
|
|
|
print_hexbytes(transfer->buffer, 8); |
|
|
|
// TODO: parse the new data |
|
|
|
for (int i=2; i < 8; i++) { |
|
|
|
uint32_t key = prev_report[i]; |
|
|
|
if (key >= 4 && !contains(key, report)) { |
|
|
|
key_release(prev_report[0], key); |
|
|
|
} |
|
|
|
} |
|
|
|
for (int i=2; i < 8; i++) { |
|
|
|
uint32_t key = report[i]; |
|
|
|
if (key >= 4 && !contains(key, prev_report)) { |
|
|
|
key_press(report[0], key); |
|
|
|
} |
|
|
|
} |
|
|
|
memcpy(prev_report, report, 8); |
|
|
|
queue_Data_Transfer(datapipe, report, 8, this); |
|
|
|
} |
|
|
|
|
|
|
|
void KeyboardController::disconnect() |
|
|
|
void KeyboardController::key_press(uint32_t mod, uint32_t key) |
|
|
|
{ |
|
|
|
// TODO: free resources |
|
|
|
// TODO: queue events, perform callback from Task |
|
|
|
println(" press, key=", key); |
|
|
|
modifiers = mod; |
|
|
|
keyOEM = key; |
|
|
|
keyCode = convert_to_unicode(mod, key); |
|
|
|
println(" unicode = ", keyCode); |
|
|
|
if (keyPressedFunction) { |
|
|
|
keyPressedFunction(keyCode); |
|
|
|
} else { |
|
|
|
keyPressed(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void KeyboardController::key_release(uint32_t mod, uint32_t key) |
|
|
|
{ |
|
|
|
// TODO: queue events, perform callback from Task |
|
|
|
println(" release, key=", key); |
|
|
|
modifiers = mod; |
|
|
|
keyOEM = key; |
|
|
|
keyCode = convert_to_unicode(mod, key); |
|
|
|
if (keyReleasedFunction) { |
|
|
|
keyReleasedFunction(keyCode); |
|
|
|
} else { |
|
|
|
keyReleased(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
uint16_t KeyboardController::convert_to_unicode(uint32_t mod, uint32_t key) |
|
|
|
{ |
|
|
|
// TODO: special keys |
|
|
|
// TODO: caps lock |
|
|
|
// TODO: dead key sequences |
|
|
|
if ((mod & 0x02) || (mod & 0x20)) key |= SHIFT_MASK; |
|
|
|
for (int i=0; i < 96; i++) { |
|
|
|
if (keycodes_ascii[i] == key) return i + 32; |
|
|
|
} |
|
|
|
#ifdef ISO_8859_1_A0 |
|
|
|
for (int i=0; i < 96; i++) { |
|
|
|
if (keycodes_iso_8859_1[i] == key) return i + 160; |
|
|
|
} |
|
|
|
#endif |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|