Commit 6c3b56e8 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 191f0f05 08792789
......@@ -149,6 +149,7 @@ int dev_hotplug (struct device *dev, const char *action)
int class_hotplug (struct device *dev, const char *action)
{
struct device_class * cls;
int retval;
pr_debug ("%s\n", __FUNCTION__);
......@@ -162,5 +163,9 @@ int class_hotplug (struct device *dev, const char *action)
if (!cls)
return -ENODEV;
return do_hotplug (dev, cls->name, action, cls->hotplug);
retval = do_hotplug (dev, cls->name, action, cls->hotplug);
put_devclass(cls);
return retval;
}
......@@ -16,9 +16,12 @@ config USB_AUDIO
The module will be called audio.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
comment "USB Bluetooth TTY can only be used with disabled Bluetooth subsystem"
depends on USB && BT
config USB_BLUETOOTH_TTY
tristate "USB Bluetooth TTY support"
depends on USB
depends on USB && BT=n
---help---
This driver implements a nonstandard tty interface to a Bluetooth
device that can be used only by specialized Bluetooth HCI software.
......
......@@ -188,8 +188,6 @@ static void usblp_dump(struct usblp *usblp) {
extern devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */
static struct usblp *usblp_table[USBLP_MINORS];
/* Quirks: various printer quirks are handled by this table & its flags. */
struct quirk_printer_struct {
......@@ -325,17 +323,22 @@ static int usblp_check_status(struct usblp *usblp, int err)
static int usblp_open(struct inode *inode, struct file *file)
{
int minor = minor(inode->i_rdev) - USBLP_MINOR_BASE;
int minor = minor(inode->i_rdev);
struct usblp *usblp;
struct usb_interface *intf;
int retval;
if (minor < 0 || minor >= USBLP_MINORS)
return -ENODEV;
lock_kernel();
usblp = usblp_table[minor];
retval = -ENODEV;
intf = usb_find_interface(&usblp_driver, mk_kdev(USB_MAJOR,minor));
if (!intf) {
goto out;
}
usblp = dev_get_drvdata (&intf->dev);
if (!usblp || !usblp->dev)
goto out;
......@@ -382,7 +385,6 @@ static int usblp_open(struct inode *inode, struct file *file)
static void usblp_cleanup (struct usblp *usblp)
{
devfs_unregister (usblp->devfs);
usblp_table [usblp->minor] = NULL;
usb_deregister_dev (1, usblp->minor);
info("usblp%d: removed", usblp->minor);
......@@ -905,14 +907,11 @@ static int usblp_probe(struct usb_interface *intf,
usblp_check_status(usblp, 0);
#endif
/* add a table entry so the device works when advertised */
usblp_table[usblp->minor] = usblp;
/* If we have devfs, create with perms=660. */
sprintf(name, "lp%d", usblp->minor);
usblp->devfs = devfs_register(usb_devfs_handle, name,
DEVFS_FL_DEFAULT, USB_MAJOR,
USBLP_MINOR_BASE + usblp->minor,
usblp->minor,
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
S_IWGRP, &usblp_fops, NULL);
......@@ -925,6 +924,10 @@ static int usblp_probe(struct usb_interface *intf,
usblp->dev->descriptor.idProduct);
dev_set_drvdata (&intf->dev, usblp);
/* add device id so the device works when advertised */
intf->kdev = mk_kdev(USB_MAJOR,usblp->minor);
return 0;
abort_minor:
......@@ -1109,6 +1112,9 @@ static void usblp_disconnect(struct usb_interface *intf)
{
struct usblp *usblp = dev_get_drvdata (&intf->dev);
/* remove device id to disable open() */
intf->kdev = NODEV;
if (!usblp || !usblp->dev) {
err("bogus disconnect");
BUG ();
......
......@@ -768,35 +768,49 @@ void usb_hub_port_disable(struct usb_device *hub, int port)
* Not covered by the spec - but easy to deal with.
*
* This implementation uses 400ms minimum debounce timeout and checks
* every 100ms for transient disconnects to restart the delay.
* every 25ms for transient disconnects to restart the delay.
*/
#define HUB_DEBOUNCE_TIMEOUT 400
#define HUB_DEBOUNCE_STEP 100
#define HUB_DEBOUNCE_STEP 25
#define HUB_DEBOUNCE_STABLE 4
/* return: -1 on error, 0 on success, 1 on disconnect. */
static int usb_hub_port_debounce(struct usb_device *hub, int port)
{
int ret;
unsigned delay_time;
int delay_time, stable_count;
u16 portchange, portstatus;
unsigned connection;
for (delay_time = 0; delay_time < HUB_DEBOUNCE_TIMEOUT; /* empty */ ) {
/* wait debounce step increment */
connection = 0;
stable_count = 0;
for (delay_time = 0; delay_time < HUB_DEBOUNCE_TIMEOUT; delay_time += HUB_DEBOUNCE_STEP) {
wait_ms(HUB_DEBOUNCE_STEP);
ret = usb_hub_port_status(hub, port, &portstatus, &portchange);
if (ret < 0)
return -1;
if ((portstatus & USB_PORT_STAT_CONNECTION) == connection) {
if (connection) {
if (++stable_count == HUB_DEBOUNCE_STABLE)
break;
}
} else {
stable_count = 0;
}
connection = portstatus & USB_PORT_STAT_CONNECTION;
if ((portchange & USB_PORT_STAT_C_CONNECTION)) {
usb_clear_port_feature(hub, port+1, USB_PORT_FEAT_C_CONNECTION);
delay_time = 0;
}
else
delay_time += HUB_DEBOUNCE_STEP;
}
/* XXX Replace this with dbg() when 2.6 is about to ship. */
info("debounce: hub %d port %d: delay %dms stable %d status 0x%x\n",
hub->devnum, port, delay_time, stable_count, portstatus);
return ((portstatus&USB_PORT_STAT_CONNECTION)) ? 0 : 1;
}
......
......@@ -470,6 +470,40 @@ usb_match_id(struct usb_interface *interface, const struct usb_device_id *id)
return NULL;
}
/**
* usb_find_interface - find usb_interface pointer for driver and device
* @drv: the driver whose current configuration is considered
* @kdev: the desired device
*
* This walks the driver device list and returns a pointer to the interface
* with the matching kdev_t.
*/
struct usb_interface *usb_find_interface(struct usb_driver *drv, kdev_t kdev)
{
struct list_head *entry;
struct device *dev;
struct usb_interface *intf;
list_for_each(entry, &drv->driver.devices) {
dev = container_of(entry, struct device, driver_list);
/* can't look at usb devices, only interfaces */
if (dev->driver == &usb_generic_driver)
continue;
intf = to_usb_interface(dev);
if (!intf)
continue;
if (kdev_same(intf->kdev,kdev)) {
return intf;
}
}
/* no device found that matches */
return NULL;
}
static int usb_device_match (struct device *dev, struct device_driver *drv)
{
struct usb_interface *intf;
......@@ -1445,6 +1479,7 @@ EXPORT_SYMBOL(usb_driver_claim_interface);
EXPORT_SYMBOL(usb_interface_claimed);
EXPORT_SYMBOL(usb_driver_release_interface);
EXPORT_SYMBOL(usb_match_id);
EXPORT_SYMBOL(usb_find_interface);
EXPORT_SYMBOL(usb_new_device);
EXPORT_SYMBOL(usb_reset_device);
......
......@@ -398,6 +398,7 @@ open_scanner(struct inode * inode, struct file * file)
{
struct scn_usb_data *scn;
struct usb_device *dev;
struct usb_interface *intf;
int scn_minor;
......@@ -409,13 +410,13 @@ open_scanner(struct inode * inode, struct file * file)
dbg("open_scanner: scn_minor:%d", scn_minor);
if (!p_scn_table[scn_minor]) {
intf = usb_find_interface(&scanner_driver, mk_kdev(USB_MAJOR,scn_minor));
if (!intf) {
up(&scn_mutex);
err("open_scanner(%d): Unable to access minor data", scn_minor);
return -ENODEV;
}
scn = p_scn_table[scn_minor];
scn = dev_get_drvdata (&intf->dev);
dev = scn->scn_dev;
......@@ -458,7 +459,7 @@ open_scanner(struct inode * inode, struct file * file)
static int
close_scanner(struct inode * inode, struct file * file)
{
struct scn_usb_data *scn;
struct scn_usb_data *scn = file->private_data;
int scn_minor;
......@@ -466,15 +467,9 @@ close_scanner(struct inode * inode, struct file * file)
dbg("close_scanner: scn_minor:%d", scn_minor);
if (!p_scn_table[scn_minor]) {
err("close_scanner(%d): invalid scn_minor", scn_minor);
return -ENODEV;
}
down(&scn_mutex);
scn = p_scn_table[scn_minor];
down(&(scn->sem));
scn->isopen = 0;
file->private_data = NULL;
......@@ -695,17 +690,12 @@ ioctl_scanner(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct usb_device *dev;
struct scn_usb_data *scn = file->private_data;
int scn_minor;
scn_minor = USB_SCN_MINOR(inode);
if (!p_scn_table[scn_minor]) {
err("ioctl_scanner(%d): invalid scn_minor", scn_minor);
return -ENODEV;
}
dev = p_scn_table[scn_minor]->scn_dev;
dev = scn->scn_dev;
switch (cmd)
{
......@@ -987,13 +977,6 @@ probe_scanner(struct usb_interface *intf,
return -ENOMEM;
}
/* Check to make sure that the last slot isn't already taken */
if (p_scn_table[scn_minor]) {
err("probe_scanner: No more minor devices remaining.");
up(&scn_mutex);
return -ENOMEM;
}
dbg("probe_scanner: Allocated minor:%d", scn_minor);
if (!(scn = kmalloc (sizeof (struct scn_usb_data), GFP_KERNEL))) {
......@@ -1082,17 +1065,19 @@ probe_scanner(struct usb_interface *intf,
scn->devfs = devfs_register(usb_devfs_handle, name,
DEVFS_FL_DEFAULT, USB_MAJOR,
SCN_BASE_MNR + scn->scn_minor,
scn->scn_minor,
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
S_IWGRP | S_IROTH | S_IWOTH, &usb_scanner_fops, NULL);
if (scn->devfs == NULL)
dbg("scanner%d: device node registration failed", scn_minor);
p_scn_table[scn_minor] = scn;
up(&scn_mutex);
dev_set_drvdata(&intf->dev, scn);
/* add device id so the device works when advertised */
intf->kdev = mk_kdev(USB_MAJOR,scn->scn_minor);
return 0;
}
......@@ -1101,6 +1086,9 @@ disconnect_scanner(struct usb_interface *intf)
{
struct scn_usb_data *scn = dev_get_drvdata(&intf->dev);
/* remove device id to disable open() */
intf->kdev = NODEV;
dev_set_drvdata(&intf->dev, NULL);
if (scn) {
down (&scn_mutex);
......@@ -1119,7 +1107,6 @@ disconnect_scanner(struct usb_interface *intf)
dbg("disconnect_scanner: De-allocating minor:%d", scn->scn_minor);
devfs_unregister(scn->devfs);
usb_deregister_dev(1, scn->scn_minor);
p_scn_table[scn->scn_minor] = NULL;
usb_free_urb(scn->scn_irq);
up (&(scn->sem));
kfree (scn);
......
......@@ -216,7 +216,7 @@ MODULE_DEVICE_TABLE (usb, scanner_device_ids);
#define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep)->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
#define IS_EP_INTR(ep) ((ep)->bmAttributes == USB_ENDPOINT_XFER_INT ? 1 : 0)
#define USB_SCN_MINOR(X) minor((X)->i_rdev) - SCN_BASE_MNR
#define USB_SCN_MINOR(X) minor((X)->i_rdev)
#ifdef DEBUG
#define SCN_DEBUG(X) X
......@@ -274,6 +274,4 @@ struct scn_usb_data {
extern devfs_handle_t usb_devfs_handle;
static struct scn_usb_data *p_scn_table[SCN_MAX_MNR] = { NULL, /* ... */};
static struct usb_driver scanner_driver;
......@@ -45,7 +45,7 @@
/*
* Version Information
*/
#define DRIVER_VERSION "v0.5.7 (2002/11/18)"
#define DRIVER_VERSION "v0.5.8 (2002/12/13)"
#define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
......@@ -118,9 +118,14 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
void *data)
{
int ret;
unsigned char buffer[256];
char *buffer;
DECLARE_WAITQUEUE(wait, current);
buffer = kmalloc(size, GFP_DMA);
if (!buffer) {
warn("%s: looks like we're out of memory", __FUNCTION__);
return -ENOMEM;
}
add_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE);
while (pegasus->flags & ETH_REGS_CHANGED)
......@@ -153,6 +158,7 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
out:
remove_wait_queue(&pegasus->ctrl_wait, &wait);
memcpy(data, buffer, size);
kfree(buffer);
return ret;
}
......@@ -161,9 +167,14 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
void *data)
{
int ret;
unsigned char buffer[256];
char *buffer;
DECLARE_WAITQUEUE(wait, current);
buffer = kmalloc(size, GFP_DMA);
if (!buffer) {
warn("%s: looks like we're out of memory", __FUNCTION__);
return -ENOMEM;
}
memcpy(buffer, data, size);
add_wait_queue(&pegasus->ctrl_wait, &wait);
......@@ -196,6 +207,7 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
schedule();
out:
remove_wait_queue(&pegasus->ctrl_wait, &wait);
kfree(buffer);
return ret;
}
......@@ -203,9 +215,15 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
{
int ret;
__u16 tmp = data;
char *tmp;
DECLARE_WAITQUEUE(wait, current);
tmp = kmalloc(1, GFP_DMA);
if (!tmp) {
warn("%s: looks like we're out of memory", __FUNCTION__);
return -ENOMEM;
}
memcpy(tmp, &data, 1);
add_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE);
while (pegasus->flags & ETH_REGS_CHANGED)
......@@ -215,7 +233,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
pegasus->dr.bRequestType = PEGASUS_REQT_WRITE;
pegasus->dr.bRequest = PEGASUS_REQ_SET_REG;
pegasus->dr.wValue = cpu_to_le16p(&tmp);
pegasus->dr.wValue = cpu_to_le16p(&data);
pegasus->dr.wIndex = cpu_to_le16p(&indx);
pegasus->dr.wLength = cpu_to_le16(1);
pegasus->ctrl_urb->transfer_buffer_length = 1;
......@@ -223,7 +241,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb,
usb_sndctrlpipe(pegasus->usb, 0),
(char *) &pegasus->dr,
&data, 1, ctrl_callback, pegasus);
&tmp, 1, ctrl_callback, pegasus);
add_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE);
......@@ -236,6 +254,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
schedule();
out:
remove_wait_queue(&pegasus->ctrl_wait, &wait);
kfree(tmp);
return ret;
}
......
......@@ -33,7 +33,7 @@ obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o
# Objects that export symbols.
export-objs := usb-serial.o ezusb.o
usbserial-objs := usb-serial.o generic.o $(usbserial-obj-y)
usbserial-objs := usb-serial.o generic.o bus.o $(usbserial-obj-y)
include $(TOPDIR)/Rules.make
/*
* USB Serial Converter Bus specific functions
*
* Copyright (C) 2002 Greg Kroah-Hartman (greg@kroah.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/tty.h>
#include <linux/module.h>
#include <linux/usb.h>
#ifdef CONFIG_USB_SERIAL_DEBUG
static int debug = 1;
#else
static int debug;
#endif
#include "usb-serial.h"
static int usb_serial_device_match (struct device *dev, struct device_driver *drv)
{
struct usb_serial_device_type *driver;
const struct usb_serial_port *port;
/*
* drivers are already assigned to ports in serial_probe so it's
* a simple check here.
*/
port = to_usb_serial_port(dev);
if (!port)
return 0;
driver = to_usb_serial_driver(drv);
if (driver == port->serial->type)
return 1;
return 0;
}
struct bus_type usb_serial_bus_type = {
.name = "usb-serial",
.match = usb_serial_device_match,
};
static int usb_serial_device_probe (struct device *dev)
{
struct usb_serial_device_type *driver;
struct usb_serial_port *port;
int retval = 0;
int minor;
port = to_usb_serial_port(dev);
if (!port) {
retval = -ENODEV;
goto exit;
}
driver = port->serial->type;
if (driver->port_probe) {
if (!try_module_get(driver->owner)) {
err ("module get failed, exiting");
retval = -EIO;
goto exit;
}
retval = driver->port_probe (port);
module_put(driver->owner);
if (retval)
goto exit;
}
minor = port->number;
tty_register_devfs (&usb_serial_tty_driver, 0, minor);
info("%s converter now attached to ttyUSB%d (or usb/tts/%d for devfs)",
driver->name, minor, minor);
exit:
return retval;
}
static int usb_serial_device_remove (struct device *dev)
{
struct usb_serial_device_type *driver;
struct usb_serial_port *port;
int retval = 0;
int minor;
port = to_usb_serial_port(dev);
if (!port) {
return -ENODEV;
}
driver = port->serial->type;
if (driver->port_remove) {
if (!try_module_get(driver->owner)) {
err ("module get failed, exiting");
retval = -EIO;
goto exit;
}
retval = driver->port_remove (port);
module_put(driver->owner);
}
exit:
minor = port->number;
tty_unregister_devfs (&usb_serial_tty_driver, minor);
info("%s converter now disconnected from ttyUSB%d",
driver->name, minor);
return retval;
}
int usb_serial_bus_register(struct usb_serial_device_type *device)
{
int retval;
device->driver.name = (char *)device->name;
device->driver.bus = &usb_serial_bus_type;
device->driver.probe = usb_serial_device_probe;
device->driver.remove = usb_serial_device_remove;
retval = driver_register(&device->driver);
return retval;
}
void usb_serial_bus_deregister(struct usb_serial_device_type *device)
{
driver_unregister (&device->driver);
}
......@@ -14,6 +14,10 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
* (12/10/2002) gkh
* Split the ports off into their own struct device, and added a
* usb-serial bus driver.
*
* (11/19/2002) gkh
* removed a few #ifdefs for the generic code and cleaned up the failure
* logic in initialization.
......@@ -345,7 +349,7 @@
/*
* Version Information
*/
#define DRIVER_VERSION "v1.8"
#define DRIVER_VERSION "v2.0"
#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
#define DRIVER_DESC "USB Serial Driver core"
......@@ -378,13 +382,13 @@ static struct usb_driver usb_serial_driver = {
*/
static int serial_refcount;
static struct tty_driver serial_tty_driver;
static struct tty_struct * serial_tty[SERIAL_TTY_MINORS];
static struct termios * serial_termios[SERIAL_TTY_MINORS];
static struct termios * serial_termios_locked[SERIAL_TTY_MINORS];
static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */
static LIST_HEAD(usb_serial_driver_list);
struct usb_serial *usb_serial_get_by_minor (unsigned int minor)
{
return serial_table[minor];
......@@ -1132,11 +1136,17 @@ int usb_serial_probe(struct usb_interface *interface,
}
}
/* initialize the devfs nodes for this device and let the user know what ports we are bound to */
for (i = 0; i < serial->num_ports; ++i) {
tty_register_devfs (&serial_tty_driver, 0, serial->port[i].number);
info("%s converter now attached to ttyUSB%d (or usb/tts/%d for devfs)",
type->name, serial->port[i].number, serial->port[i].number);
/* register all of the individual ports with the driver core */
for (i = 0; i < num_ports; ++i) {
port = &serial->port[i];
port->dev.parent = &serial->dev->dev;
port->dev.driver = NULL;
port->dev.bus = &usb_serial_bus_type;
snprintf (&port->dev.bus_id[0], sizeof(port->dev.bus_id), "ttyUSB%d", port->number);
snprintf (&port->dev.name[0], sizeof(port->dev.name), "usb serial port %d", port->number);
dbg ("%s - registering %s", __FUNCTION__, port->dev.bus_id);
device_register (&port->dev);
}
usb_serial_console_init (debug, minor);
......@@ -1203,6 +1213,9 @@ void usb_serial_disconnect(struct usb_interface *interface)
serial->dev = NULL;
serial_shutdown (serial);
for (i = 0; i < serial->num_ports; ++i)
device_unregister(&serial->port[i].dev);
for (i = 0; i < serial->num_ports; ++i)
serial->port[i].open_count = 0;
......@@ -1233,12 +1246,6 @@ void usb_serial_disconnect(struct usb_interface *interface)
if (port->interrupt_in_buffer)
kfree (port->interrupt_in_buffer);
}
for (i = 0; i < serial->num_ports; ++i) {
tty_unregister_devfs (&serial_tty_driver, serial->port[i].number);
info("%s converter now disconnected from ttyUSB%d", serial->type->name, serial->port[i].number);
}
/* return the minor range that this device had */
return_serial (serial);
......@@ -1250,7 +1257,7 @@ void usb_serial_disconnect(struct usb_interface *interface)
}
static struct tty_driver serial_tty_driver = {
struct tty_driver usb_serial_tty_driver = {
.magic = TTY_DRIVER_MAGIC,
.driver_name = "usb-serial",
#ifndef CONFIG_DEVFS_FS
......@@ -1294,6 +1301,8 @@ static int __init usb_serial_init(void)
serial_table[i] = NULL;
}
bus_register(&usb_serial_bus_type);
/* register the generic driver, if we should */
result = usb_serial_generic_register(debug);
if (result < 0) {
......@@ -1302,9 +1311,9 @@ static int __init usb_serial_init(void)
}
/* register the tty driver */
serial_tty_driver.init_termios = tty_std_termios;
serial_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
result = tty_register_driver (&serial_tty_driver);
usb_serial_tty_driver.init_termios = tty_std_termios;
usb_serial_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
result = tty_register_driver (&usb_serial_tty_driver);
if (result) {
err("%s - tty_register_driver failed", __FUNCTION__);
goto exit_generic;
......@@ -1322,7 +1331,7 @@ static int __init usb_serial_init(void)
return result;
exit_tty:
tty_unregister_driver(&serial_tty_driver);
tty_unregister_driver(&usb_serial_tty_driver);
exit_generic:
usb_serial_generic_deregister();
......@@ -1340,7 +1349,8 @@ static void __exit usb_serial_exit(void)
usb_serial_generic_deregister();
usb_deregister(&usb_serial_driver);
tty_unregister_driver(&serial_tty_driver);
tty_unregister_driver(&usb_serial_tty_driver);
bus_unregister(&usb_serial_bus_type);
}
......@@ -1350,12 +1360,24 @@ module_exit(usb_serial_exit);
int usb_serial_register(struct usb_serial_device_type *new_device)
{
int retval;
/* Add this device to our list of devices */
list_add(&new_device->driver_list, &usb_serial_driver_list);
info ("USB Serial support registered for %s", new_device->name);
retval = usb_serial_bus_register (new_device);
return 0;
if (retval)
goto error;
info("USB Serial support registered for %s", new_device->name);
return retval;
error:
err("problem %d when registering driver %s", retval, new_device->name);
list_del(&new_device->driver_list);
return retval;
}
......@@ -1376,6 +1398,7 @@ void usb_serial_deregister(struct usb_serial_device_type *device)
}
list_del(&device->driver_list);
usb_serial_bus_deregister (device);
}
......
......@@ -121,7 +121,9 @@ struct usb_serial_port {
int open_count;
struct semaphore sem;
void * private;
struct device dev;
};
#define to_usb_serial_port(d) container_of(d, struct usb_serial_port, dev)
/**
* usb_serial - structure used by the usb-serial core for a device
......@@ -206,6 +208,7 @@ struct usb_serial_device_type {
char num_ports;
struct list_head driver_list;
struct device_driver driver;
int (*probe) (struct usb_serial *serial);
int (*attach) (struct usb_serial *serial);
......@@ -213,6 +216,9 @@ struct usb_serial_device_type {
void (*shutdown) (struct usb_serial *serial);
int (*port_probe) (struct usb_serial_port *port);
int (*port_remove) (struct usb_serial_port *port);
/* serial function calls */
int (*open) (struct usb_serial_port *port, struct file * filp);
void (*close) (struct usb_serial_port *port, struct file * filp);
......@@ -229,6 +235,7 @@ struct usb_serial_device_type {
void (*read_bulk_callback)(struct urb *urb, struct pt_regs *regs);
void (*write_bulk_callback)(struct urb *urb, struct pt_regs *regs);
};
#define to_usb_serial_driver(d) container_of(d, struct usb_serial_device_type, driver)
extern int usb_serial_register(struct usb_serial_device_type *new_device);
extern void usb_serial_deregister(struct usb_serial_device_type *device);
......@@ -262,7 +269,12 @@ extern void usb_serial_generic_shutdown (struct usb_serial *serial);
extern int usb_serial_generic_register (int debug);
extern void usb_serial_generic_deregister (void);
extern int usb_serial_bus_register (struct usb_serial_device_type *device);
extern void usb_serial_bus_deregister (struct usb_serial_device_type *device);
extern struct usb_serial_device_type usb_serial_generic_device;
extern struct bus_type usb_serial_bus_type;
extern struct tty_driver usb_serial_tty_driver;
/* Inline functions to check the sanity of a pointer that is passed to us */
static inline int serial_paranoia_check (struct usb_serial *serial, const char *function)
......
......@@ -214,9 +214,9 @@ UNUSUAL_DEV( 0x0525, 0xa140, 0x0100, 0x0100,
US_FL_FIX_INQUIRY | US_FL_START_STOP ),
/* This entry is needed because the device reports Sub=ff */
UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0422,
UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0440,
"Sony",
"DSC-S30/S70/S75/505V/F505/F707",
"DSC-S30/S70/S75/505V/F505/F707/F717",
US_SC_SCSI, US_PR_CB, NULL,
US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE ),
......@@ -503,6 +503,18 @@ UNUSUAL_DEV( 0x07c4, 0xa103, 0x0000, 0x9999,
US_FL_FIX_INQUIRY ),
#endif
/* Datafab KECF-USB / Sagatek DCS-CF / Simpletech Flashlink UCF-100
* Only revision 1.13 tested (same for all of the above devices,
* based on the Datafab DF-UG-07 chip). Needed for US_FL_FIX_INQUIRY.
* Submitted by Marek Michalkiewicz <marekm@amelek.gda.pl>.
* See also http://martin.wilck.bei.t-online.de/#kecf .
*/
UNUSUAL_DEV( 0x07c4, 0xa400, 0x0000, 0xffff,
"Datafab",
"KECF-USB",
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_FIX_INQUIRY ),
/* Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant
* to the USB storage specification in two ways:
* - They tell us they are using transport protocol CBI. In reality they
......
/*
* USB Skeleton driver - 0.8
* USB Skeleton driver - 0.9
*
* Copyright (c) 2001-2002 Greg Kroah-Hartman (greg@kroah.com)
*
......@@ -17,10 +17,10 @@
*
* TODO:
* - fix urb->status race condition in write sequence
* - move minor_table to a dynamic list.
*
* History:
*
* 2002_12_12 - 0.9 - compile fixes and got rid of fixed minor array.
* 2002_09_26 - 0.8 - changes due to USB core conversion to struct device
* driver.
* 2002_02_12 - 0.7 - zero out dev in probe function for devices that do
......@@ -83,18 +83,10 @@ 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
/* 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 */
......@@ -118,7 +110,7 @@ struct usb_skel {
__u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */
struct work_struct work; /* work queue entry for line discipline waking up */
int open_count; /* number of times this port has been opened */
int open; /* if the port is open or not */
struct semaphore sem; /* locks this structure */
};
......@@ -139,13 +131,6 @@ static void skel_disconnect (struct usb_interface *intf);
static void skel_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
/* array of pointers to our devices that are currently connected */
static struct usb_skel *minor_table[MAX_DEVICES];
/* lock to protect the minor_table structure */
static DECLARE_MUTEX (minor_table_mutex);
/*
* File operations needed when we register this driver.
* This assumes that this driver NEEDS file operations,
......@@ -218,7 +203,6 @@ static inline void usb_skel_debug_data (const char *function, int size, const un
*/
static inline void skel_delete (struct usb_skel *dev)
{
minor_table[dev->minor] = NULL;
if (dev->bulk_in_buffer != NULL)
kfree (dev->bulk_in_buffer);
if (dev->bulk_out_buffer != NULL)
......@@ -235,41 +219,31 @@ static inline void skel_delete (struct usb_skel *dev)
static int skel_open (struct inode *inode, struct file *file)
{
struct usb_skel *dev = NULL;
struct usb_interface *interface;
int subminor;
int retval = 0;
dbg(__FUNCTION__);
dbg("%s", __FUNCTION__);
subminor = minor (inode->i_rdev);
subminor = MINOR (inode->i_rdev) - USB_SKEL_MINOR_BASE;
if ((subminor < 0) ||
(subminor >= MAX_DEVICES)) {
interface = usb_find_interface (&skel_driver,
mk_kdev(USB_MAJOR, subminor));
if (!interface) {
err ("%s - error, can't find device for minor %d",
__FUNCTION__, subminor);
return -ENODEV;
}
/* Increment our usage count for the module.
* This is redundant here, because "struct file_operations"
* has an "owner" field. This line is included here soley as
* a reference for drivers using lesser structures... ;-)
*/
MOD_INC_USE_COUNT;
/* lock our minor table and get our local data for this minor */
down (&minor_table_mutex);
dev = minor_table[subminor];
if (dev == NULL) {
up (&minor_table_mutex);
MOD_DEC_USE_COUNT;
dev = dev_get_drvdata (&interface->dev);
if (!dev)
return -ENODEV;
}
/* lock this device */
down (&dev->sem);
/* unlock the minor table */
up (&minor_table_mutex);
/* increment our usage count for the driver */
++dev->open_count;
++dev->open;
/* save our object in the file's private structure */
file->private_data = dev;
......@@ -291,20 +265,17 @@ static int skel_release (struct inode *inode, struct file *file)
dev = (struct usb_skel *)file->private_data;
if (dev == NULL) {
dbg (__FUNCTION__ " - object is NULL");
dbg ("%s - object is NULL", __FUNCTION__);
return -ENODEV;
}
dbg(__FUNCTION__ " - minor %d", dev->minor);
/* lock our minor table */
down (&minor_table_mutex);
dbg("%s - minor %d", __FUNCTION__, dev->minor);
/* lock our device */
down (&dev->sem);
if (dev->open_count <= 0) {
dbg (__FUNCTION__ " - device not opened");
if (dev->open <= 0) {
dbg ("%s - device not opened", __FUNCTION__);
retval = -ENODEV;
goto exit_not_opened;
}
......@@ -313,25 +284,16 @@ static int skel_release (struct inode *inode, struct file *file)
/* the device was unplugged before the file was released */
up (&dev->sem);
skel_delete (dev);
up (&minor_table_mutex);
MOD_DEC_USE_COUNT;
return 0;
}
/* decrement our usage count for the device */
--dev->open_count;
if (dev->open_count <= 0) {
/* shutdown any bulk writes that might be going on */
usb_unlink_urb (dev->write_urb);
dev->open_count = 0;
}
/* decrement our usage count for the module */
MOD_DEC_USE_COUNT;
dev->open = 0;
exit_not_opened:
up (&dev->sem);
up (&minor_table_mutex);
return retval;
}
......@@ -347,7 +309,7 @@ static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t
dev = (struct usb_skel *)file->private_data;
dbg(__FUNCTION__ " - minor %d, count = %d", dev->minor, count);
dbg("%s - minor %d, count = %d", __FUNCTION__, dev->minor, count);
/* lock this object */
down (&dev->sem);
......@@ -390,7 +352,7 @@ static ssize_t skel_write (struct file *file, const char *buffer, size_t count,
dev = (struct usb_skel *)file->private_data;
dbg(__FUNCTION__ " - minor %d, count = %d", dev->minor, count);
dbg("%s - minor %d, count = %d", __FUNCTION__, dev->minor, count);
/* lock this object */
down (&dev->sem);
......@@ -403,13 +365,13 @@ static ssize_t skel_write (struct file *file, const char *buffer, size_t count,
/* verify that we actually have some data to write */
if (count == 0) {
dbg(__FUNCTION__ " - write request of 0 bytes");
dbg("%s - write request of 0 bytes", __FUNCTION__);
goto exit;
}
/* see if we are already in the middle of a write */
if (dev->write_urb->status == -EINPROGRESS) {
dbg (__FUNCTION__ " - already writing");
dbg ("%s - already writing", __FUNCTION__);
goto exit;
}
......@@ -438,8 +400,8 @@ static ssize_t skel_write (struct file *file, const char *buffer, size_t count,
unless a spinlock is held */
retval = usb_submit_urb(dev->write_urb, GFP_KERNEL);
if (retval) {
err(__FUNCTION__ " - failed submitting write urb, error %d",
retval);
err("%s - failed submitting write urb, error %d",
__FUNCTION__, retval);
} else {
retval = bytes_written;
}
......@@ -470,7 +432,7 @@ static int skel_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
return -ENODEV;
}
dbg(__FUNCTION__ " - minor %d, cmd 0x%.4x, arg %ld",
dbg("%s - minor %d, cmd 0x%.4x, arg %ld", __FUNCTION__,
dev->minor, cmd, arg);
......@@ -491,12 +453,12 @@ static void skel_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
{
struct usb_skel *dev = (struct usb_skel *)urb->context;
dbg(__FUNCTION__ " - minor %d", dev->minor);
dbg("%s - minor %d", __FUNCTION__, dev->minor);
if ((urb->status != -ENOENT) &&
(urb->status != -ECONNRESET)) {
dbg(__FUNCTION__ " - nonzero write bulk status received: %d",
urb->status);
dbg("%s - nonzero write bulk status received: %d",
__FUNCTION__, urb->status);
return;
}
......@@ -514,7 +476,7 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
{
struct usb_device *udev = interface_to_usbdev(interface);
struct usb_skel *dev = NULL;
struct usb_interface_descriptor *iface_desc;
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
int minor;
int buffer_size;
......@@ -529,7 +491,6 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
return -ENODEV;
}
down (&minor_table_mutex);
retval = usb_register_dev (&skel_fops, USB_SKEL_MINOR_BASE, 1, &minor);
if (retval) {
/* something prevented us from registering this driver */
......@@ -544,7 +505,6 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
goto exit_minor;
}
memset (dev, 0x00, sizeof (*dev));
minor_table[minor] = dev;
init_MUTEX (&dev->sem);
dev->udev = udev;
......@@ -554,7 +514,7 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
/* set up the endpoint information */
/* check out the endpoints */
iface_desc = &interface->altsetting[0];
for (i = 0; i < iface_desc->bNumEndpoints; ++i) {
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
if ((endpoint->bEndpointAddress & 0x80) &&
......@@ -600,13 +560,17 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
dev->devfs = devfs_register (usb_devfs_handle, name,
DEVFS_FL_DEFAULT, USB_MAJOR,
USB_SKEL_MINOR_BASE + dev->minor,
dev->minor,
S_IFCHR | S_IRUSR | S_IWUSR |
S_IRGRP | S_IWGRP | S_IROTH,
&skel_fops, NULL);
/* let the user know what node this device is now attached to */
info ("USB Skeleton device now attached to USBSkel%d", dev->minor);
/* add device id so the device works when advertised */
interface->kdev = mk_kdev(USB_MAJOR, dev->minor);
goto exit;
error:
......@@ -617,7 +581,6 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
usb_deregister_dev (1, minor);
exit:
up (&minor_table_mutex);
if (dev) {
dev_set_drvdata (&interface->dev, dev);
return 0;
......@@ -642,9 +605,11 @@ static void skel_disconnect(struct usb_interface *interface)
if (!dev)
return;
down (&minor_table_mutex);
down (&dev->sem);
/* remove device id to disable open() */
interface->kdev = NODEV;
minor = dev->minor;
/* remove our devfs node */
......@@ -654,7 +619,7 @@ static void skel_disconnect(struct usb_interface *interface)
usb_deregister_dev (1, minor);
/* if the device is not opened, then we clean up right now */
if (!dev->open_count) {
if (!dev->open) {
up (&dev->sem);
skel_delete (dev);
} else {
......@@ -663,7 +628,6 @@ static void skel_disconnect(struct usb_interface *interface)
}
info("USB Skeleton #%d now disconnected", minor);
up (&minor_table_mutex);
}
......
......@@ -117,6 +117,7 @@ struct usb_interface {
unsigned max_altsetting; /* total memory allocated */
struct usb_driver *driver; /* driver */
kdev_t kdev; /* node this interface is bound to */
struct device dev; /* interface specific device info */
void *private_data;
};
......@@ -271,6 +272,8 @@ extern void usb_driver_release_interface(struct usb_driver *driver,
const struct usb_device_id *usb_match_id(struct usb_interface *interface,
const struct usb_device_id *id);
struct usb_interface *usb_find_interface(struct usb_driver *drv, kdev_t kdev);
/**
* usb_make_path - returns stable device path in the usb tree
* @dev: the device whose path is being constructed
......
......@@ -526,7 +526,7 @@ static struct snd_urb_ops audio_urb_ops[2] = {
/*
* complete callback from data urb
*/
static void snd_complete_urb(struct urb *urb)
static void snd_complete_urb(struct urb *urb, struct pt_regs *regs)
{
snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
snd_usb_substream_t *subs = ctx->subs;
......@@ -551,7 +551,7 @@ static void snd_complete_urb(struct urb *urb)
/*
* complete callback from sync urb
*/
static void snd_complete_sync_urb(struct urb *urb)
static void snd_complete_sync_urb(struct urb *urb, struct pt_regs *regs)
{
snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
snd_usb_substream_t *subs = ctx->subs;
......
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