From a2567286758bc1af829ed845be4d9f2767b0ee88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20=C5=81opaciuk?= Date: Mon, 8 Mar 2021 20:47:54 +0000 Subject: [PATCH] add support for a single button mouse MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Szymon Łopaciuk --- src/adb.h | 3 +++ src/adb_devices.h | 40 ++++++++++++++++++++------------- src/adb_structures.h | 14 ++++++++++-- src/hid_keyboard.cpp | 12 ++++++---- src/hid_keyboard.h | 4 ++-- src/hid_mouse.cpp | 29 ++++++++++++++++++++++++ src/hid_mouse.h | 10 +++++++++ src/main.cpp | 53 ++++++++++++++++++++++++++++++++++++-------- 8 files changed, 133 insertions(+), 32 deletions(-) create mode 100644 src/hid_mouse.cpp create mode 100644 src/hid_mouse.h diff --git a/src/adb.h b/src/adb.h index 2633d9e..4f498f8 100644 --- a/src/adb.h +++ b/src/adb.h @@ -15,6 +15,9 @@ #define ADB_CMD_LISTEN (0b10 << 2) #define ADB_CMD_FLUSH (0b01 << 2) +#define ADB_ADDR_KEYBOARD 2 +#define ADB_ADDR_MOUSE 3 + #define ADB_BIT_ERROR 0xFF // Reset: signal low for 3 ms. diff --git a/src/adb_devices.h b/src/adb_devices.h index 2bd6632..0830cb8 100644 --- a/src/adb_devices.h +++ b/src/adb_devices.h @@ -7,34 +7,36 @@ #include "hid_keyboard.h" #include "adb_structures.h" -adb_kb_data adb_keyboard_read_modifiers(bool* error) { - adb_kb_data modifiers = {0}; - adb_write_command(ADB_CMD_TALK | ADB_ADDRESS(2) | ADB_REGISTER(2)); +#define ADB_POLL_DELAY 5 + +adb_data adb_keyboard_read_modifiers(bool* error) { + adb_data modifiers = {0}; + adb_write_command(ADB_CMD_TALK | ADB_ADDRESS(ADB_ADDR_KEYBOARD) | ADB_REGISTER(2)); adb_wait_tlt(true); *error = !adb_read_data_packet(&modifiers.raw, 16); return modifiers; } -adb_kb_data adb_keyboard_read_key_press(bool* error) { - adb_kb_data key_press = {0}; - adb_write_command(ADB_CMD_TALK | ADB_ADDRESS(2) | ADB_REGISTER(0)); +adb_data adb_keyboard_read_key_press(bool* error) { + adb_data key_press = {0}; + adb_write_command(ADB_CMD_TALK | ADB_ADDRESS(ADB_ADDR_KEYBOARD) | ADB_REGISTER(0)); adb_wait_tlt(true); *error = !adb_read_data_packet(&key_press.raw, 16); return key_press; } -adb_kb_data adb_keyboard_read_register3(bool* error) { - adb_kb_data reg3 = {0}; - adb_write_command(ADB_CMD_TALK | ADB_ADDRESS(2) | ADB_REGISTER(3)); +adb_data adb_device_read_register3(uint8_t addr, bool* error) { + adb_data reg3 = {0}; + adb_write_command(ADB_CMD_TALK | ADB_ADDRESS(addr) | ADB_REGISTER(3)); adb_wait_tlt(true); *error = !adb_read_data_packet(®3.raw, 16); return reg3; } -bool adb_keyboard_update_register3(adb_kb_data new_reg3, uint16_t mask, bool* error) { +bool adb_device_update_register3(uint8_t addr, adb_data new_reg3, uint16_t mask, bool* error) { // Read the initial value - adb_kb_data reg3 = adb_keyboard_read_register3(error); + adb_data reg3 = adb_device_read_register3(addr, error); if (*error) return false; delay(ADB_POLL_DELAY); @@ -42,13 +44,13 @@ bool adb_keyboard_update_register3(adb_kb_data new_reg3, uint16_t reg3.raw = (reg3.raw & ~mask) | (new_reg3.raw & mask); // Write the new value - adb_write_command(ADB_CMD_LISTEN | ADB_ADDRESS(2) | ADB_REGISTER(3)); + adb_write_command(ADB_CMD_LISTEN | ADB_ADDRESS(addr) | ADB_REGISTER(3)); adb_wait_tlt(false); adb_write_data_packet(reg3.raw, 16); delay(ADB_POLL_DELAY); // Read the current value - reg3 = adb_keyboard_read_register3(error); + reg3 = adb_device_read_register3(addr, error); if (*error) return false; // Check if update worked, return true @@ -59,14 +61,22 @@ bool adb_keyboard_update_register3(adb_kb_data new_reg3, uint16_t } void adb_keyboard_write_leds(bool scroll, bool caps, bool num) { - adb_kb_data modifiers = {0}; + adb_data modifiers = {0}; modifiers.data.led_scroll = !scroll; modifiers.data.led_caps = !caps; modifiers.data.led_num = !num; - adb_write_command(ADB_CMD_LISTEN | ADB_ADDRESS(2) | ADB_REGISTER(2)); + adb_write_command(ADB_CMD_LISTEN | ADB_ADDRESS(ADB_ADDR_KEYBOARD) | ADB_REGISTER(2)); adb_wait_tlt(false); adb_write_data_packet(modifiers.raw, 16); } +adb_data adb_mouse_read_data(bool* error) { + adb_data mouse_data = {0}; + adb_write_command(ADB_CMD_TALK | ADB_ADDRESS(ADB_ADDR_MOUSE) | ADB_REGISTER(0)); + adb_wait_tlt(true); + *error = !adb_read_data_packet(&mouse_data.raw, 16); + return mouse_data; +} + #endif \ No newline at end of file diff --git a/src/adb_structures.h b/src/adb_structures.h index 22e64eb..481fbc9 100644 --- a/src/adb_structures.h +++ b/src/adb_structures.h @@ -18,6 +18,9 @@ #define ADB_KEY_RIGHT_COMMAND 0x37 #define ADB_KEY_CAPS_LOCK 0x39 +// Convert axis from 7b 2's complement to int8_t +#define ADB_MOUSE_CONV_AXIS(x) (int8_t)(x << 1) + struct adb_kb_keypress { uint8_t key1 : 7; bool released1 : 1; @@ -30,7 +33,7 @@ struct adb_kb_modifiers { bool led_num : 1; // 0, ditto bool led_caps : 1; // 1, ditto bool led_scroll : 1; // 2, changeable with `listen' command - uint8_t reserved1 : 3; // 5–3 + uint8_t reserved1 : 3; // 5 – 3 bool scroll_lock : 1; // 6 bool num_lock : 1; // 7 // Apple Standard Keyboard: @@ -44,6 +47,13 @@ struct adb_kb_modifiers { uint8_t reserved0 : 1; // 15 }; +struct adb_mouse_data { + uint8_t x_offset : 7; // 6 - 0 + uint8_t reserved0 : 1; // 7 + uint8_t y_offset : 7; // 14 - 8 + bool button : 1; // 15 +}; + // Contains device info and params struct adb_register3 { uint8_t device_handler_id : 8; @@ -55,7 +65,7 @@ struct adb_register3 { }; template -union adb_kb_data { +union adb_data { uint16_t raw; T data; }; diff --git a/src/hid_keyboard.cpp b/src/hid_keyboard.cpp index 6f26d83..10e546f 100644 --- a/src/hid_keyboard.cpp +++ b/src/hid_keyboard.cpp @@ -5,12 +5,16 @@ void hid_keyboard_init() { +#ifdef PIO_FRAMEWORK_ARDUINO_ENABLE_HID HID_Composite_Init(HID_KEYBOARD); +#endif } void hid_keyboard_close() { +#ifdef PIO_FRAMEWORK_ARDUINO_ENABLE_HID HID_Composite_DeInit(HID_KEYBOARD); +#endif } void hid_keyboard_send_report(hid_key_report* report) @@ -19,11 +23,13 @@ void hid_keyboard_send_report(hid_key_report* report) report->keys[1], report->keys[2], report->keys[3], report->keys[4], report->keys[5] }; +#ifdef PIO_FRAMEWORK_ARDUINO_ENABLE_HID HID_Composite_keyboard_sendReport(buf, 8); +#endif } bool hid_keyboard_set_keys_from_adb_register( - hid_key_report* report, adb_kb_data key_press) { + hid_key_report* report, adb_data key_press) { // Power button is a special case, residing in both octets: if (key_press.raw == ADB_KEY_POWER_DOWN) return hid_keyboard_update_key_in_report(report, KEY_POWER, false); @@ -54,7 +60,7 @@ bool hid_keyboard_set_keys_from_adb_register( } bool hid_keyboard_set_modifiers_from_adb_register( - hid_key_report* report, adb_kb_data reg) { + hid_key_report* report, adb_data reg) { // TODO: don't seem necessary, as modifiers still register normal keypresses return false; } @@ -125,5 +131,3 @@ bool hid_keyboard_remove_key_from_report(hid_key_report* report, uint8_t hid_key } return report_changed; } - -//#endif \ No newline at end of file diff --git a/src/hid_keyboard.h b/src/hid_keyboard.h index 357a0de..64dc5cb 100644 --- a/src/hid_keyboard.h +++ b/src/hid_keyboard.h @@ -14,8 +14,8 @@ struct hid_key_report { void hid_keyboard_init(); void hid_keyboard_close(); void hid_keyboard_send_report(hid_key_report* report); -bool hid_keyboard_set_keys_from_adb_register(hid_key_report* report, adb_kb_data reg); -bool hid_keyboard_set_modifiers_from_adb_register(hid_key_report* report, adb_kb_data reg); +bool hid_keyboard_set_keys_from_adb_register(hid_key_report* report, adb_data reg); +bool hid_keyboard_set_modifiers_from_adb_register(hid_key_report* report, adb_data reg); bool hid_keyboard_update_key_in_report(hid_key_report* report, uint8_t hid_keycode, bool released); bool hid_keyboard_update_modifier_in_report(hid_key_report* report, uint8_t adb_keycode, bool released); bool hid_keyboard_add_key_to_report(hid_key_report* report, uint8_t hid_keycode); diff --git a/src/hid_mouse.cpp b/src/hid_mouse.cpp new file mode 100644 index 0000000..a91e01e --- /dev/null +++ b/src/hid_mouse.cpp @@ -0,0 +1,29 @@ +#include "hid_mouse.h" +#include "usbd_hid_composite_if.h" +#include + +void hid_mouse_init() +{ +#ifdef PIO_FRAMEWORK_ARDUINO_ENABLE_HID + HID_Composite_Init(HID_MOUSE); +#endif +} + +void hid_mouse_close() +{ +#ifdef PIO_FRAMEWORK_ARDUINO_ENABLE_HID + HID_Composite_DeInit(HID_MOUSE); +#endif +} + +void hid_mouse_send_report(bool button, int8_t offset_x, int8_t offset_y) { + uint8_t m[4]; + m[0] = button; + m[1] = offset_x; + m[2] = offset_y; + m[3] = 0; + +#ifdef PIO_FRAMEWORK_ARDUINO_ENABLE_HID + HID_Composite_mouse_sendReport(m, 4); +#endif +} \ No newline at end of file diff --git a/src/hid_mouse.h b/src/hid_mouse.h new file mode 100644 index 0000000..f164ac0 --- /dev/null +++ b/src/hid_mouse.h @@ -0,0 +1,10 @@ +#ifndef HID_MOUSE_h +#define HID_MOUSE_h + +#include + +void hid_mouse_init(); +void hid_mouse_close(); +void hid_mouse_send_report(bool button, int8_t offset_x, int8_t offset_y); + +#endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index e0cc4f2..a779388 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,11 +5,14 @@ #include "hid_tables.h" #include "adb_structures.h" #include "hid_keyboard.h" +#include "hid_mouse.h" #include "adb_devices.h" +#include "Mouse.h" #define POLL_DELAY 5 bool apple_extended_detected = false; +bool keyboard_present = false, mouse_present = false; #ifdef PIO_FRAMEWORK_ARDUINO_ENABLE_CDC void print16b(uint16_t buff) { @@ -55,17 +58,27 @@ void setup() { // Initialise the ADB devices // Switch the keyboard to Apple Extended if available bool error = false; - adb_kb_data reg3 = {0}, mask = {0}; + adb_data reg3 = {0}, mask = {0}; reg3.data.device_handler_id = 0x03; mask.data.device_handler_id = 0xFF; - apple_extended_detected = adb_keyboard_update_register3(reg3, mask.raw, &error); + apple_extended_detected = adb_device_update_register3(ADB_ADDR_KEYBOARD, reg3, mask.raw, &error); + if (!error) keyboard_present = true, + + // Switch the mouse to higher resolution, if available + // TODO: Apple Extended Mouse Protocol (Handler = 4) + error = false; + reg3.raw = 0; + mask.raw = 0; + reg3.data.device_handler_id = 0x02; + mask.data.device_handler_id = 0xFF; + adb_device_update_register3(ADB_ADDR_MOUSE, reg3, mask.raw, &error); + if (!error) mouse_present = true; // Set-up successful, turn of the LED digitalWrite(PC13, HIGH); } -void loop() { - // TODO: Add proper polling based on SRQ +void keyboard_handler() { static bool led_caps = false; static hid_key_report key_report = {0}; bool error = false; @@ -109,13 +122,35 @@ void loop() { } // Send the finished report - if (report_changed) + //if (report_changed) hid_keyboard_send_report(&key_report); +} - // Wait a tiny bit before polling again, - // while ADB seems fairly tolarent of quick requests - // we don't want to overwhelm USB either - delay(POLL_DELAY); +void mouse_handler() { + bool error = false; + auto mouse_data = adb_mouse_read_data(&error); + + if (error || mouse_data.raw == 0) return; + + int8_t mouse_x = ADB_MOUSE_CONV_AXIS(mouse_data.data.x_offset); + int8_t mouse_y = ADB_MOUSE_CONV_AXIS(mouse_data.data.y_offset); + + hid_mouse_send_report(mouse_data.data.button ? 0 : 1, mouse_x, mouse_y); +} + +void loop() { + if (keyboard_present) { + keyboard_handler(); + // Wait a tiny bit before polling again, + // while ADB seems fairly tolerent of quick requests + // we don't want to overwhelm USB either + delay(POLL_DELAY); + } + + if (mouse_present) { + mouse_handler(); + delay(POLL_DELAY); + } } #endif \ No newline at end of file