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