Introduce otg_version field in usb_gadget struct. UDC can advertise OTG spec version compatibility by setting otg_version field appropriately. Gadget drivers fill the bcdOTG field in OTG descriptor based on UDC's OTG version. Add sysfs file for host_request and UDC returns the same when HNP polling request arrives from the host. Signed-off-by: Pavankumar Kondeti <pkondeti@xxxxxxxxxxxxxx> --- This patch only modifies gadget zero. But the final patch will modify all the gadget drivers. .../testing/sysfs-devices-platform-_UDC_-gadget | 14 ++++++++++++ drivers/usb/gadget/composite.c | 23 ++++++++++++++++++++ drivers/usb/gadget/zero.c | 3 ++ include/linux/usb/gadget.h | 21 ++++++++++++++++++ 4 files changed, 61 insertions(+), 0 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-devices-platform-_UDC_-gadget b/Documentation/ABI/testing/sysfs-devices-platform-_UDC_-gadget index d548eaa..9c622e4 100644 --- a/Documentation/ABI/testing/sysfs-devices-platform-_UDC_-gadget +++ b/Documentation/ABI/testing/sysfs-devices-platform-_UDC_-gadget @@ -19,3 +19,17 @@ Description: Possible values are: 1 -> ignore the FUA flag 0 -> obey the FUA flag + +What: /sys/devices/platform/_UDC_/gadget/host_request +Date: December 2010 +Contact: Pavan Kondeti <pkondeti@xxxxxxxxxxxxxx> +Description: + OTG 2.0 compliant host keeps polling OTG2.0 peripheral + for host role. Set host_request flag, which tells host + to give up the host role to peripheral. + + 1 -> host role is requested + 0 -> no effect (automatically cleared upon reset/disconnect) + + (_UDC_ is the name of the USB Device Controller driver) + diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 77cabcb..f3a2023 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -978,6 +978,7 @@ static void composite_disconnect(struct usb_gadget *gadget) struct usb_composite_dev *cdev = get_gadget_data(gadget); unsigned long flags; + gadget->host_request = 0; /* REVISIT: should we have config and device level * disconnect callbacks? */ @@ -1003,6 +1004,23 @@ static ssize_t composite_show_suspended(struct device *dev, static DEVICE_ATTR(suspended, 0444, composite_show_suspended, NULL); +static ssize_t composite_set_host_request(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct usb_gadget *gadget = dev_to_usb_gadget(dev); + int value; + + if (sscanf(buf, "%d", &value) != 1) + return -EINVAL; + + gadget->host_request = !!value; + return count; + +} + +static DEVICE_ATTR(host_request, S_IWUSR, NULL, composite_set_host_request); + static void composite_unbind(struct usb_gadget *gadget) { @@ -1047,6 +1065,7 @@ composite_unbind(struct usb_gadget *gadget) kfree(cdev->req->buf); usb_ep_free_request(gadget->ep0, cdev->req); } + device_remove_file(&gadget->dev, &dev_attr_host_request); device_remove_file(&gadget->dev, &dev_attr_suspended); kfree(cdev); set_gadget_data(gadget, NULL); @@ -1158,6 +1177,10 @@ static int composite_bind(struct usb_gadget *gadget) if (status) goto fail; + status = device_create_file(&gadget->dev, &dev_attr_host_request); + if (status) + DBG(cdev, "unable to create host_request sysfs file\n"); + INFO(cdev, "%s ready\n", composite->name); return 0; diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 6d16db9..b4fb719 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -293,6 +293,9 @@ static int __init zero_bind(struct usb_composite_dev *cdev) setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev); + if (gadget_is_otg2(cdev->gadget)) + otg_descriptor.bcdOTG = __constant_cpu_to_le16(0x0200); + /* Register primary, then secondary configuration. Note that * SH3 only allows one config... */ diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 006412c..b891257 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -443,6 +443,8 @@ struct usb_gadget_ops { * operation. If it does, the gadget driver must also support both. * @is_otg: True if the USB device port uses a Mini-AB jack, so that the * gadget driver must provide a USB OTG descriptor. + * @otg_version: UDC OTG version based on which gadget driver fills the + * bcdOTG field in a USB OTG descriptor. * @is_a_peripheral: False unless is_otg, the "A" end of a USB cable * is in the Mini-AB jack, and HNP has been used to switch roles * so that the "A" device currently acts as A-Peripheral, not A-Host. @@ -452,6 +454,7 @@ struct usb_gadget_ops { * only supports HNP on a different root port. * @b_hnp_enable: OTG device feature flag, indicating that the A-Host * enabled HNP support. + * @host_request: A Flag, indicating that user wishes to take the host role. * @name: Identifies the controller hardware type. Used in diagnostics * and sometimes configuration. * @dev: Driver model state for this abstract device. @@ -482,10 +485,14 @@ struct usb_gadget { enum usb_device_speed speed; unsigned is_dualspeed:1; unsigned is_otg:1; + u16 otg_version; +#define UDC_OTG1 0x0000 +#define UDC_OTG2 0x0001 unsigned is_a_peripheral:1; unsigned b_hnp_enable:1; unsigned a_hnp_support:1; unsigned a_alt_hnp_support:1; + unsigned host_request:1; const char *name; struct device dev; }; @@ -537,6 +544,20 @@ static inline int gadget_is_otg(struct usb_gadget *g) } /** + * gadget_is_otg2 - return true if UDC is compliant to OTG 2.0 + * @g: controller that might have a Mini-AB/Micro-AB connector + * + */ +static inline int gadget_is_otg2(struct usb_gadget *g) +{ +#ifdef CONFIG_USB_OTG + return g->otg_version && UDC_OTG2; +#else + return 0; +#endif +} + +/** * usb_gadget_frame_number - returns the current frame number * @gadget: controller that reports the frame number * -- 1.7.1 -- Sent by a consultant of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum. -- 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