1. 程式人生 > >Android USB/MTP相關實現

Android USB/MTP相關實現

前面轉發了篇部落格介紹了MTP, 偏重於上層,已經很清楚了。這篇側重於底層,按照一定的流程講。

1. 程式碼位置

packages/providers/MediaProvider/src/com/android/providers/media/MtpReceiver.java
packages/providers/MediaProvider/src/com/android/providers/media/MtpService.java
packages/providers/MediaProvider/src/com/android/providers/media/MediaProvider.java
frameworks/base/media/java/android/mtp/MtpServer.java
frameworks/base/media/java/android/mtp/MtpDatabase.java
frameworks/base/media/java/android/mtp/MtpStorage.java
frameworks/base/media/java/android/mtp/MtpPropertyGroup.java
frameworks/base/media/java/android/mtp/MtpPropertyList.java
frameworks/base/media/java/android/mtp/MtpConstants.java
frameworks/base/media/jni/android_mtp_MtpServer.cpp
frameworks/base/media/jni/android_mtp_MtpDatabase.cpp
frameworks/av/media/mtp/MtpServer.h
frameworks/av/media/mtp/MtpServer.cpp
frameworks/av/media/mtp/MtpDatabase.h

frameworks/base/services/java/com/android/server/usb/UsbDeviceManager.java (UsbManager, UsbService)

kernel/drivers/usb/* (主要是android.c, f_mtp.c)

2. 在Settings設定mtp後,程式碼執行

Usbanager.SetCurrentFunction()

    ->UsbService.SetCurrentFunction()

        ->UsbDeviceManager.setCurrentFunctions()

             -> mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS)

                   ->setEnabledFunctions(functions, makeDefault);

                       ->SystemProperties.set("persist.sys.usb.config", functions);

此時會呼叫到init.usb.rc執行相應的程式碼

如果直接開機,開機時會在設定persist.sys.usb.config/sys.usb.config時執行init.usb.rc中程式碼(沒有經過framework及以上程式碼)。

write /sys/class/android_usb/android0/enable 0/1

以上程式碼對應執行enable_store (android.c)

enable_store
1)enabled
  f->enable(f_holder->f);
     adb_android_function_enable
        android_disable
           usb_ep_dequeue
           usb_remove_config
  android_enable(dev);
    usb_add_config
    usb_gadget_connect
2)disabled
  android_disable(dev);
     usb_ep_dequeue
     usb_remove_config
  f->disable(f_holder->f)
     adb_android_function_disable
  
usb_add_config(android_bind_config)   composite.c
   bind()
     android_bind_config()
         android_bind_enabled_functions()
            f->bind_config()
               mtp_function_bind_config(mtp)
               adb_function_bind_config(adb)
                  -> usb_add_function()
            
            
usb_remove_config()          
   reset_config(cdev);
   unbind_config(cdev, config);
       f->unbind(config, f);
          ****_function_unbind_config()
      config->unbind(config);

write /sys/class/android_usb/android0/functions mtp

以上程式碼對應執行functions_store (android.c)

functions_store()
 -> android_enable_function()
         -> list_add_tail  

3. 如果開機後,連上USB線,首先執行chargr檢測,然後是列舉過程 (以高通某晶片為例),這小節講充電器檢測

 kernel\drivers\power\qpnp-charger.c

     rc = devm_request_irq(chip->dev, chip->usbin_valid.irq,
    qpnp_chg_usb_usbin_valid_irq_handler,
    IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
     "usbin-valid", chip);

qpnp_chg_usb_usbin_valid_irq_handler()中斷處理函式,檢測USB插入拔出

在連USB開機的情況下,這個處理函式會在qpnp_charger_probe()呼叫。

首先是電源恢復工作,

power_supply_set_present()

    ->msm_otg_set_vbus_state(POWER_SUPPLY_PROP_PRESENT)

        ->msm_otg_sm_work()

             ->pm_runtime_resume()

                 ->msm_otg_runtime_resume()

                     ->msm_otg_resume()

此時會看到log   "USB exited from low power mode"

開始充電器檢測工作

主要函式式msm_chg_detect_work() in msm_otg.c

通常USB線的檢測狀態變化

USB_CHG_STATE_UNDEFINED->USB_CHG_STATE_WAIT_FOR_DCD(迴圈幾次)->USB_CHG_STATE_DCD_DONE

USB線的檢測結果是USB_SDP_CHARGER,

此時會設定otg->phy->state=b_peripheral, 並設定current=100mA

4. 列舉過程

4.1 中斷

ci13xxx_msm.c
   ret = request_irq(wake_irq, ci13xxx_msm_resume_irq,
                IRQF_TRIGGER_RISING | IRQF_ONESHOT, "usb resume", NULL);
ret = request_irq(_udc_ctxt.irq, msm_udc_irq, IRQF_SHARED, pdev->name, pdev);

msm_udc_irq()直接呼叫udc_irq(),處理PM and tr complete
isr_reset_handler/isr_suspend_handler/isr_resume_handler/isr_tr_complete_handler

msm_otg.c
Vbus檢測中斷
 ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
     "msm_otg", motg);
     
msm_otg_irq()->queue_work(system_nrt_wq, &motg->sm_work);->msm_otg_sm_work()

插OTG 線後中斷

msm_pmic_id_irq(), ID pin 

4.2 呼叫過程

ci13xxx_udc.c

isr_reset_handler/isr_suspend_handler/isr_resume_handler/isr_tr_complete_handler

msm_otg_sm_work() in msm_otg.c

msm_chg_detect_work(b_idle b_sess_vld USB_SDP_CHARGER)  

msm_otg_start_peripheral(otg, 1);   "gadget on"

setup_gpio (.setup_gpio = isp1763_setup_gpio)

usb_gadget_vbus_connect

ci13xxx_vbus_session  "vbus online"    ci13xxx_udc.c

hw_device_reset

notify_event(CI13XXX_CONTROLLER_RESET_EVENT)

hw_device_state

notify_event(CI13XXX_CONTROLLER_CONNECT_EVENT);

msm_udc_irq  kernel/drivers/usb/gadget/ci13xxx_msm.c ( request_irq(_udc_ctxt.irq, msm_udc_irq, IRQF_SHARED, pdev->name...)

udc_irq

isr_suspend_handler  ci13xxx_udc.c

udc->driver->suspend(&udc->gadget);

notify_event(CI13XXX_CONTROLLER_SUSPEND_EVENT);

usb_phy_set_suspend(1)

suspended=1

isr_reset_handler   ci13xxx_udc.c

notify_event(CI13XXX_CONTROLLER_RESUME_EVENT);

usb_phy_set_suspend(0)

udc->driver->resume(&udc->gadget);

suspended=0

usb_phy_set_power(udc->transceiver, 100);

set_power()    otg.h

msm_otg_set_power  msm_otg.c

msm_otg_notify_charger(motg, mA);   msm_otg.c

msm_otg_notify_chg_type    msm_otg.c

power_supply_set_supply_type  power/power_supply_core.c

set_property(POWER_SUPPLY_PROP_TYPE)

otg_power_set_property_usb(POWER_SUPPLY_PROP_TYPE)

msm_otg_notify_power_supply      msm_otg.c

power_supply_set_online(psy, true))

power_supply_set_current_limit(100mA)

_gadget_stop_activity   ci13xxx_udc.c

android_disconnect

composite_disconnect

schedule_work()->android_work    "android_work: did not send uevent (0 0   (null))"

hw_usb_reset();

isr_resume_handler  

notify_event(CI13XXX_CONTROLLER_RESUME_EVENT)

usb_phy_set_suspend(0);

udc->driver->resume(&udc->gadget);

isr_tr_complete_handler  ci13xxx_udc.c

driver->setup

android_setup       android.c

f->ctrlrequest(f, cdev, c);

  mtp_function_ctrlrequest()

composite_setup(USB_REQ_GET_DESCRIPTOR USB_DT_DEVICE)   composite.c

schedule_work() ->android_work  "android_work: sent uevent USB_STATE=CONNECTED"

isr_reset_handler

...

_gadget_stop_activity

android_disconnect

composite_disconnect

schedule_work()->android_work "android_work: sent uevent USB_STATE=DISCONNECTED"

isr_resume_handler

...

isr_tr_complete_handler USB_REQ_SET_ADDRESS 1

isr_tr_complete_handler driver->setup

android_setup       android.c

composite_setup(USB_REQ_GET_DESCRIPTOR USB_DT_DEVICE)   composite.c

schedule_work()->android_work      "android_work: sent uevent USB_STATE=CONNECTED"

isr_tr_complete_handler driver->setup

android_setup

composite_setup USB_REQ_GET_DESCRIPTOR USB_DT_CONFIG

isr_tr_complete_handler driver->setup (USB_DT_STRING 3 times, vary)

android_setup

composite_setup USB_REQ_GET_DESCRIPTOR USB_DT_STRING

isr_tr_complete_handler driver->setup           

android_setup       android.c

composite_setup(USB_REQ_GET_DESCRIPTOR USB_DT_DEVICE)   composite.c

isr_tr_complete_handler driver->setup

android_setup

composite_setup USB_REQ_GET_DESCRIPTOR USB_DT_CONFIG

isr_tr_complete_handler USB_REQ_SET_CONFIGURATION 1

isr_tr_complete_handler driver->setup

android_setup

composite_setup USB_REQ_SET_CONFIGURATION   composite.c

set_config

set_alt

mtp_function_set_alt

adb_function_set_alt

usb_gadget_vbus_draw() 

vbus_draw()

ci13xxx_vbus_draw  ci13xxx_udc.c

usb_phy_set_power

set_power

msm_otg_set_power

msm_otg_notify_charger(motg, mA);         "usb: Avail curr from USB = 500"

msm_otg_notify_chg_type

      power_supply_set_supply_type

                                      msm_otg_notify_power_supply

...    

isr_tr_complete_handler driver->setup

android_setup

composite_setup USB_REQ_GET_DESCRIPTOR USB_DT_STRING

schedule_work()->android_work    "android_work: sent uevent USB_STATE=CONFIGURED"

 4.3 判讀HS, FS
ci13xxx_udc.c
 udc_probe()
   udc->gadget.speed        = USB_SPEED_UNKNOWN;
   udc->gadget.max_speed    = USB_SPEED_HIGH;      //最大速度

isr_resume_handler()
  udc->gadget.speed = hw_port_is_high_speed() ? USB_SPEED_HIGH : USB_SPEED_FULL;
HS/FS是通過函式hw_port_is_high_speed()得到

4.4 判斷Host/Device

msm_otg_start_peripheral(on=1)
這裡通過判斷是SDP_CHARGER,然後設成peripheral(device).

qpnp_chg_usb_usbin_valid_irq_handler: qpnp_chg_usb_usbin_valid_irq_handler usbin-valid triggered: 1 host_mode: 0
上面就可以打印出host_mode, 是通過下面函式得到
host_mode = qpnp_chg_is_otg_en_set(chip);

接OTG線後,可以通過如下中斷處理函式看出
msm_pmic_id_irq(), 主要處理函式msm_pmic_id_status_w()

也可以通過函式得到msm_otg_read_pmic_id_state()

PMIC: ID clear     host
PMIC: ID set       device

5. 下面才是MTP的單獨部分

5.1 start MTP server

android_work()傳送uevent(USB_STATE=CONFIGURED)給上層

packages/providers/MediaProvider/src/com/android/providers/media/MtpReceiver.java

handleUsbState()

   intent = new Intent(context, MtpService.class);
   context.startService(intent);

packages/providers/MediaProvider/src/com/android/providers/media/MtpService.java

onStartCommand  
   manageServiceLocked()    MtpService.java  "starting MTP server in MTP mode"
      mServer = new MtpServer(mDatabase, mPtpMode);
          MtpServer(MtpDatabase database, boolean usePtp) frameworks/base/media/java/android/mtp/MtpServer.java
      mServer.start();  

frameworks/base/media/jni/android_mtp_MtpServer.cpp

native_setup   
   android_mtp_MtpServer_setup 
         int fd = open("/dev/mtp_usb", O_RDWR);
               mtp_open()    f_mtp.c
    MtpServer* server = new MtpServer(fd, getMtpDatabase(env, javaDatabase),..)

packages/providers/MediaProvider/src/com/android/providers/media/MtpService.java
mServer.start();    
   run()  frameworks/base/media/java/android/mtp/MtpServer.java
      native_run   frameworks/base/media/jni/android_mtp_MtpServer.cpp
      android_mtp_MtpServer_run
         server->run();
             MtpServer::run()   frameworks/av/media/mtp/MtpServer.cpp

5.2 主要處理函式

frameworks/av/media/mtp/MtpServer.cpp

MtpServer::run()   
infinite loop; read request; send data/response (write)
Read part
 mRequest.read(fd); 
    MtpRequestPacket::read()  (MtpRequestPacket    mRequest;)
      ::read(fd, mBuffer, mBufferSize); 
         mtp_read()    f_mtp.c
     
Write data/response
 mData.write
    MtpDataPacket::write(int fd)
       ::write(fd, mBuffer, mPacketSize);
          mtp_write()    f_mtp.c
 mResponse.write
    MtpResponsePacket::write
       ::write(fd, mBuffer, mPacketSize);
          mtp_write()    f_mtp.c
      

Event
MtpServer::doGetObject()
   ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr);
     mtp_ioctl() in f_mtp.c
MtpServer::doSendObject()
   ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
     mtp_ioctl() in f_mtp.c

MtpServer::sendObjectAdded/sendObjectRemoved/sendStoreAdded/sendStoreRemoved/sendDevicePropertyChanged
  MtpServer::sendEvent(MtpEventCode code, uint32_t param1)
    MtpEventPacket::write(int fd)
       ::ioctl(fd, MTP_SEND_EVENT, (unsigned long)&event);
          mtp_ioctl() in f_mtp.c
            mtp_send_event()

開始的幾個操作

MTP_OPERATION_OPEN_SESSION (1002)             
MTP_OPERATION_GET_DEVICE_INFO (1001)          
MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED (9801)
MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED (9801)
MTP_OPERATION_GET_DEVICE_PROP_DESC (1014)     
MTP_OPERATION_GET_OBJECT_PROP_LIST (9805)

6. Debug方法

首先看看是哪部分出問題了

a. 檢查main log, UsbDeviceManager, setEnabledFunctions()是否正常

b. 檢查property,    persist.sys.usb.config,  sys.usb.config, sys.usb.state

c. 檢查sysfs, functions and state, vid, pid

d. 檢查kernel log, 能否看到sent uevent(USB_STATE=CONFIGURED), 同時看看main log, UsbDeviceManager

e. 檢查main log/kernel, MTP server啟動是否正常

f. 如果正常看看命令接收和response是否正常

針對不同出錯地方,仔細看相應部分程式碼

除錯工具

USB sniffer 方便看到所有資料,從協議上看看出錯地方,尤其是可能是PC問題時

對比方法

換PC, 換手機的方法來對比測試

7. 正常log

mtp_bind_config                                                                     
msm_otg : USB exited from low power mode                                
msm_otg : chg_type = USB_SDP_CHARGER                                    
msm_hsusb msm_hsusb: vbus online                                                    
msm_hsusb msm_hsusb: CI13XXX_CONTROLLER_RESET_EVENT received                        
msm_hsusb msm_hsusb: CI13XXX_CONTROLLER_CONNECT_EVENT received                      
msm_hsusb msm_hsusb: reset                                                          
msm_otg : Avail curr from USB = 100                                     
android_work: android_work: did not send uevent (0 0   (null))                      
android_work: android_work: sent uevent USB_STATE=CONNECTED                         
msm_hsusb msm_hsusb: reset                                                          
android_work: android_work: sent uevent USB_STATE=DISCONNECTED                      
android_work: android_work: sent uevent USB_STATE=CONNECTED                         
msm_otg : Avail curr from USB = 500                                     
android_work: android_work: sent uevent USB_STATE=CONFIGURED    
MtpService: starting MTP server in MTP mode                   
mtp_open