UDC-Gadget
UDC:(USB Device Controller)用於管理和控制USB裝置與主機之間的通訊。
Gadget:Android在此層實現了adb,mtp(Media Transfer Protocol 媒體傳輸協議),mass_storage等。
早期的USB只支援單一的gadget裝置,使用場景較為簡單,隨後加入了composite framework,用來支援多個function的gadget裝置,多個function的繫結在核心中完成,若需要修改,則需要修改核心,不靈活也不方便。Linux3.11版本引入了基於configfs的usb gadget configfs。
usb gadget configfs重新實現了複合裝置層,可以在使用者空間配置和組合核心的function,靈活的構成USB複合裝置,極大了提高了工作效率。
system/core/rootdir/init.usb.configfs.rc
[persist.sys.usb.config]: [diag,adb]
[sys.usb.config]: [mtp,adb]
on property:sys.usb.ffs.ready=1 && property:sys.usb.config=mtp,adb && property:sys.usb.configfs=1
write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration "mtp_adb"
write /config/usb_gadget/g1/idVendor 0x0c2e
write /config/usb_gadget/g1/idProduct 0x0ba3
symlink /config/usb_gadget/g1/functions/mtp.gs0 /config/usb_gadget/g1/configs/b.1/f1
symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2
write /config/usb_gadget/g1/UDC ${sys.usb.controller}
setprop sys.usb.state ${sys.usb.config}
drivers/usb/gadget/configfs.c
drivers\usb\gadget\composite.c
drivers/usb/gadget/udc/core.c
drivers/usb/gadget/function/f_mtp.c
USB匯流排-Linux核心USB3.0裝置控制器複合裝置之USB gadget configfs分析
gadget -> composite -> function
make_group -> function_make -> usb_get_function_instance -> alloc_inst -> mtp_alloc_inst
每個function driver建立的時候會分配一個usb_function_instance
echo 4e00000.dwc3 > configs/usb_gadget/g1/UDC
usb_udc_attch_driver-> udc_bind_to_driver-> configfs_composite_bind
-> usb_add_function -> function->bind -> mtp_function_bind
HCD-XHCI
HCD:(Host Controller Driver)是主機控制器驅動,它是對主機控制器硬體的抽象。
XHCI:(eXtensible Host Controller Interface)也是主機控制器驅動,XHIC是基於USB3.0並且向下相容,其中整合了兩個roothub,一個對應usb2.0的(main_hcd),一個對應usb3.0的(shared_hcd)
struct xhci_hcd {
/* usb_hcd結構體:用於描述USB主機控制器驅動*/
struct usb_hcd *main_hcd;
struct usb_hcd *shared_hcd;
/* glue to PCI and HCD framework */
struct xhci_cap_regs __iomem *cap_regs;
struct xhci_op_regs __iomem *op_regs;
struct xhci_run_regs __iomem *run_regs;
struct xhci_doorbell_array __iomem *dba;
/* Our HCD's current interrupter register set */
struct xhci_intr_reg __iomem *ir_set;
/* Cached register copies of read-only HC data */
__u32 hcs_params1;
...
spinlock_t lock;
/* packed release number */
u8 sbrn;
u16 hci_version;
...
...
...
};
root hub裝置註冊(三)
drivers/usb/host/xhci-plat.c
drivers/usb/core/hcd.c
drivers/usb/host/xhci.c
drivers/usb/core/hub.c
dwc3_otg_start_host -> dwc3_host_init -> platform_device_add(xhci) -> xhci_plat_probe
xhci->main_hcd = hcd;
usb_add_hcd(hcd, irq, IRQF_SHARED); //roothub對應usb0
usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
hcd->driver->start(hcd) //hc_driver
xhci_run(hcd)
xhci_try_enable_msi(hcd)
hci_setup_msix(xhci)
xhci_irq(hcd)
---------------------------------------------------------------------------------
| xhci_handle_event(xhci) |
| case: TRB_PORT_STATUS |
| handle_port_status(xhci, event); |
| case: TRB_TRANSFER |
| handle_tx_event(xhci, &event->trans_event); |
| usb_hcd_giveback_urb |
| tasklet_schedule(&bh->bh); |
| kick_hub_wq(hub); |
| queue_work(hub_wq, &hub->events) |
| hub_event->port_event->hub_port_connect_change |
| ->hub_port_connect -> usb_new_device(udev); |
----------------------------------------------------------------------------------
register_root_hub(hcd)
usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE)
usb_new_device (usb_dev)
usb_enumerate_device(udev)
announce_device(udev)/* 列印New USB device found*/
device_add(&udev->dev)
DWC3
DWC3:(DesignWare USB 3.0 Controller) 在Android系統中,dwc3通常被用作USB3.0主機控制器,用於與XHCI驅動程式配合使用,控制USB3.0裝置與主機之間的通訊。同時,dwc3還可以與Gadget驅動程式配合使用,將linux裝置轉為USB裝置,實現裝置與主機間的通訊。
dwc3控制器初始化的時候會將控制器設定為USB_DR_MODE_OTG模式,同時呼叫dwc3_host_init和dwc3_gadget_init函式初始化主機模式和裝置模式所需的資源,控制器後續可以動態切換為主機模式和裝置模式。
-> host mode xhci dwc3_host_init()
dwc3 controller -
-> device mode udc dwc3_gadget_init()
dual-role device (DRD) OTG State
enum dwc3_drd_state {
DRD_STATE_UNDEFINED = 0, //put controller and phy in suspend if no cable connected
//pm_runtime_putsync decrease usage_count
DRD_STATE_IDLE,
DRD_STATE_PERIPHERAL,
DRD_STATE_PERIPHERAL_SUSPEND,
DRD_STATE_HOST_IDLE,
DRD_STATE_HOST,
};
dual-role usb control(DR) works on a particular mode
enum usb_dr_mode {
USB_DR_MODE_UNKNOWN,
USB_DR_MODE_HOST,
USB_DR_MODE_PERIPHERAL,
USB_DR_MODE_OTG,
};
狀態的切換透過dwc3_otg_sm_work -> dwc3_otg_start_host/dwc3_otg_start_peripheral
power/supply/qcom/qpnp-smb5.c devm_extcon_dev_register 傳送廣播
static const unsigned int smblib_extcon_cable[] = {
EXTCON_USB,
EXTCON_USB_HOST,
EXTCON_NONE,
};
smblib_notify_device_mode
extcon_set_state_sync(chg->extcon, EXTCON_USB, enable);
smblib_notify_usb_host
extcon_set_state_sync(chg->extcon, EXTCON_USB_HOST, enable);
usb/dwc3/dwc3-msm.c devm_extcon_register_notifier註冊監聽usb狀態變化,接受廣播
mdwc->extcon[idx].vbus_nb.notifier_call = dwc3_msm_vbus_notifier;
extcon_register_notifier(edev, EXTCON_USB, &mdwc->extcon[idx].vbus_nb);
extcon_register_notifier(edev, EXTCON_USB_HOST,&mdwc->extcon[idx].id_nb);
dwc3_msm_vbus_notifier(&mdwc->extcon[idx].vbus_nb,true, edev);
dwc3_msm_id_notifier(&mdwc->extcon[idx].id_nb,true, edev);
DBG-LOG
echo ‘file dwc3-msm.c +p’ > /d/dynamic_debug/control
echo ‘file phy-msm-snps-hs.c +p’ > /d/dynamic_debug/control
echo ‘file phy-msm-qmp.c +p’ > /d/dynamic_debug/control
echo ‘file hub.c +p’ > /d/dynamic_debug/control