From c1a4ff02a5f0cc80982d5bbbb96652c2690fa8aa Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 6 Jun 2009 23:28:16 +0200 Subject: sound: generate change event on card device from add event on controlC device --- rules.d/78-sound-card.rules | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) 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}" -- cgit