From: Li Jun <[email protected]>

This patch adds OTG status selector request sending function, can be called
by HNP polling timer function after OTG port is in host state.

Signed-off-by: Li Jun <[email protected]>
---
 drivers/usb/common/usb-otg-fsm.c |   47 ++++++++++++++++++++++++++++++++++++++
 include/linux/usb/otg-fsm.h      |    9 ++++++++
 2 files changed, 56 insertions(+)

diff --git a/drivers/usb/common/usb-otg-fsm.c b/drivers/usb/common/usb-otg-fsm.c
index 141c8d7..1c56739 100644
--- a/drivers/usb/common/usb-otg-fsm.c
+++ b/drivers/usb/common/usb-otg-fsm.c
@@ -366,3 +366,50 @@ int otg_statemachine(struct otg_fsm *fsm)
        return state_changed;
 }
 EXPORT_SYMBOL_GPL(otg_statemachine);
+
+/*
+ * Called by HNP polling timer function to send HNP polling request
+ * return host request flag if success, otherwise error code.
+ */
+int otg_hnp_polling(struct otg_fsm *fsm)
+{
+       struct usb_device *udev;
+       u16 host_req_flag;
+       int retval;
+       enum usb_otg_state state = fsm->otg->phy->state;
+
+       if (state != OTG_STATE_A_HOST && state != OTG_STATE_B_HOST)
+               return -EINVAL;
+
+       udev = usb_hub_find_child(fsm->otg->host->root_hub, 1);
+       if (!udev) {
+               dev_err(fsm->otg->host->controller,
+                       "no usb dev connected, can't start HNP polling\n");
+               return -ENODEV;
+       }
+
+       /* Get host request flag from connected USB device */
+       retval = usb_get_status(udev, USB_RECIP_DEVICE, OTG_STS_SELECTOR,
+                                                               &host_req_flag);
+       if (retval) {
+               dev_err(&udev->dev,
+                       "ERR in HNP polling = %d, stop HNP polling\n", retval);
+               return retval;
+       }
+
+       if ((host_req_flag & 0xff) == HOST_REQUEST_FLAG) {
+               if (state == OTG_STATE_A_HOST)
+                       fsm->a_bus_req = 0;
+               else if (state == OTG_STATE_B_HOST)
+                       fsm->b_bus_req = 0;
+               retval = HOST_REQUEST_FLAG;
+       } else if ((host_req_flag & 0xff) == 0) {
+               /* Continue polling */
+               otg_add_timer(fsm, HNP_POLLING);
+       } else {
+               dev_err(&udev->dev, "host request flag is invalid\n");
+               retval = -EINVAL;
+       }
+       return retval;
+}
+EXPORT_SYMBOL_GPL(otg_hnp_polling);
diff --git a/include/linux/usb/otg-fsm.h b/include/linux/usb/otg-fsm.h
index c1da7c5..6d3514f 100644
--- a/include/linux/usb/otg-fsm.h
+++ b/include/linux/usb/otg-fsm.h
@@ -40,6 +40,14 @@
 #define PROTO_HOST     (1)
 #define PROTO_GADGET   (2)
 
+#define OTG_STS_SELECTOR       0xF000  /* OTG status selector, according to
+                                        * OTG and EH 2.0 Charpter 6.2.3
+                                        * Table:6-4
+                                        */
+#define HOST_REQUEST_FLAG      1       /* Host request flag, according to
+                                        * OTG and EH 2.0 Charpter 6.2.3
+                                        * Table:6-5
+                                        */
 enum otg_fsm_timer {
        /* Standard OTG timers */
        A_WAIT_VRISE,
@@ -240,6 +248,7 @@ static inline int otg_start_gadget(struct otg_fsm *fsm, int 
on)
        return fsm->ops->start_gadget(fsm, on);
 }
 
+int otg_hnp_polling(struct otg_fsm *fsm);
 int otg_statemachine(struct otg_fsm *fsm);
 
 #endif /* __LINUX_USB_OTG_FSM_H */
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to