]>
Commit | Line | Data |
---|---|---|
dc544062 LP |
1 | # do not edit this file, it will be overwritten on update |
2 | ||
3 | SUBSYSTEM!="sound", GOTO="sound_end" | |
4 | ||
5 | ACTION=="add|change", KERNEL=="controlC*", ATTR{../uevent}="change" | |
6 | ACTION!="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 | ||
36 | KERNEL!="card*", GOTO="sound_end" | |
37 | ||
38 | ENV{SOUND_INITIALIZED}="1" | |
39 | ||
796b06c2 | 40 | IMPORT{builtin}="hwdb" |
d7867b31 | 41 | SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id" |
dc544062 LP |
42 | SUBSYSTEMS=="usb", GOTO="skip_pci" |
43 | ||
5c0b72de AG |
44 | SUBSYSTEMS=="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}" | |
427c9ba2 KS |
48 | SUBSYSTEMS=="firewire", GOTO="skip_pci" |
49 | ||
dc544062 | 50 | SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}" |
d84071d5 DD |
51 | SUBSYSTEMS=="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. | |
56 | SUBSYSTEMS=="platform", ENV{SOUND_FORM_FACTOR}="internal", GOTO="sound_end" | |
57 | ||
dc544062 LP |
58 | LABEL="skip_pci" |
59 | ||
5c0b72de AG |
60 | # Define ID_ID if ID_BUS and ID_SERIAL are set. This will work for both |
61 | # USB and firewire. | |
0414af1d AG |
62 | ENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="?*", ENV{ID_ID}="$env{ID_BUS}-$env{ID_SERIAL}-$env{ID_USB_INTERFACE_NUM}" |
63 | ENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="", ENV{ID_ID}="$env{ID_BUS}-$env{ID_SERIAL}" | |
dc544062 | 64 | |
d7867b31 | 65 | IMPORT{builtin}="path_id" |
dc544062 LP |
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 | |
72 | ATTR{pcmC%nD0p/pcm_class}=="modem", ENV{SOUND_CLASS}="modem", GOTO="sound_end" | |
73 | ||
74 | # Identify cards on the internal PCI bus as internal | |
75 | SUBSYSTEMS=="pci", DEVPATH=="*/0000:00:??.?/sound/*", ENV{SOUND_FORM_FACTOR}="internal", GOTO="sound_end" | |
76 | ||
dc544062 LP |
77 | # Devices that also support Image/Video interfaces are most likely webcams |
78 | SUBSYSTEMS=="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 | |
81 | ENV{ID_MODEL}=="*[Ss]peaker*", ENV{SOUND_FORM_FACTOR}="speaker", GOTO="sound_end" | |
82 | ENV{ID_MODEL_FROM_DATABASE}=="*[Ss]peaker*", ENV{SOUND_FORM_FACTOR}="speaker", GOTO="sound_end" | |
83 | ||
84 | ENV{ID_MODEL}=="*[Hh]eadphone*", ENV{SOUND_FORM_FACTOR}="headphone", GOTO="sound_end" | |
85 | ENV{ID_MODEL_FROM_DATABASE}=="*[Hh]eadphone*", ENV{SOUND_FORM_FACTOR}="headphone", GOTO="sound_end" | |
86 | ||
87 | ENV{ID_MODEL}=="*[Hh]eadset*", ENV{SOUND_FORM_FACTOR}="headset", GOTO="sound_end" | |
88 | ENV{ID_MODEL_FROM_DATABASE}=="*[Hh]eadset*", ENV{SOUND_FORM_FACTOR}="headset", GOTO="sound_end" | |
89 | ||
90 | ENV{ID_MODEL}=="*[Hh]andset*", ENV{SOUND_FORM_FACTOR}="handset", GOTO="sound_end" | |
91 | ENV{ID_MODEL_FROM_DATABASE}=="*[Hh]andset*", ENV{SOUND_FORM_FACTOR}="handset", GOTO="sound_end" | |
92 | ||
93 | ENV{ID_MODEL}=="*[Mm]icrophone*", ENV{SOUND_FORM_FACTOR}="microphone", GOTO="sound_end" | |
94 | ENV{ID_MODEL_FROM_DATABASE}=="*[Mm]icrophone*", ENV{SOUND_FORM_FACTOR}="microphone", GOTO="sound_end" | |
95 | ||
96 | LABEL="sound_end" |