diff options
| author | Linus Torvalds <torvalds@home.transmeta.com> | 2002-04-28 05:29:37 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2002-04-28 05:29:37 -0700 |
| commit | f0dbe47db9f58af07d92b2eace5539e8e9caef09 (patch) | |
| tree | a6df2ca736ea06b018c32c7841e26d1501250824 /drivers/usb | |
| parent | 2ce059eca8f827e74acaf2c1ac7471913017d0d7 (diff) | |
| parent | f123a327c3999f2c1affdd63d7a99d1fa672c4e2 (diff) | |
Merge bk://linuxusb.bkbits.net/linus-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
Diffstat (limited to 'drivers/usb')
| -rw-r--r-- | drivers/usb/Config.help | 8 | ||||
| -rw-r--r-- | drivers/usb/class/printer.c | 21 | ||||
| -rw-r--r-- | drivers/usb/core/Config.in | 11 | ||||
| -rw-r--r-- | drivers/usb/core/usb.c | 175 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-hub.c | 36 | ||||
| -rw-r--r-- | drivers/usb/host/ohci-hub.c | 5 | ||||
| -rw-r--r-- | drivers/usb/image/mdc800.c | 9 | ||||
| -rw-r--r-- | drivers/usb/image/scanner.c | 9 | ||||
| -rw-r--r-- | drivers/usb/image/scanner.h | 5 | ||||
| -rw-r--r-- | drivers/usb/input/hid-core.c | 2 | ||||
| -rw-r--r-- | drivers/usb/input/hiddev.c | 28 | ||||
| -rw-r--r-- | drivers/usb/media/Makefile | 2 | ||||
| -rw-r--r-- | drivers/usb/media/dabusb.c | 15 | ||||
| -rw-r--r-- | drivers/usb/media/dabusb.h | 5 | ||||
| -rw-r--r-- | drivers/usb/media/usbvideo.c | 100 | ||||
| -rw-r--r-- | drivers/usb/media/usbvideo.h | 29 | ||||
| -rw-r--r-- | drivers/usb/misc/auerswald.c | 34 | ||||
| -rw-r--r-- | drivers/usb/misc/brlvger.c | 21 | ||||
| -rw-r--r-- | drivers/usb/net/pegasus.h | 2 | ||||
| -rw-r--r-- | drivers/usb/net/usbnet.c | 33 | ||||
| -rw-r--r-- | drivers/usb/serial/keyspan.c | 171 | ||||
| -rw-r--r-- | drivers/usb/usb-skeleton.c | 38 |
22 files changed, 541 insertions, 218 deletions
diff --git a/drivers/usb/Config.help b/drivers/usb/Config.help index 65b90af25c32..fa161a19725b 100644 --- a/drivers/usb/Config.help +++ b/drivers/usb/Config.help @@ -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. diff --git a/drivers/usb/class/printer.c b/drivers/usb/class/printer.c index abab738e601a..7a589cbd9569 100644 --- a/drivers/usb/class/printer.c +++ b/drivers/usb/class/printer.c @@ -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; + } } } diff --git a/drivers/usb/core/Config.in b/drivers/usb/core/Config.in index 023c2704c026..d1415e679f10 100644 --- a/drivers/usb/core/Config.in +++ b/drivers/usb/core/Config.in @@ -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 diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 7aa2dec50734..0d85e97251e0 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -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); diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 4b2b080663f8..22d4919cbf97 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -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) { diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 2aed53548bb5..faa9acf49ea6 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -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; diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c index 58d55e3e1d66..c211b9980c80 100644 --- a/drivers/usb/image/mdc800.c +++ b/drivers/usb/image/mdc800.c @@ -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); diff --git a/drivers/usb/image/scanner.c b/drivers/usb/image/scanner.c index d66b8e6eb865..d26c0d17635e 100644 --- a/drivers/usb/image/scanner.c +++ b/drivers/usb/image/scanner.c @@ -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)); diff --git a/drivers/usb/image/scanner.h b/drivers/usb/image/scanner.h index be6c26ac1f9c..7e07b5f84469 100644 --- a/drivers/usb/image/scanner.h +++ b/drivers/usb/image/scanner.h @@ -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 */ diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 245ad1a0b5af..e47a8d53e781 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -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 } }; diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c index 05b02b4c93fa..271ee088571e 100644 --- a/drivers/usb/input/hiddev.c +++ b/drivers/usb/input/hiddev.c @@ -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))) diff --git a/drivers/usb/media/Makefile b/drivers/usb/media/Makefile index 7b1d43f40130..1eb02f0872a4 100644 --- a/drivers/usb/media/Makefile +++ b/drivers/usb/media/Makefile @@ -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 diff --git a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c index 50d75410bbcd..30dfc3930cc6 100644 --- a/drivers/usb/media/dabusb.c +++ b/drivers/usb/media/dabusb.c @@ -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) diff --git a/drivers/usb/media/dabusb.h b/drivers/usb/media/dabusb.h index 9fc09c8a289f..259001584a7f 100644 --- a/drivers/usb/media/dabusb.h +++ b/drivers/usb/media/dabusb.h @@ -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; diff --git a/drivers/usb/media/usbvideo.c b/drivers/usb/media/usbvideo.c index c04a67e6c45c..60cf00f71c19 100644 --- a/drivers/usb/media/usbvideo.c +++ b/drivers/usb/media/usbvideo.c @@ -18,7 +18,6 @@ #include <linux/sched.h> #include <linux/list.h> #include <linux/slab.h> -#define __NO_VERSION__ /* Temporary: usbvideo is not a module yet */ #include <linux/module.h> #include <linux/mm.h> #include <linux/smp_lock.h> @@ -55,6 +54,24 @@ static int usbvideo_default_procfs_write_proc( unsigned long count, void *data); #endif +static void usbvideo_Disconnect(struct usb_device *dev, void *ptr); +static void usbvideo_CameraRelease(uvd_t *uvd); + +static int usbvideo_v4l_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); +static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma); +static int usbvideo_v4l_open(struct inode *inode, struct file *file); +static int usbvideo_v4l_read(struct file *file, char *buf, + size_t count, loff_t *ppos); +static int usbvideo_v4l_close(struct inode *inode, struct file *file); + +static int usbvideo_StartDataPump(uvd_t *uvd); +static void usbvideo_StopDataPump(uvd_t *uvd); +static int usbvideo_GetFrame(uvd_t *uvd, int frameNum); +static int usbvideo_NewFrame(uvd_t *uvd, int framenum); +static void usbvideo_SoftwareContrastAdjustment(uvd_t *uvd, + usbvideo_frame_t *frame); + /*******************************/ /* Memory management functions */ /*******************************/ @@ -73,7 +90,7 @@ unsigned long usbvideo_kvirt_to_pa(unsigned long adr) return ret; } -void *usbvideo_rvmalloc(unsigned long size) +static void *usbvideo_rvmalloc(unsigned long size) { void *mem; unsigned long adr; @@ -94,7 +111,7 @@ void *usbvideo_rvmalloc(unsigned long size) return mem; } -void usbvideo_rvfree(void *mem, unsigned long size) +static void usbvideo_rvfree(void *mem, unsigned long size) { unsigned long adr; @@ -110,13 +127,13 @@ void usbvideo_rvfree(void *mem, unsigned long size) vfree(mem); } -void RingQueue_Initialize(RingQueue_t *rq) +static void RingQueue_Initialize(RingQueue_t *rq) { assert(rq != NULL); init_waitqueue_head(&rq->wqh); } -void RingQueue_Allocate(RingQueue_t *rq, int rqLen) +static void RingQueue_Allocate(RingQueue_t *rq, int rqLen) { assert(rq != NULL); assert(rqLen > 0); @@ -125,14 +142,14 @@ void RingQueue_Allocate(RingQueue_t *rq, int rqLen) assert(rq->queue != NULL); } -int RingQueue_IsAllocated(const RingQueue_t *rq) +static int RingQueue_IsAllocated(const RingQueue_t *rq) { if (rq == NULL) return 0; return (rq->queue != NULL) && (rq->length > 0); } -void RingQueue_Free(RingQueue_t *rq) +static void RingQueue_Free(RingQueue_t *rq) { assert(rq != NULL); if (RingQueue_IsAllocated(rq)) { @@ -154,6 +171,8 @@ int RingQueue_Dequeue(RingQueue_t *rq, unsigned char *dst, int len) return len; } +EXPORT_SYMBOL(RingQueue_Dequeue); + int RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n) { int enqueued = 0; @@ -184,6 +203,8 @@ int RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n) return enqueued; } +EXPORT_SYMBOL(RingQueue_Enqueue); + int RingQueue_GetLength(const RingQueue_t *rq) { int ri, wi; @@ -200,7 +221,9 @@ int RingQueue_GetLength(const RingQueue_t *rq) return wi + (rq->length - ri); } -void RingQueue_InterruptibleSleepOn(RingQueue_t *rq) +EXPORT_SYMBOL(RingQueue_GetLength); + +static void RingQueue_InterruptibleSleepOn(RingQueue_t *rq) { assert(rq != NULL); interruptible_sleep_on(&rq->wqh); @@ -213,6 +236,8 @@ void RingQueue_WakeUpInterruptible(RingQueue_t *rq) wake_up_interruptible(&rq->wqh); } +EXPORT_SYMBOL(RingQueue_WakeUpInterruptible); + /* * usbvideo_VideosizeToString() * @@ -222,7 +247,7 @@ void RingQueue_WakeUpInterruptible(RingQueue_t *rq) * 07-Aug-2000 Created. * 19-Oct-2000 Reworked for usbvideo module. */ -void usbvideo_VideosizeToString(char *buf, int bufLen, videosize_t vs) +static void usbvideo_VideosizeToString(char *buf, int bufLen, videosize_t vs) { char tmp[40]; int n; @@ -241,8 +266,8 @@ void usbvideo_VideosizeToString(char *buf, int bufLen, videosize_t vs) * History: * 01-Feb-2000 Created. */ -void usbvideo_OverlayChar(uvd_t *uvd, usbvideo_frame_t *frame, - int x, int y, int ch) +static void usbvideo_OverlayChar(uvd_t *uvd, usbvideo_frame_t *frame, + int x, int y, int ch) { static const unsigned short digits[16] = { 0xF6DE, /* 0 */ @@ -296,8 +321,8 @@ void usbvideo_OverlayChar(uvd_t *uvd, usbvideo_frame_t *frame, * History: * 01-Feb-2000 Created. */ -void usbvideo_OverlayString(uvd_t *uvd, usbvideo_frame_t *frame, - int x, int y, const char *str) +static void usbvideo_OverlayString(uvd_t *uvd, usbvideo_frame_t *frame, + int x, int y, const char *str) { while (*str) { usbvideo_OverlayChar(uvd, frame, x, y, *str); @@ -314,7 +339,7 @@ void usbvideo_OverlayString(uvd_t *uvd, usbvideo_frame_t *frame, * History: * 01-Feb-2000 Created. */ -void usbvideo_OverlayStats(uvd_t *uvd, usbvideo_frame_t *frame) +static void usbvideo_OverlayStats(uvd_t *uvd, usbvideo_frame_t *frame) { const int y_diff = 8; char tmp[16]; @@ -437,7 +462,7 @@ void usbvideo_OverlayStats(uvd_t *uvd, usbvideo_frame_t *frame) * History: * 14-Jan-2000 Corrected default multiplier. */ -void usbvideo_ReportStatistics(const uvd_t *uvd) +static void usbvideo_ReportStatistics(const uvd_t *uvd) { if ((uvd != NULL) && (uvd->stats.urb_count > 0)) { unsigned long allPackets, badPackets, goodPackets, percent; @@ -549,6 +574,8 @@ void usbvideo_DrawLine( } } +EXPORT_SYMBOL(usbvideo_DrawLine); + /* * usbvideo_TestPattern() * @@ -636,6 +663,8 @@ void usbvideo_TestPattern(uvd_t *uvd, int fullframe, int pmode) usbvideo_OverlayStats(uvd, frame); } +EXPORT_SYMBOL(usbvideo_TestPattern); + /* * usbvideo_HexDump() * @@ -663,6 +692,8 @@ void usbvideo_HexDump(const unsigned char *data, int len) printk("%s\n", tmp); } +EXPORT_SYMBOL(usbvideo_HexDump); + /* Debugging aid */ void usbvideo_SayAndWait(const char *what) { @@ -672,6 +703,8 @@ void usbvideo_SayAndWait(const char *what) interruptible_sleep_on_timeout (&wq, HZ*3); /* Timeout */ } +EXPORT_SYMBOL(usbvideo_SayAndWait); + /* ******************************************************************** */ static void usbvideo_ClientIncModCount(uvd_t *uvd) @@ -825,6 +858,8 @@ int usbvideo_register( return 0; } +EXPORT_SYMBOL(usbvideo_register); + /* * usbvideo_Deregister() * @@ -886,6 +921,8 @@ void usbvideo_Deregister(usbvideo_t **pCams) *pCams = NULL; } +EXPORT_SYMBOL(usbvideo_Deregister); + /* * usbvideo_Disconnect() * @@ -908,7 +945,7 @@ void usbvideo_Deregister(usbvideo_t **pCams) * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). * 19-Oct-2000 Moved to usbvideo module. */ -void usbvideo_Disconnect(struct usb_device *dev, void *ptr) +static void usbvideo_Disconnect(struct usb_device *dev, void *ptr) { static const char proc[] = "usbvideo_Disconnect"; uvd_t *uvd = (uvd_t *) ptr; @@ -958,7 +995,7 @@ void usbvideo_Disconnect(struct usb_device *dev, void *ptr) * History: * 27-Jan-2000 Created. */ -void usbvideo_CameraRelease(uvd_t *uvd) +static void usbvideo_CameraRelease(uvd_t *uvd) { static const char proc[] = "usbvideo_CameraRelease"; if (uvd == NULL) { @@ -1079,6 +1116,8 @@ allocate_done: return uvd; } +EXPORT_SYMBOL(usbvideo_AllocateDevice); + int usbvideo_RegisterVideoDevice(uvd_t *uvd) { static const char proc[] = "usbvideo_RegisterVideoDevice"; @@ -1139,9 +1178,11 @@ int usbvideo_RegisterVideoDevice(uvd_t *uvd) return 0; } +EXPORT_SYMBOL(usbvideo_RegisterVideoDevice); + /* ******************************************************************** */ -int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma) +static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma) { uvd_t *uvd = file->private_data; unsigned long start = vma->vm_start; @@ -1185,7 +1226,7 @@ int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma) * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers. * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). */ -int usbvideo_v4l_open(struct inode *inode, struct file *file) +static int usbvideo_v4l_open(struct inode *inode, struct file *file) { static const char proc[] = "usbvideo_v4l_open"; struct video_device *dev = video_devdata(file); @@ -1300,7 +1341,7 @@ int usbvideo_v4l_open(struct inode *inode, struct file *file) * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers. * 24-May-2000 Moved MOD_DEC_USE_COUNT outside of code that can sleep. */ -int usbvideo_v4l_close(struct inode *inode, struct file *file) +static int usbvideo_v4l_close(struct inode *inode, struct file *file) { static const char proc[] = "usbvideo_v4l_close"; struct video_device *dev = file->private_data; @@ -1554,7 +1595,7 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file, return 0; } -int usbvideo_v4l_ioctl(struct inode *inode, struct file *file, +static int usbvideo_v4l_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(inode, file, cmd, arg, usbvideo_v4l_do_ioctl); @@ -1571,7 +1612,7 @@ int usbvideo_v4l_ioctl(struct inode *inode, struct file *file, * 20-Oct-2000 Created. * 01-Nov-2000 Added mutex (uvd->lock). */ -int usbvideo_v4l_read(struct file *file, char *buf, +static int usbvideo_v4l_read(struct file *file, char *buf, size_t count, loff_t *ppos) { static const char proc[] = "usbvideo_v4l_read"; @@ -1809,7 +1850,7 @@ urb_done_with: * of hardcoded values. Simplified by using for loop, * allowed any number of URBs. */ -int usbvideo_StartDataPump(uvd_t *uvd) +static int usbvideo_StartDataPump(uvd_t *uvd) { static const char proc[] = "usbvideo_StartDataPump"; struct usb_device *dev = uvd->dev; @@ -1885,7 +1926,7 @@ int usbvideo_StartDataPump(uvd_t *uvd) * 22-Jan-2000 Corrected order of actions to work after surprise removal. * 27-Jan-2000 Used uvd->iface, uvd->ifaceAltInactive instead of hardcoded values. */ -void usbvideo_StopDataPump(uvd_t *uvd) +static void usbvideo_StopDataPump(uvd_t *uvd) { static const char proc[] = "usbvideo_StopDataPump"; int i, j; @@ -1929,7 +1970,7 @@ void usbvideo_StopDataPump(uvd_t *uvd) * 29-Mar-00 Added copying of previous frame into the current one. * 6-Aug-00 Added model 3 video sizes, removed redundant width, height. */ -int usbvideo_NewFrame(uvd_t *uvd, int framenum) +static int usbvideo_NewFrame(uvd_t *uvd, int framenum) { usbvideo_frame_t *frame; int n; @@ -2004,7 +2045,7 @@ int usbvideo_NewFrame(uvd_t *uvd, int framenum) * FLAGS_NO_DECODING set. Therefore, any regular build of any driver * based on usbvideo can use this feature at any time. */ -void usbvideo_CollectRawData(uvd_t *uvd, usbvideo_frame_t *frame) +static void usbvideo_CollectRawData(uvd_t *uvd, usbvideo_frame_t *frame) { int n; @@ -2034,7 +2075,7 @@ void usbvideo_CollectRawData(uvd_t *uvd, usbvideo_frame_t *frame) } } -int usbvideo_GetFrame(uvd_t *uvd, int frameNum) +static int usbvideo_GetFrame(uvd_t *uvd, int frameNum) { static const char proc[] = "usbvideo_GetFrame"; usbvideo_frame_t *frame = &uvd->frame[frameNum]; @@ -2225,6 +2266,8 @@ void usbvideo_DeinterlaceFrame(uvd_t *uvd, usbvideo_frame_t *frame) usbvideo_OverlayStats(uvd, frame); } +EXPORT_SYMBOL(usbvideo_DeinterlaceFrame); + /* * usbvideo_SoftwareContrastAdjustment() * @@ -2235,7 +2278,8 @@ void usbvideo_DeinterlaceFrame(uvd_t *uvd, usbvideo_frame_t *frame) * History: * 09-Feb-2001 Created. */ -void usbvideo_SoftwareContrastAdjustment(uvd_t *uvd, usbvideo_frame_t *frame) +static void usbvideo_SoftwareContrastAdjustment(uvd_t *uvd, + usbvideo_frame_t *frame) { static const char proc[] = "usbvideo_SoftwareContrastAdjustment"; int i, j, v4l_linesize; diff --git a/drivers/usb/media/usbvideo.h b/drivers/usb/media/usbvideo.h index 211249c340db..507d56984de8 100644 --- a/drivers/usb/media/usbvideo.h +++ b/drivers/usb/media/usbvideo.h @@ -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 diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c index 3c435f78ef4b..579f6ab2f9ef 100644 --- a/drivers/usb/misc/auerswald.c +++ b/drivers/usb/misc/auerswald.c @@ -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); diff --git a/drivers/usb/misc/brlvger.c b/drivers/usb/misc/brlvger.c index a9d458b438ea..e77d0a1e466a 100644 --- a/drivers/usb/misc/brlvger.c +++ b/drivers/usb/misc/brlvger.c @@ -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); diff --git a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h index a7f0cb56be54..1004eaeb756a 100644 --- a/drivers/usb/net/pegasus.h +++ b/drivers/usb/net/pegasus.h @@ -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 ) diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index c329ed692ce5..4886279ba1e6 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c @@ -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; diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 254c25c99797..03183dcb48bd 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -28,6 +28,14 @@ Change History + Wed Apr 25 12:00:00 PST 2002 (Keyspan) + Started with Hugh Blemings' code dated Jan 17, 2002. All adapters + now supported (including QI and QW). Modified port open, port + close, and send setup() logic to fix various data and endpoint + synchronization bugs and device LED status bugs. Changed keyspan_ + write_room() to accurately return transmit buffer availability. + Changed forwardingLength from 1 to 16 for all adapters. + Fri Oct 12 16:45:00 EST 2001 Preliminary USA-19QI and USA-28 support (both test OK for me, YMMV) @@ -98,7 +106,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.1.2" +#define DRIVER_VERSION "v1.1.3" #define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu" #define DRIVER_DESC "Keyspan USB to Serial Converter Driver" @@ -423,9 +431,10 @@ static void usa26_indat_callback(struct urb *urb) /* Resubmit urb so we continue receiving */ urb->dev = port->serial->dev; - if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { - dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); - } + if (port->open_count) + if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { + dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); + } return; } @@ -461,7 +470,7 @@ static void usa26_outcont_callback(struct urb *urb) if (p_priv->resend_cont) { dbg ("%s - sending setup", __FUNCTION__); - keyspan_usa26_send_setup(port->serial, port, 0); + keyspan_usa26_send_setup(port->serial, port, p_priv->resend_cont - 1); } } @@ -519,12 +528,12 @@ static void usa26_instat_callback(struct urb *urb) /* wake_up_interruptible(&p_priv->open_wait); */ } -exit: /* Resubmit urb so we continue receiving */ urb->dev = serial->dev; if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); } +exit: } static void usa26_glocont_callback(struct urb *urb) @@ -572,9 +581,10 @@ static void usa28_indat_callback(struct urb *urb) /* Resubmit urb so we continue receiving */ urb->dev = port->serial->dev; - if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { - dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); - } + if (port->open_count) + if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { + dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); + } p_priv->in_flip ^= 1; urb = p_priv->in_urbs[p_priv->in_flip]; @@ -596,7 +606,7 @@ static void usa28_outcont_callback(struct urb *urb) if (p_priv->resend_cont) { dbg ("%s - sending setup", __FUNCTION__); - keyspan_usa28_send_setup(port->serial, port, 0); + keyspan_usa28_send_setup(port->serial, port, p_priv->resend_cont - 1); } } @@ -653,12 +663,12 @@ static void usa28_instat_callback(struct urb *urb) /* wake_up_interruptible(&p_priv->open_wait); */ } -exit: /* Resubmit urb so we continue receiving */ urb->dev = serial->dev; if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); } +exit: } static void usa28_glocont_callback(struct urb *urb) @@ -683,7 +693,7 @@ static void usa49_glocont_callback(struct urb *urb) if (p_priv->resend_cont) { dbg ("%s - sending setup", __FUNCTION__); - keyspan_usa49_send_setup(serial, port, 0); + keyspan_usa49_send_setup(serial, port, p_priv->resend_cont - 1); break; } } @@ -745,13 +755,13 @@ static void usa49_instat_callback(struct urb *urb) /* wake_up_interruptible(&p_priv->open_wait); */ } -exit: /* Resubmit urb so we continue receiving */ urb->dev = serial->dev; if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); } +exit: } static void usa49_inack_callback(struct urb *urb) @@ -805,9 +815,10 @@ static void usa49_indat_callback(struct urb *urb) /* Resubmit urb so we continue receiving */ urb->dev = port->serial->dev; - if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { - dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); - } + if (port->open_count) + if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { + dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); + } } /* not used, usa-49 doesn't have per-port control endpoints */ @@ -820,9 +831,27 @@ static void usa49_outcont_callback(struct urb *urb) static int keyspan_write_room (struct usb_serial_port *port) { + struct keyspan_port_private *p_priv; + const struct keyspan_device_details *d_details; + int flip; + struct urb *this_urb; + dbg("%s", __FUNCTION__); - return (32); + p_priv = (struct keyspan_port_private *)(port->private); + d_details = p_priv->device_details; + flip = p_priv->out_flip; + + /* Check both endpoints to see if any are available. */ + if ((this_urb = p_priv->out_urbs[flip]) != 0) { + if (this_urb->status != -EINPROGRESS) + return (63); + flip = (flip + 1) & d_details->outdat_endp_flip; + if ((this_urb = p_priv->out_urbs[flip]) != 0) + if (this_urb->status != -EINPROGRESS) + return (63); + } + return (0); } @@ -873,7 +902,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp) if ((urb = p_priv->out_urbs[i]) == NULL) continue; urb->dev = serial->dev; - usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); + /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */ } keyspan_send_setup(port, 1); @@ -909,8 +938,12 @@ static void keyspan_close(struct usb_serial_port *port, struct file *filp) p_priv->rts_state = 0; p_priv->dtr_state = 0; - if (serial->dev) - keyspan_send_setup(port, 1); + if (serial->dev) { + keyspan_send_setup(port, 2); + /* pilot-xfer seems to work best with this delay */ + mdelay(100); + keyspan_set_termios(port, NULL); + } /*while (p_priv->outcont_urb->status == -EINPROGRESS) { dbg("%s - urb in progress", __FUNCTION__); @@ -922,7 +955,7 @@ static void keyspan_close(struct usb_serial_port *port, struct file *filp) if (serial->dev) { /* Stop reading/writing urbs */ stop_urb(p_priv->inack_urb); - stop_urb(p_priv->outcont_urb); + /* stop_urb(p_priv->outcont_urb); */ for (i = 0; i < 2; i++) { stop_urb(p_priv->in_urbs[i]); stop_urb(p_priv->out_urbs[i]); @@ -1365,7 +1398,10 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial, return -1; } - p_priv->resend_cont = 1; + /* Save reset port val for resend. + Don't overwrite resend for close condition. */ + if (p_priv->resend_cont != 3) + p_priv->resend_cont = reset_port + 1; if (this_urb->status == -EINPROGRESS) { /* dbg ("%s - already writing", __FUNCTION__); */ return(-1); @@ -1414,12 +1450,26 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial, msg.ctsFlowControl = (p_priv->flow_control == flow_cts); msg.xonFlowControl = 0; msg.setFlowControl = 0xff; - - msg.forwardingLength = 1; + msg.forwardingLength = 16; msg.xonChar = 17; msg.xoffChar = 19; - if (reset_port) { + /* Opening port */ + if (reset_port == 1) { + msg._txOn = 1; + msg._txOff = 0; + msg.txFlush = 0; + msg.txBreak = 0; + msg.rxOn = 1; + msg.rxOff = 0; + msg.rxFlush = 1; + msg.rxForward = 0; + msg.returnStatus = 0; + msg.resetDataToggle = 0xff; + } + + /* Closing port */ + else if (reset_port == 2) { msg._txOn = 0; msg._txOff = 1; msg.txFlush = 0; @@ -1429,14 +1479,16 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial, msg.rxFlush = 1; msg.rxForward = 0; msg.returnStatus = 0; - msg.resetDataToggle = 0xff; + msg.resetDataToggle = 0; } + + /* Sending intermediate configs */ else { msg._txOn = (! p_priv->break_on); msg._txOff = 0; msg.txFlush = 0; msg.txBreak = (p_priv->break_on); - msg.rxOn = 1; + msg.rxOn = 0; msg.rxOff = 0; msg.rxFlush = 0; msg.rxForward = 0; @@ -1496,7 +1548,10 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial, return -1; } - p_priv->resend_cont = 1; + /* Save reset port val for resend. + Don't overwrite resend for close condition. */ + if (p_priv->resend_cont != 3) + p_priv->resend_cont = reset_port + 1; if (this_urb->status == -EINPROGRESS) { dbg ("%s already writing", __FUNCTION__); return(-1); @@ -1522,7 +1577,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial, msg.rts = p_priv->rts_state; msg.dtr = p_priv->dtr_state; - msg.forwardingLength = 1; + msg.forwardingLength = 16; msg.forwardMs = 10; msg.breakThreshold = 45; msg.xonChar = 17; @@ -1530,8 +1585,22 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial, /*msg.returnStatus = 1; msg.resetDataToggle = 0xff;*/ - - if (reset_port) { + /* Opening port */ + if (reset_port == 1) { + msg._txOn = 1; + msg._txOff = 0; + msg.txFlush = 0; + msg.txForceXoff = 0; + msg.txBreak = 0; + msg.rxOn = 1; + msg.rxOff = 0; + msg.rxFlush = 1; + msg.rxForward = 0; + msg.returnStatus = 0; + msg.resetDataToggle = 0xff; + } + /* Closing port */ + else if (reset_port == 2) { msg._txOn = 0; msg._txOff = 1; msg.txFlush = 0; @@ -1542,15 +1611,16 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial, msg.rxFlush = 1; msg.rxForward = 0; msg.returnStatus = 0; - msg.resetDataToggle = 0xff; + msg.resetDataToggle = 0; } + /* Sending intermediate configs */ else { msg._txOn = (! p_priv->break_on); msg._txOff = 0; msg.txFlush = 0; msg.txForceXoff = 0; msg.txBreak = (p_priv->break_on); - msg.rxOn = 1; + msg.rxOn = 0; msg.rxOff = 0; msg.rxFlush = 0; msg.rxForward = 0; @@ -1610,7 +1680,10 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, return -1; } - p_priv->resend_cont = 1; + /* Save reset port val for resend. + Don't overwrite resend for close condition. */ + if (p_priv->resend_cont != 3) + p_priv->resend_cont = reset_port + 1; if (this_urb->status == -EINPROGRESS) { /* dbg ("%s - already writing", __FUNCTION__); */ return(-1); @@ -1663,11 +1736,27 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, msg.xonFlowControl = 0; msg.setFlowControl = 0xff; - msg.forwardingLength = 1; + msg.forwardingLength = 16; msg.xonChar = 17; msg.xoffChar = 19; - if (reset_port) { + /* Opening port */ + if (reset_port == 1) { + msg._txOn = 1; + msg._txOff = 0; + msg.txFlush = 0; + msg.txBreak = 0; + msg.rxOn = 1; + msg.rxOff = 0; + msg.rxFlush = 1; + msg.rxForward = 0; + msg.returnStatus = 0; + msg.resetDataToggle = 0xff; + msg.enablePort = 1; + msg.disablePort = 0; + } + /* Closing port */ + else if (reset_port == 2) { msg._txOn = 0; msg._txOff = 1; msg.txFlush = 0; @@ -1677,23 +1766,23 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, msg.rxFlush = 1; msg.rxForward = 0; msg.returnStatus = 0; - msg.resetDataToggle = 0xff; + msg.resetDataToggle = 0; msg.enablePort = 0; - msg.disablePort = 0xff; - + msg.disablePort = 1; } + /* Sending intermediate configs */ else { msg._txOn = (! p_priv->break_on); msg._txOff = 0; msg.txFlush = 0; msg.txBreak = (p_priv->break_on); - msg.rxOn = 1; + msg.rxOn = 0; msg.rxOff = 0; msg.rxFlush = 0; msg.rxForward = 0; msg.returnStatus = 0; msg.resetDataToggle = 0x0; - msg.enablePort = 0xff; + msg.enablePort = 0; msg.disablePort = 0; } diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index fc2c72e4a471..1d7c06b833ff 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -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); |
