USB Audio Class (UAC) 分析_snd_usb_audio_create-程序员宅基地

技术标签: usb  Linux设备驱动  audio  Android  

一个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_quirksnd_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;
}

probe依次调用了:

snd_usb_apply_boot_quirk
snd_usb_audio_create
snd_usb_create_quirk
snd_usb_create_streams
 snd_usb_create_stream
  snd_usb_parse_audio_interface 这里根据usb的信息解析成pcm参数(如声道数量,采样率等等)

snd_usb_create_mixer
snd_card_register
// linux-3.4.y/sound/core/init.c
snd_card_register调用了init_info_for_card以及snd_device_register_all。

打开DEBUG后

<6>[   58.704000] usb 1-1.1: new full-speed USB device number 5 using nxp-ehci
<6>[   58.804000] usb 1-1.1: New USB device found, idVendor=0d8c, idProduct=0132
<6>[   58.812000] usb 1-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
<6>[   58.820000] usb 1-1.1: Product: USB PnP Audio Device
<6>[   58.824000] usb 1-1.1: Manufacturer: C-Media Electronics Inc.
<6>[   58.832000] ALSA sound/usb/stream.c:438 5:1:1: add audio endpoint 0x82
<6>[   58.840000] ALSA sound/usb/stream.c:438 5:1:2: add audio endpoint 0x82
<6>[   58.848000] ALSA sound/usb/mixer.c:1214 [10] FU [Mic Capture Switch] ch = 1, val = 0/1/1
<3>[   58.856000] ALSA sound/usb/mixer.c:868 10:0: cannot get min/max values for control 2 (id 10)
<6>[   58.864000] ALSA sound/usb/mixer.c:1214 [10] FU [Mic Capture Volume] ch = 2, val = 0/1/1
<3>[   58.876000] ALSA sound/usb/mixer.c:868 10:0: cannot get min/max values for control 2 (id 10)
<6>[   58.884000] input: C-Media Electronics Inc. USB PnP Audio Device as /devices/platform/nxp-ehci/usb1/1-1/1-1.1/1-1.1:1.2/input/input6
<6>[   58.896000] generic-usb 0003:0D8C:0132.0003: input,hidraw0: USB HID v1.11 Device [C-Media Electronics Inc. USB PnP Audio Device] on usb-nxp-ehci-1.1/input2
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。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/kangear/article/details/78485994

智能推荐

while循环&CPU占用率高问题深入分析与解决方案_main函数使用while(1)循环cpu占用99-程序员宅基地

文章浏览阅读3.8k次,点赞9次,收藏28次。直接上一个工作中碰到的问题,另外一个系统开启多线程调用我这边的接口,然后我这边会开启多线程批量查询第三方接口并且返回给调用方。使用的是两三年前别人遗留下来的方法,放到线上后发现确实是可以正常取到结果,但是一旦调用,CPU占用就直接100%(部署环境是win server服务器)。因此查看了下相关的老代码并使用JProfiler查看发现是在某个while循环的时候有问题。具体项目代码就不贴了,类似于下面这段代码。​​​​​​while(flag) {//your code;}这里的flag._main函数使用while(1)循环cpu占用99

【无标题】jetbrains idea shift f6不生效_idea shift +f6快捷键不生效-程序员宅基地

文章浏览阅读347次。idea shift f6 快捷键无效_idea shift +f6快捷键不生效

node.js学习笔记之Node中的核心模块_node模块中有很多核心模块,以下不属于核心模块,使用时需下载的是-程序员宅基地

文章浏览阅读135次。Ecmacript 中没有DOM 和 BOM核心模块Node为JavaScript提供了很多服务器级别,这些API绝大多数都被包装到了一个具名和核心模块中了,例如文件操作的 fs 核心模块 ,http服务构建的http 模块 path 路径操作模块 os 操作系统信息模块// 用来获取机器信息的var os = require('os')// 用来操作路径的var path = require('path')// 获取当前机器的 CPU 信息console.log(os.cpus._node模块中有很多核心模块,以下不属于核心模块,使用时需下载的是

数学建模【SPSS 下载-安装、方差分析与回归分析的SPSS实现(软件概述、方差分析、回归分析)】_化工数学模型数据回归软件-程序员宅基地

文章浏览阅读10w+次,点赞435次,收藏3.4k次。SPSS 22 下载安装过程7.6 方差分析与回归分析的SPSS实现7.6.1 SPSS软件概述1 SPSS版本与安装2 SPSS界面3 SPSS特点4 SPSS数据7.6.2 SPSS与方差分析1 单因素方差分析2 双因素方差分析7.6.3 SPSS与回归分析SPSS回归分析过程牙膏价格问题的回归分析_化工数学模型数据回归软件

利用hutool实现邮件发送功能_hutool发送邮件-程序员宅基地

文章浏览阅读7.5k次。如何利用hutool工具包实现邮件发送功能呢?1、首先引入hutool依赖<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.19</version></dependency>2、编写邮件发送工具类package com.pc.c..._hutool发送邮件

docker安装elasticsearch,elasticsearch-head,kibana,ik分词器_docker安装kibana连接elasticsearch并且elasticsearch有密码-程序员宅基地

文章浏览阅读867次,点赞2次,收藏2次。docker安装elasticsearch,elasticsearch-head,kibana,ik分词器安装方式基本有两种,一种是pull的方式,一种是Dockerfile的方式,由于pull的方式pull下来后还需配置许多东西且不便于复用,个人比较喜欢使用Dockerfile的方式所有docker支持的镜像基本都在https://hub.docker.com/docker的官网上能找到合..._docker安装kibana连接elasticsearch并且elasticsearch有密码

随便推点

Python 攻克移动开发失败!_beeware-程序员宅基地

文章浏览阅读1.3w次,点赞57次,收藏92次。整理 | 郑丽媛出品 | CSDN(ID:CSDNnews)近年来,随着机器学习的兴起,有一门编程语言逐渐变得火热——Python。得益于其针对机器学习提供了大量开源框架和第三方模块,内置..._beeware

Swift4.0_Timer 的基本使用_swift timer 暂停-程序员宅基地

文章浏览阅读7.9k次。//// ViewController.swift// Day_10_Timer//// Created by dongqiangfei on 2018/10/15.// Copyright 2018年 飞飞. All rights reserved.//import UIKitclass ViewController: UIViewController { ..._swift timer 暂停

元素三大等待-程序员宅基地

文章浏览阅读986次,点赞2次,收藏2次。1.硬性等待让当前线程暂停执行,应用场景:代码执行速度太快了,但是UI元素没有立马加载出来,造成两者不同步,这时候就可以让代码等待一下,再去执行找元素的动作线程休眠,强制等待 Thread.sleep(long mills)package com.example.demo;import org.junit.jupiter.api.Test;import org.openqa.selenium.By;import org.openqa.selenium.firefox.Firefox.._元素三大等待

Java软件工程师职位分析_java岗位分析-程序员宅基地

文章浏览阅读3k次,点赞4次,收藏14次。Java软件工程师职位分析_java岗位分析

Java:Unreachable code的解决方法_java unreachable code-程序员宅基地

文章浏览阅读2k次。Java:Unreachable code的解决方法_java unreachable code

标签data-*自定义属性值和根据data属性值查找对应标签_如何根据data-*属性获取对应的标签对象-程序员宅基地

文章浏览阅读1w次。1、html中设置标签data-*的值 标题 11111 222222、点击获取当前标签的data-url的值$('dd').on('click', function() { var urlVal = $(this).data('ur_如何根据data-*属性获取对应的标签对象

推荐文章

热门文章

相关标签