USB Audio accessory设备

这个手机做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_hsusb msm_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

int acc_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_hsusb msm_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 : sent uevent USB_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.c f_audio_source.c audio_hw.c中

6. Ellisys抓到的数据





  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值