Adding a new device - libratbag/libratbag GitHub Wiki

This is a short outline on how to add a new device, shown on the example of the MX Anywhere 2S. This is the easy way because the support for this device was already in ratbagd but a similar sequence should work for many Logitech devices. If you have a non-Logitech device the below will be informative but won't get your device to work. Only reverse-engineering the protocol will do that.

Check that the device is not yet supported. Plug it in, run:

$ ratbagctl list
No devices available.

ratbagd is a DBus-activated service so remember that it'll start up any time something tries to connect to it via DBus. So we'll need to kill it to have manual control over it:

$ sudo killall ratbagd

There is a risk with leaving ratbagd in place. At some point you'll try to debug some new code only to realize (after an hour) that you're running old code because it auto-activated itself. To avoid this, you can simply rename the system installation so the various DBus bits won't find it.

$ sudo mv /usr/bin/ratbagd /usr/bin/ratbagd.disabled

To undo this, move it back when you're done. This is not strictly necessary but it will save you time.

Note that we intentionally don't remove the system package because it leaves our data files, DBus activation files etc. in place. Makes life a bit easier.

Now let's run it:

$ sudo /usr/bin/ratbagd.disabled --verbose=raw
ratbag debug: New device: Logitech MX Anywhere 2S
ratbag debug: Using data directory '/usr/share/libratbag'
ratbag debug: No data file found for 046d:406a
ratbag debug: New device: Logitech USB Receiver
ratbag debug: Using data directory '/usr/share/libratbag'
ratbag debug: No data file found for 046d:c52b
ratbag debug: New device: ELAN Touchscreen
ratbag debug: Using data directory '/usr/share/libratbag'
ratbag debug: No data file found for 04f3:0224

We see three devices, our mouse, the receiver device and a touchscreen that happens to be in this system. The one we want is the first one. Note that the receiver (c52b) shows up as well but we don't talk to that one, we expect the kernel to handle those.

Looks like we need a data file, so let's do that:

$ sudo cat > /usr/share/libratbag/logitech-mx-anywhere-2s.device <<EOF
[Device]
Name=Logitech MX Anywhere 2S
DeviceMatch=usb:046d:406a
EOF

This is the most minimal data file. The DeviceMatch entry must match the 046d:406a we saw earlier, with a usb: prefixed because that's what our device is. Our output is now:

$ sudo /usr/bin/ratbagd.disabled --verbose=raw
ratbag debug: New device: Logitech MX Anywhere 2S
ratbag debug: Using data directory '/usr/share/libratbag'
ratbag error: Missing Driver in logitech-mx-anywhere-2s.device
ratbag debug: No data file found for 046d:406a

Woo! The file was found, the device was matched but the .device file is incomplete, we're missing the Driver= line. Most Logitech devices use the standard HID++ protocol version 1.0 or 2.0. Any device less than a few years old probably uses HID++2.0 or, in rodent speak: hidpp20. So let's update our .device file to read:

[Device]
Name=Logitech MX Anywhere 2S
DeviceMatch=usb:046d:406a
Driver=hidpp20

If that won't work, we'll just try hidpp10 instead later (disclaimer: this mouse supports HID++ 2.0). Of course, if you have a non-Logitech device the bits below won't be of much use now.

$ sudo /usr/bin/ratbagd.disabled --verbose=raw
ratbag debug: New device: Logitech MX Anywhere 2S
ratbag debug: Using data directory '/usr/share/libratbag'
ratbag debug: device assigned driver hidpp20
ratbag debug: hidraw info: bus 0x03 vendor 0x46d product 0x406a
ratbag debug: Logitech MX Anywhere 2S is device '/dev/hidraw1'.
ratbag debug: HID report ID 01
ratbag debug: HID report ID 0e
ratbag debug: HID report ID 02
ratbag debug: HID report ID 03
ratbag debug: HID report ID 04
ratbag debug: HID report ID 10
ratbag debug: HID report ID 11
ratbag debug: HID report ID 20
ratbag debug: HID report ID 21
ratbag raw: hidpp write: 11 ff 00 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ratbag raw: hidpp read:  10 01 8f 00 18 09 00
ratbag debug:     HID++ error from the device (1): ERR_UNSUPPORTED (09)

Yay? The good news is something happened, but that error is not comforting.... Turns out this device has aggressive power saving and you can't query it while it's asleep. So let's click a button to wake it up and re-run the command:

ratbag debug: New device: Logitech MX Anywhere 2S
ratbag debug: Using data directory '/opt/libratbag/share/libratbag'
ratbag debug: device assigned driver hidpp20
ratbag debug: hidraw info: bus 0x03 vendor 0x46d product 0x406a
ratbag debug: Logitech MX Anywhere 2S is device '/dev/hidraw1'.
ratbag debug: HID report ID 01
ratbag debug: HID report ID 0e
ratbag debug: HID report ID 02
ratbag debug: HID report ID 03
ratbag debug: HID report ID 04
ratbag debug: HID report ID 10
ratbag debug: HID report ID 11
ratbag debug: HID report ID 20
ratbag debug: HID report ID 21
ratbag raw: hidpp write: 11 ff 00 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ratbag raw: hidpp read:  11 01 00 18 04 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ratbag raw: hidpp write: 11 ff 00 08 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ratbag raw: hidpp read:  11 01 00 08 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00
ratbag raw: feature 0x0001 is at 0x01
ratbag raw: hidpp write: 11 ff 01 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ratbag raw: hidpp read:  11 01 01 08 1b 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

.... let's skip the raw read/write debug output ...

ratbag debug: 'Logitech MX Anywhere 2S' is using protocol v4.5
ratbag raw: 'Logitech MX Anywhere 2S' has 28 features
ratbag raw: Init feature HIDPP_PAGE_ROOT (0x0000) 
ratbag raw: feature 0x0000 is at 0x00
ratbag raw: Init feature HIDPP_PAGE_FEATURE_SET (0x0001) 
ratbag raw: feature 0x0001 is at 0x01
ratbag raw: Init feature HIDPP_PAGE_DEVICE_INFO (0x0003) 
ratbag raw: feature 0x0003 is at 0x02
ratbag raw: unknown feature 0x0003
ratbag raw: Init feature HIDPP_PAGE_DEVICE_NAME (0x0005) 
ratbag raw: feature 0x0005 is at 0x03
ratbag raw: unknown feature 0x0005
ratbag raw: Init feature HIDPP_PAGE_WIRELESS_DEVICE_STATUS (0x1d4b) 
ratbag raw: feature 0x1d4b is at 0x04
ratbag raw: unknown feature 0x1d4b
ratbag raw: Init feature HIDPP_PAGE_RESET (0x0020) 
ratbag raw: feature 0x0020 is at 0x05
ratbag raw: unknown feature 0x0020
ratbag raw: Init feature HIDPP_PAGE_BATTERY_LEVEL_STATUS (0x1000) 
ratbag raw: feature 0x1000 is at 0x06
ratbag debug: device battery level is 90% (next 50%), status 0 

... and lots more ...

So yay, it works. Let's see the output without all the extreme verbosity:

$ sudo /usr/bin/ratbagd.disabled --verbose
ratbag debug: New device: Logitech MX Anywhere 2S
ratbag debug: Using data directory '/usr/share/libratbag'
ratbag debug: device assigned driver hidpp20
ratbag debug: hidraw info: bus 0x03 vendor 0x46d product 0x406a
ratbag debug: Logitech MX Anywhere 2S is device '/dev/hidraw1'.
ratbag debug: HID report ID 01
ratbag debug: HID report ID 0e
ratbag debug: HID report ID 02
ratbag debug: HID report ID 03
ratbag debug: HID report ID 04
ratbag debug: HID report ID 10
ratbag debug: HID report ID 11
ratbag debug: HID report ID 20
ratbag debug: HID report ID 21
ratbag debug: 'Logitech MX Anywhere 2S' is using protocol v4.5
ratbag debug: device battery level is 90% (next 50%), status 0 
ratbag debug: device has programmable keys/buttons
ratbag debug: device has 8 buttons
ratbag debug: device has adjustable dpi
ratbag debug: device is at 1000 dpi (variable between 200 and 4000).
ratbag debug: device is at 1000 dpi (variable between 200 and 4000).
ratbag debug: device has 8 buttons
ratbag debug: driver match found: Logitech HID++2.0
hidraw1: "Logitech MX Anywhere 2S", 1 profiles

That's it, we're done. Partially anyway. The next steps are:

As said at the beginning, this is the easy case where the device is already effectively supported by libratbag without any extra work required. It will work for most new Logitech devices but not all of them. It will not work for devices from other vendors that have their own custom protocol.

So what if you have a custom protocol? You will need to create a new driver (see e.g. src/driver-steelseries.c) and make it talk the device's protocol. Then you change the driver name in the .device file to your new driver and voila, you're done.