这个手机做device, audio accessory是Host.以高通msm8x26(USB2.0) Lolliop android 5.0/5.1为例1 代码•Kernelkernel/drivers/usb/gadget/f_accessory.c,f_audio_source.c•Frameworks/baseservices/usb/java/com/android/server/usb/UsbDeviceManager.java•hardware/libhardwarehardware/libhardware/modules/usbaudio/audio_hw.c2 android_setup的调用栈handle_IRQgeneric_handle_irqhandle_fasteoi_irqhandle_irq_eventhandle_irq_event_percpumsm_udc_irqisr_tr_complete_handlerudc->driver->setup(&udc->gadget,&req);android_setupandroid.cvalue = 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 detectioncharger检测过程中的状态转换过程USB_CHG_STATE_UNDEFINEDUSB_CHG_STATE_WAIT_FOR_DCDUSB_CHG_STATE_DCD_DONEUSB_CHG_STATE_PRIMARY_DONEUSB_CHG_STATE_SECONDARY_DONEtypical log:usbin-valid triggered: 1host_mode: 0 (usbin插入中断处理函数)msm_otg f9a55000.usb:USB exited from low power modemsm_otg f9a55000.usb:chg_type =USB_CDP_CHARGERmsm_otg f9a55000.usb:Availcurr from USB =15003.2 Resetmsm_hsusbmsm_hsusb:CI13XXX_CONTROLLER_RESET_EVENT receivedmsm_hsusbmsm_hsusb:CI13XXX_CONTROLLER_CONNECT_EVENT receivedmsm_hsusbmsm_hsusb: reset (可能两次)android_work: android_work: did not senduevent (0 0(null))3.3 第一次尝试枚举GetDescriptor (Device)ResetSetAddressGetDescriptor(Device/Configuration)此时Host得到的通常是Device的Configuration为MTP的回应Typical logandroid_usb gadget: [COM]composite_setup:value=0,bRequestType=0x80,bRequest=0x6,w_value=0x100,w_length=0x40android_work: android_work: sent ueventUSB_STATE=CONNECTEDmsm_hsusbmsm_hsusb: resetandroid_work: android_work: sent ueventUSB_STATE=DISCONNECTEDisr_tr_complete_handlerUSB_REQ_SET_ADDRESSandroid_usb gadget: [COM]composite_setup:value=0,bRequestType=0x80,bRequest=0x6,w_value=0x100,w_length=0x12android_usb gadget: [COM]composite_setup:value=0,bRequestType=0x80,bRequest=0x6,w_value=0x200,w_length=0x9android_usb gadget: [COM]composite_setup:value=0,bRequestType=0x80,bRequest=0x6,w_value=0x200,w_length=0x27android_work: android_work: sent ueventUSB_STATE=CONNECTED然后host开始一些accessory的ctrl request命令typical logacc_ctrlrequest c0.33 v0000 i0000 l2acc_ctrlrequest 40.34 v0000 i0000 l1acc_ctrlrequest 40.34 v0000 i0001 l1acc_ctrlrequest 40.34 v0000 i0002 l1acc_ctrlrequest 40.34 v0000 i0003 l1acc_ctrlrequest 40.34 v0000 i0004 l1acc_ctrlrequest 40.34 v0000 i0005 l1acc_ctrlrequest 40.3a v0001 i0000 l0acc_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_sourceframeworks/base/…/usb/UsbDeviceManager.javaprivate 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);}setCurrentFunctionssend MSG_SET_CURRENT_FUNCTIONSsetEnabledFunctions(functions,makeDefault)setUsbConfig("none")setUsbConfig(functions)init.usb.rc# audio accessory configurationon property:sys.usb.config=audio_sourcewrite /sys/class/android_usb/android0/enable0write /sys/class/android_usb/android0/idVendor18d1write /sys/class/android_usb/android0/idProduct2d02write /sys/class/android_usb/android0/functions${sys.usb.config}write /sys/class/android_usb/android0/enable1setpropsys.usb.state ${sys.usb.config}typical log:android_usb gadget:usb_remove_config#1 'fe8050c8.android_usb'/ec008900android_usb gadget:unbind function 'mtp'/c3d2ab00android_usb gadget:unbindconfig'fe8050c8.android_usb'/ec008900enable_store disablemtpandroid_usb gadget:usb_add_config addingconfig #1'fe8050c8.android_usb'/ec008900android_usb gadget:usb_add_function adding 'audio_source'/c0e70460 toconfig'fe8050c8.android_usb'/ec008900android_usb gadget:cfg 1/ec008900speeds: high fullandroid_usb gadget:interface 0 =audio_source/c0e70460msm_hsusbmsm_hsusb: suspendmsm_hsusbmsm_hsusb:CI13XXX_CONTROLLER_SUSPEND_EVENT receivedandroid_work: android_work: did not senduevent (1 1(null))3.4 Resetmsm_hsusbmsm_hsusb: reset (可能重复两次)msm_hsusbmsm_hsusb:CI13XXX_CONTROLLER_RESUME_EVENT receivedandroid_work: android_work: sent ueventUSB_STATE=DISCONNECTED3.5 第二次枚举GetDescriptor(Device)ResetSetAddressGetDescriptor(Device/Configuration)SetConfigurationSetInterfaceSetCurtypical log:android_work: android_work: sent ueventUSB_STATE=CONNECTEDmsm_hsusbmsm_hsusb: resetandroid_work: android_work: sentueventUSB_STATE=DISCONNECTEDandroid_work: android_work: sent ueventUSB_STATE=CONNECTEDandroid_usb gadget:set_config high-speedconfig #1:fe8050c8.android_usbandroid_work: android_work: sent ueventUSB_STATE=CONFIGURED4. Audio初始化及播放UsbDeviceManager在得知状态为CONFIGURED后,UsbDeviceManager: updateAudioSourceFunction enabled=trueUsbDeviceManager: MSG_UPDATE_STATE updateAudioSourceFunctionif state=CONFIGUREDenable=truesend Intent AudioManager.ACTION_USB_AUDIO_ACCESSORY_PLUGframeworks/base/media/java/android/media/AudioService.javaoutDevice = AudioSystem.DEVICE_OUT_USB_ACCESSORY;setWiredDeviceConnectionState(outDevice, state, params);sendMsg MSG_SET_WIRED_DEVICE_CONNECTION_STATEonSetWiredDeviceConnectionStatehandleDeviceConnection()AudioSystem.setDeviceConnectionState() (AudioSystem.java->AudioSystem.cpp)AudioPolicyIntefaceImpl: setDeviceConnectionState()AudioPolicyManager::setDeviceConnectionState()AudioPolicyManager::setDeviceConnectionStateInt()AudioPolicyManager::setDeviceConnectionStateInt()AudioPolicyManager::checkOutputsForDevice()mpClientInterface->openOutput() frameworks/av/services/audiopolicy/AudioPolicyClientImpl.cppaf->openOutput()frameworks/av/services/audioflinger/AudioFlinger.cppAudioFlinger::openOutputAudioFlinger::openOutput_l()hwDevHal->open_output_stream()adev_open_output_stream()hardware/libhardware/modules/usbaudio/audio_hw.cadev->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.cppAudioFlinger::PlaybackThread::threadLoop_write()ssize_tframesWritten = mNormalSink->write()bytesWritten = mOutput->stream->write()out_write() in usbaudio/audio_hw.chardware/libhardware/modules/usbaudio/audio_hw.cout->stream.write = out_write;out_write usb_audio_hwstart_output_streamproxy_open alsa_device_proxypcm_open qcom/audio/legacy/libalsa-intf/alsa_pcm.copenkernel/drivers/usb/gadget/f_audio_source.caudio_pcm_open随后是audio_pcm_open(),audio_pcm_hw_params(), audio_pcm_prepare()audio_pcm_playback_trigger cmd=1audio_pcm_playback_startaudio_sendaudio_data_complete req->status 0 req->actual 176system/core/include/system/audio.haudio_devices_t;AUDIO_DEVICE_OUT_USB_ACCESSORY = 0x2000,frameworks/base/media/java/android/media/AudioSystem.javapublic 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抓到的数据
如果觉得《Android USB Audio accessory设备》对你有帮助,请点赞、收藏,并留下你的观点哦!