Hello,
People that have keyboard with multimedia keys such as "Play" "Volume up" and so on may encounter problems if these keys are not detected by xev(1).
In fact there are two ways to use these keys, a lot of manufacturers usually set these keys are simple keys with a special code that you can deal with xev(1). Some USB keyboards prefer using HID instead. It's better for some reasons like: you can use these keys without X and without setting anything in your window manager usbhidaction(1) is there for this.
1. Detect your USB (uhid) keyboard
First, check if you really have a uhid(4) device, do not forget to add it to your kernel config!
Good news, uhid0 is my keyboard!
2. Get the usable keys
Now we need to see which keys are available. Let see on mine.
My keyboard only have the following buttons :
The other keys described are not on the keyboard but I guess the manufacturer didn't want to remove then, but no worries it will work.
3. Write a usbhidaction(1) config file
Now it's time to setup a usbhidaction(1) file to associate a shell command to the specified button, the syntax is really easy.
Let's try to add an action for the Volume_Increment input:
Collection page=Consumer(1) usage=Consumer_Control(2)
Input size=1 count=1 page=Consumer(3) usage=Volume_Increment(4), logical range 0..1
There is two way to fill an action, by specifying everything like this:
Or the simpliest method is to remove (2) and (4) and simply use the following:
You must admit, it's really better.
But what are these 1 0 ?
As you can see the input has two logical range logical range 0..1, because it's a button it can has two states: pressed and released. 1 means pressed and 0 means released (I guess).
Thus the usbhidaction(1) waits for the bounce value 1 and the debounce value 0 that simply means the key was pressed and released.
4. Passing arguments when calling the action
Whenever the command is called you can pass any arguments you like just like a shell command see :
Now if I run the usbhidaction(1) and give the both arguments it will use them each time I press the key.
As you can see in this example I passed the /dev/mixer device and the increment value I wanted, then I pressed my volume up button fourth times.
5. Automatically run usbhidaction when the device is found
Now you may guess, using the /dev/uhid0 device is not well, imagine you have a joypad detected as /dev/uhid0 before the keyboard you will need to check which one is the good one. So now we will add a devd(8) appropriate entry to match only our keyboard.
First we need to get the keyboard hid vendor Id and product Id with usbconfig(8)
I know that my keyboard hid is /dev/uhid0 but to know the vendor Id and product Id I need to deal with ugenx.y devices.
[cmd=]$ usbconfig show_ifdrv[/cmd]
Now I know that my keyboard hid is located at ugen0.3, directly attached to the same ukbd(4) device.
We need to get the vendor Id and product Id
Now, we need to add the devd.conf(5) entry:
Not so hard, and of course the usbhidaction(1) config in /etc/usbhidaction.conf like this:
That's it! Now each time you reboot it will automatically run usbhidaction(1) only for your keyboard hid and not any other uhid(4) devices.
I hope this helps!
People that have keyboard with multimedia keys such as "Play" "Volume up" and so on may encounter problems if these keys are not detected by xev(1).
In fact there are two ways to use these keys, a lot of manufacturers usually set these keys are simple keys with a special code that you can deal with xev(1). Some USB keyboards prefer using HID instead. It's better for some reasons like: you can use these keys without X and without setting anything in your window manager usbhidaction(1) is there for this.
1. Detect your USB (uhid) keyboard
First, check if you really have a uhid(4) device, do not forget to add it to your kernel config!
$ dmesg | grep uhid
Code:
uhid0: <BTC USB Multimedia Keyboard, class 0/0, rev 1.10/1.20, addr 3> on usbus0
Good news, uhid0 is my keyboard!
2. Get the usable keys
Now we need to see which keys are available. Let see on mine.
$ usbhidctl -f /dev/uhid0 -r
Code:
Report descriptor:
Collection page=Generic_Desktop usage=System_Control
Input size=1 count=1 page=Generic_Desktop usage=System_Power_Down, logical range 0..1
Input size=1 count=1 page=Generic_Desktop usage=System_Sleep, logical range 0..1
Input size=1 count=1 page=Generic_Desktop usage=System_Wake_Up, logical range 0..1
End collection
Collection page=Consumer usage=Consumer_Control
Input size=1 count=1 page=Consumer usage=Volume_Increment, logical range 0..1
Input size=1 count=1 page=Consumer usage=Volume_Decrement, logical range 0..1
Input size=1 count=1 page=Consumer usage=Mute, logical range 0..1
Input size=1 count=1 page=Consumer usage=AC_Search, logical range 0..1
Input size=1 count=1 page=Consumer usage=AC_Home, logical range 0..1
Input size=1 count=1 page=Consumer usage=AC_Bookmarks, logical range 0..1
Input size=1 count=1 page=Consumer usage=Help, logical range 0..1
Input size=1 count=1 page=Consumer usage=AL_Email_Reader, logical range 0..1
Input size=1 count=1 page=Consumer usage=Stop, logical range 0..1
Input size=1 count=1 page=Consumer usage=Scan_Next_Track, logical range 0..1
Input size=1 count=1 page=Consumer usage=Play/Pause, logical range 0..1
Input size=1 count=1 page=Consumer usage=Scan_Previous_Track, logical range 0..1
Input size=1 count=1 page=Consumer usage=Eject, logical range 0..1
Input size=1 count=1 page=Consumer usage=AC_Back, logical range 0..1
Input size=1 count=1 page=Consumer usage=AC_Forward, logical range 0..1
Input size=1 count=1 page=Consumer usage=AC_Stop, logical range 0..1
Input size=1 count=1 page=Consumer usage=AC_Copy, logical range 0..1
Input size=1 count=1 page=Consumer usage=AC_Cut, logical range 0..1
Input size=1 count=1 page=Consumer usage=AL_Consumer_Control_Configuration, logical range 0..1
Input size=1 count=1 page=Consumer usage=AL_Local_Machine_Browser, logical range 0..1
Input size=1 count=1 page=Consumer usage=AL_Calculator, logical range 0..1
Input size=1 count=1 page=Consumer usage=AC_Refresh, logical range 0..1
End collection
... skipping useless microsoft usages ...
Total input size 0 bytes
Total output size 0 bytes
Total feature size 0 bytes
My keyboard only have the following buttons :
- Volume up "Volume_Increment"
- Volume down "Volume_Decrement"
- Volume muting "Mute"
- System sleep "System_Sleep"
The other keys described are not on the keyboard but I guess the manufacturer didn't want to remove then, but no worries it will work.
3. Write a usbhidaction(1) config file
Now it's time to setup a usbhidaction(1) file to associate a shell command to the specified button, the syntax is really easy.
Let's try to add an action for the Volume_Increment input:
Collection page=Consumer(1) usage=Consumer_Control(2)
Input size=1 count=1 page=Consumer(3) usage=Volume_Increment(4), logical range 0..1
There is two way to fill an action, by specifying everything like this:
Code:
# Syntax of usbhidaction file
# Collection page(1):Collection usage(2).input page(4):input usage(3) bounce debounce command
Consumer:Consumer_Control.Consumer:Volume_Increment 1 0 mixer vol +2
Or the simpliest method is to remove (2) and (4) and simply use the following:
Code:
# Simplified syntax
Consumer:Volume_Increment 1 0 mixer vol +2
You must admit, it's really better.
But what are these 1 0 ?
As you can see the input has two logical range logical range 0..1, because it's a button it can has two states: pressed and released. 1 means pressed and 0 means released (I guess).
Thus the usbhidaction(1) waits for the bounce value 1 and the debounce value 0 that simply means the key was pressed and released.
4. Passing arguments when calling the action
Whenever the command is called you can pass any arguments you like just like a shell command see :
Code:
# Syntax with arguments passed when calling the command
# $1 is the mixer device
# $2 is the increment value I want to use
Consumer:Volume_Increment 1 0 mixer -f $1 vol +$2
Now if I run the usbhidaction(1) and give the both arguments it will use them each time I press the key.
$ usbhidaction -d -f /dev/uhid0 -c usbaction.conf /dev/mixer1 2
Code:
Setting the mixer vol from 56:56 to 58:58.
Setting the mixer vol from 58:58 to 60:60.
Setting the mixer vol from 60:60 to 62:62.
Setting the mixer vol from 62:62 to 64:64.
As you can see in this example I passed the /dev/mixer device and the increment value I wanted, then I pressed my volume up button fourth times.
5. Automatically run usbhidaction when the device is found
Now you may guess, using the /dev/uhid0 device is not well, imagine you have a joypad detected as /dev/uhid0 before the keyboard you will need to check which one is the good one. So now we will add a devd(8) appropriate entry to match only our keyboard.
First we need to get the keyboard hid vendor Id and product Id with usbconfig(8)
I know that my keyboard hid is /dev/uhid0 but to know the vendor Id and product Id I need to deal with ugenx.y devices.
[cmd=]$ usbconfig show_ifdrv[/cmd]
Code:
ugen0.1: <EHCI root HUB Intel> at usbus0, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=SAVE
ugen0.1.0: uhub0: <Intel EHCI root HUB, class 9/0, rev 2.00/1.00, addr 1>
ugen1.1: <EHCI root HUB Intel> at usbus1, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=SAVE
ugen1.1.0: uhub1: <Intel EHCI root HUB, class 9/0, rev 2.00/1.00, addr 1>
ugen1.2: <product 0x0020 vendor 0x8087> at usbus1, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=ON
ugen0.2: <product 0x0020 vendor 0x8087> at usbus0, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=SAVE
ugen0.2.0: uhub3: <vendor 0x8087 product 0x0020, class 9/0, rev 2.00/0.00, addr 2>
ugen0.3: <USB Multimedia Keyboard BTC> at usbus0, cfg=0 md=HOST spd=LOW (1.5Mbps) pwr=ON
ugen0.3.0: ukbd0: <BTC USB Multimedia Keyboard, class 0/0, rev 1.10/1.20, addr 3>
ugen0.3.1: uhid0: <BTC USB Multimedia Keyboard, class 0/0, rev 1.10/1.20, addr 3>
ugen0.4: <USB Laser Mouse Logitech> at usbus0, cfg=0 md=HOST spd=LOW (1.5Mbps) pwr=ON
ugen0.4.0: ums0: <Logitech USB Laser Mouse, class 0/0, rev 2.00/31.00, addr 4>
ugen0.5: <EDRClassone vendor 0x0a12> at usbus0, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON
ugen0.5.0: ubt0: <vendor 0x0a12 EDRClassone, class 224/1, rev 2.00/19.58, addr 5>
Now I know that my keyboard hid is located at ugen0.3, directly attached to the same ukbd(4) device.
We need to get the vendor Id and product Id
$ usbconfig -d ugen0.3 dump_device_desc
Code:
ugen0.3: <USB Multimedia Keyboard BTC> at usbus0, cfg=0 md=HOST spd=LOW (1.5Mbps) pwr=ON
bLength = 0x0012
bDescriptorType = 0x0001
bcdUSB = 0x0110
bDeviceClass = 0x0000
bDeviceSubClass = 0x0000
bDeviceProtocol = 0x0000
bMaxPacketSize0 = 0x0008
[I][B]idVendor = 0x046e (1)[/B][/I]
[I][B]idProduct = 0x55a5 (2)[/B][/I]
bcdDevice = 0x0120
iManufacturer = 0x0001 <BTC>
iProduct = 0x0002 <USB Multimedia Keyboard>
iSerialNumber = 0x0000 <no string>
bNumConfigurations = 0x0001
Now, we need to add the devd.conf(5) entry:
Code:
attach 100 {
device-name "uhid[0-9]+";
match "vendor" "0x046e"; # (1)
match "product" "0x55a5"; # (2)
#
# Do not add -d flag ! if you do it devd will never detach to background
# because usbhidaction will run in foreground !
#
# Remember you can add arguments after /etc/usbhidaction.conf like
# action "/usr/bin/usbhidaction -f $device-name -c /etc/usbhidaction.conf /dev/mixer1 2"
#
action "/usr/bin/usbhidaction -f $device-name -c /etc/usbhidaction.conf";
};
Not so hard, and of course the usbhidaction(1) config in /etc/usbhidaction.conf like this:
Code:
#
# For Emprex keyboard
#
Consumer:Volume_Increment 1 0 mixer vol +2
Consumer:Volume_Decrement 1 0 mixer vol -2
Consumer:Mute 1 0 mixer vol 0
That's it! Now each time you reboot it will automatically run usbhidaction(1) only for your keyboard hid and not any other uhid(4) devices.
I hope this helps!