chiark / gitweb /
fix BUS, ID, $id usage
authorKay Sievers <kay.sievers@suse.de>
Mon, 16 Jan 2006 05:12:49 +0000 (06:12 +0100)
committerKay Sievers <kay.sievers@suse.de>
Mon, 16 Jan 2006 05:12:49 +0000 (06:12 +0100)
Signed-off-by: Kay Sievers <kay.sievers@suse.de>
TODO
docs/udev.xml
test/udev-test.pl
udev.8
udev.h
udev_rules.c

diff --git a/TODO b/TODO
index 19aae9e..bdd2e1e 100644 (file)
--- a/TODO
+++ b/TODO
@@ -4,12 +4,6 @@ These things need to be done, or would be nice to have:
     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:
 
index 7f6a30d..ab8174e 100644 (file)
             <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>
-                <para>Match the kernel device name</para>
+                <para>Match the name of the device.</para>
               </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>
-                <para>Match the kernel subsystem name</para>
+                <para>Match the subsystem of the device.</para>
               </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>
-                <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>
-                <para>Match the device number on the bus.</para>
+                <para>Search the devpath upwards for a matching device name.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
-              <term><option>ENV{<replaceable>key</replaceable>}</option></term>
+              <term><option>SYSFS{<replaceable>filename</replaceable>}</option></term>
               <listitem>
-                <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>
-              <term><option>SYSFS{<replaceable>filename</replaceable>}</option></term>
+              <term><option>ENV{<replaceable>key</replaceable>}</option></term>
               <listitem>
-                <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>
 
             <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>
 
             <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
             <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>
 
           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>
-              <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>
             </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>
-              <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>
               <listitem>
-                <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>
-              <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>
-              <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>
-              <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>
-              <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
             </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>
-              <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>
-              <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>
index 7ce9200..555d36e 100755 (executable)
@@ -231,7 +231,7 @@ KERNEL=="ttyUSB0", NAME="sub/direct/ory/visor"
 EOF
        },
        {
-               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" ,
@@ -243,18 +243,18 @@ EOF
                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" ,
                rules           => <<EOF
-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",
-               exp_name        => "M8-m3-n3-bsd-sIBM" ,
+               exp_name        => "M8-m3-n3-b0:0-sIBM" ,
                rules           => <<EOF
-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}"
 EOF
        },
        {
@@ -322,9 +322,9 @@ EOF
                desc            => "program result substitution",
                subsys          => "block",
                devpath         => "/block/sda/sda3",
-               exp_name        => "test-3" ,
+               exp_name        => "test-0:0:0:0" ,
                rules           => <<EOF
-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"
 EOF
        },
        {
@@ -385,27 +385,27 @@ EOF
                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",
                rules           => <<EOF
-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",
-               exp_name        => "Major:8-minor:3-kernelnumber:3-name:sda3" ,
+               exp_name        => "Major:8-minor:3-kernelnumber:3-id:0:0:0:0",
                rules           => <<EOF
-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",
-               exp_name        => "83sda33" ,
+               exp_name        => "830:0:0:03" ,
                rules           => <<EOF
-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"
 EOF
        },
        {
@@ -421,33 +421,23 @@ EOF
                desc            => "test substitution by variable name 5",
                subsys          => "block",
                devpath         => "/block/sda/sda3",
-               exp_name        => "833sda3" ,
+               exp_name        => "8330:0:0:0" ,
                rules           => <<EOF
-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"
 EOF
        },
        {
-               desc            => "invalid program for device with no bus",
+               desc            => "non matching BUS for device with no parent",
                subsys          => "tty",
                devpath         => "/class/tty/console",
-               exp_name        => "TTY" ,
+               exp_name        => "TTY",
                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" ,
@@ -457,7 +447,7 @@ KERNEL=="console", NAME="TTY"
 EOF
        },
        {
-               desc            => "valid label for device with no bus",
+               desc            => "SYSFS match",
                subsys          => "tty",
                devpath         => "/class/tty/console",
                exp_name        => "foo" ,
@@ -470,11 +460,11 @@ EOF
                desc            => "program and bus type match",
                subsys          => "block",
                devpath         => "/block/sda",
-               exp_name        => "scsi-sda" ,
+               exp_name        => "scsi-0:0:0:0" ,
                rules           => <<EOF
-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"
 EOF
        },
        {
@@ -797,7 +787,7 @@ 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"
 EOF
        },
        {
@@ -918,13 +908,13 @@ KERNEL=="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK+="major-%M:%m"
 EOF
        },
        {
-               desc            => "symlink %k substitution",
+               desc            => "symlink %b substitution",
                subsys          => "block",
                devpath         => "/block/sda",
-               exp_name        => "symlink-sda",
+               exp_name        => "symlink-0:0:0:0",
                exp_target      => "node",
                rules           => <<EOF
-BUS=="scsi", KERNEL=="sda", NAME="node", SYMLINK+="symlink-%k"
+BUS=="scsi", KERNEL=="sda", NAME="node", SYMLINK+="symlink-%b"
 EOF
        },
        {
@@ -1564,13 +1554,6 @@ sub udev {
 
        $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;
diff --git a/udev.8 b/udev.8
index 6d2f5e6..8eb63c2 100644 (file)
--- a/udev.8
+++ b/udev.8
@@ -70,31 +70,35 @@ Assign a value to a key finally; disallow any later changes, which may be used t
 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.
 .TP
 \fBKERNEL\fR
-Match the kernel device name
+Match the name of the device.
 .TP
 \fBDEVPATH\fR
-Match the kernel devpath.
+Match the devpath of the device.
 .TP
 \fBSUBSYSTEM\fR
-Match the kernel subsystem name
+Match the subsystem of the device.
 .TP
 \fBBUS\fR
-Match the type of bus the device is connected to.
+Search the devpath upwards for a matching device subsystem name.
 .TP
 \fBDRIVER\fR
-Match the kernel driver name.
+Search the devpath upwards for a matching device driver name.
 .TP
 \fBID\fR
-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
-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.
@@ -125,7 +129,7 @@ The name of a symlink targeting the node. Every matching rule can add this value
 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.
@@ -137,14 +141,14 @@ Named label where a GOTO can jump to.
 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
-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 
@@ -165,42 +169,46 @@ and
 \fBGROUP\fR 
 fields support simple printf\-like string substitutions:
 .TP
-\fB%k\fR, \fB$kernel\fR
+\fB$kernel\fR, \fB%k\fR
 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
+\fB$number\fR, \fB%n\fR
 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
-\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.
 .TP
-\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
-\fB%m\fR, \fB$major\fR
+\fB$major\fR, \fB%M\fR
 The kernel major number for the device.
 .TP
-\fB%M\fR \fB$minor\fR
+\fB$minor\fR \fB%m\fR
 The kernel minor number for the device.
 .TP
-\fB%c\fR, \fB$result\fR
+\fB$result\fR, \fB%c\fR
 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
-\fB%P\fR, \fB$parent\fR
+\fB$parent\fR, \fB%P\fR
 The node name of the parent device.
 .TP
-\fB%r\fR, \fB$root\fR
+\fB$root\fR, \fB%r\fR
 The udev_root value.
 .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
diff --git a/udev.h b/udev.h
index 6dc0c9e..5d54b54 100644 (file)
--- a/udev.h
+++ b/udev.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 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 list_head node;          /* for device cache */
+       struct list_head node;                  /* for device cache */
        char devpath[PATH_SIZE];
-       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 driver[NAME_SIZE];         /* device driver name */
+       char driver[NAME_SIZE];                 /* device driver name */
 };
 
 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_parent;        /* current parent device used for matching */
        char action[NAME_SIZE];
 
        /* node */
index fc1f3c9..e9d8d75 100644 (file)
@@ -376,6 +376,7 @@ static void apply_format(struct udevice *udev, char *string, size_t maxsize)
                SUBST_DEVPATH,
                SUBST_KERNEL_NUMBER,
                SUBST_KERNEL_NAME,
+               SUBST_ID,
                SUBST_MAJOR,
                SUBST_MINOR,
                SUBST_RESULT,
@@ -395,6 +396,7 @@ static void apply_format(struct udevice *udev, char *string, size_t maxsize)
                { .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 },
@@ -477,6 +479,12 @@ found:
                        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);
@@ -681,20 +689,19 @@ static int match_key(const char *key_name, struct udev_rule *rule, struct key *k
 /* 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))
-               goto exit;
+               goto nomatch;
 
        if (match_key("KERNEL", rule, &rule->kernel_name, udev->dev->kernel_name))
-               goto exit;
+               goto nomatch;
 
        if (match_key("SUBSYSTEM", rule, &rule->subsystem, udev->dev->subsystem))
-               goto exit;
+               goto nomatch;
 
        if (match_key("DEVPATH", rule, &rule->devpath, udev->dev->devpath))
-               goto exit;
+               goto nomatch;
 
        if (rule->modalias.operation != KEY_OP_UNSET) {
                const char *value;
@@ -702,10 +709,10 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule)
                value = sysfs_attr_get_value(udev->dev->devpath, "modalias");
                if (value == NULL) {
                        dbg("MODALIAS value not found");
-                       goto exit;
+                       goto nomatch;
                }
                if (match_key("MODALIAS", rule, &rule->modalias, value))
-                       goto exit;
+                       goto nomatch;
        }
 
        for (i = 0; i < rule->env.count; i++) {
@@ -721,7 +728,7 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule)
                                value = "";
                        }
                        if (match_key("ENV", rule, &pair->key, value))
-                               goto exit;
+                               goto nomatch;
                }
        }
 
@@ -741,24 +748,24 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule)
                return -1;
        }
 
-       /* 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) {
-                       if (match_key("DRIVER", rule, &rule->driver, dev_parent->driver))
+                       if (match_key("DRIVER", rule, &rule->driver, udev->dev_parent->driver))
                                goto try_parent;
                }
 
-               /* check for matching bus value */
+               /* check for matching subsystem/bus value */
                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))
                                goto try_parent;
                }
 
-               /* check for matching bus id */
+               /* check for matching bus id (device name) */
                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))
                                goto try_parent;
                }
 
@@ -773,7 +780,7 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule)
                                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));
@@ -796,12 +803,13 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule)
                /* found matching device  */
                break;
 try_parent:
+               /* move to parent 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 */
@@ -815,7 +823,7 @@ try_parent:
                        dbg("PROGRAM is false");
                        udev->program_result[0] = '\0';
                        if (rule->program.operation != KEY_OP_NOMATCH)
-                               goto exit;
+                               goto nomatch;
                } else {
                        int count;
 
@@ -828,14 +836,14 @@ try_parent:
                        strlcpy(udev->program_result, result, sizeof(udev->program_result));
                        dbg("PROGRAM returned successful");
                        if (rule->program.operation == KEY_OP_NOMATCH)
-                               goto exit;
+                               goto nomatch;
                }
                dbg("PROGRAM key is true");
        }
 
        /* check for matching result of external program */
        if (match_key("RESULT", rule, &rule->result, udev->program_result))
-               goto exit;
+               goto nomatch;
 
        /* import variables returned from program or or file into environment */
        if (rule->import.operation != KEY_OP_UNSET) {
@@ -857,7 +865,7 @@ try_parent:
                if (rc != 0) {
                        dbg("IMPORT failed");
                        if (rule->import.operation != KEY_OP_NOMATCH)
-                               goto exit;
+                               goto nomatch;
                } else
                        dbg("IMPORT '%s' imported", key_val(rule, &rule->import));
                dbg("IMPORT key is true");
@@ -879,7 +887,7 @@ try_parent:
 
        return 0;
 
-exit:
+nomatch:
        return -1;
 }