summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2009-06-06 23:28:16 +0200
committerLennart Poettering <lennart@poettering.net>2009-06-06 23:28:16 +0200
commitc1a4ff02a5f0cc80982d5bbbb96652c2690fa8aa (patch)
tree3ba55eb249e30a906785efe7e08c474910fcca6d
parenta927829d967a80ca63f451a839a8b1df65964e5d (diff)
sound: generate change event on card<N> device from add event on controlC<N> device
-rw-r--r--rules.d/78-sound-card.rules35
1 files changed, 34 insertions, 1 deletions
diff --git a/rules.d/78-sound-card.rules b/rules.d/78-sound-card.rules
index c3afbe2..679e7a3 100644
--- a/rules.d/78-sound-card.rules
+++ b/rules.d/78-sound-card.rules
@@ -1,9 +1,42 @@
# do not edit this file, it will be overwritten on update
-ACTION!="add|change", GOTO="sound_end"
SUBSYSTEM!="sound", GOTO="sound_end"
+
+ACTION=="add|change", KERNEL=="controlC*", ATTR{../uevent}="change"
+ACTION!="change", GOTO="sound_end"
+
+# Ok, we probably need a little explanation here for what the two lines above
+# are good for.
+#
+# The story goes like this: when ALSA registers a new sound card it emits a
+# series of 'add' events to userspace, for the main card device and for all the
+# child device nodes that belong to it. udev relays those to applications,
+# however only maintains the order between father and child, but not between
+# the siblings. The control device node creation can be used as synchronization
+# point. All other devices that belong to a card are created in the kernel
+# before it. However unfortunately due to the fact that siblings are forwarded
+# out of order by udev this fact is lost to applications.
+#
+# OTOH before an application can open a device it needs to make sure that all
+# its device nodes are completely created and set up.
+#
+# As a workaround for this issue we have added the udev rule above which will
+# generate a 'change' event on the main card device from the 'add' event of the
+# card's control device. Due to the ordering semantics of udev this event will
+# only be relayed after all child devices have finished processing properly.
+# When an application needs to listen for appearing devices it can hence look
+# for 'change' events only, and ignore the actual 'add' events.
+#
+# When the application is initialized at the same time as a device is plugged
+# in it may need to figure out if the 'change' event has already been triggered
+# or not for a card. To find that out we store the flag environment variable
+# SOUND_INITIALIZED on the device which simply tells us if the card 'change'
+# event has already been processed.
+
KERNEL!="card*", GOTO="sound_end"
+ENV{SOUND_INITIALIZED}="1"
+
SUBSYSTEMS=="usb", ENV{ID_MODEL}=="", IMPORT{program}="usb_id --export %p"
SUBSYSTEMS=="usb", ENV{ID_MODEL_FROM_DATABASE}=="", IMPORT{program}="usb-db %p"
SUBSYSTEMS=="usb", ATTRS{idVendor}!="", ATTRS{idProduct}!="", ENV{ID_VENDOR_ID}="$attr{idVendor}", ENV{ID_MODEL_ID}="$attr{idProduct}"