linux 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;

}

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。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值