aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJavier <dev.git@javispedro.com>2026-08-30 19:01:23 +0200
committerJavier <dev.git@javispedro.com>2026-08-30 19:01:23 +0200
commit8459567950d6d7dcc8f92753b0c1918f417ab149 (patch)
tree8ab3fe3e5c970a4c00b5e222a6c5a13525149287
parent6c79dffa4fd38a36845f518443668a3aa654728c (diff)
downloadvbados-8459567950d6d7dcc8f92753b0c1918f417ab149.tar.gz
vbados-8459567950d6d7dcc8f92753b0c1918f417ab149.zip
handle wheel serial protocol (untested)
-rw-r--r--dlog.h18
-rw-r--r--mousetsr.c68
-rw-r--r--mousmain.c46
-rw-r--r--sermouse.h14
4 files changed, 114 insertions, 32 deletions
diff --git a/dlog.h b/dlog.h
index 2878ac9..19337cd 100644
--- a/dlog.h
+++ b/dlog.h
@@ -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;
diff --git a/mousetsr.c b/mousetsr.c
index b386c89..0965b6b 100644
--- a/mousetsr.c
+++ b/mousetsr.c
@@ -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;
}
}
diff --git a/mousmain.c b/mousmain.c
index 79abfae..02540de 100644
--- a/mousmain.c
+++ b/mousmain.c
@@ -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
diff --git a/sermouse.h b/sermouse.h
index a120f26..fb2184d 100644
--- a/sermouse.h
+++ b/sermouse.h
@@ -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