LinuxQuestions.org
Latest LQ Deal: Complete CCNA, CCNP & Red Hat Certification Training Bundle
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 07-31-2008, 11:28 AM   #16
smoked kipper
Member
 
Registered: May 2008
Location: UK
Distribution: Slackware,Slamd64
Posts: 81

Rep: Reputation: 15

Here are my udev rules for a usb keyboard & mouse. (At last!)

Short version:

Code:
KERNEL=="event*", SYSFS{bInterfaceNumber}=="00", SYSFS{modalias}=="usb:v04F2p0210d0003dc00dsc00dp00ic03isc01ip01", \
        NAME="input/%k", SYMLINK+="input/creative_kbd", MODE="0640"

KERNEL=="event*", SYSFS{bInterfaceNumber}=="01", SYSFS{modalias}=="usb:v04F2p0210d0003dc00dsc00dp00ic03isc00ip00", \
        NAME="input/%k", SYMLINK+="input/creative_media", MODE="0644"

KERNEL=="mouse*", SYSFS{bInterfaceNumber}=="02", SYSFS{modalias}=="usb:v04F2p0210d0003dc00dsc00dp00ic03isc01ip02", \
        NAME="input/%k", SYMLINK+="input/creative_mouse", MODE="0644"
Long version:

OK, this is how I setup my usb keyboard/mouse. This is not to suggest it's the
only way, of course, or the "best" way, but this what worked for me. I did this
3 or 4 months ago, so I'm trying to retrace what I did. As mentioned, this is a
keyboard/mouse combo, so there are multiple devices to handle. Also, it actually
has two keyboard interfaces, one for the actual keyboard and one for the multimedia
keys, so it has three logical devices. It is a Creative Wireless 8000 (which isn't
a particularly great keyboard, but I got it cheap), and it turns out that it (or at
least the usb controller) is made by Chicony.

First, make sure the device is plugged in.

Code:
# lsusb
Bus 002 Device 004: ID 04f2:0210 Chicony Electronics Co., Ltd
...
Now, I lookup usb bus 2 device 4 in /sys.

Code:
# ls -l /sys/bus/usb/devices/2-4*
lrwxrwxrwx 1 root root 0 2008-07-27 08:59 /sys/bus/usb/devices/2-4 -> ../../../devices/pci0000:00/0000:00:02.0/usb2/2-4
lrwxrwxrwx 1 root root 0 2008-07-27 08:59 /sys/bus/usb/devices/2-4:1.0 -> ../../../devices/pci0000:00/0000:00:02.0/usb2/2-4/2-4:1.0
lrwxrwxrwx 1 root root 0 2008-07-27 08:59 /sys/bus/usb/devices/2-4:1.1 -> ../../../devices/pci0000:00/0000:00:02.0/usb2/2-4/2-4:1.1
lrwxrwxrwx 1 root root 0 2008-07-27 08:59 /sys/bus/usb/devices/2-4:1.2 -> ../../../devices/pci0000:00/0000:00:02.0/usb2/2-4/2-4:1.2
So there are 4 entries, which turn out to be:

Code:
2-4             parent device (the usb interface, don't really need to worry about this)
2-4:1.0         keyboard
2-4:1.1         2nd keyboard device (multimedia keys)
2-4:1.2         mouse
This can determined in a number of ways, for example

Code:
# cat /proc/bus/input/devices
...
I: Bus=0003 Vendor=04f2 Product=0210 Version=0110
N: Name="Chicony USB Wireless HID Receiver"
P: Phys=usb-0000:00:02.0-4/input0
S: Sysfs=/devices/pci0000:00/0000:00:02.0/usb2/2-4/2-4:1.0/input/input4
U: Uniq=
H: Handlers=kbd event4
...
   
I: Bus=0003 Vendor=04f2 Product=0210 Version=0110
N: Name="Chicony USB Wireless HID Receiver"
P: Phys=usb-0000:00:02.0-4/input1
S: Sysfs=/devices/pci0000:00/0000:00:02.0/usb2/2-4/2-4:1.1/input/input5
U: Uniq=
H: Handlers=kbd event5
...
   
I: Bus=0003 Vendor=04f2 Product=0210 Version=0110
N: Name="Chicony USB Wireless HID Receiver"
P: Phys=usb-0000:00:02.0-4/input2
S: Sysfs=/devices/pci0000:00/0000:00:02.0/usb2/2-4/2-4:1.2/input/input6
U: Uniq=
H: Handlers=mouse1 event6
...
...
Thus, device 2 (2-4:1.2) is a mouse, and the others are the keyboard devices
(trial and error easily determines which is the main keyboard, just cat (or
hexdump -C) the device node(s) and press some keys).

Now that I know which device is which, I use udevinfo to inspect them. Since I
have multiple devices, I dump the info into some files so I can look at them
all at once. If you just have one device, obviously you can pipe the udevinfo
output straight to less.

(I use a .txt extension to prevent less (or rather, lesspipe.sh) from thinking
that e.g. 2-4:1.2 is a manpage, which it is prone to do with single digit
extensions.)

Code:
# for f in /sys/bus/usb/devices/2-4*; do udevinfo -a -p $f > udev-$(basename $f).txt; done
# less udev-*
<digression> In anticipation of some smart-alec pointing it out, it is, of
course, more efficient to use ${f##*/} rather than $(basename $f), I just used
that for clarity. In reality, I actually used the more readable csh-style
syntax ${f:t} but that (like a lot of things) doesn't work in bash (happily, I
don't use bash myself). </digression>

Anyway, this is the pertinent output (I ignore the parent (2-4) device since
it is not an input device):

Code:
  looking at device '/devices/pci0000:00/0000:00:02.0/usb2/2-4/2-4:1.0':
    KERNEL=="2-4:1.0"
    SUBSYSTEM=="usb" 
    DRIVER=="usbhid" 
    SYSFS{bInterfaceNumber}=="00"
    SYSFS{bAlternateSetting}==" 0"
    SYSFS{bNumEndpoints}=="01"
    SYSFS{bInterfaceClass}=="03"
    SYSFS{bInterfaceSubClass}=="01"
    SYSFS{bInterfaceProtocol}=="01"
    SYSFS{modalias}=="usb:v04F2p0210d0003dc00dsc00dp00ic03isc01ip01"

  looking at parent device '/devices/pci0000:00/0000:00:02.0/usb2/2-4':
    ID=="2-4"
    BUS=="usb"
    DRIVER=="usb"
    SYSFS{dev}=="189:131"
    SYSFS{configuration}==""
    SYSFS{bNumInterfaces}==" 3"
    SYSFS{bConfigurationValue}=="1"
    SYSFS{bmAttributes}=="a0"
    SYSFS{bMaxPower}=="100mA"
    SYSFS{urbnum}=="149"
    SYSFS{idVendor}=="04f2"
    SYSFS{idProduct}=="0210"
    SYSFS{bcdDevice}=="0003"
    SYSFS{bDeviceClass}=="00"
    SYSFS{bDeviceSubClass}=="00"
    SYSFS{bDeviceProtocol}=="00"
    SYSFS{bNumConfigurations}=="1"
    SYSFS{bMaxPacketSize0}=="8"   
    SYSFS{speed}=="1.5"
    SYSFS{busnum}=="2" 
    SYSFS{devnum}=="4" 
    SYSFS{version}==" 1.10"
    SYSFS{maxchild}=="0"   
    SYSFS{quirks}=="0x0"   
    SYSFS{authorized}=="1" 
    SYSFS{manufacturer}=="Chicony"
    SYSFS{product}=="USB Wireless HID Receiver"

    ...
Code:
  looking at device '/devices/pci0000:00/0000:00:02.0/usb2/2-4/2-4:1.1':
    KERNEL=="2-4:1.1"
    SUBSYSTEM=="usb" 
    DRIVER=="usbhid" 
    SYSFS{bInterfaceNumber}=="01"
    SYSFS{bAlternateSetting}==" 0"
    SYSFS{bNumEndpoints}=="01"
    SYSFS{bInterfaceClass}=="03"
    SYSFS{bInterfaceSubClass}=="00"
    SYSFS{bInterfaceProtocol}=="00"
    SYSFS{modalias}=="usb:v04F2p0210d0003dc00dsc00dp00ic03isc00ip00"

    ...
    # same as above
Code:
  looking at device '/devices/pci0000:00/0000:00:02.0/usb2/2-4/2-4:1.2':
    KERNEL=="2-4:1.2"
    SUBSYSTEM=="usb" 
    DRIVER=="usbhid"
    SYSFS{bInterfaceNumber}=="02" 
    SYSFS{bAlternateSetting}==" 0"
    SYSFS{bNumEndpoints}=="01"    
    SYSFS{bInterfaceClass}=="03"   
    SYSFS{bInterfaceSubClass}=="01"
    SYSFS{bInterfaceProtocol}=="02"
    SYSFS{modalias}=="usb:v04F2p0210d0003dc00dsc00dp00ic03isc01ip02"

    ...
    # same as above
As you can see they each have a different SYSFS{bInterfaceNumber} thus
distinguishing them from each other, but every usb device has an interface
number so obviously this alone is not enough. However, you cannot (AFAIK)
combine attributes from multiple devices, so all the convenient identifying
attributes (manufacurer/product/idProduct/idVendor/etc) from the parent device
cannot be used with the bInterfaceNumber, and obviously the parent attributes
are no use by themselves since they will match all three devices (though, of
course, if you only have a single logical device, they will suffice).

But wait... we see that the kernel encodes all the pertinent information about
the device into the device's "modalias" attribute.

Code:
2-4:1.0 => SYSFS{modalias}=="usb:v04F2p0210d0003dc00dsc00dp00ic03isc01ip01"
2-4:1.1 => SYSFS{modalias}=="usb:v04F2p0210d0003dc00dsc00dp00ic03isc00ip00"
2-4:1.2 => SYSFS{modalias}=="usb:v04F2p0210d0003dc00dsc00dp00ic03isc01ip02"
As you can see, this includes the Vendor and Product IDs (04f2:0210), plus
most of the other attributes from above, thus this gives us a string uniquely
identifying each device, so we should be able to use this in a udev rule.

(You may notice that device 2-4:1.0 (InterfaceNumber 0) has an
Interface{Subclass,Protocol) of 1 whilst for device 2-4:1.1 (InterfaceNumber
1) the Interface{SubClass,Protocol} is 0. I don't know why, but it doesn't
matter as long as the device is uniquely identified.)

You'll also observe that the KERNEL attribute is "2-4:1.0" etc, which is
obviously useless for a udev rule since it tells us nothing about the actual
device (and, of course, will change depending on the port the device is
plugged into). However, we know that the name of the real device node (the one
passed to udev) will be called "event*" so we can just match that.

So these are my final rules:

Code:
# Creative Wireless 8000 (Chicony)
KERNEL=="event*", SYSFS{bInterfaceNumber}=="00", SYSFS{modalias}=="usb:v04F2p0210d0003dc00dsc00dp00ic03isc01ip01", \
        NAME="input/%k", SYMLINK+="input/creative_kbd", MODE="0640"

KERNEL=="event*", SYSFS{bInterfaceNumber}=="01", SYSFS{modalias}=="usb:v04F2p0210d0003dc00dsc00dp00ic03isc00ip00", \
        NAME="input/%k", SYMLINK+="input/creative_media", MODE="0644"

KERNEL=="mouse*", SYSFS{bInterfaceNumber}=="02", SYSFS{modalias}=="usb:v04F2p0210d0003dc00dsc00dp00ic03isc01ip02", \
        NAME="input/%k", SYMLINK+="input/creative_mouse", MODE="0644"
(Of course, technically I don't need the bInterfaceNumber because the modalias
attribute completely identifies each device, this is just for clarity, i.e.
since the Sub{Class,Protocol} numbers are reversed for the keyboard devices, I
added the bInterfaceNumber so that in a year or so when I've forgotten what I
did, I don't think "Hang on, why does the modalias for the main keyboard end
with p01 and the other device has p00, surely the main keyboard should be
first?". I can look back and see the order of the devices and I don't need to
worry about the details of modalias.)

As for the MODE, generally keyboard devices should not be world readable, you
don't want some random user reading your keyboard, so that is 0640 (which is
typically the default for event nodes). In my case, the creative_media device
only handles a few buttons, and mice are no big deal, just buttons and
coordinates, and it's useful for testing to have these readable, hence 0644
for those.

This is just one way to do it, of course, in most cases there are probably a
number of ways to write a successful rule, and after much wrestling with udev
rules, it seems to me that, like computer programming in general, it's as much
an art as a science.

And again, if you only have a single logical device, then the SYSFS
"manufacturer" and/or "product" attribute(s) should be adequate. As an
example, my main mouse is a Razer Diamondback:

Code:
  looking at device '/devices/pci0000:00/0000:00:02.0/usb2/2-2/2-2:1.0':
    KERNEL=="2-2:1.0"
    SUBSYSTEM=="usb" 
    DRIVER=="usbhid" 
    SYSFS{bInterfaceNumber}=="00"
    SYSFS{bAlternateSetting}==" 0"
    SYSFS{bNumEndpoints}=="01"
    SYSFS{bInterfaceClass}=="03"
    SYSFS{bInterfaceSubClass}=="01"
    SYSFS{bInterfaceProtocol}=="02"
    SYSFS{modalias}=="usb:v1532p0001d2300dc00dsc00dp00ic03isc01ip02"

  looking at parent device '/devices/pci0000:00/0000:00:02.0/usb2/2-2':
    ID=="2-2"
    ...
    ...
    SYSFS{manufacturer}=="Razer"
    SYSFS{product}=="Razer 1600dpi Mouse"
    ...
I could use the modalias for this too, but the parent's product attribute is
clearer and is sufficient to identify it:

Code:
KERNEL=="mouse*", SYSFS{product}=="Razer 1600dpi Mouse", NAME="input/%k", SYMLINK+="input/razer_db", MODE="0644"
Finally, I note again that you must match the KERNEL name for the node in
/dev, something like "serio" won't work since it doesn't have a device node.

So that's the kernel configuration. X is be more straightforward as you just
need to specify the path for the appropriate node in the "Device" option:

(Note, I have not specified a device for the core keyboard ("Keyboard"), so it
uses the default/primary system keyboard.)


Code:
...   
      
Section "InputDevice"
        Identifier      "Keyboard"
        Driver          "kbd"
        ...
EndSection 

Section "InputDevice"
        Identifier      "Razer"
        Driver          "mouse"
        Option          "Device"        "/dev/input/razer_db"
        ...
EndSection 

Section "InputDevice"
        Identifier      "CreativeKeyboard"
        Driver          "kbd"
        Option          "Device"        "/dev/input/creative_kbd"
        ...
EndSection 

Section "InputDevice"
        Identifier      "CreativeMedia"
        Driver          "kbd"
        Option          "Device"        "/dev/input/creative_media"
        ...
EndSection 

Section "InputDevice"
        Identifier      "CreativeMouse"
        Driver          "mouse"
        Option          "Device"        "/dev/input/creative_mouse"
        ...
EndSection 

...
   
Section "ServerLayout"
        Identifier          "default"
        Screen              "Screen0"
        InputDevice         "Keyboard"          "CoreKeyboard"
        InputDevice         "CreativeKeyboard"  "SendCoreEvents"
        InputDevice         "CreativeMedia"     "SendCoreEvents"
        InputDevice         "Razer"             "CorePointer"   
        InputDevice         "CreativeMouse"     "SendCoreEvents"
EndSection

...
Of course, you can use /dev/input/mice for all your mice, but my mice have
different levels of sensitivity so I generally need a different acceleration
for each to make them equally responsive, which can only be done if you use
seperate devices.

Last edited by smoked kipper; 08-02-2008 at 12:46 PM.
 
Old 08-01-2008, 04:13 AM   #17
JZL240I-U
Senior Member
 
Registered: Apr 2003
Location: Germany
Distribution: openSuSE 42.1_64+Tumbleweed-KDE, Mint 17.3
Posts: 3,951

Rep: Reputation: Disabled
Congratulations for your finding a solution .

Thank you for coming back and sharing it. Since you show the way how you did it very thoroughly your post has the potential to really help others here at LQ .

Quote:
Originally Posted by smoked kipper View Post
...so that in a year or so when I've forgotten what I did...
Tsk-tsk-tsk. You would of course click on the right side panel on "My Threads" and search those for "udev" && "USB" and find in no time the entry you searched .

Last edited by JZL240I-U; 08-01-2008 at 04:16 AM.
 
Old 08-04-2008, 11:27 AM   #18
smoked kipper
Member
 
Registered: May 2008
Location: UK
Distribution: Slackware,Slamd64
Posts: 81

Rep: Reputation: 15
Quote:
Originally Posted by JZL240I-U View Post
Congratulations for your finding a solution .

Tsk-tsk-tsk. You would of course click on the right side panel on "My Threads" and search those for "udev" && "USB" and find in no time the entry you searched .
Heh . Well, I did this some months ago, I'm just recollecting what I did. The redundant bInterfaceNumber attributes were added as a form of code commenting, I just found it odd that the SubClass/Protocol numbers were reversed. Posting it online wasn't a consideration at the time.

Of course, this doesn't solve the original problem of having the keyboards produce different keysyms. I think (not certain) that xmodmap applies globally, so if different keymaps are still desired, the best bet is probably to use a custom XKB configuration file, at which point I have to run away screaming because XKB is a big hairy monster.

Alternatively, you could use input_device_grab (linux specific, of course) as I mentioned earlier, and have the app interpret the input events any way it sees fit.
 
Old 08-04-2008, 07:24 PM   #19
krisbee
Member
 
Registered: Jan 2006
Posts: 60

Original Poster
Rep: Reputation: 15
Smoked Kipper,

Thank you so much for the post on what you did... I still have not tried it out yet, as work here on the farm has been pretty rough, but I am hoping soon to try it out, and of course, I will report back what I found.

I think it will pretty easy to modify the X11 keymaps to make this all work as intended.

--Krisbee
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
How to redirect keyboard as well as output ackzsel Linux - General 2 10-04-2007 10:16 AM
changing uname -r output kesari Red Hat 2 11-04-2004 06:20 AM
Keyboard output buffer Majestros Linux - Hardware 0 07-06-2004 10:01 AM
Changing the output of lspci GT_Onizuka Linux - General 2 04-30-2004 06:50 PM
Changing the color of ls output? exitsfunnel Linux - Newbie 1 02-20-2004 12:20 AM


All times are GMT -5. The time now is 08:36 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration