diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-16 01:07:24 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-16 01:07:24 +0000 |
commit | 95db6b748fc86297827fbd9c9ef174d491c9ad89 (patch) | |
tree | 27a92a942821cde1edda9a1b088718d436b3efe4 /drivers/usb/usb.c | |
parent | 45b27b0a0652331d104c953a5b192d843fff88f8 (diff) |
Merge with Linux 2.3.40.
Diffstat (limited to 'drivers/usb/usb.c')
-rw-r--r-- | drivers/usb/usb.c | 160 |
1 files changed, 85 insertions, 75 deletions
diff --git a/drivers/usb/usb.c b/drivers/usb/usb.c index 2c75fb86b..6b02641a9 100644 --- a/drivers/usb/usb.c +++ b/drivers/usb/usb.c @@ -39,8 +39,8 @@ static void usb_check_support(struct usb_device *); /* * We have a per-interface "registered driver" list. */ -static LIST_HEAD(usb_driver_list); -static LIST_HEAD(usb_bus_list); +LIST_HEAD(usb_driver_list); +LIST_HEAD(usb_bus_list); static struct usb_busmap busmap; @@ -240,6 +240,7 @@ struct usb_bus *usb_alloc_bus(struct usb_operations *op) bus->bandwidth_isoc_reqs = 0; INIT_LIST_HEAD(&bus->bus_list); + INIT_LIST_HEAD(&bus->inodes); return bus; } @@ -263,11 +264,11 @@ void usb_register_bus(struct usb_bus *bus) } else warn("too many buses"); - proc_usb_add_bus(bus); - /* Add it to the list of buses */ list_add(&bus->bus_list, &usb_bus_list); + usbdevfs_add_bus(bus); + info("new USB bus registered, assigned bus number %d", bus->busnum); } @@ -282,7 +283,7 @@ void usb_deregister_bus(struct usb_bus *bus) */ list_del(&bus->bus_list); - proc_usb_remove_bus(bus); + usbdevfs_remove_bus(bus); clear_bit(bus->busnum, busmap.busmap); } @@ -443,6 +444,8 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus) dev->bus = bus; dev->parent = parent; atomic_set(&dev->refcnt, 1); + INIT_LIST_HEAD(&dev->inodes); + INIT_LIST_HEAD(&dev->filelist); dev->bus->op->allocate(dev); @@ -559,9 +562,10 @@ static int usb_start_wait_urb(urb_t *urb, int timeout, unsigned long* rval) return status; } - if (urb->status == -EINPROGRESS) - status=schedule_timeout(timeout); // ZZzzzz.... - else + if (urb->status == -EINPROGRESS) { + while (timeout && urb->status == -EINPROGRESS) + status = timeout = schedule_timeout(timeout); + } else status = 1; remove_wait_queue(&wqh, &wait); @@ -646,8 +650,6 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *usb_request_bulk(struct usb_device *dev, unsigned int pipe, usb_device_irq handler, void *data, int len, void *dev_id) { urb_t *urb; - DECLARE_WAITQUEUE(wait, current); - DECLARE_WAIT_QUEUE_HEAD(wqh); api_wrapper_data *awd; if (!(urb=usb_alloc_urb(0))) @@ -1154,11 +1156,6 @@ void usb_destroy_configuration(struct usb_device *dev) kfree(cf->interface); } kfree(dev->config); - - if (dev->string) { - kfree(dev->string); - dev->string = 0; - } } void usb_init_root_hub(struct usb_device *dev) @@ -1229,7 +1226,7 @@ void usb_disconnect(struct usb_device **pdev) } /* remove /proc/bus/usb entry */ - proc_usb_remove_device(dev); + usbdevfs_remove_device(dev); /* Free up the device itself, including its device number */ if (dev->devnum > 0) @@ -1290,7 +1287,7 @@ int usb_get_class_descriptor(struct usb_device *dev, unsigned char type, unsigned char id, unsigned char index, void *buf, int size) { return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_DESCRIPTOR, USB_RT_INTERFACE | USB_DIR_IN, + USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN, (type << 8) + id, index, buf, size, HZ * GET_TIMEOUT); } @@ -1326,7 +1323,7 @@ int usb_get_protocol(struct usb_device *dev) int ret; if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_PROTOCOL, USB_DIR_IN | USB_RT_HIDD, + USB_REQ_GET_PROTOCOL, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, 1, &type, 1, HZ * GET_TIMEOUT)) < 0) return ret; @@ -1336,13 +1333,15 @@ int usb_get_protocol(struct usb_device *dev) int usb_set_protocol(struct usb_device *dev, int protocol) { return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_SET_PROTOCOL, USB_RT_HIDD, protocol, 1, NULL, 0, HZ * SET_TIMEOUT); + USB_REQ_SET_PROTOCOL, USB_TYPE_CLASS | USB_RECIP_INTERFACE, + protocol, 1, NULL, 0, HZ * SET_TIMEOUT); } int usb_set_idle(struct usb_device *dev, int duration, int report_id) { - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_IDLE, - USB_RT_HIDD, (duration << 8) | report_id, 1, NULL, 0, HZ * SET_TIMEOUT); + return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, + (duration << 8) | report_id, 1, NULL, 0, HZ * SET_TIMEOUT); } static void usb_set_maxpacket(struct usb_device *dev) @@ -1385,14 +1384,14 @@ int usb_clear_halt(struct usb_device *dev, int endp) */ result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CLEAR_FEATURE, USB_RT_ENDPOINT, 0, endp, NULL, 0, HZ * SET_TIMEOUT); + USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0, HZ * SET_TIMEOUT); /* don't clear if failed */ if (result < 0) return result; result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_ENDPOINT, 0, endp, + USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_ENDPOINT, 0, endp, &status, sizeof(status), HZ * SET_TIMEOUT); if (result < 0) return result; @@ -1426,7 +1425,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) } if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_SET_INTERFACE, USB_RT_INTERFACE, alternate, + USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate, interface, NULL, 0, HZ * 5)) < 0) return ret; @@ -1466,14 +1465,14 @@ int usb_set_configuration(struct usb_device *dev, int configuration) int usb_get_report(struct usb_device *dev, unsigned char type, unsigned char id, unsigned char index, void *buf, int size) { return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_REPORT, USB_DIR_IN | USB_RT_HIDD, + USB_REQ_GET_REPORT, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, (type << 8) + id, index, buf, size, HZ * GET_TIMEOUT); } int usb_set_report(struct usb_device *dev, unsigned char type, unsigned char id, unsigned char index, void *buf, int size) { return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_SET_REPORT, USB_RT_HIDD, + USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (type << 8) + id, index, buf, size, HZ); } @@ -1491,6 +1490,11 @@ int usb_get_configuration(struct usb_device *dev) return -1; } + if (dev->descriptor.bNumConfigurations < 1) { + warn("not enough configurations"); + return -1; + } + dev->config = (struct usb_config_descriptor *) kmalloc(dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor), GFP_KERNEL); @@ -1547,54 +1551,45 @@ int usb_get_configuration(struct usb_device *dev) return result; } -char *usb_string(struct usb_device *dev, int index) +int usb_string(struct usb_device *dev, int index, char *buf, size_t size) { - int i, len, ret; - char *ptr; - union { - unsigned char buffer[256]; - struct usb_string_descriptor desc; - } u; - - if (index <= 0) - return 0; - if (dev->string) - kfree (dev->string); - - if (dev->string_langid == 0) { - /* read string descriptor 0 */ - ret = usb_get_string(dev, 0, 0, u.buffer, 4); - if (ret >= 0 && u.desc.bLength >= 4) - dev->string_langid = le16_to_cpup(&u.desc.wData[0]); - else - err("error getting string"); - dev->string_langid |= 0x10000; /* so it's non-zero */ - } + unsigned char *tbuf; + int err; + unsigned int u, idx; - if (usb_get_string(dev, dev->string_langid, index, u.buffer, 4) < 0 || - ((ret = usb_get_string(dev, dev->string_langid, index, u.buffer, - u.desc.bLength)) < 0)) { - err("error retrieving string"); - return NULL; - } - - if (ret > 0) ret /= 2; /* going from 16-bit chars to 8-bit */ - len = u.desc.bLength / 2; /* includes terminating null */ - /* after removing bLength & bDescType */ - if (ret < len) len = ret; /* use min of (ret, len) */ - - ptr = kmalloc(len, GFP_KERNEL); - if (!ptr) { - err("couldn't allocate memory for string"); - return NULL; + if (size <= 0 || !buf) + return -EINVAL; + buf[0] = 0; + tbuf = kmalloc(256, GFP_KERNEL); + if (!tbuf) + return -ENOMEM; + /* + * is this two step process necessary? can't we just + * ask for a maximum length string and then take the length + * that was returned? + */ + err = usb_get_string(dev, dev->string_langid, index, tbuf, 4); + if (err < 0) + goto errout; + err = usb_get_string(dev, dev->string_langid, index, tbuf, tbuf[0]); + if (err < 0) + goto errout; + size--; + for (idx = 0, u = 2; u < tbuf[0]; u += 2) { + if (idx >= size) + break; + if (tbuf[u+1]) { + buf[idx++] = '?'; /* non ASCII character */ + continue; + } + buf[idx++] = tbuf[u]; } + buf[idx] = 0; + err = idx; - for (i = 0; i < len - 1; ++i) - ptr[i] = le16_to_cpup(&u.desc.wData[i]); - ptr[i] = 0; - - dev->string = ptr; - return ptr; + errout: + kfree(tbuf); + return err; } /* @@ -1606,10 +1601,10 @@ char *usb_string(struct usb_device *dev, int index) */ int usb_new_device(struct usb_device *dev) { + unsigned char *buf; int addr, err; - info("USB new device connect, assigned device number %d", - dev->devnum); + info("USB new device connect, assigned device number %d", dev->devnum); dev->maxpacketsize = 0; /* Default to 8 byte max packet size */ dev->epmaxpacketin [0] = 8; @@ -1657,8 +1652,7 @@ int usb_new_device(struct usb_device *dev) return 1; } - err=usb_get_configuration(dev); - + err = usb_get_configuration(dev); if (err < 0) { err("unable to get configuration (error=%d)", err); clear_bit(dev->devnum, &dev->bus->devmap.devicemap); @@ -1674,13 +1668,28 @@ int usb_new_device(struct usb_device *dev) err("failed to set default configuration"); return -1; } + /* get langid for strings */ + buf = kmalloc(256, GFP_KERNEL); + if (!buf) { + err("out of memory\n"); + } else { + err = usb_get_string(dev, 0, 0, buf, 4); + if (err < 0) { + err("error getting string descriptor 0 (error=%d)\n", err); + } else if (buf[0] < 4) { + err("string descriptpr 0 too short\n"); + } else + dev->string_langid = buf[2] | (buf[3]<< 8); + kfree(buf); + info("USB device number %d default language ID 0x%x", dev->devnum, dev->string_langid); + } usb_show_string(dev, "Manufacturer", dev->descriptor.iManufacturer); usb_show_string(dev, "Product", dev->descriptor.iProduct); usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber); /* now that the basic setup is over, add a /proc/bus/usb entry */ - proc_usb_add_device(dev); + usbdevfs_add_device(dev); /* find drivers willing to handle this device */ usb_find_drivers(dev); @@ -1771,6 +1780,7 @@ EXPORT_SYMBOL(usb_set_address); EXPORT_SYMBOL(usb_get_descriptor); EXPORT_SYMBOL(usb_get_class_descriptor); EXPORT_SYMBOL(__usb_get_extra_descriptor); +EXPORT_SYMBOL(usb_get_device_descriptor); EXPORT_SYMBOL(usb_get_string); EXPORT_SYMBOL(usb_string); EXPORT_SYMBOL(usb_get_protocol); |