Signed-off-by: Kay Sievers <kay.sievers@suse.de>
to syslog, so any error logged from the kernel can be associated with
any of the links at that time.
to syslog, so any error logged from the kernel can be associated with
any of the links at that time.
- o Fix inconsistency with KERNEL and ID. ID will walk up the device chain
- but it matches on "KERNEL names" too. And ID and SYSFS can only match
- on the same device in the chain. That's pretty hard to explain and to
- understand. Same for SUBSYSTEM and BUS.
-
-
These things are deprecated and scheduled for removal in a future
udev version:
These things are deprecated and scheduled for removal in a future
udev version:
<varlistentry>
<term><option>ACTION</option></term>
<listitem>
<varlistentry>
<term><option>ACTION</option></term>
<listitem>
- <para>Match the kernel action name.</para>
+ <para>Match the name of the event action.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>KERNEL</option></term>
<listitem>
</listitem>
</varlistentry>
<varlistentry>
<term><option>KERNEL</option></term>
<listitem>
- <para>Match the kernel device name</para>
+ <para>Match the name of the device.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>DEVPATH</option></term>
<listitem>
</listitem>
</varlistentry>
<varlistentry>
<term><option>DEVPATH</option></term>
<listitem>
- <para>Match the kernel devpath.</para>
+ <para>Match the devpath of the device.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>SUBSYSTEM</option></term>
<listitem>
</listitem>
</varlistentry>
<varlistentry>
<term><option>SUBSYSTEM</option></term>
<listitem>
- <para>Match the kernel subsystem name</para>
+ <para>Match the subsystem of the device.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>BUS</option></term>
<listitem>
</listitem>
</varlistentry>
<varlistentry>
<term><option>BUS</option></term>
<listitem>
- <para>Match the type of bus the device is connected to.</para>
+ <para>Search the devpath upwards for a matching device subsystem name.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>DRIVER</option></term>
<listitem>
</listitem>
</varlistentry>
<varlistentry>
<term><option>DRIVER</option></term>
<listitem>
- <para>Match the kernel driver name.</para>
+ <para>Search the devpath upwards for a matching device driver name.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>ID</option></term>
<listitem>
</listitem>
</varlistentry>
<varlistentry>
<term><option>ID</option></term>
<listitem>
- <para>Match the device number on the bus.</para>
+ <para>Search the devpath upwards for a matching device name.</para>
</listitem>
</varlistentry>
<varlistentry>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>ENV{<replaceable>key</replaceable>}</option></term>
+ <term><option>SYSFS{<replaceable>filename</replaceable>}</option></term>
- <para>Match against the value of an environment key. Depending on
- the specified operation, this key is also used as an assignment.</para>
+ <para>Search the devpath upwards for a device with matching sysfs attribute values.
+ Up to five <option>SYSFS</option> keys can be specified per rule. All attributes
+ must match on the same device. Trailing whitespace in the attribute values is ignored,
+ if the specified match value does not contain trailing whitespace itself.</para>
</listitem>
</varlistentry>
<varlistentry>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>SYSFS{<replaceable>filename</replaceable>}</option></term>
+ <term><option>ENV{<replaceable>key</replaceable>}</option></term>
- <para>Match the sysfs attribute value. Up to five values can be specified.
- Trailing whitespace is ignored, if the specified match value does not contain
- trailing whitespace itself.</para>
+ <para>Match against the value of an environment variable. Up to five <option>ENV</option>
+ keys can be specified per rule. This key can also be used to export a variable to
+ the environment.</para>
</listitem>
</varlistentry>
</listitem>
</varlistentry>
<varlistentry>
<term><option>ENV{<replaceable>key</replaceable>}</option></term>
<listitem>
<varlistentry>
<term><option>ENV{<replaceable>key</replaceable>}</option></term>
<listitem>
- <para>Export the key to the environment. Depending on the specified
- operation, this key is also used as a match.</para>
+ <para>Export a variable to the environment. This key can also be used to match
+ against an environment variable.</para>
</listitem>
</varlistentry>
</listitem>
</varlistentry>
<varlistentry>
<term><option>IMPORT{<replaceable>type</replaceable>}</option></term>
<listitem>
<varlistentry>
<term><option>IMPORT{<replaceable>type</replaceable>}</option></term>
<listitem>
- <para>Import the printed result or the content of a file in environment key
+ <para>Import the printed result or the value of a file in environment key
format into the event environment. <option>program</option> will execute an
external program and read its output. <option>file</option> will inport a
text file. If no option is given, udev will determine it from the executable
format into the event environment. <option>program</option> will execute an
external program and read its output. <option>file</option> will inport a
text file. If no option is given, udev will determine it from the executable
<varlistentry>
<term><option>WAIT_FOR_SYSFS</option></term>
<listitem>
<varlistentry>
<term><option>WAIT_FOR_SYSFS</option></term>
<listitem>
- <para>Wait for the specified sysfs file of the device to be created. May be used
- to fight agains timing issues wth the kernel.</para>
+ <para>Wait for the specified sysfs file of the device to be created. Can be used
+ to fight against kernel sysfs timing issues.</para>
</listitem>
</varlistentry>
</listitem>
</varlistentry>
printf-like string substitutions:</para>
<variablelist>
<varlistentry>
printf-like string substitutions:</para>
<variablelist>
<varlistentry>
- <term><option>%k</option>, <option>$kernel</option></term>
+ <term><option>$kernel</option>, <option>%k</option></term>
<listitem>
<para>The kernel name for this device.</para>
</listitem>
</varlistentry>
<varlistentry>
<listitem>
<para>The kernel name for this device.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>%n</option>, <option>$number</option></term>
+ <term><option>$number</option>, <option>%n</option></term>
<listitem>
<para>The kernel number for this device. For example, 'sda3' has
kernel number of '3'</para>
<listitem>
<para>The kernel number for this device. For example, 'sda3' has
kernel number of '3'</para>
</varlistentry>
<varlistentry>
</varlistentry>
<varlistentry>
- <term><option>%p</option>, <option>$devpath</option></term>
+ <term><option>$devpath</option>, <option>%p</option></term>
<listitem>
<para>The devpath of the device.</para>
</listitem>
</varlistentry>
<varlistentry>
<listitem>
<para>The devpath of the device.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>%s{<replaceable>file</replaceable>}</option>, <option>$sysfs{<replaceable>file</replaceable>}</option></term>
+ <term><option>$id</option>, <option>%b</option></term>
+ <listitem>
+ <para>The name of the device matched while searching the devpath upwards for
+ <option>BUS</option>, <option>ID</option> <option>DRIVER</option> and <option>SYSFS</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>$sysfs{<replaceable>file</replaceable>}</option>, <option>%s{<replaceable>file</replaceable>}</option></term>
- <para>The content of a sysfs attribute.</para>
+ <para>The value of a sysfs attribute found at the current or a parent device.</para>
</listitem>
</varlistentry>
<varlistentry>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>%E{<replaceable>key</replaceable>}</option>, <option>$env{<replaceable>key</replaceable>}</option></term>
+ <term><option>$env{<replaceable>key</replaceable>}</option>, <option>%E{<replaceable>key</replaceable>}</option></term>
<listitem>
<para>The value of an environment variable.</para>
</listitem>
</varlistentry>
<varlistentry>
<listitem>
<para>The value of an environment variable.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>%m</option>, <option>$major</option></term>
+ <term><option>$major</option>, <option>%M</option></term>
<listitem>
<para>The kernel major number for the device.</para>
</listitem>
</varlistentry>
<varlistentry>
<listitem>
<para>The kernel major number for the device.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>%M</option> <option>$minor</option></term>
+ <term><option>$minor</option> <option>%m</option></term>
<listitem>
<para>The kernel minor number for the device.</para>
</listitem>
</varlistentry>
<varlistentry>
<listitem>
<para>The kernel minor number for the device.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>%c</option>, <option>$result</option></term>
+ <term><option>$result</option>, <option>%c</option></term>
<listitem>
<para>The string returned by the external program requested with PROGRAM.
A single part of the string, separated by a space character may be selected
<listitem>
<para>The string returned by the external program requested with PROGRAM.
A single part of the string, separated by a space character may be selected
</varlistentry>
<varlistentry>
</varlistentry>
<varlistentry>
- <term><option>%P</option>, <option>$parent</option></term>
+ <term><option>$parent</option>, <option>%P</option></term>
<listitem>
<para>The node name of the parent device.</para>
</listitem>
</varlistentry>
<varlistentry>
<listitem>
<para>The node name of the parent device.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>%r</option>, <option>$root</option></term>
+ <term><option>$root</option>, <option>%r</option></term>
<listitem>
<para>The udev_root value.</para>
</listitem>
</varlistentry>
<varlistentry>
<listitem>
<para>The udev_root value.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>%N</option>, <option>$tempnode</option></term>
+ <term><option>$tempnode</option>, <option>%N</option></term>
<listitem>
<para>The name of a created temporary device node to provide access to
the device from a external program before the real node is created.</para>
<listitem>
<para>The name of a created temporary device node to provide access to
the device from a external program before the real node is created.</para>
- desc => "place on bus of scsi partition",
+ desc => "parent device name match of scsi partition",
subsys => "block",
devpath => "/block/sda/sda3",
exp_name => "first_disk3" ,
subsys => "block",
devpath => "/block/sda/sda3",
exp_name => "first_disk3" ,
desc => "test substitution chars",
subsys => "block",
devpath => "/block/sda/sda3",
desc => "test substitution chars",
subsys => "block",
devpath => "/block/sda/sda3",
- exp_name => "Major:8:minor:3:kernelnumber:3" ,
+ exp_name => "Major:8:minor:3:kernelnumber:3:id:0:0:0:0" ,
-BUS=="scsi", ID=="0:0:0:0", NAME="Major:%M:minor:%m:kernelnumber:%n"
+BUS=="scsi", ID=="0:0:0:0", NAME="Major:%M:minor:%m:kernelnumber:%n:id:%b"
EOF
},
{
desc => "test substitution chars (with length limit)",
subsys => "block",
devpath => "/block/sda/sda3",
EOF
},
{
desc => "test substitution chars (with length limit)",
subsys => "block",
devpath => "/block/sda/sda3",
- exp_name => "M8-m3-n3-bsd-sIBM" ,
+ exp_name => "M8-m3-n3-b0:0-sIBM" ,
-BUS=="scsi", ID=="0:0:0:0", NAME="M%M-m%m-n%n-b%2k-s%3s{vendor}"
+BUS=="scsi", ID=="0:0:0:0", NAME="M%M-m%m-n%n-b%3b-s%3s{vendor}"
desc => "program result substitution",
subsys => "block",
devpath => "/block/sda/sda3",
desc => "program result substitution",
subsys => "block",
devpath => "/block/sda/sda3",
+ exp_name => "test-0:0:0:0" ,
-BUS=="scsi", PROGRAM=="/bin/echo -n test-%n", RESULT=="test-3*", NAME="%c"
+BUS=="scsi", PROGRAM=="/bin/echo -n test-%b", RESULT=="test-0:0*", NAME="%c"
desc => "test substitution by variable name",
subsys => "block",
devpath => "/block/sda/sda3",
desc => "test substitution by variable name",
subsys => "block",
devpath => "/block/sda/sda3",
- exp_name => "Major:8-minor:3-kernelnumber:3" ,
+ exp_name => "Major:8-minor:3-kernelnumber:3-id:0:0:0:0",
-BUS=="scsi", ID=="0:0:0:0", NAME="Major:\$major-minor:\$minor-kernelnumber:\$number"
+BUS=="scsi", ID=="0:0:0:0", NAME="Major:\$major-minor:\$minor-kernelnumber:\$number-id:\$id"
EOF
},
{
desc => "test substitution by variable name 2",
subsys => "block",
devpath => "/block/sda/sda3",
EOF
},
{
desc => "test substitution by variable name 2",
subsys => "block",
devpath => "/block/sda/sda3",
- exp_name => "Major:8-minor:3-kernelnumber:3-name:sda3" ,
+ exp_name => "Major:8-minor:3-kernelnumber:3-id:0:0:0:0",
-BUS=="scsi", ID=="0:0:0:0", DEVPATH="*/sda/*", NAME="Major:\$major-minor:%m-kernelnumber:\$number-name:\$kernel"
+BUS=="scsi", ID=="0:0:0:0", DEVPATH="*/sda/*", NAME="Major:\$major-minor:%m-kernelnumber:\$number-id:\$id"
EOF
},
{
desc => "test substitution by variable name 3",
subsys => "block",
devpath => "/block/sda/sda3",
EOF
},
{
desc => "test substitution by variable name 3",
subsys => "block",
devpath => "/block/sda/sda3",
- exp_name => "83sda33" ,
+ exp_name => "830:0:0:03" ,
-BUS=="scsi", ID=="0:0:0:0", DEVPATH="*/sda/*", NAME="%M%m%k%n"
+BUS=="scsi", ID=="0:0:0:0", DEVPATH="*/sda/*", NAME="%M%m%b%n"
desc => "test substitution by variable name 5",
subsys => "block",
devpath => "/block/sda/sda3",
desc => "test substitution by variable name 5",
subsys => "block",
devpath => "/block/sda/sda3",
- exp_name => "833sda3" ,
+ exp_name => "8330:0:0:0" ,
-BUS=="scsi", ID=="0:0:0:0", DEVPATH="*/sda/*", NAME="\$major%m%n\$kernel"
+BUS=="scsi", ID=="0:0:0:0", DEVPATH="*/sda/*", NAME="\$major%m%n\$id"
- desc => "invalid program for device with no bus",
+ desc => "non matching BUS for device with no parent",
subsys => "tty",
devpath => "/class/tty/console",
subsys => "tty",
devpath => "/class/tty/console",
rules => <<EOF
BUS=="scsi", PROGRAM=="/bin/echo -n foo", RESULT=="foo", NAME="foo"
KERNEL=="console", NAME="TTY"
EOF
},
{
rules => <<EOF
BUS=="scsi", PROGRAM=="/bin/echo -n foo", RESULT=="foo", NAME="foo"
KERNEL=="console", NAME="TTY"
EOF
},
{
- desc => "valid program for device with no bus",
- subsys => "tty",
- devpath => "/class/tty/console",
- exp_name => "foo" ,
- rules => <<EOF
-PROGRAM=="/bin/echo -n foo", RESULT=="foo", NAME="foo"
-KERNEL=="console", NAME="TTY"
-EOF
- },
- {
- desc => "invalid label for device with no bus",
+ desc => "non matching BUS",
subsys => "tty",
devpath => "/class/tty/console",
exp_name => "TTY" ,
subsys => "tty",
devpath => "/class/tty/console",
exp_name => "TTY" ,
- desc => "valid label for device with no bus",
subsys => "tty",
devpath => "/class/tty/console",
exp_name => "foo" ,
subsys => "tty",
devpath => "/class/tty/console",
exp_name => "foo" ,
desc => "program and bus type match",
subsys => "block",
devpath => "/block/sda",
desc => "program and bus type match",
subsys => "block",
devpath => "/block/sda",
- exp_name => "scsi-sda" ,
+ exp_name => "scsi-0:0:0:0" ,
-BUS=="usb", PROGRAM=="/bin/echo -n usb-%k", NAME="%c"
-BUS=="scsi", PROGRAM=="/bin/echo -n scsi-%k", NAME="%c"
-BUS=="foo", PROGRAM=="/bin/echo -n foo-%k", NAME="%c"
+BUS=="usb", PROGRAM=="/bin/echo -n usb-%b", NAME="%c"
+BUS=="scsi", PROGRAM=="/bin/echo -n scsi-%b", NAME="%c"
+BUS=="foo", PROGRAM=="/bin/echo -n foo-%b", NAME="%c"
exp_name => "symlink2-ttyUSB0",
exp_target => "ttyUSB0",
rules => <<EOF
exp_name => "symlink2-ttyUSB0",
exp_target => "ttyUSB0",
rules => <<EOF
-KERNEL=="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="symlink1-%n symlink2-%k"
+KERNEL=="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="symlink1-%n symlink2-%k symlink3-%b"
- desc => "symlink %k substitution",
+ desc => "symlink %b substitution",
subsys => "block",
devpath => "/block/sda",
subsys => "block",
devpath => "/block/sda",
- exp_name => "symlink-sda",
+ exp_name => "symlink-0:0:0:0",
exp_target => "node",
rules => <<EOF
exp_target => "node",
rules => <<EOF
-BUS=="scsi", KERNEL=="sda", NAME="node", SYMLINK+="symlink-%k"
+BUS=="scsi", KERNEL=="sda", NAME="node", SYMLINK+="symlink-%b"
$ENV{DEVPATH} = $devpath;
$ENV{DEVPATH} = $devpath;
- open my $fd, "$sysfs$devpath/dev";
- my $dev = <$fd>;
- close $fd;
- $dev =~ m/^(.+):(.+)$/;
- $ENV{MAJOR} = $1;
- $ENV{MINOR} = $2;
-
# create temporary rules
open CONF, ">$udev_rules" || die "unable to create rules file: $udev_rules";
print CONF $$rules;
# create temporary rules
open CONF, ">$udev_rules" || die "unable to create rules file: $udev_rules";
print CONF $$rules;
The following key names can be used to match against device properties:
.TP
\fBACTION\fR
The following key names can be used to match against device properties:
.TP
\fBACTION\fR
-Match the kernel action name.
+Match the name of the event action.
-Match the kernel device name
+Match the name of the device.
-Match the kernel devpath.
+Match the devpath of the device.
-Match the kernel subsystem name
+Match the subsystem of the device.
-Match the type of bus the device is connected to.
+Search the devpath upwards for a matching device subsystem name.
-Match the kernel driver name.
+Search the devpath upwards for a matching device driver name.
-Match the device number on the bus.
-.TP
-\fBENV{\fR\fB\fIkey\fR\fR\fB}\fR
-Match against the value of an environment key. Depending on the specified operation, this key is also used as an assignment.
+Search the devpath upwards for a matching device name.
.TP
\fBSYSFS{\fR\fB\fIfilename\fR\fR\fB}\fR
.TP
\fBSYSFS{\fR\fB\fIfilename\fR\fR\fB}\fR
-Match the sysfs attribute value. Up to five values can be specified. Trailing whitespace is ignored, if the specified match value does not contain trailing whitespace itself.
+Search the devpath upwards for a device with matching sysfs attribute values. Up to five
+\fBSYSFS\fR
+keys can be specified per rule. All attributes must match on the same device. Trailing whitespace in the attribute values is ignored, if the specified match value does not contain trailing whitespace itself.
+.TP
+\fBENV{\fR\fB\fIkey\fR\fR\fB}\fR
+Match against the value of an environment variable. Up to five
+\fBENV\fR
+keys can be specified per rule. This key can also be used to export a variable to the environment.
.TP
\fBPROGRAM\fR
Execute external program. The key is true, if the program returns without exit code zero. The whole event environment is available to the executed program. The program's output printed to stdout is available for the RESULT key.
.TP
\fBPROGRAM\fR
Execute external program. The key is true, if the program returns without exit code zero. The whole event environment is available to the executed program. The program's output printed to stdout is available for the RESULT key.
The permissions for the device node. Every specified value overwrites the compiled\-in default value.
.TP
\fBENV{\fR\fB\fIkey\fR\fR\fB}\fR
The permissions for the device node. Every specified value overwrites the compiled\-in default value.
.TP
\fBENV{\fR\fB\fIkey\fR\fR\fB}\fR
-Export the key to the environment. Depending on the specified operation, this key is also used as a match.
+Export a variable to the environment. This key can also be used to match against an environment variable.
.TP
\fBRUN\fR
Add a program to the list of programs to be executed for a specific device.
.TP
\fBRUN\fR
Add a program to the list of programs to be executed for a specific device.
Jumps to the next LABEL with a matching gname
.TP
\fBIMPORT{\fR\fB\fItype\fR\fR\fB}\fR
Jumps to the next LABEL with a matching gname
.TP
\fBIMPORT{\fR\fB\fItype\fR\fR\fB}\fR
-Import the printed result or the content of a file in environment key format into the event environment.
+Import the printed result or the value of a file in environment key format into the event environment.
\fBprogram\fR
will execute an external program and read its output.
\fBfile\fR
will inport a text file. If no option is given, udev will determine it from the executable bit of of the file permissions.
.TP
\fBWAIT_FOR_SYSFS\fR
\fBprogram\fR
will execute an external program and read its output.
\fBfile\fR
will inport a text file. If no option is given, udev will determine it from the executable bit of of the file permissions.
.TP
\fBWAIT_FOR_SYSFS\fR
-Wait for the specified sysfs file of the device to be created. May be used to fight agains timing issues wth the kernel.
+Wait for the specified sysfs file of the device to be created. Can be used to fight against kernel sysfs timing issues.
.TP
\fBOPTIONS\fR
\fBlast_rule\fR
.TP
\fBOPTIONS\fR
\fBlast_rule\fR
\fBGROUP\fR
fields support simple printf\-like string substitutions:
.TP
\fBGROUP\fR
fields support simple printf\-like string substitutions:
.TP
The kernel name for this device.
.TP
The kernel name for this device.
.TP
-\fB%b\fR, \fB$id\fR
-The kernel bus id for this device.
-.TP
-\fB%n\fR, \fB$number\fR
The kernel number for this device. For example, 'sda3' has kernel number of '3'
.TP
The kernel number for this device. For example, 'sda3' has kernel number of '3'
.TP
-\fB%p\fR, \fB$devpath\fR
+\fB$devpath\fR, \fB%p\fR
The devpath of the device.
.TP
The devpath of the device.
.TP
-\fB%s{\fR\fB\fIfile\fR\fR\fB}\fR, \fB$sysfs{\fR\fB\fIfile\fR\fR\fB}\fR
-The content of a sysfs attribute.
+\fB$id\fR, \fB%b\fR
+The name of the device matched while searching the devpath upwards for
+\fBBUS\fR,
+\fBID\fR \fBDRIVER\fR
+and
+\fBSYSFS\fR.
+.TP
+\fB$sysfs{\fR\fB\fIfile\fR\fR\fB}\fR, \fB%s{\fR\fB\fIfile\fR\fR\fB}\fR
+The value of a sysfs attribute found at the current or a parent device.
-\fB%E{\fR\fB\fIkey\fR\fR\fB}\fR, \fB$env{\fR\fB\fIkey\fR\fR\fB}\fR
+\fB$env{\fR\fB\fIkey\fR\fR\fB}\fR, \fB%E{\fR\fB\fIkey\fR\fR\fB}\fR
The value of an environment variable.
.TP
The value of an environment variable.
.TP
The kernel major number for the device.
.TP
The kernel major number for the device.
.TP
The kernel minor number for the device.
.TP
The kernel minor number for the device.
.TP
The string returned by the external program requested with PROGRAM. A single part of the string, separated by a space character may be selected by specifying the part number as an attribute:
\fB%c{N}\fR. If the number is followed by the '+' char this part plus all remaining parts of the result string are substituted:
\fB%c{N+}\fR
.TP
The string returned by the external program requested with PROGRAM. A single part of the string, separated by a space character may be selected by specifying the part number as an attribute:
\fB%c{N}\fR. If the number is followed by the '+' char this part plus all remaining parts of the result string are substituted:
\fB%c{N+}\fR
.TP
The node name of the parent device.
.TP
The node name of the parent device.
.TP
-\fB%N\fR, \fB$tempnode\fR
+\fB$tempnode\fR, \fB%N\fR
The name of a created temporary device node to provide access to the device from a external program before the real node is created.
.TP
\fB%%\fR
The name of a created temporary device node to provide access to the device from a external program before the real node is created.
.TP
\fB%%\fR
#include "udev_libc_wrapper.h"
#include "udev_version.h"
#include "udev_libc_wrapper.h"
#include "udev_version.h"
-#define COMMENT_CHARACTER '#'
-#define PATH_TO_NAME_CHAR '@'
-#define LINE_SIZE 512
-#define NAME_SIZE 128
-#define PATH_SIZE 256
-#define USER_SIZE 32
-#define SEQNUM_SIZE 32
-#define VALUE_SIZE 128
-
-#define DEFAULT_PARTITIONS_COUNT 15
-#define UDEV_ALARM_TIMEOUT 180
+#define COMMENT_CHARACTER '#'
+#define PATH_TO_NAME_CHAR '@'
+#define LINE_SIZE 512
+#define NAME_SIZE 128
+#define PATH_SIZE 256
+#define USER_SIZE 32
+#define SEQNUM_SIZE 32
+#define VALUE_SIZE 128
+
+#define DEFAULT_PARTITIONS_COUNT 15
+#define UDEV_ALARM_TIMEOUT 180
#define UDEV_MAX(a,b) ((a) > (b) ? (a) : (b))
/* pipes */
#define UDEV_MAX(a,b) ((a) > (b) ? (a) : (b))
/* pipes */
-#define READ_END 0
-#define WRITE_END 1
+#define READ_END 0
+#define WRITE_END 1
-#define DB_DIR ".udev/db"
+#define DB_DIR ".udev/db"
struct udev_rules;
struct sysfs_device {
struct udev_rules;
struct sysfs_device {
- struct list_head node; /* for device cache */
+ struct list_head node; /* for device cache */
- char subsystem[NAME_SIZE]; /* $class/$bus/"drivers" */
- char kernel_name[NAME_SIZE]; /* device instance name */
+ char subsystem[NAME_SIZE]; /* $class/$bus/"drivers" */
+ char kernel_name[NAME_SIZE]; /* device instance name */
char kernel_number[NAME_SIZE];
char kernel_number[NAME_SIZE];
- char driver[NAME_SIZE]; /* device driver name */
+ char driver[NAME_SIZE]; /* device driver name */
};
struct udevice {
/* device event */
};
struct udevice {
/* device event */
- struct sysfs_device *dev; /* points to dev_local by default */
+ struct sysfs_device *dev; /* points to dev_local by default */
struct sysfs_device dev_local;
struct sysfs_device dev_local;
+ struct sysfs_device *dev_parent; /* current parent device used for matching */
char action[NAME_SIZE];
/* node */
char action[NAME_SIZE];
/* node */
SUBST_DEVPATH,
SUBST_KERNEL_NUMBER,
SUBST_KERNEL_NAME,
SUBST_DEVPATH,
SUBST_KERNEL_NUMBER,
SUBST_KERNEL_NAME,
SUBST_MAJOR,
SUBST_MINOR,
SUBST_RESULT,
SUBST_MAJOR,
SUBST_MINOR,
SUBST_RESULT,
{ .name = "devpath", .fmt = 'p', .type = SUBST_DEVPATH },
{ .name = "number", .fmt = 'n', .type = SUBST_KERNEL_NUMBER },
{ .name = "kernel", .fmt = 'k', .type = SUBST_KERNEL_NAME },
{ .name = "devpath", .fmt = 'p', .type = SUBST_DEVPATH },
{ .name = "number", .fmt = 'n', .type = SUBST_KERNEL_NUMBER },
{ .name = "kernel", .fmt = 'k', .type = SUBST_KERNEL_NAME },
+ { .name = "id", .fmt = 'b', .type = SUBST_ID },
{ .name = "major", .fmt = 'M', .type = SUBST_MAJOR },
{ .name = "minor", .fmt = 'm', .type = SUBST_MINOR },
{ .name = "result", .fmt = 'c', .type = SUBST_RESULT },
{ .name = "major", .fmt = 'M', .type = SUBST_MAJOR },
{ .name = "minor", .fmt = 'm', .type = SUBST_MINOR },
{ .name = "result", .fmt = 'c', .type = SUBST_RESULT },
strlcat(string, udev->dev->kernel_number, maxsize);
dbg("substitute kernel number '%s'", udev->dev->kernel_number);
break;
strlcat(string, udev->dev->kernel_number, maxsize);
dbg("substitute kernel number '%s'", udev->dev->kernel_number);
break;
+ case SUBST_ID:
+ if (udev->dev_parent != NULL) {
+ strlcat(string, udev->dev_parent->kernel_name, maxsize);
+ dbg("substitute id '%s'", udev->dev_parent->kernel_name);
+ }
+ break;
case SUBST_MAJOR:
sprintf(temp2, "%d", major(udev->devt));
strlcat(string, temp2, maxsize);
case SUBST_MAJOR:
sprintf(temp2, "%d", major(udev->devt));
strlcat(string, temp2, maxsize);
/* match a single rule against a given device and possibly its parent devices */
static int match_rule(struct udevice *udev, struct udev_rule *rule)
{
/* match a single rule against a given device and possibly its parent devices */
static int match_rule(struct udevice *udev, struct udev_rule *rule)
{
- struct sysfs_device *dev_parent;
int i;
if (match_key("ACTION", rule, &rule->action, udev->action))
int i;
if (match_key("ACTION", rule, &rule->action, udev->action))
if (match_key("KERNEL", rule, &rule->kernel_name, udev->dev->kernel_name))
if (match_key("KERNEL", rule, &rule->kernel_name, udev->dev->kernel_name))
if (match_key("SUBSYSTEM", rule, &rule->subsystem, udev->dev->subsystem))
if (match_key("SUBSYSTEM", rule, &rule->subsystem, udev->dev->subsystem))
if (match_key("DEVPATH", rule, &rule->devpath, udev->dev->devpath))
if (match_key("DEVPATH", rule, &rule->devpath, udev->dev->devpath))
if (rule->modalias.operation != KEY_OP_UNSET) {
const char *value;
if (rule->modalias.operation != KEY_OP_UNSET) {
const char *value;
value = sysfs_attr_get_value(udev->dev->devpath, "modalias");
if (value == NULL) {
dbg("MODALIAS value not found");
value = sysfs_attr_get_value(udev->dev->devpath, "modalias");
if (value == NULL) {
dbg("MODALIAS value not found");
}
if (match_key("MODALIAS", rule, &rule->modalias, value))
}
if (match_key("MODALIAS", rule, &rule->modalias, value))
}
for (i = 0; i < rule->env.count; i++) {
}
for (i = 0; i < rule->env.count; i++) {
value = "";
}
if (match_key("ENV", rule, &pair->key, value))
value = "";
}
if (match_key("ENV", rule, &pair->key, value))
- /* walk up the chain of physical devices and find a match */
- dev_parent = udev->dev;
+ /* walk up the chain of parent devices and find a match */
+ udev->dev_parent = udev->dev;
while (1) {
/* check for matching driver */
if (rule->driver.operation != KEY_OP_UNSET) {
while (1) {
/* check for matching driver */
if (rule->driver.operation != KEY_OP_UNSET) {
- if (match_key("DRIVER", rule, &rule->driver, dev_parent->driver))
+ if (match_key("DRIVER", rule, &rule->driver, udev->dev_parent->driver))
- /* check for matching bus value */
+ /* check for matching subsystem/bus value */
if (rule->bus.operation != KEY_OP_UNSET) {
if (rule->bus.operation != KEY_OP_UNSET) {
- if (match_key("BUS", rule, &rule->bus, dev_parent->subsystem))
+ if (match_key("BUS", rule, &rule->bus, udev->dev_parent->subsystem))
- /* check for matching bus id */
+ /* check for matching bus id (device name) */
if (rule->id.operation != KEY_OP_UNSET) {
if (rule->id.operation != KEY_OP_UNSET) {
- if (match_key("ID", rule, &rule->id, dev_parent->kernel_name))
+ if (match_key("ID", rule, &rule->id, udev->dev_parent->kernel_name))
char val[VALUE_SIZE];
size_t len;
char val[VALUE_SIZE];
size_t len;
- value = sysfs_attr_get_value(dev_parent->devpath, key_name);
+ value = sysfs_attr_get_value(udev->dev_parent->devpath, key_name);
if (value == NULL)
goto try_parent;
strlcpy(val, value, sizeof(val));
if (value == NULL)
goto try_parent;
strlcpy(val, value, sizeof(val));
/* found matching device */
break;
try_parent:
/* found matching device */
break;
try_parent:
+ /* move to parent device */
dbg("try parent sysfs device");
dbg("try parent sysfs device");
- dev_parent = sysfs_device_get_parent(dev_parent);
- if (dev_parent == NULL)
- goto exit;
- dbg("looking at dev_parent->devpath='%s'", dev_parent->devpath);
- dbg("looking at dev_parent->bus_kernel_name='%s'", dev_parent->kernel_name);
+ udev->dev_parent = sysfs_device_get_parent(udev->dev_parent);
+ if (udev->dev_parent == NULL)
+ goto nomatch;
+ dbg("looking at dev_parent->devpath='%s'", udev->dev_parent->devpath);
+ dbg("looking at dev_parent->bus_kernel_name='%s'", udev->dev_parent->kernel_name);
}
/* execute external program */
}
/* execute external program */
dbg("PROGRAM is false");
udev->program_result[0] = '\0';
if (rule->program.operation != KEY_OP_NOMATCH)
dbg("PROGRAM is false");
udev->program_result[0] = '\0';
if (rule->program.operation != KEY_OP_NOMATCH)
strlcpy(udev->program_result, result, sizeof(udev->program_result));
dbg("PROGRAM returned successful");
if (rule->program.operation == KEY_OP_NOMATCH)
strlcpy(udev->program_result, result, sizeof(udev->program_result));
dbg("PROGRAM returned successful");
if (rule->program.operation == KEY_OP_NOMATCH)
}
dbg("PROGRAM key is true");
}
/* check for matching result of external program */
if (match_key("RESULT", rule, &rule->result, udev->program_result))
}
dbg("PROGRAM key is true");
}
/* check for matching result of external program */
if (match_key("RESULT", rule, &rule->result, udev->program_result))
/* import variables returned from program or or file into environment */
if (rule->import.operation != KEY_OP_UNSET) {
/* import variables returned from program or or file into environment */
if (rule->import.operation != KEY_OP_UNSET) {
if (rc != 0) {
dbg("IMPORT failed");
if (rule->import.operation != KEY_OP_NOMATCH)
if (rc != 0) {
dbg("IMPORT failed");
if (rule->import.operation != KEY_OP_NOMATCH)
} else
dbg("IMPORT '%s' imported", key_val(rule, &rule->import));
dbg("IMPORT key is true");
} else
dbg("IMPORT '%s' imported", key_val(rule, &rule->import));
dbg("IMPORT key is true");