1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
Purpose of rules file:
This rules file provides nonvolatile, unique names (in the form of symlinks)
for input devices that cooperate.
Description of rules:
This file starts off with a few rules that make Udev skip the entire file if
the current uevent is not input related. If ACTION is not "add", or SUBSYSTEM
is not "input", or KERNEL (the device node) matches "input[0-9]*", then Udev
will GOTO the LABEL named "persistent_input_end", which is the last rule in
this file. (input[0-9]* uevents are skipped because they do not create device
nodes.)
This type of "skip this list of rules if X" operation is done in both the
persistent input and persistent storage rules files. The reason is efficiency
-- if Udev had to go run the usb_id and/or path_id programs for non-input and
non-storage rules, those rules would take much longer to process for no good
reason.
First in this file is a set of rules for by-ID style symlinks. These attempt
to uniquely identify a device based on its serial number, but there are some
issues with this. Many USB manufacturers do not provide a unique serial number
for each device -- for instance, my Microsoft Intellimouse Optical has a USB
serial number of "Microsoft_Microsoft_IntelliMouse_Optical". This kind of
nonsensical "serial number" means that if you plug in two Intellimouse Optical
devices, they will both get the same by-id symlink, and the device that the
symlink points to will be random. This defeats the purpose of by-ID symlinks.
(However, I believe this behavior is technically valid according to the USB
standard. I believe it is not recommended, though.)
Anyway, first in the by-ID rules, we have a rule that runs for any (input)
device hanging anywhere off a USB bus. It uses the IMPORT{program} option to
run the "/lib/udev/usb_id -x" program. usb_id looks at the environment to find
out which device to look at, generates a list of environment-variable VAR=value
pairs, and prints them. Udev stores this output away while the process is
running. After the process exits, Udev modifies the current environment to
include the VARs that usb_id printed. (It assigns the "value"s that usb_id
printed to each of those VARs.) Specifically, usb_id prints ID_VENDOR,
ID_MODEL, ID_REVISION, ID_SERIAL, ID_TYPE, and ID_BUS (at least in the case of
the aforementioned USB optical mouse). These variable names will all be set in
the environment.
Then, we have a set of rules to set ID_CLASS for various types of devices. The
rules first check for a "usb"-bus device that has a "bInterfaceClass" of 03 and
a "bInterfaceProtocol" of 01. If the interface class is 03, this is an HID
device. If the protocol is 01, it's a keyboard device. So we set ID_CLASS to
"kbd". The next rule checks whether the interface protocol is 02, and if so,
sets ID_CLASS to "mouse" (HID devices with a protocol of 02 are mice).
Any input device that the "pcspkr" driver claims must be a speaker. Any input
device that the "atkbd" driver claims must be a keyboard. Any input device
that the "psmouse" driver claims must be a mouse. If there's a sysfs attribute
named "name", whose contents contain "dvb", "DVB", or " IR ", then we set
ID_CLASS to "ir".
Then, we have a rule to search the tree and find the first parent that has a
modalias. If that modalias matches the big long ugly string in the rules file,
we assume this is a joystick device, and set ID_CLASS appropriately. (This
parent should be the kobject for the joystick device itself. The reason we
search the tree is that the current uevent is for a device node, not the
physical joystick device.)
Once the ID_CLASS variable is set properly, we have one more modification to
perform: if the ID_SERIAL variable was not set at all by the usb_id program, we
set it to "noserial".
Now that all the environment variables are set up properly, we start generating
the by-ID symlinks in /dev/input/by-id/. If the current device node's name
starts with "event", we add "event" into the symlink name. Otherwise, we don't
add anything for mice. (Other device types don't get a persistent by-ID
symlink.)
Next, we create by-path symlinks. The /lib/udev/path_id program takes the path
of the device as an argument, and prints out "ID_PATH=string", where "string"
is the "shortest physical path" to the device. We import this value into the
environment.
If the path is non-empty, and the device node name starts with "mouse" or
"event", we add a by-path symlink based on the path and the device class (and
we also add "event" if it's an event device). This symlink should be stable as
long as the device never moves to a different port.
|