(with thanks to the semi-anonymous comment on my last post for pointing me more firmly at the evdev subsystem)
The MX Air mouse presents two separate HID devices. I’d noticed this before, but hadn’t worked out the significance until this afternoon when I had a tentative first stab at getting the mouse working with the X.org evdev driver.
The first device looks like:
peter@mugen:~% udevinfo -q env -n /dev/input/event3 ID_VENDOR=Logitech ID_MODEL=USB_Receiver ID_REVISION=0200 ID_SERIAL=Logitech_USB_Receiver ID_TYPE=hid ID_BUS=usb ID_CLASS=mouse ID_PATH=pci-0000:00:02.0-usb-0:4:1.0
This is a standard mouse device. All the movement and regular button/scroll events are delivered via this device, as well as the BACK and SEL buttons on the MX Air.
The second device is registered as a keyboard device:
peter@mugen:~% udevinfo -q env -n /dev/input/event4 ID_VENDOR=Logitech ID_MODEL=USB_Receiver ID_REVISION=0200 ID_SERIAL=Logitech_USB_Receiver ID_TYPE=hid ID_BUS=usb ID_PATH=pci-0000:00:02.0-usb-0:4:1.1
Key press events from the play/pause and volume buttons are delivered through this device. All of the existing gesture-based commands are also translated to key presses and presented here.
Looking at both these interfaces with evtest (or its bastard cousin evtest.py) shows that the mouse does indeed to almost everything as expected. When the BACK button is pressed, evtest watching the mouse device will report
Event: time 1197461330.787205, type 1 (Key), code 275 (SideBtn), value 1 Event: time 1197461330.787220, -------------- Report Sync ------------ Event: time 1197461330.803196, type 1 (Key), code 275 (SideBtn), value 0 Event: time 1197461330.803205, -------------- Report Sync ------------
And for a gesture-based command (pick up the mouse, hold the play button, and swing it to the right), we see the following reported on the keyboard device
Event: time 1197461453.051174, type 1 (Key), code 163 (NextSong), value 1 Event: time 1197461453.051184, -------------- Report Sync ------------ Event: time 1197461453.058187, type 1 (Key), code 163 (NextSong), value 0 Event: time 1197461453.058197, -------------- Report Sync ------------
Unfortunately, once again, using the standard Linux HID driver there’s no unique event generated on either interface when the mouse switches from desk mode to air mode and back. But by passing control of the mouse to a virtual machine running Windows XP and Logitech’s SetPoint software, we can let it do… uh… magic mouse stuff, and we start to see more events.
I’ve been using a personal licence of VirtualBox to do this, as it seems to be the only virtualisation product that gives full raw access to USB2 devices. It does it by detaching the device from any drivers in the host kernel that have claimed it, and then the guest gets complete access. This means the event subsystem becomes basically useless, but by using the usbmon facility in the host I’m still able to get a text dump of all traffic in both directions on the appropriate bus (it helps to have the mouse on a bus on its own for this).
Capturing an entire session from the guest OS detecting the device until the bus settles again takes around four seconds on my machine, and results in approximately 6KB of data transferred back and forth, a mix of control and interrupt I/O. I have no idea yet how much of this is standard USB chatter and how much is specific to this application. Additionally, I’ve seen a lot of mixed opinions on whether usbmon presents entire packets or caps output, so right now I’m not even sure if I’ve captured everything. But at the end of it all, Windows will happily perform events keyed off which mode the mouse is in.
Even better, once this initialisation has been done, it’s possible to detach the mouse from the virtual machine, and then remove and reload the
usbhid module so the mouse is usable in Linux again. Once that’s done, we can attach evtest to the mouse device again, pick up the mouse, and bam
Event: time 1197447907.035723, type 1 (Key), code 284 (?), value 1 Event: time 1197447907.035735, -------------- Report Sync ------------
Put the mouse back down, and as soon as it notices its getting input from the laser again, we see a corresponding release event:
Event: time 1197447909.698531, type 1 (Key), code 284 (?), value 0 Event: time 1197447909.698542, -------------- Report Sync ------------
There’s already existing projects like lomoco around that can talk Logitechese. Presumably the MX Air is just using a superset of the existing command set. The smart money now seems to be trying to get it working with one of those.
Oh, and as far as using the evdev device in Xorg? Well, I didn’t get it working. I think that may be because I was configuring the mouse device with the
"Name" option to evdev. I realise now that that would pick up both the mouse and keyboard devices, and probably confuse the hell out of something only expecting a single pointer.