summaryrefslogtreecommitdiffstats
path: root/drivers/usb/usb.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-05 06:47:02 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-05 06:47:02 +0000
commit99a7e12f34b3661a0d1354eef83a0eef4df5e34c (patch)
tree3560aca9ca86792f9ab7bd87861ea143a1b3c7a3 /drivers/usb/usb.c
parente73a04659c0b8cdee4dd40e58630e2cf63afb316 (diff)
Merge with Linux 2.3.38.
Diffstat (limited to 'drivers/usb/usb.c')
-rw-r--r--drivers/usb/usb.c937
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);