78-sound-card.rules 4.7 KB

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