📄 udc.patch
字号:
+ /* V_PULSE done => wait VBus (session valid) */+ /* start timer, set state */++ SET_OTG_TIMER_LONG (otg, SRP_DCHRG_V);+ CHANGE_STATE (otg, OTG_STATE_B_SRP_V_DCHRG, pMask);+ }+ break;++ case OTG_STATE_B_SRP_V_DCHRG :++ CHECK_STATE (otg, OTG_STATE_B_SRP_V_DCHRG, pMask);+ if (GOT_EVENT (OTG_INT_TMX, event)) {++ /* V_PULSE done => wait VBus (session valid) */+ /* start timer, set state */++ if (IS_BIT_SET (OTG_STS_SESSVLD, state)) {++ /* Session valid => B_IDLE */++ RES_FLAG (otg, OTG_B_aSSN_REQ);+ reset_srp_conditions (otg);+ CHANGE_STATE (otg, OTG_STATE_B_IDLE, pMask);+ }+ else {+ /* Timer expired => B_SRP_WAIT_VBUS */++ SET_OTG_TIMER_LONG (otg, SRP_WAIT_VRS);+ CHANGE_STATE (otg, OTG_STATE_B_SRP_WAIT_VBUS,+ pMask);+ }+ }+ break;++ case OTG_STATE_B_SRP_WAIT_VBUS :++ CHECK_STATE (otg, OTG_STATE_B_SRP_WAIT_VBUS, pMask);+ if (IS_BIT_SET (OTG_STS_SESSVLD, state)) {++ /* Session valid => B_IDLE */+ /* stop timer */++ RES_FLAG (otg, OTG_B_aSSN_REQ);+ reset_srp_conditions (otg);+ CHANGE_STATE (otg, OTG_STATE_B_IDLE, pMask);+ }+ else if (GOT_EVENT (OTG_INT_TMX, event)) {++ /* VBus TO => B_IDLE */+ /* system notification */++ SET_FLAG (otg, OTG_B_SRP_ERROR);+ RES_FLAG (otg, OTG_B_aSSN_REQ);+ reset_srp_conditions (otg);+ ERR ("SRP: Device Not Responding, giving up\n");+ CHANGE_STATE (otg, OTG_STATE_B_IDLE, pMask);++ /* TODO kboge: system notification */+ /* otg->transceiver.state & OTG_STATE_B_SRP_ERROR */+ }+ break;++ /* unlikely */ default :++ /* something went wrong */++ BUG ();+ break;+ }+}++/**+ * \brief+ * Detect SRP (A-device)+ *+ * Detect a valid completion of a Session Request+ *+ * \param otg OTG controller info+ * \param state actual HW state+ * \param event actual event state+ * \param pMask + *+ * \return 1: detected, 0: idle or still running+ */+inline int detect_srp (struct otg *otg, u32 state, u32 event, u32 *pMask)+{+ int ret = 0;++ switch (otg->transceiver.state) {++ case OTG_STATE_A_IDLE :++ if (IS_BIT_SET (OTG_STS_LST, state)) {++ /* DP pulse detected => A_IDLE_WAIT_DPULSE */+ /* Start timer, set state */++ SET_OTG_TIMER (otg, ASRP_WAIT_MP);+ CHANGE_STATE (otg, OTG_STATE_A_IDLE_WAIT_DP, pMask);+ }+ else if (IS_BIT_SET (OTG_STS_SESSVLD, state)) {++ /* VBus pulse detected => A_IDLE_WAIT_VPULSE */+ /* Start timer, set state */++ SET_OTG_TIMER (otg, ASRP_WAIT_MP);+ CHANGE_STATE (otg, OTG_STATE_A_IDLE_WAIT_VP, pMask);+ }+ break;++ case OTG_STATE_A_IDLE_WAIT_DP :++ CHECK_STATE (otg, OTG_STATE_A_IDLE_WAIT_DP, pMask);+ if (GOT_EVENT (OTG_INT_LSTC, event) &&+ IS_BIT_SET (OTG_STS_LST, state)) {++ /* D pulse changed => restart detection */+ /* Set state */++ reset_timer (otg);+ }+ else if (IS_BIT_RES (OTG_STS_LST, state)) {++ /* DP pulse too short => A_IDLE */+ /* Set state */++ WARN ("short D pulse detected\n");+ CHANGE_STATE (otg, OTG_STATE_A_IDLE, pMask);+ }+ else if (GOT_EVENT (OTG_INT_TMX, event)) {++ /* DP pulse still active => A_IDLE_WAIT_DV */+ /* Start timer, Set state */++ SET_OTG_TIMER_LONG (otg, ASRP_WAIT_DV);+ CHANGE_STATE (otg, OTG_STATE_A_IDLE_WAIT_DV, pMask);+ }+ break;++ case OTG_STATE_A_IDLE_WAIT_VP :++ CHECK_STATE (otg, OTG_STATE_A_IDLE_WAIT_VP, pMask);+ if (IS_BIT_RES (OTG_STS_SESSVLD, state)) {++ /* VBusP pulse too short => A_IDLE */+ /* Set state */++ WARN ("short VBus pulse detected\n");+ CHANGE_STATE (otg, OTG_STATE_A_IDLE, pMask);+ }+ else if (GOT_EVENT (OTG_INT_TMX, event)) {++ /* VBus pulse still active => A_IDLE_WAIT_DV */+ /* Start timer, set state */++ SET_OTG_TIMER_LONG (otg, ASRP_WAIT_DV);+ CHANGE_STATE (otg, OTG_STATE_A_IDLE_WAIT_DV, pMask);+ }+ break;++ case OTG_STATE_A_IDLE_WAIT_DV :++ CHECK_STATE (otg, OTG_STATE_A_IDLE_WAIT_DV, pMask);+ if (GOT_EVENT (OTG_INT_TMX, event)) {++ /* SRP detected => ready to activate the bus */+ /* Set state */++ ret = 1;+ CHANGE_STATE (otg, OTG_STATE_A_IDLE, pMask);+ VDBG (" OTG event: SRP detected\n");++ /* TODO kboge: pulses that are too long will be accepted */+ }+ break;++ /* unlikely */ default :++ /* something went wrong */++ BUG ();+ break;+ }+ return (ret);+}++/**+ * \brief+ * OTG state change+ *+ * Basic state machine controlling the OTG states described in the+ * OTG supplement to the USB 2.0 spec, section 6.8.+ * This can be called either from the driver ISR or as response to+ * an application request, where application does not neccessarily+ * mean a user space application, more likely this routine will be+ * called from another kernel driver (gadget or device drivers).+ *+ * \param otg OTG controller info+ * \param event_code event that requested a state change+ * \param pEvt_mask+ *+ * \return events that were not handled here+ */+u32 otg_change_state (struct otg *otg, u32 _event, u32 *pEvt_mask)+{+ u32 event_code = _event;+ u32 uoc_status = get_status (otg);++ if (GOT_EVENT (OTG_A_CLR_ERR, event_code) &&+ ((otg->transceiver.state & OTG_STATE_MASK) !=+ OTG_STATE_A_VBUS_ERR)) {++ /* This request doesn't make sense: clear it */++ RES_FLAG (otg, OTG_A_CLR_ERR);+ RES_EVENT (OTG_A_CLR_ERR, event_code);+ }+ + if (GOT_EVENT (OTG_GADGET_READY, event_code)) {++ /* Switch from "NO_B_DEVICE" states to normal operation or */+ /* deactivate operations in case gadget was unloaded */++ if ((otg->transceiver.state & OTG_STATE_MASK) !=+ OTG_STATE_UNDEFINED) {++ CHANGE_STATE (otg, OTG_STATE_UNDEFINED, pEvt_mask);+ }+ }++ if ((OTG_INT_TMX & event_code) && otg_tmr_high_count) {++ /* a long timer is running : decrement the high part */++ restart_timer (otg);+ otg_tmr_high_count--;+ RES_EVENT (OTG_INT_TMX, event_code);+ }++ if (((otg->transceiver.state & OTG_STATE_MASK) !=+ OTG_STATE_A_SUSPEND) &&+ ((otg->transceiver.state & OTG_STATE_MASK) !=+ OTG_STATE_B_HOST) &&+ (GOT_EVENT (OTG_INT_DPRC, event_code))) {++ /* Host drives port reset => reset bHNP flag */++ if (is_b_hnp_enabled (otg)) {+ reset_b_hnp_enable (otg);+ }+ RES_EVENT (OTG_INT_DPRC, event_code);+ }++ if (GOT_EVENT (OTG_INT_HNPFC, event_code)) {++ /* HNP feature changed, just report it to the system */++ RES_EVENT (OTG_INT_HNPFC, event_code);+#ifdef DEBUG+ if (IS_BIT_SET (OTG_STS_HNPSTS, uoc_status)) {++ /* status change: only SET_FEATURE is possible */+ /* flags cannot be reset here */++ otg->transceiver.params |= uoc_status &+ OTG_STS_HNPSTS;+ }+ else {++ /* status reset: this must have been a */+ /* port reset or session end */++ otg->transceiver.params &= ~OTG_STS_HNPSTS;+ }+ DBG (" HNP feature change (%08x)\n",+ (OTG_STS_HNPSTS & uoc_status));+ if (IS_BIT_SET (OTG_STS_HNP_EN, uoc_status)) {}+ if (IS_BIT_SET (OTG_STS_HNP_SUPP, uoc_status)) {}+ if (IS_BIT_SET (OTG_STS_HNP_ALTSUPP, uoc_status)) {}+#endif /* DEBUG */++ /* TODO kboge: system notification */+ /* IS_BIT_SET (OTG_STS_HNPSTS, uoc_status) */+ }++#ifdef VERBOSE+/* if (GOT_EVENT (OTG_INT_LSTC, event_code)) { */++ /* Line state changed, just report it to the system */++/* RES_EVENT (OTG_INT_LSTC, event_code); */+/* VDBG (" line state: %2x\n", */+/* ((OTG_STS_LST & uoc_status) >> 4)); */+/* } */++ if (GOT_EVENT (OTG_INT_PSPDC, event_code)) {++ /* Port speed changed, just report it to the system */++ RES_EVENT (OTG_INT_PSPDC, event_code);++ if (OTG_STS_PCON & uoc_status) {++ if (!(OTG_STS_PSPD & uoc_status)) {+ DBG (" port is in HIGH_SPEED\n");+ }+ else if (OTG_STS_PSPD_LS & uoc_status) {+ DBG (" port is in LOW_SPEED\n");+ }+ else {+ DBG (" port is in FULL_SPEED\n");+ }+ }+ }+#endif /* VERBOSE */++ if (event_code) {++ DBG ("OTG-state change, event code: %08x\n",+ otg->transceiver.params | event_code);++#ifdef DEBUG+ if (GOT_EVENT (OTG_INT_OCD, event_code)) {++ /* Port overcurrent detected, just report it here */++ if (OTG_STS_OC & uoc_status) {+ DBG (" over-current detected\n");+ }+ else {+ DBG (" spurious over-current event\n");+ }+ }+ if (GOT_EVENT (OTG_INT_PSC, event_code)) {++ /* Port suspend state changed, just report it */++ if (OTG_STS_PSUS & uoc_status) {+ DBG (" port is suspended\n");+ }+ else {+ DBG (" port is active\n");+ }+ }+ if (GOT_EVENT (OTG_INT_PCC, event_code)) {++ /* Port connect state changed, just report it */++ if (OTG_STS_PCON & uoc_status) {+ DBG (" port is connected\n");+ }+ else {+ DBG (" port is not connected\n");+ }+ }+#endif /* DEBUG */++ do switch (otg->transceiver.state & OTG_STATE_MASK) {++ /* STATE_UNDEFINED (yet): init state, 1st time after loading */+ /* ========================================================= */++ case OTG_STATE_UNDEFINED :++ CHECK_STATE (otg, OTG_STATE_UNDEFINED, pEvt_mask);++ if (IS_FLAG_RES (otg, OTG_FLAGS_ACTIV)) {++ /* seems to be the first time: let it run ! */++ SET_FLAG (otg, OTG_FLAGS_ACTIV);+ }++ /* muxer is still neutral */++ RES_EVENT ((OTG_INT_IDC | OTG_INT_TMX), event_code);++ if (IS_FLAG_RES (otg, OTG_GADGET_READY)) {++ /* NOT_READY (substate): gadget drivers not ready */+ /* ============================================== */+ /* */+ /* check ID pin and enable host as needed */++ if (IS_BIT_RES (OTG_STS_ID, uoc_status)) {++ /* ID pin connected: A-device */+ /* muxer -> host */++ if (OTG_STATE_NO_B_DEVICE_A !=+ otg->transceiver.state) {+ CHANGE_STATE (otg,+ OTG_STATE_NO_B_DEVICE_A,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -