一个正常的UAC设备插入Android 7.0是默认打开UAC配置的,打印的log如下:
[ 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
而Android4.0是没有默认打开,是需要进行相应的配置的;这里可以看到其驱动程序为snd-usb-audio
,依据这个关键词在内核中查找到如下内容:
1 root@ubuntu:/home/lh/work/git/ML16/kernel# grep "registered new interface driver" ./ -rn
2 ./drivers/usb/core/driver.c:914: pr_info("%s: registered new interface driver %s\n",
需要在 /kernel/arch/arm/configs目录下增加msm8916_defconfig和msm8916-perf_defconfig配置;
在AndroidBoard.mk就已经定义了我们kernel配置文件的属性:
CONFIG_SND_USB_AUDIO=y就行了,因为sound/usb/中的makefile包含了:
在sound/usb/card.c
1 static struct usb_driver usb_audio_driver = {
2 .name = "snd-usb-audio",
3 .probe = usb_audio_probe,
4 .disconnect = usb_audio_disconnect,
5 .suspend = usb_audio_suspend,
6 .resume = usb_audio_resume,
7 .id_table = usb_audio_ids,
8 .supports_autosuspend = 1,
9 };
根据probe方法snd_usb_audio_probe
调用了snd_usb_apply_boot_quirk
和snd_card_register
,查到了:
1 static int usb_audio_probe(struct usb_interface *intf,
2 const struct usb_device_id *id)
3 {
4 struct snd_usb_audio *chip;
5 chip = snd_usb_audio_probe(interface_to_usbdev(intf), intf, id);
6 if (chip) {
7 usb_set_intfdata(intf, chip);
8 return 0;
9 } else
10 return -EIO;
11 }
12
13
14 // linux-3.4.y/sound/usb/quirks.c
15 int snd_usb_apply_boot_quirk(struct usb_device *dev,
16 struct usb_interface *intf,
17 const struct snd_usb_audio_quirk *quirk)
18 {
19 u32 id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
20 le16_to_cpu(dev->descriptor.idProduct));
21
22 switch (id) {
23 case USB_ID(0x041e, 0x3000):
24 /* SB Extigy needs special boot-up sequence */
25 /* if more models come, this will go to the quirk list. */
26 return snd_usb_extigy_boot_quirk(dev, intf);
27
28 case USB_ID(0x041e, 0x3020):
29 /* SB Audigy 2 NX needs its own boot-up magic, too */
30 return snd_usb_audigy2nx_boot_quirk(dev);
31
32 case USB_ID(0x10f5, 0x0200):
33 /* C-Media CM106 / Turtle Beach Audio Advantage Roadie */
34 return snd_usb_cm106_boot_quirk(dev);
35
36 case USB_ID(0x0d8c, 0x0102):
37 /* C-Media CM6206 / CM106-Like Sound Device */
38 case USB_ID(0x0ccd, 0x00b1): /* Terratec Aureon 7.1 USB */
39 return snd_usb_cm6206_boot_quirk(dev);
40
41 case USB_ID(0x133e, 0x0815):
42 /* Access Music VirusTI Desktop */
43 return snd_usb_accessmusic_boot_quirk(dev);
44
45 case USB_ID(0x17cc, 0x1000): /* Komplete Audio 6 */
46 case USB_ID(0x17cc, 0x1010): /* Traktor Audio 6 */
47 case USB_ID(0x17cc, 0x1020): /* Traktor Audio 10 */
48 return snd_usb_nativeinstruments_boot_quirk(dev);
49 case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro USB */
50 return snd_usb_fasttrackpro_boot_quirk(dev);
51 }
52
53 return 0;
54 }
snd_usb_audio_probe:
1 /*
2 * probe the active usb device
3 *
4 * note that this can be called multiple times per a device, when it
5 * includes multiple audio control interfaces.
6 *
7 * thus we check the usb device pointer and creates the card instance
8 * only at the first time. the successive calls of this function will
9 * append the pcm interface to the corresponding card.
10 */
11 static struct snd_usb_audio *
12 snd_usb_audio_probe(struct usb_device *dev,
13 struct usb_interface *intf,
14 const struct usb_device_id *usb_id)
15 {
16 const struct snd_usb_audio_quirk *quirk = (const struct snd_usb_audio_quirk *)usb_id->driver_info;
17 int i, err;
18 struct snd_usb_audio *chip;
19 struct usb_host_interface *alts;
20 int ifnum;
21 u32 id;
22
23 alts = &intf->altsetting[0];
24 ifnum = get_iface_desc(alts)->bInterfaceNumber;
25 id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
26 le16_to_cpu(dev->descriptor.idProduct));
27 if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum)
28 goto __err_val;
29
30 if (snd_usb_apply_boot_quirk(dev, intf, quirk) < 0)
31 goto __err_val;
32
33 /*
34 * found a config. now register to ALSA
35 */
36
37 /* check whether it's already registered */
38 chip = NULL;
39 mutex_lock(®ister_mutex);
40 for (i = 0; i < SNDRV_CARDS; i++) {
41 if (usb_chip[i] && usb_chip[i]->dev == dev) {
42 if (usb_chip[i]->shutdown) {
43 snd_printk(KERN_ERR "USB device is in the shutdown state, cannot create a card instance\n");
44 goto __error;
45 }
46 chip = usb_chip[i];
47 chip->probing = 1;
48 break;
49 }
50 }
51 if (! chip) {
52 /* it's a fresh one.
53 * now look for an empty slot and create a new card instance
54 */
55 for (i = 0; i < SNDRV_CARDS; i++)
56 if (enable[i] && ! usb_chip[i] &&
57 (vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) &&
58 (pid[i] == -1 || pid[i] == USB_ID_PRODUCT(id))) {
59 if (snd_usb_audio_create(dev, i, quirk, &chip) < 0) {
60 goto __error;
61 }
62 snd_card_set_dev(chip->card, &intf->dev);
63 chip->pm_intf = intf;
64 break;
65 }
66 if (!chip) {
67 printk(KERN_ERR "no available usb audio device\n");
68 goto __error;
69 }
70 }
71
72 /*
73 * For devices with more than one control interface, we assume the
74 * first contains the audio controls. We might need a more specific
75 * check here in the future.
76 */
77 if (!chip->ctrl_intf)
78 chip->ctrl_intf = alts;
79
80 chip->txfr_quirk = 0;
81 err = 1; /* continue */
82 if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) {
83 /* need some special handlings */
84 if ((err = snd_usb_create_quirk(chip, intf, &usb_audio_driver, quirk)) < 0)
85 goto __error;
86 }
87
88 if (err > 0) {
89 /* create normal USB audio interfaces */
90 if (snd_usb_create_streams(chip, ifnum) < 0 ||
91 snd_usb_create_mixer(chip, ifnum, ignore_ctl_error) < 0) {
92 goto __error;
93 }
94 }
95
96 /* we are allowed to call snd_card_register() many times */
97 if (snd_card_register(chip->card) < 0) {
98 goto __error;
99 }
100
101 usb_chip[chip->index] = chip;
102 chip->num_interfaces++;
103 chip->probing = 0;
104 mutex_unlock(®ister_mutex);
105 return chip;
106
107 __error:
108 if (chip) {
109 if (!chip->num_interfaces)
110 snd_card_free(chip->card);
111 chip->probing = 0;
112 }
113 mutex_unlock(®ister_mutex);
114 __err_val:
115 return NULL;
116 }
probe依次调用了:
1 snd_usb_apply_boot_quirk
2 snd_usb_audio_create
3 snd_usb_create_quirk
4 snd_usb_create_streams
5 snd_usb_create_stream
6 snd_usb_parse_audio_interface 这里根据usb的信息解析成pcm参数(如声道数量,采样率等等)
7
8 snd_usb_create_mixer
9 snd_card_register
总结:
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。