linux-usb.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3] usb: misc: ehset: Rework test mode entry
@ 2021-12-13 17:35 Razvan Heghedus
  2021-12-13 17:35 ` [PATCH] usb: core: Export usb_device_match_id Razvan Heghedus
  0 siblings, 1 reply; 2+ messages in thread
From: Razvan Heghedus @ 2021-12-13 17:35 UTC (permalink / raw)
  Cc: heghedus.razvan, Greg Kroah-Hartman, Johan Hovold, Wei Ming Chen,
	Peter Chen, Anant Thazhemadam, linux-usb, linux-kernel

The USB2.0 spec chapter 11.24.2.13 says that the USB port which is going
under test needs to be put in suspend state before sending the test
command. Many hubs, don't enforce this precondition and they work fine
without this step. We should follow the specification and put the USB
port in suspend before sending the test command.

Also there are some "special" hubs, which requires to disable the USB
port power instead of putting it in suspend. I found out only three hubs
which requires this step, but if more are found, they can be added to
the list.

Since this changes the default implementation, it raises the posibility
of finding other broken hubs which are not compliant with the spec and
the test command might not work is the port is suspended. If such hubs
are found, a similar workaround like the disable part can be implemented
to skip putting the port in suspend.

Signed-off-by: Razvan Heghedus <heghedus.razvan@gmail.com>
---
 Changes in v3:
  - use usb_device_match_id to correctly match the hub based on VID:PID
  - reword commit message to be more explanatory on what the patch does
 Changes in v2:
  - style change regarding multi-line comments and a new black line
    after local variable definitions
  - No more corporate email annotation
 drivers/usb/misc/ehset.c | 58 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/drivers/usb/misc/ehset.c b/drivers/usb/misc/ehset.c
index f87890f9cd26..986d6589f053 100644
--- a/drivers/usb/misc/ehset.c
+++ b/drivers/usb/misc/ehset.c
@@ -18,6 +18,52 @@
 #define TEST_SINGLE_STEP_GET_DEV_DESC		0x0107
 #define TEST_SINGLE_STEP_SET_FEATURE		0x0108
 
+extern const struct usb_device_id *usb_device_match_id(struct usb_device *udev,
+						const struct usb_device_id *id);
+
+/*
+ * A list of USB hubs which requires to disable the power
+ * to the port before starting the testing procedures.
+ */
+static const struct usb_device_id ehset_hub_list[] = {
+	{ USB_DEVICE(0x0424, 0x4502) },
+	{ USB_DEVICE(0x0424, 0x4913) },
+	{ USB_DEVICE(0x0451, 0x8027) },
+	{ }
+};
+
+static int ehset_prepare_port_for_testing(struct usb_device *hub_udev, u16 portnum)
+{
+	int ret = 0;
+
+	/*
+	 * The USB2.0 spec chapter 11.24.2.13 says that the USB port which is
+	 * going under test needs to be put in suspend before sending the
+	 * test command. Most hubs don't enforce this precondition, but there
+	 * are some hubs which needs to disable the power to the port before
+	 * starting the test.
+	 */
+	if (usb_device_match_id(hub_udev, ehset_hub_list)) {
+		ret = usb_control_msg_send(hub_udev, 0, USB_REQ_CLEAR_FEATURE,
+					   USB_RT_PORT, USB_PORT_FEAT_ENABLE,
+					   portnum, NULL, 0, 1000, GFP_KERNEL);
+		/*
+		 * Wait for the port to be disabled. It's an arbitrary value
+		 * which worked every time.
+		 */
+		msleep(100);
+	} else {
+		/*
+		 * For the hubs which are compliant with the spec,
+		 * put the port in SUSPEND.
+		 */
+		ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
+					   USB_RT_PORT, USB_PORT_FEAT_SUSPEND,
+					   portnum, NULL, 0, 1000, GFP_KERNEL);
+	}
+	return ret;
+}
+
 static int ehset_probe(struct usb_interface *intf,
 		       const struct usb_device_id *id)
 {
@@ -30,24 +76,36 @@ static int ehset_probe(struct usb_interface *intf,
 
 	switch (test_pid) {
 	case TEST_SE0_NAK_PID:
+		ret = ehset_prepare_port_for_testing(hub_udev, portnum);
+		if (!ret)
+			break;
 		ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
 					   USB_RT_PORT, USB_PORT_FEAT_TEST,
 					   (USB_TEST_SE0_NAK << 8) | portnum,
 					   NULL, 0, 1000, GFP_KERNEL);
 		break;
 	case TEST_J_PID:
+		ret = ehset_prepare_port_for_testing(hub_udev, portnum);
+		if (!ret)
+			break;
 		ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
 					   USB_RT_PORT, USB_PORT_FEAT_TEST,
 					   (USB_TEST_J << 8) | portnum, NULL, 0,
 					   1000, GFP_KERNEL);
 		break;
 	case TEST_K_PID:
+		ret = ehset_prepare_port_for_testing(hub_udev, portnum);
+		if (!ret)
+			break;
 		ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
 					   USB_RT_PORT, USB_PORT_FEAT_TEST,
 					   (USB_TEST_K << 8) | portnum, NULL, 0,
 					   1000, GFP_KERNEL);
 		break;
 	case TEST_PACKET_PID:
+		ret = ehset_prepare_port_for_testing(hub_udev, portnum);
+		if (!ret)
+			break;
 		ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
 					   USB_RT_PORT, USB_PORT_FEAT_TEST,
 					   (USB_TEST_PACKET << 8) | portnum,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [PATCH] usb: core: Export usb_device_match_id
  2021-12-13 17:35 [PATCH v3] usb: misc: ehset: Rework test mode entry Razvan Heghedus
@ 2021-12-13 17:35 ` Razvan Heghedus
  0 siblings, 0 replies; 2+ messages in thread
From: Razvan Heghedus @ 2021-12-13 17:35 UTC (permalink / raw)
  Cc: heghedus.razvan, Greg Kroah-Hartman, Johan Hovold, Wei Ming Chen,
	linux-usb, linux-kernel

Export usb_device_match_id so that it can be used for easily matching an
usb_device with a table of IDs.

Signed-off-by: Razvan Heghedus <heghedus.razvan@gmail.com>
---
 drivers/usb/core/driver.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 267a134311be..355ed33a2179 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -834,6 +834,7 @@ const struct usb_device_id *usb_device_match_id(struct usb_device *udev,
 
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(usb_device_match_id);
 
 bool usb_driver_applicable(struct usb_device *udev,
 			   struct usb_device_driver *udrv)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-12-13 17:37 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-13 17:35 [PATCH v3] usb: misc: ehset: Rework test mode entry Razvan Heghedus
2021-12-13 17:35 ` [PATCH] usb: core: Export usb_device_match_id Razvan Heghedus

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).