Skip to content

MX Air in evdev

(with thanks to the semi-anonymous com­ment on my last post for point­ing me more firmly at the evdev subsystem)

The MX Air mouse presents two sep­ar­ate HID devices. I’d noticed this before, but hadn’t worked out the sig­ni­fic­ance until this after­noon when I had a tent­at­ive first stab at get­ting the mouse work­ing 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 stand­ard mouse device. All the move­ment and reg­u­lar button/scroll events are delivered via this device, as well as the BACK and SEL but­tons on the MX Air.

The second device is registered as a key­board 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 but­tons are delivered through this device. All of the exist­ing gesture-based com­mands are also trans­lated to key presses and presen­ted here.

Look­ing at both these inter­faces with evtest (or its bas­tard cousin evtest.py) shows that the mouse does indeed to almost everything as expec­ted. When the BACK but­ton is pressed, evtest watch­ing 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 com­mand (pick up the mouse, hold the play but­ton, and swing it to the right), we see the fol­low­ing repor­ted on the key­board 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 ------------

Unfor­tu­nately, once again, using the stand­ard Linux HID driver there’s no unique event gen­er­ated on either inter­face when the mouse switches from desk mode to air mode and back. But by passing con­trol of the mouse to a vir­tual machine run­ning Win­dows XP and Logitech’s Set­Point soft­ware, we can let it do… uh… magic mouse stuff, and we start to see more events.

I’ve been using a per­sonal licence of Vir­tu­al­Box to do this, as it seems to be the only vir­tu­al­isa­tion product that gives full raw access to USB2 devices. It does it by detach­ing the device from any drivers in the host ker­nel that have claimed it, and then the guest gets com­plete access. This means the event sub­sys­tem becomes basic­ally use­less, but by using the usb­mon facil­ity in the host I’m still able to get a text dump of all traffic in both dir­ec­tions on the appro­pri­ate bus (it helps to have the mouse on a bus on its own for this).

Cap­tur­ing an entire ses­sion from the guest OS detect­ing the device until the bus settles again takes around four seconds on my machine, and res­ults in approx­im­ately 6KB of data trans­ferred back and forth, a mix of con­trol and inter­rupt I/O. I have no idea yet how much of this is stand­ard USB chat­ter and how much is spe­cific to this applic­a­tion. Addi­tion­ally, I’ve seen a lot of mixed opin­ions on whether usb­mon presents entire pack­ets or caps out­put, so right now I’m not even sure if I’ve cap­tured everything. But at the end of it all, Win­dows will hap­pily per­form events keyed off which mode the mouse is in.

Even bet­ter, once this ini­tial­isa­tion has been done, it’s pos­sible to detach the mouse from the vir­tual machine, and then remove and reload the usbhid mod­ule 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 get­ting input from the laser again, we see a cor­res­pond­ing release event:

Event: time 1197447909.698531, type 1 (Key), code 284 (?), value 0
Event: time 1197447909.698542, -------------- Report Sync ------------

There’s already exist­ing pro­jects like lomoco around that can talk Logit­echese. Pre­sum­ably the MX Air is just using a super­set of the exist­ing com­mand set. The smart money now seems to be try­ing to get it work­ing with one of those.

Oh, and as far as using the evdev device in Xorg? Well, I didn’t get it work­ing. I think that may be because I was con­fig­ur­ing the mouse device with the "Name" option to evdev. I real­ise now that that would pick up both the mouse and key­board devices, and prob­ably con­fuse the hell out of some­thing only expect­ing a single pointer.