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