Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 20 Sep 2015 23:42:05 +0200
From:      =?UTF-8?Q?Maxime_Soul=c3=a9?= <btik-fbsd@scoubidou.com>
To:        freebsd-usb@FreeBSD.org
Subject:   Patch to allow dynamic USB quirks at boot
Message-ID:  <55FF282D.2040003@scoubidou.com>

next in thread | raw e-mail | index | archive | help
Hi all,

I own a X9800 Tecknet mouse with 3 side buttons. When I plug it in, a
ukbd device appears handling each 3 buttons with key modifiers Control,
Shift and Alt, with one device uhid.

As I wanted to see these buttons as buttons under X and not as key
modifiers, I first thought about using USB quirk UQ_KBD_IGNORE and devd
to hack it. I succeeded (more or less) but devd starts to late during
boot to be able to apply the quirk when the mouse is already plugged in,
so I needed to always plug the mouse in once the system has booted...
Not very cool...

When the USB quirk UQ_KBD_IGNORE is applied, the ukbd device does not
appear, but two uhid devices appear, including the one dedicated to the
"keyboard" feature of the mouse.

During my searches on the net, I found the Bug 122819 in which Maurice
Castro implemented dynamic quirks in 2008, allowing quirks to be defined
dynamically and also through the environment. Unfortunately, this code
was for the old USB 1 stack.

Indeed, the new USB 2 stack allows dynamic additions to the quirk table,
but not at boot time (or I did not find the way).

So, I made a patch, with the help of Maurice one, allowing the
modification of the quirks table through the environment:
http://scoubidou.com/usb_quirk/usb_quirk.diff

Now in my loader.conf, I have:

usb.quirk.0="0x04d9 0xfa50 0 0xffff UQ_KBD_IGNORE"

The value format is "VendorId ProductId LowRevision HighRevision
Quirk1,...,QuirkN".
One can have usb.quirk.1, .2, ..., .99 if there is enough space in the
quirks table...

In a devd conf file:

notify 1000 {
       match "system" "DEVFS";
       match "subsystem" "CDEV";
       match "type" "CREATE";
       match "cdev" "uhid[0-9]+";

       action "/usr/bin/usbhidctl -f /dev/$cdev \
            Keyboard:Keyboard_LeftShift \
            Keyboard:Keyboard_LeftAlt \
            Keyboard:Keyboard_LeftControl > /dev/null 2>&1 \
        && DISPLAY=:0.0 /usr/bin/usbhidaction -f $cdev \
            -c /usr/local/etc/tecknet-mouse-usbhidaction.conf \
            -p /var/run/usbhidaction.$cdev.pid";
};

The usbhidctl is to check that we handle the right uhid device, the one
with Keyboard_LeftShift, Keyboard_LeftAlt AND Keyboard_LeftControl
features. Then, usbhidaction daemon can be launched to handle all the
"keyboard" events.

And the contents of my /usr/local/etc/tecknet-mouse-usbhidaction.conf file:

Keyboard:Keyboard_LeftShift    1 0 /usr/local/bin/xdotool mousedown 8
Keyboard:Keyboard_LeftShift    0 1 /usr/local/bin/xdotool mouseup 8
Keyboard:Keyboard_LeftAlt    1 0 /usr/local/bin/xdotool mousedown 9
Keyboard:Keyboard_LeftAlt    0 1 /usr/local/bin/xdotool mouseup 9
Keyboard:Keyboard_LeftControl    1 0 /usr/local/bin/xdotool mousedown 6
Keyboard:Keyboard_LeftControl    0 1 /usr/local/bin/xdotool mouseup 6

to translate "keyboard" actions to buttons clicks thanks to xdotool
(from ports).

And all works like a charm :)

Finally, I have two questions:

First, is there a way to link the uhid device with the USB
vendor/product ID in devd? Without doing it using a script and parsing
devinfo output of course...

Second, when I unplug the mouse, devd did not receive the "DESTROY"
event for the uhid device, until the usbhidaction daemon is killed. But
I would have liked to be able to kill usbhidaction daemon automatically
when the mouse is unplugged using devd... With USB vendor/product
details available at uhid level, I could have done it when the
corresponding ugen device is DETACHed by caching this information...

Best regards,

Max.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?55FF282D.2040003>