Show pageOld revisionsBacklinksBack to top This page is read only. You can view the source, but not change it. Ask your administrator if you think this is wrong. ====== uhidd ====== USB HID daemon ====== Overview ====== ''%%uhidd%%'' is a userland driver/daemon for USB HID devices like mouse, keyboard etc. It is based on libusb20 and currently only works for %%FreeBSD%% 8.x and above. The ''%%uhidd%%'' userland driver aims to support USB HID devices with multiple Top-Level application collections in one interface, i.e, HID devices with multiple logical device sharing one endpoint. This kind of devices currently can not be fully supported by the in-kernel drivers ''%%(ukbd/ums/uhid)%%''. See the examples section below for examples of such devices and how to setup the driver to support them. ''%%uhidd%%'' also provide support for multimedia keys found on USB keyboard, a multimedia keymap needs to be created to make it function. See the examples section below. ====== News ====== [2012-10-15] uhidd 0.2.1 released: * Support for kernel driver detach * Support for mouse tilt wheel * Support for linear Volume control found on some keyboard * Support for cuse4bsd-based virtual device ====== Download & Install ====== The latest release tarball is [[https://people.freebsd.org/~kaiw/distfiles/uhidd-0.2.1.tar.gz|uhidd-0.2.1.tar.gz]] You could also fetch the latest source code from github: <code> % git clone https://github.com/kaiwang27/uhidd.git </code> The recommended way to install ''%%uhidd%%'' is through the ports system instead of compiling the source by yourself. <code> # pkg install uhidd </code> The port will also install rc(8) script and devd(8) config file. ====== How to use it ====== ''%%uhidd%%'' daemon is using libusb20 to access usb device, so it deals with /dev/ugenX.Y nodes. Note that before you can use ''%%uhidd%%'' with certain ugenX.Y device, you need to make sure there is no kernel HID device driver attached to that device. You could either remove ''%%'device ukbd'%%'', ''%%'device ums'%%'' and ''%%'device uhid'%%'' from your kernel config file and recomplie the kernel, or if these drivers are loaded as kernel modules, ''%%kldunload(8)%%'' them. The relevant ''%%devd(8)%%'' rules for those kernel modules in ''%%/etc/devd/usb.conf%%'' also needs to be removed to prevent them from loading automatically by ''%%devd(8)%%''. However, ''%%uhidd%%'' could be also used together with kernel drivers, for example ''%%uhidd%%'' and a kernel driver can each attach to one interface of the same device. See the Examples section below for details. The following example starts ''%%uhidd%%'' deamon on ''%%/dev/ugen2.2%%'', attaching keyboard, mouse, consumer control and generic hid child devices: (see the ''%%uhidd(8)%%'' manual page for details about the command line args) <code> # /usr/local/sbin/uhidd -kmohs /dev/ugen2.2 </code> Or, if you installed ''%%uhidd%%'' from ports you can use the ''%%uhidd%%'' rc(8) script to simplify things: Frist add the following lines to ''%%/etc/rc.conf%%'': (uhidd_flags corresponding to the command line args) <code> uhidd_flags="-kmohs" uhidd_enable="YES" </code> Then you have several ways to invoke the rc(8) script: To start ''%%uhidd%%'' on /dev/ugen2.2 <code> # /usr/local/etc/rc.d/uhidd start /dev/ugen2.2 </code> To stop ''%%uhidd%%'' on /dev/ugen2.2 <code> # /usr/local/etc/rc.d/uhidd stop /dev/ugen2.2 </code> To start ''%%uhidd%%'' on all /dev/ugenX.Y devices that do not have ''%%uhidd%%'' attached: (This command will run automatically at the startup, if ''%%uhidd_enable="YES"%%'' is present) <code> # /usr/local/etc/rc.d/uhidd start </code> To stop all ''%%uhidd%%'' instances: <code> # /usr/local/etc/rc.d/uhidd stop </code> To start ''%%uhidd%%'' on new attached ''%%ugenX.Y%%'' device automatically, you can use the following devd(8) config file: (It is already installed to ''%%/usr/local/etc/devd/%%'' if you install ''%%uhidd%%'' from ports ) <code> notify 0 { match "subsystem" "DEVICE"; match "type" "ATTACH"; match "cdev" "ugen[0-9]+.[0-9]+"; action "env LD_PRELOAD=/usr/local/lib/libcuse4bsd.so /usr/local/etc/rc.d/uhidd start /dev/$cdev"; }; </code> Note that ''%%uhidd%%'' will ignore ''%%ugenX.Y%%'' device that does not have USB HID interfaces, so it is safe to "try" attaching ''%%uhidd%%'' on any ''%%ugenX.Y%%'' device. ====== Coexists/Conflicts with kernel drivers ====== * If ''%%uhidd%%'' daemon and the kernel driver attaches to different interfaces of a device, they can coexist without problems. * If ''%%uhidd%%'' daemon finds out that a kernel driver is active on a device and the command line option ''%%-u%%'' is not specified, it will abort. * If ''%%uhidd%%'' daemon finds out that a kernel driver is active on a device and the command line option ''%%-u%%'' is specified, it will first attempt to detach the kernel driver, then attach itself to the device. In this way ''%%uhidd%%'' can be used without recompiling the kernel. <del>HOWEVER, it appears that the kernel driver detaching function is NOT always reliable. Sometimes (tested on %%FreeBSD%% 9.0) it will cause the USB stack to deadlock!--)</del> The recommanded way to use ''%%uhidd%%'' is: * Use the GENERIC kernel or a kernel compiled in USB drivers. * Use ''%%uhidd%%'' option ''%%-u%%'' to detach kernel driver when needed. Note that if you have USB kernel drivers(''%%ukbd(4)%%'',''%%ums(4)%%'' and ''%%uhid(4)%%'') compiled as modules, it's possible that ''%%uhidd%%'' and USB kernel drivers attach to the device at the same time and cause strange behaviors like mouse cursor jumping, keyboard key repeating etc. It's better to remove the relevant ''%%devd(8)%%'' rules from ''%%/etc/devd/usb.conf%%'' in this case. To recover from such issues, you can restart ''%%uhidd%%'' by ''%%/usr/local/etc/rc.d uhidd restart%%''. ====== How does it work ====== The ''%%uhidd%%'' daemon attaches interface driver to each interface of the device and attaches sub class drivers to the top-level application collections inside the interface. The HID interface driver retrieve hid data from the shared interrupt endpoint using libusb20, then dispatch the data to one of the class drivers, based on the report ID found in the beginning of data. The HID class driver then process the data as appropriate: * Keyboard: The keyboard class driver will create a virtual keyboard using the ''%%vkbd(4)%%'' interface and ''%%write(2)%%'' the data (scancodes) received from its parent to the vkbd control device. User programs (for example X window system) and text console can use the virtual keyboard the same way as other normal real keyboards. (See also ''%%bthidd(8)%%''). * Mouse: The mouse class driver will open the ''%%/dev/consolectl%%'' special character device and pass the data (mouse events) to it. It works just like the ''%%moused(8)%%'' daemon. * Consumer Control: The Consumer Control class driver is basically a special keyboard driver that handles multimedia keys found on USB keyboard. This driver translate multimedia key usages to key codes and then an application can handle the key event the same way as any other normal key. See the Multimedia Keys section below for details. * Generic HID: Application collections that don't have a specific class driver can be attached by the Generic HID driver. The driver will create a virtual generic hid device using the ''%%cuse4bsd(3)%%'' library. The virtual HID interface behaves quite similar to the ''%%uhid(4)%%'' interface, except that the data is not generated from a real hid hardware but instead from a userland application. USB hid application like ''%%usbhidctl(1)%%'' and ''%%usbhidaction(1)%%'' can access the virtual generic device through ''%%/dev/uvhid<N>%%'' nodes. (Note that the nodes can be renamed using a configuration option.) ====== Multimedia Keys ====== To support multimedia keys basically is to translate USB consumer usage to keycodes. A multimedia keymap that describes the usage and keycode binding is required in order to make it work. You can build the keymap manually, or better you can let ''%%uhidd%%'' generate it automatically. When you start ''%%uhidd%%'' on a USB mutlimedia Keyboard without a pre-configured keymap, ''%%uhidd%%'' will prepare a in memory keymap. Each time you pressed a new multimedia keys, ''%%uhidd%%'' will remember the key(hid usage) you pressed and assign a free keycode to it, then it adds the usage<->keycode binding to the in memory keymap. The keymap will also be written down to the file ''%%/var/run/uhidd.ugen.X.Y/cc_keymap%%'', what you need to do is copy the keymap to the configuration file ''%%/usr/local/etc/uhidd.conf%%'', so next time uhidd will load the fixed keymap for this keyboard instead of generating another new keymap again. To use the translated keycodes under X window, you will need to write yet another keymap ''%%.Xmodmap%%'' that map the keycode to X window key event. See the Examples section below for an complete setup example for Mircosoft Wireless Desktop 1000. To build the keymap manually, you need to know the consumer usage names and a bunch of unassigned keycodes. Consumer usage name list can be found in ''%%usage_consumer.c%%'' in the source code tarball. A list of free keycodes and the format of the keymap is documented in the ''%%uhidd.conf(5)%%'' manual page. If you played with USB multimedia keyboard on %%FreeBSD%% before, you were probably using the ''%%usbhidaction(1)%%'' utility. The advantage of ''%%uhidd%%'' is that it does not translate hid usage directly to an action(command), instead it only translate them to keycodes and let other applications (e.g. KDE) to handle keycodes->action translation. So in my opinion ''%%uhidd%%'' is more suitable if you intent to let X window (KDE/Gnome) to handle multimedia key events, for example. Further more, ''%%uhidd%%'' support more USB multimedia keyboards than ''%%usbhidaction(1)%%'' ====== Examples ====== ===== PlayStation 2 Hand Controller to USB converter ===== The convertor can support two PS2 hand controls. Below is the appearance of the device. {{uhidd/playstation.2.hand.controller.to.usb.converter.jpg|PlayStation 2 Hand Controller to USB converter}} When connected to the PC under %%FreeBSD%% with in-kernel ''%%uhid(4)%%'' driver active, it will attach itself as a single ''%%/dev/uhid<X>%%'' device. However, from the report descriptor of the converter, it's actually one interface containing two joystick: <code> USAGE PAGE Generic Desktop(0x1) USAGE Joystick(0x4)[Generic Desktop(0x1)] COLLECTION Application(1) REPORT ID 1 ...... END COLLECTION USAGE Joystick(0x4)[Generic Desktop(0x1)] COLLECTION Application(1) REPORT ID 2 ...... END COLLECTION </code> There are two top-level application collections (joystick) corresponding to the two PS2 hand controller it supports. The first controller has report ID 1, and the second has report ID 2. This converter works just fine under M$ Windows, but it won't work under %%FreeBSD%% (or Linux the last time I tested, it attached as just one ''%%/dev/js0%%'') The problem is that some applications/libraries (for example ''%%devel/sdl12%%'') that deal with USB joysticks expect that there should be exactly one ''%%/dev/uhid<X>%%'' node for each USB joystick, but here we got one ''%%/dev/uhid<X>%%'' for two joysticks. So it just won't work. ''%%uhidd%%'' daemon on the other hand can handle this device properly. It will attach those two joystick application collections as two generic hid child devices and creates two virtual HID device nodes. The use ''%%uhidd%%'' daemon with this device, first you need deactivate the in-kernel ''%%uhid(4)%%'' driver, then execute: <code> # uhidd -hs /dev/ugenX.Y </code> ''%%-h%%'' tells the daemon to attach generic hid child device. ''%%-s%%'' tells the daemon to strip the report ID for each report data, to mimic the behaviour of the ''%%uhid(4)%%'' driver. Note that you should unload uhid.ko kernel modules first, otherwise the ''%%uhid(4)%%'' kernel module and the ''%%uhidd%%'' daemon will each get a part of the hid data. (and there won't be any warning/error messages.) At this point, you should find two newly created ''%%uvhid<X>%%'' (or any other name specified in the configuration option) nodes under ''%%/dev%%''. If you use the defualt ''%%uvhid<X>%%'' names, you will probably need to create two symbolic links, in case the application/library has hard-coded ''%%/dev/uhidX%%'' in its source code: <code> # cd /dev # ln -s uvhid0 uhid0 # ln -s uvhid1 uhid1 </code> Then start the application and it should just work. ===== Microsoft Keyboard Mouse Combo ===== The M$ keyboard/mouse combos usually has two interfaces: one interface contains a single keyboard application collection, another one contains a mouse collection plus several consumer control collections. At the time of writing the kernel ''%%ums(4)%%'' driver still has problems supporting the mouse part, while the keyboard is well supported by the ''%%ukbd(4)%%'' (except that the multimedia keys won't work.) Below is the report descriptor of the combos: <code> [interface:0] USAGE Keyboard(0x6)[Generic Desktop(0x1)] COLLECTION Application(1) ...... (omitted) END COLLECTION [interface:1] USAGE Consumer Control(0x1)[Consumer(0xc)] COLLECTION Application(1) ...... END COLLECTION USAGE Mouse(0x2)[Generic Desktop(0x1)] COLLECTION Application(1) ...... END COLLECTION USAGE Consumer Control(0x1)[Consumer(0xc)] COLLECTION Application(1) ...... END COLLECTION USAGE System Control(0x80)[Generic Desktop(0x1)] COLLECTION Application(1) ...... END COLLECTION </code> To use ''%%uhidd%%'' daemon with the combo, first you need to deactivate in-kernel ''%%uhid(4)%%'', ''%%ukbd(4)%%'' and ''%%ums(4)%%'' driver and then execute: <code> # uhidd -kmo /dev/ugenX.Y </code> ''%%-k%%'' tells the daemon to attach the keyboard, ''%%-m%%'' to attach the mouse and ''%%-o%%'' to attach the consumer control driver to handle multimedia keys. Since the keyboard collection is on a separate interface and is the only child device of that interface, it is possible to let the kernel ''%%ukbd(4)%%'' driver handle the keyboard interface, while ''%%uhidd%%'' handles the mouse and multimedia keys. <code> # kldload ukbd.ko # uhidd -mo /dev/ugenX.Y </code> Letting kernel ''%%ukbd(4)%%'' driver handle the keyboard interface makes it possible to use ''%%ddb(4)%%'' with this keyboard/mouse combo. At this point, the mouse should work just fine, while additional work is needed to make the multimedia keys work. First you can just press the multimedia keys on the keyboard, at least once for each key. Then check if you can find a keymap file ''%%/var/run/uhidd.ugen.X.Y/cc_keymap%%'' created by the ''%%uhidd%%'' daemon. What you need to do is to copy paste the content of this file to your uhidd configuration file (usually ''%%/usr/local/etc/uhidd.conf%%'', create a new one if you need) and restart ''%%uhidd%%'' daemon. The daemon will then load the provided keymap and translate keys according to the bindings defined in it. Note that if you do not copy the keymap to configuration file for this keyboard, ''%%uhidd%%'' will try to generate a new keymap (probably different bindings) again the next time it restarts. Example multimedia keymap for Microsoft Wiress Desktop 1000: <code> # 0x045e is the vendor id and 0x009d is the product id. # See `uhidd.conf(5)` manual page for details about configuration file. 0x045e:0x009d={ cc_keymap={ Help="0x7F" Scan_Next_Track="0x62" Scan_Previous_Track="0x60" Stop="0x70" Play/Pause="0x54" Mute="0x63" Volume_Increment="0x5A" Volume_Decrement="0x5F" AL_Consumer_Control_Configuration="0x74" AL_Email_Reader="0x75" AL_Calculator="0x76" AL_Network_Chat="0x7C" AL_Logoff="0x73" AL_Documents="0x6F" AL_Spell_Check="0x6C" AL_Image_Browser="0x71" AL_Audio_Browser="0x72" AC_New="0x66" AC_Open="0x67" AC_Close="0x68" AC_Save="0x6D" AC_Print="0x6E" AC_Undo="0x64" AC_Home="0x7A" AC_Redo/Repeat="0x65" AC_Reply="0x69" AC_Forward_Msg="0x6A" AC_Send="0x6B" } } </code> Now you can confirm this multimedia key translation works by observing key events under ''%%xev(1)%%'', assuming you are using X. It is working if ''%%xev(1)%%'' generate something when you press the multimedia keys. To make the keycodes work under KDE/Gnome you need to create a Xmodmap that additionally translates the keycodes reported by ''%%xev(1)%%'' to X key events. Below is a example Xmodmap for Wireless Desktop 1000: <code> keycode 170 = XF86AudioRaiseVolume keycode 184 = XF86AudioLowerVolume keycode 190 = XF86AudioMute ...... </code> It can be loaded by execute: <code> xmodmap .Xmodmap </code> You can put this line into your X initialization file. For most multimedia keyboards, the basic keyboard part and the multimedia keys are on separate interfaces. So it's perfectly OK to let ''%%ukbd(4)%%'' handle the basic keyboard, and let ''%%uhidd%%'' deal with the multimedia keys. The ''%%uhidd%%'' daemon is confirmed working with ''%%MICROSOFT WIRELESS LASER DESKTOP 5000 USB%%'' and ''%%MICROSOFT WIRELESS OPTICAL DESKTOP 1000 USB%%'', and it should work with other models in the series as well. ====== Debugging and Report Bugs ====== Normally ''%%uhidd%%'' runs in daemon mode in background. Command line option ''%%-d%%'' makes it run in foreground. ''%%-v%%'' makes it output debugging information and multiple ''%%-v%%'' specified in the command line will increase the level of verbosity. ''%%-D%%'' makes the daemon dump the report descriptor. If you are having problems using ''%%uhidd%%'' with your USB hid device, send the output of the following command to kaiw@%%FreeBSD%%.org <code> # uhidd -dD -vvv -kmohu /dev/ugenX.Y </code> uhidd.txt Last modified: 2019/09/18 02:39by KubilayKocak