From f16f7a2464917bc992572155dbd115f359e57c24 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 2 May 2023 21:53:42 +0200 Subject: [PATCH] Some minor Logitech serial mouse bug fixes and implemented the auto baud rate mode. --- src/device/mouse_serial.c | 51 +++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/src/device/mouse_serial.c b/src/device/mouse_serial.c index f7956a9bd..58541d79a 100644 --- a/src/device/mouse_serial.c +++ b/src/device/mouse_serial.c @@ -37,7 +37,9 @@ enum { PHASE_DIAGNOSTIC, PHASE_FORMAT_AND_REVISION, PHASE_COPYRIGHT_STRING, - PHASE_BUTTONS + PHASE_BUTTONS, + PHASE_ACK, + PHASE_BAUD_RATE }; enum { @@ -63,7 +65,8 @@ typedef struct { int command_pos, command_phase, report_pos, report_phase, command_enabled, report_enabled; - double transmit_period, report_period; + double transmit_period, report_period, + auto_period; pc_timer_t command_timer, report_timer; serial_t *serial; @@ -191,9 +194,9 @@ sermouse_data_msystems(mouse_t *dev, int x, int y, int b) static uint8_t sermouse_data_3bp(mouse_t *dev, int x, int y, int b) { - dev->data[0] |= (b & 0x01) ? 0x00 : 0x04; /* left button */ - dev->data[0] |= (b & 0x04) ? 0x00 : 0x02; /* middle button */ - dev->data[0] |= (b & 0x02) ? 0x00 : 0x01; /* right button */ + dev->data[0] |= (b & 0x01) ? 0x04 : 0x00; /* left button */ + dev->data[0] |= (b & 0x04) ? 0x02 : 0x00; /* middle button */ + dev->data[0] |= (b & 0x02) ? 0x01 : 0x00; /* right button */ dev->data[1] = x; dev->data[2] = -y; @@ -211,7 +214,7 @@ sermouse_data_mmseries(mouse_t *dev, int x, int y, int b) dev->data[0] = 0x80; if (x >= 0) dev->data[0] |= 0x10; - if (y < 0) + if (y >= 0) dev->data[0] |= 0x08; dev->data[0] |= (b & 0x01) ? 0x04 : 0x00; /* left button */ dev->data[0] |= (b & 0x04) ? 0x02 : 0x00; /* middle button */ @@ -481,6 +484,15 @@ sermouse_command_timer(void *priv) sermouse_report_timer((void *) dev); } break; + case PHASE_ACK: + serial_write_fifo(dev->serial, 0x06); + /* FALLTHROUGH */ + case PHASE_BAUD_RATE: + sermouse_command_phase_idle(dev); + sermouse_timer_on(dev, dev->report_period, 1); + dev->report_phase = REPORT_PHASE_PREPARE; + sermouse_report_timer((void *) dev); + break; case PHASE_DATA: serial_write_fifo(dev->serial, dev->data[dev->command_pos]); sermouse_command_pos_check(dev, dev->data_len); @@ -587,6 +599,15 @@ ltsermouse_set_report_period(mouse_t *dev, int rps) dev->report_phase = REPORT_PHASE_PREPARE; } +static void +ltsermouse_switch_baud_rate(mouse_t *dev, int phase) +{ + dev->command_pos = 0; + dev->command_phase = phase; + timer_stop(&dev->command_timer); + sermouse_timer_on(dev, 10000.0, 0); +} + static void ltsermouse_write(struct serial_s *serial, void *priv, uint8_t data) { @@ -617,11 +638,18 @@ ltsermouse_write(struct serial_s *serial, void *priv, uint8_t data) dev->transmit_period = sermouse_transmit_period(dev, 9600, -1); break; } + ltsermouse_switch_baud_rate(dev, PHASE_BAUD_RATE); break; } else switch (data) { + case 0x20: + sermouse_timer_on(dev, 0.0, 1); + dev->transmit_period = dev->auto_period; + ltsermouse_switch_baud_rate(dev, PHASE_ACK); + break; case 0x2A: + sermouse_timer_on(dev, 0.0, 1); dev->want_data = data; dev->data_len = 1; break; @@ -699,6 +727,14 @@ ltsermouse_write(struct serial_s *serial, void *priv, uint8_t data) } } +static void +ltsermouse_transmit_period(serial_t *serial, void *priv, double transmit_period) +{ + mouse_t *dev = (mouse_t *) priv; + + dev->auto_period = transmit_period; +} + static void sermouse_speed_changed(void *priv) { @@ -775,6 +811,7 @@ sermouse_init(const device_t *info) } dev->transmit_period = sermouse_transmit_period(dev, 1200, -1); + dev->auto_period = dev->transmit_period; /* Default: Continuous reporting = no delay between reports. */ dev->report_phase = REPORT_PHASE_PREPARE; @@ -787,7 +824,7 @@ sermouse_init(const device_t *info) /* Attach a serial port to the mouse. */ if (info->local) - dev->serial = serial_attach(dev->port, sermouse_callback, ltsermouse_write, dev); + dev->serial = serial_attach_ex(dev->port, sermouse_callback, ltsermouse_write, ltsermouse_transmit_period, NULL, dev); else dev->serial = serial_attach(dev->port, sermouse_callback, NULL, dev);