X-Git-Url: https://git.friedersdorff.com/?a=blobdiff_plain;f=converter%2Fadb_usb%2Fmatrix.c;h=f4bf50c1f5af375f2da651f0af85e127e821616f;hb=e89ade52e105bcdcf949b63645c3df38935011b0;hp=c9113c3cee103a419308f557b04b521429048b0d;hpb=814eaa2dffa10f8b3a9f5c5ae6fab430322056d7;p=max%2Ftmk_keyboard.git diff --git a/converter/adb_usb/matrix.c b/converter/adb_usb/matrix.c index c9113c3c..f4bf50c1 100644 --- a/converter/adb_usb/matrix.c +++ b/converter/adb_usb/matrix.c @@ -21,7 +21,6 @@ along with this program. If not, see . #include #include #include -#include #include "print.h" #include "util.h" #include "debug.h" @@ -31,39 +30,57 @@ along with this program. If not, see . #include "host.h" #include "led.h" #include "timer.h" +#include "wait.h" static bool has_media_keys = false; static bool is_iso_layout = false; -static uint8_t mouse_handler = ADB_HANDLER_CLASSIC1_MOUSE; + +#if ADB_MOUSE_ENABLE +#define dmprintf(fmt, ...) do { /* if (debug_mouse) */ xprintf("M:" fmt, ##__VA_ARGS__); } while (0) +static uint16_t mouse_cpi = 100; +static void mouse_init(uint8_t addr); +#endif // matrix state buffer(1:on, 0:off) static matrix_row_t matrix[MATRIX_ROWS]; static void register_key(uint8_t key); +static void device_scan(void) +{ + xprintf("\nScan:\n"); + for (uint8_t addr = 0; addr < 16; addr++) { + uint16_t reg3 = adb_host_talk(addr, ADB_REG_3); + if (reg3) { + xprintf(" addr:%d, reg3:%04X\n", addr, reg3); + } + } +} void matrix_init(void) { + debug_enable = true; + //debug_matrix = true; + //debug_keyboard = true; + //debug_mouse = true; + // LED on DDRD |= (1<<6); PORTD |= (1<<6); adb_host_init(); - // wait for keyboard to boot up and receive command - _delay_ms(2000); - // device scan - xprintf("\nScan:\n"); - for (uint8_t addr = 1; addr < 16; addr++) { - uint16_t reg3 = adb_host_talk(addr, ADB_REG_3); - if (reg3) { - xprintf(" addr:%d, reg3:%04X\n", addr, reg3); - } - _delay_ms(20); - } + // AEK/AEKII(ANSI/ISO) startup is slower. Without proper delay + // it would fail to recognize layout and enable Extended protocol. + // 200ms seems to be enough for AEKs. 1000ms is used for safety. + // Tested with devices: + // M0115J(AEK), M3501(AEKII), M0116(Standard), M1242(Adjustable), + // G5431(Mouse), 64210(Kensington Trubo Mouse 5) + wait_ms(1000); + device_scan(); // // Keyboard @@ -82,7 +99,7 @@ void matrix_init(void) is_iso_layout = false; break; } - xprintf("hadler: %02X, ISO: %s\n", handler_id, (is_iso_layout ? "yes" : "no")); + xprintf("handler: %02X, ISO: %s\n", handler_id, (is_iso_layout ? "yes" : "no")); // Adjustable keyboard media keys: address=0x07 and handlerID=0x02 has_media_keys = (0x02 == (adb_host_talk(ADB_ADDR_APPLIANCE, ADB_REG_3) & 0xff)); @@ -96,24 +113,74 @@ void matrix_init(void) // lower byte: device handler 00000011 adb_host_listen(ADB_ADDR_KEYBOARD, ADB_REG_3, ADB_ADDR_KEYBOARD, ADB_HANDLER_EXTENDED_KEYBOARD); + // initialize matrix state: all keys off + for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; - #ifdef ADB_MOUSE_ENABLE - // - // Mouse - // - // https://developer.apple.com/library/archive/technotes/hw/hw_01.html#Extended - xprintf("\nMouse:\n"); + led_set(host_keyboard_leds()); + + device_scan(); + + // LED off + DDRD |= (1<<6); PORTD &= ~(1<<6); + return; +} + +#ifdef ADB_MOUSE_ENABLE +static void mouse_init(uint8_t orig_addr) +{ + uint16_t reg3; + uint8_t mouse_handler; + uint8_t addr; + +again: + // Move to tmp address 15 to setup mouse function + mouse_handler = (reg3 = adb_host_talk(orig_addr, ADB_REG_3)) & 0xFF; + if (!reg3) return; + dmprintf("addr%d reg3: %04X\n", orig_addr, reg3); + + // Move device to tmp address + adb_host_flush(orig_addr); + adb_host_listen(orig_addr, ADB_REG_3, ((reg3 >> 8) & 0xF0) | ADB_ADDR_TMP, 0xFE); + adb_host_flush(ADB_ADDR_TMP); + + mouse_handler = (reg3 = adb_host_talk(ADB_ADDR_TMP, ADB_REG_3)) & 0xFF; + if (!reg3) { + dmprintf("move fail\n"); + goto again; + } + addr = ADB_ADDR_TMP; + + +detect_again: + // Try to escalate into extended/classic2 protocol + if (mouse_handler == ADB_HANDLER_CLASSIC1_MOUSE || mouse_handler == ADB_HANDLER_CLASSIC2_MOUSE) { + adb_host_flush(addr); + adb_host_listen(addr, ADB_REG_3, (reg3 >> 8), ADB_HANDLER_EXTENDED_MOUSE); - // Some old mouses seems to need wait between commands. - _delay_ms(20); - adb_host_listen(ADB_ADDR_MOUSE, ADB_REG_3, ADB_ADDR_MOUSE, ADB_HANDLER_CLASSIC2_MOUSE); + mouse_handler = (reg3 = adb_host_talk(addr, ADB_REG_3)) & 0xFF; - _delay_ms(20); - adb_host_listen(ADB_ADDR_MOUSE, ADB_REG_3, ADB_ADDR_MOUSE, ADB_HANDLER_EXTENDED_MOUSE); - _delay_ms(20); - mouse_handler = adb_host_talk(ADB_ADDR_MOUSE, ADB_REG_3) & 0xff; - mouse_handler = mouse_handler ? mouse_handler : ADB_HANDLER_CLASSIC1_MOUSE; + if (mouse_handler == ADB_HANDLER_CLASSIC1_MOUSE) { + adb_host_flush(addr); + adb_host_listen(addr, ADB_REG_3, (reg3 >> 8), ADB_HANDLER_CLASSIC2_MOUSE); + + mouse_handler = (reg3 = adb_host_talk(addr, ADB_REG_3)) & 0xFF; + } + dmprintf("addr%d reg3: %04X\n", addr, reg3); + + } + + // Classic Protocol 100cpi + if (mouse_handler == ADB_HANDLER_CLASSIC1_MOUSE) { + xprintf("Classic 100cpi\n"); + mouse_cpi = 100; + } + + // Classic Protocol 200cpi + if (mouse_handler == ADB_HANDLER_CLASSIC2_MOUSE) { + xprintf("Classic 200cpi\n"); + mouse_cpi = 200; + } // Extended Mouse Protocol if (mouse_handler == ADB_HANDLER_EXTENDED_MOUSE) { @@ -124,67 +191,70 @@ void matrix_init(void) // 7 : num of buttons uint8_t len; uint8_t buf[8]; - len = adb_host_talk_buf(ADB_ADDR_MOUSE, ADB_REG_1, buf, sizeof(buf)); + len = adb_host_talk_buf(addr, ADB_REG_1, buf, sizeof(buf)); + + if (len > 5) { + mouse_cpi = (buf[4]<<8) | buf[5]; + } else { + mouse_cpi = 100; + } + if (len) { - xprintf("Devinfo: [", len); + xprintf("Ext: [", len); for (int8_t i = 0; i < len; i++) xprintf("%02X ", buf[i]); - xprintf("]\n"); + xprintf("] cpi=%d\n", mouse_cpi); } - // Kensington Turbo Mouse 5 - if (len == 8 && buf[0] == 0x4B && buf[1] == 0x4D && buf[2] == 0x4C && buf[3] == 0x31) { - xprintf("Turbo Mouse 5\n"); - - // Turbo Mouse command sequence to enable four buttons - // https://elixir.bootlin.com/linux/v4.4/source/drivers/macintosh/adbhid.c#L1176 - // https://github.com/NetBSD/src/blob/64b8a48e1288eb3902ed73113d157af50b2ec596/sys/arch/macppc/dev/ams.c#L261 - static uint8_t cmd1[] = { 0xE7, 0x8C, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x94 }; - static uint8_t cmd2[] = { 0xA5, 0x14, 0x00, 0x00, 0x69, 0xFF, 0xFF, 0x27 }; - - // configure with new address 9 - adb_host_listen(ADB_ADDR_MOUSE, ADB_REG_3, 0x69, 0xFE); - adb_host_flush(9); - adb_host_flush(ADB_ADDR_MOUSE); - adb_host_listen_buf(ADB_ADDR_MOUSE, ADB_REG_2, cmd1, sizeof(cmd1)); - adb_host_flush(ADB_ADDR_MOUSE); - adb_host_listen_buf(ADB_ADDR_MOUSE, ADB_REG_2, cmd2, sizeof(cmd2)); + // Kensington Turbo Mouse 5: default device + if (buf[0] == 0x4B && buf[1] == 0x4D && buf[2] == 0x4C && buf[3] == 0x31) { + xprintf("TM5: default\n"); + // Move it to addr0 to remove this device and get new device with handle id 50 on addr 3 + // and the new device on address 3 should be handled with command sequence later. + // + // Turbo Mouse 5 has one default device on addr3 as normal mouse at first, and another device + // with hander id 50 appears after the default device is moved from addr3. + // The mouse has the two devices at same time transiently in the result. The default device is + // removed automatically after the another device receives command sequence. + // NOTE: The mouse hangs if you try moving the two deivces to same address. + adb_host_flush(addr); + adb_host_listen(addr, ADB_REG_3, ((reg3 >> 8) & 0xF0) | ADB_ADDR_0, 0xFE); + } else { + xprintf("Unknown\n"); } - - // Add device specific init here } - mouse_handler = adb_host_talk(ADB_ADDR_MOUSE, ADB_REG_3) & 0xff; - mouse_handler = mouse_handler ? mouse_handler : ADB_HANDLER_CLASSIC1_MOUSE; - xprintf("handler: %d\n", mouse_handler); - #endif + // Kensington Turbo Mouse 5: setup + if (mouse_handler == ADB_HANDLER_TURBO_MOUSE) { + xprintf("TM5: ext\n"); - xprintf("\nScan:\n"); - for (uint8_t addr = 1; addr < 16; addr++) { - uint16_t reg3 = adb_host_talk(addr, ADB_REG_3); - if (reg3) { - xprintf(" addr:%d, reg3:%04X\n", addr, reg3); - } - _delay_ms(20); + // Kensington Turbo Mouse 5 command sequence to enable four buttons + // https://elixir.bootlin.com/linux/v4.4/source/drivers/macintosh/adbhid.c#L1176 + // https://github.com/NetBSD/src/blob/64b8a48e1288eb3902ed73113d157af50b2ec596/sys/arch/macppc/dev/ams.c#L261 + static uint8_t cmd1[] = { 0xE7, 0x8C, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x94 }; + static uint8_t cmd2[] = { 0xA5, 0x14, 0x00, 0x00, 0x69, 0xFF, 0xFF, 0x27 }; + + adb_host_flush(addr); + adb_host_listen_buf(addr, ADB_REG_2, cmd1, sizeof(cmd1)); + adb_host_flush(addr); + adb_host_listen_buf(addr, ADB_REG_2, cmd2, sizeof(cmd2)); } - // initialize matrix state: all keys off - for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; - led_set(host_keyboard_leds()); + // Move to address 10 for mouse polling + adb_host_flush(addr); + adb_host_listen(addr, ADB_REG_3, ((reg3 >> 8) & 0xF0) | ADB_ADDR_MOUSE_POLL, 0xFE); + adb_host_flush(ADB_ADDR_MOUSE_POLL); - debug_enable = true; - //debug_matrix = true; - //debug_keyboard = true; - debug_mouse = true; + mouse_handler = (reg3 = adb_host_talk(addr, ADB_REG_3)) & 0xFF; + if (reg3) { + dmprintf("detect again\n"); + goto detect_again; + } - // LED off - DDRD |= (1<<6); PORTD &= ~(1<<6); - return; + goto again; } -#ifdef ADB_MOUSE_ENABLE - #ifdef MAX #undef MAX #endif @@ -206,6 +276,13 @@ void adb_mouse_task(void) if (timer_elapsed(tick_ms) < 12) return; tick_ms = timer_read(); + static uint16_t detect_ms; + if (timer_elapsed(detect_ms) > 1000) { + detect_ms = timer_read(); + // check new device on addr3 + mouse_init(ADB_ADDR_MOUSE); + } + // Extended Mouse Protocol data can be 2-5 bytes // https://developer.apple.com/library/archive/technotes/hw/hw_01.html#Extended // @@ -218,13 +295,14 @@ void adb_mouse_task(void) // b--: Button state.(0: on, 1: off) // x--: X axis movement. // y--: Y axis movement. - len = adb_host_talk_buf(ADB_ADDR_MOUSE, ADB_REG_0, buf, sizeof(buf)); + len = adb_host_talk_buf(ADB_ADDR_MOUSE_POLL, ADB_REG_0, buf, sizeof(buf)); // If nothing received reset mouse acceleration, and quit. if (len < 2) { mouseacc = 1; return; }; + dmprintf("[%02X %02X %02X %02X %02X]\n", buf[0], buf[1], buf[2], buf[3], buf[4]); // Store off-buttons and 0-movements in unused bytes bool xneg = false; @@ -271,20 +349,14 @@ void adb_mouse_task(void) mouse_report.x = -MAX(-MAX(x, -127), -127); mouse_report.y = -MAX(-MAX(y, -127), -127); - if (debug_mouse) { - xprintf("Mouse raw: ["); - for (int8_t i = 0; i < len; i++) xprintf("%02X ", buf[i]); - xprintf("]\n"); - - xprintf("Mouse info["); - xprintf("B:%02X, X:%d(%d), Y:%d(%d), A:%d]\n", buttons, x, xx, y, yy, mouseacc); - } + dmprintf("[B:%02X X:%d(%d) Y:%d(%d) A:%d]\n", mouse_report.buttons, mouse_report.x, xx, mouse_report.y, yy, mouseacc); // Send result by usb. host_mouse_send(&mouse_report); + // TODO: acceleration curve is needed for precise operation? // increase acceleration of mouse - mouseacc += ( mouseacc < ADB_MOUSE_MAXACC ? 1 : 0 ); + mouseacc += ( mouseacc < (mouse_cpi < 200 ? ADB_MOUSE_MAXACC : ADB_MOUSE_MAXACC/2) ? 1 : 0 ); return; } @@ -372,12 +444,14 @@ uint8_t matrix_scan(void) register_key(0x7F); } else if (codes == 0xFFFF) { // power key release register_key(0xFF); - } else if (key0 == 0xFF) { // error - xprintf("adb_host_kbd_recv: ERROR(%d)\n", codes); - // something wrong or plug-in - matrix_init(); - return key1; } else { + // Macally keyboard sends keys inversely against ADB protocol + // https://deskthority.net/workshop-f7/macally-mk96-t20116.html + if (key0 == 0xFF) { + key0 = key1; + key1 = 0xFF; + } + /* Swap codes for ISO keyboard * https://github.com/tmk/tmk_keyboard/issues/35 *