X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fusb%2Fserial%2Fusb-serial.c;h=03e8a7e1c8eef2bda3d1266503d2e7eb18016df0;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=609c1d164c12fdb0651f4773c71e7db1f2c816af;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 609c1d164..03e8a7e1c 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1,7 +1,7 @@ /* * USB Serial Converter driver * - * Copyright (C) 1999 - 2003 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 1999 - 2004 Greg Kroah-Hartman (greg@kroah.com) * Copyright (C) 2000 Peter Berger (pberger@brimson.com) * Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com) * @@ -330,19 +330,12 @@ #include #include #include +#include #include #include #include #include #include - - -#ifdef CONFIG_USB_SERIAL_DEBUG - static int debug = 1; -#else - static int debug; -#endif - #include "usb-serial.h" #include "pl2303.h" @@ -353,26 +346,12 @@ #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/" #define DRIVER_DESC "USB Serial Driver core" - -#ifdef CONFIG_USB_SERIAL_GENERIC -/* we want to look at all devices, as the vendor/product id can change - * depending on the command line argument */ -static struct usb_device_id generic_serial_ids[] = { - {.driver_info = 42}, - {} -}; - -#endif /* CONFIG_USB_SERIAL_GENERIC */ - /* Driver structure we register with the USB core */ static struct usb_driver usb_serial_driver = { .owner = THIS_MODULE, .name = "usbserial", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, -#ifdef CONFIG_USB_SERIAL_GENERIC - .id_table = generic_serial_ids, -#endif }; /* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead @@ -382,10 +361,10 @@ static struct usb_driver usb_serial_driver = { drivers depend on it. */ -static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */ +static int debug; +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_index(unsigned index) { struct usb_serial *serial = serial_table[index]; @@ -416,8 +395,7 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po } if (good_spot == 0) continue; - - serial->magic = USB_SERIAL_MAGIC; + *minor = i; dbg("%s - minor base = %d", __FUNCTION__, *minor); for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) @@ -443,6 +421,63 @@ static void return_serial (struct usb_serial *serial) return; } +static void destroy_serial(struct kref *kref) +{ + struct usb_serial *serial; + struct usb_serial_port *port; + int i; + + serial = to_usb_serial(kref); + + dbg ("%s - %s", __FUNCTION__, serial->type->name); + + serial->type->shutdown(serial); + + /* return the minor range that this device had */ + return_serial(serial); + + for (i = 0; i < serial->num_ports; ++i) + serial->port[i]->open_count = 0; + + /* the ports are cleaned up and released in port_release() */ + for (i = 0; i < serial->num_ports; ++i) + if (serial->port[i]->dev.parent != NULL) { + device_unregister(&serial->port[i]->dev); + serial->port[i] = NULL; + } + + /* If this is a "fake" port, we have to clean it up here, as it will + * not get cleaned up in port_release() as it was never registered with + * the driver core */ + if (serial->num_ports < serial->num_port_pointers) { + for (i = serial->num_ports; i < serial->num_port_pointers; ++i) { + port = serial->port[i]; + if (!port) + continue; + if (port->read_urb) { + usb_unlink_urb(port->read_urb); + usb_free_urb(port->read_urb); + } + if (port->write_urb) { + usb_unlink_urb(port->write_urb); + usb_free_urb(port->write_urb); + } + if (port->interrupt_in_urb) { + usb_unlink_urb(port->interrupt_in_urb); + usb_free_urb(port->interrupt_in_urb); + } + kfree(port->bulk_in_buffer); + kfree(port->bulk_out_buffer); + kfree(port->interrupt_in_buffer); + } + } + + usb_put_dev(serial->dev); + + /* free up any memory that we allocated */ + kfree (serial); +} + /***************************************************************************** * Driver tty interface functions *****************************************************************************/ @@ -460,9 +495,10 @@ static int serial_open (struct tty_struct *tty, struct file * filp) /* get the serial object associated with this tty pointer */ serial = usb_serial_get_by_index(tty->index); - - if (serial_paranoia_check (serial, __FUNCTION__)) - return -ENODEV; + if (!serial) { + retval = -ENODEV; + goto bailout; + } /* set up our port structure making the tty driver remember our port object, and us it */ portNumber = tty->index - serial->minor; @@ -486,7 +522,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp) if (retval) { port->open_count = 0; module_put(serial->type->owner); - kref_put(&serial->kref); + kref_put(&serial->kref, destroy_serial); } } bailout: @@ -496,9 +532,8 @@ bailout: static void serial_close(struct tty_struct *tty, struct file * filp) { struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); - if (!serial) + if (!port) return; dbg("%s - port %d", __FUNCTION__, port->number); @@ -518,18 +553,14 @@ static void serial_close(struct tty_struct *tty, struct file * filp) } module_put(port->serial->type->owner); - kref_put(&port->serial->kref); + kref_put(&port->serial->kref, destroy_serial); } static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count) { struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); int retval = -EINVAL; - if (!serial) - return -ENODEV; - dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count); if (!port->open_count) { @@ -538,7 +569,7 @@ static int serial_write (struct tty_struct * tty, int from_user, const unsigned } /* pass on to the driver specific version of this function */ - retval = serial->type->write(port, from_user, buf, count); + retval = port->serial->type->write(port, from_user, buf, count); exit: return retval; @@ -547,12 +578,8 @@ exit: static int serial_write_room (struct tty_struct *tty) { struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); int retval = -EINVAL; - if (!serial) - return -ENODEV; - dbg("%s - port %d", __FUNCTION__, port->number); if (!port->open_count) { @@ -561,7 +588,7 @@ static int serial_write_room (struct tty_struct *tty) } /* pass on to the driver specific version of this function */ - retval = serial->type->write_room(port); + retval = port->serial->type->write_room(port); exit: return retval; @@ -570,12 +597,8 @@ exit: static int serial_chars_in_buffer (struct tty_struct *tty) { struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); int retval = -EINVAL; - if (!serial) - return -ENODEV; - dbg("%s = port %d", __FUNCTION__, port->number); if (!port->open_count) { @@ -584,7 +607,7 @@ static int serial_chars_in_buffer (struct tty_struct *tty) } /* pass on to the driver specific version of this function */ - retval = serial->type->chars_in_buffer(port); + retval = port->serial->type->chars_in_buffer(port); exit: return retval; @@ -593,10 +616,6 @@ exit: static void serial_throttle (struct tty_struct * tty) { struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); - - if (!serial) - return; dbg("%s - port %d", __FUNCTION__, port->number); @@ -606,8 +625,8 @@ static void serial_throttle (struct tty_struct * tty) } /* pass on to the driver specific version of this function */ - if (serial->type->throttle) - serial->type->throttle(port); + if (port->serial->type->throttle) + port->serial->type->throttle(port); exit: ; @@ -616,10 +635,6 @@ exit: static void serial_unthrottle (struct tty_struct * tty) { struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); - - if (!serial) - return; dbg("%s - port %d", __FUNCTION__, port->number); @@ -629,8 +644,8 @@ static void serial_unthrottle (struct tty_struct * tty) } /* pass on to the driver specific version of this function */ - if (serial->type->unthrottle) - serial->type->unthrottle(port); + if (port->serial->type->unthrottle) + port->serial->type->unthrottle(port); exit: ; @@ -639,12 +654,8 @@ exit: static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); int retval = -ENODEV; - if (!serial) - return -ENODEV; - dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd); if (!port->open_count) { @@ -653,8 +664,8 @@ static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned in } /* pass on to the driver specific version of this function if it is available */ - if (serial->type->ioctl) - retval = serial->type->ioctl(port, file, cmd, arg); + if (port->serial->type->ioctl) + retval = port->serial->type->ioctl(port, file, cmd, arg); else retval = -ENOIOCTLCMD; @@ -665,10 +676,6 @@ exit: static void serial_set_termios (struct tty_struct *tty, struct termios * old) { struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); - - if (!serial) - return; dbg("%s - port %d", __FUNCTION__, port->number); @@ -678,8 +685,8 @@ static void serial_set_termios (struct tty_struct *tty, struct termios * old) } /* pass on to the driver specific version of this function if it is available */ - if (serial->type->set_termios) - serial->type->set_termios(port, old); + if (port->serial->type->set_termios) + port->serial->type->set_termios(port, old); exit: ; @@ -688,10 +695,6 @@ exit: static void serial_break (struct tty_struct *tty, int break_state) { struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); - - if (!serial) - return; dbg("%s - port %d", __FUNCTION__, port->number); @@ -701,20 +704,13 @@ static void serial_break (struct tty_struct *tty, int break_state) } /* pass on to the driver specific version of this function if it is available */ - if (serial->type->break_ctl) - serial->type->break_ctl(port, break_state); + if (port->serial->type->break_ctl) + port->serial->type->break_ctl(port, break_state); exit: ; } -static void serial_shutdown (struct usb_serial *serial) -{ - dbg ("%s", __FUNCTION__); - - serial->type->shutdown(serial); -} - static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { struct usb_serial *serial; @@ -748,7 +744,7 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int begin += length; length = 0; } - kref_put(&serial->kref); + kref_put(&serial->kref, destroy_serial); } *eof = 1; done: @@ -761,10 +757,6 @@ done: static int serial_tiocmget (struct tty_struct *tty, struct file *file) { struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); - - if (!serial) - goto exit; dbg("%s - port %d", __FUNCTION__, port->number); @@ -773,8 +765,8 @@ static int serial_tiocmget (struct tty_struct *tty, struct file *file) goto exit; } - if (serial->type->tiocmget) - return serial->type->tiocmget(port, file); + if (port->serial->type->tiocmget) + return port->serial->type->tiocmget(port, file); exit: return -EINVAL; @@ -784,10 +776,6 @@ static int serial_tiocmset (struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); - - if (!serial) - goto exit; dbg("%s - port %d", __FUNCTION__, port->number); @@ -796,8 +784,8 @@ static int serial_tiocmset (struct tty_struct *tty, struct file *file, goto exit; } - if (serial->type->tiocmset) - return serial->type->tiocmset(port, file, set, clear); + if (port->serial->type->tiocmset) + return port->serial->type->tiocmset(port, file, set, clear); exit: return -EINVAL; @@ -806,7 +794,6 @@ exit: void usb_serial_port_softint(void *private) { struct usb_serial_port *port = (struct usb_serial_port *)private; - struct usb_serial *serial; struct tty_struct *tty; dbg("%s - port %d", __FUNCTION__, port->number); @@ -814,76 +801,11 @@ void usb_serial_port_softint(void *private) if (!port) return; - serial = get_usb_serial (port, __FUNCTION__); - if (!serial) - return; - tty = port->tty; if (!tty) return; - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) { - dbg("%s - write wakeup call.", __FUNCTION__); - (tty->ldisc.write_wakeup)(tty); - } - - wake_up_interruptible(&tty->write_wait); -} - -static void destroy_serial(struct kref *kref) -{ - struct usb_serial *serial; - struct usb_serial_port *port; - int i; - - serial = to_usb_serial(kref); - - dbg ("%s - %s", __FUNCTION__, serial->type->name); - serial_shutdown (serial); - - /* return the minor range that this device had */ - return_serial(serial); - - for (i = 0; i < serial->num_ports; ++i) - serial->port[i]->open_count = 0; - - /* the ports are cleaned up and released in port_release() */ - for (i = 0; i < serial->num_ports; ++i) - if (serial->port[i]->dev.parent != NULL) { - device_unregister(&serial->port[i]->dev); - serial->port[i] = NULL; - } - - /* If this is a "fake" port, we have to clean it up here, as it will - * not get cleaned up in port_release() as it was never registered with - * the driver core */ - if (serial->num_ports < serial->num_port_pointers) { - for (i = serial->num_ports; i < serial->num_port_pointers; ++i) { - port = serial->port[i]; - if (!port) - continue; - if (port->read_urb) { - usb_unlink_urb(port->read_urb); - usb_free_urb(port->read_urb); - } - if (port->write_urb) { - usb_unlink_urb(port->write_urb); - usb_free_urb(port->write_urb); - } - if (port->interrupt_in_urb) { - usb_unlink_urb(port->interrupt_in_urb); - usb_free_urb(port->interrupt_in_urb); - } - kfree(port->bulk_in_buffer); - kfree(port->bulk_out_buffer); - kfree(port->interrupt_in_buffer); - } - } - - usb_put_dev(serial->dev); - - /* free up any memory that we allocated */ - kfree (serial); + tty_wakeup(tty); } static void port_release(struct device *dev) @@ -926,7 +848,7 @@ static struct usb_serial * create_serial (struct usb_device *dev, serial->interface = interface; serial->vendor = dev->descriptor.idVendor; serial->product = dev->descriptor.idProduct; - kref_init(&serial->kref, destroy_serial); + kref_init(&serial->kref); return serial; } @@ -1037,7 +959,7 @@ int usb_serial_probe(struct usb_interface *interface, (dev->descriptor.idProduct == ATEN_PRODUCT_ID))) { if (interface != dev->actconfig->interface[0]) { /* check out the endpoints of the other interface*/ - iface_desc = &dev->actconfig->interface[0]->altsetting[0]; + iface_desc = dev->actconfig->interface[0]->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; if ((endpoint->bEndpointAddress & 0x80) && @@ -1117,7 +1039,6 @@ int usb_serial_probe(struct usb_interface *interface, memset(port, 0x00, sizeof(struct usb_serial_port)); port->number = i + serial->minor; port->serial = serial; - port->magic = USB_SERIAL_PORT_MAGIC; INIT_WORK(&port->work, usb_serial_port_softint, port); serial->port[i] = port; } @@ -1277,7 +1198,7 @@ void usb_serial_disconnect(struct usb_interface *interface) if (serial) { /* let the last holder of this object * cause it to be cleaned up */ - kref_put(&serial->kref); + kref_put(&serial->kref, destroy_serial); } dev_info(dev, "device disconnected\n"); } @@ -1429,22 +1350,9 @@ error: void usb_serial_deregister(struct usb_serial_device_type *device) { - struct usb_serial *serial; - int i; - info("USB Serial deregistering driver %s", device->name); - - /* clear out the serial_table if the device is attached to a port */ - for(i = 0; i < SERIAL_TTY_MINORS; ++i) { - serial = serial_table[i]; - if ((serial != NULL) && (serial->type == device)) { - usb_driver_release_interface (&usb_serial_driver, serial->interface); - usb_serial_disconnect (serial->interface); - } - } - list_del(&device->driver_list); - usb_serial_bus_deregister (device); + usb_serial_bus_deregister(device); } @@ -1463,5 +1371,5 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); MODULE_LICENSE("GPL"); -MODULE_PARM(debug, "i"); +module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug enabled or not");