Commit fe1ae7fd authored by Alan Cox's avatar Alan Cox Committed by Live-CD User

tty: USB serial termios bits

Various drivers have hacks to mangle termios structures. This stems from
the fact there is no nice setup hook for configuring the termios settings
when the port is created
Signed-off-by: default avatarAlan Cox <alan@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent ba15ab0e
......@@ -1184,6 +1184,7 @@ int tty_init_termios(struct tty_struct *tty)
tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
return 0;
}
EXPORT_SYMBOL_GPL(tty_init_termios);
/**
* tty_driver_install_tty() - install a tty entry in the driver
......
......@@ -35,11 +35,6 @@ static struct usb_device_id id_table [] = {
};
MODULE_DEVICE_TABLE(usb, id_table);
struct ark3116_private {
spinlock_t lock;
u8 termios_initialized;
};
static inline void ARK3116_SND(struct usb_serial *serial, int seq,
__u8 request, __u8 requesttype,
__u16 value, __u16 index)
......@@ -82,22 +77,11 @@ static inline void ARK3116_RCV_QUIET(struct usb_serial *serial,
static int ark3116_attach(struct usb_serial *serial)
{
char *buf;
struct ark3116_private *priv;
int i;
for (i = 0; i < serial->num_ports; ++i) {
priv = kzalloc(sizeof(struct ark3116_private), GFP_KERNEL);
if (!priv)
goto cleanup;
spin_lock_init(&priv->lock);
usb_set_serial_port_data(serial->port[i], priv);
}
buf = kmalloc(1, GFP_KERNEL);
if (!buf) {
dbg("error kmalloc -> out of mem?");
goto cleanup;
return -ENOMEM;
}
/* 3 */
......@@ -149,13 +133,16 @@ static int ark3116_attach(struct usb_serial *serial)
kfree(buf);
return 0;
}
cleanup:
for (--i; i >= 0; --i) {
kfree(usb_get_serial_port_data(serial->port[i]));
usb_set_serial_port_data(serial->port[i], NULL);
}
return -ENOMEM;
static void ark3116_init_termios(struct tty_struct *tty)
{
struct ktermios *termios = tty->termios;
*termios = tty_std_termios;
termios->c_cflag = B9600 | CS8
| CREAD | HUPCL | CLOCAL;
termios->c_ispeed = 9600;
termios->c_ospeed = 9600;
}
static void ark3116_set_termios(struct tty_struct *tty,
......@@ -163,10 +150,8 @@ static void ark3116_set_termios(struct tty_struct *tty,
struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
struct ark3116_private *priv = usb_get_serial_port_data(port);
struct ktermios *termios = tty->termios;
unsigned int cflag = termios->c_cflag;
unsigned long flags;
int baud;
int ark3116_baud;
char *buf;
......@@ -176,16 +161,6 @@ static void ark3116_set_termios(struct tty_struct *tty,
dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->lock, flags);
if (!priv->termios_initialized) {
*termios = tty_std_termios;
termios->c_cflag = B9600 | CS8
| CREAD | HUPCL | CLOCAL;
termios->c_ispeed = 9600;
termios->c_ospeed = 9600;
priv->termios_initialized = 1;
}
spin_unlock_irqrestore(&priv->lock, flags);
cflag = termios->c_cflag;
termios->c_cflag &= ~(CMSPAR|CRTSCTS);
......@@ -454,6 +429,7 @@ static struct usb_serial_driver ark3116_device = {
.num_ports = 1,
.attach = ark3116_attach,
.set_termios = ark3116_set_termios,
.init_termios = ark3116_init_termios,
.ioctl = ark3116_ioctl,
.tiocmget = ark3116_tiocmget,
.open = ark3116_open,
......
......@@ -657,15 +657,7 @@ static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port)
spin_unlock_irqrestore(&priv->lock, flags);
/* Set termios */
result = cypress_write(tty, port, NULL, 0);
if (result) {
dev_err(&port->dev,
"%s - failed setting the control lines - error %d\n",
__func__, result);
return result;
} else
dbg("%s - success setting the control lines", __func__);
cypress_send(port);
if (tty)
cypress_set_termios(tty, port, &priv->tmp_termios);
......@@ -1003,6 +995,8 @@ static void cypress_set_termios(struct tty_struct *tty,
dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->lock, flags);
/* We can't clean this one up as we don't know the device type
early enough */
if (!priv->termios_initialized) {
if (priv->chiptype == CT_EARTHMATE) {
*(tty->termios) = tty_std_termios;
......
......@@ -89,8 +89,7 @@ static int empeg_chars_in_buffer(struct tty_struct *tty);
static void empeg_throttle(struct tty_struct *tty);
static void empeg_unthrottle(struct tty_struct *tty);
static int empeg_startup(struct usb_serial *serial);
static void empeg_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios);
static void empeg_init_termios(struct tty_struct *tty);
static void empeg_write_bulk_callback(struct urb *urb);
static void empeg_read_bulk_callback(struct urb *urb);
......@@ -122,7 +121,7 @@ static struct usb_serial_driver empeg_device = {
.throttle = empeg_throttle,
.unthrottle = empeg_unthrottle,
.attach = empeg_startup,
.set_termios = empeg_set_termios,
.init_termios = empeg_init_termios,
.write = empeg_write,
.write_room = empeg_write_room,
.chars_in_buffer = empeg_chars_in_buffer,
......@@ -148,9 +147,6 @@ static int empeg_open(struct tty_struct *tty,struct usb_serial_port *port)
dbg("%s - port %d", __func__, port->number);
/* Force default termio settings */
empeg_set_termios(tty, port, NULL);
bytes_in = 0;
bytes_out = 0;
......@@ -423,11 +419,9 @@ static int empeg_startup(struct usb_serial *serial)
}
static void empeg_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
static void empeg_init_termios(struct tty_struct *tty)
{
struct ktermios *termios = tty->termios;
dbg("%s - port %d", __func__, port->number);
/*
* The empeg-car player wants these particular tty settings.
......
......@@ -71,7 +71,6 @@ struct iuu_private {
spinlock_t lock; /* store irq state */
wait_queue_head_t delta_msr_wait;
u8 line_status;
u8 termios_initialized;
int tiostatus; /* store IUART SIGNAL for tiocmget call */
u8 reset; /* if 1 reset is needed */
int poll; /* number of poll */
......@@ -1018,13 +1017,24 @@ static void iuu_close(struct usb_serial_port *port)
}
}
static void iuu_init_termios(struct tty_struct *tty)
{
*(tty->termios) = tty_std_termios;
tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600
| TIOCM_CTS | CSTOPB | PARENB;
tty->termios->c_ispeed = 9600;
tty->termios->c_ospeed = 9600;
tty->termios->c_lflag = 0;
tty->termios->c_oflag = 0;
tty->termios->c_iflag = 0;
}
static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
u8 *buf;
int result;
u32 actual;
unsigned long flags;
struct iuu_private *priv = usb_get_serial_port_data(port);
dbg("%s - port %d", __func__, port->number);
......@@ -1063,21 +1073,7 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port)
port->bulk_in_buffer, 512,
NULL, NULL);
/* set the termios structure */
spin_lock_irqsave(&priv->lock, flags);
if (tty && !priv->termios_initialized) {
*(tty->termios) = tty_std_termios;
tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600
| TIOCM_CTS | CSTOPB | PARENB;
tty->termios->c_ispeed = 9600;
tty->termios->c_ospeed = 9600;
tty->termios->c_lflag = 0;
tty->termios->c_oflag = 0;
tty->termios->c_iflag = 0;
priv->termios_initialized = 1;
priv->poll = 0;
}
spin_unlock_irqrestore(&priv->lock, flags);
/* initialize writebuf */
#define FISH(a, b, c, d) do { \
......@@ -1200,6 +1196,7 @@ static struct usb_serial_driver iuu_device = {
.tiocmget = iuu_tiocmget,
.tiocmset = iuu_tiocmset,
.set_termios = iuu_set_termios,
.init_termios = iuu_init_termios,
.attach = iuu_startup,
.release = iuu_release,
};
......
......@@ -84,7 +84,7 @@ static void kobil_read_int_callback(struct urb *urb);
static void kobil_write_callback(struct urb *purb);
static void kobil_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old);
static void kobil_init_termios(struct tty_struct *tty);
static struct usb_device_id id_table [] = {
{ USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_ADAPTER_B_PRODUCT_ID) },
......@@ -119,6 +119,7 @@ static struct usb_serial_driver kobil_device = {
.release = kobil_release,
.ioctl = kobil_ioctl,
.set_termios = kobil_set_termios,
.init_termios = kobil_init_termios,
.tiocmget = kobil_tiocmget,
.tiocmset = kobil_tiocmset,
.open = kobil_open,
......@@ -209,6 +210,15 @@ static void kobil_release(struct usb_serial *serial)
kfree(usb_get_serial_port_data(serial->port[i]));
}
static void kobil_init_termios(struct tty_struct *tty)
{
/* Default to echo off and other sane device settings */
tty->termios->c_lflag = 0;
tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN | XCASE);
tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF;
/* do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) */
tty->termios->c_oflag &= ~ONLCR;
}
static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)
{
......@@ -224,16 +234,6 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)
/* someone sets the dev to 0 if the close method has been called */
port->interrupt_in_urb->dev = port->serial->dev;
if (tty) {
/* Default to echo off and other sane device settings */
tty->termios->c_lflag = 0;
tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN |
XCASE);
tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF;
/* do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) */
tty->termios->c_oflag &= ~ONLCR;
}
/* allocate memory for transfer buffer */
transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
if (!transfer_buffer)
......
......@@ -145,6 +145,7 @@ static int oti6858_open(struct tty_struct *tty, struct usb_serial_port *port);
static void oti6858_close(struct usb_serial_port *port);
static void oti6858_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old);
static void oti6858_init_termios(struct tty_struct *tty);
static int oti6858_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
static void oti6858_read_int_callback(struct urb *urb);
......@@ -185,6 +186,7 @@ static struct usb_serial_driver oti6858_device = {
.write = oti6858_write,
.ioctl = oti6858_ioctl,
.set_termios = oti6858_set_termios,
.init_termios = oti6858_init_termios,
.tiocmget = oti6858_tiocmget,
.tiocmset = oti6858_tiocmset,
.read_bulk_callback = oti6858_read_bulk_callback,
......@@ -205,7 +207,6 @@ struct oti6858_private {
struct {
u8 read_urb_in_use;
u8 write_urb_in_use;
u8 termios_initialized;
} flags;
struct delayed_work delayed_write_work;
......@@ -446,6 +447,14 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty)
return chars;
}
static void oti6858_init_termios(struct tty_struct *tty)
{
*(tty->termios) = tty_std_termios;
tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
tty->termios->c_ispeed = 38400;
tty->termios->c_ospeed = 38400;
}
static void oti6858_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
......@@ -463,16 +472,6 @@ static void oti6858_set_termios(struct tty_struct *tty,
return;
}
spin_lock_irqsave(&priv->lock, flags);
if (!priv->flags.termios_initialized) {
*(tty->termios) = tty_std_termios;
tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
tty->termios->c_ispeed = 38400;
tty->termios->c_ospeed = 38400;
priv->flags.termios_initialized = 1;
}
spin_unlock_irqrestore(&priv->lock, flags);
cflag = tty->termios->c_cflag;
spin_lock_irqsave(&priv->lock, flags);
......
......@@ -299,7 +299,6 @@ struct spcp8x5_private {
wait_queue_head_t delta_msr_wait;
u8 line_control;
u8 line_status;
u8 termios_initialized;
};
/* desc : when device plug in,this function would be called.
......@@ -498,6 +497,15 @@ static void spcp8x5_close(struct usb_serial_port *port)
dev_dbg(&port->dev, "usb_unlink_urb(read_urb) = %d\n", result);
}
static void spcp8x5_init_termios(struct tty_struct *tty)
{
/* for the 1st time call this function */
*(tty->termios) = tty_std_termios;
tty->termios->c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
tty->termios->c_ispeed = 115200;
tty->termios->c_ospeed = 115200;
}
/* set the serial param for transfer. we should check if we really need to
* transfer. if we set flow control we should do this too. */
static void spcp8x5_set_termios(struct tty_struct *tty,
......@@ -514,16 +522,6 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
int i;
u8 control;
/* for the 1st time call this function */
spin_lock_irqsave(&priv->lock, flags);
if (!priv->termios_initialized) {
*(tty->termios) = tty_std_termios;
tty->termios->c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
tty->termios->c_ispeed = 115200;
tty->termios->c_ospeed = 115200;
priv->termios_initialized = 1;
}
spin_unlock_irqrestore(&priv->lock, flags);
/* check that they really want us to change something */
if (!tty_termios_hw_change(tty->termios, old_termios))
......@@ -1008,6 +1006,7 @@ static struct usb_serial_driver spcp8x5_device = {
.carrier_raised = spcp8x5_carrier_raised,
.write = spcp8x5_write,
.set_termios = spcp8x5_set_termios,
.init_termios = spcp8x5_init_termios,
.ioctl = spcp8x5_ioctl,
.tiocmget = spcp8x5_tiocmget,
.tiocmset = spcp8x5_tiocmset,
......
......@@ -721,6 +721,41 @@ static const struct tty_port_operations serial_port_ops = {
.dtr_rts = serial_dtr_rts,
};
/**
* serial_install - install tty
* @driver: the driver (USB in our case)
* @tty: the tty being created
*
* Create the termios objects for this tty. We use the default USB
* serial ones but permit them to be overriddenby serial->type->termios.
* This lets us remove all the ugly hackery
*/
static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
{
int idx = tty->index;
struct usb_serial *serial;
int retval;
/* If the termios setup has yet to be done */
if (tty->driver->termios[idx] == NULL) {
/* perform the standard setup */
retval = tty_init_termios(tty);
if (retval)
return retval;
/* allow the driver to update it */
serial = usb_serial_get_by_index(tty->index);
if (serial->type->init_termios)
serial->type->init_termios(tty);
usb_serial_put(serial);
}
/* Final install (we use the default method) */
tty_driver_kref_get(driver);
tty->count++;
driver->ttys[idx] = tty;
return 0;
}
int usb_serial_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
......@@ -1229,6 +1264,7 @@ static const struct tty_operations serial_ops = {
.tiocmget = serial_tiocmget,
.tiocmset = serial_tiocmset,
.shutdown = serial_do_free,
.install = serial_install,
.proc_fops = &serial_proc_fops,
};
......
......@@ -259,7 +259,7 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command,
__u8 *data, __u8 datasize);
static int firm_open(struct usb_serial_port *port);
static int firm_close(struct usb_serial_port *port);
static int firm_setup_port(struct tty_struct *tty);
static void firm_setup_port(struct tty_struct *tty);
static int firm_set_rts(struct usb_serial_port *port, __u8 onoff);
static int firm_set_dtr(struct usb_serial_port *port, __u8 onoff);
static int firm_set_break(struct usb_serial_port *port, __u8 onoff);
......@@ -1210,7 +1210,7 @@ static int firm_close(struct usb_serial_port *port)
}
static int firm_setup_port(struct tty_struct *tty)
static void firm_setup_port(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct whiteheat_port_settings port_settings;
......@@ -1285,7 +1285,7 @@ static int firm_setup_port(struct tty_struct *tty)
port_settings.lloop = 0;
/* now send the message to the device */
return firm_send_command(port, WHITEHEAT_SETUP_PORT,
firm_send_command(port, WHITEHEAT_SETUP_PORT,
(__u8 *)&port_settings, sizeof(port_settings));
}
......
......@@ -260,6 +260,9 @@ struct usb_serial_driver {
be an attached tty at this point */
void (*dtr_rts)(struct usb_serial_port *port, int on);
int (*carrier_raised)(struct usb_serial_port *port);
/* Called by the usb serial hooks to allow the user to rework the
termios state */
void (*init_termios)(struct tty_struct *tty);
/* USB events */
void (*read_int_callback)(struct urb *urb);
void (*write_int_callback)(struct urb *urb);
......
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