add support for a single button mouse
Signed-off-by: Szymon Łopaciuk <szymon@lopaciuk.eu>
This commit is contained in:
@@ -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
@@ -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(®3.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
@@ -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 <typename T>
|
||||
union adb_kb_data {
|
||||
union adb_data {
|
||||
uint16_t raw;
|
||||
T data;
|
||||
};
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
Reference in New Issue
Block a user