libratbag / libratbag Goto Github PK
View Code? Open in Web Editor NEWA DBus daemon to configure input devices, mainly high-end and gaming mice
License: MIT License
A DBus daemon to configure input devices, mainly high-end and gaming mice
License: MIT License
libratbag just needs access to an appropriate hidraw device, right?
If so, one could make an udev rule that adds the uaccess
tag to the right hidraw device, which would make systemd-logind give access to the device to whatever user is currently logged in locally (like it does with soundcard, etc.).
I wrote a little quick rule to do this with my G300S, but I'm matching the USB ID directly:
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c246", TAG+="uaccess"
ratbag-command seems to work without root with this rule.
I think it'd be better if it used the hwdb somehow, instead of matching one particular mouse, but I have no idea how to use hwdb.
I have the Logitech G500s and running the dpi set
command causes an assertion error.
$ sudo tools/ratbag-command dpi set 800 /dev/input/event5
ratbag-command: libratbag.c:925: ratbag_resolution_set_dpi: Assertion `profile->device->driver->write_resolution_dpi' failed.
Currently, libratbag only allows to change the value of a resolution within a profile. When the profile supports several resolutions that can be toggled, libratbag doesn't export the required API to change between those resolutions.
in hidpp10.c, coverity complains that the 0x2 has no effect on the operation and always results in false.
Looks like we're mixing datatypes here, led is a boolean array but the hidpp10 backend wants 0x1 and 0x2 for off/on (iirc). @bentiss, most of the git blame is on you, so maybe you remember how this was supposed to work.
1526 hidpp_log_raw(&dev->base,
1527 "LED status: 1:%s 2:%s 3:%s 4:%s\n",
1528 (profile->dpi_modes[i].led[0] & 0x2) ? "on" : "off",
1529 (profile->dpi_modes[i].led[1] & 0x2) ? "on" : "off",
1530 (profile->dpi_modes[i].led[2] & 0x2) ? "on" : "off",
1531 (profile->dpi_modes[i].led[3] & 0x2) ? "on" : "off");
gaming mice can have keyboard like functionality too. see roccat's devices e.g.
e.g. i can have hardware macros on the mouse. bind the mouse buttons to the multimedia keys and more.
also did you checkout their libgaminggear?
The G302 shows:
ratbag raw: sensor 0: current dpi: 1596 (default: 0) min: 252 max: 4032 steps: 84 ratbag debug: device is at 1596 dpi (variable between 252 and 4032).
While LGS has 48 steps from 240 - 4000.
Is this common for the mice using HID++2.0? Which range should I use for the hwdb entry?
Hi,
I may do this myself when I find some time to do so, but I completely reverse-engineered the USB protocol for these gaming mice (see https://github.com/MayeulC/Saitek as well as the associated wiki for code and documentation), so it should be quite easily feasible by someone else too.
I am just letting you know ;)
There are several points of which I am unsure about profiles. I think there is need for a discussion on this.
In the code, I have seen you use three profiles for the G500s. But I have only seen LGS use two: the temporary one in page 0 and a permanent one in the memory (page 2 for my G500 and I think my G500s use this one too). Actually you can write as many profiles as you can fit in memory, but they can only be switched from the driver, so it is not really useful.
The CMD_PROFILE command (0x0F), is one of the command I have documented that I least understand. It did not always behave like I intended in ways I did not manage to reproduce. I must be missing something.
But I know never found a way to get from where in the memory the current profile. I don't know how hidpp10_get_current_profile could be implemented.
About the page for the default permanent profile: I mainly tested the commands on my G500 and I quite sure it is on page 2, but I am less certain about the G500s, I will redo some tests. Or maybe there is something else that determine the location of the default profile.
The G900 introduced a new special usage RATBAG_BUTTON_ACTION_SPECIAL_BATTERY_LEVEL (the one we already have in the G700(s)). This usage is only valid for wireless mice, but the current libratbag implementation does not allow us to tell which device support which special action.
We should export this capabilities to the caller so it knows which special/key/macro it can use.
(we might close this as NOT_A_BUG but we need to keep it in mind for hid++ given that we are somewhat generic for Logitech devices)
Triggered by a47f506 which replaced the - in the man page with -
I think it's the wrong thing to do tbh. Can't see a difference in the man page but when converting to PDF, it puts a minus sign in, instead of a hyphen. Looks wrong tbh and http://man7.org/linux/man-pages/man7/groff_char.7.html says
the ISO latin1 ‘Hyphen, Minus Sign’ (code 45) prints as a hyphen; a minus sign can be obtained with ‘-’.
Given the double meaning of "-" on the terminal, "minus minus help" or "dash dash help", we shouldn't be using the explicit minus sign. Definitely not on concatenated words like ratbag-command which is now rendered as "ratbag minus command"
cc @skitt, any comments?
It'd be nice if there was a complete list of dependencies somewhere so I can avoid the whole build-getError-installDependency-repeat loop to find them all, especially when it complains about things like check
for which it's not clear what I actually need to install...
Hi,
these are the steps I have done:
1)
I installed libratbag from this corp:
https://copr.fedorainfracloud.org/coprs/bentiss/libratbag/
2)
Then I make sure the systemd service is enabled:
[valerio@valerio-casa ~]$ sudo systemctl status ratbagd.service
● ratbagd.service - Daemon to introspect and modify configurable mice
Loaded: loaded (/usr/lib/systemd/system/ratbagd.service; disabled; vendor preset: disabled
Active: active (running) since mar 2016-09-06 18:21:48 CEST; 2s ago
Main PID: 3284 (ratbagd)
Tasks: 1 (limit: 512)
CGroup: /system.slice/ratbagd.service
└─3284 /usr/bin/ratbagd
set 06 18:21:48 valerio-casa systemd[1]: Starting Daemon to introspect and modify configurabl
set 06 18:21:48 valerio-casa systemd[1]: Started Daemon to introspect and modify configurable
3)
Then I anplug-replug the mouse (it is a G300s).
[valerio@valerio-casa ~]$ xinput --list
⎡ Virtual core pointer id=2 [master pointer (3)]
⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)]
⎜ ↳ Logitech USB Keyboard id=9 [slave pointer (2)]
⎜ ↳ Logitech G300s Optical Gaming Mouse id=11 [slave pointer (2)]
⎣ Virtual core keyboard id=3 [master keyboard (2)]
↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)]
↳ Power Button id=6 [slave keyboard (3)]
↳ Power Button id=7 [slave keyboard (3)]
↳ Logitech USB Keyboard id=8 [slave keyboard (3)]
↳ Logitech USB Keyboard id=12 [slave keyboard (3)]
↳ Logitech G300s Optical Gaming Mouse id=10 [slave keyboard (3)]
run the command: ratbag-command list
[valerio@valerio-casa ~]$ sudo ratbag-command list
[sudo] password for valerio:
No supported devices found
What I'm missed or what is wrong with the steps I have done?
Regards,
Valerio
In CMD_READ_MEMORY, you use a 16 bits offset. I am not sure what the real size offset but I don't think it makes sense. Since pages are 512 byte long, the maximum offset is 0xFF. And if you look at the parameters for the memory op command (0xA0), there is no room to have the two offsets be 16 bits with the same endianness.
Here is a test with offset 0x100 on my G500:
$ xxd -r -p <<< "10 00 83 A2 02 00 00" | src/send-raw-request /dev/hidraw1 | xxd -g 1
00000000: 11 00 83 a2 ff 00 00 80 00 11 00 11 22 11 00 22 ............".."
00000010: 00 22 22 12 ."".
$ xxd -r -p <<< "10 00 83 A2 02 00 01" | src/send-raw-request /dev/hidraw1 | xxd -g 1
00000000: 11 00 83 a2 ff 00 00 80 00 11 00 11 22 11 00 22 ............".."
00000010: 00 22 22 12 ."".
$ xxd -r -p <<< "10 00 83 A2 03 00 00" | src/send-raw-request /dev/hidraw1 | xxd -g 1
00000000: 11 00 83 a2 00 ff 00 80 00 09 00 09 22 11 00 22 ............".."
00000010: 00 22 22 1
It looks like the third byte is ignored.
I played around with piper and noticed that some button mappings are wrong.
As you can see in the picture Button 6 and 7 are mapped as Wheel Left and Right and Button 8 and 9 for the Resolution Control. But these mappings are actually the other way round. Also shouldn't the arrows of Button 8 and 9 point left and right?
ratbag_led_get_effect_rate() says: The LED rate in Hz, can be 100 - 20000
.
100Hz is something the eye doesn't distinguish, so 20000 is insanely more insane :)
I think the intend was to express the period in ms of the effect, not in Hz.
(opening an issue given it's public API).
Reported by @cvuchener
I have a Logitech MX Master. By default, the thumb button (Button 5) acts as a "gesture" button, grabbing all mouse movement events and deciding which action to take upon button release. For whatever reason, under Linux, this results in a press-release sequence of Ctrl+Alt+Tab if the mouse isn't moved before releasing, and no keys if the mouse is moved before releasing.
I ran ratbag-command info /dev/input/event0
initially, which read/wrote the following data (as reported by strace):
open("/dev/hidraw1", O_RDWR) = 3 ioctl(3, HIDIOCGRAWINFO, 0x7ffe6d093480) = 0 ioctl(3, HIDIOCGRDESCSIZE or HIDIOCGVERSION, 0x7ffe6d09240c) = 0 ioctl(3, HIDIOCGRDESC, 0x7ffe6d092410) = 0 ioctl(3, HIDIOCGRDESCSIZE or HIDIOCGVERSION, 0x7ffe6d09240c) = 0 ioctl(3, HIDIOCGRDESC, 0x7ffe6d092410) = 0 write(3, "\21\377\0\30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\30\4\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\1\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\10\36\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\0\1\0\1\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\0\3\0\2\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\35K\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\30\6`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\30\24\0\1\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\t\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\33\4\0\3\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\n\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\"\1\0\1\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\v\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30!\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\f\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30!\20\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\r\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30!!\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\16\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30e\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\17\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\0\301\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\30\23`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\21\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\0300`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\22\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\30\220`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\23\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\30\221`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\24\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\30\241`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\25\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\30\300`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\26\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\35\363`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\27\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\36\0@\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\36\260`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\31\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\30\3`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\32\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\30a`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\33\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\220\0`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\34\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\222\0`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\35\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\222@`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\1\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\0\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\2\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\35K\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\6\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\6\0102\24\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\30\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\7`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\30\24\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\10\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\33\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\t\0\3\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\10\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0P\0008\1\0\1\1\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0P\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0P\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0Q\0009\1\0\1\1\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0Q\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0Q\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0R\0:1\0\3\7\1\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0R\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0R\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0S\0<1\0\2\3\1\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0S\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0S\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0V\0>1\0\2\3\1\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0V\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0V\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0\303\0\2511\0\3\7\1\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0\303\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0\303\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0\304\0\2351\0\3\7\1\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0\304\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0\304\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0\327\0\264\240\0\4\0\3\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0\327\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0\327\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\"\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\n\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\n\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\n\10\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\n\30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\n\30\0\1\220\340\310\6@\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\n(\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\n(\0\3\350\3\350\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10!\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\v\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10!\20\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\f\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10!!\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\r\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10e\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\16\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\0\301\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\17\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\30\23\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\20`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\0300\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\21`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\30\220\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\22`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\30\221\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\23`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\30\241\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\24`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\30\300\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\25`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\35\363\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\26`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\36\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\27@\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\36\260\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\30`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\30\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\31`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\30a\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\32`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\220\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\33`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\222\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\34`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\222@\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\35`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\n\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\n\10\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\n\30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\n\30\0\1\220\340\310\6@\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\n(\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\n(\0\3\350\3\350\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\10\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0P\0008\1\0\1\1\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0P\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0P\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0Q\0009\1\0\1\1\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0Q\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0Q\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0R\0:1\0\3\7\1\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0R\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0R\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0S\0<1\0\2\3\1\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0S\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0S\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0V\0>1\0\2\3\1\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0V\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0V\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0\303\0\2511\0\3\7\1\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0\303\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0\303\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0\304\0\2351\0\3\7\1\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0\304\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0\304\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0\327\0\264\240\0\4\0\3\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0\327\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0\327\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20
and gave the output:
Device 'Logitech MX Master'
Capabilities: res btn-key
Number of buttons: 8
Profiles supported: 1
Profile 0 (active)
Resolutions:
0: 1000dpi @ 0Hz (active)
Button: 0 type left is mapped to 'button 1'
Button: 1 type right is mapped to 'button 2'
Button: 2 type middle is mapped to 'button 3'
Button: 3 type side (backward) is mapped to 'button 4'
Button: 4 type extra (forward) is mapped to 'button 5'
Button: 5 type unknown is mapped to 'none'
Button: 6 type wheel ratchet mode switch is mapped to 'UNKNOWN'
Button: 7 type unknown is mapped to 'none'
Then I ran ratbag-command button 5 action set button 1
, which returned 0.
Afterward, the thumb button doesn't do anything at all (neither interferes with mouse movement reporting like previously, nor emits any events as shown by libinput-debug-events
upon press or release). I can't find any configuration that results in the thumb button actually performing user-assigned actions.
The output of running info again shows button 5 as being mapped to 'button 1'; the data from the mouse, as per strace, is below:
open("/dev/hidraw1", O_RDWR) = 3 ioctl(3, HIDIOCGRAWINFO, 0x7ffee833ab60) = 0 ioctl(3, HIDIOCGRDESCSIZE or HIDIOCGVERSION, 0x7ffee8339aec) = 0 ioctl(3, HIDIOCGRDESC, 0x7ffee8339af0) = 0 ioctl(3, HIDIOCGRDESCSIZE or HIDIOCGVERSION, 0x7ffee8339aec) = 0 ioctl(3, HIDIOCGRDESC, 0x7ffee8339af0) = 0 write(3, "\21\377\0\30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 0 (Timeout) read(3, "\21\1\0\30\4\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\1\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\10\36\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\0\1\0\1\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\0\3\0\2\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\35K\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\30\6`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\30\24\0\1\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\t\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\33\4\0\3\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\n\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\"\1\0\1\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\v\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30!\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\f\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30!\20\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\r\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30!!\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\16\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30e\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\17\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\0\301\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\30\23`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\21\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\0300`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\22\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\30\220`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\23\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\30\221`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\24\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\30\241`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\25\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\30\300`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\26\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\35\363`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\27\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\36\0@\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\36\260`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\31\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\30\3`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\32\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\30a`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\33\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\220\0`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\34\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\222\0`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\1\30\35\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\1\30\222@`\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\1\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\0\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\2\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\35K\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\6\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\6\0102\24\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\30\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\7`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\30\24\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\10\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\33\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\t\0\3\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\10\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0P\0008\1\0\1\1\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0P\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0P\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0Q\0009\1\0\1\1\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0Q\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0Q\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0R\0:1\0\3\7\1\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0R\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0R\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0S\0<1\0\2\3\1\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0S\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0S\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0V\0>1\0\2\3\1\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0V\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0V\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0\303\0\2511\0\3\7\1\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0\303\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0\303\1\0P\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0\304\0\2351\0\3\7\1\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0\304\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0\304\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0\327\0\264\240\0\4\0\3\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0\327\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0\327\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\"\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\n\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\n\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\n\10\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\n\30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\n\30\0\1\220\340\310\6@\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\n(\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\n(\0\3\350\3\350\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10!\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\v\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10!\20\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\f\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10!!\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\r\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10e\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\16\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\0\301\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\17\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\30\23\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\20`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\0300\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\21`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\30\220\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\22`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\30\221\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\23`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\30\241\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\24`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\30\300\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\25`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\35\363\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\26`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\36\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\27@\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\36\260\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\30`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\30\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\31`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\30a\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\32`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\220\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\33`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\222\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\34`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\0\10\222@\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\0\10\35`\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\n\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\n\10\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\n\30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\n\30\0\1\220\340\310\6@\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\n(\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\n(\0\3\350\3\350\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\10\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0P\0008\1\0\1\1\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0P\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0P\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0Q\0009\1\0\1\1\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0Q\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0Q\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0R\0:1\0\3\7\1\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0R\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0R\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\2\0\0\2\300\377\0\0", 20) = 8 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0S\0<1\0\2\3\1\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0S\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\2\0\0\fp\376\0\0", 20) = 8 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0S\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\2\0\0\25`\375\0\0", 20) = 8 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0V\0>1\0\2\3\1\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0V\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\2\0\0\16\360\375\0\0", 20) = 8 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0V\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\2\0\0\4\360\376\0\0", 20) = 8 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0\303\0\2511\0\3\7\1\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0\303\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\2\0\0\363\37\0\0\0", 20) = 8 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0\303\1\0P\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\2\0\0\357\177\0\0\0", 20) = 8 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0\304\0\2351\0\3\7\1\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0\304\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\2\0\0\364/\0\0\0", 20) = 8 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0\304\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t\30\7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\2\0\0\374\37\0\0\0", 20) = 8 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t\30\0\327\0\264\240\0\4\0\3\0\0\0\0\0\0\0", 20) = 20 write(3, "\21\377\t(\0\327\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20 poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}]) read(3, "\21\1\t(\0\327\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20
I also seem unable to get the output back to what it was originally; is there any way to clear button actions or assign "none"? I don't know whether it's reasonable to expect this to reset the thumb behavior to what it does by default, but it's a reasonable configuration someone might want even if not.
In addition, I have no idea what button 7 as reported by ratbag-command info
might be, and it would be nice to rename the "UNKNOWN" default action of the wheel-ratchet-mode-switch button to something like "toggle ratchet".
make install places the following files:
$DESTDIR/usr/lib64/udev/hwdb.d/70-libratbag-mouse.hwdb
$DESTDIR/usr/lib64/udev/rules.d/70-libratbag-mouse.rules
This is incorrect and is a regression introduced by
$ git blame configure.ac
c12cb66 (Peter Hutterer 2016-03-15 09:43:49 +1000 65) UDEV_BASE_DIR="$libdir/udev"
What it should have probably be: $prefix/lib/udev or $libexecdir/udev.
I would like to point out that identifiers like "__ratbag_find_hidraw
" and "__test_probe
" do not fit to the expected naming convention of the C language standard.
Would you like to adjust your selection for unique names?
G700s while connected by cable I get
$ sudo ratbag-command list
ratbag error: USB error: Connection timed out (110)
write: No such file or directory
/dev/input/event8: Logitech G700s Rechargeable Gaming Mouse
$ sudo ratbag-command --verbose=raw info /dev/input/event8
ratbag debug: Logitech USB Receiver is device '/dev/hidraw0'.
ratbag debug: Logitech USB Receiver is device '/dev/hidraw1'.
ratbag debug: report ID 01
ratbag debug: report ID 03
ratbag debug: report ID 04
ratbag debug: report ID 10
ratbag debug: report ID 11
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 ff 8f 00 18 01 00
ratbag debug: HID++ error from the device (255): ERR_INVALID_SUBID (01)
ratbag debug: Logitech USB Receiver is device '/dev/hidraw0'.
ratbag debug: Logitech USB Receiver is device '/dev/hidraw1'.
ratbag debug: report ID 01
ratbag debug: report ID 03
ratbag debug: report ID 04
ratbag debug: report ID 10
ratbag debug: report ID 11
ratbag raw: Fetching individual features
ratbag raw: expected_header: ?? 00 81 01
ratbag raw: expected_error_dev: 10 00 8f 81 01 00 00
ratbag raw: hidpp write: 10 00 81 01 00 00 00
ratbag raw: hidpp read: 10 00 8f 81 01 08 00
ratbag raw: HID++ error from the device (0): ERR_UNKNOWN_DEVICE (08)
ratbag raw: Fetching HID++ notifications
ratbag raw: expected_header: ?? 00 81 00
ratbag raw: expected_error_dev: 10 00 8f 81 00 00 00
ratbag raw: hidpp write: 10 00 81 00 00 00 00
ratbag raw: hidpp read: 10 00 8f 81 00 08 00
ratbag raw: HID++ error from the device (0): ERR_UNKNOWN_DEVICE (08)
ratbag raw: Fetching current resolution
ratbag raw: expected_header: ?? 00 83 63
ratbag raw: expected_error_dev: 10 00 8f 83 63 00 00
ratbag raw: hidpp write: 10 00 83 63 00 00 00
ratbag raw: hidpp read: 10 00 8f 83 63 08 00
ratbag raw: HID++ error from the device (0): ERR_UNKNOWN_DEVICE (08)
ratbag raw: Fetching LED status
ratbag raw: expected_header: ?? 00 81 51
ratbag raw: expected_error_dev: 10 00 8f 81 51 00 00
ratbag raw: hidpp write: 10 00 81 51 00 00 00
ratbag raw: hidpp read: 10 00 8f 81 51 08 00
ratbag raw: HID++ error from the device (0): ERR_UNKNOWN_DEVICE (08)
ratbag raw: Fetching USB refresh rate
ratbag raw: expected_header: ?? 00 81 64
ratbag raw: expected_error_dev: 10 00 8f 81 64 00 00
ratbag raw: hidpp write: 10 00 81 64 00 00 00
ratbag raw: hidpp read: 10 00 8f 81 64 08 00
ratbag raw: HID++ error from the device (0): ERR_UNKNOWN_DEVICE (08)
ratbag raw: Fetching optical sensor settings
ratbag raw: expected_header: ?? 00 81 61
ratbag raw: expected_error_dev: 10 00 8f 81 61 00 00
ratbag raw: hidpp write: 10 00 81 61 00 00 00
ratbag raw: hidpp read: 10 00 8f 81 61 08 00
ratbag raw: HID++ error from the device (0): ERR_UNKNOWN_DEVICE (08)
ratbag raw: Fetching the profiles' directory
ratbag debug: no profile type given
ratbag raw: Fetching current profile
ratbag raw: expected_header: ?? 00 81 0f
ratbag raw: expected_error_dev: 10 00 8f 81 0f 00 00
ratbag raw: hidpp write: 10 00 81 0f 00 00 00
ratbag raw: hidpp read: 10 00 8f 81 0f 08 00
ratbag raw: HID++ error from the device (0): ERR_UNKNOWN_DEVICE (08)
ratbag debug: no profile type given
ratbag debug: no profile type given
ratbag raw: Fetching profile 0
ratbag debug: no profile type given
ratbag raw: Fetching profile 0
ratbag debug: no profile type given
ratbag debug: driver match found: Logitech HID++1.0
Device 'Logitech USB Receiver'
Capabilities:
Number of buttons: 3
Profiles supported: 1
Profile 0 (enabled) (active)
Resolutions:
0: <disabled>
Button: 0 type left is mapped to 'none'
Button: 1 type middle is mapped to 'none'
Button: 2 type right is mapped to 'none'
(connecting wireless gives exactly the same output as in issue #92)
Did I do something wrong?
Hi everyone, awesome work! I have a Logitech G700s mouse which currently seems to be unsupported. What would be required to add support for that device type?
reproducer here is the G500s, symptom is that this device has two event nodes and I'm getting a "no hidraw device found" on each ratbagd start. ratbag-command list lists both event nodes as supported and both show the same info. but: ratbag_open_hidraw_node() has a check so we don't open the same hidraw node twice for two devices. It returns -ENODEV which triggers the error message.
ratbag-command list papers over this because we close the first device before we look at the second one, thus never triggering that code path.
I'm using a tiny subset of hid++ in the fwupd unifying updater plugin in fwupd: https://github.com/hughsie/fwupd/blob/master/plugins/unifying/unifying-dongle.c#L34
It would be really good to either have a file we can share, or include in either build. I'm happy just merging your file into mine, but a better solution might be to have a hidpp-constants.h in libratbag that I can copy into fwupd.
One prerequisite is that the HID++ constants need a HIDPP_ prefix to avoid things like ERR_BUSY conflicting with other things in fwupd.
Comments welcome, thanks.
we've already merged a bunch of patches without it and many projects don't bother with it anyway. How about we drop this too? any comments?
The active resolution can only be retrieved for the middle and upper DPIs for my G500s, when I have it set to the lowest (so there's only 1 LED on indicating the DPI setting) then it fails to report the active resolution.
So this is me polling the active resolution starting at the highest DPI (all 3 LED indicators are on on the mouse) and then decreasing 1 level before running the command again and then going back up:
~ Projects libratbag sudo tools/ratbag-command resolution active get /dev/input/event5
2
~ Projects libratbag sudo tools/ratbag-command resolution active get /dev/input/event5
1
~ Projects libratbag sudo tools/ratbag-command resolution active get /dev/input/event5
Error: Failed to retrieve the active resolution
~ Projects libratbag sudo tools/ratbag-command resolution active get /dev/input/event5
1
~ Projects libratbag sudo tools/ratbag-command resolution active get /dev/input/event5
2
I tried doing a little debugging, and it looks like the problem is pretty deep. If I use gdb to look at ratbag_profile_get_resolution()
, the first profile has an is_active
member of false. So actually retrieving the data from the mouse is incorrect it looks like.
Extract of the G900:
Profile 4
Resolutions:
0: 400dpi @ 1000Hz
1: 800dpi @ 1000Hz (default)
2: 1600dpi @ 1000Hz
3: 3200dpi @ 1000Hz
4:
Button: 0 type unknown is mapped to 'button 1'
Button: 1 type unknown is mapped to 'button 2'
Button: 2 type unknown is mapped to 'button 3'
Button: 3 type unknown is mapped to 'button 4'
Button: 4 type unknown is mapped to 'button 5'
Button: 5 type unknown is mapped to 'button 4'
Button: 6 type unknown is mapped to 'button 5'
Button: 7 type unknown is mapped to 'resolution down'
Button: 8 type unknown is mapped to 'resolution up'
Button: 9 type unknown is mapped to 'wheel left'
Button: 10 type unknown is mapped to 'wheel right'
Button: 11 type unknown is mapped to 'profile cycle up'
Type "unknown" should be filled properly
Would you like to add more error handling for return values from functions like the following?
I am trying to make a list of things we cannot guess from the HID++ 1.0 protocol only.
Needed for correctly using the mouse protocol:
Some features are present/tolerated in the protocol but don't do anything. They won't prevent the driver from successfully communicating with the mouse, but the feature will appear broken to the user.
ratbag error: ROCCAT ROCCAT Kone XTD: driver specified in hwdb not found: roccat
Error: Device '/dev/input/event10' is not supported
First event node works though. Either this should fail with a better message or not fail.
[Hi,]
I have installed Piper (with Libratbag & Ratbagd) on Arch, but when I run Piper I am unable save device settings onto device (but I can change device settings & I can see the current loaded presets).
I am guessing the "Here, picture, picture, picture" is an error message, but I don't quite know where to trouble shoot from here.
Any help would be most appreciated, really love Libratbag! Great project!
Cheers,
Alex
We are currently trying to provide stable ABI in libratbag by bumping the soname when needed and properly exporting the symbols. We are not guarantee to introduce any breakage unless we rely on ABI comparison between versions.
libaigail allows to run ABI checks between .so.
It would be interesting to add such comparison in the semaphore script.
libabigail provides a tool abidiff which compares 2 .so and returns a non null value in case of an ABI failure. The 2 .so need to be compiled with debug information (DWARF style, obtained by appending "-g" to the CPPFLAGS).
We should compare the ABI to the last tagged git entry and/or to the last soname bump.
(I propose we try to integrate libabigail in our continuous integration so we can have the same type of check in libinput, libevdev, etc... )
[CC @whot @jwrdegoede @cvuchener @phomes @tolga9009 @mbuesch @skitt @ogay @xnlcasad -- add more people if you believe they are interested in]
After a long thinking, I am finally starting to believe we should probably envision the fact of supporting keyboards too. I know we shut down the idea multiple times, and that's why I'd like to have an open discussion about it.
I am thinking of gearing myself with a G910 from Logitech and a K70 RGB from Corsair to have at least 2 vendors. @gicmo has access to a Razer Blade (not sure from how long), so this would give us 3 vendors.
To start the discussion, I think we should first do a little state of the art and define what we want to support for keyboards. I personally don't want to open too much the thing, so I would say we should not support more than what we support in mice nowadays:
The 3 keyboards I am looking at are rather similar (images are not hosted here, so they may drop):
(note that each LED can be individually lit up, even if it's not shown here).
Most mechanical keyboards have macro keys available. We currently support macro in libratbag, and for Logitech devices, the protocol is the same. So it shouldn't be much of an issue to add macro keys.
Not all keys can be mapped on all keyboards, so we might export only 5 keys for a full keyboard. It looks like the K70 can remap any key, I haven't checked on the other vendor products.
Looking at this picture, it seems that we can individually light up each key.
This should be easily doable in libratbag because the LED are exported individually.
Note that the Razer Blade Pro 2017 has a specific lighting around the touchpad:
We can apply a global effect to the keyboard (color wave, star light, ripple, etc...)
Not sure how to handle this, but this is something to consider.
I think those keyboards handle profiles, so should we.
Yeah, we probably don't want to go there.
https://github.com/mattanger/ckb-next
I really like the design of the UI :)
https://sourceforge.net/projects/roccat/
The UI is IMO less polished than ckb-next. Still, it's there and there is existing code for it.
https://github.com/mbuesch/razer
Does it support keyboards?
Edit: from @mbuesch :
I originally designed the internal APIs and structures of razercfg with the idea in mind for keyboard support to be added, but I never added an actual driver backend for any keyboard.
https://terrycain.github.io/razer-drivers/
Support different UI, for instance:
https://github.com/lah7/polychromatic
https://github.com/GabMus/razerCommander
https://github.com/z3ntu/RazerGenie
https://github.com/keyleds/keyleds
It supports both compiled plugins and scripted animations (in LUA) and can react to keypresses and desktop events such as current window changing title. It does not need root access.
https://github.com/MatMoul/g810-led
CLI only
Feel free to add more link to other projects
Regarding forking the project, I already been suggested libwasd as for the name :)
Forking would be cleaner. But OTOH, a lot of the boilerplate is already there in libratbag, so maybe forking is not so good.
Like having in a low level library the drivers, the protocols, and the objects. And have 2 separate libraries libratbag
and libcrazykeyboard
(or any other name) that are just thin wrappers around the low level one to provide the differences we want in the API (key
vs button
for instance).
From a technical point of view, nothing in libratbag express that a device is a mouse.
We have capabilities, so we could describe a mouse or a keyboard by its capabilities.
The visual is shown through SVG, so we don't need to differentiate a LED on a mouse from one on a keyboard.
However, I have a feeling we want to have a different UI for keyboards than mice, so we might need a type telling keyboard/mouse/touchpad/trackball/etc...
ratbag-command
The CLI output is going to be interesting (106 macros to redefine, the same amount of LEDs), but given ratbag-command
should not be used outside from developers (hmm...) we should be able to find a way.
We should probably group capabilities by hundreds, as in libinput
:
enum libratbag_capability {
CAP_PROFILE = 100,
CAP_PROFILE_SWITCHABLE,
....
CAP_RESOLUTION = 200,
CAP_RESOLUTION_SWITCHABLE,
CAP_RESOLUTION_SET_DEFAULT,
...
CAP_LED = 300,
CAP_LED_EFFECTS,
...
};
This will break ABI, but we don't care yet. We can just bump the soname.
We have ratbagd
, yes, but do we need to have it running for the animations of the LEDs to be working? If so, then we should probably take this into account to some level (if ratbagd
is running, what happens when ratbag-command
is called?)
Not an issue for mice, but I have no ideas for the keyboards.
Currently libratbag doesn't export what type of devices it supports, and which common features we want to support. This is all describe in the API, but we should probably have some central place of saying: "we can support this and this feature from this keyboard, but the rest needs to be handled in a specific project".
feel free to add comments and concerns
After a further implementation in the kernel, I understood we don't really need to store in the hwdb the device index if the device is a wireless one using a wireless receiver.
The wireless receiver still answers on device address 0xff like most wired devices. We can detect if the device is a plain mouse or a wireless receiver by checking the register 0xB5 Pairing Information
. I believe non-receivers will return an error if we try to address this register.
Then, poking at each possible device index (from 1 to 6) allows to know if a device is connected to the receiver. Once we figured out which device index is in use, we can restart the probe of the hidraw node with the wireless device index.
The G402 has bigger sectors/pages with 1024 bytes. But libratbag uses hard-coded HIDPP20_PAGE_SIZE
of 256 bytes instead of the size from hidpp20_onboard_profiles_info
. Thus writing the CRC at an invalid location.
Parameters for CMD_ONBOARD_PROFILES_MEMORY_READ
and CMD_ONBOARD_PROFILES_MEMORY_ADDR_WRITE
need fixing for supporting bigger sector. section
is actually 16 bits and in big endian in bytes 2 and 3. And bytes 4 and 5 of CMD_ONBOARD_PROFILES_MEMORY_ADDR_WRITE
is the data length as 16 bits big endian (currently hard-coded to 0x0100 = 256 bytes).
I cannot test the G402 myself, it is a supposed bug. I found this from dumps from @dslul. GSeriesDev/gseries-tools#3 (comment)
The G700s is reporting expected results when accessing the device over its wired USB connection.
However, when trying to access it over its wireless USB receiver I am not able to retrieve information on buttons beyond left, right, and middle click. This occurs when using both ratbag-command and ratbagctl.
Sample output:
vivid@2500k:~$ sudo ratbag-command list
/dev/input/event2: Logitech G700s Rechargeable Gaming Mouse
/dev/input/event22: Logitech USB Receiver
/dev/input/event23: Logitech USB Receiver
/dev/input/event3: Logitech G700s Rechargeable Gaming Mouse
vivid@2500k:~$ sudo ratbag-command button count /dev/input/event3
13
vivid@2500k:~$ sudo ratbag-command button count /dev/input/event23
3
vivid@2500k:~$ ratbagctl list-devices
event23: Logitech USB Receiver
event3: Logitech G700s Rechargeable Gaming Mouse
vivid@2500k:~$ ratbagctl show-button event3 0 3
Button 3 on Profile 0 on event3 (Logitech G700s Rechargeable Gaming Mouse)
Type: thumb
Action Type: button
Button Mapping: 4
vivid@2500k:~$ ratbagctl show-button event23 0 3
Invalid button index 3
As pointed out in the Piper redesign wiki here: https://github.com/libratbag/piper/wiki/Piper-Redesign/
The LEDs should be named in the SVG file, just as the buttons are, ideally on their own SVG layer
Hello. I'm trying to load my Logitech G502 mouse into ratbag, however I am running across issues loading the device.
For starters, Piper doesn't recognise the mouse, and when I check the device with
sudo ratbag-command list
, my shell returns:
“sudo ratbag-command list” terminated by signal SIGSEGV (Address boundary error)
.
systemctl-status of ratbagd.service returns the following:
● ratbagd.service - Daemon to introspect and modify configurable mice
Loaded: loaded (/usr/lib/systemd/system/ratbagd.service; enabled; vendor preset: disabled)
Active: failed (Result: core-dump) since Fri 2017-03-24 16:38:22 AEDT; 20min ago
Main PID: 1881 (code=dumped, signal=SEGV)
Mar 24 16:38:22 arch-desktop-26 systemd[1]: ratbagd.service: Unit entered failed state.
Mar 24 16:38:22 arch-desktop-26 systemd[1]: ratbagd.service: Failed with result 'core-dump'.
Mar 24 16:38:22 arch-desktop-26 systemd[1]: ratbagd.service: Service hold-off time over, scheduling restart.
Mar 24 16:38:22 arch-desktop-26 systemd[1]: Stopped Daemon to introspect and modify configurable mice.
Mar 24 16:38:22 arch-desktop-26 systemd[1]: ratbagd.service: Start request repeated too quickly.
Mar 24 16:38:22 arch-desktop-26 systemd[1]: Failed to start Daemon to introspect and modify configurable mice.
Mar 24 16:38:22 arch-desktop-26 systemd[1]: ratbagd.service: Unit entered failed state.
Mar 24 16:38:22 arch-desktop-26 systemd[1]: ratbagd.service: Failed with result 'core-dump'.
sudo udevadm info /sys/class/input/eventX | grep RATBAG_DRIVER
returns
Unknown device, --name=, --path=, or absolute path in /dev/ or /sys expected.
Keep in mind, I installed via the AUR. I'm still not sure why the daemon is resulting in a core dump and a segmentation fault.
It seems that page 1 consists of a list of 3-byte data. The list is terminated by two bytes of 0xFF.
Each 3 byte data is a description of a profile. The first byte is page number for the profile. I am not sure about the rest but byte 2 is always 0x00 here, and byte 3 is a number that seems unique per profile.
Here is a dump of the list from my G9 with all profiles enabled:
02 00 01
03 00 03
04 00 07
05 00 06
06 00 04
FF FF
When I disable a profile in LGS it is removed from the list in page 1.
Do we want to support enabling/disabling of profiles from libratbag?
Should ratbag-command show info for disabled profiles?
As noted on issue #142:
/home/iliya/src/libratbag/README.md:135: warning: Unexpected html tag <img> found within <a href=...> context
The problem is that README.md
is used for both the github front page, and for the docs.
I wonder if we couldn't have a simpler README.md
without the doxygen tags (/*@mainpage
, */
), and have doxygen ignore for the semaphoreCI tag, and have a doxygen front page that just includes the content of README.md
with proper doxygen marks.
This could easily be achieved by a script, but a proper doxygen include (if any) would be better.
We also need an API to control the LED (because we need it).
From what I can gather from the various devices I encountered, some have very tunable LED (like the G303), others have basic functionalities (like the Etekcity). I think the common denominator is:
We might not expose that many effects (breathing, heartbit, etc). The most important ones are IMO ON/OFF and the set_color so we can assign a color per profile.
Somehow, ratbag-command happily pushed 13000dpi onto my mouse, and then wasn't able to change it back until I switched to a different profile and set it by reference (i.e. profile 0 resolution 1 dpi set 800). Then I was able to change it directly again.
Which in theory is good, because it just works, but in the hwdb file the svg image is also specified RATBAG_SVG=logitech-g900.svg which would be wrong for the G403.
Are there any interrest in the Func MS mouse series?
I managed to reverse-engineer most of the protocol for the Func MS-3, except for the macro mapping, before my mouse broke. If anyone is interested in support for the MS-2 or MS-3 I will buy a new and try porting my code.
I havn't read the whole HID++ 1/2 protocol, but it seems that it's possible to read and write individual actions and settings? For what I remember there is no way to read from a Func mouse and it is programmed with a whole profile at the time. If you want to chang the light color for profile1 you have to re-program all settings along with the newly changed color.
libratbag currently has its own HID++ handling code, which supports both the 1.0 and 2.0 versions.
We have similar code in UPower to query battery status and solar charging support:
http://cgit.freedesktop.org/upower/tree/src/linux/hidpp-device.h
And we would want to integrate unifying receiver support in GNOME directly, to allow pairing and unpairing devices:
https://bugzilla.gnome.org/show_bug.cgi?id=756574
To avoid adding external dependencies, the new library could be a cut'n'paste library, or a git submodule. The API needed would be:
The meson build system [1] is gaining a fair bit of traction, parts of GNOME are being switched over and we are currently discussing it for X.Org and Wayland. It'd remove automake, the big benefit is a great speedup in configure + build time (quick tests here are 20s vs 4s for a build from a fresh repo).
What's better though is that it's a lot more understandable, your average meson config makes a lot more sense than your average autotools setup.
I have a test branch that adds meson, if we're happy with this I think we should go ahead here.
For the Func mouses there is no option for reading the active profile on request. An event is given when a hardware button press cycles to the next profile, but that's it.
Currently ratbag-command
doesn't accept a device with an unknown active profile. Working around this I have hardcoded profile 0 to be the active profile. As profile 0 always is the active one, I'm able to switch between profile 1 and 2, using ratbat-command profile active set 1|2
, but never profile 0 as it is already active.
Would it be possible to change this, such that no profile has to be marked as active. In the case of not having an active profile it would be mandatory to specify a profile number with the command. In this case something along the lines of this would be the result:
$ ratbag-command dpi set 800
ratbag error: libratbag bug: Func Func MS-2 Gaming Mouse: missing profile id
$ ratbag-command profile 0 dpi set 800
Switched 'Func Func MS-2 Gaming Mouse' profile '0' dpi '800'
The second interface of G5 that provide the vendor specific reports for HID++, does not have any input reports. Thus, the kernel does not create any input/event device and libratbag does not find the device.
Event devices:
$ ll /dev/input/by-id/
total 0
lrwxrwxrwx. 1 root root 9 17 sept. 09:47 usb-Chicony_Electronics_Co._Ltd_Chicony_USB_2.0_Camera-event-if00 -> ../event9
lrwxrwxrwx. 1 root root 10 17 sept. 12:07 usb-Logitech_G500_05554A4FA20018-event-mouse -> ../event13
lrwxrwxrwx. 1 root root 10 17 sept. 12:07 usb-Logitech_G500_05554A4FA20018-if01-event-kbd -> ../event14
lrwxrwxrwx. 1 root root 9 17 sept. 12:07 usb-Logitech_G500_05554A4FA20018-mouse -> ../mouse1
lrwxrwxrwx. 1 root root 10 17 sept. 12:07 usb-Logitech_USB_Gaming_Mouse-event-mouse -> ../event15
lrwxrwxrwx. 1 root root 9 17 sept. 12:07 usb-Logitech_USB_Gaming_Mouse-mouse -> ../mouse2
Logitech_USB_Gaming_Mouse is the G5, there is no event device for if01.
The report descriptor for the second interface:
06 00 FF Usage Page (FF00 - Vendor)
09 01 Usage (0001 - Vendor)
A1 01 Collection (Application)
85 10 Report ID (16)
75 08 Report Size (8)
95 06 Report Count (6)
15 00 Logical Minimum (0)
26 FF 00 Logical Maximum (255)
09 01 Usage (0001 - Vendor)
81 00 Input ()
09 01 Usage (0001 - Vendor)
91 00 Output ()
C0 End Collection
06 00 FF Usage Page (FF00 - Vendor)
09 02 Usage (0002 - Vendor)
A1 01 Collection (Application)
85 11 Report ID (17)
75 08 Report Size (8)
95 13 Report Count (19)
15 00 Logical Minimum (0)
26 FF 00 Logical Maximum (255)
09 02 Usage (0002 - Vendor)
81 00 Input ()
09 02 Usage (0002 - Vendor)
91 00 Output ()
C0 End Collection
Side effect of 91eefb9 was that we now ignore ID_INPUT_TOUCHPAD devices in libratbag. The mouse and touchpad tags are mutually exclusive, so you only have either.
So the main question here now is: should we care about touchpad devices? Other than protocol testing there is little libratbag can do to the current generation of devices. It's useful for testing, but that's about it.
Hi,
I'm the project maintainer of sidewinderd (https://github.com/tolga9009/sidewinderd) and watched this project for a while. It looks like we're trying to solve very similar problems and I wanted to ask, if there is interest in adding keyboard support.
Gaming mice and keyboards share alot of code (macros, profiles, LEDs) and this project seems to have everything important included.
Please let me know, whether there is interest, or not.
Cheers,
Tolga
libratbag should be taught to talk to Razer mice.
Razer uses proprietaty USB messages to perform device configuration.
An implementation of some Razer mouse protocols can be found in razercfg.
https://bues.ch/h/razercfg#device_support
https://github.com/mbuesch/razer
This is NOT an issue.
As there are no other discussion or forum options when it comes to Github, I hope you don't mind me asking questions here?
It has been a while since I last looked at the USB protocol when using a windows driver. Back then I used USBlyzer, very nice interface and easy to use. However, I'm once again limited to the 30 days trial which won't get me to the finish line. What are you using?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.