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) ...@@ -149,6 +149,7 @@ int dev_hotplug (struct device *dev, const char *action)
int class_hotplug (struct device *dev, const char *action) int class_hotplug (struct device *dev, const char *action)
{ {
struct device_class * cls; struct device_class * cls;
int retval;
pr_debug ("%s\n", __FUNCTION__); pr_debug ("%s\n", __FUNCTION__);
...@@ -162,5 +163,9 @@ int class_hotplug (struct device *dev, const char *action) ...@@ -162,5 +163,9 @@ int class_hotplug (struct device *dev, const char *action)
if (!cls) if (!cls)
return -ENODEV; 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 ...@@ -16,9 +16,12 @@ config USB_AUDIO
The module will be called audio.o. If you want to compile it as a 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>. 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 config USB_BLUETOOTH_TTY
tristate "USB Bluetooth TTY support" tristate "USB Bluetooth TTY support"
depends on USB depends on USB && BT=n
---help--- ---help---
This driver implements a nonstandard tty interface to a Bluetooth This driver implements a nonstandard tty interface to a Bluetooth
device that can be used only by specialized Bluetooth HCI software. device that can be used only by specialized Bluetooth HCI software.
......
...@@ -188,8 +188,6 @@ static void usblp_dump(struct usblp *usblp) { ...@@ -188,8 +188,6 @@ static void usblp_dump(struct usblp *usblp) {
extern devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */ 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. */ /* Quirks: various printer quirks are handled by this table & its flags. */
struct quirk_printer_struct { struct quirk_printer_struct {
...@@ -325,17 +323,22 @@ static int usblp_check_status(struct usblp *usblp, int err) ...@@ -325,17 +323,22 @@ static int usblp_check_status(struct usblp *usblp, int err)
static int usblp_open(struct inode *inode, struct file *file) 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 usblp *usblp;
struct usb_interface *intf;
int retval; int retval;
if (minor < 0 || minor >= USBLP_MINORS) if (minor < 0 || minor >= USBLP_MINORS)
return -ENODEV; return -ENODEV;
lock_kernel(); lock_kernel();
usblp = usblp_table[minor];
retval = -ENODEV; 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) if (!usblp || !usblp->dev)
goto out; goto out;
...@@ -382,7 +385,6 @@ static int usblp_open(struct inode *inode, struct file *file) ...@@ -382,7 +385,6 @@ static int usblp_open(struct inode *inode, struct file *file)
static void usblp_cleanup (struct usblp *usblp) static void usblp_cleanup (struct usblp *usblp)
{ {
devfs_unregister (usblp->devfs); devfs_unregister (usblp->devfs);
usblp_table [usblp->minor] = NULL;
usb_deregister_dev (1, usblp->minor); usb_deregister_dev (1, usblp->minor);
info("usblp%d: removed", usblp->minor); info("usblp%d: removed", usblp->minor);
...@@ -905,14 +907,11 @@ static int usblp_probe(struct usb_interface *intf, ...@@ -905,14 +907,11 @@ static int usblp_probe(struct usb_interface *intf,
usblp_check_status(usblp, 0); usblp_check_status(usblp, 0);
#endif #endif
/* add a table entry so the device works when advertised */
usblp_table[usblp->minor] = usblp;
/* If we have devfs, create with perms=660. */ /* If we have devfs, create with perms=660. */
sprintf(name, "lp%d", usblp->minor); sprintf(name, "lp%d", usblp->minor);
usblp->devfs = devfs_register(usb_devfs_handle, name, usblp->devfs = devfs_register(usb_devfs_handle, name,
DEVFS_FL_DEFAULT, USB_MAJOR, DEVFS_FL_DEFAULT, USB_MAJOR,
USBLP_MINOR_BASE + usblp->minor, usblp->minor,
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
S_IWGRP, &usblp_fops, NULL); S_IWGRP, &usblp_fops, NULL);
...@@ -925,6 +924,10 @@ static int usblp_probe(struct usb_interface *intf, ...@@ -925,6 +924,10 @@ static int usblp_probe(struct usb_interface *intf,
usblp->dev->descriptor.idProduct); usblp->dev->descriptor.idProduct);
dev_set_drvdata (&intf->dev, usblp); 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; return 0;
abort_minor: abort_minor:
...@@ -1109,6 +1112,9 @@ static void usblp_disconnect(struct usb_interface *intf) ...@@ -1109,6 +1112,9 @@ static void usblp_disconnect(struct usb_interface *intf)
{ {
struct usblp *usblp = dev_get_drvdata (&intf->dev); struct usblp *usblp = dev_get_drvdata (&intf->dev);
/* remove device id to disable open() */
intf->kdev = NODEV;
if (!usblp || !usblp->dev) { if (!usblp || !usblp->dev) {
err("bogus disconnect"); err("bogus disconnect");
BUG (); BUG ();
......
...@@ -768,35 +768,49 @@ void usb_hub_port_disable(struct usb_device *hub, int port) ...@@ -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. * Not covered by the spec - but easy to deal with.
* *
* This implementation uses 400ms minimum debounce timeout and checks * 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_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. */ /* return: -1 on error, 0 on success, 1 on disconnect. */
static int usb_hub_port_debounce(struct usb_device *hub, int port) static int usb_hub_port_debounce(struct usb_device *hub, int port)
{ {
int ret; int ret;
unsigned delay_time; int delay_time, stable_count;
u16 portchange, portstatus; u16 portchange, portstatus;
unsigned connection;
for (delay_time = 0; delay_time < HUB_DEBOUNCE_TIMEOUT; /* empty */ ) { connection = 0;
stable_count = 0;
/* wait debounce step increment */ for (delay_time = 0; delay_time < HUB_DEBOUNCE_TIMEOUT; delay_time += HUB_DEBOUNCE_STEP) {
wait_ms(HUB_DEBOUNCE_STEP); wait_ms(HUB_DEBOUNCE_STEP);
ret = usb_hub_port_status(hub, port, &portstatus, &portchange); ret = usb_hub_port_status(hub, port, &portstatus, &portchange);
if (ret < 0) if (ret < 0)
return -1; 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)) { if ((portchange & USB_PORT_STAT_C_CONNECTION)) {
usb_clear_port_feature(hub, port+1, USB_PORT_FEAT_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; 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) ...@@ -470,6 +470,40 @@ usb_match_id(struct usb_interface *interface, const struct usb_device_id *id)
return NULL; 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) static int usb_device_match (struct device *dev, struct device_driver *drv)
{ {
struct usb_interface *intf; struct usb_interface *intf;
...@@ -1445,6 +1479,7 @@ EXPORT_SYMBOL(usb_driver_claim_interface); ...@@ -1445,6 +1479,7 @@ EXPORT_SYMBOL(usb_driver_claim_interface);
EXPORT_SYMBOL(usb_interface_claimed); EXPORT_SYMBOL(usb_interface_claimed);
EXPORT_SYMBOL(usb_driver_release_interface); EXPORT_SYMBOL(usb_driver_release_interface);
EXPORT_SYMBOL(usb_match_id); EXPORT_SYMBOL(usb_match_id);
EXPORT_SYMBOL(usb_find_interface);
EXPORT_SYMBOL(usb_new_device); EXPORT_SYMBOL(usb_new_device);
EXPORT_SYMBOL(usb_reset_device); EXPORT_SYMBOL(usb_reset_device);
......
...@@ -398,6 +398,7 @@ open_scanner(struct inode * inode, struct file * file) ...@@ -398,6 +398,7 @@ open_scanner(struct inode * inode, struct file * file)
{ {
struct scn_usb_data *scn; struct scn_usb_data *scn;
struct usb_device *dev; struct usb_device *dev;
struct usb_interface *intf;
int scn_minor; int scn_minor;
...@@ -409,13 +410,13 @@ open_scanner(struct inode * inode, struct file * file) ...@@ -409,13 +410,13 @@ open_scanner(struct inode * inode, struct file * file)
dbg("open_scanner: scn_minor:%d", scn_minor); 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); up(&scn_mutex);
err("open_scanner(%d): Unable to access minor data", scn_minor); err("open_scanner(%d): Unable to access minor data", scn_minor);
return -ENODEV; return -ENODEV;
} }
scn = dev_get_drvdata (&intf->dev);
scn = p_scn_table[scn_minor];
dev = scn->scn_dev; dev = scn->scn_dev;
...@@ -458,7 +459,7 @@ open_scanner(struct inode * inode, struct file * file) ...@@ -458,7 +459,7 @@ open_scanner(struct inode * inode, struct file * file)
static int static int
close_scanner(struct inode * inode, struct file * file) close_scanner(struct inode * inode, struct file * file)
{ {
struct scn_usb_data *scn; struct scn_usb_data *scn = file->private_data;
int scn_minor; int scn_minor;
...@@ -466,15 +467,9 @@ close_scanner(struct inode * inode, struct file * file) ...@@ -466,15 +467,9 @@ close_scanner(struct inode * inode, struct file * file)
dbg("close_scanner: scn_minor:%d", scn_minor); 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); down(&scn_mutex);
scn = p_scn_table[scn_minor];
down(&(scn->sem)); down(&(scn->sem));
scn->isopen = 0; scn->isopen = 0;
file->private_data = NULL; file->private_data = NULL;
...@@ -695,17 +690,12 @@ ioctl_scanner(struct inode *inode, struct file *file, ...@@ -695,17 +690,12 @@ ioctl_scanner(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
struct usb_device *dev; struct usb_device *dev;
struct scn_usb_data *scn = file->private_data;
int scn_minor; int scn_minor;
scn_minor = USB_SCN_MINOR(inode); scn_minor = USB_SCN_MINOR(inode);
if (!p_scn_table[scn_minor]) { dev = scn->scn_dev;
err("ioctl_scanner(%d): invalid scn_minor", scn_minor);
return -ENODEV;
}
dev = p_scn_table[scn_minor]->scn_dev;
switch (cmd) switch (cmd)
{ {
...@@ -987,13 +977,6 @@ probe_scanner(struct usb_interface *intf, ...@@ -987,13 +977,6 @@ probe_scanner(struct usb_interface *intf,
return -ENOMEM; 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); dbg("probe_scanner: Allocated minor:%d", scn_minor);
if (!(scn = kmalloc (sizeof (struct scn_usb_data), GFP_KERNEL))) { if (!(scn = kmalloc (sizeof (struct scn_usb_data), GFP_KERNEL))) {
...@@ -1082,17 +1065,19 @@ probe_scanner(struct usb_interface *intf, ...@@ -1082,17 +1065,19 @@ probe_scanner(struct usb_interface *intf,
scn->devfs = devfs_register(usb_devfs_handle, name, scn->devfs = devfs_register(usb_devfs_handle, name,
DEVFS_FL_DEFAULT, USB_MAJOR, DEVFS_FL_DEFAULT, USB_MAJOR,
SCN_BASE_MNR + scn->scn_minor, scn->scn_minor,
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
S_IWGRP | S_IROTH | S_IWOTH, &usb_scanner_fops, NULL); S_IWGRP | S_IROTH | S_IWOTH, &usb_scanner_fops, NULL);
if (scn->devfs == NULL) if (scn->devfs == NULL)
dbg("scanner%d: device node registration failed", scn_minor); dbg("scanner%d: device node registration failed", scn_minor);
p_scn_table[scn_minor] = scn;
up(&scn_mutex); up(&scn_mutex);
dev_set_drvdata(&intf->dev, scn); 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; return 0;
} }
...@@ -1101,6 +1086,9 @@ disconnect_scanner(struct usb_interface *intf) ...@@ -1101,6 +1086,9 @@ disconnect_scanner(struct usb_interface *intf)
{ {
struct scn_usb_data *scn = dev_get_drvdata(&intf->dev); 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); dev_set_drvdata(&intf->dev, NULL);
if (scn) { if (scn) {
down (&scn_mutex); down (&scn_mutex);
...@@ -1119,7 +1107,6 @@ disconnect_scanner(struct usb_interface *intf) ...@@ -1119,7 +1107,6 @@ disconnect_scanner(struct usb_interface *intf)
dbg("disconnect_scanner: De-allocating minor:%d", scn->scn_minor); dbg("disconnect_scanner: De-allocating minor:%d", scn->scn_minor);
devfs_unregister(scn->devfs); devfs_unregister(scn->devfs);
usb_deregister_dev(1, scn->scn_minor); usb_deregister_dev(1, scn->scn_minor);
p_scn_table[scn->scn_minor] = NULL;
usb_free_urb(scn->scn_irq); usb_free_urb(scn->scn_irq);
up (&(scn->sem)); up (&(scn->sem));
kfree (scn); kfree (scn);
......
...@@ -216,7 +216,7 @@ MODULE_DEVICE_TABLE (usb, scanner_device_ids); ...@@ -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_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 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 #ifdef DEBUG
#define SCN_DEBUG(X) X #define SCN_DEBUG(X) X
...@@ -274,6 +274,4 @@ struct scn_usb_data { ...@@ -274,6 +274,4 @@ struct scn_usb_data {
extern devfs_handle_t usb_devfs_handle; 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; static struct usb_driver scanner_driver;
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
/* /*
* Version Information * 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_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver" #define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
...@@ -118,9 +118,14 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size, ...@@ -118,9 +118,14 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
void *data) void *data)
{ {
int ret; int ret;
unsigned char buffer[256]; char *buffer;
DECLARE_WAITQUEUE(wait, current); 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); add_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
while (pegasus->flags & ETH_REGS_CHANGED) while (pegasus->flags & ETH_REGS_CHANGED)
...@@ -153,6 +158,7 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size, ...@@ -153,6 +158,7 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
out: out:
remove_wait_queue(&pegasus->ctrl_wait, &wait); remove_wait_queue(&pegasus->ctrl_wait, &wait);
memcpy(data, buffer, size); memcpy(data, buffer, size);
kfree(buffer);
return ret; return ret;
} }
...@@ -161,9 +167,14 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size, ...@@ -161,9 +167,14 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
void *data) void *data)
{ {
int ret; int ret;
unsigned char buffer[256]; char *buffer;
DECLARE_WAITQUEUE(wait, current); 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); memcpy(buffer, data, size);
add_wait_queue(&pegasus->ctrl_wait, &wait); add_wait_queue(&pegasus->ctrl_wait, &wait);
...@@ -196,6 +207,7 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size, ...@@ -196,6 +207,7 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
schedule(); schedule();
out: out:
remove_wait_queue(&pegasus->ctrl_wait, &wait); remove_wait_queue(&pegasus->ctrl_wait, &wait);
kfree(buffer);
return ret; return ret;
} }
...@@ -203,9 +215,15 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size, ...@@ -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) static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
{ {
int ret; int ret;
__u16 tmp = data; char *tmp;
DECLARE_WAITQUEUE(wait, current); 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); add_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
while (pegasus->flags & ETH_REGS_CHANGED) while (pegasus->flags & ETH_REGS_CHANGED)
...@@ -215,7 +233,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data) ...@@ -215,7 +233,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
pegasus->dr.bRequestType = PEGASUS_REQT_WRITE; pegasus->dr.bRequestType = PEGASUS_REQT_WRITE;
pegasus->dr.bRequest = PEGASUS_REQ_SET_REG; 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.wIndex = cpu_to_le16p(&indx);
pegasus->dr.wLength = cpu_to_le16(1); pegasus->dr.wLength = cpu_to_le16(1);
pegasus->ctrl_urb->transfer_buffer_length = 1; pegasus->ctrl_urb->transfer_buffer_length = 1;
...@@ -223,7 +241,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data) ...@@ -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_fill_control_urb(pegasus->ctrl_urb, pegasus->usb,
usb_sndctrlpipe(pegasus->usb, 0), usb_sndctrlpipe(pegasus->usb, 0),
(char *) &pegasus->dr, (char *) &pegasus->dr,
&data, 1, ctrl_callback, pegasus); &tmp, 1, ctrl_callback, pegasus);
add_wait_queue(&pegasus->ctrl_wait, &wait); add_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
...@@ -236,6 +254,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data) ...@@ -236,6 +254,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
schedule(); schedule();
out: out:
remove_wait_queue(&pegasus->ctrl_wait, &wait); remove_wait_queue(&pegasus->ctrl_wait, &wait);
kfree(tmp);
return ret; return ret;
} }
......
...@@ -33,7 +33,7 @@ obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o ...@@ -33,7 +33,7 @@ obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o
# Objects that export symbols. # Objects that export symbols.
export-objs := usb-serial.o ezusb.o 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 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 @@ ...@@ -14,6 +14,10 @@
* *
* See Documentation/usb/usb-serial.txt for more information on using this driver * 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 * (11/19/2002) gkh
* removed a few #ifdefs for the generic code and cleaned up the failure * removed a few #ifdefs for the generic code and cleaned up the failure
* logic in initialization. * logic in initialization.
...@@ -345,7 +349,7 @@ ...@@ -345,7 +349,7 @@
/* /*
* Version Information * 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_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
#define DRIVER_DESC "USB Serial Driver core" #define DRIVER_DESC "USB Serial Driver core"
...@@ -378,13 +382,13 @@ static struct usb_driver usb_serial_driver = { ...@@ -378,13 +382,13 @@ static struct usb_driver usb_serial_driver = {
*/ */
static int serial_refcount; static int serial_refcount;
static struct tty_driver serial_tty_driver;
static struct tty_struct * serial_tty[SERIAL_TTY_MINORS]; static struct tty_struct * serial_tty[SERIAL_TTY_MINORS];
static struct termios * serial_termios[SERIAL_TTY_MINORS]; static struct termios * serial_termios[SERIAL_TTY_MINORS];
static struct termios * serial_termios_locked[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 struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */
static LIST_HEAD(usb_serial_driver_list); static LIST_HEAD(usb_serial_driver_list);
struct usb_serial *usb_serial_get_by_minor (unsigned int minor) struct usb_serial *usb_serial_get_by_minor (unsigned int minor)
{ {
return serial_table[minor]; return serial_table[minor];
...@@ -1132,11 +1136,17 @@ int usb_serial_probe(struct usb_interface *interface, ...@@ -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 */ /* register all of the individual ports with the driver core */
for (i = 0; i < serial->num_ports; ++i) { for (i = 0; i < num_ports; ++i) {
tty_register_devfs (&serial_tty_driver, 0, serial->port[i].number); port = &serial->port[i];
info("%s converter now attached to ttyUSB%d (or usb/tts/%d for devfs)", port->dev.parent = &serial->dev->dev;
type->name, serial->port[i].number, serial->port[i].number); 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); usb_serial_console_init (debug, minor);
...@@ -1203,6 +1213,9 @@ void usb_serial_disconnect(struct usb_interface *interface) ...@@ -1203,6 +1213,9 @@ void usb_serial_disconnect(struct usb_interface *interface)
serial->dev = NULL; serial->dev = NULL;
serial_shutdown (serial); 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) for (i = 0; i < serial->num_ports; ++i)
serial->port[i].open_count = 0; serial->port[i].open_count = 0;
...@@ -1233,12 +1246,6 @@ void usb_serial_disconnect(struct usb_interface *interface) ...@@ -1233,12 +1246,6 @@ void usb_serial_disconnect(struct usb_interface *interface)
if (port->interrupt_in_buffer) if (port->interrupt_in_buffer)
kfree (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 the minor range that this device had */
return_serial (serial); return_serial (serial);
...@@ -1250,7 +1257,7 @@ void usb_serial_disconnect(struct usb_interface *interface) ...@@ -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, .magic = TTY_DRIVER_MAGIC,
.driver_name = "usb-serial", .driver_name = "usb-serial",
#ifndef CONFIG_DEVFS_FS #ifndef CONFIG_DEVFS_FS
...@@ -1294,6 +1301,8 @@ static int __init usb_serial_init(void) ...@@ -1294,6 +1301,8 @@ static int __init usb_serial_init(void)
serial_table[i] = NULL; serial_table[i] = NULL;
} }
bus_register(&usb_serial_bus_type);
/* register the generic driver, if we should */ /* register the generic driver, if we should */
result = usb_serial_generic_register(debug); result = usb_serial_generic_register(debug);
if (result < 0) { if (result < 0) {
...@@ -1302,9 +1311,9 @@ static int __init usb_serial_init(void) ...@@ -1302,9 +1311,9 @@ static int __init usb_serial_init(void)
} }
/* register the tty driver */ /* register the tty driver */
serial_tty_driver.init_termios = tty_std_termios; usb_serial_tty_driver.init_termios = tty_std_termios;
serial_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; usb_serial_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
result = tty_register_driver (&serial_tty_driver); result = tty_register_driver (&usb_serial_tty_driver);
if (result) { if (result) {
err("%s - tty_register_driver failed", __FUNCTION__); err("%s - tty_register_driver failed", __FUNCTION__);
goto exit_generic; goto exit_generic;
...@@ -1322,7 +1331,7 @@ static int __init usb_serial_init(void) ...@@ -1322,7 +1331,7 @@ static int __init usb_serial_init(void)
return result; return result;
exit_tty: exit_tty:
tty_unregister_driver(&serial_tty_driver); tty_unregister_driver(&usb_serial_tty_driver);
exit_generic: exit_generic:
usb_serial_generic_deregister(); usb_serial_generic_deregister();
...@@ -1340,7 +1349,8 @@ static void __exit usb_serial_exit(void) ...@@ -1340,7 +1349,8 @@ static void __exit usb_serial_exit(void)
usb_serial_generic_deregister(); usb_serial_generic_deregister();
usb_deregister(&usb_serial_driver); 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); ...@@ -1350,12 +1360,24 @@ module_exit(usb_serial_exit);
int usb_serial_register(struct usb_serial_device_type *new_device) int usb_serial_register(struct usb_serial_device_type *new_device)
{ {
int retval;
/* Add this device to our list of devices */ /* Add this device to our list of devices */
list_add(&new_device->driver_list, &usb_serial_driver_list); 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) ...@@ -1376,6 +1398,7 @@ void usb_serial_deregister(struct usb_serial_device_type *device)
} }
list_del(&device->driver_list); list_del(&device->driver_list);
usb_serial_bus_deregister (device);
} }
......
...@@ -121,7 +121,9 @@ struct usb_serial_port { ...@@ -121,7 +121,9 @@ struct usb_serial_port {
int open_count; int open_count;
struct semaphore sem; struct semaphore sem;
void * private; 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 * usb_serial - structure used by the usb-serial core for a device
...@@ -206,13 +208,17 @@ struct usb_serial_device_type { ...@@ -206,13 +208,17 @@ struct usb_serial_device_type {
char num_ports; char num_ports;
struct list_head driver_list; struct list_head driver_list;
struct device_driver driver;
int (*probe) (struct usb_serial *serial); int (*probe) (struct usb_serial *serial);
int (*attach) (struct usb_serial *serial); int (*attach) (struct usb_serial *serial);
int (*calc_num_ports) (struct usb_serial *serial); int (*calc_num_ports) (struct usb_serial *serial);
void (*shutdown) (struct usb_serial *serial); 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 */ /* serial function calls */
int (*open) (struct usb_serial_port *port, struct file * filp); int (*open) (struct usb_serial_port *port, struct file * filp);
void (*close) (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 { ...@@ -229,6 +235,7 @@ struct usb_serial_device_type {
void (*read_bulk_callback)(struct urb *urb, struct pt_regs *regs); void (*read_bulk_callback)(struct urb *urb, struct pt_regs *regs);
void (*write_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 int usb_serial_register(struct usb_serial_device_type *new_device);
extern void usb_serial_deregister(struct usb_serial_device_type *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); ...@@ -262,7 +269,12 @@ extern void usb_serial_generic_shutdown (struct usb_serial *serial);
extern int usb_serial_generic_register (int debug); extern int usb_serial_generic_register (int debug);
extern void usb_serial_generic_deregister (void); 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 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 */ /* 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) static inline int serial_paranoia_check (struct usb_serial *serial, const char *function)
......
...@@ -214,9 +214,9 @@ UNUSUAL_DEV( 0x0525, 0xa140, 0x0100, 0x0100, ...@@ -214,9 +214,9 @@ UNUSUAL_DEV( 0x0525, 0xa140, 0x0100, 0x0100,
US_FL_FIX_INQUIRY | US_FL_START_STOP ), US_FL_FIX_INQUIRY | US_FL_START_STOP ),
/* This entry is needed because the device reports Sub=ff */ /* This entry is needed because the device reports Sub=ff */
UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0422, UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0440,
"Sony", "Sony",
"DSC-S30/S70/S75/505V/F505/F707", "DSC-S30/S70/S75/505V/F505/F707/F717",
US_SC_SCSI, US_PR_CB, NULL, US_SC_SCSI, US_PR_CB, NULL,
US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE ), US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE ),
...@@ -503,6 +503,18 @@ UNUSUAL_DEV( 0x07c4, 0xa103, 0x0000, 0x9999, ...@@ -503,6 +503,18 @@ UNUSUAL_DEV( 0x07c4, 0xa103, 0x0000, 0x9999,
US_FL_FIX_INQUIRY ), US_FL_FIX_INQUIRY ),
#endif #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 /* Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant
* to the USB storage specification in two ways: * to the USB storage specification in two ways:
* - They tell us they are using transport protocol CBI. In reality they * - They tell us they are using transport protocol CBI. In reality they
......
This diff is collapsed.
...@@ -117,6 +117,7 @@ struct usb_interface { ...@@ -117,6 +117,7 @@ struct usb_interface {
unsigned max_altsetting; /* total memory allocated */ unsigned max_altsetting; /* total memory allocated */
struct usb_driver *driver; /* driver */ struct usb_driver *driver; /* driver */
kdev_t kdev; /* node this interface is bound to */
struct device dev; /* interface specific device info */ struct device dev; /* interface specific device info */
void *private_data; void *private_data;
}; };
...@@ -271,6 +272,8 @@ extern void usb_driver_release_interface(struct usb_driver *driver, ...@@ -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 *usb_match_id(struct usb_interface *interface,
const struct usb_device_id *id); 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 * usb_make_path - returns stable device path in the usb tree
* @dev: the device whose path is being constructed * @dev: the device whose path is being constructed
......
...@@ -526,7 +526,7 @@ static struct snd_urb_ops audio_urb_ops[2] = { ...@@ -526,7 +526,7 @@ static struct snd_urb_ops audio_urb_ops[2] = {
/* /*
* complete callback from data urb * 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_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
snd_usb_substream_t *subs = ctx->subs; snd_usb_substream_t *subs = ctx->subs;
...@@ -551,7 +551,7 @@ static void snd_complete_urb(struct urb *urb) ...@@ -551,7 +551,7 @@ static void snd_complete_urb(struct urb *urb)
/* /*
* complete callback from sync 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_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
snd_usb_substream_t *subs = ctx->subs; 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