mame icon indicating copy to clipboard operation
mame copied to clipboard

logitech_mouse breaks LMOUSE.DRV in Windows 3.1

Open davide125 opened this issue 5 years ago • 12 comments

By default, at386 plugs a logitech_mouse in the first serial port. When installing win31, this gets detected as "Logitech", and the LMOUSE.DRV driver is installed. When the setup then switches to Windows mode, it hangs forever. Changing the mouse type to "Microsoft" (or plugging microsoft_mouse into the serial port instead) mitigates this, which makes me suspect there's something wrong with the logitech implementation in hlemouse.cpp.

To repro this:

  • run at386 -hard1 win31 (win31 comes from from https://github.com/mamedev/mame/pull/7192)
  • go to Windows Setup - Options - Change System Settings, pick Logitech in the Mouse dropdown, confirm
  • plug in the requested floppy from the win31 set and let it install the driver
  • restart Windows, notice it hangs forever now

This also repros with wfw311, and with at486 / ct486.

davide125 avatar Sep 06 '20 03:09 davide125

This has been reported before, and it confuses me. The Logitech mouse in MAME does work correctly with the CuteMouse driver for DOS and follows the description of the protocol in the Linux mouse(4) man page. There’s something going wrong somewhere, but I’m honestly at a loss to know what it is. The code provided the fourth report byte for the additional button state whenever the additional button is depressed and on the first report after it’s released, which is what CuteMouse and Linux expect. Is there any more detail on what Windows 3 wants or why it goes wrong?

cuavas avatar Sep 06 '20 06:09 cuavas

Also quoting from https://www.kryslix.com/nsfaq/Q.12.html (it has a bad certificate):

Logitech extended the 2 button mouse protocol to support 3 button mice by adding a 4th byte when the middle button is pressed (and the first packet after it is released). If a 4th byte is encountered (i.e., an extra byte with D6 set to 0) then D5 of that byte (0x20) indicates the status of the middle mouse button.

cuavas avatar Sep 06 '20 06:09 cuavas

I don't know whether this has anything to do with this issue, but there appears to be a copy-and-paste error in hle_msmouse_device_base::input_rts.

ajrhacker avatar Sep 06 '20 11:09 ajrhacker

Ah yes, that does appear to be an error.

cuavas avatar Sep 06 '20 11:09 cuavas

After fixing that, and adding some debug logging, it looks like the logitech driver sends some stuff over (maybe to negotiate speed / protocol?), and it likely expects a reply. Compare: microsoft driver:

[:board2:comat:serport0:logitech_mouse] dtr
[:board2:comat:serport0:logitech_mouse] rts
[:board2:comat:serport0:logitech_mouse] dtr
[:board2:comat:serport0:logitech_mouse] rts
[:board2:comat:serport0:logitech_mouse] logitech reset
[:board2:comat:serport0:logitech_mouse] dtr
[:board2:comat:serport0:logitech_mouse] rts
[:board2:comat:serport0:logitech_mouse] dtr
[:board2:comat:serport0:logitech_mouse] rts
[:board2:comat:serport0:logitech_mouse] logitech reset
[:board2:comat:serport0:logitech_mouse] dtr
[:board2:comat:serport0:logitech_mouse] rts

logitech driver

[:board2:comat:serport0:logitech_mouse] dtr
[:board2:comat:serport0:logitech_mouse] rts
[:board2:comat:serport0:logitech_mouse] logitech reset
[:board2:comat:serport0:logitech_mouse] received byte 00000044
[:board2:comat:serport0:logitech_mouse] received byte 00000073
[:board2:comat:serport0:logitech_mouse] received byte 00000070
[:board2:comat:serport0:logitech_mouse] received byte 00000075
[:board2:comat:serport0:logitech_mouse] received byte 0000007e
[:board2:comat:serport0:logitech_mouse] received byte 0000007d
[:board2:comat:serport0:logitech_mouse] received byte 0000007f
[:board2:comat:serport0:logitech_mouse] received byte 0000007f
[:board2:comat:serport0:logitech_mouse] dtr
[:board2:comat:serport0:logitech_mouse] rts
[:board2:comat:serport0:logitech_mouse] dtr
[:board2:comat:serport0:logitech_mouse] rts
[:board2:comat:serport0:logitech_mouse] dtr
[:board2:comat:serport0:logitech_mouse] rts
[:board2:comat:serport0:logitech_mouse] logitech reset
[:board2:comat:serport0:logitech_mouse] received byte 0000002a

and that was done with

diff --git a/src/devices/bus/rs232/hlemouse.cpp b/src/devices/bus/rs232/hlemouse.cpp
index a6452b9dcef..96d81523b94 100644
--- a/src/devices/bus/rs232/hlemouse.cpp
+++ b/src/devices/bus/rs232/hlemouse.cpp
@@ -66,6 +66,9 @@
 #include "emu.h"
 #include "hlemouse.h"
 
+#define VERBOSE 1
+#include "logmacro.h"
+
 #include <cassert>
 #include <cmath>
 
@@ -241,13 +244,15 @@ void hle_msmouse_device_base::device_start()
 
 WRITE_LINE_MEMBER(hle_msmouse_device_base::input_dtr)
 {
+       LOG("dtr\n");
        m_dtr = state ? 1U : 0U;
        check_enable();
 }
 
 WRITE_LINE_MEMBER(hle_msmouse_device_base::input_rts)
 {
-       m_dtr = state ? 1U : 0U;
+       LOG("rts\n");
+       m_rts = state ? 1U : 0U;
        check_enable();
 }
 
@@ -260,6 +265,7 @@ void hle_msmouse_device_base::tra_complete()
 
 void hle_msmouse_device_base::received_byte(u8 byte)
 {
+       LOG("received byte %08x\n", byte);
 }
 
 
@@ -355,6 +361,7 @@ ioport_constructor hle_logitech_mouse_device::device_input_ports() const
 
 void hle_logitech_mouse_device::reset_and_identify()
 {
+       LOG("logitech reset\n");
        // assume ASCII host system
        transmit_byte('M');
        transmit_byte('3');

davide125 avatar Sep 06 '20 14:09 davide125

If I hardcode the baudrate to 2400 it doesn't hang anymore, but the mouse doesn't work at all. The data the driver sends over is a bit different:

[:board2:comat:serport0:logitech_mouse] logitech reset
[:board2:comat:serport0:logitech_mouse] received byte 00000060
[:board2:comat:serport0:logitech_mouse] received byte 0000007e
[:board2:comat:serport0:logitech_mouse] received byte 0000001e
[:board2:comat:serport0:logitech_mouse] received byte 00000078
[:board2:comat:serport0:logitech_mouse] received byte 00000044
[:board2:comat:serport0:logitech_mouse] received byte 00000073
[:board2:comat:serport0:logitech_mouse] received byte 00000070
[:board2:comat:serport0:logitech_mouse] received byte 00000075
[:board2:comat:serport0:logitech_mouse] received byte 0000007e
[:board2:comat:serport0:logitech_mouse] received byte 0000007d

Same for 4800, where I get

[:board2:comat:serport0:logitech_mouse] logitech reset
[:board2:comat:serport0:logitech_mouse] received byte 00000000
[:board2:comat:serport0:logitech_mouse] received byte 00000000
[:board2:comat:serport0:logitech_mouse] received byte 00000078
[:board2:comat:serport0:logitech_mouse] received byte 00000078
[:board2:comat:serport0:logitech_mouse] received byte 00000000
[:board2:comat:serport0:logitech_mouse] received byte 00000000
[:board2:comat:serport0:logitech_mouse] received byte 00000060
[:board2:comat:serport0:logitech_mouse] received byte 0000007e
[:board2:comat:serport0:logitech_mouse] received byte 0000001e
[:board2:comat:serport0:logitech_mouse] received byte 00000078
[:board2:comat:serport0:logitech_mouse] received byte 00000044
[:board2:comat:serport0:logitech_mouse] received byte 00000073
[:board2:comat:serport0:logitech_mouse] received byte 00000070
[:board2:comat:serport0:logitech_mouse] received byte 00000075

and 9600

[:board2:comat:serport0:logitech_mouse] logitech reset
[:board2:comat:serport0:logitech_mouse] received byte 00000000
[:board2:comat:serport0:logitech_mouse] received byte 00000000
[:board2:comat:serport0:logitech_mouse] received byte 00000000
[:board2:comat:serport0:logitech_mouse] received byte 00000000
[:board2:comat:serport0:logitech_mouse] received byte 00000000
[:board2:comat:serport0:logitech_mouse] received byte 00000000
[:board2:comat:serport0:logitech_mouse] received byte 00000000
[:board2:comat:serport0:logitech_mouse] received byte 00000000
[:board2:comat:serport0:logitech_mouse] received byte 00000078
[:board2:comat:serport0:logitech_mouse] received byte 00000078
[:board2:comat:serport0:logitech_mouse] received byte 00000000
[:board2:comat:serport0:logitech_mouse] received byte 00000000
[:board2:comat:serport0:logitech_mouse] received byte 00000060
[:board2:comat:serport0:logitech_mouse] received byte 0000007e
[:board2:comat:serport0:logitech_mouse] received byte 0000001e
[:board2:comat:serport0:logitech_mouse] received byte 00000078
[:board2:comat:serport0:logitech_mouse] received byte 00000044
[:board2:comat:serport0:logitech_mouse] received byte 00000073

davide125 avatar Sep 06 '20 14:09 davide125

Some (possibly) helpful information in https://github.com/FreeBSDDesktop/freebsd-base/blob/master/usr.sbin/moused/moused.c#L1591

davide125 avatar Sep 06 '20 15:09 davide125

Apparently it works fine in 86Box. Here's the code that emulates the Logitech serial mouse in 86Box. https://github.com/86Box/86Box/blob/master/src/device/mouse_serial.c

fuel-pcbox avatar Sep 06 '20 23:09 fuel-pcbox

Ok, the actual protocol is described here (specifically, section 14.10): http://www.bitsavers.org/pdf/logitech/Logitech_Logimouse_C7_Firmware_Rev_3.0_Jan86.pdf

Specifically, it looks like the driver attempts to enable prompt mode (44), request status (73) and set speed to 4800 baud (70).

davide125 avatar Sep 07 '20 16:09 davide125

Since changing hosts, Bitsavers is now black-holing traffic from at least half the world. This document doesn’t appear to be on a mirror I just checked.

cuavas avatar Sep 07 '20 17:09 cuavas

I put it up here: https://drive.google.com/file/d/15vZMlrFveS21FaWmOQFWBL9ohxK-aIDP/view?usp=sharing and the whole folder at https://drive.google.com/file/d/19RCe08yLYAUqWv9vxdNJUrFQqsodm7UM/view?usp=sharing

Note that this isn't quite the complete story, as there's a few extra commands (like the mode selection stuff like *X mentioned in the freebsd source I linked above) that were likely added later and aren't covered there. Bitsavers also has an actual ROM of this C7 mouse (also in the folder), but I don't know how easy that would be to get running (it's marked as a LSC82406P / MC1146805F2, and I couldn't find an equivalent in MAME, nor a datasheet).

davide125 avatar Sep 07 '20 17:09 davide125

Just thought I'd add that I just ran into this problem a day or two ago with the latest release of MAME (0.258). The workaround of switching away from the default Logitech mouse to the Microsoft mouse allowed the Windows 3.1 Setup program to complete it's switch to Windows mode.

Davidian1024 avatar Sep 19 '23 15:09 Davidian1024