Received: from mailman by lists.gnu.org with archive (Exim 4.43) id 1OQGj8-0003Ld-KR for mharc-grub-devel@gnu.org; Sun, 20 Jun 2010 05:22:06 -0400 Received: from [140.186.70.92] (port=58439 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OQGj4-0003LU-Mi for grub-devel@gnu.org; Sun, 20 Jun 2010 05:22:03 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OQGj3-0003f5-GP for grub-devel@gnu.org; Sun, 20 Jun 2010 05:22:02 -0400 Received: from smtp-out3.iol.cz ([194.228.2.91]:50149) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OQGj3-0003en-19 for grub-devel@gnu.org; Sun, 20 Jun 2010 05:22:01 -0400 Received: from antivir5.iol.cz (unknown [192.168.30.212]) by smtp-out3.iol.cz (Postfix) with ESMTP id 48C8DBC82E4 for ; Sun, 20 Jun 2010 09:21:58 +0000 (UTC) Received: from localhost (antivir5.iol.cz [127.0.0.1]) by antivir5.iol.cz (Postfix) with ESMTP id 38A1D28009 for ; Sun, 20 Jun 2010 11:21:58 +0200 (CEST) X-Virus-Scanned: amavisd-new at iol.cz Received: from antivir5.iol.cz ([127.0.0.1]) by localhost (antivir5.iol.cz [127.0.0.1]) (amavisd-new, port 10224) with LMTP id 89kVWIzv50pH for ; Sun, 20 Jun 2010 11:21:58 +0200 (CEST) Received: from port6.iol.cz (unknown [192.168.30.96]) by antivir5.iol.cz (Postfix) with ESMTP id 09EB428006 for ; Sun, 20 Jun 2010 11:21:58 +0200 (CEST) X-SBRS: None X-SBRS-none: None X-RECVLIST: MTA-OUT-IOL X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AqABANJ6HUxVRnXk/2dsb2JhbAAHgxWBAcpzkAmEK3AE Received: from 228.117.broadband3.iol.cz (HELO [192.168.6.160]) ([85.70.117.228]) by port6.iol.cz with ESMTP; 20 Jun 2010 11:21:57 +0200 From: =?UTF-8?Q?Ale=C5=A1?= Nesrsta To: grub-devel@gnu.org Content-Type: multipart/mixed; boundary="=-u9n1XReEtqsfuM4lvt54" Date: Sun, 20 Jun 2010 11:21:56 +0200 Message-Id: <1277025716.4952.4.camel@pracovna> Mime-Version: 1.0 X-Mailer: Evolution 2.22.3.1 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) Subject: [Patch] Simple USB hub support X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: The development of GNU GRUB List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 20 Jun 2010 09:22:04 -0000 --=-u9n1XReEtqsfuM4lvt54 Content-Type: text/plain Content-Transfer-Encoding: 7bit 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 --=-u9n1XReEtqsfuM4lvt54 Content-Disposition: attachment; filename=usb_patch_hub_100620_0 Content-Type: text/x-patch; name=usb_patch_hub_100620_0; charset=UTF-8 Content-Transfer-Encoding: 7bit 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 { --=-u9n1XReEtqsfuM4lvt54--