1# do not edit this file, it will be overwritten on update 2 3SUBSYSTEM!="sound", GOTO="sound_end" 4 5ACTION=="add|change", KERNEL=="controlC*", ATTR{../uevent}="change" 6ACTION!="change", GOTO="sound_end" 7 8# Ok, we probably need a little explanation here for what the two lines above 9# are good for. 10# 11# The story goes like this: when ALSA registers a new sound card it emits a 12# series of 'add' events to userspace, for the main card device and for all the 13# child device nodes that belong to it. udev relays those to applications, 14# however only maintains the order between father and child, but not between 15# the siblings. The control device node creation can be used as synchronization 16# point. All other devices that belong to a card are created in the kernel 17# before it. However unfortunately due to the fact that siblings are forwarded 18# out of order by udev this fact is lost to applications. 19# 20# OTOH before an application can open a device it needs to make sure that all 21# its device nodes are completely created and set up. 22# 23# As a workaround for this issue we have added the udev rule above which will 24# generate a 'change' event on the main card device from the 'add' event of the 25# card's control device. Due to the ordering semantics of udev this event will 26# only be relayed after all child devices have finished processing properly. 27# When an application needs to listen for appearing devices it can hence look 28# for 'change' events only, and ignore the actual 'add' events. 29# 30# When the application is initialized at the same time as a device is plugged 31# in it may need to figure out if the 'change' event has already been triggered 32# or not for a card. To find that out we store the flag environment variable 33# SOUND_INITIALIZED on the device which simply tells us if the card 'change' 34# event has already been processed. 35 36KERNEL!="card*", GOTO="sound_end" 37 38ENV{SOUND_INITIALIZED}="1" 39 40IMPORT{builtin}="hwdb" 41SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id" 42SUBSYSTEMS=="usb", GOTO="skip_pci" 43 44SUBSYSTEMS=="firewire", ATTRS{guid}=="?*", \ 45 ENV{ID_BUS}="firewire", ENV{ID_SERIAL}="$attr{guid}", ENV{ID_SERIAL_SHORT}="$attr{guid}", \ 46 ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{model}", \ 47 ENV{ID_VENDOR}="$attr{vendor_name}", ENV{ID_MODEL}="$attr{model_name}" 48SUBSYSTEMS=="firewire", GOTO="skip_pci" 49 50SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}" 51SUBSYSTEMS=="pci", GOTO="skip_pci" 52 53# If we reach here, the device nor any of its parents are USB/PCI/firewire bus devices. 54# If we now find a parent that is a platform device, assume that we're working with 55# an internal sound card. 56SUBSYSTEMS=="platform", ENV{SOUND_FORM_FACTOR}="internal", GOTO="sound_end" 57 58LABEL="skip_pci" 59 60# Define ID_ID if ID_BUS and ID_SERIAL are set. This will work for both 61# USB and firewire. 62ENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="?*", ENV{ID_ID}="$env{ID_BUS}-$env{ID_SERIAL}-$env{ID_USB_INTERFACE_NUM}" 63ENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="", ENV{ID_ID}="$env{ID_BUS}-$env{ID_SERIAL}" 64 65IMPORT{builtin}="path_id" 66 67# The values used here for $SOUND_FORM_FACTOR and $SOUND_CLASS should be kept 68# in sync with those defined for PulseAudio's src/pulse/proplist.h 69# PA_PROP_DEVICE_FORM_FACTOR, PA_PROP_DEVICE_CLASS properties. 70 71# If the first PCM device of this card has the pcm class 'modem', then the card is a modem 72ATTR{pcmC%nD0p/pcm_class}=="modem", ENV{SOUND_CLASS}="modem", GOTO="sound_end" 73 74# Identify cards on the internal PCI bus as internal 75SUBSYSTEMS=="pci", DEVPATH=="*/0000:00:??.?/sound/*", ENV{SOUND_FORM_FACTOR}="internal", GOTO="sound_end" 76 77# Devices that also support Image/Video interfaces are most likely webcams 78SUBSYSTEMS=="usb", ENV{ID_USB_INTERFACES}=="*:0e????:*", ENV{SOUND_FORM_FACTOR}="webcam", GOTO="sound_end" 79 80# Matching on the model strings is a bit ugly, I admit 81ENV{ID_MODEL}=="*[Ss]peaker*", ENV{SOUND_FORM_FACTOR}="speaker", GOTO="sound_end" 82ENV{ID_MODEL_FROM_DATABASE}=="*[Ss]peaker*", ENV{SOUND_FORM_FACTOR}="speaker", GOTO="sound_end" 83 84ENV{ID_MODEL}=="*[Hh]eadphone*", ENV{SOUND_FORM_FACTOR}="headphone", GOTO="sound_end" 85ENV{ID_MODEL_FROM_DATABASE}=="*[Hh]eadphone*", ENV{SOUND_FORM_FACTOR}="headphone", GOTO="sound_end" 86 87ENV{ID_MODEL}=="*[Hh]eadset*", ENV{SOUND_FORM_FACTOR}="headset", GOTO="sound_end" 88ENV{ID_MODEL_FROM_DATABASE}=="*[Hh]eadset*", ENV{SOUND_FORM_FACTOR}="headset", GOTO="sound_end" 89 90ENV{ID_MODEL}=="*[Hh]andset*", ENV{SOUND_FORM_FACTOR}="handset", GOTO="sound_end" 91ENV{ID_MODEL_FROM_DATABASE}=="*[Hh]andset*", ENV{SOUND_FORM_FACTOR}="handset", GOTO="sound_end" 92 93ENV{ID_MODEL}=="*[Mm]icrophone*", ENV{SOUND_FORM_FACTOR}="microphone", GOTO="sound_end" 94ENV{ID_MODEL_FROM_DATABASE}=="*[Mm]icrophone*", ENV{SOUND_FORM_FACTOR}="microphone", GOTO="sound_end" 95 96LABEL="sound_end" 97