文章目录
  1. 1. USB Audio Class (UAC) 分析

USB Audio Class (UAC) 分析

一个UAC设备插入到Ubuntu 14.04电脑上dmesg中打印的信息如下:

[ 2367.490491] usb 3-3.2: new full-speed USB device number 9 using xhci_hcd
[ 2367.580010] usb 3-3.2: New USB device found, idVendor=0d8c, idProduct=0132
[ 2367.580018] usb 3-3.2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 2367.580023] usb 3-3.2: Product: USB PnP Audio Device
[ 2367.580027] usb 3-3.2: Manufacturer: C-Media Electronics Inc.
[ 2367.581679] input: C-Media Electronics Inc. USB PnP Audio Device as /devices/pci0000:00/0000:00:14.0/usb3/3-3/3-3.2/3-3.2:1.2/0003:0D8C:0132.0004/input/input18
[ 2367.581999] hid-generic 0003:0D8C:0132.0004: input,hidraw3: USB HID v1.11 Device [C-Media Electronics Inc. USB PnP Audio Device] on usb-0000:00:14.0-3.2/input2
[ 2367.913280] usbcore: registered new interface driver snd-usb-audio

这里可以看到其驱动程序为snd-usb-audio,依据这个关键词在内核中查找到如下内容:

tony@tony-E431:~/linux-3.4.y$ grep “registered new interface driver” ./ -rn
Binary file ./vmlinux.o matches
Binary file ./.tmp_vmlinux1 matches
Binary file ./.tmp_vmlinux2 matches
Binary file ./drivers/built-in.o matches
Binary file ./drivers/usb/built-in.o matches
Binary file ./drivers/usb/core/built-in.o matches
./drivers/usb/core/driver.c:865: pr_info(“%s: registered new interface driver %s\n”,
Binary file ./drivers/usb/core/driver.o matches
Binary file ./drivers/usb/core/usbcore.o matches
Binary file ./arch/arm/boot/Image matches
Binary file ./vmlinux matches
tony@tony-E431:~/linux-3.4.y$

以及

// file: linux-3.4.y/sound/usb/card.c
/*

  • entry point for linux usb interface
    */

static struct usb_driver usb_audio_driver = {
.name = “snd-usb-audio”,
.probe = usb_audio_probe,
.disconnect = usb_audio_disconnect,
.suspend = usb_audio_suspend,
.resume = usb_audio_resume,
.id_table = usb_audio_ids,
.supports_autosuspend = 1,
};

根据probe方法snd_usb_audio_probe调用了snd_usb_apply_boot_quirk和snd_card_register,查到了

// linux-3.4.y/sound/usb/card.c
/*

  • new 2.5 USB kernel API
    /
    static int usb_audio_probe(struct usb_interface
    intf,
    const struct usb_device_id *id)
    
    {
    struct snd_usb_audio *chip;
    chip = snd_usb_audio_probe(interface_to_usbdev(intf), intf, id);
    if (chip) {
    usb_set_intfdata(intf, chip);
    return 0;
    
    } else
    return -EIO;
    
    }

// linux-3.4.y/sound/usb/quirks.c
int snd_usb_apply_boot_quirk(struct usb_device dev,
struct usb_interface
intf,
const struct snd_usb_audio_quirk *quirk)
{
u32 id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
le16_to_cpu(dev->descriptor.idProduct));

switch (id) {
case USB_ID(0x041e, 0x3000):
    /* SB Extigy needs special boot-up sequence */
    /* if more models come, this will go to the quirk list. */
    return snd_usb_extigy_boot_quirk(dev, intf);

case USB_ID(0x041e, 0x3020):
    /* SB Audigy 2 NX needs its own boot-up magic, too */
    return snd_usb_audigy2nx_boot_quirk(dev);

case USB_ID(0x10f5, 0x0200):
    /* C-Media CM106 / Turtle Beach Audio Advantage Roadie */
    return snd_usb_cm106_boot_quirk(dev);

case USB_ID(0x0d8c, 0x0102):
    /* C-Media CM6206 / CM106-Like Sound Device */
case USB_ID(0x0ccd, 0x00b1): /* Terratec Aureon 7.1 USB */
    return snd_usb_cm6206_boot_quirk(dev);

case USB_ID(0x133e, 0x0815):
    /* Access Music VirusTI Desktop */
    return snd_usb_accessmusic_boot_quirk(dev);

case USB_ID(0x17cc, 0x1000): /* Komplete Audio 6 */
case USB_ID(0x17cc, 0x1010): /* Traktor Audio 6 */
case USB_ID(0x17cc, 0x1020): /* Traktor Audio 10 */
    return snd_usb_nativeinstruments_boot_quirk(dev);
case USB_ID(0x0763, 0x2012):  /* M-Audio Fast Track Pro USB */
    return snd_usb_fasttrackpro_boot_quirk(dev);
}

return 0;

}

snd_usb_audio_probe
/*

  • probe the active usb device
    *
  • note that this can be called multiple times per a device, when it
  • includes multiple audio control interfaces.
    *
  • thus we check the usb device pointer and creates the card instance
  • only at the first time. the successive calls of this function will
  • append the pcm interface to the corresponding card.
    /
    static struct snd_usb_audio

    snd_usb_audio_probe(struct usb_device *dev,

    struct usb_interface *intf,
    const struct usb_device_id *usb_id)
    

    {
    const struct snd_usb_audio_quirk quirk = (const struct snd_usb_audio_quirk )usb_id->driver_info;
    int i, err;
    struct snd_usb_audio chip;
    struct usb_host_interface
    alts;
    int ifnum;
    u32 id;

    alts = &intf->altsetting[0];
    ifnum = get_iface_desc(alts)->bInterfaceNumber;
    id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),

    le16_to_cpu(dev->descriptor.idProduct));
    

    if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum)

    goto __err_val;
    

    if (snd_usb_apply_boot_quirk(dev, intf, quirk) < 0)

    goto __err_val;
    

    /*

    • found a config. now register to ALSA
      */

      / check whether it’s already registered /
      chip = NULL;
      mutex_lock(&register_mutex);
      for (i = 0; i < SNDRV_CARDS; i++) {
      if (usb_chip[i] && usb_chip[i]->dev == dev) {

      if (usb_chip[i]->shutdown) {
          snd_printk(KERN_ERR "USB device is in the shutdown state, cannot create a card instance\n");
          goto __error;
      }
      chip = usb_chip[i];
      chip->probing = 1;
      break;
      

      }
      }
      if (! chip) {
      /* it’s a fresh one.

      • now look for an empty slot and create a new card instance
        */
        for (i = 0; i < SNDRV_CARDS; i++)
        if (enable[i] && ! usb_chip[i] &&
        (vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) &&
        (pid[i] == -1 || pid[i] == USB_ID_PRODUCT(id))) {
        if (snd_usb_audio_create(dev, i, quirk, &chip) < 0) {
            goto __error;
        }
        snd_card_set_dev(chip->card, &intf->dev);
        chip->pm_intf = intf;
        break;
        
        }
        if (!chip) {
        printk(KERN_ERR “no available usb audio device\n”);
        goto __error;
        }
        }

      /*

    • For devices with more than one control interface, we assume the
    • first contains the audio controls. We might need a more specific
    • check here in the future.
      */
      if (!chip->ctrl_intf)
      chip->ctrl_intf = alts;

      chip->txfr_quirk = 0;
      err = 1; / continue /
      if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) {
      / need some special handlings /
      if ((err = snd_usb_create_quirk(chip, intf, &usb_audio_driver, quirk)) < 0)

      goto __error;
      

      }

      if (err > 0) {
      / create normal USB audio interfaces /
      if (snd_usb_create_streams(chip, ifnum) < 0 ||

      snd_usb_create_mixer(chip, ifnum, ignore_ctl_error) < 0) {
      goto __error;
      

      }
      }

      / we are allowed to call snd_card_register() many times /
      if (snd_card_register(chip->card) < 0) {
      goto __error;
      }

      usb_chip[chip->index] = chip;
      chip->num_interfaces++;
      chip->probing = 0;
      mutex_unlock(&register_mutex);
      return chip;

    __error:
    if (chip) {

    if (!chip->num_interfaces)
        snd_card_free(chip->card);
    chip->probing = 0;
    

    }
    mutex_unlock(&register_mutex);
    __err_val:
    return NULL;
    }

Bus 003 Device 019: ID 0d8c:0132 C-Media Electronics, Inc.
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 16
idVendor 0x0d8c C-Media Electronics, Inc.
idProduct 0x0132
bcdDevice 1.00
iManufacturer 1 C-Media Electronics Inc.
iProduct 2 USB PnP Audio Device
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 221
bNumInterfaces 3
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
(Bus Powered)
MaxPower 100mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 0
bInterfaceClass 1 Audio
bInterfaceSubClass 1 Control Device
bInterfaceProtocol 0
iInterface 0
AudioControl Interface Descriptor:
bLength 9
bDescriptorType 36
bDescriptorSubtype 1 (HEADER)
bcdADC 1.00
wTotalLength 47
bInCollection 1
baInterfaceNr( 0) 1
AudioControl Interface Descriptor:
bLength 12
bDescriptorType 36
bDescriptorSubtype 2 (INPUT_TERMINAL)
bTerminalID 2
wTerminalType 0x0201 Microphone
bAssocTerminal 0
bNrChannels 2
wChannelConfig 0x0003
Left Front (L)
Right Front (R)
iChannelNames 0
iTerminal 0
AudioControl Interface Descriptor:
bLength 9
bDescriptorType 36
bDescriptorSubtype 3 (OUTPUT_TERMINAL)
bTerminalID 7
wTerminalType 0x0101 USB Streaming
bAssocTerminal 0
bSourceID 8
iTerminal 0
AudioControl Interface Descriptor:
bLength 7
bDescriptorType 36
bDescriptorSubtype 5 (SELECTOR_UNIT)
bUnitID 8
bNrInPins 1
baSource( 0) 10
iSelector 0
AudioControl Interface Descriptor:
bLength 10
bDescriptorType 36
bDescriptorSubtype 6 (FEATURE_UNIT)
bUnitID 10
bSourceID 2
bControlSize 1
bmaControls( 0) 0x01
Mute Control
bmaControls( 1) 0x02
Volume Control
bmaControls( 2) 0x02
Volume Control
iFeature 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 0
bInterfaceClass 1 Audio
bInterfaceSubClass 2 Streaming
bInterfaceProtocol 0
iInterface 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 1
bNumEndpoints 1
bInterfaceClass 1 Audio
bInterfaceSubClass 2 Streaming
bInterfaceProtocol 0
iInterface 0
AudioStreaming Interface Descriptor:
bLength 7
bDescriptorType 36
bDescriptorSubtype 1 (AS_GENERAL)
bTerminalLink 7
bDelay 1 frames
wFormatTag 1 PCM
AudioStreaming Interface Descriptor:
bLength 29
bDescriptorType 36
bDescriptorSubtype 2 (FORMAT_TYPE)
bFormatType 1 (FORMAT_TYPE_I)
bNrChannels 1
bSubframeSize 2
bBitResolution 16
bSamFreqType 7 Discrete
tSamFreq[ 0] 8000
tSamFreq[ 1] 11025
tSamFreq[ 2] 16000
tSamFreq[ 3] 22050
tSamFreq[ 4] 32000
tSamFreq[ 5] 44100
tSamFreq[ 6] 48000
Endpoint Descriptor:
bLength 9
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 5
Transfer Type Isochronous
Synch Type Asynchronous
Usage Type Data
wMaxPacketSize 0x0064 1x 100 bytes
bInterval 1
bRefresh 0
bSynchAddress 0
AudioControl Endpoint Descriptor:
bLength 7
bDescriptorType 37
bDescriptorSubtype 1 (EP_GENERAL)
bmAttributes 0x01
Sampling Frequency
bLockDelayUnits 0 Undefined
wLockDelay 0 Undefined
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 2
bNumEndpoints 1
bInterfaceClass 1 Audio
bInterfaceSubClass 2 Streaming
bInterfaceProtocol 0
iInterface 0
AudioStreaming Interface Descriptor:
bLength 7
bDescriptorType 36
bDescriptorSubtype 1 (AS_GENERAL)
bTerminalLink 7
bDelay 1 frames
wFormatTag 1 PCM
AudioStreaming Interface Descriptor:
bLength 29
bDescriptorType 36
bDescriptorSubtype 2 (FORMAT_TYPE)
bFormatType 1 (FORMAT_TYPE_I)
bNrChannels 2
bSubframeSize 2
bBitResolution 16
bSamFreqType 7 Discrete
tSamFreq[ 0] 8000
tSamFreq[ 1] 11025
tSamFreq[ 2] 16000
tSamFreq[ 3] 22050
tSamFreq[ 4] 32000
tSamFreq[ 5] 44100
tSamFreq[ 6] 48000
Endpoint Descriptor:
bLength 9
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 5
Transfer Type Isochronous
Synch Type Asynchronous
Usage Type Data
wMaxPacketSize 0x00c8 1x 200 bytes
bInterval 1
bRefresh 0
bSynchAddress 0
AudioControl Endpoint Descriptor:
bLength 7
bDescriptorType 37
bDescriptorSubtype 1 (EP_GENERAL)
bmAttributes 0x01
Sampling Frequency
bLockDelayUnits 0 Undefined
wLockDelay 0 Undefined
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 2
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 0 No Subclass
bInterfaceProtocol 0 None
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.11
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 26
Report Descriptors:
UNAVAILABLE
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x87 EP 7 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0010 1x 16 bytes
bInterval 1
Device Status: 0x0000
(Bus Powered)

总结:
UAC设备的参数是通过USB描述符确定的。比如声道是bNrChannels,位深是bBitResolution,采样率是bSamFreqType。截取其中一段说明:

bNrChannels 1
bSubframeSize 2
bBitResolution 16
bSamFreqType 7 Discrete
tSamFreq[ 0] 8000
tSamFreq[ 1] 11025
tSamFreq[ 2] 16000
tSamFreq[ 3] 22050
tSamFreq[ 4] 32000
tSamFreq[ 5] 44100
tSamFreq[ 6] 48000

声道1,位深16,波特率8000~48000。

-博客地址: Born2013.github.io

文章目录
  1. 1. USB Audio Class (UAC) 分析