当手机设备连接PC 电脑时,手机作为peripheral 模式,其开机被枚举的过程大概分为三步:
一次完整的开机 ipc log 如下:
// (1)检测usb cable 插入;
[ 5.862865121] FF extcon idx 0 ?
[ 5.868430850] dwc3_msm_vbus_notifier: edev:c440000.qcom,spmi:qcom,pm8150b@2:qcom,usb-pdphy@1700
[ 5.879845642] dwc3_resume_work: resume_work: ext_idx:0
[ 5.879848403] dwc3_resume_work: edev:c440000.qcom,spmi:qcom,pm8150b@2:qcom,usb-pdphy@1700
[ 5.879853142] FF ss_flag 8 ?
[ 5.879855798] dwc3_resume_work: max_speed:6 hw_supp_speed:6 override_speed:0
[ 5.879857882] FF speed 6 ?
[ 5.879863246] dwc3_ext_event_notify: enter: mdwc->inputs:1 hs_phy_flags:0
[ 5.879865121] dwc3_ext_event_notify: XCVR: ID set
[ 5.879866528] dwc3_ext_event_notify: XCVR: BSV set
[ 5.879867725] dwc3_ext_event_notify: XCVR: SUSP clear
[ 5.879868871] dwc3_ext_event_notify: eud: state:0 active:0 hs_phy_flags:0x0
[ 5.879870642] dwc3_ext_event_notify: exit: mdwc->inputs:3
[ 5.891133663] FF undefined 0 ?
[ 5.891135850] FF Exit UNDEF 0 ?
[ 5.920572673] FF RT Res 0 ?
[ 5.920576684] FF bus_vote_start 1 ?
[ 5.920902361] FF bus_vote_end 1 ?
[ 5.933785955] FF ss_flag 8 ?
[ 6.020502518] FF Ctl Res 0 ?
[ 6.020506788] FF BIDLE gsync 1 ?
[ 6.020508872] FF StrtGdgt gsync 2 ?
[ 6.021841059] FF VbusSess 1 ?
[ 6.021857205] FF StopGdgt psync 1 ?
[ 6.021862778] FF peripheral 0 ?
// (2)开启UDC;
[14.053613792] FF Gadgetstart 0 ?
[14.053622230] FF Pullup gsync 1 ?
[14.232620824] FF EP0 is not in SETUP phase 0 ?
[14.246319209] FF run_stop 1 ?
[14.276135251] FF __Gadgetstart 0 ?
[14.280788480] FF UnmaskINT 0 ?
[14.287081970] FF Pullup put 0 ?
// (3)接收主机的枚举消息,并回应。
[14.313223949] FF BUS RESET 0 ?
[14.335765460] FF currentDraw 100 ?
[14.360327439] FF CONNECT DONE 4 ?
底层识别到 usb cable 插入,产生通知事件到mdwc
,mdwc 开启peripheral 模式:
# cat /sys/kernel/debug/ipc_logging/a600000.dwc3/log
[ 21.782829232/ 0x21faefc3] FF extcon idx 0 ?
[ 21.782832305/ 0x21faeffe] dwc3_msm_vbus_notifier: edev:c440000.qcom,spmi:qcom,pm8150b@2:qcom,usb-pdphy@1700 //pdphy(qcom,usb-pdphy@1700) 挂在pm(qcom,pm8150b@2)下,pm 挂在spmi(c440000.qcom,spmi)下
[ 21.782944857/ 0x21faf870] dwc3_resume_work: edev:c440000.qcom,spmi:qcom,pm8150b@2:qcom,usb-pdphy@1700
[ 21.783028295/ 0x21fafeb2] FF speed 6 ?
[ 21.783039284/ 0x21faff84] FF cc_state 2 ?
[ 21.784039961/ 0x21fb4a92] FF undefined 0 ?
[ 21.784050795/ 0x21fb4b61] FF Exit UNDEF 0 ?
[ 21.784074388/ 0x21fb4d27] FF RT Res 0 ?
[ 21.784093503/ 0x21fb4e95] FF bus_vote_start 1 ?
[ 21.784613555/ 0x21fb7597] FF bus_vote_end 1 ?
[ 21.860795639/ 0x2211c73f] FF Ctl Res 0 ?
[ 21.860818451/ 0x2211c8f4] FF BIDLE gsync 1 ?
[ 21.860829493/ 0x2211c9c8] FF StrtGdgt gsync 2 ?
[ 21.862160534/ 0x22122d9d] FF VbusSess 1 ?
[ 21.862372826/ 0x22123d89] FF StopGdgt psync 1 ?
[ 21.862392409/ 0x22123f01] FF peripheral 0 ?
\drivers\usb\pd\qpnp-pdphy.c 、policy_engine.c
当 pmic
子系统发生 psy change
事件,会 notify
各个子系统,包括 usbpd
:
== pd->psy_nb.notifier_call = psy_changed; power_supply_reg_notifier(&pd->psy_nb);
== psy_changed(); //发生了power supply changed notify
== queue_work(pd->wq, &pd->psy_chg_work);
== psy_changed_notifier_work();
== usbpd_process_typec_mode(pd, typec_mode);
== kick_sm(pd, 0);
== queue_work(pd->wq, &pd->sm_work);
== usbpd_sm();
== state_handlers[pd->current_state].handle_state(pd, rx_msg);
== enter_state_snk_startup();
== start_usb_peripheral(pd);
== extcon_set_state_sync(pd->extcon, EXTCON_USB, 1);
在 usbpd 中,会创建一个extcon(依赖于一个设备节点),然后其他子系统可以引用该设备节点,并使用该 extcon。
/*
* associate extcon with the parent dev as it could have a DT
* node which will be useful for extcon_get_edev_by_phandle()
*/
pd->extcon = devm_extcon_dev_allocate(parent, usbpd_extcon_cable);
if (IS_ERR(pd->extcon)) {
usbpd_err(&pd->dev, "failed to allocate extcon device\n");
ret = PTR_ERR(pd->extcon);
goto put_psy;
}
ret = devm_extcon_dev_register(parent, pd->extcon);
if (ret) {
usbpd_err(&pd->dev, "failed to register extcon device\n");
goto put_psy;
}
== dwc3_msm_vbus_notifier(); dbg_event(0xFF, "extcon idx", enb->idx);
== queue_work(mdwc->dwc3_wq, &mdwc->resume_work);
== dwc3_resume_work();
== dwc3_msm_resume();
== dwc3_ext_event_notify();
== queue_delayed_work(mdwc->sm_usb_wq, &mdwc->sm_work, 0);
== dwc3_otg_sm_work(struct work_struct *w);
== dwc3_otg_sm_work(struct work_struct *w);
== dwc3_otg_start_peripheral(mdwc, 1);
== dwc3_override_vbus_status(mdwc, true);
== usb_phy_notify_connect(mdwc->hs_phy[0], USB_SPEED_HIGH);
== usb_gadget_vbus_connect(&dwc->gadget);
== gadget->ops->vbus_session(gadget, 1);
== dwc3_gadget_vbus_session(struct usb_gadget *_gadget, int is_active);
== dwc3_gadget_run_stop_util(dwc);
== dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend);
== __dwc3_gadget_start(struct dwc3 *dwc);
== dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg);
== __dwc3_gadget_ep_enable(dep, DWC3_DEPCFG_ACTION_INIT);
上层 init 进程启动,并开启UDC。
echo "a600000.dwc3" > UDC
[ 39.641421266/ 0x366af229] FF Gadgetstart 0 ?
[ 39.641428349/ 0x366af2b1] FF Pullup gsync 1 ?
[ 39.696342724/ 0x367b0946] FF EP0 is not in SETUP phase 0 ?
[ 39.696351162/ 0x367b09e7] FF run_stop 1 ?
[ 39.696385433/ 0x367b0c79] FF __Gadgetstart 0 ?
[ 39.701054443/ 0x367c6aa6] FF UnmaskINT 0 ?
[ 39.701113610/ 0x367c6f16] FF Pullup put 0 ?
(1)绑定gadget 设备与驱动;
(2)start gadget;
(3)pullup gadget。
== gadget_dev_desc_UDC_store(); // \drivers\usb\gadget\configfs.c
== usb_gadget_probe_driver() // \drivers\usb\gadget\udc\core.c
== udc_bind_to_driver();
== driver->bind(udc->gadget, driver);
== configfs_composite_bind(); //绑定usb_gadget 与usb_gadget_driver
== usb_add_function(c, f); //添加function,执行function 的函数
== usb_gadget_udc_start(udc);
== udc->gadget->ops->udc_start(udc->gadget, udc->driver);
== dwc3_gadget_start();
== request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt, IRQF_SHARED, "dwc3", dwc->ev_buf);
//注册dwc3中断,当host发消息过来时,触发中断函数
== usb_udc_connect_control(struct usb_udc *udc)
== usb_gadget_connect(struct usb_gadget *gadget)
== gadget->ops->pullup(gadget, 1);
== dwc3_gadget_pullup(struct usb_gadget *g, int is_on);
== dwc3_gadget_run_stop_util();
== dwc3_gadget_run_stop(dwc, true, false);
== __dwc3_gadget_start(dwc); //enable端点传输
== __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action) // initializes a hw endpoint
接收到host 发来的消息,正式开始枚举。
[ 39.759129391/ 0x368d6e47] FF BUS RESET 0 ?
[ 39.759165954/ 0x368d7104] FF currentDraw 100 ?
[ 39.759205954/ 0x368d7403] dwc3_stop_active_transfers: START
[ 39.759213141/ 0x368d748d] dwc3_stop_active_transfers: DONE
[ 39.764147829/ 0x368ee6a7] FF CONNECT DONE
当端点 enable 之后,即可进行数据传输。
(1)对端点的处理中断;
(2)对设备的处理中断。
== dwc3_thread_interrupt(); //中断产生(host发消息过来),调用回调函数
== dwc3_process_event_buf(); //处理中断事件buf(dwc3_event_buffer )
== dwc3_process_event_entry(); trace_dwc3_event(event->raw, dwc);
== dwc3_endpoint_interrupt(); //对端点处理的中断
== dwc3_ep0_interrupt(); //控制传输if (epnum == 0 || epnum == 1)
== dwc3_ep0_xfer_complete(); //event->endpoint_event = DWC3_DEPEVT_XFERCOMPLETE
== dwc3_ep0_inspect_setup(); //dwc->ep0state = EP0_SETUP_PHASE
//dwc3_ep0_std_request() == dwc3_ep0_set_config()
== dwc3_ep0_delegate_req();
== dwc->gadget_driver->setup(&dwc->gadget, ctrl);
== configfs_composite_setup();
== composite_setup(); //setup 包括获取描述符,配置,地址等操作
== set_config(); //ctrl->bRequest = USB_REQ_SET_CONFIGURATION
== dwc3_gadget_endpoint_transfer_complete(); //传输完成,返回给function(interface)
== dwc3_gadget_endpoint_trbs_complete();
== dwc3_gadget_ep_cleanup_completed_requests()
== dwc3_gadget_giveback(); //数据返回
== dwc3_gadget_del_and_unmap_request(); trace_dwc3_gadget_giveback(req);
== usb_gadget_giveback_request() trace_usb_gadget_giveback_request(ep, req, 0);// give the request back to the gadget layer
== req->complete(ep, req);
== ffs_ep0_complete() // function的完成函数
== dwc3_gadget_interrupt(dwc, &event->devt); //对gadget设备的中断
== dwc3_gadget_reset_interrupt(); dbg_event(0xFF, "BUS RESET", dwc->gadget.speed);
== usb_gadget_vbus_draw(&dwc->gadget, 2); trace_usb_gadget_vbus_draw(gadget, ret);
== gadget->ops->vbus_draw(gadget, mA);
== dwc3_gadget_vbus_draw(); dbg_event(0xFF, "currentDraw", mA);
== dwc3_notify_event(dwc, DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT, 0);
== dwc3_gadget_conndone_interrupt(); dbg_event(0xFF, "CONNECT DONE", speed);
其中,对端点的处理中断:
\drivers\usb\dwc3\ep0.c
static void dwc3_ep0_xfer_complete(struct dwc3 *dwc,
const struct dwc3_event_depevt *event)
{
struct dwc3_ep *dep = dwc->eps[event->endpoint_number];
switch (dwc->ep0state) { //判断ep0 的state
case EP0_SETUP_PHASE:
dwc3_ep0_inspect_setup(dwc, event);
break;
case EP0_DATA_PHASE:
dwc3_ep0_complete_data(dwc, event);
break;
case EP0_STATUS_PHASE:
dwc3_ep0_complete_status(dwc, event);
break;
default:
WARN(true, "UNKNOWN ep0state %d\n", dwc->ep0state);
}
}
setup 阶段,会响应 host 的各种 req:
== configfs_composite_setup();
== composite_setup(); //setup 包括获取描述符,配置,地址等操作
== set_config(); //ctrl->bRequest = USB_REQ_SET_CONFIGURATION
/*
* Standard requests, for the bRequest field of a SETUP packet.
*
* These are qualified by the bRequestType field, so that for example
* TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved
* by a GET_STATUS request.
*/
#define USB_REQ_GET_STATUS 0x00
#define USB_REQ_CLEAR_FEATURE 0x01
#define USB_REQ_SET_FEATURE 0x03
#define USB_REQ_SET_ADDRESS 0x05
#define USB_REQ_GET_DESCRIPTOR 0x06
#define USB_REQ_SET_DESCRIPTOR 0x07
#define USB_REQ_GET_CONFIGURATION 0x08
#define USB_REQ_SET_CONFIGURATION 0x09
#define USB_REQ_GET_INTERFACE 0x0A
#define USB_REQ_SET_INTERFACE 0x0B
#define USB_REQ_SYNCH_FRAME 0x0C
#define USB_REQ_SET_SEL 0x30
#define USB_REQ_SET_ISOCH_DELAY 0x31