Commit f0dbe47d authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://linuxusb.bkbits.net/linus-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 2ce059ec f123a327
18-Dec-2001
26-Apr-2002
The EHCI driver is used to talk to high speed USB 2.0 devices using
USB 2.0-capable host controller hardware. The USB 2.0 standard is
......@@ -19,6 +19,9 @@ interact with the EHCI controller through a "Transaction Translator"
(TT) in the hub, which turns low or full speed transactions into
high speed "split transactions" that don't waste transfer bandwidth.
At this writing, this driver has been seen to work with implementations
of EHCI from (in alphabetical order): Intel, NEC, Philips, and VIA.
At this writing, high speed devices are finally beginning to appear.
While usb-storage devices have been available for some time (working
quite speedily on the 2.4 version of this driver), hubs have only
......@@ -36,7 +39,7 @@ APIs exposed to USB device drivers.
FUNCTIONALITY
This driver is regularly tested on x86 hardware, and has also been
used on PPC hardware so big/little endianneess issues should be gone.
used on PPC hardware so big/little endianness issues should be gone.
It's believed to do all the right PCI magic so that I/O works even on
systems with interesting DMA mapping issues.
......@@ -51,11 +54,13 @@ scheduling for interrupt transfers, which means among other things that
connecting USB 1.1 hubs, keyboards, and mice to USB 2.0 hubs won't work.
Connect them to USB 1.1 hubs, or to a root hub.
Isochronous (ISO) transfer support is not yet working. No production
Isochronous (ISO) transfer support is also newly functional. No production
high speed devices are available which would need it (though high quality
webcams are in the works!). Note that split transaction support for ISO
transfers can't share much code with the code for high speed ISO transfers,
since EHCI represents these with a different data structure.
since EHCI represents these with a different data structure. So for now,
most USB audio and video devices have the same restrictions as hubs, mice,
and keyboards: don't connect them using high speed USB hubs.
The EHCI root hub code should hand off USB 1.1 devices to its companion
controller. This driver doesn't need to know anything about those
......@@ -99,6 +104,8 @@ Device drivers shouldn't care whether they're running over EHCI or not,
but they may want to check for "usb_device->speed == USB_SPEED_HIGH".
High speed devices can do things that full speed (or low speed) ones
can't, such as "high bandwidth" periodic (interrupt or ISO) transfers.
Also, some values in device descriptors (such as polling intervals for
periodic transfers) use different encodings when operating at high speed.
PERFORMANCE
......
......@@ -69,3 +69,11 @@ CONFIG_USB_BANDWIDTH
If you say N here, these conditions will cause warning messages
about USB bandwidth usage to be logged and some devices or
drivers may not work correctly.
CONFIG_USB_DYNAMIC_MINORS
If you say Y here, the USB subsystem will use dynamic minor
allocation for any device that uses the USB major number.
This means that you can have more than 16 of a single type
of device (like USB printers).
If you are unsure about this, say N here.
......@@ -107,7 +107,11 @@ MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:H
#define USBLP_REQ_RESET 0x02
#define USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST 0x00 /* HP Vendor-specific */
#ifdef CONFIG_USB_DYNAMIC_MINORS
#define USBLP_MINORS 256
#else
#define USBLP_MINORS 16
#endif
#define USBLP_MINOR_BASE 0
#define USBLP_WRITE_TIMEOUT (5*HZ) /* 5 seconds */
......@@ -208,6 +212,8 @@ static int usblp_select_alts(struct usblp *usblp);
static int usblp_set_protocol(struct usblp *usblp, int protocol);
static int usblp_cache_device_id_string(struct usblp *usblp);
/* forward reference to make our lives easier */
extern struct usb_driver usblp_driver;
/*
* Functions for usblp control messages.
......@@ -366,6 +372,7 @@ static void usblp_cleanup (struct usblp *usblp)
{
devfs_unregister (usblp->devfs);
usblp_table [usblp->minor] = NULL;
usb_deregister_dev (&usblp_driver, 1, usblp->minor);
info("usblp%d: removed", usblp->minor);
kfree (usblp->writeurb->transfer_buffer);
......@@ -801,12 +808,14 @@ static void *usblp_probe(struct usb_device *dev, unsigned int ifnum,
init_waitqueue_head(&usblp->wait);
usblp->ifnum = ifnum;
/* Look for a free usblp_table entry. */
while (usblp_table[usblp->minor]) {
usblp->minor++;
if (usblp->minor >= USBLP_MINORS) {
err("no more free usblp devices");
goto abort;
if (usb_register_dev(&usblp_driver, 1, &usblp->minor)) {
/* Look for a free usblp_table entry on our own. */
while (usblp_table[usblp->minor]) {
usblp->minor++;
if (usblp->minor >= USBLP_MINORS) {
err("no more free usblp devices");
goto abort;
}
}
}
......
......@@ -4,11 +4,8 @@
bool ' USB verbose debug messages' CONFIG_USB_DEBUG
comment 'Miscellaneous USB options'
bool ' USB device filesystem' CONFIG_USB_DEVICEFS
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
bool ' Enforce USB bandwidth allocation (EXPERIMENTAL)' CONFIG_USB_BANDWIDTH
else
define_bool CONFIG_USB_BANDWIDTH n
fi
bool ' Long timeout for slow-responding devices (some MGE Ellipse UPSes)' CONFIG_USB_LONG_TIMEOUT
bool ' USB device filesystem' CONFIG_USB_DEVICEFS
bool ' Long timeout for slow-responding devices (some MGE Ellipse UPSes)' CONFIG_USB_LONG_TIMEOUT
dep_bool ' Enforce USB bandwidth allocation (EXPERIMENTAL)' CONFIG_USB_BANDWIDTH $CONFIG_EXPERIMENTAL
dep_bool ' Dynamic USB minor allocation (EXPERIMENTAL)' CONFIG_USB_DYNAMIC_MINORS $CONFIG_EXPERIMENTAL
......@@ -11,6 +11,7 @@
more docs, etc)
* (C) Copyright Yggdrasil Computing, Inc. 2000
* (usb_device_id matching changes by Adam J. Richter)
* (C) Copyright Greg Kroah-Hartman 2002
*
* NOTE! This is not actually a driver at all, rather this is
* just a collection of helper routines that implement the
......@@ -59,7 +60,47 @@ LIST_HEAD(usb_driver_list);
devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */
static struct usb_driver *usb_minors[256];
#define MAX_USB_MINORS 256
static struct usb_driver *usb_minors[MAX_USB_MINORS];
static spinlock_t minor_lock = SPIN_LOCK_UNLOCKED;
static int usb_register_minors (struct usb_driver *driver, int num_minors, int start_minor)
{
int i;
dbg("registering %d minors, starting at %d", num_minors, start_minor);
if (start_minor + num_minors >= MAX_USB_MINORS)
return -EINVAL;
spin_lock (&minor_lock);
for (i = start_minor; i < (start_minor + num_minors); ++i)
if (usb_minors[i]) {
spin_unlock (&minor_lock);
err("minor %d is already in use, error registering %s driver",
i, driver->name);
return -EINVAL;
}
for (i = start_minor; i < (start_minor + num_minors); ++i)
usb_minors[i] = driver;
spin_unlock (&minor_lock);
return 0;
}
static void usb_deregister_minors (struct usb_driver *driver, int num_minors, int start_minor)
{
int i;
dbg ("%s is removing %d minors starting at %d", driver->name,
num_minors, start_minor);
spin_lock (&minor_lock);
for (i = start_minor; i < (start_minor + num_minors); ++i)
usb_minors[i] = NULL;
spin_unlock (&minor_lock);
}
/**
* usb_register - register a USB driver
......@@ -72,18 +113,20 @@ static struct usb_driver *usb_minors[256];
*/
int usb_register(struct usb_driver *new_driver)
{
int i;
int retval = 0;
if ((new_driver->fops) && (new_driver->num_minors == 0)) {
err ("%s driver must specify num_minors", new_driver->name);
return -EINVAL;
}
#ifndef CONFIG_USB_DYNAMIC_MINORS
if (new_driver->fops != NULL) {
for (i = new_driver->minor; i < new_driver->minor + new_driver->num_minors; ++i) {
if (usb_minors[i]) {
err("error registering %s driver", new_driver->name);
return -EINVAL;
}
}
for (i = new_driver->minor; i < new_driver->minor + new_driver->num_minors; ++i)
usb_minors[i] = new_driver;
retval = usb_register_minors (new_driver, new_driver->num_minors, new_driver->minor);
if (retval)
return retval;
}
#endif
info("registered new driver %s", new_driver->name);
......@@ -96,9 +139,96 @@ int usb_register(struct usb_driver *new_driver)
usbfs_update_special();
return 0;
return retval;
}
/**
* usb_register_dev - register a USB device, and ask for a minor number
* @new_driver: USB operations for the driver
* @num_minors: number of minor numbers requested for this device
* @start_minor: place to put the new starting minor number
*
* Used to ask the USB core for a new minor number for a device that has
* just showed up. This is used to dynamically allocate minor numbers
* from the pool of USB reserved minor numbers.
*
* This should be called by all drivers that use the USB major number.
* This only returns a good value of CONFIG_USB_DYNAMIC_MINORS is
* selected by the user.
*
* usb_deregister_dev() should be called when the driver is done with
* the minor numbers given out by this function.
*
* Returns -ENODEV if CONFIG_USB_DYNAMIC_MINORS is not enabled in this
* kernel, -EINVAL if something bad happens with trying to register a
* device, and 0 on success, alone with a value that the driver should
* use in start_minor.
*/
#ifdef CONFIG_USB_DYNAMIC_MINORS
int usb_register_dev (struct usb_driver *new_driver, int num_minors, int *start_minor)
{
int i;
int j;
int good_spot;
int retval = -EINVAL;
dbg ("%s is asking for %d minors", new_driver->name, num_minors);
if (new_driver->fops == NULL)
goto exit;
*start_minor = 0;
spin_lock (&minor_lock);
for (i = 0; i < MAX_USB_MINORS; ++i) {
if (usb_minors[i])
continue;
good_spot = 1;
for (j = 1; j <= num_minors-1; ++j)
if (usb_minors[i+j]) {
good_spot = 0;
break;
}
if (good_spot == 0)
continue;
*start_minor = i;
spin_unlock (&minor_lock);
retval = usb_register_minors (new_driver, num_minors, *start_minor);
if (retval) {
/* someone snuck in here, so let's start looking all over again */
spin_lock (&minor_lock);
i = 0;
continue;
}
goto exit;
}
spin_unlock (&minor_lock);
exit:
return retval;
}
/**
* usb_deregister_dev - deregister a USB device's dynamic minor.
* @driver: USB operations for the driver
* @num_minors: number of minor numbers to put back.
* @start_minor: the starting minor number
*
* Used in conjunction with usb_register_dev(). This function is called
* when the USB driver is finished with the minor numbers gotten from a
* call to usb_register_dev() (usually when the device is disconnected
* from the system.)
*
* This should be called by all drivers that use the USB major number.
*/
void usb_deregister_dev (struct usb_driver *driver, int num_minors, int start_minor)
{
usb_deregister_minors (driver, num_minors, start_minor);
}
#endif /* CONFIG_USB_DYNAMIC_MINORS */
/**
* usb_scan_devices - scans all unclaimed USB interfaces
* Context: !in_interrupt ()
......@@ -177,12 +307,13 @@ static void usb_drivers_purge(struct usb_driver *driver,struct usb_device *dev)
void usb_deregister(struct usb_driver *driver)
{
struct list_head *tmp;
int i;
info("deregistering driver %s", driver->name);
#ifndef CONFIG_USB_DYNAMIC_MINORS
if (driver->fops != NULL)
for (i = driver->minor; i < driver->minor + driver->num_minors; ++i)
usb_minors[i] = NULL;
usb_deregister_minors (driver, driver->num_minors, driver->minor);
#endif
/*
* first we remove the driver, to be sure it doesn't get used by
......@@ -2524,14 +2655,14 @@ int usb_new_device(struct usb_device *dev)
static int usb_open(struct inode * inode, struct file * file)
{
int minor = minor(inode->i_rdev);
struct usb_driver *c = usb_minors[minor];
struct usb_driver *c;
int err = -ENODEV;
struct file_operations *old_fops, *new_fops = NULL;
/*
* No load-on-demand? Randy, could you ACK that it's really not
* supposed to be done? -- AV
*/
spin_lock (&minor_lock);
c = usb_minors[minor];
spin_unlock (&minor_lock);
if (!c || !(new_fops = fops_get(c->fops)))
return err;
old_fops = file->f_op;
......@@ -2623,9 +2754,13 @@ EXPORT_SYMBOL(usb_register);
EXPORT_SYMBOL(usb_deregister);
EXPORT_SYMBOL(usb_scan_devices);
#ifdef CONFIG_USB_DYNAMIC_MINORS
EXPORT_SYMBOL(usb_register_dev);
EXPORT_SYMBOL(usb_deregister_dev);
#endif
EXPORT_SYMBOL(usb_alloc_dev);
EXPORT_SYMBOL(usb_free_dev);
EXPORT_SYMBOL(usb_inc_dev_use);
EXPORT_SYMBOL(usb_find_interface_driver_for_ifnum);
EXPORT_SYMBOL(usb_driver_claim_interface);
......
......@@ -91,7 +91,10 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
if (!(temp & PORT_CONNECT))
ehci->reset_done [i] = 0;
if ((temp & (PORT_CSC | PORT_PEC | PORT_OCC)) != 0) {
set_bit (i, buf);
if (i < 7)
buf [0] |= 1 << (i + 1);
else
buf [1] |= 1 << (i - 7);
status = STS_PCD;
}
}
......@@ -141,7 +144,7 @@ static int ehci_hub_control (
) {
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
int ports = HCS_N_PORTS (ehci->hcs_params);
u32 temp;
u32 temp, status;
unsigned long flags;
int retval = 0;
......@@ -219,22 +222,22 @@ static int ehci_hub_control (
if (!wIndex || wIndex > ports)
goto error;
wIndex--;
memset (buf, 0, 4);
status = 0;
temp = readl (&ehci->regs->port_status [wIndex]);
// wPortChange bits
if (temp & PORT_CSC)
set_bit (USB_PORT_FEAT_C_CONNECTION, buf);
status |= 1 << USB_PORT_FEAT_C_CONNECTION;
if (temp & PORT_PEC)
set_bit (USB_PORT_FEAT_C_ENABLE, buf);
status |= 1 << USB_PORT_FEAT_C_ENABLE;
// USB_PORT_FEAT_C_SUSPEND
if (temp & PORT_OCC)
set_bit (USB_PORT_FEAT_C_OVER_CURRENT, buf);
status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT;
/* whoever resets must GetPortStatus to complete it!! */
if ((temp & PORT_RESET)
&& jiffies > ehci->reset_done [wIndex]) {
set_bit (USB_PORT_FEAT_C_RESET, buf);
status |= 1 << USB_PORT_FEAT_C_RESET;
/* force reset to complete */
writel (temp & ~PORT_RESET,
......@@ -252,26 +255,27 @@ static int ehci_hub_control (
// don't show wPortStatus if it's owned by a companion hc
if (!(temp & PORT_OWNER)) {
if (temp & PORT_CONNECT) {
set_bit (USB_PORT_FEAT_CONNECTION, buf);
set_bit (USB_PORT_FEAT_HIGHSPEED, buf);
status |= 1 << USB_PORT_FEAT_CONNECTION;
status |= 1 << USB_PORT_FEAT_HIGHSPEED;
}
if (temp & PORT_PE)
set_bit (USB_PORT_FEAT_ENABLE, buf);
status |= 1 << USB_PORT_FEAT_ENABLE;
if (temp & PORT_SUSPEND)
set_bit (USB_PORT_FEAT_SUSPEND, buf);
status |= 1 << USB_PORT_FEAT_SUSPEND;
if (temp & PORT_OC)
set_bit (USB_PORT_FEAT_OVER_CURRENT, buf);
status |= 1 << USB_PORT_FEAT_OVER_CURRENT;
if (temp & PORT_RESET)
set_bit (USB_PORT_FEAT_RESET, buf);
status |= 1 << USB_PORT_FEAT_RESET;
if (temp & PORT_POWER)
set_bit (USB_PORT_FEAT_POWER, buf);
status |= 1 << USB_PORT_FEAT_POWER;
}
#ifndef EHCI_VERBOSE_DEBUG
if (*(u16*)(buf+2)) /* only if wPortChange is interesting */
if (status & ~0xffff) /* only if wPortChange is interesting */
#endif
dbg_port (hcd, "GetStatus", wIndex + 1, temp);
cpu_to_le32s ((u32 *) buf);
// we "know" this alignment is good, caller used kmalloc()...
*((u32 *) buf) = cpu_to_le32 (status);
break;
case SetHubFeature:
switch (wValue) {
......
......@@ -96,7 +96,10 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
| RH_PS_OCIC | RH_PS_PRSC;
if (status) {
changed = 1;
set_bit (i + 1, buf);
if (i < 7)
buf [0] |= 1 << (i + 1);
else
buf [1] |= 1 << (i - 7);
}
}
return changed ? length : 0;
......
......@@ -119,8 +119,12 @@
#define TO_READ_FROM_IRQ TO_DEFAULT_COMMAND
#define TO_GET_READY TO_DEFAULT_COMMAND
#ifdef CONFIG_USB_DYNAMIC_MINORS
#define MDC800_DEVICE_MINOR_BASE 0
#else
/* Minor Number of the device (create with mknod /dev/mustek c 180 32) */
#define MDC800_DEVICE_MINOR_BASE 32
#endif
/**************************************************************************
......@@ -176,6 +180,7 @@ struct mdc800_data
int pic_index; // Cache for the Imagesize (-1 for nothing cached )
int pic_len;
int minor;
};
......@@ -470,6 +475,8 @@ static void* mdc800_usb_probe (struct usb_device *dev ,unsigned int ifnum,
down (&mdc800->io_lock);
usb_register_dev (&mdc800_usb_driver, 1, &mdc800->minor);
mdc800->dev=dev;
mdc800->open=0;
......@@ -525,6 +532,8 @@ static void mdc800_usb_disconnect (struct usb_device *dev,void* ptr)
if (mdc800->state == NOT_CONNECTED)
return;
usb_deregister_dev (&mdc800_usb_driver, 1, mdc800->minor);
mdc800->state=NOT_CONNECTED;
usb_unlink_urb (mdc800->irq_urb);
......
......@@ -953,9 +953,11 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum,
down(&scn_mutex);
for (scn_minor = 0; scn_minor < SCN_MAX_MNR; scn_minor++) {
if (!p_scn_table[scn_minor])
break;
if (usb_register_dev(&scanner_driver, 1, &scn_minor)) {
for (scn_minor = 0; scn_minor < SCN_MAX_MNR; scn_minor++) {
if (!p_scn_table[scn_minor])
break;
}
}
/* Check to make sure that the last slot isn't already taken */
......@@ -1086,6 +1088,7 @@ disconnect_scanner(struct usb_device *dev, void *ptr)
dbg("disconnect_scanner: De-allocating minor:%d", scn->scn_minor);
devfs_unregister(scn->devfs);
usb_deregister_dev(&scanner_driver, 1, scn->scn_minor);
p_scn_table[scn->scn_minor] = NULL;
usb_free_urb(scn->scn_irq);
up (&(scn->sem));
......
......@@ -233,8 +233,13 @@ MODULE_DEVICE_TABLE (usb, scanner_device_ids);
#define SCANNER_IOCTL_CTRLMSG _IOWR('U', 0x22, struct usb_ctrlrequest)
#ifdef CONFIG_USB_DYNAMIC_MINORS
#define SCN_MAX_MNR 256
#define SCN_BASE_MNR 0
#else
#define SCN_MAX_MNR 16 /* We're allocated 16 minors */
#define SCN_BASE_MNR 48 /* USB Scanners start at minor 48 */
#endif
static DECLARE_MUTEX (scn_mutex); /* Initializes to unlocked */
......
......@@ -1271,6 +1271,7 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_ATEN_UC100KM 0x2004
#define USB_DEVICE_ID_ATEN_CS124U 0x2202
#define USB_DEVICE_ID_ATEN_2PORTKVM 0x2204
#define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205
struct hid_blacklist {
__u16 idVendor;
......@@ -1288,6 +1289,7 @@ struct hid_blacklist {
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
{ 0, 0 }
};
......
......@@ -25,10 +25,7 @@
* e-mail - mail your message to Paul Stewart <stewart@wetlogic.net>
*/
#define HIDDEV_MINOR_BASE 96
#define HIDDEV_MINORS 16
#define HIDDEV_BUFFER_SIZE 64
#include <linux/config.h>
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/module.h>
......@@ -39,6 +36,15 @@
#include "hid.h"
#include <linux/hiddev.h>
#ifdef CONFIG_USB_DYNAMIC_MINORS
#define HIDDEV_MINOR_BASE 0
#define HIDDEV_MINORS 256
#else
#define HIDDEV_MINOR_BASE 96
#define HIDDEV_MINORS 16
#endif
#define HIDDEV_BUFFER_SIZE 64
struct hiddev {
int exist;
int open;
......@@ -62,6 +68,9 @@ struct hiddev_list {
static struct hiddev *hiddev_table[HIDDEV_MINORS];
static devfs_handle_t hiddev_devfs_handle;
/* forward reference to make our lives easier */
extern struct usb_driver hiddev_driver;
/*
* Find a report, given the report's type and ID. The ID can be specified
* indirectly by REPORT_ID_FIRST (which returns the first report of the given
......@@ -184,6 +193,7 @@ static int hiddev_fasync(int fd, struct file *file, int on)
static void hiddev_cleanup(struct hiddev *hiddev)
{
devfs_unregister(hiddev->devfs);
usb_deregister_dev(&hiddev_driver, 1, hiddev->minor);
hiddev_table[hiddev->minor] = NULL;
kfree(hiddev);
}
......@@ -605,10 +615,12 @@ int hiddev_connect(struct hid_device *hid)
if (i == hid->maxapplication)
return -1;
for (minor = 0; minor < HIDDEV_MINORS && hiddev_table[minor]; minor++);
if (minor == HIDDEV_MINORS) {
printk(KERN_ERR "hiddev: no more free hiddev devices\n");
return -1;
if (usb_register_dev (&hiddev_driver, 1, &minor)) {
for (minor = 0; minor < HIDDEV_MINORS && hiddev_table[minor]; minor++);
if (minor == HIDDEV_MINORS) {
printk(KERN_ERR "hiddev: no more free hiddev devices\n");
return -1;
}
}
if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL)))
......
......@@ -4,7 +4,7 @@
O_TARGET := media.o
export-objs := ov511.o pwc-uncompress.o
export-objs := ov511.o pwc-uncompress.o usbvideo.o
pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o
......
......@@ -52,12 +52,17 @@
/* --------------------------------------------------------------------- */
#ifdef CONFIG_USB_DYNAMIC_MINORS
#define NRDABUSB 256
#else
#define NRDABUSB 4
#endif
/*-------------------------------------------------------------------*/
static dabusb_t dabusb[NRDABUSB];
static int buffers = 256;
extern struct usb_driver dabusb_driver;
/*-------------------------------------------------------------------*/
......@@ -734,15 +739,18 @@ static void *dabusb_probe (struct usb_device *usbdev, unsigned int ifnum,
if (ifnum != _DABUSB_IF && usbdev->descriptor.idProduct == 0x9999)
return NULL;
devnum = dabusb_find_struct ();
if (devnum == -1)
return NULL;
if (usb_register_dev (&dabusb_driver, 1, &devnum)) {
devnum = dabusb_find_struct ();
if (devnum == -1)
return NULL;
}
s = &dabusb[devnum];
down (&s->mutex);
s->remove_pending = 0;
s->usbdev = usbdev;
s->devnum = devnum;
if (usb_set_configuration (usbdev, usbdev->config[0].bConfigurationValue) < 0) {
err("set_configuration failed");
......@@ -777,6 +785,7 @@ static void dabusb_disconnect (struct usb_device *usbdev, void *ptr)
dbg("dabusb_disconnect");
usb_deregister_dev (&dabusb_driver, 1, s->devnum);
s->remove_pending = 1;
wake_up (&s->wait);
if (s->state == _started)
......
......@@ -6,7 +6,11 @@ typedef struct
unsigned int pipe;
}bulk_transfer_t,*pbulk_transfer_t;
#ifdef CONFIG_USB_DYNAMIC_MINORS
#define DABUSB_MINOR 0
#else
#define DABUSB_MINOR 240 /* some unassigned USB minor */
#endif
#define DABUSB_VERSION 0x1000
#define IOCTL_DAB_BULK _IOWR('d', 0x30, bulk_transfer_t)
#define IOCTL_DAB_OVERRUNS _IOR('d', 0x15, int)
......@@ -31,6 +35,7 @@ typedef struct
unsigned int overruns;
int readptr;
int opened;
int devnum;
struct list_head free_buff_list;
struct list_head rec_buff_list;
} dabusb_t,*pdabusb_t;
......
This diff is collapsed.
......@@ -304,35 +304,22 @@ typedef struct s_usbvideo_t usbvideo_t;
#define VALID_CALLBACK(uvd,cbName) ((((uvd) != NULL) && \
((uvd)->handle != NULL)) ? GET_CALLBACK(uvd,cbName) : NULL)
void RingQueue_Initialize(RingQueue_t *rq);
void RingQueue_Allocate(RingQueue_t *rq, int rqLen);
int RingQueue_IsAllocated(const RingQueue_t *rq);
void RingQueue_Free(RingQueue_t *rq);
int RingQueue_Dequeue(RingQueue_t *rq, unsigned char *dst, int len);
int RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n);
int RingQueue_GetLength(const RingQueue_t *rq);
void RingQueue_InterruptibleSleepOn(RingQueue_t *rq);
void RingQueue_WakeUpInterruptible(RingQueue_t *rq);
void usbvideo_CollectRawData(uvd_t *uvd, usbvideo_frame_t *frame);
void usbvideo_DrawLine(
usbvideo_frame_t *frame,
int x1, int y1,
int x2, int y2,
unsigned char cr, unsigned char cg, unsigned char cb);
void usbvideo_HexDump(const unsigned char *data, int len);
void usbvideo_OverlayChar(uvd_t *uvd, usbvideo_frame_t *frame, int x, int y, int ch);
void usbvideo_OverlayString(uvd_t *uvd, usbvideo_frame_t *frame, int x, int y, const char *str);
void usbvideo_OverlayStats(uvd_t *uvd, usbvideo_frame_t *frame);
void usbvideo_ReportStatistics(const uvd_t *uvd);
void usbvideo_SayAndWait(const char *what);
void usbvideo_TestPattern(uvd_t *uvd, int fullframe, int pmode);
void usbvideo_VideosizeToString(char *buf, int bufLen, videosize_t vs);
/* Memory allocation routines */
unsigned long usbvideo_kvirt_to_pa(unsigned long adr);
void *usbvideo_rvmalloc(unsigned long size);
void usbvideo_rvfree(void *mem, unsigned long size);
int usbvideo_register(
usbvideo_t **pCams,
......@@ -344,24 +331,10 @@ int usbvideo_register(
uvd_t *usbvideo_AllocateDevice(usbvideo_t *cams);
int usbvideo_RegisterVideoDevice(uvd_t *uvd);
void usbvideo_Deregister(usbvideo_t **uvt);
void usbvideo_Disconnect(struct usb_device *dev, void *ptr);
void usbvideo_CameraRelease(uvd_t *uvd);
int usbvideo_v4l_close(struct inode *inode, struct file *file);
int usbvideo_v4l_initialize(struct video_device *dev);
int usbvideo_v4l_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg);
int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma);
int usbvideo_v4l_open(struct inode *inode, struct file *file);
int usbvideo_v4l_read(struct file *file, char *buf,
size_t count, loff_t *ppos);
int usbvideo_GetFrame(uvd_t *uvd, int frameNum);
int usbvideo_NewFrame(uvd_t *uvd, int framenum);
int usbvideo_StartDataPump(uvd_t *uvd);
void usbvideo_StopDataPump(uvd_t *uvd);
void usbvideo_DeinterlaceFrame(uvd_t *uvd, usbvideo_frame_t *frame);
void usbvideo_SoftwareContrastAdjustment(uvd_t *uvd, usbvideo_frame_t *frame);
/*
* This code performs bounds checking - use it when working with
......
......@@ -60,12 +60,17 @@ do { \
/* Auerswald Vendor ID */
#define ID_AUERSWALD 0x09BF
#ifndef AUER_MINOR_BASE /* allow external override */
#ifdef CONFIG_USB_DYNAMIC_MINORS
/* we can have up to 256 devices at once */
#define AUER_MINOR_BASE 0
#define AUER_MAX_DEVICES 256
#else
#define AUER_MINOR_BASE 112 /* auerswald driver minor number */
#endif
/* we can have up to this number of device plugged in at once */
#define AUER_MAX_DEVICES 16
#endif
/* prefix for the device descriptors in /dev/usb */
#define AU_PREFIX "auer"
......@@ -284,6 +289,7 @@ typedef struct
/* Forwards */
static void auerswald_ctrlread_complete (struct urb * urb);
static void auerswald_removeservice (pauerswald_t cp, pauerscon_t scp);
extern struct usb_driver auerswald_driver;
/*-------------------------------------------------------------------*/
......@@ -1941,16 +1947,18 @@ static void *auerswald_probe (struct usb_device *usbdev, unsigned int ifnum,
auerbuf_init (&cp->bufctl);
init_waitqueue_head (&cp->bufferwait);
/* find a free slot in the device table */
down (&dev_table_mutex);
for (dtindex = 0; dtindex < AUER_MAX_DEVICES; ++dtindex) {
if (dev_table[dtindex] == NULL)
break;
}
if ( dtindex >= AUER_MAX_DEVICES) {
err ("more than %d devices plugged in, can not handle this device", AUER_MAX_DEVICES);
up (&dev_table_mutex);
goto pfail;
if (usb_register_dev (&auerswald_driver, 1, &dtindex)) {
/* find a free slot in the device table */
for (dtindex = 0; dtindex < AUER_MAX_DEVICES; ++dtindex) {
if (dev_table[dtindex] == NULL)
break;
}
if ( dtindex >= AUER_MAX_DEVICES) {
err ("more than %d devices plugged in, can not handle this device", AUER_MAX_DEVICES);
up (&dev_table_mutex);
goto pfail;
}
}
/* Give the device a name */
......@@ -2081,6 +2089,9 @@ static void auerswald_disconnect (struct usb_device *usbdev, void *driver_contex
/* Nobody can see this device any more */
devfs_unregister (cp->devfs);
/* give back our USB minor number */
usb_deregister_dev (&auerswald_driver, 1, cp->dtindex);
/* Stop the interrupt endpoint */
auerswald_int_release (cp);
......@@ -2181,6 +2192,7 @@ static void __exit auerswald_cleanup (void)
MODULE_AUTHOR (DRIVER_AUTHOR);
MODULE_DESCRIPTION (DRIVER_DESC);
MODULE_LICENSE ("GPL");
module_init (auerswald_init);
module_exit (auerswald_cleanup);
......
......@@ -315,14 +315,16 @@ brlvger_probe (struct usb_device *dev, unsigned ifnum,
down(&reserve_sem);
for( i = 0; i < MAX_NR_BRLVGER_DEVS; i++ )
if( display_table[i] == NULL )
break;
if( i == MAX_NR_BRLVGER_DEVS ) {
err( "This driver cannot handle more than %d "
"braille displays", MAX_NR_BRLVGER_DEVS);
goto error;
if (usb_register_dev(&brlvger_driver, 1, &i)) {
for( i = 0; i < MAX_NR_BRLVGER_DEVS; i++ )
if( display_table[i] == NULL )
break;
if( i == MAX_NR_BRLVGER_DEVS ) {
err( "This driver cannot handle more than %d "
"braille displays", MAX_NR_BRLVGER_DEVS);
goto error;
}
}
if( !(priv = kmalloc (sizeof *priv, GFP_KERNEL)) ){
......@@ -423,7 +425,8 @@ brlvger_disconnect(struct usb_device *dev, void *ptr)
info("Display %d disconnecting", priv->subminor);
devfs_unregister(priv->devfs);
usb_deregister_dev(&brlvger_driver, 1, priv->subminor);
down(&disconnect_sem);
display_table[priv->subminor] = NULL;
up(&disconnect_sem);
......
......@@ -255,6 +255,8 @@ PEGASUS_DEV( "SMC 2206 USB Ethernet", VENDOR_SMC, 0x0201,
DEFAULT_GPIO_RESET | PEGASUS_II)
PEGASUS_DEV( "SOHOware NUB100 Ethernet", VENDOR_SOHOWARE, 0x9100,
DEFAULT_GPIO_RESET )
PEGASUS_DEV( "SOHOware NUB110 Ethernet", VENDOR_SOHOWARE, 0x9110,
DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_SIEMENS, 0x1001,
DEFAULT_GPIO_RESET )
......
......@@ -121,7 +121,7 @@
#define CONFIG_USB_PL2301
#define DRIVER_VERSION "06-Apr-2002"
#define DRIVER_VERSION "26-Apr-2002"
/*-------------------------------------------------------------------------*/
......@@ -484,14 +484,6 @@ static int genelink_free (struct usbnet *dev)
return 0;
}
#else
static int genelink_check_connect (struct usbnet *dev)
{
dbg ("%s: assuming peer is connected", dev->net.name);
return 0;
}
#endif
// reset the device status
......@@ -623,12 +615,15 @@ static const struct driver_info genelink_info = {
description: "Genesys GeneLink",
flags: FLAG_FRAMING_GL | FLAG_NO_SETINT,
reset: genelink_reset,
check_connect: genelink_check_connect,
rx_fixup: genelink_rx_fixup,
tx_fixup: genelink_tx_fixup,
in: 1, out: 2,
epsize: 64,
#ifdef GENELINK_ACK
check_connect: genelink_check_connect,
#endif
};
#endif /* CONFIG_USB_GENESYS */
......@@ -652,11 +647,15 @@ static const struct driver_info genelink_info = {
*
*-------------------------------------------------------------------------*/
static int linuxdev_check_connect (struct usbnet *dev)
{
return 0; // by definition, always connected
}
static const struct driver_info linuxdev_info = {
description: "Linux Device",
// no reset defined (yet?)
// no check_connect needed!
check_connect: linuxdev_check_connect,
in: 2, out: 1,
epsize: 64,
};
......@@ -1169,21 +1168,11 @@ static int pl_reset (struct usbnet *dev)
PL_S_EN|PL_RESET_OUT|PL_RESET_IN|PL_PEER_E);
}
static int pl_check_connect (struct usbnet *dev)
{
// FIXME test interrupt data PL_PEER_E bit
// plus, there's some handshake done by
// the prolific win32 driver...
dbg ("%s: assuming peer is connected", dev->net.name);
return 0;
}
static const struct driver_info prolific_info = {
description: "Prolific PL-2301/PL-2302",
flags: FLAG_NO_SETINT,
/* some PL-2302 versions seem to fail usb_set_interface() */
reset: pl_reset,
check_connect: pl_check_connect,
in: 3, out: 2,
epsize: 64,
......@@ -1567,7 +1556,7 @@ static int usbnet_ethtool_ioctl (struct net_device *net, void *useraddr)
if (dev->driver_info->check_connect) {
struct ethtool_value edata = { ETHTOOL_GLINK };
edata.data = dev->driver_info->check_connect (dev);
edata.data = dev->driver_info->check_connect (dev) == 0;
if (copy_to_user (useraddr, &edata, sizeof (edata)))
return -EFAULT;
return 0;
......
This diff is collapsed.
......@@ -85,12 +85,20 @@ static struct usb_device_id skel_table [] = {
MODULE_DEVICE_TABLE (usb, skel_table);
#ifdef CONFIG_USB_DYNAMIC_MINORS
/*
* if the user wants to use dynamic minor numbers, then we can have up to 256
* devices
*/
#define USB_SKEL_MINOR_BASE 0
#define MAX_DEVICES 256
#else
/* Get a minor range for your devices from the usb maintainer */
#define USB_SKEL_MINOR_BASE 200
#define USB_SKEL_MINOR_BASE 200
/* we can have up to this number of device plugged in at once */
#define MAX_DEVICES 16
#endif
/* Structure to hold all of our device specific stuff */
struct usb_skel {
......@@ -192,9 +200,6 @@ static struct usb_driver skel_driver = {
};
/**
* usb_skel_debug_data
*/
......@@ -529,15 +534,17 @@ static void * skel_probe(struct usb_device *udev, unsigned int ifnum, const stru
return NULL;
}
/* select a "subminor" number (part of a minor number) */
down (&minor_table_mutex);
for (minor = 0; minor < MAX_DEVICES; ++minor) {
if (minor_table[minor] == NULL)
break;
}
if (minor >= MAX_DEVICES) {
info ("Too many devices plugged in, can not handle this device.");
goto exit;
if (usb_register_dev (&skel_driver, 1, &minor)) {
/* we could not get a dynamic minor, so lets find one of our own */
for (minor = 0; minor < MAX_DEVICES; ++minor) {
if (minor_table[minor] == NULL)
break;
}
if (minor >= MAX_DEVICES) {
info ("Too many devices plugged in, can not handle this device.");
goto exit;
}
}
/* allocate memory for our device state and intialize it */
......@@ -642,8 +649,11 @@ static void skel_disconnect(struct usb_device *udev, void *ptr)
minor = dev->minor;
/* remove our devfs node */
devfs_unregister(dev->devfs);
devfs_unregister (dev->devfs);
/* give back our dynamic minor */
usb_deregister_dev (&skel_driver, 1, minor);
/* if the device is not opened, then we clean up right now */
if (!dev->open_count) {
up (&dev->sem);
......
......@@ -30,11 +30,16 @@
#define BRLVGER_DISPLAY_OFF 3
#define BRLVGER_BUZZ 4
#ifdef CONFIG_USB_DYNAMIC_MINORS
#define MAX_NR_BRLVGER_DEVS 256
#define BRLVGER_MINOR 0
#else
/* Number of supported devices, and range of covered minors */
#define MAX_NR_BRLVGER_DEVS 2
#define MAX_NR_BRLVGER_DEVS 4
/* Base minor for the char devices */
#define BRLVGER_MINOR 128
#endif
/* Size of some fields */
#define BRLVGER_HWVER_SIZE 2
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment