diff options
| -rw-r--r-- | dlog.h | 18 | ||||
| -rw-r--r-- | mousetsr.c | 68 | ||||
| -rw-r--r-- | mousmain.c | 46 | ||||
| -rw-r--r-- | sermouse.h | 14 |
4 files changed, 114 insertions, 32 deletions
@@ -56,14 +56,26 @@ static inline void dlog_init() // No initialization required } -static inline void dputc(char c); -#pragma aux dputc = \ +static inline void dconputc(char c); +#pragma aux dconputc = \ "mov ah, 0x0E" \ "xor bx, bx" \ "int 0x10" \ __parm [AL] \ __modify __exact [AH AL BH BL]; +static inline void dputc(char c) +{ + // Need to convert CR into CRLF... + if (c == '\n') { + dconputc('\n'); + dconputc('\r'); + } else { + dconputc(c); + } +} + + #elif DLOG_TARGET == DLOG_TARGET_SERIAL static void dlog_init() @@ -167,7 +179,6 @@ static void d_itoa(int num, unsigned base) { unsigned unum; - // TODO if (num < 0) { dputc('-'); unum = -num; @@ -182,7 +193,6 @@ static void d_ltoa(long num, unsigned base) { unsigned long unum; - // TODO if (num < 0) { dputc('-'); unum = -num; @@ -1546,14 +1546,13 @@ void __declspec(naked) __far int33_isr(void) } #if USE_SERIAL -static void handle_serial_ms_packet() +static void handle_serial_m_packet() { int x = (int8_t) ((data.cur_packet[1] & SERMOUSE_MS_X_LO_MASK) | ((data.cur_packet[0] & SERMOUSE_MS_X_HI_MASK) << SERMOUSE_MS_X_HI_SHIFT)); int y = (int8_t) ((data.cur_packet[2] & SERMOUSE_MS_Y_LO_MASK) | ((data.cur_packet[0] & SERMOUSE_MS_Y_HI_MASK) << SERMOUSE_MS_Y_HI_SHIFT)); unsigned buttons = 0; - // Unused: bool abs = false; char wheeln = 0; int z = 0; @@ -1562,25 +1561,62 @@ static void handle_serial_ms_packet() buttons |= INT33_BUTTON_MASK_LEFT; if (data.cur_packet[0] & SERMOUSE_MS_BUTTON_RIGHT) buttons |= INT33_BUTTON_MASK_RIGHT; - + if (data.num_buttons >= 3 && (data.buttons & INT33_BUTTON_MASK_CENTER)) + buttons |= INT33_BUTTON_MASK_CENTER; // preserve status of mid button for now #if TRACE_PROTO - dprintf("serial decoded packet buttons=%x x=%d y=%d\n", buttons, x, y); + dprintf("serial decoded M packet buttons=%x x=%d y=%d\n", buttons, x, y); #endif /* TRACE_PROTO */ handle_mouse_event(buttons, abs, x, y, wheeln, z); } +static void handle_serial_m3_packet() +{ + // No need to send mouse movement as it will have been processed + // back when we received the 3rd byte. + // Instead focus on wheel and mid mouse button which come in the 4rd byte. + int x = 0; + int y = 0; + // Preserve old button state for most part + unsigned buttons = data.buttons & (INT33_BUTTON_MASK_LEFT|INT33_BUTTON_MASK_RIGHT); + bool abs = false; + char wheeln = 0; // only one wheel supported for now + int z = sign_extend(data.cur_packet[3] & SERMOUSE_MS_Z_LO_MASK, 4); + + if (data.cur_packet[3] & SERMOUSE_MS_BUTTON_CENTER) { + buttons |= INT33_BUTTON_MASK_CENTER; + } + +#if TRACE_PROTO + dprintf("serial decoded M3 packet buttons=%x z=%d\n", buttons, z); +#endif /* TRACE_PROTO */ + + // Only send 2nd event if really necessary + if (buttons != data.buttons || z) { + handle_mouse_event(buttons, abs, x, y, wheeln, z); + } +} + static void handle_serial_data(uint8_t byte) { // TODO: not checking cur_packet_ticks for now, don't think it necessary for serial // due to different synchronization // Depending on the serial protocol now... - switch (data.device_id) { - case 'M': - case '3': + if (data.device_id == SERMOUSE_DEVICE_ID_MS) { // All these protocols use bit #6 (MSB since we use 7 data bits) as Start-of-Frame indicator if (byte & (1 << 6)) { + if (data.buttons & INT33_BUTTON_MASK_CENTER && data.cur_packet_bytes == 3) { + // Was the previous packet a 3byte one and the middle button is down? + // Assume the mouse just skipped the 4th byte and release the middle button + // TODO I am not sure if this hack is required +#if TRACE_PROTO + dputs("serial releasing mid button"); +#endif /* TRACE_PROTO */ + handle_mouse_event(data.buttons & ~INT33_BUTTON_MASK_CENTER, false, 0, 0, 0, 0); + } + + // Prepare for new packet data.cur_packet_bytes = 0; } @@ -1592,12 +1628,24 @@ static void handle_serial_data(uint8_t byte) data.cur_packet[data.cur_packet_bytes] = byte; data.cur_packet_bytes++; + // However there is no End-of-Frame indicator. + // We do not know if this is going to be a 3 byte or 4 byte packet + // (apparently 4-byte packet mouses may send up a 3-byte packet + // if no wheel or extra buttons are modified) + // So we will send a "main" mouse event when we receive the 3rd byte + // and then follow up with a second mouse event if we receive the 4rd. + + if (data.cur_packet_bytes == 3) { + // send main mouse event now + handle_serial_m_packet(); + } else if (data.cur_packet_bytes == 4) { + // handle the 4th byte + handle_serial_m3_packet(); + } + if (data.cur_packet_bytes >= data.packet_size) { - handle_serial_ms_packet(); data.cur_packet_bytes = 0; } - - break; } } @@ -29,6 +29,7 @@ #include "int21dos.h" #include "int15ps2.h" #include "serial.h" +#include "sermouse.h" #include "vbox.h" #include "vmware.h" #include "dostsr.h" @@ -324,7 +325,7 @@ static int configure_driver_serial(LPTSRDATA data, int port, unsigned iobase) { struct serial_config serconfig; unsigned delay; - char sig1 = 0, sig2 = 0; + char sig = 0; if (!iobase) { dprintf("Skip search on COM%u because no IO base found\n", port); @@ -334,6 +335,7 @@ static int configure_driver_serial(LPTSRDATA data, int port, unsigned iobase) #if ENABLE_DLOG && DLOG_TARGET == DLOG_TARGET_SERIAL if (iobase == DLOG_TARGET_PORT) { dprintf("Skip search on COM%u because it would overlap with dlog %x\n", port, iobase); + return -2; } #endif @@ -360,53 +362,63 @@ static int configure_driver_serial(LPTSRDATA data, int port, unsigned iobase) uint8_t car = serial_read_data(iobase); // Is this something we recognize ? - dprintf("received serial data after reset: 0x%hx '%c'\n", car, car); + dprintf("serial data after reset: 0x%hx '%c'\n", car, car); if (car == 'M') { // Ok, got the MS signature, break out of this wait - sig1 = car; + sig = car; break; } } - if (sig1) break; + if (sig) break; bda_wait_tick(); dprintf("remaining ticks %u\n", delay); } - if (sig1 == 'M') { + switch (sig) { + case 'M': // We have a valid MS-style serial mouse data->port = port; - data->device_id = 'M'; + data->device_id = SERMOUSE_DEVICE_ID_MS; data->port_io = iobase; data->port_irq = serial_get_irq(port); data->num_buttons = 2; -#if USE_WHEEL data->num_wheels = 0; -#endif data->packet_size = 3; - // Should we wait for an extended signature? Let's do it + // Wait for an extended signature for about 2 ticks (50-100ms) + sig = 0; for (delay = 2; delay > 0; delay--) { while (serial_data_ready(iobase)) { uint8_t car = serial_read_data(iobase); - dprintf("received serial data after '%c': 0x%hx '%c'\n", sig1, car, car); - if (car == '3') { - // Ok, got the MS signature, break out of this wait - sig2 = car; + dprintf("serial data after 'M': 0x%hx '%c'\n", car, car); + if (car == '3' || car == 'Z') { + sig = car; break; } } - if (sig2) break; + if (sig) break; bda_wait_tick(); dprintf("2nd loop remaining ticks %u\n", delay); } - if (sig2 == '3') { - data->device_id = '3'; + // Update the mouse details based on the extended signature + // We don't change the device ID since we treat all the same. + switch (sig) { + case '3': + data->packet_size = 4; + data->num_buttons = 3; + break; + case 'Z': + data->packet_size = 4; data->num_buttons = 3; +#if USE_WHEEL + data->num_wheels = 1; +#endif + break; } // In any case, we got ourselves a mouse. @@ -415,7 +427,7 @@ static int configure_driver_serial(LPTSRDATA data, int port, unsigned iobase) // No mouse found on this port. serial_restore_config(iobase, &serconfig); - return -2; + return -3; } #endif @@ -20,19 +20,31 @@ #ifndef SERMOUSE_H #define SERMOUSE_H -enum { +enum SERMOUSE_DEVICE_ID +{ + SERMOUSE_DEVICE_ID_MS = 'M' +}; + +enum SERMOUSE_PROTOCOL_MS { + // 1st byte: SERMOUSE_MS_BUTTON_LEFT = 1 << 5, SERMOUSE_MS_BUTTON_RIGHT = 1 << 4, SERMOUSE_MS_X_LO_MASK = 0x3F, SERMOUSE_MS_Y_LO_MASK = 0x3F, + // 2nd byte: SERMOUSE_MS_X_HI_MASK = 0x3, SERMOUSE_MS_X_HI_SHIFT = 6, + // 3rd byte: SERMOUSE_MS_Y_HI_MASK = 0xC, SERMOUSE_MS_Y_HI_SHIFT = 4, + // 4th byte: + SERMOUSE_MS_BUTTON_CENTER = 1 << 5, + SERMOUSE_MS_Z_LO_MASK = 0xF, + SERMOUSE_MS_Z_LO_SHIFT = 0 }; #endif // SERMOUSE_H |
