*
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
-#include <linux/usb/serial.h>
+#include "usb-serial.h"
#include "pl2303.h"
/*
#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
#define DRIVER_DESC "USB Serial Driver core"
-static void port_free(struct usb_serial_port *port);
-
/* Driver structure we register with the USB core */
static struct usb_driver usb_serial_driver = {
.name = "usbserial",
port = serial->port[i];
if (!port)
continue;
- port_free(port);
+ usb_kill_urb(port->read_urb);
+ usb_free_urb(port->read_urb);
+ usb_kill_urb(port->write_urb);
+ usb_free_urb(port->write_urb);
+ usb_kill_urb(port->interrupt_in_urb);
+ usb_free_urb(port->interrupt_in_urb);
+ usb_kill_urb(port->interrupt_out_urb);
+ usb_free_urb(port->interrupt_out_urb);
+ kfree(port->bulk_in_buffer);
+ kfree(port->bulk_out_buffer);
+ kfree(port->interrupt_in_buffer);
+ kfree(port->interrupt_out_buffer);
}
}
kfree (serial);
}
-void usb_serial_put(struct usb_serial *serial)
-{
- kref_put(&serial->kref, destroy_serial);
-}
-
/*****************************************************************************
* Driver tty interface functions
*****************************************************************************/
++port->open_count;
- /* set up our port structure making the tty driver
- * remember our port object, and us it */
- tty->driver_data = port;
- port->tty = tty;
-
if (port->open_count == 1) {
+ /* set up our port structure making the tty driver
+ * remember our port object, and us it */
+ tty->driver_data = port;
+ port->tty = tty;
+
/* lock this module before we call it
* this may fail, which means we must bail out,
* safe because we are called with BKL held */
module_put(serial->type->driver.owner);
bailout_mutex_unlock:
port->open_count = 0;
- tty->driver_data = NULL;
- port->tty = NULL;
mutex_unlock(&port->mutex);
bailout_kref_put:
- usb_serial_put(serial);
+ kref_put(&serial->kref, destroy_serial);
return retval;
}
}
mutex_unlock(&port->mutex);
- usb_serial_put(port->serial);
+ kref_put(&port->serial->kref, destroy_serial);
}
static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count)
struct usb_serial_port *port = tty->driver_data;
int retval = -EINVAL;
- if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED)
+ if (!port)
goto exit;
dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
static int serial_write_room (struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- int retval = -ENODEV;
+ int retval = -EINVAL;
if (!port)
goto exit;
static int serial_chars_in_buffer (struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- int retval = -ENODEV;
+ int retval = -EINVAL;
if (!port)
goto exit;
length += sprintf (page+length, " path:%s", tmp);
length += sprintf (page+length, "\n");
- if ((length + begin) > (off + count)) {
- usb_serial_put(serial);
+ if ((length + begin) > (off + count))
goto done;
- }
if ((length + begin) < off) {
begin += length;
length = 0;
}
- usb_serial_put(serial);
+ kref_put(&serial->kref, destroy_serial);
}
*eof = 1;
done:
struct usb_serial_port *port = tty->driver_data;
if (!port)
- return -ENODEV;
+ goto exit;
dbg("%s - port %d", __FUNCTION__, port->number);
if (!port->open_count) {
dbg("%s - port not open", __FUNCTION__);
- return -ENODEV;
+ goto exit;
}
if (port->serial->type->tiocmget)
return port->serial->type->tiocmget(port, file);
+exit:
return -EINVAL;
}
struct usb_serial_port *port = tty->driver_data;
if (!port)
- return -ENODEV;
+ goto exit;
dbg("%s - port %d", __FUNCTION__, port->number);
if (!port->open_count) {
dbg("%s - port not open", __FUNCTION__);
- return -ENODEV;
+ goto exit;
}
if (port->serial->type->tiocmset)
return port->serial->type->tiocmset(port, file, set, clear);
+exit:
return -EINVAL;
}
-/*
- * We would be calling tty_wakeup here, but unfortunately some line
- * disciplines have an annoying habit of calling tty->write from
- * the write wakeup callback (e.g. n_hdlc.c).
- */
-void usb_serial_port_softint(struct usb_serial_port *port)
-{
- schedule_work(&port->work);
-}
-
-static void usb_serial_port_work(void *private)
+void usb_serial_port_softint(void *private)
{
struct usb_serial_port *port = private;
struct tty_struct *tty;
struct usb_serial_port *port = to_usb_serial_port(dev);
dbg ("%s - %s", __FUNCTION__, dev->bus_id);
- port_free(port);
-}
-
-static void port_free(struct usb_serial_port *port)
-{
usb_kill_urb(port->read_urb);
usb_free_urb(port->read_urb);
usb_kill_urb(port->write_urb);
kfree(port->bulk_out_buffer);
kfree(port->interrupt_in_buffer);
kfree(port->interrupt_out_buffer);
- flush_scheduled_work(); /* port->work */
kfree(port);
}
port->serial = serial;
spin_lock_init(&port->lock);
mutex_init(&port->mutex);
- INIT_WORK(&port->work, usb_serial_port_work, port);
+ INIT_WORK(&port->work, usb_serial_port_softint, port);
serial->port[i] = port;
}
struct device *dev = &interface->dev;
struct usb_serial_port *port;
- usb_serial_console_disconnect(serial);
dbg ("%s", __FUNCTION__);
usb_set_intfdata (interface, NULL);
}
/* let the last holder of this object
* cause it to be cleaned up */
- usb_serial_put(serial);
+ kref_put(&serial->kref, destroy_serial);
}
dev_info(dev, "device disconnected\n");
}
usb_serial_tty_driver->owner = THIS_MODULE;
usb_serial_tty_driver->driver_name = "usbserial";
+ usb_serial_tty_driver->devfs_name = "usb/tts/";
usb_serial_tty_driver->name = "ttyUSB";
usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
usb_serial_tty_driver->minor_start = 0;
usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
- usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+ usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
usb_serial_tty_driver->init_termios = tty_std_termios;
usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
tty_set_operations(usb_serial_tty_driver, &serial_ops);