您的位置:首页 > 其它

USB Audio accessory设备

2015-09-07 22:26 183 查看
这个手机做device, audio accessory是Host.

以高通msm8x26(USB2.0) Lolliop android 5.0/5.1为例

1 代码

•Kernel

kernel/drivers/usb/gadget/f_accessory.c,f_audio_source.c

•Frameworks/base
services/usb/java/com/android/server/usb/UsbDeviceManager.java

•hardware/libhardware
hardware/libhardware/modules/usbaudio/audio_hw.c

2 android_setup的调用栈

handle_IRQ

generic_handle_irq

handle_fasteoi_irq

handle_irq_event

handle_irq_event_percpu

msm_udc_irq

isr_tr_complete_handler

udc->driver->setup(&udc->gadget,&req);

android_setup android.c

value = f->ctrlrequest(f,cdev, c); (value < 0)

value =
acc_ctrlrequest(cdev, c);

value =
composite_setup(gadget, c);

schedule_work(&dev->work);

android_work()

3 连接过程

大致分5步

3.1 CDP charger detection

charger检测过程中的状态转换过程

USB_CHG_STATE_UNDEFINED

USB_CHG_STATE_WAIT_FOR_DCD

USB_CHG_STATE_DCD_DONE

USB_CHG_STATE_PRIMARY_DONE

USB_CHG_STATE_SECONDARY_DONE

typical log:

usbin-valid triggered: 1host_mode: 0 (usbin插入中断处理函数)

msm_otg f9a55000.usb:USB exited from low power mode

msm_otg f9a55000.usb:chg_type =USB_CDP_CHARGER

msm_otg f9a55000.usb:Availcurr from USB =1500

3.2 Reset

msm_hsusbmsm_hsusb:CI13XXX_CONTROLLER_RESET_EVENT received

msm_hsusbmsm_hsusb:CI13XXX_CONTROLLER_CONNECT_EVENT received

msm_hsusbmsm_hsusb: reset (可能两次)

android_work:
android_work: did not senduevent (0 0 (null))

3.3 第一次尝试枚举

GetDescriptor (Device)

Reset

SetAddress

GetDescriptor(Device/Configuration)

此时Host得到的通常是Device的Configuration为MTP的回应

Typical log

android_usb gadget: [COM]composite_setup:value=0,bRequestType=0x80,bRequest=0x6,w_value=0x100,w_length=0x40

android_work:
android_work: sent
ueventUSB_STATE=CONNECTED

msm_hsusbmsm_hsusb: reset

android_work:
android_work: sent
ueventUSB_STATE=DISCONNECTED

isr_tr_complete_handlerUSB_REQ_SET_ADDRESS

android_usb gadget: [COM]composite_setup:value=0,bRequestType=0x80,bRequest=0x6,w_value=0x100,w_length=0x12

android_usb gadget: [COM]composite_setup:value=0,bRequestType=0x80,bRequest=0x6,w_value=0x200,w_length=0x9

android_usb gadget: [COM]composite_setup:value=0,bRequestType=0x80,bRequest=0x6,w_value=0x200,w_length=0x27

android_work:
android_work: sent
ueventUSB_STATE=CONNECTED

然后host开始一些accessory的ctrl request命令

typical log

acc_ctrlrequest c0.33 v0000 i0000 l2

acc_ctrlrequest 40.34 v0000 i0000 l1

acc_ctrlrequest 40.34 v0000 i0001 l1

acc_ctrlrequest 40.34 v0000 i0002 l1

acc_ctrlrequest 40.34 v0000 i0003 l1

acc_ctrlrequest 40.34 v0000 i0004 l1

acc_ctrlrequest 40.34 v0000 i0005 l1

acc_ctrlrequest 40.3a v0001 i0000 l0

acc_ctrlrequest 40.35 v0000 i0000 l0

代码实现在

Kernel/drivers/usb/gadget/f_accessory.c

定义在

kernel/include/linux/usb/f_accessory.h

•intacc_ctrlrequest(…)

if (b_requestType ==(USB_DIR_OUT | USB_TYPE_VENDOR)) {

if(b_request ==ACCESSORY_START) {

dev->start_requested = 1;

schedule_delayed_work(

&dev->start_work,…)

}else if (b_request ==ACCESSORY_SET_AUDIO_MODE &&

w_index == 0&&w_length == 0) {

dev->audio_mode =w_value;

value= 0;

...

static void acc_start_work(structwork_struct *data)

{

char*envp[2] = {"ACCESSORY=START", NULL };

kobject_uevent_env(&acc_device.this_device->kobj,
KOBJ_CHANGE,envp);

}

设置USB Mode to audio_source

frameworks/base/…/usb/UsbDeviceManager.java

private final UEventObservermUEventObserver = newUEventObserver()
{

} else if ("START".equals(accessory)) {

if (DEBUG)
Slog.d(TAG,"got accessory start");

startAccessoryMode();

private void startAccessoryMode() {

if (enableAccessory &&enableAudio) {

functions =
UsbManager.USB_FUNCTION_ACCESSORY +","

+
UsbManager.USB_FUNCTION_AUDIO_SOURCE;

} else if (enableAccessory) {

functions =
UsbManager.USB_FUNCTION_ACCESSORY;

} else if (enableAudio) {

functions =
UsbManager.USB_FUNCTION_AUDIO_SOURCE;

}

if (functions != null) {

mAccessoryModeRequestTime =SystemClock.elapsedRealtime();

setCurrentFunctions(functions,false);

}

setCurrentFunctions

send MSG_SET_CURRENT_FUNCTIONS

setEnabledFunctions(functions,makeDefault)

setUsbConfig("none")

setUsbConfig(functions)

init.usb.rc

# audio accessory configuration

on property:sys.usb.config=audio_source

write /sys/class/android_usb/android0/enable0

write /sys/class/android_usb/android0/idVendor18d1

write /sys/class/android_usb/android0/idProduct2d02

write /sys/class/android_usb/android0/functions${sys.usb.config}

write /sys/class/android_usb/android0/enable1

setpropsys.usb.state ${sys.usb.config}

typical log:

android_usb gadget:usb_remove_config #1 'fe8050c8.android_usb'/ec008900

android_usb gadget:unbind function 'mtp'/c3d2ab00

android_usb gadget:unbindconfig'fe8050c8.android_usb'/ec008900

enable_store disablemtp

android_usb gadget:usb_add_config addingconfig #1'fe8050c8.android_usb'/ec008900

android_usb gadget:usb_add_function adding 'audio_source'/c0e70460
toconfig'fe8050c8.android_usb'/ec008900

android_usb gadget:cfg 1/ec008900speeds: high full

android_usb gadget: interface 0 =audio_source/c0e70460

msm_hsusbmsm_hsusb: suspend

msm_hsusbmsm_hsusb:CI13XXX_CONTROLLER_SUSPEND_EVENT received
android_work:
android_work: did not senduevent (1 1 (null))

3.4 Reset

msm_hsusbmsm_hsusb: reset (可能重复两次)

msm_hsusbmsm_hsusb:CI13XXX_CONTROLLER_RESUME_EVENT received

android_work:
android_work: sent
ueventUSB_STATE=DISCONNECTED

3.5 第二次枚举

GetDescriptor(Device)
Reset
SetAddress
GetDescriptor(Device/Configuration)
SetConfiguration
SetInterface
SetCur

typical log:

android_work:
android_work: sent
ueventUSB_STATE=CONNECTED

msm_hsusbmsm_hsusb: reset

android_work: android_work: sentueventUSB_STATE=DISCONNECTED

android_work:
android_work: sent
ueventUSB_STATE=CONNECTED

android_usb gadget:set_config high-speedconfig #1:fe8050c8.android_usb

android_work:
android_work: sent
ueventUSB_STATE=CONFIGURED

4. Audio初始化及播放

UsbDeviceManager在得知状态为CONFIGURED后,

UsbDeviceManager:
updateAudioSourceFunction enabled=true

UsbDeviceManager: MSG_UPDATE_STATE updateAudioSourceFunction

if state=CONFIGURED

enable=true

send Intent AudioManager.ACTION_USB_AUDIO_ACCESSORY_PLUG

frameworks/base/media/java/android/media/AudioService.java

outDevice = AudioSystem.DEVICE_OUT_USB_ACCESSORY;

setWiredDeviceConnectionState(outDevice, state, params);

sendMsg MSG_SET_WIRED_DEVICE_CONNECTION_STATE

onSetWiredDeviceConnectionState

handleDeviceConnection()

AudioSystem.setDeviceConnectionState()
(AudioSystem.java->AudioSystem.cpp)

AudioPolicyIntefaceImpl:
setDeviceConnectionState()

AudioPolicyManager::setDeviceConnectionState()

AudioPolicyManager::setDeviceConnectionStateInt()

AudioPolicyManager::setDeviceConnectionStateInt()

AudioPolicyManager::checkOutputsForDevice()

mpClientInterface->openOutput()
frameworks/av/services/audiopolicy/AudioPolicyClientImpl.cpp

af->openOutput()

frameworks/av/services/audioflinger/AudioFlinger.cpp

AudioFlinger::openOutput

AudioFlinger::openOutput_l()

hwDevHal->open_output_stream()

adev_open_output_stream()

hardware/libhardware/modules/usbaudio/audio_hw.c

adev->hw_device.open_output_stream =
adev_open_output_stream;

此时usb_audio_hw.c里adev_open_output_stream()函数被调用

随后是alsa_device_proxy: proxy_prepare()

usb_audio_hw.c out_set_parameters

如果开始播放音乐

usb_audio_hw.c里的out_write() 被调用

AudioFlinger:
MixerThread::threadLoop_write
Threads.cpp

AudioFlinger::PlaybackThread::threadLoop_write()

ssize_tframesWritten =
mNormalSink->write()

bytesWritten =
mOutput->stream->write()

out_write() in
usbaudio/audio_hw.c

hardware/libhardware/modules/usbaudio/audio_hw.c

out->stream.write =
out_write;

out_write usb_audio_hw

start_output_stream

proxy_open alsa_device_proxy

pcm_open qcom/audio/legacy/libalsa-intf/alsa_pcm.c

open

kernel/drivers/usb/gadget/f_audio_source.c

audio_pcm_open

随后是

audio_pcm_open(),audio_pcm_hw_params(), audio_pcm_prepare()

audio_pcm_playback_trigger cmd=1

audio_pcm_playback_start

audio_send

audio_data_complete req->status 0 req->actual 176

system/core/include/system/audio.h

audio_devices_t;

AUDIO_DEVICE_OUT_USB_ACCESSORY = 0x2000,

frameworks/base/media/java/android/media/AudioSystem.java

public static final intDEVICE_OUT_USB_ACCESSORY = 0x2000;

5. Debug方法

•检查 /dev/usb_accessory 是否存在

•检查USB状态是否为CONFIGURED

•检查property
sys.usb.config=audio_source

•检查USB data(Ellisys)
•加上一些log 在文件f_accessory.cf_audio_source.caudio_hw.c中

6. Ellisys抓到的数据

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: