Skip to content

Commit

Permalink
tty: Bring the usb tty port structure into more use
Browse files Browse the repository at this point in the history
This allows us to clean stuff up, but is probably also going to cause
some app breakage with buggy apps as we now implement proper POSIX behaviour
for USB ports matching all the other ports. This does also mean other apps
that break on USB will now work properly.

Signed-off-by: Alan Cox <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Alan-Cox authored and torvalds committed Jun 11, 2009
1 parent 1ec739b commit 335f851
Show file tree
Hide file tree
Showing 39 changed files with 467 additions and 661 deletions.
6 changes: 2 additions & 4 deletions drivers/usb/serial/belkin_sa.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,7 @@ static int belkin_sa_startup(struct usb_serial *serial);
static void belkin_sa_shutdown(struct usb_serial *serial);
static int belkin_sa_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
static void belkin_sa_close(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
static void belkin_sa_close(struct usb_serial_port *port);
static void belkin_sa_read_int_callback(struct urb *urb);
static void belkin_sa_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios * old);
Expand Down Expand Up @@ -244,8 +243,7 @@ static int belkin_sa_open(struct tty_struct *tty,
} /* belkin_sa_open */


static void belkin_sa_close(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp)
static void belkin_sa_close(struct usb_serial_port *port)
{
dbg("%s port %d", __func__, port->number);

Expand Down
46 changes: 26 additions & 20 deletions drivers/usb/serial/ch341.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,32 +262,40 @@ error: kfree(priv);
return r;
}

static void ch341_close(struct tty_struct *tty, struct usb_serial_port *port,
struct file *filp)
static int ch341_carrier_raised(struct usb_serial_port *port)
{
struct ch341_private *priv = usb_get_serial_port_data(port);
if (priv->line_status & CH341_BIT_DCD)
return 1;
return 0;
}

static void ch341_dtr_rts(struct usb_serial_port *port, int on)
{
struct ch341_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int c_cflag;

dbg("%s - port %d", __func__, port->number);
/* drop DTR and RTS */
spin_lock_irqsave(&priv->lock, flags);
if (on)
priv->line_control |= CH341_BIT_RTS | CH341_BIT_DTR;
else
priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR);
spin_unlock_irqrestore(&priv->lock, flags);
ch341_set_handshake(port->serial->dev, priv->line_control);
wake_up_interruptible(&priv->delta_msr_wait);
}

static void ch341_close(struct usb_serial_port *port)
{
dbg("%s - port %d", __func__, port->number);

/* shutdown our urbs */
dbg("%s - shutting down urbs", __func__);
usb_kill_urb(port->write_urb);
usb_kill_urb(port->read_urb);
usb_kill_urb(port->interrupt_in_urb);

if (tty) {
c_cflag = tty->termios->c_cflag;
if (c_cflag & HUPCL) {
/* drop DTR and RTS */
spin_lock_irqsave(&priv->lock, flags);
priv->line_control = 0;
spin_unlock_irqrestore(&priv->lock, flags);
ch341_set_handshake(port->serial->dev, 0);
}
}
wake_up_interruptible(&priv->delta_msr_wait);
}


Expand All @@ -302,7 +310,6 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port,
dbg("ch341_open()");

priv->baud_rate = DEFAULT_BAUD_RATE;
priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;

r = ch341_configure(serial->dev, priv);
if (r)
Expand All @@ -322,7 +329,7 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port,
if (r) {
dev_err(&port->dev, "%s - failed submitting interrupt urb,"
" error %d\n", __func__, r);
ch341_close(tty, port, NULL);
ch341_close(port);
return -EPROTO;
}

Expand All @@ -343,9 +350,6 @@ static void ch341_set_termios(struct tty_struct *tty,

dbg("ch341_set_termios()");

if (!tty || !tty->termios)
return;

baud_rate = tty_get_baud_rate(tty);

priv->baud_rate = baud_rate;
Expand Down Expand Up @@ -568,6 +572,8 @@ static struct usb_serial_driver ch341_device = {
.usb_driver = &ch341_driver,
.num_ports = 1,
.open = ch341_open,
.dtr_rts = ch341_dtr_rts,
.carrier_raised = ch341_carrier_raised,
.close = ch341_close,
.ioctl = ch341_ioctl,
.set_termios = ch341_set_termios,
Expand Down
6 changes: 4 additions & 2 deletions drivers/usb/serial/console.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,9 @@ static int usb_console_setup(struct console *co, char *options)
kfree(tty);
}
}

/* So we know not to kill the hardware on a hangup on this
port. We have also bumped the use count by one so it won't go
idle */
port->console = 1;
retval = 0;

Expand All @@ -182,7 +184,7 @@ static int usb_console_setup(struct console *co, char *options)
kfree(tty);
reset_open_count:
port->port.count = 0;
goto out;
goto out;
}

static void usb_console_write(struct console *co,
Expand Down
6 changes: 2 additions & 4 deletions drivers/usb/serial/cp210x.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@
static int cp2101_open(struct tty_struct *, struct usb_serial_port *,
struct file *);
static void cp2101_cleanup(struct usb_serial_port *);
static void cp2101_close(struct tty_struct *, struct usb_serial_port *,
struct file*);
static void cp2101_close(struct usb_serial_port *);
static void cp2101_get_termios(struct tty_struct *,
struct usb_serial_port *port);
static void cp2101_get_termios_port(struct usb_serial_port *port,
Expand Down Expand Up @@ -398,8 +397,7 @@ static void cp2101_cleanup(struct usb_serial_port *port)
}
}

static void cp2101_close(struct tty_struct *tty, struct usb_serial_port *port,
struct file *filp)
static void cp2101_close(struct usb_serial_port *port)
{
dbg("%s - port %d", __func__, port->number);

Expand Down
6 changes: 2 additions & 4 deletions drivers/usb/serial/cyberjack.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ static int cyberjack_startup(struct usb_serial *serial);
static void cyberjack_shutdown(struct usb_serial *serial);
static int cyberjack_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
static void cyberjack_close(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
static void cyberjack_close(struct usb_serial_port *port);
static int cyberjack_write(struct tty_struct *tty,
struct usb_serial_port *port, const unsigned char *buf, int count);
static int cyberjack_write_room(struct tty_struct *tty);
Expand Down Expand Up @@ -185,8 +184,7 @@ static int cyberjack_open(struct tty_struct *tty,
return result;
}

static void cyberjack_close(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp)
static void cyberjack_close(struct usb_serial_port *port)
{
dbg("%s - port %d", __func__, port->number);

Expand Down
81 changes: 23 additions & 58 deletions drivers/usb/serial/cypress_m8.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,8 @@ static int cypress_ca42v2_startup(struct usb_serial *serial);
static void cypress_shutdown(struct usb_serial *serial);
static int cypress_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
static void cypress_close(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
static void cypress_close(struct usb_serial_port *port);
static void cypress_dtr_rts(struct usb_serial_port *port, int on);
static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
static void cypress_send(struct usb_serial_port *port);
Expand Down Expand Up @@ -218,6 +218,7 @@ static struct usb_serial_driver cypress_earthmate_device = {
.shutdown = cypress_shutdown,
.open = cypress_open,
.close = cypress_close,
.dtr_rts = cypress_dtr_rts,
.write = cypress_write,
.write_room = cypress_write_room,
.ioctl = cypress_ioctl,
Expand All @@ -244,6 +245,7 @@ static struct usb_serial_driver cypress_hidcom_device = {
.shutdown = cypress_shutdown,
.open = cypress_open,
.close = cypress_close,
.dtr_rts = cypress_dtr_rts,
.write = cypress_write,
.write_room = cypress_write_room,
.ioctl = cypress_ioctl,
Expand All @@ -270,6 +272,7 @@ static struct usb_serial_driver cypress_ca42v2_device = {
.shutdown = cypress_shutdown,
.open = cypress_open,
.close = cypress_close,
.dtr_rts = cypress_dtr_rts,
.write = cypress_write,
.write_room = cypress_write_room,
.ioctl = cypress_ioctl,
Expand Down Expand Up @@ -656,11 +659,7 @@ static int cypress_open(struct tty_struct *tty,
priv->rx_flags = 0;
spin_unlock_irqrestore(&priv->lock, flags);

/* raise both lines and set termios */
spin_lock_irqsave(&priv->lock, flags);
priv->line_control = CONTROL_DTR | CONTROL_RTS;
priv->cmd_ctrl = 1;
spin_unlock_irqrestore(&priv->lock, flags);
/* Set termios */
result = cypress_write(tty, port, NULL, 0);

if (result) {
Expand Down Expand Up @@ -694,76 +693,42 @@ static int cypress_open(struct tty_struct *tty,
__func__, result);
cypress_set_dead(port);
}

port->port.drain_delay = 256;
return result;
} /* cypress_open */

static void cypress_dtr_rts(struct usb_serial_port *port, int on)
{
struct cypress_private *priv = usb_get_serial_port_data(port);
/* drop dtr and rts */
priv = usb_get_serial_port_data(port);
spin_lock_irq(&priv->lock);
if (on == 0)
priv->line_control = 0;
else
priv->line_control = CONTROL_DTR | CONTROL_RTS;
priv->cmd_ctrl = 1;
spin_unlock_irq(&priv->lock);
cypress_write(NULL, port, NULL, 0);
}

static void cypress_close(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp)
static void cypress_close(struct usb_serial_port *port)
{
struct cypress_private *priv = usb_get_serial_port_data(port);
unsigned int c_cflag;
int bps;
long timeout;
wait_queue_t wait;

dbg("%s - port %d", __func__, port->number);

/* wait for data to drain from buffer */
spin_lock_irq(&priv->lock);
timeout = CYPRESS_CLOSING_WAIT;
init_waitqueue_entry(&wait, current);
add_wait_queue(&tty->write_wait, &wait);
for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
if (cypress_buf_data_avail(priv->buf) == 0
|| timeout == 0 || signal_pending(current)
/* without mutex, allowed due to harmless failure mode */
|| port->serial->disconnected)
break;
spin_unlock_irq(&priv->lock);
timeout = schedule_timeout(timeout);
spin_lock_irq(&priv->lock);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&tty->write_wait, &wait);
/* clear out any remaining data in the buffer */
cypress_buf_clear(priv->buf);
spin_unlock_irq(&priv->lock);

/* writing is potentially harmful, lock must be taken */
mutex_lock(&port->serial->disc_mutex);
if (port->serial->disconnected) {
mutex_unlock(&port->serial->disc_mutex);
return;
}
/* wait for characters to drain from device */
if (tty) {
bps = tty_get_baud_rate(tty);
if (bps > 1200)
timeout = max((HZ * 2560) / bps, HZ / 10);
else
timeout = 2 * HZ;
schedule_timeout_interruptible(timeout);
}

cypress_buf_clear(priv->buf);
dbg("%s - stopping urbs", __func__);
usb_kill_urb(port->interrupt_in_urb);
usb_kill_urb(port->interrupt_out_urb);

if (tty) {
c_cflag = tty->termios->c_cflag;
if (c_cflag & HUPCL) {
/* drop dtr and rts */
priv = usb_get_serial_port_data(port);
spin_lock_irq(&priv->lock);
priv->line_control = 0;
priv->cmd_ctrl = 1;
spin_unlock_irq(&priv->lock);
cypress_write(tty, port, NULL, 0);
}
}

if (stats)
dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
Expand Down
Loading

0 comments on commit 335f851

Please sign in to comment.