add support for a single button mouse

Signed-off-by: Szymon Łopaciuk <szymon@lopaciuk.eu>
This commit is contained in:
Szymon Łopaciuk
2021-03-08 20:47:54 +00:00
parent 7bee9cdcb1
commit a256728675
8 changed files with 133 additions and 32 deletions
+3
View File
@@ -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.
+25 -15
View File
@@ -7,34 +7,36 @@
#include "hid_keyboard.h"
#include "adb_structures.h"
adb_kb_data<adb_kb_modifiers> adb_keyboard_read_modifiers(bool* error) {
adb_kb_data<adb_kb_modifiers> modifiers = {0};
adb_write_command(ADB_CMD_TALK | ADB_ADDRESS(2) | ADB_REGISTER(2));
#define ADB_POLL_DELAY 5
adb_data<adb_kb_modifiers> adb_keyboard_read_modifiers(bool* error) {
adb_data<adb_kb_modifiers> 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_kb_keypress> adb_keyboard_read_key_press(bool* error) {
adb_kb_data<adb_kb_keypress> key_press = {0};
adb_write_command(ADB_CMD_TALK | ADB_ADDRESS(2) | ADB_REGISTER(0));
adb_data<adb_kb_keypress> adb_keyboard_read_key_press(bool* error) {
adb_data<adb_kb_keypress> 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_register3> adb_keyboard_read_register3(bool* error) {
adb_kb_data<adb_register3> reg3 = {0};
adb_write_command(ADB_CMD_TALK | ADB_ADDRESS(2) | ADB_REGISTER(3));
adb_data<adb_register3> adb_device_read_register3(uint8_t addr, bool* error) {
adb_data<adb_register3> reg3 = {0};
adb_write_command(ADB_CMD_TALK | ADB_ADDRESS(addr) | ADB_REGISTER(3));
adb_wait_tlt(true);
*error = !adb_read_data_packet(&reg3.raw, 16);
return reg3;
}
bool adb_keyboard_update_register3(adb_kb_data<adb_register3> new_reg3, uint16_t mask, bool* error) {
bool adb_device_update_register3(uint8_t addr, adb_data<adb_register3> new_reg3, uint16_t mask, bool* error) {
// Read the initial value
adb_kb_data<adb_register3> reg3 = adb_keyboard_read_register3(error);
adb_data<adb_register3> 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<adb_register3> 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<adb_register3> new_reg3, uint16_t
}
void adb_keyboard_write_leds(bool scroll, bool caps, bool num) {
adb_kb_data<adb_kb_modifiers> modifiers = {0};
adb_data<adb_kb_modifiers> 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_data> adb_mouse_read_data(bool* error) {
adb_data<adb_mouse_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
+12 -2
View File
@@ -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; // 53
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 <typename T>
union adb_kb_data {
union adb_data {
uint16_t raw;
T data;
};
+8 -4
View File
@@ -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<adb_kb_keypress> key_press) {
hid_key_report* report, adb_data<adb_kb_keypress> 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<adb_kb_keypress> reg) {
hid_key_report* report, adb_data<adb_kb_keypress> 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
+2 -2
View File
@@ -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<adb_kb_keypress> reg);
bool hid_keyboard_set_modifiers_from_adb_register(hid_key_report* report, adb_kb_data<adb_kb_keypress> reg);
bool hid_keyboard_set_keys_from_adb_register(hid_key_report* report, adb_data<adb_kb_keypress> reg);
bool hid_keyboard_set_modifiers_from_adb_register(hid_key_report* report, adb_data<adb_kb_keypress> 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);
+29
View File
@@ -0,0 +1,29 @@
#include "hid_mouse.h"
#include "usbd_hid_composite_if.h"
#include <Arduino.h>
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
}
+10
View File
@@ -0,0 +1,10 @@
#ifndef HID_MOUSE_h
#define HID_MOUSE_h
#include <cstdint>
void hid_mouse_init();
void hid_mouse_close();
void hid_mouse_send_report(bool button, int8_t offset_x, int8_t offset_y);
#endif
+44 -9
View File
@@ -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<adb_register3> reg3 = {0}, mask = {0};
adb_data<adb_register3> 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