<div dir="ltr">Thanks for clearing that up, Can confirm the patch works.<br><br>udev rules were put in /usr/local/lib/udev by make command, moved to /usr/lib/udev then devadm hwdb --update.<br><br>Looking forward to seeing this in upstream Fedora one day.<br><br>Thanks,<br><br>Joel<br><br><br>On Wed, Feb 3, 2016 at 9:30 PM, Peter Hutterer <<a href="mailto:peter.hutterer@who-t.net">peter.hutterer@who-t.net</a>> wrote:<br>><br>> On Wed, Feb 03, 2016 at 06:47:01PM +0000, Joel Duncan wrote:<br>> ><br>> > Hi guys,<br>> ><br>> > Not being a libinput dev I was looking for advice on using this patch.<br>> > I noticed that a lot of the RAT config was in /test. After compiling the<br>> > driver<br>> > and installing it the problem still persists.<br>> ><br>> > I'm assuming it's due to needing a flag when compiling to include /test<br>> > components?<br>><br>> anything in test are libinput-internal tests, you don't need them to use<br>> libinput.<br>><br>> This fix relies on a udev tag applied to the mouse. So my best guess is<br>> that you either didn't install the udev rule/hwdb entry correctly, or that<br>> you didn't run sudo udevadm hwdb --update afterwards.<br>><br>> run udevadm info /sys/class/input/eventX for whatever event node your mouse<br>> has and check if the LIBINPUT_MODEL_CYBORG_RAT variable is set on the<br>> device. I not, then you need to check the udev rule/hwdb install.<br>> if it's set and it still doesn't work, the patch is buggy.<br>><br>> Cheers,<br>>    Peter<br>><br>> > Any advice would be great!<br>> ><br>> > Thanks,<br>> ><br>> > Joel<br>> ><br>> > On Fri, Jan 29, 2016 at 12:48 AM, Peter Hutterer <<a href="mailto:peter.hutterer@who-t.net">peter.hutterer@who-t.net</a>><br>> > wrote:<br>> ><br>> > > This button sends a release N, press N+1 on each press, cycling through the<br>> > > three event codes supported. This causes a stuck button since the current<br>> > > mode<br>> > > is never released.<br>> > ><br>> > > Long-term this better served by a set of switches that toggle accordingly,<br>> > > for<br>> > > now disable the button codes.<br>> > ><br>> > > <a href="https://bugs.freedesktop.org/show_bug.cgi?id=92127">https://bugs.freedesktop.org/show_bug.cgi?id=92127</a><br>> > ><br>> > > Signed-off-by: Peter Hutterer <<a href="mailto:peter.hutterer@who-t.net">peter.hutterer@who-t.net</a>><br>> > > ---<br>> > >  src/evdev.c                            | 36 +++++++++++++++++<br>> > >  src/evdev.h                            |  1 +<br>> > >  test/Makefile.am                       |  1 +<br>> > >  test/device.c                          | 33 ++++++++++++++++<br>> > >  test/litest-device-cyborg-rat-5.c      | 71<br>> > > ++++++++++++++++++++++++++++++++++<br>> > >  test/litest.c                          |  2 +<br>> > >  test/litest.h                          |  1 +<br>> > >  udev/90-libinput-model-quirks.hwdb     |  7 ++++<br>> > >  udev/<a href="http://90-libinput-model-quirks.rules.in">90-libinput-model-quirks.rules.in</a> |  4 ++<br>> > >  9 files changed, 156 insertions(+)<br>> > >  create mode 100644 test/litest-device-cyborg-rat-5.c<br>> > ><br>> > > diff --git a/src/evdev.c b/src/evdev.c<br>> > > index 8f0a607..66673a8 100644<br>> > > --- a/src/evdev.c<br>> > > +++ b/src/evdev.c<br>> > > @@ -1677,6 +1677,7 @@ evdev_read_model_flags(struct evdev_device *device)<br>> > >                 { "LIBINPUT_MODEL_JUMPING_SEMI_MT",<br>> > > EVDEV_MODEL_JUMPING_SEMI_MT },<br>> > >                 { "LIBINPUT_MODEL_ELANTECH_TOUCHPAD",<br>> > > EVDEV_MODEL_ELANTECH_TOUCHPAD },<br>> > >                 { "LIBINPUT_MODEL_APPLE_INTERNAL_KEYBOARD",<br>> > > EVDEV_MODEL_APPLE_INTERNAL_KEYBOARD },<br>> > > +               { "LIBINPUT_MODEL_CYBORG_RAT", EVDEV_MODEL_CYBORG_RAT },<br>> > >                 { NULL, EVDEV_MODEL_DEFAULT },<br>> > >         };<br>> > >         const struct model_map *m = model_map;<br>> > > @@ -2249,6 +2250,39 @@ evdev_drain_fd(int fd)<br>> > >         }<br>> > >  }<br>> > ><br>> > > +static inline void<br>> > > +evdev_pre_configure_model_quirks(struct evdev_device *device)<br>> > > +{<br>> > > +       /* The Cyborg RAT has a mode button that cycles through event<br>> > > codes.<br>> > > +        * On press, we get a release for the current mode and a press for<br>> > > the<br>> > > +        * next mode:<br>> > > +        * E: 0.000001 0004 0004 589833 # EV_MSC / MSC_SCAN<br>> > >  589833<br>> > > +        * E: 0.000001 0001 0118 0000   # EV_KEY / (null)               0<br>> > > +        * E: 0.000001 0004 0004 589834 # EV_MSC / MSC_SCAN<br>> > >  589834<br>> > > +        * E: 0.000001 0001 0119 0001   # EV_KEY / (null)               1<br>> > > +        * E: 0.000001 0000 0000 0000   # ------------ SYN_REPORT (0)<br>> > > ---------- +0ms<br>> > > +        * E: 0.705000 0004 0004 589834 # EV_MSC / MSC_SCAN<br>> > >  589834<br>> > > +        * E: 0.705000 0001 0119 0000   # EV_KEY / (null)               0<br>> > > +        * E: 0.705000 0004 0004 589835 # EV_MSC / MSC_SCAN<br>> > >  589835<br>> > > +        * E: 0.705000 0001 011a 0001   # EV_KEY / (null)               1<br>> > > +        * E: 0.705000 0000 0000 0000   # ------------ SYN_REPORT (0)<br>> > > ---------- +705ms<br>> > > +        * E: 1.496995 0004 0004 589833 # EV_MSC / MSC_SCAN<br>> > >  589833<br>> > > +        * E: 1.496995 0001 0118 0001   # EV_KEY / (null)               1<br>> > > +        * E: 1.496995 0004 0004 589835 # EV_MSC / MSC_SCAN<br>> > >  589835<br>> > > +        * E: 1.496995 0001 011a 0000   # EV_KEY / (null)               0<br>> > > +        * E: 1.496995 0000 0000 0000   # ------------ SYN_REPORT (0)<br>> > > ---------- +791ms<br>> > > +        *<br>> > > +        * <a href="https://bugs.freedesktop.org/show_bug.cgi?id=92127">https://bugs.freedesktop.org/show_bug.cgi?id=92127</a><br>> > > +        *<br>> > > +        * Disable the event codes to avoid stuck buttons.<br>> > > +        */<br>> > > +       if(device->model_flags & EVDEV_MODEL_CYBORG_RAT) {<br>> > > +               libevdev_disable_event_code(device->evdev, EV_KEY, 0x118);<br>> > > +               libevdev_disable_event_code(device->evdev, EV_KEY, 0x119);<br>> > > +               libevdev_disable_event_code(device->evdev, EV_KEY, 0x11a);<br>> > > +       }<br>> > > +}<br>> > > +<br>> > >  struct evdev_device *<br>> > >  evdev_device_create(struct libinput_seat *seat,<br>> > >                     struct udev_device *udev_device)<br>> > > @@ -2318,6 +2352,8 @@ evdev_device_create(struct libinput_seat *seat,<br>> > >         matrix_init_identity(&device->abs.usermatrix);<br>> > >         matrix_init_identity(&device->abs.default_calibration);<br>> > ><br>> > > +       evdev_pre_configure_model_quirks(device);<br>> > > +<br>> > >         if (evdev_configure_device(device) == -1)<br>> > >                 goto err;<br>> > ><br>> > > diff --git a/src/evdev.h b/src/evdev.h<br>> > > index 02b5112..8b567a8 100644<br>> > > --- a/src/evdev.h<br>> > > +++ b/src/evdev.h<br>> > > @@ -110,6 +110,7 @@ enum evdev_device_model {<br>> > >         EVDEV_MODEL_ELANTECH_TOUCHPAD = (1 << 11),<br>> > >         EVDEV_MODEL_LENOVO_X220_TOUCHPAD_FW81 = (1 << 12),<br>> > >         EVDEV_MODEL_APPLE_INTERNAL_KEYBOARD = (1 << 13),<br>> > > +       EVDEV_MODEL_CYBORG_RAT = (1 << 14),<br>> > >  };<br>> > ><br>> > >  struct mt_slot {<br>> > > diff --git a/test/Makefile.am b/test/Makefile.am<br>> > > index 885d9c6..27a2a36 100644<br>> > > --- a/test/Makefile.am<br>> > > +++ b/test/Makefile.am<br>> > > @@ -20,6 +20,7 @@ liblitest_la_SOURCES = \<br>> > >         litest-device-asus-rog-gladius.c \<br>> > >         litest-device-atmel-hover.c \<br>> > >         litest-device-bcm5974.c \<br>> > > +       litest-device-cyborg-rat-5.c \<br>> > >         litest-device-elantech-touchpad.c \<br>> > >         litest-device-generic-singletouch.c \<br>> > >         litest-device-huion-pentablet.c \<br>> > > diff --git a/test/device.c b/test/device.c<br>> > > index 351dffe..ac487a2 100644<br>> > > --- a/test/device.c<br>> > > +++ b/test/device.c<br>> > > @@ -1299,6 +1299,38 @@ START_TEST(device_quirks_no_abs_mt_y)<br>> > >  }<br>> > >  END_TEST<br>> > ><br>> > > +START_TEST(device_quirks_cyborg_rat_mode_button)<br>> > > +{<br>> > > +       struct litest_device *dev = litest_current_device();<br>> > > +       struct libinput_device *device = dev->libinput_device;<br>> > > +       struct libinput *li = dev->libinput;<br>> > > +<br>> > > +       ck_assert(!libinput_device_pointer_has_button(device, 0x118));<br>> > > +       ck_assert(!libinput_device_pointer_has_button(device, 0x119));<br>> > > +       ck_assert(!libinput_device_pointer_has_button(device, 0x11a));<br>> > > +<br>> > > +       litest_drain_events(li);<br>> > > +<br>> > > +       litest_event(dev, EV_KEY, 0x118, 0);<br>> > > +       litest_event(dev, EV_KEY, 0x119, 1);<br>> > > +       litest_event(dev, EV_SYN, SYN_REPORT, 0);<br>> > > +<br>> > > +       litest_assert_empty_queue(li);<br>> > > +<br>> > > +       litest_event(dev, EV_KEY, 0x119, 0);<br>> > > +       litest_event(dev, EV_KEY, 0x11a, 1);<br>> > > +       litest_event(dev, EV_SYN, SYN_REPORT, 0);<br>> > > +<br>> > > +       litest_assert_empty_queue(li);<br>> > > +<br>> > > +       litest_event(dev, EV_KEY, 0x11a, 0);<br>> > > +       litest_event(dev, EV_KEY, 0x118, 1);<br>> > > +       litest_event(dev, EV_SYN, SYN_REPORT, 0);<br>> > > +<br>> > > +       litest_assert_empty_queue(li);<br>> > > +}<br>> > > +END_TEST<br>> > > +<br>> > >  void<br>> > >  litest_setup_tests(void)<br>> > >  {<br>> > > @@ -1356,4 +1388,5 @@ litest_setup_tests(void)<br>> > >         litest_add_no_device("device:invalid rel events", device_abs_rel);<br>> > ><br>> > >         litest_add_for_device("device:quirks", device_quirks_no_abs_mt_y,<br>> > > LITEST_ANKER_MOUSE_KBD);<br>> > > +       litest_add_for_device("device:quirks",<br>> > > device_quirks_cyborg_rat_mode_button, LITEST_CYBORG_RAT);<br>> > >  }<br>> > > diff --git a/test/litest-device-cyborg-rat-5.c<br>> > > b/test/litest-device-cyborg-rat-5.c<br>> > > new file mode 100644<br>> > > index 0000000..a1db77a<br>> > > --- /dev/null<br>> > > +++ b/test/litest-device-cyborg-rat-5.c<br>> > > @@ -0,0 +1,71 @@<br>> > > +/*<br>> > > + * Copyright © 2013 Red Hat, Inc.<br>> > > + *<br>> > > + * Permission is hereby granted, free of charge, to any person obtaining a<br>> > > + * copy of this software and associated documentation files (the<br>> > > "Software"),<br>> > > + * to deal in the Software without restriction, including without<br>> > > limitation<br>> > > + * the rights to use, copy, modify, merge, publish, distribute,<br>> > > sublicense,<br>> > > + * and/or sell copies of the Software, and to permit persons to whom the<br>> > > + * Software is furnished to do so, subject to the following conditions:<br>> > > + *<br>> > > + * The above copyright notice and this permission notice (including the<br>> > > next<br>> > > + * paragraph) shall be included in all copies or substantial portions of<br>> > > the<br>> > > + * Software.<br>> > > + *<br>> > > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,<br>> > > EXPRESS OR<br>> > > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF<br>> > > MERCHANTABILITY,<br>> > > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT<br>> > > SHALL<br>> > > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR<br>> > > OTHER<br>> > > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING<br>> > > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER<br>> > > + * DEALINGS IN THE SOFTWARE.<br>> > > + */<br>> > > +<br>> > > +#if HAVE_CONFIG_H<br>> > > +#include "config.h"<br>> > > +#endif<br>> > > +<br>> > > +#include "litest.h"<br>> > > +#include "litest-int.h"<br>> > > +<br>> > > +static void litest_cyborg_rat_setup(void)<br>> > > +{<br>> > > +       struct litest_device *d = litest_create_device(LITEST_CYBORG_RAT);<br>> > > +       litest_set_current_device(d);<br>> > > +}<br>> > > +<br>> > > +static struct input_id input_id = {<br>> > > +       .bustype = 0x3,<br>> > > +       .vendor = 0x6a3,<br>> > > +       .product = 0xcd5,<br>> > > +};<br>> > > +<br>> > > +static int events[] = {<br>> > > +       EV_KEY, BTN_LEFT,<br>> > > +       EV_KEY, BTN_RIGHT,<br>> > > +       EV_KEY, BTN_MIDDLE,<br>> > > +       EV_KEY, BTN_SIDE,<br>> > > +       EV_KEY, BTN_EXTRA,<br>> > > +       EV_KEY, BTN_FORWARD,<br>> > > +       EV_KEY, BTN_TASK,<br>> > > +       EV_KEY, 0x118,<br>> > > +       EV_KEY, 0x119,<br>> > > +       EV_KEY, 0x11a,<br>> > > +       EV_REL, REL_X,<br>> > > +       EV_REL, REL_Y,<br>> > > +       EV_REL, REL_WHEEL,<br>> > > +       -1 , -1,<br>> > > +};<br>> > > +<br>> > > +struct litest_test_device litest_cyborg_rat_device = {<br>> > > +       .type = LITEST_CYBORG_RAT,<br>> > > +       .features = LITEST_RELATIVE | LITEST_BUTTON | LITEST_WHEEL,<br>> > > +       .shortname = "cyborg_rat",<br>> > > +       .setup = litest_cyborg_rat_setup,<br>> > > +       .interface = NULL,<br>> > > +<br>> > > +       .name = "Saitek Cyborg R.A.T.5 Mouse",<br>> > > +       .id = &input_id,<br>> > > +       .absinfo = NULL,<br>> > > +       .events = events,<br>> > > +};<br>> > > diff --git a/test/litest.c b/test/litest.c<br>> > > index 99bed06..6822fe6 100644<br>> > > --- a/test/litest.c<br>> > > +++ b/test/litest.c<br>> > > @@ -375,6 +375,7 @@ extern struct litest_test_device<br>> > > litest_apple_keyboard_device;<br>> > >  extern struct litest_test_device litest_anker_mouse_kbd_device;<br>> > >  extern struct litest_test_device litest_waltop_tablet_device;<br>> > >  extern struct litest_test_device litest_huion_tablet_device;<br>> > > +extern struct litest_test_device litest_cyborg_rat_device;<br>> > ><br>> > >  struct litest_test_device* devices[] = {<br>> > >         &litest_synaptics_clickpad_device,<br>> > > @@ -416,6 +417,7 @@ struct litest_test_device* devices[] = {<br>> > >         &litest_anker_mouse_kbd_device,<br>> > >         &litest_waltop_tablet_device,<br>> > >         &litest_huion_tablet_device,<br>> > > +       &litest_cyborg_rat_device,<br>> > >         NULL,<br>> > >  };<br>> > ><br>> > > diff --git a/test/litest.h b/test/litest.h<br>> > > index 4d96576..bd9b903 100644<br>> > > --- a/test/litest.h<br>> > > +++ b/test/litest.h<br>> > > @@ -192,6 +192,7 @@ enum litest_device_type {<br>> > >         LITEST_WACOM_ISDV4 = -38,<br>> > >         LITEST_WALTOP = -39,<br>> > >         LITEST_HUION_TABLET = -40,<br>> > > +       LITEST_CYBORG_RAT = -41,<br>> > >  };<br>> > ><br>> > >  enum litest_device_feature {<br>> > > diff --git a/udev/90-libinput-model-quirks.hwdb<br>> > > b/udev/90-libinput-model-quirks.hwdb<br>> > > index baebcb3..fa668d6 100644<br>> > > --- a/udev/90-libinput-model-quirks.hwdb<br>> > > +++ b/udev/90-libinput-model-quirks.hwdb<br>> > > @@ -38,6 +38,13 @@ libinput:name:*Apple Inc. Apple Internal Keyboard*:dmi:*<br>> > >   LIBINPUT_MODEL_APPLE_INTERNAL_KEYBOARD=1<br>> > ><br>> > >  ##########################################<br>> > > +# Cyborg<br>> > > +##########################################<br>> > > +# Saitek Cyborg R.A.T.5 Mouse<br>> > > +libinput:mouse:input:b0003v06A3p0CD5*<br>> > > + LIBINPUT_MODEL_CYBORG_RAT=1<br>> > > +<br>> > > +##########################################<br>> > >  # Elantech<br>> > >  ##########################################<br>> > >  libinput:name:*ETPS/2 Elantech Touchpad*:dmi:*<br>> > > diff --git a/udev/<a href="http://90-libinput-model-quirks.rules.in">90-libinput-model-quirks.rules.in</a> b/udev/<br>> > > <a href="http://90-libinput-model-quirks.rules.in">90-libinput-model-quirks.rules.in</a><br>> > > index 5b07726..8bff192 100644<br>> > > --- a/udev/<a href="http://90-libinput-model-quirks.rules.in">90-libinput-model-quirks.rules.in</a><br>> > > +++ b/udev/<a href="http://90-libinput-model-quirks.rules.in">90-libinput-model-quirks.rules.in</a><br>> > > @@ -29,6 +29,10 @@ KERNELS=="*input*", \<br>> > >  ENV{ID_INPUT_TOUCHPAD}=="1", \<br>> > >    IMPORT{builtin}="hwdb --subsystem=input<br>> > > --lookup-prefix=libinput:touchpad:"<br>> > ><br>> > > +# libinput:mouse:<modalias><br>> > > +ENV{ID_INPUT_MOUSE}=="1", \<br>> > > +  IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=libinput:mouse:"<br>> > > +<br>> > >  # libinput:name:<name>:dmi:<dmi string><br>> > >  KERNELS=="input*", \<br>> > >    IMPORT{builtin}="hwdb<br>> > > 'libinput:name:$attr{name}:$attr{[dmi/id]modalias}'"<br>> > > --<br>> > > 2.5.0<br>> > ><br>> > ></div>