diff options
Diffstat (limited to 'drivers/usb/serial/usbserial.c')
-rw-r--r-- | drivers/usb/serial/usbserial.c | 309 |
1 files changed, 115 insertions, 194 deletions
diff --git a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c index 588fed5d1..9fe65ae8d 100644 --- a/drivers/usb/serial/usbserial.c +++ b/drivers/usb/serial/usbserial.c @@ -1,7 +1,7 @@ /* * USB Serial Converter driver * - * (C) Copyright (C) 1999, 2000 + * Copyright (C) 1999, 2000 * Greg Kroah-Hartman (greg@kroah.com) * * This program is free software; you can redistribute it and/or modify @@ -14,6 +14,16 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (05/03/2000) gkh + * Added the Digi Acceleport driver from Al Borchers and Peter Berger. + * + * (05/02/2000) gkh + * Changed devfs and tty register code to work properly now. This was based on + * the ACM driver changes by Vojtech Pavlik. + * + * (04/27/2000) Ryan VanderBijl + * Put calls to *_paranoia_checks into one function. + * * (04/23/2000) gkh * Fixed bug that Randy Dunlap found for Generic devices with no bulk out ports. * Moved when the startup code printed out the devices that are supported. @@ -282,15 +292,13 @@ static struct usb_serial_device_type *usb_serial_devices[] = { #ifdef CONFIG_USB_SERIAL_OMNINET &zyxel_omninet_device, #endif +#ifdef CONFIG_USB_SERIAL_DIGI_ACCELEPORT + &digi_acceleport_device, +#endif NULL }; -/* variables needed for the tty_driver structure */ -static char *driver_name = "usb"; -static char *tty_driver_name = "usb/tty/%d"; - - /* local function prototypes */ static int serial_open (struct tty_struct *tty, struct file * filp); static void serial_close (struct tty_struct *tty, struct file * filp); @@ -312,12 +320,27 @@ 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] = {NULL, }; +static inline struct usb_serial* get_usb_serial (struct usb_serial_port *port, const char *function) +{ + /* if no port was specified, or it fails a paranoia check */ + if (!port || + port_paranoia_check (port, function) || + serial_paranoia_check (port->serial, function)) { + /* then say that we dont have a valid usb_serial thing, which will + * end up genrating -ENODEV return values */ + return NULL; + } + + return port->serial; +} + static struct usb_serial *get_serial_by_minor (int minor) { @@ -357,7 +380,7 @@ static struct usb_serial *get_free_serial (int num_ports, int *minor) for (i = *minor+1; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) serial_table[i] = serial; return serial; - } + } return NULL; } @@ -454,16 +477,9 @@ static int serial_open (struct tty_struct *tty, struct file * filp) 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; + struct usb_serial *serial = get_usb_serial (port, "serial_close"); - dbg("serial_close"); - - if (port_paranoia_check (port, "serial_close")) { - return; - } - - serial = port->serial; - if (serial_paranoia_check (serial, "serial_close")) { + if (!serial) { return; } @@ -486,16 +502,9 @@ static void serial_close(struct tty_struct *tty, struct file * filp) 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; - - dbg("serial_write"); + struct usb_serial *serial = get_usb_serial (port, "serial_write"); - if (port_paranoia_check (port, "serial_write")) { - return -ENODEV; - } - - serial = port->serial; - if (serial_paranoia_check (serial, "serial_write")) { + if (!serial) { return -ENODEV; } @@ -518,26 +527,19 @@ static int serial_write (struct tty_struct * tty, int from_user, const unsigned 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; - - dbg("serial_write_room"); - - if (port_paranoia_check (port, "serial_write")) { - return -ENODEV; - } - - serial = port->serial; - if (serial_paranoia_check (serial, "serial_write")) { + struct usb_serial *serial = get_usb_serial (port, "serial_write_room"); + + if (!serial) { return -ENODEV; } - + dbg("serial_write_room port %d", port->number); if (!port->active) { dbg ("port not open"); return -EINVAL; } - + /* pass on to the driver specific version of this function if it is available */ if (serial->type->write_room) { return (serial->type->write_room(port)); @@ -550,24 +552,17 @@ static int serial_write_room (struct tty_struct *tty) 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; - - dbg("serial_chars_in_buffer"); - - if (port_paranoia_check (port, "serial_chars_in_buffer")) { - return -ENODEV; - } - - serial = port->serial; - if (serial_paranoia_check (serial, "serial_chars_in_buffer")) { + struct usb_serial *serial = get_usb_serial (port, "serial_chars_in_buffer"); + + if (!serial) { return -ENODEV; } - + if (!port->active) { dbg ("port not open"); return -EINVAL; } - + /* pass on to the driver specific version of this function if it is available */ if (serial->type->chars_in_buffer) { return (serial->type->chars_in_buffer(port)); @@ -580,21 +575,14 @@ static int serial_chars_in_buffer (struct tty_struct *tty) static void serial_throttle (struct tty_struct * tty) { struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial; - - dbg("serial_throttle"); - - if (port_paranoia_check (port, "serial_throttle")) { - return; - } - - serial = port->serial; - if (serial_paranoia_check (serial, "serial_throttle")) { + struct usb_serial *serial = get_usb_serial (port, "serial_throttle"); + + if (!serial) { return; } - + dbg("serial_throttle port %d", port->number); - + if (!port->active) { dbg ("port not open"); return; @@ -612,21 +600,14 @@ static void serial_throttle (struct tty_struct * tty) static void serial_unthrottle (struct tty_struct * tty) { struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial; - - dbg("serial_unthrottle"); - - if (port_paranoia_check (port, "serial_unthrottle")) { - return; - } - - serial = port->serial; - if (serial_paranoia_check (serial, "serial_unthrottle")) { + struct usb_serial *serial = get_usb_serial (port, "serial_unthrottle"); + + if (!serial) { return; } - + dbg("serial_unthrottle port %d", port->number); - + if (!port->active) { dbg ("port not open"); return; @@ -644,21 +625,14 @@ static void serial_unthrottle (struct tty_struct * tty) 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; - - dbg("serial_ioctl"); - - if (port_paranoia_check (port, "serial_ioctl")) { - return -ENODEV; - } + struct usb_serial *serial = get_usb_serial (port, "serial_ioctl"); - serial = port->serial; - if (serial_paranoia_check (serial, "serial_ioctl")) { + if (!serial) { return -ENODEV; } - + dbg("serial_ioctl port %d", port->number); - + if (!port->active) { dbg ("port not open"); return -ENODEV; @@ -676,16 +650,9 @@ static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned in 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; - - dbg("serial_set_termios"); - - if (port_paranoia_check (port, "serial_set_termios")) { - return; - } + struct usb_serial *serial = get_usb_serial (port, "serial_set_termios"); - serial = port->serial; - if (serial_paranoia_check (serial, "serial_set_termios")) { + if (!serial) { return; } @@ -708,16 +675,9 @@ static void serial_set_termios (struct tty_struct *tty, struct termios * old) 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; - - dbg("serial_break"); - - if (port_paranoia_check (port, "serial_break")) { - return; - } + struct usb_serial *serial = get_usb_serial (port, "serial_break"); - serial = port->serial; - if (serial_paranoia_check (serial, "serial_break")) { + if (!serial) { return; } @@ -861,22 +821,15 @@ static int generic_chars_in_buffer (struct usb_serial_port *port) static void generic_read_bulk_callback (struct urb *urb) { struct usb_serial_port *port = (struct usb_serial_port *)urb->context; - struct usb_serial *serial; - struct tty_struct *tty; - unsigned char *data = urb->transfer_buffer; + struct usb_serial *serial = get_usb_serial (port, "generic_read_bulk_callback"); + struct tty_struct *tty; + unsigned char *data = urb->transfer_buffer; int i; - dbg("generic_read_bulk_callback"); - - if (port_paranoia_check (port, "generic_read_bulk_callback")) { + if (!serial) { return; } - serial = port->serial; - if (serial_paranoia_check (serial, "generic_read_bulk_callback")) { - return; - } - if (urb->status) { dbg("nonzero read bulk status received: %d", urb->status); return; @@ -911,20 +864,13 @@ static void generic_read_bulk_callback (struct urb *urb) static void generic_write_bulk_callback (struct urb *urb) { struct usb_serial_port *port = (struct usb_serial_port *)urb->context; - struct usb_serial *serial; - struct tty_struct *tty; - - dbg("generic_write_bulk_callback"); + struct usb_serial *serial = get_usb_serial (port, "generic_write_bulk_callback"); + struct tty_struct *tty; - if (port_paranoia_check (port, "generic_write_bulk_callback")) { + if (!serial) { return; } - serial = port->serial; - if (serial_paranoia_check (serial, "generic_write_bulk_callback")) { - return; - } - if (urb->status) { dbg("nonzero write bulk status received: %d", urb->status); return; @@ -940,48 +886,6 @@ static void generic_write_bulk_callback (struct urb *urb) } -static struct tty_driver * usb_serial_tty_driver_init (struct usb_serial *serial) -{ - struct tty_driver *serial_tty_driver; - - if (!(serial_tty_driver = kmalloc(sizeof(struct tty_driver), GFP_KERNEL))) { - err("Out of memory"); - return NULL; - } - - memset (serial_tty_driver, 0x00, sizeof(struct tty_driver)); - - /* initialize the entries that we don't want to be NULL */ - serial_tty_driver->magic = TTY_DRIVER_MAGIC; - serial_tty_driver->driver_name = driver_name; - serial_tty_driver->name = tty_driver_name; - serial_tty_driver->major = SERIAL_TTY_MAJOR; - serial_tty_driver->minor_start = serial->minor; - serial_tty_driver->num = serial->num_ports; - serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; - serial_tty_driver->subtype = SERIAL_TYPE_NORMAL; - serial_tty_driver->flags = TTY_DRIVER_REAL_RAW; - serial_tty_driver->refcount = &serial_refcount; - serial_tty_driver->table = serial_tty; - serial_tty_driver->termios = serial_termios; - serial_tty_driver->termios_locked = serial_termios_locked; - serial_tty_driver->open = serial_open; - serial_tty_driver->close = serial_close; - serial_tty_driver->write = serial_write; - serial_tty_driver->write_room = serial_write_room; - serial_tty_driver->ioctl = serial_ioctl; - serial_tty_driver->set_termios = serial_set_termios; - serial_tty_driver->throttle = serial_throttle; - serial_tty_driver->unthrottle = serial_unthrottle; - serial_tty_driver->break_ctl = serial_break; - serial_tty_driver->chars_in_buffer = serial_chars_in_buffer; - serial_tty_driver->init_termios = tty_std_termios; - serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - - return serial_tty_driver; -} - - static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum) { struct usb_serial *serial = NULL; @@ -1101,18 +1005,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum) serial->num_bulk_out = num_bulk_out; serial->num_interrupt_in = num_interrupt_in; - /* initialize a tty_driver for this device */ - serial->tty_driver = usb_serial_tty_driver_init (serial); - if (serial->tty_driver == NULL) { - err("Can't create a tty_serial_driver"); - goto probe_error; - } - - if (tty_register_driver (serial->tty_driver)) { - err("failed to register tty driver"); - goto probe_error; - } - /* if this device type has a startup function, call it */ if (type->startup) { if (type->startup (serial)) { @@ -1196,14 +1088,16 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum) max_endpoints = MAX(max_endpoints, num_interrupt_in); for (i = 0; i < max_endpoints; ++i) { port = &serial->port[i]; - port->number = i; + port->number = i + serial->minor; port->serial = serial; port->magic = USB_SERIAL_PORT_MAGIC; } + /* 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) { - info("%s converter now attached to ttyUSB%d", - type->name, serial->minor + 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); } return serial; /* success */ @@ -1235,13 +1129,6 @@ probe_error: /* return the minor range that this device had */ return_serial (serial); - /* if this device has a tty_driver, then unregister it and free it */ - if (serial->tty_driver) { - tty_unregister_driver (serial->tty_driver); - kfree (serial->tty_driver); - serial->tty_driver = NULL; - } - /* free up any memory that we allocated */ kfree (serial); MOD_DEC_USE_COUNT; @@ -1291,18 +1178,13 @@ static void usb_serial_disconnect(struct usb_device *dev, void *ptr) } for (i = 0; i < serial->num_ports; ++i) { - info("%s converter now disconnected from ttyUSB%d", serial->type->name, serial->minor + 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); - /* if this device has a tty_driver, then unregister it and free it */ - if (serial->tty_driver) { - tty_unregister_driver (serial->tty_driver); - kfree (serial->tty_driver); - serial->tty_driver = NULL; - } /* free up any memory that we allocated */ kfree (serial); @@ -1314,6 +1196,35 @@ static void usb_serial_disconnect(struct usb_device *dev, void *ptr) } +static struct tty_driver serial_tty_driver = { + magic: TTY_DRIVER_MAGIC, + driver_name: "usb-serial", + name: "usb/tts/%d", + major: SERIAL_TTY_MAJOR, + minor_start: 0, + num: SERIAL_TTY_MINORS, + type: TTY_DRIVER_TYPE_SERIAL, + subtype: SERIAL_TYPE_NORMAL, + flags: TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS, + + refcount: &serial_refcount, + table: serial_tty, + termios: serial_termios, + termios_locked: serial_termios_locked, + + open: serial_open, + close: serial_close, + write: serial_write, + write_room: serial_write_room, + ioctl: serial_ioctl, + set_termios: serial_set_termios, + throttle: serial_throttle, + unthrottle: serial_unthrottle, + break_ctl: serial_break, + chars_in_buffer: serial_chars_in_buffer, +}; + + int usb_serial_init(void) { int i; @@ -1336,9 +1247,18 @@ int usb_serial_init(void) if (!something) info ("USB Serial driver is not configured for any devices!"); + /* register the tty driver */ + serial_tty_driver.init_termios = tty_std_termios; + serial_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + if (tty_register_driver (&serial_tty_driver)) { + err("failed to register tty driver"); + return -1; + } + /* register the USB driver */ result = usb_register(&usb_serial_driver); if (result < 0) { + tty_unregister_driver(&serial_tty_driver); err("usb_register failed for the usb-serial driver. Error number %d", result); return -1; } @@ -1350,6 +1270,7 @@ int usb_serial_init(void) void usb_serial_exit(void) { usb_deregister(&usb_serial_driver); + tty_unregister_driver(&serial_tty_driver); } |