199ca880aSopenharmony_ci# do not edit this file, it will be overwritten on update 299ca880aSopenharmony_ci 399ca880aSopenharmony_ciSUBSYSTEM!="sound", GOTO="sound_end" 499ca880aSopenharmony_ci 599ca880aSopenharmony_ciACTION=="add|change", KERNEL=="controlC*", ATTR{../uevent}="change" 699ca880aSopenharmony_ciACTION!="change", GOTO="sound_end" 799ca880aSopenharmony_ci 899ca880aSopenharmony_ci# Ok, we probably need a little explanation here for what the two lines above 999ca880aSopenharmony_ci# are good for. 1099ca880aSopenharmony_ci# 1199ca880aSopenharmony_ci# The story goes like this: when ALSA registers a new sound card it emits a 1299ca880aSopenharmony_ci# series of 'add' events to userspace, for the main card device and for all the 1399ca880aSopenharmony_ci# child device nodes that belong to it. udev relays those to applications, 1499ca880aSopenharmony_ci# however only maintains the order between father and child, but not between 1599ca880aSopenharmony_ci# the siblings. The control device node creation can be used as synchronization 1699ca880aSopenharmony_ci# point. All other devices that belong to a card are created in the kernel 1799ca880aSopenharmony_ci# before it. However unfortunately due to the fact that siblings are forwarded 1899ca880aSopenharmony_ci# out of order by udev this fact is lost to applications. 1999ca880aSopenharmony_ci# 2099ca880aSopenharmony_ci# OTOH before an application can open a device it needs to make sure that all 2199ca880aSopenharmony_ci# its device nodes are completely created and set up. 2299ca880aSopenharmony_ci# 2399ca880aSopenharmony_ci# As a workaround for this issue we have added the udev rule above which will 2499ca880aSopenharmony_ci# generate a 'change' event on the main card device from the 'add' event of the 2599ca880aSopenharmony_ci# card's control device. Due to the ordering semantics of udev this event will 2699ca880aSopenharmony_ci# only be relayed after all child devices have finished processing properly. 2799ca880aSopenharmony_ci# When an application needs to listen for appearing devices it can hence look 2899ca880aSopenharmony_ci# for 'change' events only, and ignore the actual 'add' events. 2999ca880aSopenharmony_ci# 3099ca880aSopenharmony_ci# When the application is initialized at the same time as a device is plugged 3199ca880aSopenharmony_ci# in it may need to figure out if the 'change' event has already been triggered 3299ca880aSopenharmony_ci# or not for a card. To find that out we store the flag environment variable 3399ca880aSopenharmony_ci# SOUND_INITIALIZED on the device which simply tells us if the card 'change' 3499ca880aSopenharmony_ci# event has already been processed. 3599ca880aSopenharmony_ci 3699ca880aSopenharmony_ciKERNEL!="card*", GOTO="sound_end" 3799ca880aSopenharmony_ci 3899ca880aSopenharmony_ciENV{SOUND_INITIALIZED}="1" 3999ca880aSopenharmony_ci 4099ca880aSopenharmony_ciIMPORT{builtin}="hwdb" 4199ca880aSopenharmony_ciSUBSYSTEMS=="usb", IMPORT{builtin}="usb_id" 4299ca880aSopenharmony_ciSUBSYSTEMS=="usb", GOTO="skip_pci" 4399ca880aSopenharmony_ci 4499ca880aSopenharmony_ciSUBSYSTEMS=="firewire", ATTRS{guid}=="?*", \ 4599ca880aSopenharmony_ci ENV{ID_BUS}="firewire", ENV{ID_SERIAL}="$attr{guid}", ENV{ID_SERIAL_SHORT}="$attr{guid}", \ 4699ca880aSopenharmony_ci ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{model}", \ 4799ca880aSopenharmony_ci ENV{ID_VENDOR}="$attr{vendor_name}", ENV{ID_MODEL}="$attr{model_name}" 4899ca880aSopenharmony_ciSUBSYSTEMS=="firewire", GOTO="skip_pci" 4999ca880aSopenharmony_ci 5099ca880aSopenharmony_ciSUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}" 5199ca880aSopenharmony_ciSUBSYSTEMS=="pci", GOTO="skip_pci" 5299ca880aSopenharmony_ci 5399ca880aSopenharmony_ci# If we reach here, the device nor any of its parents are USB/PCI/firewire bus devices. 5499ca880aSopenharmony_ci# If we now find a parent that is a platform device, assume that we're working with 5599ca880aSopenharmony_ci# an internal sound card. 5699ca880aSopenharmony_ciSUBSYSTEMS=="platform", ENV{SOUND_FORM_FACTOR}="internal", GOTO="sound_end" 5799ca880aSopenharmony_ci 5899ca880aSopenharmony_ciLABEL="skip_pci" 5999ca880aSopenharmony_ci 6099ca880aSopenharmony_ci# Define ID_ID if ID_BUS and ID_SERIAL are set. This will work for both 6199ca880aSopenharmony_ci# USB and firewire. 6299ca880aSopenharmony_ciENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="?*", ENV{ID_ID}="$env{ID_BUS}-$env{ID_SERIAL}-$env{ID_USB_INTERFACE_NUM}" 6399ca880aSopenharmony_ciENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="", ENV{ID_ID}="$env{ID_BUS}-$env{ID_SERIAL}" 6499ca880aSopenharmony_ci 6599ca880aSopenharmony_ciIMPORT{builtin}="path_id" 6699ca880aSopenharmony_ci 6799ca880aSopenharmony_ci# The values used here for $SOUND_FORM_FACTOR and $SOUND_CLASS should be kept 6899ca880aSopenharmony_ci# in sync with those defined for PulseAudio's src/pulse/proplist.h 6999ca880aSopenharmony_ci# PA_PROP_DEVICE_FORM_FACTOR, PA_PROP_DEVICE_CLASS properties. 7099ca880aSopenharmony_ci 7199ca880aSopenharmony_ci# If the first PCM device of this card has the pcm class 'modem', then the card is a modem 7299ca880aSopenharmony_ciATTR{pcmC%nD0p/pcm_class}=="modem", ENV{SOUND_CLASS}="modem", GOTO="sound_end" 7399ca880aSopenharmony_ci 7499ca880aSopenharmony_ci# Identify cards on the internal PCI bus as internal 7599ca880aSopenharmony_ciSUBSYSTEMS=="pci", DEVPATH=="*/0000:00:??.?/sound/*", ENV{SOUND_FORM_FACTOR}="internal", GOTO="sound_end" 7699ca880aSopenharmony_ci 7799ca880aSopenharmony_ci# Devices that also support Image/Video interfaces are most likely webcams 7899ca880aSopenharmony_ciSUBSYSTEMS=="usb", ENV{ID_USB_INTERFACES}=="*:0e????:*", ENV{SOUND_FORM_FACTOR}="webcam", GOTO="sound_end" 7999ca880aSopenharmony_ci 8099ca880aSopenharmony_ci# Matching on the model strings is a bit ugly, I admit 8199ca880aSopenharmony_ciENV{ID_MODEL}=="*[Ss]peaker*", ENV{SOUND_FORM_FACTOR}="speaker", GOTO="sound_end" 8299ca880aSopenharmony_ciENV{ID_MODEL_FROM_DATABASE}=="*[Ss]peaker*", ENV{SOUND_FORM_FACTOR}="speaker", GOTO="sound_end" 8399ca880aSopenharmony_ci 8499ca880aSopenharmony_ciENV{ID_MODEL}=="*[Hh]eadphone*", ENV{SOUND_FORM_FACTOR}="headphone", GOTO="sound_end" 8599ca880aSopenharmony_ciENV{ID_MODEL_FROM_DATABASE}=="*[Hh]eadphone*", ENV{SOUND_FORM_FACTOR}="headphone", GOTO="sound_end" 8699ca880aSopenharmony_ci 8799ca880aSopenharmony_ciENV{ID_MODEL}=="*[Hh]eadset*", ENV{SOUND_FORM_FACTOR}="headset", GOTO="sound_end" 8899ca880aSopenharmony_ciENV{ID_MODEL_FROM_DATABASE}=="*[Hh]eadset*", ENV{SOUND_FORM_FACTOR}="headset", GOTO="sound_end" 8999ca880aSopenharmony_ci 9099ca880aSopenharmony_ciENV{ID_MODEL}=="*[Hh]andset*", ENV{SOUND_FORM_FACTOR}="handset", GOTO="sound_end" 9199ca880aSopenharmony_ciENV{ID_MODEL_FROM_DATABASE}=="*[Hh]andset*", ENV{SOUND_FORM_FACTOR}="handset", GOTO="sound_end" 9299ca880aSopenharmony_ci 9399ca880aSopenharmony_ciENV{ID_MODEL}=="*[Mm]icrophone*", ENV{SOUND_FORM_FACTOR}="microphone", GOTO="sound_end" 9499ca880aSopenharmony_ciENV{ID_MODEL_FROM_DATABASE}=="*[Mm]icrophone*", ENV{SOUND_FORM_FACTOR}="microphone", GOTO="sound_end" 9599ca880aSopenharmony_ci 9699ca880aSopenharmony_ciLABEL="sound_end" 97