summaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-07-15 03:32:22 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-07-15 03:32:22 +0000
commitf1da2c3860e301527d56a1ef0b56c649ee7c4b1b (patch)
tree562b5d2e8b9cb62eb983d78ff6bcf9789e08fcf6 /drivers/usb
parent00f11569ac8ca73cbcdef8822de1583e79aee571 (diff)
Merge with Linux 2.4.0-test5-pre1. This works again on Origin UP.
The IP22 cache bugs which are plaguing some machines are still unfixed.
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/Config.in4
-rw-r--r--drivers/usb/audio.c31
-rw-r--r--drivers/usb/bluetooth.c9
-rw-r--r--drivers/usb/dabusb.c3
-rw-r--r--drivers/usb/dc2xx.c3
-rw-r--r--drivers/usb/devices.c116
-rw-r--r--drivers/usb/evdev.c6
-rw-r--r--drivers/usb/joydev.c6
-rw-r--r--drivers/usb/mdc800.c3
-rw-r--r--drivers/usb/mousedev.c6
-rw-r--r--drivers/usb/printer.c18
-rw-r--r--drivers/usb/usb.c27
12 files changed, 159 insertions, 73 deletions
diff --git a/drivers/usb/Config.in b/drivers/usb/Config.in
index 55b8b1df5..7e29c7807 100644
--- a/drivers/usb/Config.in
+++ b/drivers/usb/Config.in
@@ -28,6 +28,9 @@ comment 'USB Controllers'
comment 'USB Devices'
dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
dep_tristate ' USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ dep_tristate ' Microtek X6USB scanner support (EXPERIMENTAL)' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI
+ fi
dep_tristate ' USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB $CONFIG_SOUND
dep_tristate ' USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB
dep_tristate ' USB Serial Converter support' CONFIG_USB_SERIAL $CONFIG_USB
@@ -68,7 +71,6 @@ comment 'USB Devices'
dep_tristate ' USB ADMtek Pegasus-based device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET
dep_tristate ' USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB
dep_tristate ' D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV
- dep_tristate ' Microtek X6USB scanner support (EXPERIMENTAL)' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI
dep_tristate ' USB Bluetooth support (EXPERIMENTAL)' CONFIG_USB_BLUETOOTH $CONFIG_USB
fi
diff --git a/drivers/usb/audio.c b/drivers/usb/audio.c
index 67f1635a6..4560ad602 100644
--- a/drivers/usb/audio.c
+++ b/drivers/usb/audio.c
@@ -171,6 +171,7 @@
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include <linux/module.h>
#include <linux/sound.h>
#include <linux/soundcard.h>
@@ -1944,10 +1945,13 @@ static int usb_audio_open_mixdev(struct inode *inode, struct file *file)
static int usb_audio_release_mixdev(struct inode *inode, struct file *file)
{
struct usb_mixerdev *ms = (struct usb_mixerdev *)file->private_data;
- struct usb_audio_state *s = ms->state;
+ struct usb_audio_state *s;
+ lock_kernel();
+ s = ms->state;
down(&open_sem);
release(s);
+ unlock_kernel();
return 0;
}
@@ -2283,23 +2287,28 @@ static int usb_audio_mmap(struct file *file, struct vm_area_struct *vma)
{
struct usb_audiodev *as = (struct usb_audiodev *)file->private_data;
struct dmabuf *db;
- int ret;
+ int ret = -EINVAL;
+ lock_kernel();
if (vma->vm_flags & VM_WRITE) {
if ((ret = prog_dmabuf_out(as)) != 0)
- return ret;
+ goto out;
db = &as->usbout.dma;
} else if (vma->vm_flags & VM_READ) {
if ((ret = prog_dmabuf_in(as)) != 0)
- return ret;
+ goto out;
db = &as->usbin.dma;
} else
- return -EINVAL;
+ goto out;
+ ret = -EINVAL;
if (vma->vm_pgoff != 0)
- return -EINVAL;
+ goto out;
- return dmabuf_mmap(db, vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot);
+ ret = dmabuf_mmap(db, vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot);
+out:
+ unlock_kernel();
+ return ret;
}
static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -2615,10 +2624,13 @@ static int usb_audio_open(struct inode *inode, struct file *file)
static int usb_audio_release(struct inode *inode, struct file *file)
{
struct usb_audiodev *as = (struct usb_audiodev *)file->private_data;
- struct usb_audio_state *s = as->state;
- struct usb_device *dev = s->usbdev;
+ struct usb_audio_state *s;
+ struct usb_device *dev;
struct usb_interface *iface;
+ lock_kernel();
+ s = as->state;
+ dev = s->usbdev;
if (file->f_mode & FMODE_WRITE)
drain_out(as, file->f_flags & O_NONBLOCK);
down(&open_sem);
@@ -2643,6 +2655,7 @@ static int usb_audio_release(struct inode *inode, struct file *file)
as->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
release(s);
wake_up(&open_wait);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/usb/bluetooth.c b/drivers/usb/bluetooth.c
index aaea67a4c..bd7be69e8 100644
--- a/drivers/usb/bluetooth.c
+++ b/drivers/usb/bluetooth.c
@@ -1,11 +1,15 @@
/*
- * bluetooth.c Version 0.1
+ * bluetooth.c Version 0.2
*
* Copyright (c) 2000 Greg Kroah-Hartman <greg@kroah.com>
*
* USB Bluetooth driver, based on the Bluetooth Spec version 1.0B
*
*
+ * (07/11/2000) Version 0.2 gkh
+ * Fixed a small bug found by Nils Faerber in the usb_bluetooth_probe
+ * function.
+ *
* (07/09/2000) Version 0.1 gkh
* Initial release. Has support for sending ACL data (which is really just
* a HCI frame.) Raw HCI commands and HCI events are not supported.
@@ -619,6 +623,7 @@ static void * usb_bluetooth_probe(struct usb_device *dev, unsigned int ifnum)
memset(bluetooth, 0, sizeof(struct usb_bluetooth));
+ bluetooth->magic = USB_BLUETOOTH_MAGIC;
bluetooth->dev = dev;
bluetooth->minor = minor;
bluetooth->tqueue.routine = bluetooth_softint;
@@ -676,6 +681,8 @@ static void * usb_bluetooth_probe(struct usb_device *dev, unsigned int ifnum)
tty_register_devfs (&bluetooth_tty_driver, 0, minor);
info("Bluetooth converter now attached to ttyBLUE%d (or usb/ttblue/%d for devfs)", minor, minor);
+ bluetooth_table[minor] = bluetooth;
+
return bluetooth; /* success */
probe_error:
diff --git a/drivers/usb/dabusb.c b/drivers/usb/dabusb.c
index 8b1df4edf..9b3bc24fa 100644
--- a/drivers/usb/dabusb.c
+++ b/drivers/usb/dabusb.c
@@ -38,6 +38,7 @@
#include <asm/atomic.h>
#include <linux/delay.h>
#include <linux/usb.h>
+#include <linux/smp_lock.h>
#include "dabusb.h"
#include "dabfirmware.h"
@@ -613,6 +614,7 @@ static int dabusb_release (struct inode *inode, struct file *file)
dbg("dabusb_release");
+ lock_kernel();
down (&s->mutex);
dabusb_stop (s);
dabusb_free_buffers (s);
@@ -626,6 +628,7 @@ static int dabusb_release (struct inode *inode, struct file *file)
wake_up (&s->remove_ok);
s->opened = 0;
+ unlock_kernel();
return 0;
}
diff --git a/drivers/usb/dc2xx.c b/drivers/usb/dc2xx.c
index 4fcfa640c..bb960a4af 100644
--- a/drivers/usb/dc2xx.c
+++ b/drivers/usb/dc2xx.c
@@ -60,6 +60,7 @@
#include <linux/module.h>
#undef DEBUG
#include <linux/usb.h>
+#include <linux/smp_lock.h>
@@ -298,10 +299,12 @@ static int camera_release (struct inode *inode, struct file *file)
kfree (camera->buf);
/* If camera was unplugged with open file ... */
+ lock_kernel();
if (!camera->dev) {
minor_data [camera->subminor] = NULL;
kfree (camera);
}
+ unlock_kernel();
dbg ("close");
diff --git a/drivers/usb/devices.c b/drivers/usb/devices.c
index c99f86973..df02bcf2a 100644
--- a/drivers/usb/devices.c
+++ b/drivers/usb/devices.c
@@ -45,6 +45,9 @@
* up an eventual usbd
* 2000-01-04: Thomas Sailer <sailer@ife.ee.ethz.ch>
* Turned into its own filesystem
+ * 2000-07-05: Ashley Montanaro <ashley@compsoc.man.ac.uk>
+ * Converted file reading routine to dump to buffer once
+ * per device, not per bus
*
* $Id: devices.c,v 1.5 2000/01/11 13:58:21 tom Exp $
*/
@@ -367,23 +370,40 @@ static char *usb_dump_string(char *start, char *end, const struct usb_device *de
/*****************************************************************/
-static char *usb_device_dump(char *start, char *end, struct usb_device *usbdev,
- struct usb_bus *bus, int level, int index, int count)
+/* This is a recursive function. Parameters:
+ * buffer - the user-space buffer to write data into
+ * nbytes - the maximum number of bytes to write
+ * skip_bytes - the number of bytes to skip before writing anything
+ * file_offset - the offset into the devices file on completion
+ */
+static ssize_t usb_device_dump(char **buffer, size_t *nbytes, loff_t *skip_bytes, loff_t *file_offset,
+ struct usb_device *usbdev, struct usb_bus *bus, int level, int index, int count)
{
int chix;
- int cnt = 0;
+ int ret, cnt = 0;
int parent_devnum = 0;
-
+ char *pages_start, *data_end;
+ unsigned int length;
+ ssize_t total_written = 0;
+
+ /* don't bother with anything else if we're not writing any data */
+ if (*nbytes <= 0)
+ return 0;
+
if (level > MAX_TOPO_LEVEL)
- return start;
+ return total_written;
+ /* allocate 2^1 pages = 8K (on i386); should be more than enough for one device */
+ if (!(pages_start = (char*) __get_free_pages(GFP_KERNEL,1)))
+ return -ENOMEM;
+
if (usbdev->parent && usbdev->parent->devnum != -1)
parent_devnum = usbdev->parent->devnum;
/*
* So the root hub's parent is 0 and any device that is
* plugged into the root hub has a parent of 0.
*/
- start += sprintf(start, format_topo, bus->busnum, level, parent_devnum, index, count,
- usbdev->devnum, usbdev->slow ? "1.5" : "12 ", usbdev->maxchild);
+ data_end = pages_start + sprintf(pages_start, format_topo, bus->busnum, level, parent_devnum, index, count,
+ usbdev->devnum, usbdev->slow ? "1.5" : "12 ", usbdev->maxchild);
/*
* level = topology-tier level;
* parent_devnum = parent device number;
@@ -392,30 +412,58 @@ static char *usb_device_dump(char *start, char *end, struct usb_device *usbdev,
*/
/* If this is the root hub, display the bandwidth information */
if (level == 0)
- start += sprintf(start, format_bandwidth, bus->bandwidth_allocated,
+ data_end += sprintf(data_end, format_bandwidth, bus->bandwidth_allocated,
FRAME_TIME_MAX_USECS_ALLOC,
(100 * bus->bandwidth_allocated + FRAME_TIME_MAX_USECS_ALLOC / 2) / FRAME_TIME_MAX_USECS_ALLOC,
bus->bandwidth_int_reqs, bus->bandwidth_isoc_reqs);
- start = usb_dump_desc(start, end, usbdev);
- if (start > end)
- return start + sprintf(start, "(truncated)\n");
+
+ data_end = usb_dump_desc(data_end, pages_start + (2 * PAGE_SIZE) - 256, usbdev);
+
+ if (data_end > (pages_start + (2 * PAGE_SIZE) - 256))
+ data_end += sprintf(data_end, "(truncated)\n");
+
+ length = data_end - pages_start;
+ /* if we can start copying some data to the user */
+ if (length > *skip_bytes) {
+ length -= *skip_bytes;
+ if (length > *nbytes)
+ length = *nbytes;
+ if (copy_to_user(*buffer, pages_start + *skip_bytes, length)) {
+ free_pages((unsigned long)pages_start, 1);
+
+ if (total_written == 0)
+ return -EFAULT;
+ return total_written;
+ }
+ *nbytes -= length;
+ *file_offset += length;
+ total_written += length;
+ *buffer += length;
+ *skip_bytes = 0;
+ } else
+ *skip_bytes -= length;
+
+ free_pages((unsigned long)pages_start, 1);
+
/* Now look at all of this device's children. */
for (chix = 0; chix < usbdev->maxchild; chix++) {
- if (start > end)
- return start;
- if (usbdev->children[chix])
- start = usb_device_dump(start, end, usbdev->children[chix], bus, level + 1, chix, ++cnt);
+ if (usbdev->children[chix]) {
+ ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, usbdev->children[chix],
+ bus, level + 1, chix, ++cnt);
+ if (ret == -EFAULT)
+ return total_written;
+ total_written += ret;
+ }
}
- return start;
+ return total_written;
}
static ssize_t usb_device_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
{
struct list_head *buslist;
struct usb_bus *bus;
- char *page, *end;
- ssize_t ret = 0;
- unsigned int pos, len;
+ ssize_t ret, total_written = 0;
+ loff_t skip_bytes = *ppos;
if (*ppos < 0)
return -EINVAL;
@@ -423,34 +471,18 @@ static ssize_t usb_device_read(struct file *file, char *buf, size_t nbytes, loff
return 0;
if (!access_ok(VERIFY_WRITE, buf, nbytes))
return -EFAULT;
- if (!(page = (char*) __get_free_pages(GFP_KERNEL,1)))
- return -ENOMEM;
- pos = *ppos;
+
/* enumerate busses */
for (buslist = usb_bus_list.next; buslist != &usb_bus_list; buslist = buslist->next) {
/* print devices for this bus */
bus = list_entry(buslist, struct usb_bus, bus_list);
- end = usb_device_dump(page, page + (2*PAGE_SIZE - 256), bus->root_hub, bus, 0, 0, 0);
- len = end - page;
- if (len > pos) {
- len -= pos;
- if (len > nbytes)
- len = nbytes;
- if (copy_to_user(buf, page + pos, len)) {
- if (!ret)
- ret = -EFAULT;
- break;
- }
- nbytes -= len;
- buf += len;
- ret += len;
- pos = 0;
- *ppos += len;
- } else
- pos -= len;
+ /* recurse through all children of the root hub */
+ ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0);
+ if (ret < 0)
+ return ret;
+ total_written += ret;
}
- free_pages((unsigned long)page, 1);
- return ret;
+ return total_written;
}
/* Kernel lock for "lastev" protection */
diff --git a/drivers/usb/evdev.c b/drivers/usb/evdev.c
index 7eca5e304..e11327cef 100644
--- a/drivers/usb/evdev.c
+++ b/drivers/usb/evdev.c
@@ -37,6 +37,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
+#include <linux/smp_lock.h>
struct evdev {
int exist;
@@ -91,8 +92,10 @@ static int evdev_fasync(int fd, struct file *file, int on)
static int evdev_release(struct inode * inode, struct file * file)
{
struct evdev_list *list = file->private_data;
- struct evdev_list **listptr = &list->evdev->list;
+ struct evdev_list **listptr;
+ lock_kernel();
+ listptr = &list->evdev->list;
evdev_fasync(-1, file, 0);
while (*listptr && (*listptr != list))
@@ -110,6 +113,7 @@ static int evdev_release(struct inode * inode, struct file * file)
}
kfree(list);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/usb/joydev.c b/drivers/usb/joydev.c
index 5349d515c..2210ad0d1 100644
--- a/drivers/usb/joydev.c
+++ b/drivers/usb/joydev.c
@@ -44,6 +44,7 @@
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/init.h>
+#include <linux/smp_lock.h>
#define JOYDEV_MINOR_BASE 0
#define JOYDEV_MINORS 32
@@ -160,8 +161,10 @@ static int joydev_fasync(int fd, struct file *file, int on)
static int joydev_release(struct inode * inode, struct file * file)
{
struct joydev_list *list = file->private_data;
- struct joydev_list **listptr = &list->joydev->list;
+ struct joydev_list **listptr;
+ lock_kernel();
+ listptr = &list->joydev->list;
joydev_fasync(-1, file, 0);
while (*listptr && (*listptr != list))
@@ -179,6 +182,7 @@ static int joydev_release(struct inode * inode, struct file * file)
}
kfree(list);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/usb/mdc800.c b/drivers/usb/mdc800.c
index dc578df33..80a1ebbf4 100644
--- a/drivers/usb/mdc800.c
+++ b/drivers/usb/mdc800.c
@@ -76,6 +76,7 @@
#include <linux/init.h>
#include <linux/malloc.h>
#include <linux/module.h>
+#include <linux/smp_lock.h>
#include <linux/usb.h>
@@ -582,6 +583,7 @@ static int mdc800_device_release (struct inode* inode, struct file *file)
int retval=0;
dbg ("Mustek MDC800 device closed.");
+ lock_kernel();
if (mdc800->open && (mdc800->state != NOT_CONNECTED))
{
mdc800->open=0;
@@ -593,6 +595,7 @@ static int mdc800_device_release (struct inode* inode, struct file *file)
{
retval=-EIO;
}
+ unlock_kernel();
return retval;
}
diff --git a/drivers/usb/mousedev.c b/drivers/usb/mousedev.c
index 5c871a88d..ea5ad301b 100644
--- a/drivers/usb/mousedev.c
+++ b/drivers/usb/mousedev.c
@@ -38,6 +38,7 @@
#include <linux/init.h>
#include <linux/input.h>
#include <linux/config.h>
+#include <linux/smp_lock.h>
#ifndef CONFIG_INPUT_MOUSEDEV_SCREEN_X
#define CONFIG_INPUT_MOUSEDEV_SCREEN_X 1024
@@ -159,8 +160,10 @@ static int mousedev_fasync(int fd, struct file *file, int on)
static int mousedev_release(struct inode * inode, struct file * file)
{
struct mousedev_list *list = file->private_data;
- struct mousedev_list **listptr = &list->mousedev->list;
+ struct mousedev_list **listptr;
+ lock_kernel();
+ listptr = &list->mousedev->list;
mousedev_fasync(-1, file, 0);
while (*listptr && (*listptr != list))
@@ -197,6 +200,7 @@ static int mousedev_release(struct inode * inode, struct file * file)
}
kfree(list);
+ unlock_kernel();
return 0;
}
diff --git a/drivers/usb/printer.c b/drivers/usb/printer.c
index 4dc11aee0..987f1a8b5 100644
--- a/drivers/usb/printer.c
+++ b/drivers/usb/printer.c
@@ -37,6 +37,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include <linux/signal.h>
#include <linux/poll.h>
#include <linux/init.h>
@@ -167,17 +168,19 @@ static int usblp_open(struct inode *inode, struct file *file)
if (minor < 0 || minor >= USBLP_MINORS)
return -ENODEV;
+ lock_kernel();
usblp = usblp_table[minor];
+ retval = -ENODEV;
if (!usblp || !usblp->dev)
- return -ENODEV;
+ goto out;
+ retval = -EBUSY;
if (usblp->used)
- return -EBUSY;
+ goto out;
- if ((retval = usblp_check_status(usblp))) {
- return retval;
- }
+ if ((retval = usblp_check_status(usblp)))
+ goto out;
usblp->used = 1;
file->private_data = usblp;
@@ -189,8 +192,9 @@ static int usblp_open(struct inode *inode, struct file *file)
usblp->readcount = 0;
usb_submit_urb(&usblp->readurb);
}
-
- return 0;
+out:
+ unlock_kernel();
+ return retval;
}
static int usblp_release(struct inode *inode, struct file *file)
diff --git a/drivers/usb/usb.c b/drivers/usb/usb.c
index 3fba783e0..9c650cfdc 100644
--- a/drivers/usb/usb.c
+++ b/drivers/usb/usb.c
@@ -58,8 +58,6 @@ static struct usb_driver *usb_minors[16];
int usb_register(struct usb_driver *new_driver)
{
- struct list_head *tmp;
-
if (new_driver->fops != NULL) {
if (usb_minors[new_driver->minor/16]) {
err("error registering %s driver", new_driver->name);
@@ -75,13 +73,22 @@ int usb_register(struct usb_driver *new_driver)
/* Add it to the list of known drivers */
list_add(&new_driver->driver_list, &usb_driver_list);
- /*
- * We go through all existing devices, and see if any of them would
- * be acceptable to the new driver.. This is done using a depth-first
- * search for devices without a registered driver already, then
- * running 'probe' with each of the drivers registered on every one
- * of these.
- */
+ usb_scan_devices();
+
+ return 0;
+}
+
+/*
+ * We go through all existing devices, and see if any of them would
+ * be acceptable to the new driver.. This is done using a depth-first
+ * search for devices without a registered driver already, then
+ * running 'probe' with each of the drivers registered on every one
+ * of these.
+ */
+void usb_scan_devices(void)
+{
+ struct list_head *tmp;
+
tmp = usb_bus_list.next;
while (tmp != &usb_bus_list) {
struct usb_bus *bus = list_entry(tmp,struct usb_bus, bus_list);
@@ -89,7 +96,6 @@ int usb_register(struct usb_driver *new_driver)
tmp = tmp->next;
usb_check_support(bus->root_hub);
}
- return 0;
}
/*
@@ -1772,6 +1778,7 @@ EXPORT_SYMBOL(usb_ifnum_to_if);
EXPORT_SYMBOL(usb_register);
EXPORT_SYMBOL(usb_deregister);
+EXPORT_SYMBOL(usb_scan_devices);
EXPORT_SYMBOL(usb_alloc_bus);
EXPORT_SYMBOL(usb_free_bus);
EXPORT_SYMBOL(usb_register_bus);