VOGONS


First post, by HwAoRrDk

User metadata
Rank Newbie
Rank
Newbie

I'm attempting to reverse-engineer, using Ghidra, version 6.30 of the Logitech MouseWare driver to find out what potential 'asterisk' commands it's capable of sending to Logitech serial mice. This all started because while some of these commands are documented (e.g. "*n", "*o", etc. for changing baud rates), there are others that still remain a mystery (either in purpose or expected response - e.g. "*#"), so I figured why not try and find out what the mouse driver actually does?

I've thrown the binary (MOUSE.COM, 55KB) into Ghidra and disassembled it as a 16-bit real-mode executable with a memory origin of 0x100. It's identified a whole bunch of functions. And I've managed to go through and identify a large number of strings - mostly messages (inc. the loading message with box-char borders), INI config file keys/values, and command line args. Some oddities: all are null-terminated strings, except the command-line args, which oddly are Pascal strings (i.e. length-prefix), and there are a hell of a lot of empty (i.e. only spaces) strings that seem as if they are 'blanking' strings for overwriting/substituting for other strings. All the null-terminated strings are arranged in 'blocks' followed by a table of pointers to each string in that block; the code only appears to reference the tables, not the strings directly. I even think I've identified the INT33h handler entry point (thanks to this blog post).

In order to try and get to the code that sends commands to the serial mouse, I thought a good place to start would be to identify where it sends data on the serial port, and work backwards. Firstly, it doesn't appear to use INT14h BIOS routines (there are zero instances of an INT 0x14 instruction anywhere, nor a CD 14 byte pair anywhere in the binary), so I assume it must talk to the UART hardware directly. Okay, so it'll be using 3F8/2F8 I/O port base addresses. So I search for all uses of an OUT instruction and come up with only 5 instances in the disassembled code. However, none of them appear to do anything with the UART! 😕

The first is in an apparently general-purpose function that appears to read an arbitrary I/O port register (with IN), bitwise-AND an argument value with the read value, and write it back (with OUT) to the register. The second is in a similar function to the first, but instead bitwise-ORs with the inverted argument value. The third is in a function that appears to read the PIT counter value (via 0x0043). The 4th and 5th are both in the same lengthy function, whose purpose is unclear to me, but appears to do something with reading/writing VGA registers. It sets the target IN/OUT address by reading from a table elsewhere, which appears to be populated with VGA port addresses (0x3C2, 0x3C4, 0x3CE, 0x3D4).

I'm totally mystified that there are no other I/O writes anywhere in the disassembled code! No instruction variants like OUTS, OUTSB, or OUTSW either.

I feel like I may be missing something because there's still a lot of 'junk' data that Ghidra has not disassembled that I suspect may be more code, but there's obviously no point blindly disassembling it without knowing it is: a) actually code, and b) called from somewhere/something (which it apparently isn't). Could there be more interrupt handlers? How do I figure that out?

So I'm kind of stuck. Does anyone have any advice?

Reply 1 of 7, by EduBat

User metadata
Rank Member
Rank
Member

Not sure if it will help or not but, if ctmouse also sends those asterisk commands, it is free software with available sources and it can be studied.

Reply 2 of 7, by jmarsh

User metadata
Rank Oldbie
Rank
Oldbie

Search for the port addresses then find the code that references them.

Reply 3 of 7, by jakethompson1

User metadata
Rank l33t
Rank
l33t

The function at 0x40bd looks promising as highly related to the serial port. In particular the table it references at 0x99a4 has what looks like three function pointers followed by the port numbers 3f8h, 2f8h, 3e8h, and 2e8h. Function 0x43d4 (which 0x40bd calls) looks like the baud rate setting function. It's called with si=0x99f8 and the two bytes there are 0x60 0x00, and after setting port+3 to 0x80 to set the divisor latch access bit, it outputs [si] to port and [si+1] to port+1. 115200/1200=0x60 so that would be defaulting to a baud rate of 1200 which makes sense.

Really it should consult the BIOS data area at 40h:00h and 40h:02h to find the I/O ports of COM1: and COM2:, but I didn't see anything like that. The BIOS cannot tell you the IRQs so perhaps they considered it useless if it's anything other than 3f8/2f8.

Reply 4 of 7, by HwAoRrDk

User metadata
Rank Newbie
Rank
Newbie
EduBat wrote on Yesterday, 21:22:

if ctmouse also sends those asterisk commands

No, it does not.

jmarsh wrote on Yesterday, 21:50:

Search for the port addresses then find the code that references them.

That was one of the first things that came to mind. I could not find any instances of instructions that had the immediate value of 0x3F8 or 0x2F8 (or did something like load a low-byte of 0xF8 and then conditionally a high byte of 0x2/0x3).

Besides, I didn't expect that it would have the serial port addresses hard-coded, because the driver takes which COM port to use from a parameter in the MOUSEDRV.INI configuration file (e.g. "ConnectionPort=COM1"). Which, BTW, is another mystery, because that filename only appears in the binary within message strings, so I have no idea how it actually accesses the file if it doesn't do it by name! 😄

Reply 5 of 7, by HwAoRrDk

User metadata
Rank Newbie
Rank
Newbie
jakethompson1 wrote on Yesterday, 22:30:

The function at 0x40bd looks promising as highly related to the serial port. In particular the table it references at 0x99a4 has what looks like three function pointers followed by the port numbers 3f8h, 2f8h, 3e8h, and 2e8h.

Thank you!! 😃 How did you locate that function? For me that's within a a bunch of the 'junk' data that Ghidra hadn't so far disassembled. Is it referenced from an interrupt handler that I haven't discovered?

It's hard for me to intuit what a section of code does because I'm not at all familiar with x86 assembly, so I would not pick things like this up. Much time is spent referring to x86 instruction and register cheat sheets. 😅

jakethompson1 wrote on Yesterday, 22:30:

Really it should consult the BIOS data area at 40h:00h and 40h:02h to find the I/O ports of COM1: and COM2:, but I didn't see anything like that. The BIOS cannot tell you the IRQs so perhaps they considered it useless if it's anything other than 3f8/2f8.

Yeah, makes sense it doesn't due to what I said in the previous post about it being capable of reading COM port parameters from the INI file (MOUSEDRV.INI can have "[COMx]" sections with "BaseAddress" and "IRQValue" parameters). Although, given that the default MOUSEDRV.INI file doesn't actually include those sections by default, it seems right it would make assumptions about 3F8/2F8 for COM1/COM2.

Reply 6 of 7, by vetz

User metadata
Rank l33t
Rank
l33t

I had Claude check what *# does and according to the findings it's an internal mouse firmware identification protocol. It queries the model number in a 5-byte ASCII string from the mouse to set the correct mouse type and differentiate genuine Logitech mice from generic Microsoft-compatible serial mice on the same port.

3D Accelerated Games List (Proprietary APIs - No 3DFX/Direct3D)
3D Acceleration Comparison Episodes

Reply 7 of 7, by HwAoRrDk

User metadata
Rank Newbie
Rank
Newbie
vetz wrote on Today, 10:35:

I had Claude check what *# does and according to the findings it's an internal mouse firmware identification protocol. It queries the model number in a 5-byte ASCII string from the mouse to set the correct mouse type and differentiate genuine Logitech mice from generic Microsoft-compatible serial mice on the same port.

Yes, I got your private message with the Claude analysis. Very useful! Thanks again. 😁