diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-05 06:47:02 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-05 06:47:02 +0000 |
commit | 99a7e12f34b3661a0d1354eef83a0eef4df5e34c (patch) | |
tree | 3560aca9ca86792f9ab7bd87861ea143a1b3c7a3 /drivers/usb/usb.c | |
parent | e73a04659c0b8cdee4dd40e58630e2cf63afb316 (diff) |
Merge with Linux 2.3.38.
Diffstat (limited to 'drivers/usb/usb.c')
-rw-r--r-- | drivers/usb/usb.c | 937 |
1 files changed, 601 insertions, 336 deletions
diff --git a/drivers/usb/usb.c b/drivers/usb/usb.c index 14dc97320..2c75fb86b 100644 --- a/drivers/usb/usb.c +++ b/drivers/usb/usb.c @@ -5,6 +5,7 @@ * (C) Copyright Johannes Erdfelt 1999 * (C) Copyright Andreas Gal 1999 * (C) Copyright Gregory P. Smith 1999 + * (C) Copyright Deti Fliegl 1999 (new USB architecture) * * NOTE! This is not actually a driver at all, rather this is * just a collection of helper routines that implement the @@ -13,19 +14,18 @@ * Think of this as a "USB library" rather than anything else. * It should be considered a slave, with no callbacks. Callbacks * are evil. + * + * $Id: usb.c,v 1.39 1999/12/27 15:17:47 acher Exp $ */ -#ifndef EXPORT_SYMTAB -#define EXPORT_SYMTAB -#endif - -#define USB_DEBUG 1 - #include <linux/config.h> #include <linux/module.h> #include <linux/string.h> #include <linux/bitops.h> #include <linux/malloc.h> +#include <linux/interrupt.h> /* for in_interrupt() */ + +#define DEBUG #include "usb.h" @@ -36,8 +36,6 @@ static void usb_find_drivers(struct usb_device *); static int usb_find_interface_driver(struct usb_device *, unsigned int); static void usb_check_support(struct usb_device *); -static int usb_debug = 1; - /* * We have a per-interface "registered driver" list. */ @@ -54,15 +52,13 @@ int usb_register(struct usb_driver *new_driver) if (new_driver->fops != NULL) { if (usb_minors[new_driver->minor/16]) { - printk(KERN_ERR "Error registering %s driver\n", - new_driver->name); - return USB_ST_NOTSUPPORTED; + err("error registering %s driver", new_driver->name); + return -EINVAL; } usb_minors[new_driver->minor/16] = new_driver; } - printk("usbcore: Registered new driver %s\n", new_driver->name); - + info("registered new driver %s", new_driver->name); /* Add it to the list of known drivers */ list_add(&new_driver->driver_list, &usb_driver_list); @@ -77,7 +73,7 @@ int usb_register(struct usb_driver *new_driver) while (tmp != &usb_bus_list) { struct usb_bus *bus = list_entry(tmp,struct usb_bus, bus_list); - tmp = tmp->next; + tmp = tmp->next; usb_check_support(bus->root_hub); } return 0; @@ -92,7 +88,7 @@ static void usb_drivers_purge(struct usb_driver *driver,struct usb_device *dev) int i; if (!dev) { - printk(KERN_ERR "usbcore: null device being purged!!!\n"); + err("null device being purged!!!"); return; } @@ -100,21 +96,21 @@ static void usb_drivers_purge(struct usb_driver *driver,struct usb_device *dev) if (dev->children[i]) usb_drivers_purge(driver, dev->children[i]); - if (!dev->actconfig) - return; - - for (i = 0; i < dev->actconfig->bNumInterfaces; i++) { - struct usb_interface *interface = &dev->actconfig->interface[i]; + if (!dev->actconfig) + return; + + for (i = 0; i < dev->actconfig->bNumInterfaces; i++) { + struct usb_interface *interface = &dev->actconfig->interface[i]; - if (interface->driver == driver) { - driver->disconnect(dev, interface->private_data); + if (interface->driver == driver) { + driver->disconnect(dev, interface->private_data); usb_driver_release_interface(driver, interface); - /* - * This will go through the list looking for another - * driver that can handle the device - */ - usb_find_interface_driver(dev, i); - } + /* + * This will go through the list looking for another + * driver that can handle the device + */ + usb_find_interface_driver(dev, i); + } } } @@ -125,7 +121,7 @@ void usb_deregister(struct usb_driver *driver) { struct list_head *tmp; - printk("usbcore: Deregistering driver %s\n", driver->name); + info("deregistering driver %s", driver->name); if (driver->fops != NULL) usb_minors[driver->minor/16] = NULL; @@ -157,12 +153,12 @@ static long calc_bus_time (int low_speed, int input_dir, int isoc, int bytecount if (low_speed) /* no isoc. here */ { if (input_dir) - { - tmp = (67667L * (31L + 10L * BitTime (bytecount))) / 1000L; + { + tmp = (67667L * (31L + 10L * BitTime (bytecount))) / 1000L; return (64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp); } else - { + { tmp = (66700L * (31L + 10L * BitTime (bytecount))) / 1000L; return (64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp); } @@ -213,7 +209,7 @@ static int check_bandwidth_alloc (unsigned int old_alloc, long bustime) new_alloc = old_alloc + bustime; /* what new total allocated bus time would be */ - PRINTD ("usb-bandwidth-alloc: was: %u, new: %u, " + dbg("usb-bandwidth-alloc: was: %u, new: %u, " "bustime = %ld us, Pipe allowed: %s", old_alloc, new_alloc, bustime, (new_alloc <= FRAME_TIME_MAX_USECS_ALLOC) ? @@ -265,19 +261,19 @@ void usb_register_bus(struct usb_bus *bus) set_bit(busnum, busmap.busmap); bus->busnum = busnum; } else - printk(KERN_INFO "usb: too many buses\n"); + warn("too many buses"); proc_usb_add_bus(bus); /* Add it to the list of buses */ list_add(&bus->bus_list, &usb_bus_list); - printk("New USB bus registered, assigned bus number %d\n", bus->busnum); + info("new USB bus registered, assigned bus number %d", bus->busnum); } void usb_deregister_bus(struct usb_bus *bus) { - printk("usbcore: USB bus %d deregistered\n", bus->busnum); + info("USB bus %d deregistered", bus->busnum); /* * NOTE: make sure that all the devices are removed by the @@ -300,7 +296,7 @@ static void usb_check_support(struct usb_device *dev) int i; if (!dev) { - printk(KERN_ERR "usbcore: null device being checked!!!\n"); + err("null device being checked!!!"); return; } @@ -308,13 +304,13 @@ static void usb_check_support(struct usb_device *dev) if (dev->children[i]) usb_check_support(dev->children[i]); - if (!dev->actconfig) - return; + if (!dev->actconfig) + return; /* now we check this device */ - if (dev->devnum > 0) - for (i = 0; i < dev->actconfig->bNumInterfaces; i++) - usb_find_interface_driver(dev, i); + if (dev->devnum > 0) + for (i = 0; i < dev->actconfig->bNumInterfaces; i++) + usb_find_interface_driver(dev, i); } @@ -330,7 +326,7 @@ void usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface if (!iface || !driver) return; - printk(KERN_DEBUG "usbcore: %s driver claimed interface %p\n", driver->name, iface); + dbg("%s driver claimed interface %p", driver->name, iface); iface->driver = driver; iface->private_data = priv; @@ -376,31 +372,31 @@ void usb_driver_release_interface(struct usb_driver *driver, struct usb_interfac static int usb_find_interface_driver(struct usb_device *dev, unsigned ifnum) { struct list_head *tmp = usb_driver_list.next; - struct usb_interface *interface; + struct usb_interface *interface; if ((!dev) || (ifnum >= dev->actconfig->bNumInterfaces)) { - printk(KERN_ERR "usb-core: bad find_interface_driver params\n"); + err("bad find_interface_driver params"); return -1; } interface = dev->actconfig->interface + ifnum; - if (usb_interface_claimed(interface)) - return -1; + if (usb_interface_claimed(interface)) + return -1; - while (tmp != &usb_driver_list) { + while (tmp != &usb_driver_list) { void *private; - struct usb_driver *driver = list_entry(tmp, struct usb_driver, - driver_list); - - tmp = tmp->next; - if (!(private = driver->probe(dev, ifnum))) - continue; + struct usb_driver *driver = list_entry(tmp, struct usb_driver, + driver_list); + + tmp = tmp->next; + if (!(private = driver->probe(dev, ifnum))) + continue; usb_driver_claim_interface(driver, interface, private); - return 0; - } - + return 0; + } + return -1; } @@ -412,7 +408,7 @@ static int usb_find_interface_driver(struct usb_device *dev, unsigned ifnum) static void usb_find_drivers(struct usb_device *dev) { unsigned ifnum; - unsigned rejected = 0; + unsigned rejected = 0; for (ifnum = 0; ifnum < dev->actconfig->bNumInterfaces; ifnum++) { /* if this interface hasn't already been claimed */ @@ -422,9 +418,12 @@ static void usb_find_drivers(struct usb_device *dev) } } - if (rejected) { - printk(KERN_DEBUG "usbcore: unhandled interfaces on device.\n"); - } + if (rejected) + dbg("unhandled interfaces on device"); + +#ifdef DEBUG + usb_show_device(dev); +#endif } /* @@ -463,7 +462,358 @@ void usb_inc_dev_use(struct usb_device *dev) { atomic_inc(&dev->refcnt); } +/* ------------------------------------------------------------------------------------- + * New USB Core Functions + * -------------------------------------------------------------------------------------*/ + +urb_t* usb_alloc_urb(int iso_packets) +{ + urb_t *urb; + urb=(urb_t*)kmalloc(sizeof(urb_t) + iso_packets*sizeof(iso_packet_descriptor_t), + in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); + if (!urb) + { + err("alloc_urb: kmalloc failed"); + return 0; + } + memset(urb,0,sizeof(urb_t)); + return urb; +} + +/*-------------------------------------------------------------------*/ +void usb_free_urb(urb_t* urb) +{ + kfree(urb); +} +/*-------------------------------------------------------------------*/ +int usb_submit_urb(urb_t *urb) +{ + if(urb && urb->dev) + return urb->dev->bus->op->submit_urb(urb); + else + return -1; +} + +/*-------------------------------------------------------------------*/ +int usb_unlink_urb(urb_t *urb) +{ + if(urb && urb->dev) + return urb->dev->bus->op->unlink_urb(urb); + else + return -1; +} +/*-------------------------------------------------------------------* + * COMPLETION HANDLERS * + *-------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------* + * completion handler for compatibility wrappers (sync control/bulk) * + *-------------------------------------------------------------------*/ +static void usb_api_blocking_completion(urb_t *urb) +{ + api_wrapper_data *awd = (api_wrapper_data *)urb->context; + + if (waitqueue_active(awd->wakeup)) + wake_up(awd->wakeup); +#if 0 + else + dbg("(blocking_completion): waitqueue empty!"); + // even occurs if urb was unlinked by timeout... +#endif +} + +/*-------------------------------------------------------------------* + * completion handler for compatibility wrappers (async bulk) * + *-------------------------------------------------------------------*/ +static void usb_api_async_completion(urb_t *urb) +{ + api_wrapper_data *awd=(api_wrapper_data*)urb->context; + + if (awd->handler) + awd->handler(urb->status,urb->transfer_buffer,urb->actual_length,awd->stuff); + } + +/*-------------------------------------------------------------------* + * COMPATIBILITY STUFF * + *-------------------------------------------------------------------*/ + +// Starts urb and waits for completion or timeout +static int usb_start_wait_urb(urb_t *urb, int timeout, unsigned long* rval) +{ + DECLARE_WAITQUEUE(wait, current); + DECLARE_WAIT_QUEUE_HEAD(wqh); + api_wrapper_data awd; + int status; + + awd.wakeup=&wqh; + awd.handler=0; + init_waitqueue_head(&wqh); + current->state = TASK_UNINTERRUPTIBLE; + add_wait_queue(&wqh, &wait); + urb->context=&awd; + status=usb_submit_urb(urb); + if (status) { + // something went wrong + usb_free_urb(urb); + remove_wait_queue(&wqh, &wait); + return status; + } + + if (urb->status == -EINPROGRESS) + status=schedule_timeout(timeout); // ZZzzzz.... + else + status = 1; + + remove_wait_queue(&wqh, &wait); + + if (!status) { + // timeout + dbg("usb_control/bulk_msg: timeout"); + usb_unlink_urb(urb); // remove urb safely + status=-ETIMEDOUT; + } + else + status=urb->status; + + if (rval) + *rval=urb->actual_length; + + usb_free_urb(urb); + return status; +} + +/*-------------------------------------------------------------------*/ +// returns status (negative) are length (positive) +int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, + devrequest *cmd, void *data, int len, int timeout) +{ + urb_t *urb; + int retv; + unsigned long length; + + urb=usb_alloc_urb(0); + if (!urb) + return -ENOMEM; + + FILL_CONTROL_URB(urb, usb_dev, pipe, (unsigned char*)cmd, data, len, /* build urb */ + (usb_complete_t)usb_api_blocking_completion,0); + + retv=usb_start_wait_urb(urb,timeout, &length); + if (retv < 0) + return retv; + else + return length; + +} +/*-------------------------------------------------------------------*/ +int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, + __u16 value, __u16 index, void *data, __u16 size, int timeout) +{ + devrequest dr; + + dr.requesttype = requesttype; + dr.request = request; + dr.value = cpu_to_le16p(&value); + dr.index = cpu_to_le16p(&index); + dr.length = cpu_to_le16p(&size); + //dbg("usb_control_msg"); + return usb_internal_control_msg(dev, pipe, &dr, data, size, timeout); +} + +/*-------------------------------------------------------------------*/ +/* compatibility wrapper, builds bulk urb, and waits for completion */ +/* synchronous behavior */ + +int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, + void *data, int len, unsigned long *rval, int timeout) +{ + urb_t *urb; + + if (len < 0) + return -EINVAL; + + urb=usb_alloc_urb(0); + if (!urb) + return -ENOMEM; + + FILL_BULK_URB(urb,usb_dev,pipe,(unsigned char*)data,len, /* build urb */ + (usb_complete_t)usb_api_blocking_completion,0); + + return usb_start_wait_urb(urb,timeout,rval); +} +/*-------------------------------------------------------------------*/ + +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))) + return NULL; + if (!(awd = kmalloc(sizeof(api_wrapper_data), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL))) { + kfree(urb); + return NULL; + } + + /* build urb */ + FILL_BULK_URB(urb, dev, pipe, data, len, (usb_complete_t)usb_api_async_completion, awd); + + awd->handler=handler; + awd->stuff=dev_id; + if (usb_submit_urb(urb) < 0) { + kfree(awd); + kfree(urb); + return NULL; + } + return urb; +} + +// compatibility wrapper. Remove urb only if it is called before the +// transaction's completion interrupt. If called from within the +// completion handler (urb->completed==1), it does nothing, since the +// qh is already removed + +int usb_terminate_bulk(struct usb_device *dev, void *first) +{ + urb_t *urb=(urb_t*)first; + dbg("usb_terminate_bulk: urb:%p",urb); + if (!urb) // none found? there is nothing to remove! + return -ENODEV; + + usb_unlink_urb(urb); + kfree(urb->context); + kfree(urb); + return USB_ST_NOERROR; +} + +/* + * usb_release_bandwidth(): + * + * called to release an interrupt pipe's bandwidth (in microseconds) + */ +void usb_release_bandwidth(struct usb_device *dev, int bw_alloc) +{ + dev->bus->bandwidth_allocated -= bw_alloc; + dev->bus->bandwidth_int_reqs--; + dbg("bw_alloc reduced to %d for %d requesters", + dev->bus->bandwidth_allocated, + dev->bus->bandwidth_int_reqs + + dev->bus->bandwidth_isoc_reqs); +} + +static void irq_callback(urb_t *urb) +{ + struct irq_wrapper_data *wd = (struct irq_wrapper_data *)urb->context; + + if (!wd->handler) + return; +#if 0 // verbose... + if (!wd->handler(urb->status, urb->transfer_buffer, urb->actual_length, wd->context)) + err("legacy irq callback returned 0!!!"); +#else + wd->handler(urb->status, urb->transfer_buffer, urb->actual_length, wd->context); +#endif +} + +int usb_request_irq(struct usb_device *dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id, void **handle) +{ + long bustime; + int ret; + struct irq_wrapper_data *wd; + urb_t *urb; + unsigned int maxsze = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); + + *handle = NULL; + + //dbg("irq: dev:%p pipe:%08X handler:%p period:%d dev_id:%p max:%d", dev, pipe, handler, period, dev_id, maxsze); + + /* Check host controller's bandwidth for this int. request. */ + bustime = calc_bus_time (usb_pipeslow(pipe), usb_pipein(pipe), 0, + usb_maxpacket(dev, pipe, usb_pipeout(pipe))); + bustime = NS_TO_US(bustime); /* work in microseconds */ + if (check_bandwidth_alloc (dev->bus->bandwidth_allocated, bustime)) + return -EUSERS; // no bandwidth left + if (!maxsze || !usb_pipeint(pipe)) + return -EINVAL; + + if (!(urb = usb_alloc_urb(0))) + return -ENOMEM; + + if (!(wd = kmalloc(sizeof(struct irq_wrapper_data), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL))) { + kfree(urb); + return -ENOMEM; + } + if (!(urb->transfer_buffer = kmalloc(maxsze, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL))) { + kfree(urb); + kfree(wd); + return -ENOMEM; + } + wd->handler=handler; + wd->context=dev_id; + urb->dev = dev; + urb->pipe = pipe; + urb->transfer_buffer_length = urb->actual_length = maxsze; + urb->interval = period; + urb->context = wd; + urb->complete = irq_callback; + if ((ret = usb_submit_urb(urb)) < 0) { + kfree(wd); + kfree(urb->transfer_buffer); + kfree(urb); + return ret; + } + *handle = urb; + + /* Claim the USB bandwidth if no error. */ + if (!ret) { + dev->bus->bandwidth_allocated += bustime; + dev->bus->bandwidth_int_reqs++; + dbg("bw_alloc bumped to %d for %d requesters", + dev->bus->bandwidth_allocated, + dev->bus->bandwidth_int_reqs + + dev->bus->bandwidth_isoc_reqs); + } + + return ret; +} + +int usb_release_irq(struct usb_device *dev, void *handle, unsigned int pipe) +{ + long bustime; + int err; + urb_t *urb = (urb_t*)handle; + + if (!urb) + return -EBADF; + err=usb_unlink_urb(urb); + kfree(urb->context); + kfree(urb->transfer_buffer); + kfree(urb); + + /* Return the USB bandwidth if no error. */ + if (!err) { + bustime = calc_bus_time (usb_pipeslow(pipe), usb_pipein(pipe), 0, + usb_maxpacket(dev, pipe, usb_pipeout(pipe))); + bustime = NS_TO_US(bustime); /* work in microseconds */ + usb_release_bandwidth(dev, bustime); + } + return err; +} + +/* + * usb_get_current_frame_number() + * + * returns the current frame number for the parent USB bus/controller + * of the given USB device. + */ +int usb_get_current_frame_number(struct usb_device *usb_dev) +{ + return usb_dev->bus->op->get_frame_number (usb_dev); +} +/*-------------------------------------------------------------------*/ static int usb_parse_endpoint(struct usb_device *dev, struct usb_endpoint_descriptor *endpoint, unsigned char *buffer, int size) { struct usb_descriptor_header *header; @@ -475,18 +825,22 @@ static int usb_parse_endpoint(struct usb_device *dev, struct usb_endpoint_descri /* Everything should be fine being passed into here, but we sanity */ /* check JIC */ if (header->bLength > size) { - printk(KERN_ERR "usb: ran out of descriptors parsing\n"); + err("ran out of descriptors parsing"); return -1; } if (header->bDescriptorType != USB_DT_ENDPOINT) { - printk(KERN_INFO "usb: unexpected descriptor 0x%X, expecting endpoint descriptor, type 0x%X\n", + warn("unexpected descriptor 0x%X, expecting endpoint descriptor, type 0x%X", endpoint->bDescriptorType, USB_DT_ENDPOINT); return parsed; } - memcpy(endpoint, buffer, USB_DT_ENDPOINT_SIZE); - le16_to_cpus(&endpoint->wMaxPacketSize); + if (header->bLength == USB_DT_ENDPOINT_AUDIO_SIZE) + memcpy(endpoint, buffer, USB_DT_ENDPOINT_AUDIO_SIZE); + else + memcpy(endpoint, buffer, USB_DT_ENDPOINT_SIZE); + + le16_to_cpus(&endpoint->wMaxPacketSize); buffer += header->bLength; size -= header->bLength; @@ -500,27 +854,28 @@ static int usb_parse_endpoint(struct usb_device *dev, struct usb_endpoint_descri header = (struct usb_descriptor_header *)buffer; if (header->bLength < 2) { - printk(KERN_ERR "usb: invalid descriptor length of %d\n", header->bLength); + err("invalid descriptor length of %d", header->bLength); return -1; } /* If we find another descriptor which is at or below us */ - /* in the descriptor heirarchy then we're done */ + /* in the descriptor heirarchy then we're done */ if ((header->bDescriptorType == USB_DT_ENDPOINT) || (header->bDescriptorType == USB_DT_INTERFACE) || (header->bDescriptorType == USB_DT_CONFIG) || (header->bDescriptorType == USB_DT_DEVICE)) break; + dbg("skipping descriptor 0x%X", + header->bDescriptorType); numskipped++; buffer += header->bLength; size -= header->bLength; parsed += header->bLength; } - if (numskipped) - printk(KERN_INFO "usb: skipped %d class/vendor specific endpoint descriptors\n", numskipped); + dbg("skipped %d class/vendor specific endpoint descriptors", numskipped); /* Copy any unknown descriptors into a storage area for drivers */ /* to later parse */ @@ -532,8 +887,9 @@ static int usb_parse_endpoint(struct usb_device *dev, struct usb_endpoint_descri } endpoint->extra = kmalloc(len, GFP_KERNEL); + if (!endpoint->extra) { - printk(KERN_ERR "Couldn't allocate memory for endpoint extra descriptors\n"); + err("couldn't allocate memory for endpoint extra descriptors"); endpoint->extralen = 0; return parsed; } @@ -556,8 +912,9 @@ static int usb_parse_interface(struct usb_device *dev, struct usb_interface *int interface->max_altsetting = USB_ALTSETTINGALLOC; interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL); + if (!interface->altsetting) { - printk(KERN_ERR "couldn't kmalloc interface->altsetting\n"); + err("couldn't kmalloc interface->altsetting"); return -1; } @@ -569,7 +926,7 @@ static int usb_parse_interface(struct usb_device *dev, struct usb_interface *int oldmas = interface->max_altsetting; interface->max_altsetting += USB_ALTSETTINGALLOC; if (interface->max_altsetting > USB_MAXALTSETTING) { - printk(KERN_WARNING "usb: too many alternate settings (max %d)\n", + warn("too many alternate settings (max %d)", USB_MAXALTSETTING); return -1; } @@ -577,7 +934,7 @@ static int usb_parse_interface(struct usb_device *dev, struct usb_interface *int ptr = interface->altsetting; interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL); if (!interface->altsetting) { - printk("couldn't kmalloc interface->altsetting\n"); + err("couldn't kmalloc interface->altsetting"); interface->altsetting = ptr; return -1; } @@ -604,7 +961,7 @@ static int usb_parse_interface(struct usb_device *dev, struct usb_interface *int header = (struct usb_descriptor_header *)buffer; if (header->bLength < 2) { - printk(KERN_ERR "usb: invalid descriptor length of %d\n", header->bLength); + err("invalid descriptor length of %d", header->bLength); return -1; } @@ -624,7 +981,7 @@ static int usb_parse_interface(struct usb_device *dev, struct usb_interface *int } if (numskipped) - printk(KERN_INFO "usb: skipped %d class/vendor specific interface descriptors\n", numskipped); + dbg("skipped %d class/vendor specific interface descriptors", numskipped); /* Copy any unknown descriptors into a storage area for */ /* drivers to later parse */ @@ -634,8 +991,9 @@ static int usb_parse_interface(struct usb_device *dev, struct usb_interface *int ifp->extralen = 0; } else { ifp->extra = kmalloc(len, GFP_KERNEL); + if (!ifp->extra) { - printk(KERN_ERR "couldn't allocate memory for interface extra descriptors\n"); + err("couldn't allocate memory for interface extra descriptors"); ifp->extralen = 0; return -1; } @@ -651,7 +1009,7 @@ static int usb_parse_interface(struct usb_device *dev, struct usb_interface *int return parsed; if (ifp->bNumEndpoints > USB_MAXENDPOINTS) { - printk(KERN_WARNING "usb: too many endpoints\n"); + warn("too many endpoints"); return -1; } @@ -659,7 +1017,7 @@ static int usb_parse_interface(struct usb_device *dev, struct usb_interface *int kmalloc(ifp->bNumEndpoints * sizeof(struct usb_endpoint_descriptor), GFP_KERNEL); if (!ifp->endpoint) { - printk(KERN_WARNING "usb: out of memory\n"); + err("out of memory"); return -1; } @@ -670,7 +1028,7 @@ static int usb_parse_interface(struct usb_device *dev, struct usb_interface *int header = (struct usb_descriptor_header *)buffer; if (header->bLength > size) { - printk(KERN_ERR "usb: ran out of descriptors parsing\n"); + err("ran out of descriptors parsing"); return -1; } @@ -694,7 +1052,7 @@ static int usb_parse_interface(struct usb_device *dev, struct usb_interface *int return parsed; } -static int usb_parse_configuration(struct usb_device *dev, struct usb_config_descriptor *config, char *buffer) +int usb_parse_configuration(struct usb_device *dev, struct usb_config_descriptor *config, char *buffer) { int i; int retval; @@ -702,20 +1060,20 @@ static int usb_parse_configuration(struct usb_device *dev, struct usb_config_des struct usb_descriptor_header *header; memcpy(config, buffer, USB_DT_INTERFACE_SIZE); - le16_to_cpus(&config->wTotalLength); size = config->wTotalLength; if (config->bNumInterfaces > USB_MAXINTERFACES) { - printk(KERN_WARNING "usb: too many interfaces\n"); + warn("too many interfaces"); return -1; } config->interface = (struct usb_interface *) kmalloc(config->bNumInterfaces * sizeof(struct usb_interface), GFP_KERNEL); + dbg("kmalloc IF %p, numif %i",config->interface,config->bNumInterfaces); if (!config->interface) { - printk(KERN_WARNING "usb: out of memory\n"); + err("out of memory"); return -1; } @@ -728,12 +1086,12 @@ static int usb_parse_configuration(struct usb_device *dev, struct usb_config_des for (i = 0; i < config->bNumInterfaces; i++) { header = (struct usb_descriptor_header *)buffer; if (header->bLength > size) { - printk(KERN_ERR "usb: ran out of descriptors parsing\n"); + err("ran out of descriptors parsing"); return -1; } if (header->bDescriptorType != USB_DT_INTERFACE) { - printk(KERN_INFO "usb: unexpected descriptor 0x%X\n", + warn("unexpected descriptor 0x%X", header->bDescriptorType); buffer += header->bLength; @@ -754,7 +1112,7 @@ static int usb_parse_configuration(struct usb_device *dev, struct usb_config_des void usb_destroy_configuration(struct usb_device *dev) { - int c, i, j; + int c, i, j, k; if (!dev->config) return; @@ -763,24 +1121,34 @@ void usb_destroy_configuration(struct usb_device *dev) struct usb_config_descriptor *cf = &dev->config[c]; if (!cf->interface) - break; + break; for (i = 0; i < cf->bNumInterfaces; i++) { struct usb_interface *ifp = &cf->interface[i]; - + if (!ifp->altsetting) - break; + break; for (j = 0; j < ifp->num_altsetting; j++) { struct usb_interface_descriptor *as = &ifp->altsetting[j]; + + if(as->extra) { + kfree(as->extra); + } if (!as->endpoint) break; - + + for(k = 0; k < as->bNumEndpoints; k++) { + if(as->endpoint[k].extra) { + kfree(as->endpoint[k].extra); + } + } kfree(as->endpoint); } + kfree(ifp->altsetting); } kfree(cf->interface); @@ -801,6 +1169,34 @@ void usb_init_root_hub(struct usb_device *dev) } /* + * __usb_get_extra_descriptor() finds a descriptor of specific type in the + * extra field of the interface and endpoint descriptor structs. + */ + +int __usb_get_extra_descriptor(char *buffer, unsigned size, unsigned char type, void **ptr) +{ + struct usb_descriptor_header *header; + + while (size >= sizeof(struct usb_descriptor_header)) { + header = (struct usb_descriptor_header *)buffer; + + if (header->bLength < 2) { + err("invalid descriptor length of %d", header->bLength); + return -1; + } + + if (header->bDescriptorType == type) { + *ptr = header; + return 0; + } + + buffer += header->bLength; + size -= header->bLength; + } + return -1; +} + +/* * Something got disconnected. Get rid of it, and all of its children. */ void usb_disconnect(struct usb_device **pdev) @@ -813,18 +1209,18 @@ void usb_disconnect(struct usb_device **pdev) *pdev = NULL; - printk("usbcore: USB disconnect on device %d\n", dev->devnum); + info("USB disconnect on device %d", dev->devnum); - if (dev->actconfig) { - for (i = 0; i < dev->actconfig->bNumInterfaces; i++) { - struct usb_interface *interface = &dev->actconfig->interface[i]; + if (dev->actconfig) { + for (i = 0; i < dev->actconfig->bNumInterfaces; i++) { + struct usb_interface *interface = &dev->actconfig->interface[i]; struct usb_driver *driver = interface->driver; - if (driver) { - driver->disconnect(dev, interface->private_data); + if (driver) { + driver->disconnect(dev, interface->private_data); usb_driver_release_interface(driver, interface); - } - } - } + } + } + } /* Free up all the children.. */ for (i = 0; i < USB_MAXCHILDREN; i++) { @@ -838,8 +1234,9 @@ void usb_disconnect(struct usb_device **pdev) /* Free up the device itself, including its device number */ if (dev->devnum > 0) clear_bit(dev->devnum, &dev->bus->devmap.devicemap); - + usb_free_dev(dev); + } /* @@ -851,9 +1248,8 @@ void usb_disconnect(struct usb_device **pdev) void usb_connect(struct usb_device *dev) { int devnum; - - dev->descriptor.bMaxPacketSize0 = 8; /* Start off at 8 bytes */ - + // FIXME needs locking for SMP!! + dev->descriptor.bMaxPacketSize0 = 8; /* Start off at 8 bytes */ devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, 1); if (devnum < 128) { set_bit(devnum, dev->bus->devmap.devicemap); @@ -865,10 +1261,14 @@ void usb_connect(struct usb_device *dev) * These are the actual routines to send * and receive control messages. */ + +#define GET_TIMEOUT 3 +#define SET_TIMEOUT 3 + int usb_set_address(struct usb_device *dev) { return usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS, - 0, dev->devnum, 0, NULL, 0, HZ); + 0, dev->devnum, 0, NULL, 0, HZ * GET_TIMEOUT); } int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size) @@ -879,18 +1279,26 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char while (i--) { if ((result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, - (type << 8) + index, 0, buf, size, HZ)) >= 0 || - result == USB_ST_STALL) + (type << 8) + index, 0, buf, size, HZ * GET_TIMEOUT)) >= 0 || + result == -EPIPE) break; } return result; } +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, + (type << 8) + id, index, buf, size, HZ * GET_TIMEOUT); +} + int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size) { return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, - (USB_DT_STRING << 8) + index, langid, buf, size, HZ); + (USB_DT_STRING << 8) + index, langid, buf, size, HZ * GET_TIMEOUT); } int usb_get_device_descriptor(struct usb_device *dev) @@ -909,7 +1317,7 @@ int usb_get_device_descriptor(struct usb_device *dev) int usb_get_status(struct usb_device *dev, int type, int target, void *data) { return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2, HZ); + USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2, HZ * GET_TIMEOUT); } int usb_get_protocol(struct usb_device *dev) @@ -919,7 +1327,7 @@ int usb_get_protocol(struct usb_device *dev) if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_PROTOCOL, USB_DIR_IN | USB_RT_HIDD, - 0, 1, &type, 1, HZ)) < 0) + 0, 1, &type, 1, HZ * GET_TIMEOUT)) < 0) return ret; return type; @@ -928,15 +1336,13 @@ 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); + USB_REQ_SET_PROTOCOL, USB_RT_HIDD, protocol, 1, NULL, 0, HZ * SET_TIMEOUT); } -/* keyboards want a nonzero duration according to HID spec, but - mice should use infinity (0) -keryan */ 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); + USB_RT_HIDD, (duration << 8) | report_id, 1, NULL, 0, HZ * SET_TIMEOUT); } static void usb_set_maxpacket(struct usb_device *dev) @@ -979,7 +1385,7 @@ 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); + USB_REQ_CLEAR_FEATURE, USB_RT_ENDPOINT, 0, endp, NULL, 0, HZ * SET_TIMEOUT); /* don't clear if failed */ if (result < 0) @@ -987,12 +1393,12 @@ int usb_clear_halt(struct usb_device *dev, int endp) result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_ENDPOINT, 0, endp, - &status, sizeof(status), HZ); + &status, sizeof(status), HZ * SET_TIMEOUT); if (result < 0) return result; if (status & 1) - return USB_ST_STALL; /* still halted */ + return -EPIPE; /* still halted */ usb_endpoint_running(dev, endp & 0x0f, usb_endpoint_out(endp)); @@ -1005,14 +1411,26 @@ int usb_clear_halt(struct usb_device *dev, int endp) int usb_set_interface(struct usb_device *dev, int interface, int alternate) { - int ret; + struct usb_interface *iface = NULL; + int ret, i; + + for (i=0; i<dev->actconfig->bNumInterfaces; i++) { + if (dev->actconfig->interface[i].altsetting->bInterfaceNumber == interface) { + iface = &dev->actconfig->interface[i]; + break; + } + } + if (!iface) { + warn("selecting invalid interface %d", interface); + return -EINVAL; + } if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_INTERFACE, USB_RT_INTERFACE, alternate, - interface, NULL, 0, HZ)) < 0) + interface, NULL, 0, HZ * 5)) < 0) return ret; - dev->actconfig->interface[interface].act_altsetting = alternate; + iface->act_altsetting = alternate; usb_set_maxpacket(dev); return 0; } @@ -1029,12 +1447,12 @@ int usb_set_configuration(struct usb_device *dev, int configuration) } } if (!cp) { - printk(KERN_INFO "usb: selecting invalid configuration %d\n", configuration); + warn("selecting invalid configuration %d", configuration); return -1; } if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_SET_CONFIGURATION, 0, configuration, 0, NULL, 0, HZ)) < 0) + USB_REQ_SET_CONFIGURATION, 0, configuration, 0, NULL, 0, HZ * SET_TIMEOUT)) < 0) return ret; dev->actconfig = cp; @@ -1049,11 +1467,19 @@ int usb_get_report(struct usb_device *dev, unsigned char type, unsigned char id, { return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_REPORT, USB_DIR_IN | USB_RT_HIDD, + (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, (type << 8) + id, index, buf, size, HZ); } int usb_get_configuration(struct usb_device *dev) { + int result; unsigned int cfgno; unsigned char buffer[8]; unsigned char *bigbuffer; @@ -1061,7 +1487,7 @@ int usb_get_configuration(struct usb_device *dev) (struct usb_config_descriptor *)buffer; if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) { - printk(KERN_WARNING "usb: too many configurations\n"); + warn("too many configurations"); return -1; } @@ -1069,21 +1495,21 @@ int usb_get_configuration(struct usb_device *dev) kmalloc(dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor), GFP_KERNEL); if (!dev->config) { - printk(KERN_WARNING "usb: out of memory.\n"); + err("out of memory"); return -1; } memset(dev->config, 0, dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor)); for (cfgno = 0; cfgno < dev->descriptor.bNumConfigurations; cfgno++) { - int result; + /* We grab the first 8 bytes so we know how long the whole */ /* configuration is */ result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8); if (result < 0) { - printk(KERN_ERR "usb: unable to get descriptor\n"); - return result; + err("unable to get descriptor"); + goto err; } /* Get the full buffer */ @@ -1091,28 +1517,34 @@ int usb_get_configuration(struct usb_device *dev) bigbuffer = kmalloc(desc->wTotalLength, GFP_KERNEL); if (!bigbuffer) { - printk(KERN_ERR "unable to allocate memory for configuration descriptors\n"); - return USB_ST_INTERNALERROR; + err("unable to allocate memory for configuration descriptors"); + result=-ENOMEM; + goto err; } /* Now that we know the length, get the whole thing */ result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, desc->wTotalLength); if (result < 0) { - printk(KERN_ERR "couldn't get all of config descriptors\n"); + err("couldn't get all of config descriptors"); kfree(bigbuffer); - return result; - } - + goto err; + } result = usb_parse_configuration(dev, &dev->config[cfgno], bigbuffer); kfree(bigbuffer); if (result > 0) - printk(KERN_INFO "usb: descriptor data left\n"); + dbg("descriptor data left"); else if (result < 0) - return -1; + { + result=-1; + goto err; + } } return 0; + err: + dev->descriptor.bNumConfigurations=cfgno; + return result; } char *usb_string(struct usb_device *dev, int index) @@ -1135,14 +1567,14 @@ char *usb_string(struct usb_device *dev, int index) if (ret >= 0 && u.desc.bLength >= 4) dev->string_langid = le16_to_cpup(&u.desc.wData[0]); else - printk(KERN_ERR "usb: error getting string!\n"); + err("error getting string"); dev->string_langid |= 0x10000; /* so it's non-zero */ } 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)) { - printk(KERN_ERR "usb: error retrieving string\n"); + err("error retrieving string"); return NULL; } @@ -1153,7 +1585,7 @@ char *usb_string(struct usb_device *dev, int index) ptr = kmalloc(len, GFP_KERNEL); if (!ptr) { - printk(KERN_ERR "usb: couldn't allocate memory for string\n"); + err("couldn't allocate memory for string"); return NULL; } @@ -1176,9 +1608,9 @@ int usb_new_device(struct usb_device *dev) { int addr, err; - printk(KERN_INFO "USB new device connect, assigned device number %d\n", + 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; dev->epmaxpacketout[0] = 8; @@ -1189,7 +1621,8 @@ int usb_new_device(struct usb_device *dev) err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8); if (err < 0) { - printk(KERN_ERR "usbcore: USB device not responding, giving up (error=%d)\n", err); + err("USB device not responding, giving up (error=%d)", err); + clear_bit(addr, &dev->bus->devmap.devicemap); dev->devnum = -1; return 1; } @@ -1206,8 +1639,10 @@ int usb_new_device(struct usb_device *dev) dev->devnum = addr; err = usb_set_address(dev); + if (err < 0) { - printk(KERN_ERR "usbcore: USB device not accepting new address (error=%d)\n", err); + err("USB device not accepting new address (error=%d)", err); + clear_bit(dev->devnum, &dev->bus->devmap.devicemap); dev->devnum = -1; return 1; } @@ -1216,14 +1651,17 @@ int usb_new_device(struct usb_device *dev) err = usb_get_device_descriptor(dev); if (err < 0) { - printk(KERN_ERR "usbcore: unable to get device descriptor (error=%d)\n", err); + err("unable to get device descriptor (error=%d)",err); + clear_bit(dev->devnum, &dev->bus->devmap.devicemap); dev->devnum = -1; return 1; } - err = usb_get_configuration(dev); + err=usb_get_configuration(dev); + if (err < 0) { - printk(KERN_ERR "usbcore: unable to get configuration (error=%d)\n", err); + err("unable to get configuration (error=%d)", err); + clear_bit(dev->devnum, &dev->bus->devmap.devicemap); dev->devnum = -1; return 1; } @@ -1233,7 +1671,7 @@ int usb_new_device(struct usb_device *dev) /* we set the default configuration here */ if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) { - printk(KERN_ERR "usbcore: failed to set default configuration\n"); + err("failed to set default configuration"); return -1; } @@ -1245,189 +1683,11 @@ int usb_new_device(struct usb_device *dev) proc_usb_add_device(dev); /* find drivers willing to handle this device */ - usb_find_drivers(dev); + usb_find_drivers(dev); return 0; } -int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout) -{ - devrequest dr; - int ret; - - dr.requesttype = requesttype; - dr.request = request; - dr.value = cpu_to_le16p(&value); - dr.index = cpu_to_le16p(&index); - dr.length = cpu_to_le16p(&size); - - ret = dev->bus->op->control_msg(dev, pipe, &dr, data, size, timeout); - - if (ret < 0 && usb_debug) { - unsigned char *p = (unsigned char *)&dr; - - printk(KERN_DEBUG "Failed control msg - r:%02X rt:%02X v:%04X i:%04X s:%04X - ret: %d\n", - request, requesttype, value, index, size, ret); - printk(KERN_DEBUG " %02X %02X %02X %02X %02X %02X %02X %02X\n", - p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); - } - - return ret; -} - -int usb_request_irq(struct usb_device *dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id, void **handle) -{ - long bustime; - int ret; - - *handle = NULL; - - /* Check host controller's bandwidth for this int. request. */ - bustime = calc_bus_time (usb_pipeslow(pipe), usb_pipein(pipe), 0, - usb_maxpacket(dev, pipe, usb_pipeout(pipe))); - bustime = NS_TO_US(bustime); /* work in microseconds */ - if (check_bandwidth_alloc (dev->bus->bandwidth_allocated, bustime)) - return (USB_ST_BANDWIDTH_ERROR); - - ret = dev->bus->op->request_irq(dev, pipe, handler, period, dev_id, handle, bustime); - - /* Claim the USB bandwidth if no error. */ - if (!ret) { - dev->bus->bandwidth_allocated += bustime; - dev->bus->bandwidth_int_reqs++; - PRINTD ("bw_alloc bumped to %d for %d requesters", - dev->bus->bandwidth_allocated, - dev->bus->bandwidth_int_reqs + - dev->bus->bandwidth_isoc_reqs); - } - - return ret; -} - -int usb_bulk_msg(struct usb_device *dev, unsigned int pipe, void *data, int len, unsigned long *rval, int timeout) -{ - return dev->bus->op->bulk_msg(dev, pipe, data, len, rval, timeout); -} - -void *usb_request_bulk(struct usb_device *dev, unsigned int pipe, usb_device_irq handler, void *data, int len, void *dev_id) -{ - return dev->bus->op->request_bulk(dev, pipe, handler, data, len, dev_id); -} - -int usb_terminate_bulk(struct usb_device *dev, void *first) -{ - return dev->bus->op->terminate_bulk(dev, first); -} - -/* - * usb_release_bandwidth(): - * - * called to release an interrupt pipe's bandwidth (in microseconds) - */ -void usb_release_bandwidth(struct usb_device *dev, int bw_alloc) -{ - dev->bus->bandwidth_allocated -= bw_alloc; - dev->bus->bandwidth_int_reqs--; - PRINTD ("bw_alloc reduced to %d for %d requesters", - dev->bus->bandwidth_allocated, - dev->bus->bandwidth_int_reqs + - dev->bus->bandwidth_isoc_reqs); -} - -int usb_release_irq(struct usb_device *dev, void *handle, unsigned int pipe) -{ - long bustime; - int err; - - err = dev->bus->op->release_irq(dev, handle); - - /* Return the USB bandwidth if no error. */ - if (!err) { - bustime = calc_bus_time (usb_pipeslow(pipe), usb_pipein(pipe), 0, - usb_maxpacket(dev, pipe, usb_pipeout(pipe))); - bustime = NS_TO_US(bustime); /* work in microseconds */ - usb_release_bandwidth(dev, bustime); - } - - return err; -} - -/* - * usb_get_current_frame_number() - * - * returns the current frame number for the parent USB bus/controller - * of the given USB device. - */ -int usb_get_current_frame_number(struct usb_device *usb_dev) -{ - return usb_dev->bus->op->get_frame_number (usb_dev); -} - -int usb_init_isoc(struct usb_device *usb_dev, - unsigned int pipe, - int frame_count, - void *context, - struct usb_isoc_desc **isocdesc) -{ - long bustime; - int err; - - if (frame_count <= 0) - return -EINVAL; - - /* Check host controller's bandwidth for this Isoc. request. */ - /* TBD: some way to factor in frame_spacing ??? */ - bustime = calc_bus_time (0, usb_pipein(pipe), 1, - usb_maxpacket(usb_dev, pipe, usb_pipeout(pipe))); - bustime = NS_TO_US(bustime) / frame_count; /* work in microseconds */ - if (check_bandwidth_alloc (usb_dev->bus->bandwidth_allocated, bustime)) - return USB_ST_BANDWIDTH_ERROR; - - err = usb_dev->bus->op->init_isoc (usb_dev, pipe, frame_count, context, isocdesc); - - /* Claim the USB bandwidth if no error. */ - if (!err) { - usb_dev->bus->bandwidth_allocated += bustime; - usb_dev->bus->bandwidth_isoc_reqs++; - PRINTD ("bw_alloc bumped to %d for %d requesters", - usb_dev->bus->bandwidth_allocated, - usb_dev->bus->bandwidth_int_reqs + - usb_dev->bus->bandwidth_isoc_reqs); - } - - return err; -} - -void usb_free_isoc(struct usb_isoc_desc *isocdesc) -{ - long bustime; - - /* Return the USB bandwidth. */ - bustime = calc_bus_time (0, usb_pipein(isocdesc->pipe), 1, - usb_maxpacket(isocdesc->usb_dev, isocdesc->pipe, - usb_pipeout(isocdesc->pipe))); - bustime = NS_TO_US(bustime) / isocdesc->frame_count; - isocdesc->usb_dev->bus->bandwidth_allocated -= bustime; - isocdesc->usb_dev->bus->bandwidth_isoc_reqs--; - PRINTD ("bw_alloc reduced to %d for %d requesters", - isocdesc->usb_dev->bus->bandwidth_allocated, - isocdesc->usb_dev->bus->bandwidth_int_reqs + - isocdesc->usb_dev->bus->bandwidth_isoc_reqs); - - isocdesc->usb_dev->bus->op->free_isoc (isocdesc); -} - -int usb_run_isoc(struct usb_isoc_desc *isocdesc, - struct usb_isoc_desc *pr_isocdesc) -{ - return isocdesc->usb_dev->bus->op->run_isoc (isocdesc, pr_isocdesc); -} - -int usb_kill_isoc(struct usb_isoc_desc *isocdesc) -{ - return isocdesc->usb_dev->bus->op->kill_isoc (isocdesc); -} - static int usb_open(struct inode * inode, struct file * file) { int minor = MINOR(inode->i_rdev); @@ -1442,24 +1702,25 @@ static int usb_open(struct inode * inode, struct file * file) } static struct file_operations usb_fops = { - NULL, /* seek */ + NULL, /* seek */ NULL, /* read */ NULL, /* write */ NULL, /* readdir */ NULL, /* poll */ NULL, /* ioctl */ NULL, /* mmap */ - usb_open, + usb_open, NULL, /* flush */ - NULL /* release */ + NULL /* release */ }; -void usb_major_init(void) +int usb_major_init(void) { if (register_chrdev(USB_MAJOR,"usb",&usb_fops)) { - printk("unable to get major %d for usb devices\n", - USB_MAJOR); + err("unable to get major %d for usb devices", USB_MAJOR); + return -EBUSY; } + return 0; } void usb_major_cleanup(void) @@ -1508,26 +1769,30 @@ EXPORT_SYMBOL(usb_release_bandwidth); 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_string); EXPORT_SYMBOL(usb_string); EXPORT_SYMBOL(usb_get_protocol); EXPORT_SYMBOL(usb_set_protocol); EXPORT_SYMBOL(usb_get_report); +EXPORT_SYMBOL(usb_set_report); EXPORT_SYMBOL(usb_set_idle); EXPORT_SYMBOL(usb_clear_halt); EXPORT_SYMBOL(usb_set_interface); EXPORT_SYMBOL(usb_get_configuration); EXPORT_SYMBOL(usb_set_configuration); +EXPORT_SYMBOL(usb_get_current_frame_number); + +EXPORT_SYMBOL(usb_alloc_urb); +EXPORT_SYMBOL(usb_free_urb); +EXPORT_SYMBOL(usb_submit_urb); +EXPORT_SYMBOL(usb_unlink_urb); + EXPORT_SYMBOL(usb_control_msg); EXPORT_SYMBOL(usb_request_irq); EXPORT_SYMBOL(usb_release_irq); EXPORT_SYMBOL(usb_bulk_msg); EXPORT_SYMBOL(usb_request_bulk); EXPORT_SYMBOL(usb_terminate_bulk); - -EXPORT_SYMBOL(usb_get_current_frame_number); -EXPORT_SYMBOL(usb_init_isoc); -EXPORT_SYMBOL(usb_free_isoc); -EXPORT_SYMBOL(usb_run_isoc); -EXPORT_SYMBOL(usb_kill_isoc); |