--- linux/include/linux/usb.h-orig Tue Mar 21 19:40:50 2000 +++ linux/include/linux/usb.h Tue Mar 21 19:43:15 2000 @@ -604,6 +604,7 @@ extern int usb_terminate_bulk(struct usb_device *, void *); extern void usb_init_root_hub(struct usb_device *dev); +extern int usb_root_hub_string(int id, int serial, char *type, __u8 *data, int len); extern void usb_connect(struct usb_device *dev); extern void usb_disconnect(struct usb_device **); --- linux/drivers/usb-dist/usb.c Tue Mar 21 18:28:08 2000 +++ linux/drivers/usb/usb.c Tue Mar 21 20:45:33 2000 @@ -1184,6 +1184,54 @@ dev->actconfig = NULL; } +/* for returning string descriptors in UTF-16LE */ +static int ascii2utf (char *ascii, __u8 *utf, int utfmax) +{ + int retval; + + for (retval = 0; *ascii && utfmax > 1; utfmax -= 2, retval += 2) { + *utf++ = *ascii++ & 0x7f; + *utf++ = 0; + } + return retval; +} + +/* + * root_hub_string is used by each host controller's root hub code, + * so that they're identified consistently throughout the system. + */ +int usb_root_hub_string (int id, int serial, char *type, __u8 *data, int len) +{ + char buf [20]; + + // assert (len > (2 * (sizeof (buf) + 1))); + // assert (strlen (type) ~== 4); + + // language ids + if (id == 0) { + *data++ = 4; *data++ = 0; /* 4 bytes data */ + *data++ = 0; *data++ = 0; /* some language id */ + return 4; + + // serial number + } else if (id == 1) { + sprintf (buf, "%x", serial); + + // product description + } else if (id == 2) { + sprintf (buf, "USB %s Root Hub", type); + + // id 3 == vendor description + + // unsupported IDs --> "stall" + } else + return 0; + + data [0] = 2 + ascii2utf (buf, data + 2, len - 2); + data [1] = 3; + return data [0]; +} + /* * __usb_get_extra_descriptor() finds a descriptor of specific type in the * extra field of the interface and endpoint descriptor structs. @@ -1824,6 +1872,7 @@ EXPORT_SYMBOL(usb_driver_release_interface); EXPORT_SYMBOL(usb_init_root_hub); +EXPORT_SYMBOL(usb_root_hub_string); EXPORT_SYMBOL(usb_new_device); EXPORT_SYMBOL(usb_connect); EXPORT_SYMBOL(usb_disconnect); --- linux/drivers/usb-dist/usb-ohci.c Tue Mar 21 18:28:08 2000 +++ linux/drivers/usb/usb-ohci.c Tue Mar 21 20:33:46 2000 @@ -1128,8 +1128,8 @@ 0x00, /* __u16 bcdDevice; */ 0x00, 0x00, /* __u8 iManufacturer; */ - 0x00, /* __u8 iProduct; */ - 0x00, /* __u8 iSerialNumber; */ + 0x02, /* __u8 iProduct; */ + 0x01, /* __u8 iSerialNumber; */ 0x01 /* __u8 bNumConfigurations; */ }; @@ -1388,6 +1388,14 @@ len = min (leni, min (sizeof (root_hub_config_des), wLength)); data_buf = root_hub_config_des; OK(len); case (0x03): /* string descriptors */ + len = usb_root_hub_string (wValue & 0xff, + (int) ohci->regs, "OHCI", + data, wLength); + if (len > 0) { + data_buf = data; + OK (min (leni, len)); + } + // else fallthrough default: status = TD_CC_STALL; } @@ -1436,7 +1444,8 @@ dbg("USB HC roothubstat2: %x", readl ( &(ohci->regs->roothub.portstatus[1]) )); len = min(len, leni); - memcpy (data, data_buf, len); + if (data != data_buf) + memcpy (data, data_buf, len); urb->actual_length = len; urb->status = cc_to_error [status]; --- linux/drivers/usb-dist/usb-uhci.c Tue Mar 21 18:28:09 2000 +++ linux/drivers/usb/usb-uhci.c Tue Mar 21 20:48:16 2000 @@ -1617,8 +1617,8 @@ 0x00, /* __u16 bcdDevice; */ 0x00, 0x00, /* __u8 iManufacturer; */ - 0x00, /* __u8 iProduct; */ - 0x00, /* __u8 iSerialNumber; */ + 0x02, /* __u8 iProduct; */ + 0x01, /* __u8 iSerialNumber; */ 0x01 /* __u8 bNumConfigurations; */ }; @@ -1915,8 +1915,14 @@ len = min (leni, min (sizeof (root_hub_config_des), wLength)); memcpy (data, root_hub_config_des, len); OK (len); - case (0x03): /*string descriptors */ - stat = -EPIPE; + case (0x03): /* string descriptors */ + len = usb_root_hub_string (wValue & 0xff, + uhci->io_addr, "UHCI", + data, wLength); + if (len > 0) { + OK (min (leni, len)); + } else + stat = -EPIPE; } break; --- linux/drivers/usb-dist/uhci.c Tue Mar 21 18:28:09 2000 +++ linux/drivers/usb/uhci.c Tue Mar 21 20:32:43 2000 @@ -1315,8 +1315,8 @@ 0x00, /* __u16 bcdDevice; */ 0x00, 0x00, /* __u8 iManufacturer; */ - 0x00, /* __u8 iProduct; */ - 0x00, /* __u8 iSerialNumber; */ + 0x02, /* __u8 iProduct; */ + 0x01, /* __u8 iSerialNumber; */ 0x01 /* __u8 bNumConfigurations; */ }; @@ -1617,7 +1617,13 @@ memcpy (data, root_hub_config_des, len); OK(len); case 0x03: /* string descriptors */ - stat = -EPIPE; + len = usb_root_hub_string (wValue & 0xff, + uhci->io_addr, "UHCI", + data, wLength); + if (len > 0) { + OK (min (leni, len)); + } else + stat = -EPIPE; } break; case RH_GET_DESCRIPTOR | RH_CLASS: