[PATCH v2 2/3] usb: common: otg-fsm: add HNP polling request sending funciton

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Li Jun <b47624@xxxxxxxxxxxxx>

This patch adds OTG status selector request sending function, can be used
to poll peripheral if it wants to be host after OTG port is in host state.

Signed-off-by: Li Jun <b47624@xxxxxxxxxxxxx>
---
 drivers/usb/common/usb-otg-fsm.c |   55 ++++++++++++++++++++++++++++++++++++++
 include/linux/usb/otg-fsm.h      |    9 +++++++
 2 files changed, 64 insertions(+)

diff --git a/drivers/usb/common/usb-otg-fsm.c b/drivers/usb/common/usb-otg-fsm.c
index 141c8d7..384cdaf 100644
--- a/drivers/usb/common/usb-otg-fsm.c
+++ b/drivers/usb/common/usb-otg-fsm.c
@@ -366,3 +366,58 @@ int otg_statemachine(struct otg_fsm *fsm)
 	return state_changed;
 }
 EXPORT_SYMBOL_GPL(otg_statemachine);
+
+/*
+ * Called by host to poll peripheral if it wants to be host after OTG port
+ * is in host state.
+ * return host request flag if success, otherwise error code.
+ */
+int otg_hnp_polling(struct otg_fsm *fsm)
+{
+	struct usb_device *udev;
+	u8 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_control_msg(udev,
+				usb_rcvctrlpipe(udev, 0),
+				USB_REQ_GET_STATUS,
+				USB_DIR_IN | USB_RECIP_DEVICE,
+				0,
+				OTG_STS_SELECTOR,
+				&host_req_flag,
+				1,
+				USB_CTRL_GET_TIMEOUT);
+	if (retval == 1) {
+		if (host_req_flag == 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 == 0) {
+			/* Continue polling */
+			otg_add_timer(fsm, HNP_POLLING);
+			retval = 0;
+		} else {
+			dev_err(&udev->dev, "host request flag is invalid\n");
+			retval = -EINVAL;
+		}
+	} else {
+		dev_err(&udev->dev, "Get one byte OTG status failed\n");
+		retval = -EIO;
+	}
+	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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux