summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvinash Kumar <avinash.kumar@stericsson.com>2012-02-14 14:33:12 +0530
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-05-22 11:03:18 +0200
commit56d0696232fa2ba60006fcd05888e933ef9dc085 (patch)
tree2b37ce31e915e9299d248fdd487daaab1bbd16e0
parentbdb74d8442ca934d2a06a35379cd5315d76c7888 (diff)
USB: USB Electrical Test Mode Support
Added the Test device VID/PID in TPL list for OTG 2.0 Removed the is_host_active check while setting the test mode. OTG Test Mode support is added.An OTG device shall support the test device that initiates these test modes. Upon enumeration by the host, the test device presents a VID/PID pair that defines a test mode or operation to execute. Upon enumerating the test device with VID of 0x1A0A, the Targeted Host shall perform the following operations based on the PID presented. PID Test Mode 0x0101 Test_SE0_NAK 0x0102 Test_J 0x0103 Test_K 0x0104 Test_Packet 0x0105 Reserved. 0x0106 HS_HOST_PORT_SUSPEND_RESUME 0x0107 SINGLE_STEP_GET_DEV_DESC 0x0108 SINGLE_STEP_ GET_DEV_DESC_DATA ST-Ericsson ID: 401192 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: STETL-FOSS-OUT-10054 Change-Id: I63525228da242419ceb54198f117795bf44df483 Signed-off-by: Avinash Kumar <avinash.kumar@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/48813 Reviewed-by: Praveena NADAHALLY <praveen.nadahally@stericsson.com> Reviewed-by: QABUILD Reviewed-by: QATEST
-rw-r--r--drivers/usb/core/hub.c95
-rw-r--r--drivers/usb/core/otg_whitelist.h68
-rw-r--r--drivers/usb/gadget/Kconfig11
-rw-r--r--drivers/usb/musb/musb_virthub.c2
4 files changed, 175 insertions, 1 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index abb0084795c..f4038c53b61 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -3569,6 +3569,101 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
if (status)
dev_dbg(hub_dev, "%dmA power budget left\n", status);
+#ifdef CONFIG_USB_OTG_20
+
+ u16 idVendor = le16_to_cpu(udev->descriptor.idVendor);
+ if (idVendor == USB_OTG_TEST_MODE_VID) {
+ u16 wValue, typeReq, wIndex;
+ u32 set_feature = 0;
+ int err = 0;
+ struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+ u16 idProduct = le16_to_cpu(
+ udev->descriptor.idProduct);
+ /* Convert the Test Mode Request
+ * to control request
+ */
+ wValue = USB_PORT_FEAT_TEST;
+ typeReq = SetPortFeature;
+ wIndex = 1;
+
+ switch (idProduct) {
+ case USB_OTG_TEST_SE0_NAK_PID:
+ wIndex |= USB_OTG_TEST_SE0_NAK << 8;
+ set_feature = 1;
+ break;
+ case USB_OTG_TEST_J_PID:
+ wIndex |= USB_OTG_TEST_J << 8;
+ set_feature = 1;
+ break;
+ case USB_OTG_TEST_K_PID:
+ wIndex |= USB_OTG_TEST_K << 8;
+ set_feature = 1;
+ break;
+ case USB_OTG_TEST_PACKET_PID:
+ wIndex |= USB_OTG_TEST_PACKET << 8;
+ set_feature = 1;
+ break;
+ case USB_OTG_TEST_HS_HOST_PORT_SUSPEND_RESUME_PID:
+ /* Sleep for 15 sec. Suspend
+ * for 15 Sec, Then Resume
+ */
+ ssleep(15);
+
+ err = usb_port_suspend(udev,
+ PMSG_SUSPEND);
+ if (err < 0) {
+ dev_err(&udev->dev, "OTG TEST_MODE:"
+ "Suspend Fail, %d\n", err);
+ goto loop_disable;
+ }
+ ssleep(15);
+ err = usb_port_resume(udev, PMSG_RESUME);
+ if (err < 0) {
+ dev_err(&udev->dev,
+ "can't resume for"
+ "OTG TEST_MODE: %d\n", err);
+ goto loop_disable;
+ }
+ break;
+ case USB_OTG_TEST_SINGLE_STEP_GET_DEV_DESC_PID:
+ /* Sleep for 15 Sec. Issue the GetDeviceDescriptor */
+ ssleep(15);
+ err = usb_get_device_descriptor(udev,
+ sizeof(udev->descriptor));
+ if (err < 0) {
+ dev_err(&udev->dev, "can't re-read"
+ "device descriptor for "
+ "OTG TEST MODE: %d\n", err);
+ goto loop_disable;
+ }
+ break;
+ case USB_OTG_TEST_SINGLE_STEP_GET_DEV_DESC_DATA_PID:
+ /* Issue GetDeviceDescriptor, Sleep for 15 Sec. */
+ err = usb_get_device_descriptor(udev,
+ sizeof(udev->descriptor));
+ if (err < 0) {
+ dev_err(&udev->dev, "can't re-read"
+ "device descriptor for "
+ "OTG TEST MODE: %d\n", err);
+ goto loop_disable;
+ }
+ ssleep(15);
+ break;
+ default:
+ /* is_targeted() will take care for wrong PID */
+ dev_dbg(&udev->dev, "OTG TEST_MODE:Wrong
+ PID %d\n" idProduct);
+ break;
+ }
+
+ if (set_feature) {
+ err = hcd->driver->hub_control(hcd,
+ typeReq, wValue, wIndex,
+ NULL, 0);
+ }
+ }
+
+#endif
return;
loop_disable:
diff --git a/drivers/usb/core/otg_whitelist.h b/drivers/usb/core/otg_whitelist.h
index e8cdce571bb..86a09972836 100644
--- a/drivers/usb/core/otg_whitelist.h
+++ b/drivers/usb/core/otg_whitelist.h
@@ -43,12 +43,50 @@ static struct usb_device_id whitelist_table [] = {
{ USB_DEVICE(0x0525, 0xa4a0), },
#endif
+#ifdef CONFIG_USB_OTG_20
+{ USB_DEVICE_INFO(8, 6, 80) },/* Mass Storage Devices */
+{ USB_DEVICE_INFO(1, 1, 0) },/* Audio Devices */
+{ USB_DEVICE_INFO(3, 0, 0) },/* keyboard Devices */
+{ USB_DEVICE_INFO(3, 1, 2) },/* Mouse Devices */
+
+/* Test Devices */
+{ USB_DEVICE(0x1A0A, 0x0101), },/* Test_SE0_NAK */
+{ USB_DEVICE(0x1A0A, 0x0102), },/* Test_J */
+{ USB_DEVICE(0x1A0A, 0x0103), },/* Test_K */
+{ USB_DEVICE(0x1A0A, 0x0104), },/* Test_Packet */
+{ USB_DEVICE(0x1A0A, 0x0106), },/* HS_HOST_PORT_SUSPEND_RESUME */
+{ USB_DEVICE(0x1A0A, 0x0107), },/* SINGLE_STEP_GET_DEV_DESC */
+{ USB_DEVICE(0x1A0A, 0x0108), },/* SINGLE_STEP_ GET_DEV_DESC_DATA*/
+{ USB_DEVICE(0x1A0A, 0x0201), },/* OTG 2 TEST DEVICE*/
+#endif
{ } /* Terminating entry */
};
+/* The TEST_MODE Definition for OTG as per 6.4 of OTG Rev 2.0 */
+
+#ifdef CONFIG_USB_OTG_20
+#define USB_OTG_TEST_MODE_VID 0x1A0A
+#define USB_OTG_TEST_SE0_NAK_PID 0x0101
+#define USB_OTG_TEST_J_PID 0x0102
+#define USB_OTG_TEST_K_PID 0x0103
+#define USB_OTG_TEST_PACKET_PID 0x0104
+#define USB_OTG_TEST_HS_HOST_PORT_SUSPEND_RESUME_PID 0x0106
+#define USB_OTG_TEST_SINGLE_STEP_GET_DEV_DESC_PID 0x0107
+#define USB_OTG_TEST_SINGLE_STEP_GET_DEV_DESC_DATA_PID 0x0108
+
+#define USB_OTG_TEST_SE0_NAK 0x01
+#define USB_OTG_TEST_J 0x02
+#define USB_OTG_TEST_K 0x03
+#define USB_OTG_TEST_PACKET 0x04
+#endif
+
static int is_targeted(struct usb_device *dev)
{
struct usb_device_id *id = whitelist_table;
+#ifdef CONFIG_USB_OTG_20
+ u8 number_configs = 0;
+ u8 number_interface = 0;
+#endif
/* possible in developer configs only! */
if (!dev->bus->otg_port)
@@ -98,6 +136,36 @@ static int is_targeted(struct usb_device *dev)
/* add other match criteria here ... */
+#ifdef CONFIG_USB_OTG_20
+
+ /* Checking class,subclass and protocal at interface level */
+ for (number_configs = dev->descriptor.bNumConfigurations;
+ number_configs > 0; number_configs--)
+ for (number_interface = dev->config->desc.bNumInterfaces;
+ number_interface > 0;
+ number_interface--)
+ for (id = whitelist_table; id->match_flags; id++) {
+ if ((id->match_flags &
+ USB_DEVICE_ID_MATCH_DEV_CLASS) &&
+ (id->bDeviceClass !=
+ dev->config->intf_cache[number_interface-1]
+ ->altsetting[0].desc.bInterfaceClass))
+ continue;
+ if ((id->match_flags &
+ USB_DEVICE_ID_MATCH_DEV_SUBCLASS)
+ && (id->bDeviceSubClass !=
+ dev->config->intf_cache[number_interface-1]
+ ->altsetting[0].desc.bInterfaceSubClass))
+ continue;
+ if ((id->match_flags &
+ USB_DEVICE_ID_MATCH_DEV_PROTOCOL)
+ && (id->bDeviceProtocol !=
+ dev->config->intf_cache[number_interface-1]
+ ->altsetting[0].desc.bInterfaceProtocol))
+ continue;
+ return 1;
+ }
+#endif
/* OTG MESSAGE: report errors here, customize to match your product */
dev_err(&dev->dev, "device v%04x p%04x is not supported\n",
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 2633f759511..7e99677b81b 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -977,4 +977,15 @@ config USB_G_WEBCAM
endchoice
+config USB_OTG_20
+ bool "OTG 2.0 USB SUPPORT"
+ select USB_OTG
+ select PM_RUNTIME
+ select USB_OTG_WHITELIST
+ select USB_SUSPEND
+ default n
+ help
+ Enabling the whitelist (Target Peripheral List-TPL) and runtime power
+ management at system level and usb level for OTG 2.0.
+
endif # USB_GADGET
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
index 22ec3e37998..702d5efe9ef 100644
--- a/drivers/usb/musb/musb_virthub.c
+++ b/drivers/usb/musb/musb_virthub.c
@@ -379,7 +379,7 @@ int musb_hub_control(
musb_port_suspend(musb, true);
break;
case USB_PORT_FEAT_TEST:
- if (unlikely(is_host_active(musb)))
+ if (unlikely(!is_host_active(musb)))
goto error;
wIndex >>= 8;