From 66e97371bacb1ad55096f0407b47f0a73fadc6c7 Mon Sep 17 00:00:00 2001 From: tmk Date: Sun, 23 Jun 2019 13:31:54 +0900 Subject: [PATCH] adb_usb: Fix mouse_init --- converter/adb_usb/matrix.c | 215 +++++++++++++++++++++++++------------ tmk_core/protocol/adb.c | 66 ++++++++++-- tmk_core/protocol/adb.h | 15 ++- 3 files changed, 223 insertions(+), 73 deletions(-) diff --git a/converter/adb_usb/matrix.c b/converter/adb_usb/matrix.c index 82ccee89..d2da841c 100644 --- a/converter/adb_usb/matrix.c +++ b/converter/adb_usb/matrix.c @@ -37,17 +37,37 @@ along with this program. If not, see . 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(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); + } + _delay_ms(20); + } +} void matrix_init(void) { + debug_enable = true; + //debug_matrix = true; + //debug_keyboard = true; + //debug_mouse = true; + // LED on DDRD |= (1<<6); PORTD |= (1<<6); @@ -55,16 +75,7 @@ void matrix_init(void) // 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); - } - + device_scan(); // // Keyboard @@ -98,26 +109,88 @@ void matrix_init(void) adb_host_listen(ADB_ADDR_KEYBOARD, ADB_REG_3, ADB_ADDR_KEYBOARD, ADB_HANDLER_EXTENDED_KEYBOARD); - #ifdef ADB_MOUSE_ENABLE // // Mouse // // https://developer.apple.com/library/archive/technotes/hw/hw_01.html#Extended + #ifdef ADB_MOUSE_ENABLE xprintf("\nMouse:\n"); + // Check device on addr3 + mouse_init(ADB_ADDR_MOUSE); + #endif + + device_scan(); + + // initialize matrix state: all keys off + for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; + + led_set(host_keyboard_leds()); + + // 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: // 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(orig_addr, ADB_REG_3)) & 0xFF; + if (!reg3) return; + dmprintf("addr%d reg3: %02X\n", orig_addr, reg3); + // Move device to tmp address + _delay_ms(20); + adb_host_flush(orig_addr); _delay_ms(20); - adb_host_listen(ADB_ADDR_MOUSE, ADB_REG_3, ADB_ADDR_MOUSE, ADB_HANDLER_EXTENDED_MOUSE); + adb_host_listen(orig_addr, ADB_REG_3, ((reg3 >> 8) & 0xF0) | ADB_ADDR_TMP, 0xFE); + adb_host_flush(ADB_ADDR_TMP); _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; + 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; + dmprintf("addr%d reg3: %02X\n", addr, reg3); + + +detect_again: + if (mouse_handler == ADB_HANDLER_CLASSIC1_MOUSE || mouse_handler == ADB_HANDLER_CLASSIC2_MOUSE) { + _delay_ms(20); + adb_host_flush(addr); + adb_host_listen(addr, ADB_REG_3, (reg3 >> 8), ADB_HANDLER_EXTENDED_MOUSE); + + _delay_ms(20); + mouse_handler = (reg3 = adb_host_talk(addr, ADB_REG_3)) & 0xFF; + + + if (mouse_handler == ADB_HANDLER_CLASSIC1_MOUSE) { + _delay_ms(20); + adb_host_flush(addr); + adb_host_listen(addr, ADB_REG_3, (reg3 >> 8), ADB_HANDLER_CLASSIC2_MOUSE); + + _delay_ms(20); + mouse_handler = (reg3 = adb_host_talk(addr, ADB_REG_3)) & 0xFF; + } - if (mouse_handler == ADB_HANDLER_CLASSIC1_MOUSE) { mouse_cpi = 100; } - if (mouse_handler == ADB_HANDLER_CLASSIC2_MOUSE) { mouse_cpi = 200; } + if (mouse_handler == ADB_HANDLER_CLASSIC1_MOUSE) { + xprintf("Classic 100cpi\n"); + mouse_cpi = 100; + } + if (mouse_handler == ADB_HANDLER_CLASSIC2_MOUSE) { + xprintf("Classic 200cpi\n"); + mouse_cpi = 200; + } + } // Extended Mouse Protocol if (mouse_handler == ADB_HANDLER_EXTENDED_MOUSE) { @@ -128,12 +201,8 @@ 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)); - if (len) { - xprintf("Devinfo: [", len); - for (int8_t i = 0; i < len; i++) xprintf("%02X ", buf[i]); - xprintf("]\n"); - } + _delay_ms(20); + len = adb_host_talk_buf(addr, ADB_REG_1, buf, sizeof(buf)); if (len > 5) { mouse_cpi = (buf[4]<<8) | buf[5]; @@ -141,60 +210,66 @@ void matrix_init(void) mouse_cpi = 100; } - // 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 }; + if (len) { + xprintf("Ext: [", len); + for (int8_t i = 0; i < len; i++) xprintf("%02X ", buf[i]); + xprintf("] cpi=%d\n", mouse_cpi); + } - // 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); - xprintf("cpi: %d\n", mouse_cpi); - #endif + if (mouse_handler == ADB_HANDLER_TURBO_MOUSE) { + xprintf("TM5: ext\n"); + + // 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 }; - 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); + 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 all mouses to a address after init to be polled + _delay_ms(20); + 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; + _delay_ms(20); + 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 +// dmprintf("handler: %d\n", mouse_handler); +// dmprintf("cpi: %d\n", mouse_cpi); +} #ifdef MAX #undef MAX @@ -217,6 +292,14 @@ 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(); + dmprintf("."); + // 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 // @@ -229,7 +312,7 @@ 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) { diff --git a/tmk_core/protocol/adb.c b/tmk_core/protocol/adb.c index 7feffb30..36005951 100644 --- a/tmk_core/protocol/adb.c +++ b/tmk_core/protocol/adb.c @@ -1,5 +1,5 @@ /* -Copyright 2011 Jun WAKO +Copyright 2011-19 Jun WAKO Copyright 2013 Shay Green This software is licensed with a Modified BSD License. @@ -113,18 +113,71 @@ uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len) attention(); send_byte((addr<<4) | ADB_CMD_TALK | reg); place_bit0(); // Stopbit(0) + // TODO: Service Request(Srq): + // Device holds low part of comannd stopbit for 140-260us + // + // Command: + // ......._ ______________________ ___ ............_ ------- + // | | | | | | | + // Command | | | | | Data bytes | | + // ........|___| | 140-260 |__| |_............|___| + // |stop0 | Tlt Stop-to-Start |start1| |stop0 | + // + // Command without data: + // ......._ __________________________ + // | | + // Command | | + // ........|___| | 140-260 | + // |stop0 | Tlt Stop-to-Start | + // + // Service Request: + // ......._ ______ ___ ............_ ------- + // | 140-260 | | | | | | + // Command | Service Request | | | | Data bytes | | + // ........|___________________| |__| |_............|___| + // |stop0 | |start1| |stop0 | + // ......._ __________ + // | 140-260 | + // Command | Service Request | + // ........|___________________| + // |stop0 | + // This can be happened? + // ......._ ______________________ ___ ............_ ----- + // | | | | | | 140-260 | + // Command | | | | | Data bytes | Service Request | + // ........|___| | 140-260 |__| |_............|_________________| + // |stop0 | Tlt Stop-to-Start |start1| |stop0 | + // + // "Service requests are issued by the devices during a very specific time at the + // end of the reception of the command packet. + // If a device in need of service issues a service request, it must do so within + // the 65 µs of the Stop Bit’s low time and maintain the line low for a total of 300 µs." + // + // "A device sends a Service Request signal by holding the bus low during the low + // portion of the stop bit of any command or data transaction. The device must lengthen + // the stop by a minimum of 140 J.lS beyond its normal duration, as shown in Figure 8-15." + // http://ww1.microchip.com/downloads/en/AppNotes/00591b.pdf if (!wait_data_hi(500)) { // Service Request(310us Adjustable Keyboard): just ignored + xprintf("R"); sei(); - return -30; // something wrong + return 0; } if (!wait_data_lo(500)) { // Tlt/Stop to Start(140-260us) sei(); - return 0; // No data to send + return 0; // No data from device(not error); } // start bit(1) - if (!wait_data_hi(40)) return 0; - if (!wait_data_lo(100)) return 0; + if (!wait_data_hi(40)) { + xprintf("S"); + sei(); + return 0; + } + if (!wait_data_lo(100)) { + xprintf("s"); + sei(); + return 0; + } uint8_t n = 0; // bit count do { @@ -143,7 +196,7 @@ uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len) uint8_t hi = (uint8_t) wait_data_lo(lo); if (!hi) - goto error; // stop bit extedned by Srq + goto error; // stop bit extedned by Srq? if (n/8 >= len) continue; // can't store in buf @@ -174,6 +227,7 @@ void adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len) attention(); send_byte((addr<<4) | ADB_CMD_LISTEN | reg); place_bit0(); // Stopbit(0) + // TODO: Service Request _delay_us(200); // Tlt/Stop to Start place_bit1(); // Startbit(1) for (int8_t i = 0; i < len; i++) { diff --git a/tmk_core/protocol/adb.h b/tmk_core/protocol/adb.h index 52932c94..5e155cbc 100644 --- a/tmk_core/protocol/adb.h +++ b/tmk_core/protocol/adb.h @@ -1,5 +1,5 @@ /* -Copyright 2011 Jun WAKO +Copyright 2011-19 Jun WAKO This software is licensed with a Modified BSD License. All of this is supposed to be Free Software, Open Source, DFSG-free, @@ -54,11 +54,23 @@ POSSIBILITY OF SUCH DAMAGE. /* ADB commands */ // Default Address +#define ADB_ADDR_0 0 #define ADB_ADDR_DONGLE 1 #define ADB_ADDR_KEYBOARD 2 #define ADB_ADDR_MOUSE 3 #define ADB_ADDR_TABLET 4 #define ADB_ADDR_APPLIANCE 7 +#define ADB_ADDR_8 8 +#define ADB_ADDR_9 9 +#define ADB_ADDR_10 10 +#define ADB_ADDR_11 11 +#define ADB_ADDR_12 12 +#define ADB_ADDR_13 13 +#define ADB_ADDR_14 14 +#define ADB_ADDR_15 15 +// for temporary purpose, do not use for polling +#define ADB_ADDR_TMP 15 +#define ADB_ADDR_MOUSE_POLL 10 // Command Type #define ADB_CMD_RESET 0 #define ADB_CMD_FLUSH 1 @@ -80,6 +92,7 @@ POSSIBILITY OF SUCH DAMAGE. #define ADB_HANDLER_CLASSIC1_MOUSE 0x01 #define ADB_HANDLER_CLASSIC2_MOUSE 0x02 #define ADB_HANDLER_EXTENDED_MOUSE 0x04 +#define ADB_HANDLER_TURBO_MOUSE 0x32 // ADB host -- 2.46.2