<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;"># This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.483   -&gt; 1.484  
#	   drivers/usb/hcd.h	1.2     -&gt; 1.3    
#	   drivers/usb/hcd.c	1.10    -&gt; 1.11   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/03/07	david-b@pacbell.net	1.484
# USB
# hcd-0305, periodic and pci fixup
#   
#       - removes the pci dependency you mentioned in the
#         rh_string code (friendlier to non-PCI HCs)
#       - makes code match doc (8859-1 chars, not just ascii)
#       - adds sanity checking for the periodic transfer interval,
#         and forces it to a power-of-two (code can leave HCDs)
#       - facilitates better IRQ sharing
# --------------------------------------------
#
diff -Nru a/drivers/usb/hcd.c b/drivers/usb/hcd.c
--- a/drivers/usb/hcd.c	Thu Mar  7 17:02:39 2002
+++ b/drivers/usb/hcd.c	Thu Mar  7 17:02:39 2002
@@ -224,12 +224,12 @@
  * helper routine for returning string descriptors in UTF-16LE
  * input can actually be ISO-8859-1; ASCII is its 7-bit subset
  */
-static int ascii2utf (char *ascii, u8 *utf, int utfmax)
+static int ascii2utf (char *s, u8 *utf, int utfmax)
 {
 	int retval;
 
-	for (retval = 0; *ascii &amp;&amp; utfmax &gt; 1; utfmax -= 2, retval += 2) {
-		*utf++ = *ascii++ &amp; 0x7f;
+	for (retval = 0; *s &amp;&amp; utfmax &gt; 1; utfmax -= 2, retval += 2) {
+		*utf++ = *s++;
 		*utf++ = 0;
 	}
 	return retval;
@@ -248,8 +248,7 @@
  */
 static int rh_string (
 	int		id,
-	struct pci_dev	*pci_desc,
-	char		*type,
+	struct usb_hcd	*hcd,
 	u8		*data,
 	int		len
 ) {
@@ -263,15 +262,16 @@
 
 	// serial number
 	} else if (id == 1) {
-		strcpy (buf, pci_desc-&gt;slot_name);
+		strcpy (buf, hcd-&gt;bus_name);
 
 	// product description
 	} else if (id == 2) {
-                strcpy (buf, pci_desc-&gt;name);
+                strcpy (buf, hcd-&gt;product_desc);
 
  	// id 3 == vendor description
 	} else if (id == 3) {
-                sprintf (buf, "%s %s %s", UTS_SYSNAME, UTS_RELEASE, type);
+                sprintf (buf, "%s %s %s", UTS_SYSNAME, UTS_RELEASE,
+			hcd-&gt;description);
 
 	// unsupported IDs --&gt; "protocol stall"
 	} else
@@ -338,9 +338,7 @@
 			break;
 		case USB_DT_STRING &lt;&lt; 8:
 			urb-&gt;actual_length = rh_string (
-				wValue &amp; 0xff,
-				 hcd-&gt;pdev,
-				(char *) hcd-&gt;description,
+				wValue &amp; 0xff, hcd,
 				ubuf, wLength);
 			break;
 		default:
@@ -1004,6 +1002,7 @@
 	hcd-&gt;self.hcpriv = (void *) hcd;
 	hcd-&gt;bus = &amp;hcd-&gt;self;
 	hcd-&gt;bus_name = dev-&gt;slot_name;
+	hcd-&gt;product_desc = dev-&gt;name;
 
 	INIT_LIST_HEAD (&amp;hcd-&gt;dev_list);
 
@@ -1266,7 +1265,7 @@
 	struct usb_hcd		*hcd;
 	struct hcd_dev		*dev;
 	unsigned long		flags;
-	int			pipe;
+	int			pipe, temp;
 
 	if (!urb || urb-&gt;hcpriv || !urb-&gt;complete)
 		return -EINVAL;
@@ -1286,6 +1285,7 @@
 	if (hcd-&gt;state == USB_STATE_QUIESCING || !HCD_IS_RUNNING (hcd-&gt;state))
 		return -ESHUTDOWN;
 	pipe = urb-&gt;pipe;
+	temp = usb_pipetype (urb-&gt;pipe);
 	if (usb_endpoint_halted (urb-&gt;dev, usb_pipeendpoint (pipe),
 			usb_pipeout (pipe)))
 		return -EPIPE;
@@ -1298,7 +1298,7 @@
 	/* enforce simple/standard policy */
 	allowed = USB_ASYNC_UNLINK;	// affects later unlinks
 	allowed |= USB_NO_FSBR;		// only affects UHCI
-	switch (usb_pipetype (pipe)) {
+	switch (temp) {
 	case PIPE_CONTROL:
 		allowed |= USB_DISABLE_SPD;
 		break;
@@ -1317,15 +1317,55 @@
 
 	/* warn if submitter gave bogus flags */
 	if (urb-&gt;transfer_flags != orig_flags)
-		warn ("BOGUS urb flags, %x --&gt; %x",
+		err ("BOGUS urb flags, %x --&gt; %x",
 			orig_flags, urb-&gt;transfer_flags);
 	}
 #endif
 	/*
-	 * FIXME:  alloc periodic bandwidth here, for interrupt and iso?
-	 * Need to look at the ring submit mechanism for iso tds ... they
-	 * aren't actually "periodic" in 2.4 kernels.
+	 * Force periodic transfer intervals to be legal values that are
+	 * a power of two (so HCDs don't need to).
 	 *
+	 * FIXME want bus-&gt;{intr,iso}_sched_horizon values here.  Each HC
+	 * supports different values... this uses EHCI/UHCI defaults (and
+	 * EHCI can use smaller non-default values).
+	 */
+	switch (temp) {
+	case PIPE_ISOCHRONOUS:
+	case PIPE_INTERRUPT:
+		/* too small? */
+		if (urb-&gt;interval &lt;= 0)
+			return -EINVAL;
+		/* too big? */
+		switch (urb-&gt;dev-&gt;speed) {
+		case USB_SPEED_HIGH:	/* units are microframes */
+			// NOTE usb handles 2^15
+			if (urb-&gt;interval &gt; (1024 * 8))
+				urb-&gt;interval = 1024 * 8;
+			temp = 1024 * 8;
+			break;
+		case USB_SPEED_FULL:	/* units are frames/msec */
+		case USB_SPEED_LOW:
+			if (temp == PIPE_INTERRUPT) {
+				if (urb-&gt;interval &gt; 255)
+					return -EINVAL;
+				// NOTE ohci only handles up to 32
+				temp = 128;
+			} else {
+				if (urb-&gt;interval &gt; 1024)
+					urb-&gt;interval = 1024;
+				// NOTE usb and ohci handle up to 2^15
+				temp = 1024;
+			}
+		default:
+			return -EINVAL;
+		}
+		/* power of two? */
+		while (temp &gt; urb-&gt;interval)
+			temp &gt;&gt;= 1;
+		urb-&gt;interval = temp;
+	}
+
+	/*
 	 * FIXME:  make urb timeouts be generic, keeping the HCD cores
 	 * as simple as possible.
 	 */
@@ -1589,6 +1629,9 @@
 	struct usb_hcd		*hcd = __hcd;
 	int			start = hcd-&gt;state;
 
+	if (unlikely (hcd-&gt;state == USB_STATE_HALT))	/* irq sharing? */
+		return;
+
 	hcd-&gt;driver-&gt;irq (hcd);
 	if (hcd-&gt;state != start &amp;&amp; hcd-&gt;state == USB_STATE_HALT)
 		hc_died (hcd);
@@ -1642,7 +1685,8 @@
 	// hcd_monitor_hook(MONITOR_URB_UPDATE, urb, dev)
 
 	if (urb-&gt;status)
-		dbg ("giveback urb %p status %d", urb, urb-&gt;status);
+		dbg ("giveback urb %p status %d len %d",
+			urb, urb-&gt;status, urb-&gt;actual_length);
 
 	/* if no error, make sure urb-&gt;next progresses */
 	else if (urb-&gt;next) {
diff -Nru a/drivers/usb/hcd.h b/drivers/usb/hcd.h
--- a/drivers/usb/hcd.h	Thu Mar  7 17:02:39 2002
+++ b/drivers/usb/hcd.h	Thu Mar  7 17:02:39 2002
@@ -39,7 +39,7 @@
 	struct usb_bus		self;		/* hcd is-a bus */
 
 	const char		*bus_name;
-
+	const char		*product_desc;	/* product/vendor string */
 	const char		*description;	/* "ehci-hcd" etc */
 
 	struct timer_list	rh_timer;	/* drives root hub */
</pre></body></html>