All of lore.kernel.org
 help / color / mirror / Atom feed
* [Patch] Simple USB hub support
@ 2010-06-20  9:21 Aleš Nesrsta
  2010-06-20 18:25 ` richardvoigt
  2010-06-28 16:44 ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 2 replies; 14+ messages in thread
From: Aleš Nesrsta @ 2010-06-20  9:21 UTC (permalink / raw)
  To: grub-devel

[-- Attachment #1: Type: text/plain, Size: 578 bytes --]

Hi,

included patch should make USB hubs operational.

It works in the same simple way as whole GRUB2 USB support, i.e. USB hub
and device must be connected to computer BEFORE uhci/ohci module is
loaded.

Note (mainly for Vladimir):
Via hub are normally working also devices which I reported to be not
functional on UHCI. So, from my point of view it looks like there is
surely some problem in powering of UHCI root hubs on my computer. But I
still don't know why only some devices are sensitive to this problem
(all of them are not big consumers of power).

Best regards
Ales


[-- Attachment #2: usb_patch_hub_100620_0 --]
[-- Type: text/x-patch, Size: 5884 bytes --]

diff -urB ./usb/bus/usb/usbhub.c ./usb_patched/bus/usb/usbhub.c
--- ./usb/bus/usb/usbhub.c	2010-06-20 10:20:58.000000000 +0200
+++ ./usb_patched/bus/usb/usbhub.c	2010-06-18 22:34:56.000000000 +0200
@@ -87,14 +87,47 @@
   struct grub_usb_usb_hubdesc hubdesc;
   grub_err_t err;
   int i;
+  grub_uint64_t timeout;
+  grub_usb_device_t next_dev;
+  
+  err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
+	  		            | GRUB_USB_REQTYPE_CLASS
+			            | GRUB_USB_REQTYPE_TARGET_DEV),
+                              GRUB_USB_REQ_GET_DESCRIPTOR,
+			      (GRUB_USB_DESCRIPTOR_HUB << 8) | 0,
+			      0, sizeof (hubdesc), (char *) &hubdesc);
+  if (err)
+    return err;
+  grub_dprintf ("usb", "Hub descriptor:\n\t\t len:%d, typ:0x%02x, cnt:%d, char:0x%02x, pwg:%d, curr:%d\n",
+                hubdesc.length, hubdesc.type, hubdesc.portcnt,
+                hubdesc.characteristics, hubdesc.pwdgood,
+                hubdesc.current);
+
+  /* Activate the first configuration. Hubs should have only one conf. */
+  grub_dprintf ("usb", "Hub set configuration\n");
+  grub_usb_set_configuration (dev, 1);
 
-  grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
-			      | GRUB_USB_REQTYPE_CLASS
-			      | GRUB_USB_REQTYPE_TARGET_DEV),
-			GRUB_USB_REQ_GET_DESCRIPTOR,
-			(GRUB_USB_DESCRIPTOR_HUB << 8) | 0,
-			0, sizeof (hubdesc), (char *) &hubdesc);
-
+  /* Power on all Hub ports.  */
+  for (i = 1; i <= hubdesc.portcnt; i++)
+    {
+      grub_dprintf ("usb", "Power on - port %d\n", i);
+      /* Power on the port and wait for possible device connect */
+      err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
+					| GRUB_USB_REQTYPE_CLASS
+					| GRUB_USB_REQTYPE_TARGET_OTHER),
+				  GRUB_USB_REQ_SET_FEATURE,
+				  GRUB_USB_HUB_FEATURE_PORT_POWER,
+				  i, 0, NULL);
+      /* Just ignore the device if some error happened */
+      if (err)
+	continue;
+    }
+  /* Wait for port power-on */
+  if (hubdesc.pwdgood >= 50)
+    grub_millisleep (hubdesc.pwdgood * 2);
+  else
+    grub_millisleep (100);
+    
   /* Iterate over the Hub ports.  */
   for (i = 1; i <= hubdesc.portcnt; i++)
     {
@@ -104,9 +137,8 @@
       err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
 					| GRUB_USB_REQTYPE_CLASS
 					| GRUB_USB_REQTYPE_TARGET_OTHER),
-				  GRUB_USB_REQ_HUB_GET_PORT_STATUS,
+				  GRUB_USB_REQ_GET_STATUS,
 				  0, i, sizeof (status), (char *) &status);
-
       /* Just ignore the device if the Hub does not report the
 	 status.  */
       if (err)
@@ -111,7 +143,8 @@
 	 status.  */
       if (err)
 	continue;
-
+      grub_dprintf ("usb", "Hub port %d status: 0x%02x\n", i, status);
+      	    
       /* If connected, reset and enable the port.  */
       if (status & GRUB_USB_HUB_STATUS_CONNECTED)
 	{
@@ -128,21 +161,46 @@
 		speed = GRUB_USB_SPEED_FULL;
 	    }
 
-	  /* A device is actually connected to this port, not enable
-	     the port.  XXX: Why 0x03?  According to some docs it
-	     should be 0x0.  Check the specification!  */
+	  /* A device is actually connected to this port.
+	   * Now do reset of port. */
+          grub_dprintf ("usb", "Reset hub port - port %d\n", i);
 	  err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
 					    | GRUB_USB_REQTYPE_CLASS
 					    | GRUB_USB_REQTYPE_TARGET_OTHER),
-				      0x3, 0x4, i, 0, 0);
-
+				      GRUB_USB_REQ_SET_FEATURE,
+				      GRUB_USB_HUB_FEATURE_PORT_RESET,
+				      i, 0, 0);
 	  /* If the Hub does not cooperate for this port, just skip
 	     the port.  */
 	  if (err)
 	    continue;
 
+          /* Wait for reset procedure done */
+          timeout = grub_get_time_ms () + 1000;
+          do
+            {
+              /* Get the port status.  */
+              err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
+	   	 			        | GRUB_USB_REQTYPE_CLASS
+					        | GRUB_USB_REQTYPE_TARGET_OTHER),
+				          GRUB_USB_REQ_GET_STATUS,
+				          0, i, sizeof (status), (char *) &status);
+            }
+          while (!err &&
+                 !(status & GRUB_USB_HUB_STATUS_C_PORT_RESET) &&
+                 (grub_get_time_ms() < timeout) );
+          if (err || !(status & GRUB_USB_HUB_STATUS_C_PORT_RESET) )
+            continue;
+   
 	  /* Add the device and assign a device address to it.  */
-	  grub_usb_hub_add_dev (&dev->controller, speed);
+          grub_dprintf ("usb", "Call hub_add_dev - port %d\n", i);
+	  next_dev = grub_usb_hub_add_dev (&dev->controller, speed);
+          if (! next_dev)
+            continue;
+
+          /* If the device is a Hub, scan it for more devices.  */
+          if (next_dev->descdev.class == 0x09)
+            grub_usb_add_hub (next_dev);
 	}
     }
 
@@ -156,7 +214,7 @@
   grub_usb_device_t dev;
   grub_err_t err;
 
-  /* Enable the port.  */
+  /* Disable the port. XXX: Why? */
   err = controller->dev->portstatus (controller, portno, 0);
   if (err)
     return;
diff -urB ./usb/include/grub/usbtrans.h ./usb_patched/include/grub/usbtrans.h
--- ./usb/include/grub/usbtrans.h	2010-06-20 10:20:58.000000000 +0200
+++ ./usb_patched/include/grub/usbtrans.h	2010-06-20 10:27:13.000000000 +0200
@@ -87,15 +87,17 @@
 #define GRUB_USB_REQ_SET_INTERFACE	0x0B
 #define GRUB_USB_REQ_SYNC_FRAME		0x0C
 
-#define GRUB_USB_REQ_HUB_GET_PORT_STATUS 0x00
-
 #define GRUB_USB_FEATURE_ENDP_HALT	0x00
 #define GRUB_USB_FEATURE_DEV_REMOTE_WU	0x01
 #define GRUB_USB_FEATURE_TEST_MODE	0x02
 
-#define GRUB_USB_HUB_STATUS_CONNECTED	(1 << 0)
-#define GRUB_USB_HUB_STATUS_LOWSPEED	(1 << 9)
-#define GRUB_USB_HUB_STATUS_HIGHSPEED	(1 << 10)
+#define GRUB_USB_HUB_FEATURE_PORT_RESET   0x04
+#define GRUB_USB_HUB_FEATURE_PORT_POWER   0x08
+
+#define GRUB_USB_HUB_STATUS_CONNECTED	 (1 << 0)
+#define GRUB_USB_HUB_STATUS_LOWSPEED	 (1 << 9)
+#define GRUB_USB_HUB_STATUS_HIGHSPEED	 (1 << 10)
+#define GRUB_USB_HUB_STATUS_C_PORT_RESET (1 << 20)
 
 struct grub_usb_packet_setup
 {

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

end of thread, other threads:[~2010-07-28 14:55 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-06-20  9:21 [Patch] Simple USB hub support Aleš Nesrsta
2010-06-20 18:25 ` richardvoigt
2010-06-21 19:56   ` Aleš Nesrsta
2010-06-28 16:44 ` Vladimir 'φ-coder/phcoder' Serbinenko
2010-07-05 17:11   ` Aleš Nesrsta
2010-07-05 23:59     ` Vladimir 'φ-coder/phcoder' Serbinenko
2010-07-06 17:14       ` Aleš Nesrsta
2010-07-06 17:23         ` Colin Watson
2010-07-06 23:06       ` [Patch] USB hot-plugging support - usb branch Aleš Nesrsta
2010-07-08 21:11         ` Aleš Nesrsta
2010-07-17 11:34           ` Vladimir 'φ-coder/phcoder' Serbinenko
2010-07-17 11:38         ` Vladimir 'φ-coder/phcoder' Serbinenko
2010-07-24 18:15           ` Aleš Nesrsta
2010-07-28 14:55             ` Vladimir 'φ-coder/phcoder' Serbinenko

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.