tty: Bring the usb tty port structure into more use
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 <alan@lxorguk.ukuu.org.uk> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Родитель
1ec739be75
Коммит
335f8514f2
|
@ -93,8 +93,7 @@ static int belkin_sa_startup(struct usb_serial *serial);
|
||||||
static void belkin_sa_shutdown(struct usb_serial *serial);
|
static void belkin_sa_shutdown(struct usb_serial *serial);
|
||||||
static int belkin_sa_open(struct tty_struct *tty,
|
static int belkin_sa_open(struct tty_struct *tty,
|
||||||
struct usb_serial_port *port, struct file *filp);
|
struct usb_serial_port *port, struct file *filp);
|
||||||
static void belkin_sa_close(struct tty_struct *tty,
|
static void belkin_sa_close(struct usb_serial_port *port);
|
||||||
struct usb_serial_port *port, struct file *filp);
|
|
||||||
static void belkin_sa_read_int_callback(struct urb *urb);
|
static void belkin_sa_read_int_callback(struct urb *urb);
|
||||||
static void belkin_sa_set_termios(struct tty_struct *tty,
|
static void belkin_sa_set_termios(struct tty_struct *tty,
|
||||||
struct usb_serial_port *port, struct ktermios * old);
|
struct usb_serial_port *port, struct ktermios * old);
|
||||||
|
@ -244,8 +243,7 @@ exit:
|
||||||
} /* belkin_sa_open */
|
} /* belkin_sa_open */
|
||||||
|
|
||||||
|
|
||||||
static void belkin_sa_close(struct tty_struct *tty,
|
static void belkin_sa_close(struct usb_serial_port *port)
|
||||||
struct usb_serial_port *port, struct file *filp)
|
|
||||||
{
|
{
|
||||||
dbg("%s port %d", __func__, port->number);
|
dbg("%s port %d", __func__, port->number);
|
||||||
|
|
||||||
|
|
|
@ -262,13 +262,33 @@ error: kfree(priv);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ch341_close(struct tty_struct *tty, struct usb_serial_port *port,
|
static int ch341_carrier_raised(struct usb_serial_port *port)
|
||||||
struct file *filp)
|
{
|
||||||
|
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);
|
struct ch341_private *priv = usb_get_serial_port_data(port);
|
||||||
unsigned long flags;
|
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);
|
dbg("%s - port %d", __func__, port->number);
|
||||||
|
|
||||||
/* shutdown our urbs */
|
/* shutdown our urbs */
|
||||||
|
@ -276,18 +296,6 @@ static void ch341_close(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
usb_kill_urb(port->write_urb);
|
usb_kill_urb(port->write_urb);
|
||||||
usb_kill_urb(port->read_urb);
|
usb_kill_urb(port->read_urb);
|
||||||
usb_kill_urb(port->interrupt_in_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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -302,7 +310,6 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
dbg("ch341_open()");
|
dbg("ch341_open()");
|
||||||
|
|
||||||
priv->baud_rate = DEFAULT_BAUD_RATE;
|
priv->baud_rate = DEFAULT_BAUD_RATE;
|
||||||
priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
|
|
||||||
|
|
||||||
r = ch341_configure(serial->dev, priv);
|
r = ch341_configure(serial->dev, priv);
|
||||||
if (r)
|
if (r)
|
||||||
|
@ -322,7 +329,7 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
if (r) {
|
if (r) {
|
||||||
dev_err(&port->dev, "%s - failed submitting interrupt urb,"
|
dev_err(&port->dev, "%s - failed submitting interrupt urb,"
|
||||||
" error %d\n", __func__, r);
|
" error %d\n", __func__, r);
|
||||||
ch341_close(tty, port, NULL);
|
ch341_close(port);
|
||||||
return -EPROTO;
|
return -EPROTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,9 +350,6 @@ static void ch341_set_termios(struct tty_struct *tty,
|
||||||
|
|
||||||
dbg("ch341_set_termios()");
|
dbg("ch341_set_termios()");
|
||||||
|
|
||||||
if (!tty || !tty->termios)
|
|
||||||
return;
|
|
||||||
|
|
||||||
baud_rate = tty_get_baud_rate(tty);
|
baud_rate = tty_get_baud_rate(tty);
|
||||||
|
|
||||||
priv->baud_rate = baud_rate;
|
priv->baud_rate = baud_rate;
|
||||||
|
@ -568,6 +572,8 @@ static struct usb_serial_driver ch341_device = {
|
||||||
.usb_driver = &ch341_driver,
|
.usb_driver = &ch341_driver,
|
||||||
.num_ports = 1,
|
.num_ports = 1,
|
||||||
.open = ch341_open,
|
.open = ch341_open,
|
||||||
|
.dtr_rts = ch341_dtr_rts,
|
||||||
|
.carrier_raised = ch341_carrier_raised,
|
||||||
.close = ch341_close,
|
.close = ch341_close,
|
||||||
.ioctl = ch341_ioctl,
|
.ioctl = ch341_ioctl,
|
||||||
.set_termios = ch341_set_termios,
|
.set_termios = ch341_set_termios,
|
||||||
|
|
|
@ -169,7 +169,9 @@ static int usb_console_setup(struct console *co, char *options)
|
||||||
kfree(tty);
|
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;
|
port->console = 1;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
||||||
|
@ -182,7 +184,7 @@ free_tty:
|
||||||
kfree(tty);
|
kfree(tty);
|
||||||
reset_open_count:
|
reset_open_count:
|
||||||
port->port.count = 0;
|
port->port.count = 0;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usb_console_write(struct console *co,
|
static void usb_console_write(struct console *co,
|
||||||
|
|
|
@ -36,8 +36,7 @@
|
||||||
static int cp2101_open(struct tty_struct *, struct usb_serial_port *,
|
static int cp2101_open(struct tty_struct *, struct usb_serial_port *,
|
||||||
struct file *);
|
struct file *);
|
||||||
static void cp2101_cleanup(struct usb_serial_port *);
|
static void cp2101_cleanup(struct usb_serial_port *);
|
||||||
static void cp2101_close(struct tty_struct *, struct usb_serial_port *,
|
static void cp2101_close(struct usb_serial_port *);
|
||||||
struct file*);
|
|
||||||
static void cp2101_get_termios(struct tty_struct *,
|
static void cp2101_get_termios(struct tty_struct *,
|
||||||
struct usb_serial_port *port);
|
struct usb_serial_port *port);
|
||||||
static void cp2101_get_termios_port(struct usb_serial_port *port,
|
static void cp2101_get_termios_port(struct usb_serial_port *port,
|
||||||
|
@ -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,
|
static void cp2101_close(struct usb_serial_port *port)
|
||||||
struct file *filp)
|
|
||||||
{
|
{
|
||||||
dbg("%s - port %d", __func__, port->number);
|
dbg("%s - port %d", __func__, port->number);
|
||||||
|
|
||||||
|
|
|
@ -61,8 +61,7 @@ static int cyberjack_startup(struct usb_serial *serial);
|
||||||
static void cyberjack_shutdown(struct usb_serial *serial);
|
static void cyberjack_shutdown(struct usb_serial *serial);
|
||||||
static int cyberjack_open(struct tty_struct *tty,
|
static int cyberjack_open(struct tty_struct *tty,
|
||||||
struct usb_serial_port *port, struct file *filp);
|
struct usb_serial_port *port, struct file *filp);
|
||||||
static void cyberjack_close(struct tty_struct *tty,
|
static void cyberjack_close(struct usb_serial_port *port);
|
||||||
struct usb_serial_port *port, struct file *filp);
|
|
||||||
static int cyberjack_write(struct tty_struct *tty,
|
static int cyberjack_write(struct tty_struct *tty,
|
||||||
struct usb_serial_port *port, const unsigned char *buf, int count);
|
struct usb_serial_port *port, const unsigned char *buf, int count);
|
||||||
static int cyberjack_write_room(struct tty_struct *tty);
|
static int cyberjack_write_room(struct tty_struct *tty);
|
||||||
|
@ -185,8 +184,7 @@ static int cyberjack_open(struct tty_struct *tty,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cyberjack_close(struct tty_struct *tty,
|
static void cyberjack_close(struct usb_serial_port *port)
|
||||||
struct usb_serial_port *port, struct file *filp)
|
|
||||||
{
|
{
|
||||||
dbg("%s - port %d", __func__, port->number);
|
dbg("%s - port %d", __func__, port->number);
|
||||||
|
|
||||||
|
|
|
@ -174,8 +174,8 @@ static int cypress_ca42v2_startup(struct usb_serial *serial);
|
||||||
static void cypress_shutdown(struct usb_serial *serial);
|
static void cypress_shutdown(struct usb_serial *serial);
|
||||||
static int cypress_open(struct tty_struct *tty,
|
static int cypress_open(struct tty_struct *tty,
|
||||||
struct usb_serial_port *port, struct file *filp);
|
struct usb_serial_port *port, struct file *filp);
|
||||||
static void cypress_close(struct tty_struct *tty,
|
static void cypress_close(struct usb_serial_port *port);
|
||||||
struct usb_serial_port *port, struct file *filp);
|
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,
|
static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
const unsigned char *buf, int count);
|
const unsigned char *buf, int count);
|
||||||
static void cypress_send(struct usb_serial_port *port);
|
static void cypress_send(struct usb_serial_port *port);
|
||||||
|
@ -218,6 +218,7 @@ static struct usb_serial_driver cypress_earthmate_device = {
|
||||||
.shutdown = cypress_shutdown,
|
.shutdown = cypress_shutdown,
|
||||||
.open = cypress_open,
|
.open = cypress_open,
|
||||||
.close = cypress_close,
|
.close = cypress_close,
|
||||||
|
.dtr_rts = cypress_dtr_rts,
|
||||||
.write = cypress_write,
|
.write = cypress_write,
|
||||||
.write_room = cypress_write_room,
|
.write_room = cypress_write_room,
|
||||||
.ioctl = cypress_ioctl,
|
.ioctl = cypress_ioctl,
|
||||||
|
@ -244,6 +245,7 @@ static struct usb_serial_driver cypress_hidcom_device = {
|
||||||
.shutdown = cypress_shutdown,
|
.shutdown = cypress_shutdown,
|
||||||
.open = cypress_open,
|
.open = cypress_open,
|
||||||
.close = cypress_close,
|
.close = cypress_close,
|
||||||
|
.dtr_rts = cypress_dtr_rts,
|
||||||
.write = cypress_write,
|
.write = cypress_write,
|
||||||
.write_room = cypress_write_room,
|
.write_room = cypress_write_room,
|
||||||
.ioctl = cypress_ioctl,
|
.ioctl = cypress_ioctl,
|
||||||
|
@ -270,6 +272,7 @@ static struct usb_serial_driver cypress_ca42v2_device = {
|
||||||
.shutdown = cypress_shutdown,
|
.shutdown = cypress_shutdown,
|
||||||
.open = cypress_open,
|
.open = cypress_open,
|
||||||
.close = cypress_close,
|
.close = cypress_close,
|
||||||
|
.dtr_rts = cypress_dtr_rts,
|
||||||
.write = cypress_write,
|
.write = cypress_write,
|
||||||
.write_room = cypress_write_room,
|
.write_room = cypress_write_room,
|
||||||
.ioctl = cypress_ioctl,
|
.ioctl = cypress_ioctl,
|
||||||
|
@ -656,11 +659,7 @@ static int cypress_open(struct tty_struct *tty,
|
||||||
priv->rx_flags = 0;
|
priv->rx_flags = 0;
|
||||||
spin_unlock_irqrestore(&priv->lock, flags);
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
|
||||||
/* raise both lines and set termios */
|
/* 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);
|
|
||||||
result = cypress_write(tty, port, NULL, 0);
|
result = cypress_write(tty, port, NULL, 0);
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
|
@ -694,76 +693,42 @@ static int cypress_open(struct tty_struct *tty,
|
||||||
__func__, result);
|
__func__, result);
|
||||||
cypress_set_dead(port);
|
cypress_set_dead(port);
|
||||||
}
|
}
|
||||||
|
port->port.drain_delay = 256;
|
||||||
return result;
|
return result;
|
||||||
} /* cypress_open */
|
} /* cypress_open */
|
||||||
|
|
||||||
|
static void cypress_dtr_rts(struct usb_serial_port *port, int on)
|
||||||
static void cypress_close(struct tty_struct *tty,
|
{
|
||||||
struct usb_serial_port *port, struct file *filp)
|
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 usb_serial_port *port)
|
||||||
{
|
{
|
||||||
struct cypress_private *priv = usb_get_serial_port_data(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);
|
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 */
|
/* writing is potentially harmful, lock must be taken */
|
||||||
mutex_lock(&port->serial->disc_mutex);
|
mutex_lock(&port->serial->disc_mutex);
|
||||||
if (port->serial->disconnected) {
|
if (port->serial->disconnected) {
|
||||||
mutex_unlock(&port->serial->disc_mutex);
|
mutex_unlock(&port->serial->disc_mutex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* wait for characters to drain from device */
|
cypress_buf_clear(priv->buf);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
dbg("%s - stopping urbs", __func__);
|
dbg("%s - stopping urbs", __func__);
|
||||||
usb_kill_urb(port->interrupt_in_urb);
|
usb_kill_urb(port->interrupt_in_urb);
|
||||||
usb_kill_urb(port->interrupt_out_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)
|
if (stats)
|
||||||
dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
|
dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
|
||||||
|
|
|
@ -422,7 +422,6 @@ struct digi_port {
|
||||||
int dp_throttled;
|
int dp_throttled;
|
||||||
int dp_throttle_restart;
|
int dp_throttle_restart;
|
||||||
wait_queue_head_t dp_flush_wait;
|
wait_queue_head_t dp_flush_wait;
|
||||||
int dp_in_close; /* close in progress */
|
|
||||||
wait_queue_head_t dp_close_wait; /* wait queue for close */
|
wait_queue_head_t dp_close_wait; /* wait queue for close */
|
||||||
struct work_struct dp_wakeup_work;
|
struct work_struct dp_wakeup_work;
|
||||||
struct usb_serial_port *dp_port;
|
struct usb_serial_port *dp_port;
|
||||||
|
@ -456,8 +455,9 @@ static int digi_write_room(struct tty_struct *tty);
|
||||||
static int digi_chars_in_buffer(struct tty_struct *tty);
|
static int digi_chars_in_buffer(struct tty_struct *tty);
|
||||||
static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
|
static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
struct file *filp);
|
struct file *filp);
|
||||||
static void digi_close(struct tty_struct *tty, struct usb_serial_port *port,
|
static void digi_close(struct usb_serial_port *port);
|
||||||
struct file *filp);
|
static int digi_carrier_raised(struct usb_serial_port *port);
|
||||||
|
static void digi_dtr_rts(struct usb_serial_port *port, int on);
|
||||||
static int digi_startup_device(struct usb_serial *serial);
|
static int digi_startup_device(struct usb_serial *serial);
|
||||||
static int digi_startup(struct usb_serial *serial);
|
static int digi_startup(struct usb_serial *serial);
|
||||||
static void digi_shutdown(struct usb_serial *serial);
|
static void digi_shutdown(struct usb_serial *serial);
|
||||||
|
@ -510,6 +510,8 @@ static struct usb_serial_driver digi_acceleport_2_device = {
|
||||||
.num_ports = 3,
|
.num_ports = 3,
|
||||||
.open = digi_open,
|
.open = digi_open,
|
||||||
.close = digi_close,
|
.close = digi_close,
|
||||||
|
.dtr_rts = digi_dtr_rts,
|
||||||
|
.carrier_raised = digi_carrier_raised,
|
||||||
.write = digi_write,
|
.write = digi_write,
|
||||||
.write_room = digi_write_room,
|
.write_room = digi_write_room,
|
||||||
.write_bulk_callback = digi_write_bulk_callback,
|
.write_bulk_callback = digi_write_bulk_callback,
|
||||||
|
@ -1328,6 +1330,19 @@ static int digi_chars_in_buffer(struct tty_struct *tty)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void digi_dtr_rts(struct usb_serial_port *port, int on)
|
||||||
|
{
|
||||||
|
/* Adjust DTR and RTS */
|
||||||
|
digi_set_modem_signals(port, on * (TIOCM_DTR|TIOCM_RTS), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int digi_carrier_raised(struct usb_serial_port *port)
|
||||||
|
{
|
||||||
|
struct digi_port *priv = usb_get_serial_port_data(port);
|
||||||
|
if (priv->dp_modem_signals & TIOCM_CD)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
|
static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
struct file *filp)
|
struct file *filp)
|
||||||
|
@ -1336,7 +1351,6 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
unsigned char buf[32];
|
unsigned char buf[32];
|
||||||
struct digi_port *priv = usb_get_serial_port_data(port);
|
struct digi_port *priv = usb_get_serial_port_data(port);
|
||||||
struct ktermios not_termios;
|
struct ktermios not_termios;
|
||||||
unsigned long flags = 0;
|
|
||||||
|
|
||||||
dbg("digi_open: TOP: port=%d, open_count=%d",
|
dbg("digi_open: TOP: port=%d, open_count=%d",
|
||||||
priv->dp_port_num, port->port.count);
|
priv->dp_port_num, port->port.count);
|
||||||
|
@ -1345,26 +1359,6 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
if (digi_startup_device(port->serial) != 0)
|
if (digi_startup_device(port->serial) != 0)
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
|
|
||||||
spin_lock_irqsave(&priv->dp_port_lock, flags);
|
|
||||||
|
|
||||||
/* don't wait on a close in progress for non-blocking opens */
|
|
||||||
if (priv->dp_in_close && (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0) {
|
|
||||||
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
|
|
||||||
return -EAGAIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* wait for a close in progress to finish */
|
|
||||||
while (priv->dp_in_close) {
|
|
||||||
cond_wait_interruptible_timeout_irqrestore(
|
|
||||||
&priv->dp_close_wait, DIGI_RETRY_TIMEOUT,
|
|
||||||
&priv->dp_port_lock, flags);
|
|
||||||
if (signal_pending(current))
|
|
||||||
return -EINTR;
|
|
||||||
spin_lock_irqsave(&priv->dp_port_lock, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
|
|
||||||
|
|
||||||
/* read modem signals automatically whenever they change */
|
/* read modem signals automatically whenever they change */
|
||||||
buf[0] = DIGI_CMD_READ_INPUT_SIGNALS;
|
buf[0] = DIGI_CMD_READ_INPUT_SIGNALS;
|
||||||
buf[1] = priv->dp_port_num;
|
buf[1] = priv->dp_port_num;
|
||||||
|
@ -1387,16 +1381,11 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
not_termios.c_iflag = ~tty->termios->c_iflag;
|
not_termios.c_iflag = ~tty->termios->c_iflag;
|
||||||
digi_set_termios(tty, port, ¬_termios);
|
digi_set_termios(tty, port, ¬_termios);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set DTR and RTS */
|
|
||||||
digi_set_modem_signals(port, TIOCM_DTR|TIOCM_RTS, 1);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void digi_close(struct tty_struct *tty, struct usb_serial_port *port,
|
static void digi_close(struct usb_serial_port *port)
|
||||||
struct file *filp)
|
|
||||||
{
|
{
|
||||||
DEFINE_WAIT(wait);
|
DEFINE_WAIT(wait);
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -1411,28 +1400,9 @@ static void digi_close(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
if (port->serial->disconnected)
|
if (port->serial->disconnected)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
/* do cleanup only after final close on this port */
|
|
||||||
spin_lock_irq(&priv->dp_port_lock);
|
|
||||||
priv->dp_in_close = 1;
|
|
||||||
spin_unlock_irq(&priv->dp_port_lock);
|
|
||||||
|
|
||||||
/* tell line discipline to process only XON/XOFF */
|
|
||||||
tty->closing = 1;
|
|
||||||
|
|
||||||
/* wait for output to drain */
|
|
||||||
if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0)
|
|
||||||
tty_wait_until_sent(tty, DIGI_CLOSE_TIMEOUT);
|
|
||||||
|
|
||||||
/* flush driver and line discipline buffers */
|
|
||||||
tty_driver_flush_buffer(tty);
|
|
||||||
tty_ldisc_flush(tty);
|
|
||||||
|
|
||||||
if (port->serial->dev) {
|
if (port->serial->dev) {
|
||||||
/* wait for transmit idle */
|
/* FIXME: Transmit idle belongs in the wait_unti_sent path */
|
||||||
if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0)
|
|
||||||
digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
|
digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
|
||||||
/* drop DTR and RTS */
|
|
||||||
digi_set_modem_signals(port, 0, 0);
|
|
||||||
|
|
||||||
/* disable input flow control */
|
/* disable input flow control */
|
||||||
buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
|
buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
|
||||||
|
@ -1477,11 +1447,9 @@ static void digi_close(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
/* shutdown any outstanding bulk writes */
|
/* shutdown any outstanding bulk writes */
|
||||||
usb_kill_urb(port->write_urb);
|
usb_kill_urb(port->write_urb);
|
||||||
}
|
}
|
||||||
tty->closing = 0;
|
|
||||||
exit:
|
exit:
|
||||||
spin_lock_irq(&priv->dp_port_lock);
|
spin_lock_irq(&priv->dp_port_lock);
|
||||||
priv->dp_write_urb_in_use = 0;
|
priv->dp_write_urb_in_use = 0;
|
||||||
priv->dp_in_close = 0;
|
|
||||||
wake_up_interruptible(&priv->dp_close_wait);
|
wake_up_interruptible(&priv->dp_close_wait);
|
||||||
spin_unlock_irq(&priv->dp_port_lock);
|
spin_unlock_irq(&priv->dp_port_lock);
|
||||||
mutex_unlock(&port->serial->disc_mutex);
|
mutex_unlock(&port->serial->disc_mutex);
|
||||||
|
@ -1560,7 +1528,6 @@ static int digi_startup(struct usb_serial *serial)
|
||||||
priv->dp_throttled = 0;
|
priv->dp_throttled = 0;
|
||||||
priv->dp_throttle_restart = 0;
|
priv->dp_throttle_restart = 0;
|
||||||
init_waitqueue_head(&priv->dp_flush_wait);
|
init_waitqueue_head(&priv->dp_flush_wait);
|
||||||
priv->dp_in_close = 0;
|
|
||||||
init_waitqueue_head(&priv->dp_close_wait);
|
init_waitqueue_head(&priv->dp_close_wait);
|
||||||
INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
|
INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
|
||||||
priv->dp_port = serial->port[i];
|
priv->dp_port = serial->port[i];
|
||||||
|
|
|
@ -81,8 +81,7 @@ static int debug;
|
||||||
/* function prototypes for an empeg-car player */
|
/* function prototypes for an empeg-car player */
|
||||||
static int empeg_open(struct tty_struct *tty, struct usb_serial_port *port,
|
static int empeg_open(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
struct file *filp);
|
struct file *filp);
|
||||||
static void empeg_close(struct tty_struct *tty, struct usb_serial_port *port,
|
static void empeg_close(struct usb_serial_port *port);
|
||||||
struct file *filp);
|
|
||||||
static int empeg_write(struct tty_struct *tty, struct usb_serial_port *port,
|
static int empeg_write(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
const unsigned char *buf,
|
const unsigned char *buf,
|
||||||
int count);
|
int count);
|
||||||
|
@ -181,8 +180,7 @@ static int empeg_open(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void empeg_close(struct tty_struct *tty, struct usb_serial_port *port,
|
static void empeg_close(struct usb_serial_port *port)
|
||||||
struct file *filp)
|
|
||||||
{
|
{
|
||||||
dbg("%s - port %d", __func__, port->number);
|
dbg("%s - port %d", __func__, port->number);
|
||||||
|
|
||||||
|
|
|
@ -719,8 +719,8 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port);
|
||||||
static int ftdi_sio_port_remove(struct usb_serial_port *port);
|
static int ftdi_sio_port_remove(struct usb_serial_port *port);
|
||||||
static int ftdi_open(struct tty_struct *tty,
|
static int ftdi_open(struct tty_struct *tty,
|
||||||
struct usb_serial_port *port, struct file *filp);
|
struct usb_serial_port *port, struct file *filp);
|
||||||
static void ftdi_close(struct tty_struct *tty,
|
static void ftdi_close(struct usb_serial_port *port);
|
||||||
struct usb_serial_port *port, struct file *filp);
|
static void ftdi_dtr_rts(struct usb_serial_port *port, int on);
|
||||||
static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port,
|
static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
const unsigned char *buf, int count);
|
const unsigned char *buf, int count);
|
||||||
static int ftdi_write_room(struct tty_struct *tty);
|
static int ftdi_write_room(struct tty_struct *tty);
|
||||||
|
@ -758,6 +758,7 @@ static struct usb_serial_driver ftdi_sio_device = {
|
||||||
.port_remove = ftdi_sio_port_remove,
|
.port_remove = ftdi_sio_port_remove,
|
||||||
.open = ftdi_open,
|
.open = ftdi_open,
|
||||||
.close = ftdi_close,
|
.close = ftdi_close,
|
||||||
|
.dtr_rts = ftdi_dtr_rts,
|
||||||
.throttle = ftdi_throttle,
|
.throttle = ftdi_throttle,
|
||||||
.unthrottle = ftdi_unthrottle,
|
.unthrottle = ftdi_unthrottle,
|
||||||
.write = ftdi_write,
|
.write = ftdi_write,
|
||||||
|
@ -1558,6 +1559,30 @@ static int ftdi_open(struct tty_struct *tty,
|
||||||
} /* ftdi_open */
|
} /* ftdi_open */
|
||||||
|
|
||||||
|
|
||||||
|
static void ftdi_dtr_rts(struct usb_serial_port *port, int on)
|
||||||
|
{
|
||||||
|
struct ftdi_private *priv = usb_get_serial_port_data(port);
|
||||||
|
char buf[1];
|
||||||
|
|
||||||
|
mutex_lock(&port->serial->disc_mutex);
|
||||||
|
if (!port->serial->disconnected) {
|
||||||
|
/* Disable flow control */
|
||||||
|
if (!on && usb_control_msg(port->serial->dev,
|
||||||
|
usb_sndctrlpipe(port->serial->dev, 0),
|
||||||
|
FTDI_SIO_SET_FLOW_CTRL_REQUEST,
|
||||||
|
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
|
||||||
|
0, priv->interface, buf, 0,
|
||||||
|
WDR_TIMEOUT) < 0) {
|
||||||
|
dev_err(&port->dev, "error from flowcontrol urb\n");
|
||||||
|
}
|
||||||
|
/* drop RTS and DTR */
|
||||||
|
if (on)
|
||||||
|
set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
|
||||||
|
else
|
||||||
|
clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
|
||||||
|
}
|
||||||
|
mutex_unlock(&port->serial->disc_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* usbserial:__serial_close only calls ftdi_close if the point is open
|
* usbserial:__serial_close only calls ftdi_close if the point is open
|
||||||
|
@ -1567,31 +1592,12 @@ static int ftdi_open(struct tty_struct *tty,
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void ftdi_close(struct tty_struct *tty,
|
static void ftdi_close(struct usb_serial_port *port)
|
||||||
struct usb_serial_port *port, struct file *filp)
|
|
||||||
{ /* ftdi_close */
|
{ /* ftdi_close */
|
||||||
unsigned int c_cflag = tty->termios->c_cflag;
|
|
||||||
struct ftdi_private *priv = usb_get_serial_port_data(port);
|
struct ftdi_private *priv = usb_get_serial_port_data(port);
|
||||||
char buf[1];
|
|
||||||
|
|
||||||
dbg("%s", __func__);
|
dbg("%s", __func__);
|
||||||
|
|
||||||
mutex_lock(&port->serial->disc_mutex);
|
|
||||||
if (c_cflag & HUPCL && !port->serial->disconnected) {
|
|
||||||
/* Disable flow control */
|
|
||||||
if (usb_control_msg(port->serial->dev,
|
|
||||||
usb_sndctrlpipe(port->serial->dev, 0),
|
|
||||||
FTDI_SIO_SET_FLOW_CTRL_REQUEST,
|
|
||||||
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
|
|
||||||
0, priv->interface, buf, 0,
|
|
||||||
WDR_TIMEOUT) < 0) {
|
|
||||||
dev_err(&port->dev, "error from flowcontrol urb\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* drop RTS and DTR */
|
|
||||||
clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
|
|
||||||
} /* Note change no line if hupcl is off */
|
|
||||||
mutex_unlock(&port->serial->disc_mutex);
|
|
||||||
|
|
||||||
/* cancel any scheduled reading */
|
/* cancel any scheduled reading */
|
||||||
cancel_delayed_work_sync(&priv->rx_work);
|
cancel_delayed_work_sync(&priv->rx_work);
|
||||||
|
|
|
@ -993,8 +993,7 @@ static int garmin_open(struct tty_struct *tty,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void garmin_close(struct tty_struct *tty,
|
static void garmin_close(struct usb_serial_port *port)
|
||||||
struct usb_serial_port *port, struct file *filp)
|
|
||||||
{
|
{
|
||||||
struct usb_serial *serial = port->serial;
|
struct usb_serial *serial = port->serial;
|
||||||
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
|
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
|
||||||
|
|
|
@ -184,8 +184,7 @@ int usb_serial_generic_resume(struct usb_serial *serial)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(usb_serial_generic_resume);
|
EXPORT_SYMBOL_GPL(usb_serial_generic_resume);
|
||||||
|
|
||||||
void usb_serial_generic_close(struct tty_struct *tty,
|
void usb_serial_generic_close(struct usb_serial_port *port)
|
||||||
struct usb_serial_port *port, struct file *filp)
|
|
||||||
{
|
{
|
||||||
dbg("%s - port %d", __func__, port->number);
|
dbg("%s - port %d", __func__, port->number);
|
||||||
generic_cleanup(port);
|
generic_cleanup(port);
|
||||||
|
|
|
@ -207,8 +207,7 @@ static void edge_bulk_out_cmd_callback(struct urb *urb);
|
||||||
/* function prototypes for the usbserial callbacks */
|
/* function prototypes for the usbserial callbacks */
|
||||||
static int edge_open(struct tty_struct *tty, struct usb_serial_port *port,
|
static int edge_open(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
struct file *filp);
|
struct file *filp);
|
||||||
static void edge_close(struct tty_struct *tty, struct usb_serial_port *port,
|
static void edge_close(struct usb_serial_port *port);
|
||||||
struct file *filp);
|
|
||||||
static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
|
static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
const unsigned char *buf, int count);
|
const unsigned char *buf, int count);
|
||||||
static int edge_write_room(struct tty_struct *tty);
|
static int edge_write_room(struct tty_struct *tty);
|
||||||
|
@ -965,7 +964,7 @@ static int edge_open(struct tty_struct *tty,
|
||||||
|
|
||||||
if (!edge_port->txfifo.fifo) {
|
if (!edge_port->txfifo.fifo) {
|
||||||
dbg("%s - no memory", __func__);
|
dbg("%s - no memory", __func__);
|
||||||
edge_close(tty, port, filp);
|
edge_close(port);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -975,7 +974,7 @@ static int edge_open(struct tty_struct *tty,
|
||||||
|
|
||||||
if (!edge_port->write_urb) {
|
if (!edge_port->write_urb) {
|
||||||
dbg("%s - no memory", __func__);
|
dbg("%s - no memory", __func__);
|
||||||
edge_close(tty, port, filp);
|
edge_close(port);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1099,8 +1098,7 @@ static void block_until_tx_empty(struct edgeport_port *edge_port)
|
||||||
* edge_close
|
* edge_close
|
||||||
* this function is called by the tty driver when a port is closed
|
* this function is called by the tty driver when a port is closed
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
static void edge_close(struct tty_struct *tty,
|
static void edge_close(struct usb_serial_port *port)
|
||||||
struct usb_serial_port *port, struct file *filp)
|
|
||||||
{
|
{
|
||||||
struct edgeport_serial *edge_serial;
|
struct edgeport_serial *edge_serial;
|
||||||
struct edgeport_port *edge_port;
|
struct edgeport_port *edge_port;
|
||||||
|
|
|
@ -2009,8 +2009,7 @@ release_es_lock:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void edge_close(struct tty_struct *tty,
|
static void edge_close(struct usb_serial_port *port)
|
||||||
struct usb_serial_port *port, struct file *filp)
|
|
||||||
{
|
{
|
||||||
struct edgeport_serial *edge_serial;
|
struct edgeport_serial *edge_serial;
|
||||||
struct edgeport_port *edge_port;
|
struct edgeport_port *edge_port;
|
||||||
|
|
|
@ -76,8 +76,7 @@ static int initial_wait;
|
||||||
/* Function prototypes for an ipaq */
|
/* Function prototypes for an ipaq */
|
||||||
static int ipaq_open(struct tty_struct *tty,
|
static int ipaq_open(struct tty_struct *tty,
|
||||||
struct usb_serial_port *port, struct file *filp);
|
struct usb_serial_port *port, struct file *filp);
|
||||||
static void ipaq_close(struct tty_struct *tty,
|
static void ipaq_close(struct usb_serial_port *port);
|
||||||
struct usb_serial_port *port, struct file *filp);
|
|
||||||
static int ipaq_calc_num_ports(struct usb_serial *serial);
|
static int ipaq_calc_num_ports(struct usb_serial *serial);
|
||||||
static int ipaq_startup(struct usb_serial *serial);
|
static int ipaq_startup(struct usb_serial *serial);
|
||||||
static void ipaq_shutdown(struct usb_serial *serial);
|
static void ipaq_shutdown(struct usb_serial *serial);
|
||||||
|
@ -714,8 +713,7 @@ error:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ipaq_close(struct tty_struct *tty,
|
static void ipaq_close(struct usb_serial_port *port)
|
||||||
struct usb_serial_port *port, struct file *filp)
|
|
||||||
{
|
{
|
||||||
struct ipaq_private *priv = usb_get_serial_port_data(port);
|
struct ipaq_private *priv = usb_get_serial_port_data(port);
|
||||||
|
|
||||||
|
|
|
@ -302,23 +302,17 @@ static int ipw_open(struct tty_struct *tty,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ipw_close(struct tty_struct *tty,
|
static void ipw_dtr_rts(struct usb_serial_port *port, int on)
|
||||||
struct usb_serial_port *port, struct file *filp)
|
|
||||||
{
|
{
|
||||||
struct usb_device *dev = port->serial->dev;
|
struct usb_device *dev = port->serial->dev;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (tty_hung_up_p(filp)) {
|
|
||||||
dbg("%s: tty_hung_up_p ...", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--1: drop the dtr */
|
/*--1: drop the dtr */
|
||||||
dbg("%s:dropping dtr", __func__);
|
dbg("%s:dropping dtr", __func__);
|
||||||
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
|
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
|
||||||
IPW_SIO_SET_PIN,
|
IPW_SIO_SET_PIN,
|
||||||
USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
|
USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
|
||||||
IPW_PIN_CLRDTR,
|
on ? IPW_PIN_SETDTR : IPW_PIN_CLRDTR,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
0,
|
0,
|
||||||
|
@ -332,7 +326,7 @@ static void ipw_close(struct tty_struct *tty,
|
||||||
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
|
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
|
||||||
IPW_SIO_SET_PIN, USB_TYPE_VENDOR |
|
IPW_SIO_SET_PIN, USB_TYPE_VENDOR |
|
||||||
USB_RECIP_INTERFACE | USB_DIR_OUT,
|
USB_RECIP_INTERFACE | USB_DIR_OUT,
|
||||||
IPW_PIN_CLRRTS,
|
on ? IPW_PIN_SETRTS : IPW_PIN_CLRRTS,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
0,
|
0,
|
||||||
|
@ -340,7 +334,12 @@ static void ipw_close(struct tty_struct *tty,
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
dev_err(&port->dev,
|
dev_err(&port->dev,
|
||||||
"dropping rts failed (error = %d)\n", result);
|
"dropping rts failed (error = %d)\n", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ipw_close(struct usb_serial_port *port)
|
||||||
|
{
|
||||||
|
struct usb_device *dev = port->serial->dev;
|
||||||
|
int result;
|
||||||
|
|
||||||
/*--3: purge */
|
/*--3: purge */
|
||||||
dbg("%s:sending purge", __func__);
|
dbg("%s:sending purge", __func__);
|
||||||
|
@ -461,6 +460,7 @@ static struct usb_serial_driver ipw_device = {
|
||||||
.num_ports = 1,
|
.num_ports = 1,
|
||||||
.open = ipw_open,
|
.open = ipw_open,
|
||||||
.close = ipw_close,
|
.close = ipw_close,
|
||||||
|
.dtr_rts = ipw_dtr_rts,
|
||||||
.port_probe = ipw_probe,
|
.port_probe = ipw_probe,
|
||||||
.port_remove = ipw_disconnect,
|
.port_remove = ipw_disconnect,
|
||||||
.write = ipw_write,
|
.write = ipw_write,
|
||||||
|
|
|
@ -88,8 +88,7 @@ static int xbof = -1;
|
||||||
static int ir_startup (struct usb_serial *serial);
|
static int ir_startup (struct usb_serial *serial);
|
||||||
static int ir_open(struct tty_struct *tty, struct usb_serial_port *port,
|
static int ir_open(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
struct file *filep);
|
struct file *filep);
|
||||||
static void ir_close(struct tty_struct *tty, struct usb_serial_port *port,
|
static void ir_close(struct usb_serial_port *port);
|
||||||
struct file *filep);
|
|
||||||
static int ir_write(struct tty_struct *tty, struct usb_serial_port *port,
|
static int ir_write(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
const unsigned char *buf, int count);
|
const unsigned char *buf, int count);
|
||||||
static void ir_write_bulk_callback (struct urb *urb);
|
static void ir_write_bulk_callback (struct urb *urb);
|
||||||
|
@ -346,8 +345,7 @@ static int ir_open(struct tty_struct *tty,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ir_close(struct tty_struct *tty,
|
static void ir_close(struct usb_serial_port *port)
|
||||||
struct usb_serial_port *port, struct file * filp)
|
|
||||||
{
|
{
|
||||||
dbg("%s - port %d", __func__, port->number);
|
dbg("%s - port %d", __func__, port->number);
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,6 @@ static void read_rxcmd_callback(struct urb *urb);
|
||||||
struct iuu_private {
|
struct iuu_private {
|
||||||
spinlock_t lock; /* store irq state */
|
spinlock_t lock; /* store irq state */
|
||||||
wait_queue_head_t delta_msr_wait;
|
wait_queue_head_t delta_msr_wait;
|
||||||
u8 line_control;
|
|
||||||
u8 line_status;
|
u8 line_status;
|
||||||
u8 termios_initialized;
|
u8 termios_initialized;
|
||||||
int tiostatus; /* store IUART SIGNAL for tiocmget call */
|
int tiostatus; /* store IUART SIGNAL for tiocmget call */
|
||||||
|
@ -946,19 +945,10 @@ static int iuu_uart_baud(struct usb_serial_port *port, u32 baud,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_control_lines(struct usb_device *dev, u8 value)
|
static void iuu_close(struct usb_serial_port *port)
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void iuu_close(struct tty_struct *tty,
|
|
||||||
struct usb_serial_port *port, struct file *filp)
|
|
||||||
{
|
{
|
||||||
/* iuu_led (port,255,0,0,0); */
|
/* iuu_led (port,255,0,0,0); */
|
||||||
struct usb_serial *serial;
|
struct usb_serial *serial;
|
||||||
struct iuu_private *priv = usb_get_serial_port_data(port);
|
|
||||||
unsigned long flags;
|
|
||||||
unsigned int c_cflag;
|
|
||||||
|
|
||||||
serial = port->serial;
|
serial = port->serial;
|
||||||
if (!serial)
|
if (!serial)
|
||||||
|
@ -968,17 +958,6 @@ static void iuu_close(struct tty_struct *tty,
|
||||||
|
|
||||||
iuu_uart_off(port);
|
iuu_uart_off(port);
|
||||||
if (serial->dev) {
|
if (serial->dev) {
|
||||||
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_irqsave(&priv->lock, flags);
|
|
||||||
priv->line_control = 0;
|
|
||||||
spin_unlock_irqrestore(&priv->lock, flags);
|
|
||||||
set_control_lines(port->serial->dev, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* free writebuf */
|
/* free writebuf */
|
||||||
/* shutdown our urbs */
|
/* shutdown our urbs */
|
||||||
dbg("%s - shutting down urbs", __func__);
|
dbg("%s - shutting down urbs", __func__);
|
||||||
|
@ -1154,7 +1133,7 @@ static int iuu_open(struct tty_struct *tty,
|
||||||
if (result) {
|
if (result) {
|
||||||
dev_err(&port->dev, "%s - failed submitting read urb,"
|
dev_err(&port->dev, "%s - failed submitting read urb,"
|
||||||
" error %d\n", __func__, result);
|
" error %d\n", __func__, result);
|
||||||
iuu_close(tty, port, NULL);
|
iuu_close(port);
|
||||||
return -EPROTO;
|
return -EPROTO;
|
||||||
} else {
|
} else {
|
||||||
dbg("%s - rxcmd OK", __func__);
|
dbg("%s - rxcmd OK", __func__);
|
||||||
|
|
|
@ -1298,8 +1298,16 @@ static inline void stop_urb(struct urb *urb)
|
||||||
usb_kill_urb(urb);
|
usb_kill_urb(urb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyspan_close(struct tty_struct *tty,
|
static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
|
||||||
struct usb_serial_port *port, struct file *filp)
|
{
|
||||||
|
struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
|
||||||
|
|
||||||
|
p_priv->rts_state = on;
|
||||||
|
p_priv->dtr_state = on;
|
||||||
|
keyspan_send_setup(port, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void keyspan_close(struct usb_serial_port *port)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct usb_serial *serial = port->serial;
|
struct usb_serial *serial = port->serial;
|
||||||
|
@ -1336,7 +1344,6 @@ static void keyspan_close(struct tty_struct *tty,
|
||||||
stop_urb(p_priv->out_urbs[i]);
|
stop_urb(p_priv->out_urbs[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tty_port_tty_set(&port->port, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* download the firmware to a pre-renumeration device */
|
/* download the firmware to a pre-renumeration device */
|
||||||
|
|
|
@ -38,9 +38,8 @@
|
||||||
static int keyspan_open (struct tty_struct *tty,
|
static int keyspan_open (struct tty_struct *tty,
|
||||||
struct usb_serial_port *port,
|
struct usb_serial_port *port,
|
||||||
struct file *filp);
|
struct file *filp);
|
||||||
static void keyspan_close (struct tty_struct *tty,
|
static void keyspan_close (struct usb_serial_port *port);
|
||||||
struct usb_serial_port *port,
|
static void keyspan_dtr_rts (struct usb_serial_port *port, int on);
|
||||||
struct file *filp);
|
|
||||||
static int keyspan_startup (struct usb_serial *serial);
|
static int keyspan_startup (struct usb_serial *serial);
|
||||||
static void keyspan_shutdown (struct usb_serial *serial);
|
static void keyspan_shutdown (struct usb_serial *serial);
|
||||||
static int keyspan_write_room (struct tty_struct *tty);
|
static int keyspan_write_room (struct tty_struct *tty);
|
||||||
|
@ -562,6 +561,7 @@ static struct usb_serial_driver keyspan_1port_device = {
|
||||||
.num_ports = 1,
|
.num_ports = 1,
|
||||||
.open = keyspan_open,
|
.open = keyspan_open,
|
||||||
.close = keyspan_close,
|
.close = keyspan_close,
|
||||||
|
.dtr_rts = keyspan_dtr_rts,
|
||||||
.write = keyspan_write,
|
.write = keyspan_write,
|
||||||
.write_room = keyspan_write_room,
|
.write_room = keyspan_write_room,
|
||||||
.set_termios = keyspan_set_termios,
|
.set_termios = keyspan_set_termios,
|
||||||
|
@ -582,6 +582,7 @@ static struct usb_serial_driver keyspan_2port_device = {
|
||||||
.num_ports = 2,
|
.num_ports = 2,
|
||||||
.open = keyspan_open,
|
.open = keyspan_open,
|
||||||
.close = keyspan_close,
|
.close = keyspan_close,
|
||||||
|
.dtr_rts = keyspan_dtr_rts,
|
||||||
.write = keyspan_write,
|
.write = keyspan_write,
|
||||||
.write_room = keyspan_write_room,
|
.write_room = keyspan_write_room,
|
||||||
.set_termios = keyspan_set_termios,
|
.set_termios = keyspan_set_termios,
|
||||||
|
@ -602,6 +603,7 @@ static struct usb_serial_driver keyspan_4port_device = {
|
||||||
.num_ports = 4,
|
.num_ports = 4,
|
||||||
.open = keyspan_open,
|
.open = keyspan_open,
|
||||||
.close = keyspan_close,
|
.close = keyspan_close,
|
||||||
|
.dtr_rts = keyspan_dtr_rts,
|
||||||
.write = keyspan_write,
|
.write = keyspan_write,
|
||||||
.write_room = keyspan_write_room,
|
.write_room = keyspan_write_room,
|
||||||
.set_termios = keyspan_set_termios,
|
.set_termios = keyspan_set_termios,
|
||||||
|
|
|
@ -651,6 +651,35 @@ static int keyspan_pda_chars_in_buffer(struct tty_struct *tty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void keyspan_pda_dtr_rts(struct usb_serial_port *port, int on)
|
||||||
|
{
|
||||||
|
struct usb_serial *serial = port->serial;
|
||||||
|
|
||||||
|
if (serial->dev) {
|
||||||
|
if (on)
|
||||||
|
keyspan_pda_set_modem_info(serial, (1<<7) | (1<< 2));
|
||||||
|
else
|
||||||
|
keyspan_pda_set_modem_info(serial, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int keyspan_pda_carrier_raised(struct usb_serial_port *port)
|
||||||
|
{
|
||||||
|
struct usb_serial *serial = port->serial;
|
||||||
|
unsigned char modembits;
|
||||||
|
|
||||||
|
/* If we can read the modem status and the DCD is low then
|
||||||
|
carrier is not raised yet */
|
||||||
|
if (keyspan_pda_get_modem_info(serial, &modembits) >= 0) {
|
||||||
|
if (!(modembits & (1>>6)))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Carrier raised, or we failed (eg disconnected) so
|
||||||
|
progress accordingly */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int keyspan_pda_open(struct tty_struct *tty,
|
static int keyspan_pda_open(struct tty_struct *tty,
|
||||||
struct usb_serial_port *port, struct file *filp)
|
struct usb_serial_port *port, struct file *filp)
|
||||||
{
|
{
|
||||||
|
@ -682,13 +711,6 @@ static int keyspan_pda_open(struct tty_struct *tty,
|
||||||
priv->tx_room = room;
|
priv->tx_room = room;
|
||||||
priv->tx_throttled = room ? 0 : 1;
|
priv->tx_throttled = room ? 0 : 1;
|
||||||
|
|
||||||
/* the normal serial device seems to always turn on DTR and RTS here,
|
|
||||||
so do the same */
|
|
||||||
if (tty && (tty->termios->c_cflag & CBAUD))
|
|
||||||
keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2));
|
|
||||||
else
|
|
||||||
keyspan_pda_set_modem_info(serial, 0);
|
|
||||||
|
|
||||||
/*Start reading from the device*/
|
/*Start reading from the device*/
|
||||||
port->interrupt_in_urb->dev = serial->dev;
|
port->interrupt_in_urb->dev = serial->dev;
|
||||||
rc = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
|
rc = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
|
||||||
|
@ -700,19 +722,11 @@ static int keyspan_pda_open(struct tty_struct *tty,
|
||||||
error:
|
error:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
static void keyspan_pda_close(struct usb_serial_port *port)
|
||||||
|
|
||||||
static void keyspan_pda_close(struct tty_struct *tty,
|
|
||||||
struct usb_serial_port *port, struct file *filp)
|
|
||||||
{
|
{
|
||||||
struct usb_serial *serial = port->serial;
|
struct usb_serial *serial = port->serial;
|
||||||
|
|
||||||
if (serial->dev) {
|
if (serial->dev) {
|
||||||
/* the normal serial device seems to always shut
|
|
||||||
off DTR and RTS now */
|
|
||||||
if (tty->termios->c_cflag & HUPCL)
|
|
||||||
keyspan_pda_set_modem_info(serial, 0);
|
|
||||||
|
|
||||||
/* shutdown our bulk reads and writes */
|
/* shutdown our bulk reads and writes */
|
||||||
usb_kill_urb(port->write_urb);
|
usb_kill_urb(port->write_urb);
|
||||||
usb_kill_urb(port->interrupt_in_urb);
|
usb_kill_urb(port->interrupt_in_urb);
|
||||||
|
@ -839,6 +853,8 @@ static struct usb_serial_driver keyspan_pda_device = {
|
||||||
.usb_driver = &keyspan_pda_driver,
|
.usb_driver = &keyspan_pda_driver,
|
||||||
.id_table = id_table_std,
|
.id_table = id_table_std,
|
||||||
.num_ports = 1,
|
.num_ports = 1,
|
||||||
|
.dtr_rts = keyspan_pda_dtr_rts,
|
||||||
|
.carrier_raised = keyspan_pda_carrier_raised,
|
||||||
.open = keyspan_pda_open,
|
.open = keyspan_pda_open,
|
||||||
.close = keyspan_pda_close,
|
.close = keyspan_pda_close,
|
||||||
.write = keyspan_pda_write,
|
.write = keyspan_pda_write,
|
||||||
|
|
|
@ -76,8 +76,7 @@ static int klsi_105_startup(struct usb_serial *serial);
|
||||||
static void klsi_105_shutdown(struct usb_serial *serial);
|
static void klsi_105_shutdown(struct usb_serial *serial);
|
||||||
static int klsi_105_open(struct tty_struct *tty,
|
static int klsi_105_open(struct tty_struct *tty,
|
||||||
struct usb_serial_port *port, struct file *filp);
|
struct usb_serial_port *port, struct file *filp);
|
||||||
static void klsi_105_close(struct tty_struct *tty,
|
static void klsi_105_close(struct usb_serial_port *port);
|
||||||
struct usb_serial_port *port, struct file *filp);
|
|
||||||
static int klsi_105_write(struct tty_struct *tty,
|
static int klsi_105_write(struct tty_struct *tty,
|
||||||
struct usb_serial_port *port, const unsigned char *buf, int count);
|
struct usb_serial_port *port, const unsigned char *buf, int count);
|
||||||
static void klsi_105_write_bulk_callback(struct urb *urb);
|
static void klsi_105_write_bulk_callback(struct urb *urb);
|
||||||
|
@ -447,8 +446,7 @@ exit:
|
||||||
} /* klsi_105_open */
|
} /* klsi_105_open */
|
||||||
|
|
||||||
|
|
||||||
static void klsi_105_close(struct tty_struct *tty,
|
static void klsi_105_close(struct usb_serial_port *port)
|
||||||
struct usb_serial_port *port, struct file *filp)
|
|
||||||
{
|
{
|
||||||
struct klsi_105_private *priv = usb_get_serial_port_data(port);
|
struct klsi_105_private *priv = usb_get_serial_port_data(port);
|
||||||
int rc;
|
int rc;
|
||||||
|
|
|
@ -72,8 +72,7 @@ static int kobil_startup(struct usb_serial *serial);
|
||||||
static void kobil_shutdown(struct usb_serial *serial);
|
static void kobil_shutdown(struct usb_serial *serial);
|
||||||
static int kobil_open(struct tty_struct *tty,
|
static int kobil_open(struct tty_struct *tty,
|
||||||
struct usb_serial_port *port, struct file *filp);
|
struct usb_serial_port *port, struct file *filp);
|
||||||
static void kobil_close(struct tty_struct *tty, struct usb_serial_port *port,
|
static void kobil_close(struct usb_serial_port *port);
|
||||||
struct file *filp);
|
|
||||||
static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
|
static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
const unsigned char *buf, int count);
|
const unsigned char *buf, int count);
|
||||||
static int kobil_write_room(struct tty_struct *tty);
|
static int kobil_write_room(struct tty_struct *tty);
|
||||||
|
@ -209,7 +208,7 @@ static void kobil_shutdown(struct usb_serial *serial)
|
||||||
|
|
||||||
for (i = 0; i < serial->num_ports; ++i) {
|
for (i = 0; i < serial->num_ports; ++i) {
|
||||||
while (serial->port[i]->port.count > 0)
|
while (serial->port[i]->port.count > 0)
|
||||||
kobil_close(NULL, serial->port[i], NULL);
|
kobil_close(serial->port[i]);
|
||||||
kfree(usb_get_serial_port_data(serial->port[i]));
|
kfree(usb_get_serial_port_data(serial->port[i]));
|
||||||
usb_set_serial_port_data(serial->port[i], NULL);
|
usb_set_serial_port_data(serial->port[i], NULL);
|
||||||
}
|
}
|
||||||
|
@ -346,11 +345,11 @@ static int kobil_open(struct tty_struct *tty,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void kobil_close(struct tty_struct *tty,
|
static void kobil_close(struct usb_serial_port *port)
|
||||||
struct usb_serial_port *port, struct file *filp)
|
|
||||||
{
|
{
|
||||||
dbg("%s - port %d", __func__, port->number);
|
dbg("%s - port %d", __func__, port->number);
|
||||||
|
|
||||||
|
/* FIXME: Add rts/dtr methods */
|
||||||
if (port->write_urb) {
|
if (port->write_urb) {
|
||||||
usb_kill_urb(port->write_urb);
|
usb_kill_urb(port->write_urb);
|
||||||
usb_free_urb(port->write_urb);
|
usb_free_urb(port->write_urb);
|
||||||
|
|
|
@ -95,8 +95,8 @@ static int mct_u232_startup(struct usb_serial *serial);
|
||||||
static void mct_u232_shutdown(struct usb_serial *serial);
|
static void mct_u232_shutdown(struct usb_serial *serial);
|
||||||
static int mct_u232_open(struct tty_struct *tty,
|
static int mct_u232_open(struct tty_struct *tty,
|
||||||
struct usb_serial_port *port, struct file *filp);
|
struct usb_serial_port *port, struct file *filp);
|
||||||
static void mct_u232_close(struct tty_struct *tty,
|
static void mct_u232_close(struct usb_serial_port *port);
|
||||||
struct usb_serial_port *port, struct file *filp);
|
static void mct_u232_dtr_rts(struct usb_serial_port *port, int on);
|
||||||
static void mct_u232_read_int_callback(struct urb *urb);
|
static void mct_u232_read_int_callback(struct urb *urb);
|
||||||
static void mct_u232_set_termios(struct tty_struct *tty,
|
static void mct_u232_set_termios(struct tty_struct *tty,
|
||||||
struct usb_serial_port *port, struct ktermios *old);
|
struct usb_serial_port *port, struct ktermios *old);
|
||||||
|
@ -140,6 +140,7 @@ static struct usb_serial_driver mct_u232_device = {
|
||||||
.num_ports = 1,
|
.num_ports = 1,
|
||||||
.open = mct_u232_open,
|
.open = mct_u232_open,
|
||||||
.close = mct_u232_close,
|
.close = mct_u232_close,
|
||||||
|
.dtr_rts = mct_u232_dtr_rts,
|
||||||
.throttle = mct_u232_throttle,
|
.throttle = mct_u232_throttle,
|
||||||
.unthrottle = mct_u232_unthrottle,
|
.unthrottle = mct_u232_unthrottle,
|
||||||
.read_int_callback = mct_u232_read_int_callback,
|
.read_int_callback = mct_u232_read_int_callback,
|
||||||
|
@ -496,29 +497,29 @@ error:
|
||||||
return retval;
|
return retval;
|
||||||
} /* mct_u232_open */
|
} /* mct_u232_open */
|
||||||
|
|
||||||
|
static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)
|
||||||
static void mct_u232_close(struct tty_struct *tty,
|
|
||||||
struct usb_serial_port *port, struct file *filp)
|
|
||||||
{
|
{
|
||||||
unsigned int c_cflag;
|
|
||||||
unsigned int control_state;
|
unsigned int control_state;
|
||||||
struct mct_u232_private *priv = usb_get_serial_port_data(port);
|
struct mct_u232_private *priv = usb_get_serial_port_data(port);
|
||||||
dbg("%s port %d", __func__, port->number);
|
|
||||||
|
|
||||||
if (tty) {
|
|
||||||
c_cflag = tty->termios->c_cflag;
|
|
||||||
mutex_lock(&port->serial->disc_mutex);
|
mutex_lock(&port->serial->disc_mutex);
|
||||||
if (c_cflag & HUPCL && !port->serial->disconnected) {
|
if (!port->serial->disconnected) {
|
||||||
/* drop DTR and RTS */
|
/* drop DTR and RTS */
|
||||||
spin_lock_irq(&priv->lock);
|
spin_lock_irq(&priv->lock);
|
||||||
|
if (on)
|
||||||
|
priv->control_state |= TIOCM_DTR | TIOCM_RTS;
|
||||||
|
else
|
||||||
priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
|
priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
|
||||||
control_state = priv->control_state;
|
control_state = priv->control_state;
|
||||||
spin_unlock_irq(&priv->lock);
|
spin_unlock_irq(&priv->lock);
|
||||||
mct_u232_set_modem_ctrl(port->serial, control_state);
|
mct_u232_set_modem_ctrl(port->serial, control_state);
|
||||||
}
|
}
|
||||||
mutex_unlock(&port->serial->disc_mutex);
|
mutex_unlock(&port->serial->disc_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mct_u232_close(struct usb_serial_port *port)
|
||||||
|
{
|
||||||
|
dbg("%s port %d", __func__, port->number);
|
||||||
|
|
||||||
if (port->serial->dev) {
|
if (port->serial->dev) {
|
||||||
/* shutdown our urbs */
|
/* shutdown our urbs */
|
||||||
|
|
|
@ -533,8 +533,7 @@ static int mos7720_chars_in_buffer(struct tty_struct *tty)
|
||||||
return chars;
|
return chars;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mos7720_close(struct tty_struct *tty,
|
static void mos7720_close(struct usb_serial_port *port)
|
||||||
struct usb_serial_port *port, struct file *filp)
|
|
||||||
{
|
{
|
||||||
struct usb_serial *serial;
|
struct usb_serial *serial;
|
||||||
struct moschip_port *mos7720_port;
|
struct moschip_port *mos7720_port;
|
||||||
|
|
|
@ -1135,54 +1135,12 @@ static int mos7840_chars_in_buffer(struct tty_struct *tty)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
|
||||||
*
|
|
||||||
* mos7840_block_until_tx_empty
|
|
||||||
*
|
|
||||||
* This function will block the close until one of the following:
|
|
||||||
* 1. TX count are 0
|
|
||||||
* 2. The mos7840 has stopped
|
|
||||||
* 3. A timeout of 3 seconds without activity has expired
|
|
||||||
*
|
|
||||||
************************************************************************/
|
|
||||||
static void mos7840_block_until_tx_empty(struct tty_struct *tty,
|
|
||||||
struct moschip_port *mos7840_port)
|
|
||||||
{
|
|
||||||
int timeout = HZ / 10;
|
|
||||||
int wait = 30;
|
|
||||||
int count;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
|
|
||||||
count = mos7840_chars_in_buffer(tty);
|
|
||||||
|
|
||||||
/* Check for Buffer status */
|
|
||||||
if (count <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Block the thread for a while */
|
|
||||||
interruptible_sleep_on_timeout(&mos7840_port->wait_chase,
|
|
||||||
timeout);
|
|
||||||
|
|
||||||
/* No activity.. count down section */
|
|
||||||
wait--;
|
|
||||||
if (wait == 0) {
|
|
||||||
dbg("%s - TIMEOUT", __func__);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
/* Reset timeout value back to seconds */
|
|
||||||
wait = 30;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* mos7840_close
|
* mos7840_close
|
||||||
* this function is called by the tty driver when a port is closed
|
* this function is called by the tty driver when a port is closed
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
static void mos7840_close(struct tty_struct *tty,
|
static void mos7840_close(struct usb_serial_port *port)
|
||||||
struct usb_serial_port *port, struct file *filp)
|
|
||||||
{
|
{
|
||||||
struct usb_serial *serial;
|
struct usb_serial *serial;
|
||||||
struct moschip_port *mos7840_port;
|
struct moschip_port *mos7840_port;
|
||||||
|
@ -1223,10 +1181,6 @@ static void mos7840_close(struct tty_struct *tty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serial->dev)
|
|
||||||
/* flush and block until tx is empty */
|
|
||||||
mos7840_block_until_tx_empty(tty, mos7840_port);
|
|
||||||
|
|
||||||
/* While closing port, shutdown all bulk read, write *
|
/* While closing port, shutdown all bulk read, write *
|
||||||
* and interrupt read if they exists */
|
* and interrupt read if they exists */
|
||||||
if (serial->dev) {
|
if (serial->dev) {
|
||||||
|
|
|
@ -98,8 +98,7 @@ static int navman_open(struct tty_struct *tty,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void navman_close(struct tty_struct *tty,
|
static void navman_close(struct usb_serial_port *port)
|
||||||
struct usb_serial_port *port, struct file *filp)
|
|
||||||
{
|
{
|
||||||
dbg("%s - port %d", __func__, port->number);
|
dbg("%s - port %d", __func__, port->number);
|
||||||
|
|
||||||
|
|
|
@ -66,8 +66,7 @@ static int debug;
|
||||||
/* function prototypes */
|
/* function prototypes */
|
||||||
static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port,
|
static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
struct file *filp);
|
struct file *filp);
|
||||||
static void omninet_close(struct tty_struct *tty, struct usb_serial_port *port,
|
static void omninet_close(struct usb_serial_port *port);
|
||||||
struct file *filp);
|
|
||||||
static void omninet_read_bulk_callback(struct urb *urb);
|
static void omninet_read_bulk_callback(struct urb *urb);
|
||||||
static void omninet_write_bulk_callback(struct urb *urb);
|
static void omninet_write_bulk_callback(struct urb *urb);
|
||||||
static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
|
static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
|
@ -189,8 +188,7 @@ static int omninet_open(struct tty_struct *tty,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void omninet_close(struct tty_struct *tty,
|
static void omninet_close(struct usb_serial_port *port)
|
||||||
struct usb_serial_port *port, struct file *filp)
|
|
||||||
{
|
{
|
||||||
dbg("%s - port %d", __func__, port->number);
|
dbg("%s - port %d", __func__, port->number);
|
||||||
usb_kill_urb(port->read_urb);
|
usb_kill_urb(port->read_urb);
|
||||||
|
|
|
@ -173,8 +173,7 @@ static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void opticon_close(struct tty_struct *tty, struct usb_serial_port *port,
|
static void opticon_close(struct usb_serial_port *port)
|
||||||
struct file *filp)
|
|
||||||
{
|
{
|
||||||
struct opticon_private *priv = usb_get_serial_data(port->serial);
|
struct opticon_private *priv = usb_get_serial_data(port->serial);
|
||||||
|
|
||||||
|
|
|
@ -45,8 +45,9 @@
|
||||||
/* Function prototypes */
|
/* Function prototypes */
|
||||||
static int option_open(struct tty_struct *tty, struct usb_serial_port *port,
|
static int option_open(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
struct file *filp);
|
struct file *filp);
|
||||||
static void option_close(struct tty_struct *tty, struct usb_serial_port *port,
|
static void option_close(struct usb_serial_port *port);
|
||||||
struct file *filp);
|
static void option_dtr_rts(struct usb_serial_port *port, int on);
|
||||||
|
|
||||||
static int option_startup(struct usb_serial *serial);
|
static int option_startup(struct usb_serial *serial);
|
||||||
static void option_shutdown(struct usb_serial *serial);
|
static void option_shutdown(struct usb_serial *serial);
|
||||||
static int option_write_room(struct tty_struct *tty);
|
static int option_write_room(struct tty_struct *tty);
|
||||||
|
@ -61,7 +62,7 @@ static void option_set_termios(struct tty_struct *tty,
|
||||||
static int option_tiocmget(struct tty_struct *tty, struct file *file);
|
static int option_tiocmget(struct tty_struct *tty, struct file *file);
|
||||||
static int option_tiocmset(struct tty_struct *tty, struct file *file,
|
static int option_tiocmset(struct tty_struct *tty, struct file *file,
|
||||||
unsigned int set, unsigned int clear);
|
unsigned int set, unsigned int clear);
|
||||||
static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *port);
|
static int option_send_setup(struct usb_serial_port *port);
|
||||||
static int option_suspend(struct usb_serial *serial, pm_message_t message);
|
static int option_suspend(struct usb_serial *serial, pm_message_t message);
|
||||||
static int option_resume(struct usb_serial *serial);
|
static int option_resume(struct usb_serial *serial);
|
||||||
|
|
||||||
|
@ -551,6 +552,7 @@ static struct usb_serial_driver option_1port_device = {
|
||||||
.num_ports = 1,
|
.num_ports = 1,
|
||||||
.open = option_open,
|
.open = option_open,
|
||||||
.close = option_close,
|
.close = option_close,
|
||||||
|
.dtr_rts = option_dtr_rts,
|
||||||
.write = option_write,
|
.write = option_write,
|
||||||
.write_room = option_write_room,
|
.write_room = option_write_room,
|
||||||
.chars_in_buffer = option_chars_in_buffer,
|
.chars_in_buffer = option_chars_in_buffer,
|
||||||
|
@ -630,7 +632,7 @@ static void option_set_termios(struct tty_struct *tty,
|
||||||
dbg("%s", __func__);
|
dbg("%s", __func__);
|
||||||
/* Doesn't support option setting */
|
/* Doesn't support option setting */
|
||||||
tty_termios_copy_hw(tty->termios, old_termios);
|
tty_termios_copy_hw(tty->termios, old_termios);
|
||||||
option_send_setup(tty, port);
|
option_send_setup(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int option_tiocmget(struct tty_struct *tty, struct file *file)
|
static int option_tiocmget(struct tty_struct *tty, struct file *file)
|
||||||
|
@ -669,7 +671,7 @@ static int option_tiocmset(struct tty_struct *tty, struct file *file,
|
||||||
portdata->rts_state = 0;
|
portdata->rts_state = 0;
|
||||||
if (clear & TIOCM_DTR)
|
if (clear & TIOCM_DTR)
|
||||||
portdata->dtr_state = 0;
|
portdata->dtr_state = 0;
|
||||||
return option_send_setup(tty, port);
|
return option_send_setup(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write */
|
/* Write */
|
||||||
|
@ -897,10 +899,6 @@ static int option_open(struct tty_struct *tty,
|
||||||
|
|
||||||
dbg("%s", __func__);
|
dbg("%s", __func__);
|
||||||
|
|
||||||
/* Set some sane defaults */
|
|
||||||
portdata->rts_state = 1;
|
|
||||||
portdata->dtr_state = 1;
|
|
||||||
|
|
||||||
/* Reset low level data toggle and start reading from endpoints */
|
/* Reset low level data toggle and start reading from endpoints */
|
||||||
for (i = 0; i < N_IN_URB; i++) {
|
for (i = 0; i < N_IN_URB; i++) {
|
||||||
urb = portdata->in_urbs[i];
|
urb = portdata->in_urbs[i];
|
||||||
|
@ -936,13 +934,28 @@ static int option_open(struct tty_struct *tty,
|
||||||
usb_pipeout(urb->pipe), 0); */
|
usb_pipeout(urb->pipe), 0); */
|
||||||
}
|
}
|
||||||
|
|
||||||
option_send_setup(tty, port);
|
option_send_setup(port);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void option_close(struct tty_struct *tty,
|
static void option_dtr_rts(struct usb_serial_port *port, int on)
|
||||||
struct usb_serial_port *port, struct file *filp)
|
{
|
||||||
|
struct usb_serial *serial = port->serial;
|
||||||
|
struct option_port_private *portdata;
|
||||||
|
|
||||||
|
dbg("%s", __func__);
|
||||||
|
portdata = usb_get_serial_port_data(port);
|
||||||
|
mutex_lock(&serial->disc_mutex);
|
||||||
|
portdata->rts_state = on;
|
||||||
|
portdata->dtr_state = on;
|
||||||
|
if (serial->dev)
|
||||||
|
option_send_setup(port);
|
||||||
|
mutex_unlock(&serial->disc_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void option_close(struct usb_serial_port *port)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct usb_serial *serial = port->serial;
|
struct usb_serial *serial = port->serial;
|
||||||
|
@ -951,22 +964,13 @@ static void option_close(struct tty_struct *tty,
|
||||||
dbg("%s", __func__);
|
dbg("%s", __func__);
|
||||||
portdata = usb_get_serial_port_data(port);
|
portdata = usb_get_serial_port_data(port);
|
||||||
|
|
||||||
portdata->rts_state = 0;
|
|
||||||
portdata->dtr_state = 0;
|
|
||||||
|
|
||||||
if (serial->dev) {
|
if (serial->dev) {
|
||||||
mutex_lock(&serial->disc_mutex);
|
|
||||||
if (!serial->disconnected)
|
|
||||||
option_send_setup(tty, port);
|
|
||||||
mutex_unlock(&serial->disc_mutex);
|
|
||||||
|
|
||||||
/* Stop reading/writing urbs */
|
/* Stop reading/writing urbs */
|
||||||
for (i = 0; i < N_IN_URB; i++)
|
for (i = 0; i < N_IN_URB; i++)
|
||||||
usb_kill_urb(portdata->in_urbs[i]);
|
usb_kill_urb(portdata->in_urbs[i]);
|
||||||
for (i = 0; i < N_OUT_URB; i++)
|
for (i = 0; i < N_OUT_URB; i++)
|
||||||
usb_kill_urb(portdata->out_urbs[i]);
|
usb_kill_urb(portdata->out_urbs[i]);
|
||||||
}
|
}
|
||||||
tty_port_tty_set(&port->port, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper functions used by option_setup_urbs */
|
/* Helper functions used by option_setup_urbs */
|
||||||
|
@ -1032,18 +1036,16 @@ static void option_setup_urbs(struct usb_serial *serial)
|
||||||
* This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN
|
* This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN
|
||||||
* CDC.
|
* CDC.
|
||||||
*/
|
*/
|
||||||
static int option_send_setup(struct tty_struct *tty,
|
static int option_send_setup(struct usb_serial_port *port)
|
||||||
struct usb_serial_port *port)
|
|
||||||
{
|
{
|
||||||
struct usb_serial *serial = port->serial;
|
struct usb_serial *serial = port->serial;
|
||||||
struct option_port_private *portdata;
|
struct option_port_private *portdata;
|
||||||
int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
|
int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
|
||||||
|
int val = 0;
|
||||||
dbg("%s", __func__);
|
dbg("%s", __func__);
|
||||||
|
|
||||||
portdata = usb_get_serial_port_data(port);
|
portdata = usb_get_serial_port_data(port);
|
||||||
|
|
||||||
if (tty) {
|
|
||||||
int val = 0;
|
|
||||||
if (portdata->dtr_state)
|
if (portdata->dtr_state)
|
||||||
val |= 0x01;
|
val |= 0x01;
|
||||||
if (portdata->rts_state)
|
if (portdata->rts_state)
|
||||||
|
@ -1052,8 +1054,6 @@ static int option_send_setup(struct tty_struct *tty,
|
||||||
return usb_control_msg(serial->dev,
|
return usb_control_msg(serial->dev,
|
||||||
usb_rcvctrlpipe(serial->dev, 0),
|
usb_rcvctrlpipe(serial->dev, 0),
|
||||||
0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT);
|
0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT);
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int option_startup(struct usb_serial *serial)
|
static int option_startup(struct usb_serial *serial)
|
||||||
|
|
|
@ -143,8 +143,7 @@ struct oti6858_control_pkt {
|
||||||
/* function prototypes */
|
/* function prototypes */
|
||||||
static int oti6858_open(struct tty_struct *tty,
|
static int oti6858_open(struct tty_struct *tty,
|
||||||
struct usb_serial_port *port, struct file *filp);
|
struct usb_serial_port *port, struct file *filp);
|
||||||
static void oti6858_close(struct tty_struct *tty,
|
static void oti6858_close(struct usb_serial_port *port);
|
||||||
struct usb_serial_port *port, struct file *filp);
|
|
||||||
static void oti6858_set_termios(struct tty_struct *tty,
|
static void oti6858_set_termios(struct tty_struct *tty,
|
||||||
struct usb_serial_port *port, struct ktermios *old);
|
struct usb_serial_port *port, struct ktermios *old);
|
||||||
static int oti6858_ioctl(struct tty_struct *tty, struct file *file,
|
static int oti6858_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
|
@ -622,67 +621,30 @@ static int oti6858_open(struct tty_struct *tty,
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
dev_err(&port->dev, "%s(): usb_submit_urb() failed"
|
dev_err(&port->dev, "%s(): usb_submit_urb() failed"
|
||||||
" with error %d\n", __func__, result);
|
" with error %d\n", __func__, result);
|
||||||
oti6858_close(tty, port, NULL);
|
oti6858_close(port);
|
||||||
return -EPROTO;
|
return -EPROTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* setup termios */
|
/* setup termios */
|
||||||
if (tty)
|
if (tty)
|
||||||
oti6858_set_termios(tty, port, &tmp_termios);
|
oti6858_set_termios(tty, port, &tmp_termios);
|
||||||
|
port->port.drain_delay = 256; /* FIXME: check the FIFO length */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void oti6858_close(struct tty_struct *tty,
|
static void oti6858_close(struct usb_serial_port *port)
|
||||||
struct usb_serial_port *port, struct file *filp)
|
|
||||||
{
|
{
|
||||||
struct oti6858_private *priv = usb_get_serial_port_data(port);
|
struct oti6858_private *priv = usb_get_serial_port_data(port);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
long timeout;
|
|
||||||
wait_queue_t wait;
|
|
||||||
|
|
||||||
dbg("%s(port = %d)", __func__, port->number);
|
dbg("%s(port = %d)", __func__, port->number);
|
||||||
|
|
||||||
/* wait for data to drain from the buffer */
|
|
||||||
spin_lock_irqsave(&priv->lock, flags);
|
spin_lock_irqsave(&priv->lock, flags);
|
||||||
timeout = 30 * HZ; /* PL2303_CLOSING_WAIT */
|
|
||||||
init_waitqueue_entry(&wait, current);
|
|
||||||
add_wait_queue(&tty->write_wait, &wait);
|
|
||||||
dbg("%s(): entering wait loop", __func__);
|
|
||||||
for (;;) {
|
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
|
||||||
if (oti6858_buf_data_avail(priv->buf) == 0
|
|
||||||
|| timeout == 0 || signal_pending(current)
|
|
||||||
|| port->serial->disconnected)
|
|
||||||
break;
|
|
||||||
spin_unlock_irqrestore(&priv->lock, flags);
|
|
||||||
timeout = schedule_timeout(timeout);
|
|
||||||
spin_lock_irqsave(&priv->lock, flags);
|
|
||||||
}
|
|
||||||
set_current_state(TASK_RUNNING);
|
|
||||||
remove_wait_queue(&tty->write_wait, &wait);
|
|
||||||
dbg("%s(): after wait loop", __func__);
|
|
||||||
|
|
||||||
/* clear out any remaining data in the buffer */
|
/* clear out any remaining data in the buffer */
|
||||||
oti6858_buf_clear(priv->buf);
|
oti6858_buf_clear(priv->buf);
|
||||||
spin_unlock_irqrestore(&priv->lock, flags);
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
|
||||||
/* wait for characters to drain from the device */
|
dbg("%s(): after buf_clear()", __func__);
|
||||||
/* (this is long enough for the entire 256 byte */
|
|
||||||
/* pl2303 hardware buffer to drain with no flow */
|
|
||||||
/* control for data rates of 1200 bps or more, */
|
|
||||||
/* for lower rates we should really know how much */
|
|
||||||
/* data is in the buffer to compute a delay */
|
|
||||||
/* that is not unnecessarily long) */
|
|
||||||
/* FIXME
|
|
||||||
bps = tty_get_baud_rate(tty);
|
|
||||||
if (bps > 1200)
|
|
||||||
timeout = max((HZ*2560)/bps,HZ/10);
|
|
||||||
else
|
|
||||||
*/
|
|
||||||
timeout = 2*HZ;
|
|
||||||
schedule_timeout_interruptible(timeout);
|
|
||||||
dbg("%s(): after schedule_timeout_interruptible()", __func__);
|
|
||||||
|
|
||||||
/* cancel scheduled setup */
|
/* cancel scheduled setup */
|
||||||
cancel_delayed_work(&priv->delayed_setup_work);
|
cancel_delayed_work(&priv->delayed_setup_work);
|
||||||
|
@ -694,15 +656,6 @@ static void oti6858_close(struct tty_struct *tty,
|
||||||
usb_kill_urb(port->write_urb);
|
usb_kill_urb(port->write_urb);
|
||||||
usb_kill_urb(port->read_urb);
|
usb_kill_urb(port->read_urb);
|
||||||
usb_kill_urb(port->interrupt_in_urb);
|
usb_kill_urb(port->interrupt_in_urb);
|
||||||
|
|
||||||
/*
|
|
||||||
if (tty && (tty->termios->c_cflag) & HUPCL) {
|
|
||||||
// drop DTR and RTS
|
|
||||||
spin_lock_irqsave(&priv->lock, flags);
|
|
||||||
priv->pending_setup.control &= ~CONTROL_MASK;
|
|
||||||
spin_unlock_irqrestore(&priv->lock, flags);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int oti6858_tiocmset(struct tty_struct *tty, struct file *file,
|
static int oti6858_tiocmset(struct tty_struct *tty, struct file *file,
|
||||||
|
|
|
@ -652,69 +652,41 @@ static void pl2303_set_termios(struct tty_struct *tty,
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pl2303_close(struct tty_struct *tty,
|
static void pl2303_dtr_rts(struct usb_serial_port *port, int on)
|
||||||
struct usb_serial_port *port, struct file *filp)
|
{
|
||||||
|
struct pl2303_private *priv = usb_get_serial_port_data(port);
|
||||||
|
unsigned long flags;
|
||||||
|
u8 control;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&priv->lock, flags);
|
||||||
|
/* Change DTR and RTS */
|
||||||
|
if (on)
|
||||||
|
priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
|
||||||
|
else
|
||||||
|
priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
|
||||||
|
control = priv->line_control;
|
||||||
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
set_control_lines(port->serial->dev, control);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pl2303_close(struct usb_serial_port *port)
|
||||||
{
|
{
|
||||||
struct pl2303_private *priv = usb_get_serial_port_data(port);
|
struct pl2303_private *priv = usb_get_serial_port_data(port);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned int c_cflag;
|
|
||||||
int bps;
|
|
||||||
long timeout;
|
|
||||||
wait_queue_t wait;
|
|
||||||
|
|
||||||
dbg("%s - port %d", __func__, port->number);
|
dbg("%s - port %d", __func__, port->number);
|
||||||
|
|
||||||
/* wait for data to drain from the buffer */
|
|
||||||
spin_lock_irqsave(&priv->lock, flags);
|
spin_lock_irqsave(&priv->lock, flags);
|
||||||
timeout = PL2303_CLOSING_WAIT;
|
|
||||||
init_waitqueue_entry(&wait, current);
|
|
||||||
add_wait_queue(&tty->write_wait, &wait);
|
|
||||||
for (;;) {
|
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
|
||||||
if (pl2303_buf_data_avail(priv->buf) == 0 ||
|
|
||||||
timeout == 0 || signal_pending(current) ||
|
|
||||||
port->serial->disconnected)
|
|
||||||
break;
|
|
||||||
spin_unlock_irqrestore(&priv->lock, flags);
|
|
||||||
timeout = schedule_timeout(timeout);
|
|
||||||
spin_lock_irqsave(&priv->lock, flags);
|
|
||||||
}
|
|
||||||
set_current_state(TASK_RUNNING);
|
|
||||||
remove_wait_queue(&tty->write_wait, &wait);
|
|
||||||
/* clear out any remaining data in the buffer */
|
/* clear out any remaining data in the buffer */
|
||||||
pl2303_buf_clear(priv->buf);
|
pl2303_buf_clear(priv->buf);
|
||||||
spin_unlock_irqrestore(&priv->lock, flags);
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
|
||||||
/* wait for characters to drain from the device */
|
|
||||||
/* (this is long enough for the entire 256 byte */
|
|
||||||
/* pl2303 hardware buffer to drain with no flow */
|
|
||||||
/* control for data rates of 1200 bps or more, */
|
|
||||||
/* for lower rates we should really know how much */
|
|
||||||
/* data is in the buffer to compute a delay */
|
|
||||||
/* that is not unnecessarily long) */
|
|
||||||
bps = tty_get_baud_rate(tty);
|
|
||||||
if (bps > 1200)
|
|
||||||
timeout = max((HZ*2560)/bps, HZ/10);
|
|
||||||
else
|
|
||||||
timeout = 2*HZ;
|
|
||||||
schedule_timeout_interruptible(timeout);
|
|
||||||
|
|
||||||
/* shutdown our urbs */
|
/* shutdown our urbs */
|
||||||
dbg("%s - shutting down urbs", __func__);
|
dbg("%s - shutting down urbs", __func__);
|
||||||
usb_kill_urb(port->write_urb);
|
usb_kill_urb(port->write_urb);
|
||||||
usb_kill_urb(port->read_urb);
|
usb_kill_urb(port->read_urb);
|
||||||
usb_kill_urb(port->interrupt_in_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);
|
|
||||||
set_control_lines(port->serial->dev, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pl2303_open(struct tty_struct *tty,
|
static int pl2303_open(struct tty_struct *tty,
|
||||||
|
@ -748,7 +720,7 @@ static int pl2303_open(struct tty_struct *tty,
|
||||||
if (result) {
|
if (result) {
|
||||||
dev_err(&port->dev, "%s - failed submitting read urb,"
|
dev_err(&port->dev, "%s - failed submitting read urb,"
|
||||||
" error %d\n", __func__, result);
|
" error %d\n", __func__, result);
|
||||||
pl2303_close(tty, port, NULL);
|
pl2303_close(port);
|
||||||
return -EPROTO;
|
return -EPROTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,9 +730,10 @@ static int pl2303_open(struct tty_struct *tty,
|
||||||
if (result) {
|
if (result) {
|
||||||
dev_err(&port->dev, "%s - failed submitting interrupt urb,"
|
dev_err(&port->dev, "%s - failed submitting interrupt urb,"
|
||||||
" error %d\n", __func__, result);
|
" error %d\n", __func__, result);
|
||||||
pl2303_close(tty, port, NULL);
|
pl2303_close(port);
|
||||||
return -EPROTO;
|
return -EPROTO;
|
||||||
}
|
}
|
||||||
|
port->port.drain_delay = 256;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -821,6 +794,14 @@ static int pl2303_tiocmget(struct tty_struct *tty, struct file *file)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pl2303_carrier_raised(struct usb_serial_port *port)
|
||||||
|
{
|
||||||
|
struct pl2303_private *priv = usb_get_serial_port_data(port);
|
||||||
|
if (priv->line_status & UART_DCD)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
|
static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
|
||||||
{
|
{
|
||||||
struct pl2303_private *priv = usb_get_serial_port_data(port);
|
struct pl2303_private *priv = usb_get_serial_port_data(port);
|
||||||
|
@ -1125,6 +1106,8 @@ static struct usb_serial_driver pl2303_device = {
|
||||||
.num_ports = 1,
|
.num_ports = 1,
|
||||||
.open = pl2303_open,
|
.open = pl2303_open,
|
||||||
.close = pl2303_close,
|
.close = pl2303_close,
|
||||||
|
.dtr_rts = pl2303_dtr_rts,
|
||||||
|
.carrier_raised = pl2303_carrier_raised,
|
||||||
.write = pl2303_write,
|
.write = pl2303_write,
|
||||||
.ioctl = pl2303_ioctl,
|
.ioctl = pl2303_ioctl,
|
||||||
.break_ctl = pl2303_break_ctl,
|
.break_ctl = pl2303_break_ctl,
|
||||||
|
|
|
@ -240,40 +240,26 @@ struct sierra_port_private {
|
||||||
int ri_state;
|
int ri_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int sierra_send_setup(struct tty_struct *tty,
|
static int sierra_send_setup(struct usb_serial_port *port)
|
||||||
struct usb_serial_port *port)
|
|
||||||
{
|
{
|
||||||
struct usb_serial *serial = port->serial;
|
struct usb_serial *serial = port->serial;
|
||||||
struct sierra_port_private *portdata;
|
struct sierra_port_private *portdata;
|
||||||
__u16 interface = 0;
|
__u16 interface = 0;
|
||||||
|
int val = 0;
|
||||||
|
|
||||||
dev_dbg(&port->dev, "%s", __func__);
|
dev_dbg(&port->dev, "%s", __func__);
|
||||||
|
|
||||||
portdata = usb_get_serial_port_data(port);
|
portdata = usb_get_serial_port_data(port);
|
||||||
|
|
||||||
if (tty) {
|
|
||||||
int val = 0;
|
|
||||||
if (portdata->dtr_state)
|
if (portdata->dtr_state)
|
||||||
val |= 0x01;
|
val |= 0x01;
|
||||||
if (portdata->rts_state)
|
if (portdata->rts_state)
|
||||||
val |= 0x02;
|
val |= 0x02;
|
||||||
|
|
||||||
/* If composite device then properly report interface */
|
/* If composite device then properly report interface */
|
||||||
if (serial->num_ports == 1) {
|
if (serial->num_ports == 1)
|
||||||
interface = sierra_calc_interface(serial);
|
interface = sierra_calc_interface(serial);
|
||||||
|
|
||||||
/* Control message is sent only to interfaces with
|
|
||||||
* interrupt_in endpoints
|
|
||||||
*/
|
|
||||||
if (port->interrupt_in_urb) {
|
|
||||||
/* send control message */
|
|
||||||
return usb_control_msg(serial->dev,
|
|
||||||
usb_rcvctrlpipe(serial->dev, 0),
|
|
||||||
0x22, 0x21, val, interface,
|
|
||||||
NULL, 0, USB_CTRL_SET_TIMEOUT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise the need to do non-composite mapping */
|
/* Otherwise the need to do non-composite mapping */
|
||||||
else {
|
else {
|
||||||
if (port->bulk_out_endpointAddress == 2)
|
if (port->bulk_out_endpointAddress == 2)
|
||||||
|
@ -282,15 +268,11 @@ static int sierra_send_setup(struct tty_struct *tty,
|
||||||
interface = 1;
|
interface = 1;
|
||||||
else if (port->bulk_out_endpointAddress == 5)
|
else if (port->bulk_out_endpointAddress == 5)
|
||||||
interface = 2;
|
interface = 2;
|
||||||
|
}
|
||||||
return usb_control_msg(serial->dev,
|
return usb_control_msg(serial->dev,
|
||||||
usb_rcvctrlpipe(serial->dev, 0),
|
usb_rcvctrlpipe(serial->dev, 0),
|
||||||
0x22, 0x21, val, interface,
|
0x22, 0x21, val, interface,
|
||||||
NULL, 0, USB_CTRL_SET_TIMEOUT);
|
NULL, 0, USB_CTRL_SET_TIMEOUT);
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,7 +281,7 @@ static void sierra_set_termios(struct tty_struct *tty,
|
||||||
{
|
{
|
||||||
dev_dbg(&port->dev, "%s", __func__);
|
dev_dbg(&port->dev, "%s", __func__);
|
||||||
tty_termios_copy_hw(tty->termios, old_termios);
|
tty_termios_copy_hw(tty->termios, old_termios);
|
||||||
sierra_send_setup(tty, port);
|
sierra_send_setup(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sierra_tiocmget(struct tty_struct *tty, struct file *file)
|
static int sierra_tiocmget(struct tty_struct *tty, struct file *file)
|
||||||
|
@ -338,7 +320,7 @@ static int sierra_tiocmset(struct tty_struct *tty, struct file *file,
|
||||||
portdata->rts_state = 0;
|
portdata->rts_state = 0;
|
||||||
if (clear & TIOCM_DTR)
|
if (clear & TIOCM_DTR)
|
||||||
portdata->dtr_state = 0;
|
portdata->dtr_state = 0;
|
||||||
return sierra_send_setup(tty, port);
|
return sierra_send_setup(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sierra_outdat_callback(struct urb *urb)
|
static void sierra_outdat_callback(struct urb *urb)
|
||||||
|
@ -598,7 +580,7 @@ static int sierra_open(struct tty_struct *tty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sierra_send_setup(tty, port);
|
sierra_send_setup(port);
|
||||||
|
|
||||||
/* start up the interrupt endpoint if we have one */
|
/* start up the interrupt endpoint if we have one */
|
||||||
if (port->interrupt_in_urb) {
|
if (port->interrupt_in_urb) {
|
||||||
|
@ -610,8 +592,24 @@ static int sierra_open(struct tty_struct *tty,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sierra_close(struct tty_struct *tty,
|
static void sierra_dtr_rts(struct usb_serial_port *port, int on)
|
||||||
struct usb_serial_port *port, struct file *filp)
|
{
|
||||||
|
struct usb_serial *serial = port->serial;
|
||||||
|
struct sierra_port_private *portdata;
|
||||||
|
|
||||||
|
portdata = usb_get_serial_port_data(port);
|
||||||
|
portdata->rts_state = on;
|
||||||
|
portdata->dtr_state = on;
|
||||||
|
|
||||||
|
if (serial->dev) {
|
||||||
|
mutex_lock(&serial->disc_mutex);
|
||||||
|
if (!serial->disconnected)
|
||||||
|
sierra_send_setup(port);
|
||||||
|
mutex_unlock(&serial->disc_mutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sierra_close(struct usb_serial_port *port)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct usb_serial *serial = port->serial;
|
struct usb_serial *serial = port->serial;
|
||||||
|
@ -620,22 +618,12 @@ static void sierra_close(struct tty_struct *tty,
|
||||||
dev_dbg(&port->dev, "%s", __func__);
|
dev_dbg(&port->dev, "%s", __func__);
|
||||||
portdata = usb_get_serial_port_data(port);
|
portdata = usb_get_serial_port_data(port);
|
||||||
|
|
||||||
portdata->rts_state = 0;
|
|
||||||
portdata->dtr_state = 0;
|
|
||||||
|
|
||||||
if (serial->dev) {
|
if (serial->dev) {
|
||||||
mutex_lock(&serial->disc_mutex);
|
|
||||||
if (!serial->disconnected)
|
|
||||||
sierra_send_setup(tty, port);
|
|
||||||
mutex_unlock(&serial->disc_mutex);
|
|
||||||
|
|
||||||
/* Stop reading/writing urbs */
|
/* Stop reading/writing urbs */
|
||||||
for (i = 0; i < N_IN_URB; i++)
|
for (i = 0; i < N_IN_URB; i++)
|
||||||
usb_kill_urb(portdata->in_urbs[i]);
|
usb_kill_urb(portdata->in_urbs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_kill_urb(port->interrupt_in_urb);
|
usb_kill_urb(port->interrupt_in_urb);
|
||||||
tty_port_tty_set(&port->port, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sierra_startup(struct usb_serial *serial)
|
static int sierra_startup(struct usb_serial *serial)
|
||||||
|
@ -737,6 +725,7 @@ static struct usb_serial_driver sierra_device = {
|
||||||
.probe = sierra_probe,
|
.probe = sierra_probe,
|
||||||
.open = sierra_open,
|
.open = sierra_open,
|
||||||
.close = sierra_close,
|
.close = sierra_close,
|
||||||
|
.dtr_rts = sierra_dtr_rts,
|
||||||
.write = sierra_write,
|
.write = sierra_write,
|
||||||
.write_room = sierra_write_room,
|
.write_room = sierra_write_room,
|
||||||
.set_termios = sierra_set_termios,
|
.set_termios = sierra_set_termios,
|
||||||
|
|
|
@ -446,66 +446,47 @@ static void spcp8x5_set_workMode(struct usb_device *dev, u16 value,
|
||||||
"RTSCTS usb_control_msg(enable flowctrl) = %d\n", ret);
|
"RTSCTS usb_control_msg(enable flowctrl) = %d\n", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* close the serial port. We should wait for data sending to device 1st and
|
static int spcp8x5_carrier_raised(struct usb_serial_port *port)
|
||||||
* then kill all urb. */
|
{
|
||||||
static void spcp8x5_close(struct tty_struct *tty,
|
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
|
||||||
struct usb_serial_port *port, struct file *filp)
|
if (priv->line_status & MSR_STATUS_LINE_DCD)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void spcp8x5_dtr_rts(struct usb_serial_port *port, int on)
|
||||||
|
{
|
||||||
|
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
|
||||||
|
unsigned long flags;
|
||||||
|
u8 control;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&priv->lock, flags);
|
||||||
|
if (on)
|
||||||
|
priv->line_control = MCR_CONTROL_LINE_DTR
|
||||||
|
| MCR_CONTROL_LINE_RTS;
|
||||||
|
else
|
||||||
|
priv->line_control &= ~ (MCR_CONTROL_LINE_DTR
|
||||||
|
| MCR_CONTROL_LINE_RTS);
|
||||||
|
control = priv->line_control;
|
||||||
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* close the serial port. We should wait for data sending to device 1st and
|
||||||
|
* then kill all urb. */
|
||||||
|
static void spcp8x5_close(struct usb_serial_port *port)
|
||||||
{
|
{
|
||||||
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
|
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned int c_cflag;
|
|
||||||
int bps;
|
|
||||||
long timeout;
|
|
||||||
wait_queue_t wait;
|
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
dbg("%s - port %d", __func__, port->number);
|
dbg("%s - port %d", __func__, port->number);
|
||||||
|
|
||||||
/* wait for data to drain from the buffer */
|
|
||||||
spin_lock_irqsave(&priv->lock, flags);
|
spin_lock_irqsave(&priv->lock, flags);
|
||||||
timeout = SPCP8x5_CLOSING_WAIT;
|
|
||||||
init_waitqueue_entry(&wait, current);
|
|
||||||
add_wait_queue(&tty->write_wait, &wait);
|
|
||||||
for (;;) {
|
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
|
||||||
if (ringbuf_avail_data(priv->buf) == 0 ||
|
|
||||||
timeout == 0 || signal_pending(current))
|
|
||||||
break;
|
|
||||||
spin_unlock_irqrestore(&priv->lock, flags);
|
|
||||||
timeout = schedule_timeout(timeout);
|
|
||||||
spin_lock_irqsave(&priv->lock, flags);
|
|
||||||
}
|
|
||||||
set_current_state(TASK_RUNNING);
|
|
||||||
remove_wait_queue(&tty->write_wait, &wait);
|
|
||||||
|
|
||||||
/* clear out any remaining data in the buffer */
|
/* clear out any remaining data in the buffer */
|
||||||
clear_ringbuf(priv->buf);
|
clear_ringbuf(priv->buf);
|
||||||
spin_unlock_irqrestore(&priv->lock, flags);
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
|
||||||
/* wait for characters to drain from the device (this is long enough
|
|
||||||
* for the entire all byte spcp8x5 hardware buffer to drain with no
|
|
||||||
* flow control for data rates of 1200 bps or more, for lower rates we
|
|
||||||
* should really know how much data is in the buffer to compute a delay
|
|
||||||
* that is not unnecessarily long) */
|
|
||||||
bps = tty_get_baud_rate(tty);
|
|
||||||
if (bps > 1200)
|
|
||||||
timeout = max((HZ*2560) / bps, HZ/10);
|
|
||||||
else
|
|
||||||
timeout = 2*HZ;
|
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
|
||||||
schedule_timeout(timeout);
|
|
||||||
|
|
||||||
/* clear control lines */
|
|
||||||
if (tty) {
|
|
||||||
c_cflag = tty->termios->c_cflag;
|
|
||||||
if (c_cflag & HUPCL) {
|
|
||||||
spin_lock_irqsave(&priv->lock, flags);
|
|
||||||
priv->line_control = 0;
|
|
||||||
spin_unlock_irqrestore(&priv->lock, flags);
|
|
||||||
spcp8x5_set_ctrlLine(port->serial->dev, 0 , priv->type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* kill urb */
|
/* kill urb */
|
||||||
if (port->write_urb != NULL) {
|
if (port->write_urb != NULL) {
|
||||||
result = usb_unlink_urb(port->write_urb);
|
result = usb_unlink_urb(port->write_urb);
|
||||||
|
@ -665,13 +646,6 @@ static int spcp8x5_open(struct tty_struct *tty,
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
spin_lock_irqsave(&priv->lock, flags);
|
|
||||||
if (tty && (tty->termios->c_cflag & CBAUD))
|
|
||||||
priv->line_control = MCR_DTR | MCR_RTS;
|
|
||||||
else
|
|
||||||
priv->line_control = 0;
|
|
||||||
spin_unlock_irqrestore(&priv->lock, flags);
|
|
||||||
|
|
||||||
spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type);
|
spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type);
|
||||||
|
|
||||||
/* Setup termios */
|
/* Setup termios */
|
||||||
|
@ -691,9 +665,10 @@ static int spcp8x5_open(struct tty_struct *tty,
|
||||||
port->read_urb->dev = serial->dev;
|
port->read_urb->dev = serial->dev;
|
||||||
ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
|
ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
spcp8x5_close(tty, port, NULL);
|
spcp8x5_close(port);
|
||||||
return -EPROTO;
|
return -EPROTO;
|
||||||
}
|
}
|
||||||
|
port->port.drain_delay = 256;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1033,6 +1008,8 @@ static struct usb_serial_driver spcp8x5_device = {
|
||||||
.num_ports = 1,
|
.num_ports = 1,
|
||||||
.open = spcp8x5_open,
|
.open = spcp8x5_open,
|
||||||
.close = spcp8x5_close,
|
.close = spcp8x5_close,
|
||||||
|
.dtr_rts = spcp8x5_dtr_rts,
|
||||||
|
.carrier_raised = spcp8x5_carrier_raised,
|
||||||
.write = spcp8x5_write,
|
.write = spcp8x5_write,
|
||||||
.set_termios = spcp8x5_set_termios,
|
.set_termios = spcp8x5_set_termios,
|
||||||
.ioctl = spcp8x5_ioctl,
|
.ioctl = spcp8x5_ioctl,
|
||||||
|
|
|
@ -152,8 +152,7 @@ static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void symbol_close(struct tty_struct *tty, struct usb_serial_port *port,
|
static void symbol_close(struct usb_serial_port *port)
|
||||||
struct file *filp)
|
|
||||||
{
|
{
|
||||||
struct symbol_private *priv = usb_get_serial_data(port->serial);
|
struct symbol_private *priv = usb_get_serial_data(port->serial);
|
||||||
|
|
||||||
|
|
|
@ -100,8 +100,7 @@ static int ti_startup(struct usb_serial *serial);
|
||||||
static void ti_shutdown(struct usb_serial *serial);
|
static void ti_shutdown(struct usb_serial *serial);
|
||||||
static int ti_open(struct tty_struct *tty, struct usb_serial_port *port,
|
static int ti_open(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
struct file *file);
|
struct file *file);
|
||||||
static void ti_close(struct tty_struct *tty, struct usb_serial_port *port,
|
static void ti_close(struct usb_serial_port *port);
|
||||||
struct file *file);
|
|
||||||
static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
|
static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
const unsigned char *data, int count);
|
const unsigned char *data, int count);
|
||||||
static int ti_write_room(struct tty_struct *tty);
|
static int ti_write_room(struct tty_struct *tty);
|
||||||
|
@ -647,8 +646,7 @@ release_lock:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ti_close(struct tty_struct *tty, struct usb_serial_port *port,
|
static void ti_close(struct usb_serial_port *port)
|
||||||
struct file *file)
|
|
||||||
{
|
{
|
||||||
struct ti_device *tdev;
|
struct ti_device *tdev;
|
||||||
struct ti_port *tport;
|
struct ti_port *tport;
|
||||||
|
|
|
@ -238,8 +238,10 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
|
||||||
goto bailout_interface_put;
|
goto bailout_interface_put;
|
||||||
mutex_unlock(&serial->disc_mutex);
|
mutex_unlock(&serial->disc_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&port->mutex);
|
mutex_unlock(&port->mutex);
|
||||||
|
/* Now do the correct tty layer semantics */
|
||||||
|
retval = tty_port_block_til_ready(&port->port, tty, filp);
|
||||||
|
if (retval == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
bailout_interface_put:
|
bailout_interface_put:
|
||||||
|
@ -259,66 +261,91 @@ bailout_serial_put:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serial_close(struct tty_struct *tty, struct file *filp)
|
/**
|
||||||
|
* serial_do_down - shut down hardware
|
||||||
|
* @port: port to shut down
|
||||||
|
*
|
||||||
|
* Shut down a USB port unless it is the console. We never shut down the
|
||||||
|
* console hardware as it will always be in use.
|
||||||
|
*
|
||||||
|
* Don't free any resources at this point
|
||||||
|
*/
|
||||||
|
static void serial_do_down(struct usb_serial_port *port)
|
||||||
{
|
{
|
||||||
struct usb_serial_port *port = tty->driver_data;
|
struct usb_serial_driver *drv = port->serial->type;
|
||||||
struct usb_serial *serial;
|
struct usb_serial *serial;
|
||||||
struct module *owner;
|
struct module *owner;
|
||||||
int count;
|
|
||||||
|
|
||||||
if (!port)
|
/* The console is magical, do not hang up the console hardware
|
||||||
|
or there will be tears */
|
||||||
|
if (port->console)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dbg("%s - port %d", __func__, port->number);
|
|
||||||
|
|
||||||
mutex_lock(&port->mutex);
|
mutex_lock(&port->mutex);
|
||||||
serial = port->serial;
|
serial = port->serial;
|
||||||
owner = serial->type->driver.owner;
|
owner = serial->type->driver.owner;
|
||||||
|
|
||||||
if (port->port.count == 0) {
|
if (drv->close)
|
||||||
mutex_unlock(&port->mutex);
|
drv->close(port);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (port->port.count == 1)
|
mutex_unlock(&port->mutex);
|
||||||
/* only call the device specific close if this
|
}
|
||||||
* port is being closed by the last owner. Ensure we do
|
|
||||||
* this before we drop the port count. The call is protected
|
/**
|
||||||
* by the port mutex
|
* serial_do_free - free resources post close/hangup
|
||||||
|
* @port: port to free up
|
||||||
|
*
|
||||||
|
* Do the resource freeing and refcount dropping for the port. We must
|
||||||
|
* be careful about ordering and we must avoid freeing up the console.
|
||||||
*/
|
*/
|
||||||
serial->type->close(tty, port, filp);
|
|
||||||
|
|
||||||
if (port->port.count == (port->console ? 2 : 1)) {
|
static void serial_do_free(struct usb_serial_port *port)
|
||||||
struct tty_struct *tty = tty_port_tty_get(&port->port);
|
{
|
||||||
if (tty) {
|
struct usb_serial *serial;
|
||||||
/* We must do this before we drop the port count to
|
struct module *owner;
|
||||||
zero. */
|
|
||||||
if (tty->driver_data)
|
|
||||||
tty->driver_data = NULL;
|
|
||||||
tty_port_tty_set(&port->port, NULL);
|
|
||||||
tty_kref_put(tty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
--port->port.count;
|
/* The console is magical, do not hang up the console hardware
|
||||||
count = port->port.count;
|
or there will be tears */
|
||||||
mutex_unlock(&port->mutex);
|
if (port->console)
|
||||||
|
return;
|
||||||
|
|
||||||
|
serial = port->serial;
|
||||||
|
owner = serial->type->driver.owner;
|
||||||
put_device(&port->dev);
|
put_device(&port->dev);
|
||||||
|
|
||||||
/* Mustn't dereference port any more */
|
/* Mustn't dereference port any more */
|
||||||
if (count == 0) {
|
|
||||||
mutex_lock(&serial->disc_mutex);
|
mutex_lock(&serial->disc_mutex);
|
||||||
if (!serial->disconnected)
|
if (!serial->disconnected)
|
||||||
usb_autopm_put_interface(serial->interface);
|
usb_autopm_put_interface(serial->interface);
|
||||||
mutex_unlock(&serial->disc_mutex);
|
mutex_unlock(&serial->disc_mutex);
|
||||||
}
|
|
||||||
usb_serial_put(serial);
|
usb_serial_put(serial);
|
||||||
|
|
||||||
/* Mustn't dereference serial any more */
|
/* Mustn't dereference serial any more */
|
||||||
if (count == 0)
|
|
||||||
module_put(owner);
|
module_put(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void serial_close(struct tty_struct *tty, struct file *filp)
|
||||||
|
{
|
||||||
|
struct usb_serial_port *port = tty->driver_data;
|
||||||
|
|
||||||
|
dbg("%s - port %d", __func__, port->number);
|
||||||
|
|
||||||
|
|
||||||
|
if (tty_port_close_start(&port->port, tty, filp) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
serial_do_down(port);
|
||||||
|
tty_port_close_end(&port->port, tty);
|
||||||
|
tty_port_tty_set(&port->port, NULL);
|
||||||
|
serial_do_free(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void serial_hangup(struct tty_struct *tty)
|
||||||
|
{
|
||||||
|
struct usb_serial_port *port = tty->driver_data;
|
||||||
|
serial_do_down(port);
|
||||||
|
tty_port_hangup(&port->port);
|
||||||
|
serial_do_free(port);
|
||||||
|
}
|
||||||
|
|
||||||
static int serial_write(struct tty_struct *tty, const unsigned char *buf,
|
static int serial_write(struct tty_struct *tty, const unsigned char *buf,
|
||||||
int count)
|
int count)
|
||||||
{
|
{
|
||||||
|
@ -648,6 +675,29 @@ static struct usb_serial_driver *search_serial_device(
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int serial_carrier_raised(struct tty_port *port)
|
||||||
|
{
|
||||||
|
struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
|
||||||
|
struct usb_serial_driver *drv = p->serial->type;
|
||||||
|
if (drv->carrier_raised)
|
||||||
|
return drv->carrier_raised(p);
|
||||||
|
/* No carrier control - don't block */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void serial_dtr_rts(struct tty_port *port, int on)
|
||||||
|
{
|
||||||
|
struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
|
||||||
|
struct usb_serial_driver *drv = p->serial->type;
|
||||||
|
if (drv->dtr_rts)
|
||||||
|
drv->dtr_rts(p, on);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct tty_port_operations serial_port_ops = {
|
||||||
|
.carrier_raised = serial_carrier_raised,
|
||||||
|
.dtr_rts = serial_dtr_rts,
|
||||||
|
};
|
||||||
|
|
||||||
int usb_serial_probe(struct usb_interface *interface,
|
int usb_serial_probe(struct usb_interface *interface,
|
||||||
const struct usb_device_id *id)
|
const struct usb_device_id *id)
|
||||||
{
|
{
|
||||||
|
@ -841,6 +891,7 @@ int usb_serial_probe(struct usb_interface *interface,
|
||||||
if (!port)
|
if (!port)
|
||||||
goto probe_error;
|
goto probe_error;
|
||||||
tty_port_init(&port->port);
|
tty_port_init(&port->port);
|
||||||
|
port->port.ops = &serial_port_ops;
|
||||||
port->serial = serial;
|
port->serial = serial;
|
||||||
spin_lock_init(&port->lock);
|
spin_lock_init(&port->lock);
|
||||||
mutex_init(&port->mutex);
|
mutex_init(&port->mutex);
|
||||||
|
@ -1071,6 +1122,9 @@ void usb_serial_disconnect(struct usb_interface *interface)
|
||||||
if (port) {
|
if (port) {
|
||||||
struct tty_struct *tty = tty_port_tty_get(&port->port);
|
struct tty_struct *tty = tty_port_tty_get(&port->port);
|
||||||
if (tty) {
|
if (tty) {
|
||||||
|
/* The hangup will occur asynchronously but
|
||||||
|
the object refcounts will sort out all the
|
||||||
|
cleanup */
|
||||||
tty_hangup(tty);
|
tty_hangup(tty);
|
||||||
tty_kref_put(tty);
|
tty_kref_put(tty);
|
||||||
}
|
}
|
||||||
|
@ -1135,6 +1189,7 @@ static const struct tty_operations serial_ops = {
|
||||||
.open = serial_open,
|
.open = serial_open,
|
||||||
.close = serial_close,
|
.close = serial_close,
|
||||||
.write = serial_write,
|
.write = serial_write,
|
||||||
|
.hangup = serial_hangup,
|
||||||
.write_room = serial_write_room,
|
.write_room = serial_write_room,
|
||||||
.ioctl = serial_ioctl,
|
.ioctl = serial_ioctl,
|
||||||
.set_termios = serial_set_termios,
|
.set_termios = serial_set_termios,
|
||||||
|
@ -1147,6 +1202,7 @@ static const struct tty_operations serial_ops = {
|
||||||
.proc_fops = &serial_proc_fops,
|
.proc_fops = &serial_proc_fops,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct tty_driver *usb_serial_tty_driver;
|
struct tty_driver *usb_serial_tty_driver;
|
||||||
|
|
||||||
static int __init usb_serial_init(void)
|
static int __init usb_serial_init(void)
|
||||||
|
|
|
@ -38,8 +38,7 @@
|
||||||
/* function prototypes for a handspring visor */
|
/* function prototypes for a handspring visor */
|
||||||
static int visor_open(struct tty_struct *tty, struct usb_serial_port *port,
|
static int visor_open(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
struct file *filp);
|
struct file *filp);
|
||||||
static void visor_close(struct tty_struct *tty, struct usb_serial_port *port,
|
static void visor_close(struct usb_serial_port *port);
|
||||||
struct file *filp);
|
|
||||||
static int visor_write(struct tty_struct *tty, struct usb_serial_port *port,
|
static int visor_write(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
const unsigned char *buf, int count);
|
const unsigned char *buf, int count);
|
||||||
static int visor_write_room(struct tty_struct *tty);
|
static int visor_write_room(struct tty_struct *tty);
|
||||||
|
@ -324,8 +323,7 @@ exit:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void visor_close(struct tty_struct *tty,
|
static void visor_close(struct usb_serial_port *port)
|
||||||
struct usb_serial_port *port, struct file *filp)
|
|
||||||
{
|
{
|
||||||
struct visor_private *priv = usb_get_serial_port_data(port);
|
struct visor_private *priv = usb_get_serial_port_data(port);
|
||||||
unsigned char *transfer_buffer;
|
unsigned char *transfer_buffer;
|
||||||
|
|
|
@ -147,8 +147,7 @@ static int whiteheat_attach(struct usb_serial *serial);
|
||||||
static void whiteheat_shutdown(struct usb_serial *serial);
|
static void whiteheat_shutdown(struct usb_serial *serial);
|
||||||
static int whiteheat_open(struct tty_struct *tty,
|
static int whiteheat_open(struct tty_struct *tty,
|
||||||
struct usb_serial_port *port, struct file *filp);
|
struct usb_serial_port *port, struct file *filp);
|
||||||
static void whiteheat_close(struct tty_struct *tty,
|
static void whiteheat_close(struct usb_serial_port *port);
|
||||||
struct usb_serial_port *port, struct file *filp);
|
|
||||||
static int whiteheat_write(struct tty_struct *tty,
|
static int whiteheat_write(struct tty_struct *tty,
|
||||||
struct usb_serial_port *port,
|
struct usb_serial_port *port,
|
||||||
const unsigned char *buf, int count);
|
const unsigned char *buf, int count);
|
||||||
|
@ -712,8 +711,7 @@ exit:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void whiteheat_close(struct tty_struct *tty,
|
static void whiteheat_close(struct usb_serial_port *port)
|
||||||
struct usb_serial_port *port, struct file *filp)
|
|
||||||
{
|
{
|
||||||
struct whiteheat_private *info = usb_get_serial_port_data(port);
|
struct whiteheat_private *info = usb_get_serial_port_data(port);
|
||||||
struct whiteheat_urb_wrap *wrap;
|
struct whiteheat_urb_wrap *wrap;
|
||||||
|
@ -723,31 +721,7 @@ static void whiteheat_close(struct tty_struct *tty,
|
||||||
|
|
||||||
dbg("%s - port %d", __func__, port->number);
|
dbg("%s - port %d", __func__, port->number);
|
||||||
|
|
||||||
mutex_lock(&port->serial->disc_mutex);
|
|
||||||
/* filp is NULL when called from usb_serial_disconnect */
|
|
||||||
if ((filp && (tty_hung_up_p(filp))) || port->serial->disconnected) {
|
|
||||||
mutex_unlock(&port->serial->disc_mutex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mutex_unlock(&port->serial->disc_mutex);
|
|
||||||
|
|
||||||
tty->closing = 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Not currently in use; tty_wait_until_sent() calls
|
|
||||||
* serial_chars_in_buffer() which deadlocks on the second semaphore
|
|
||||||
* acquisition. This should be fixed at some point. Greg's been
|
|
||||||
* notified.
|
|
||||||
if ((filp->f_flags & (O_NDELAY | O_NONBLOCK)) == 0) {
|
|
||||||
tty_wait_until_sent(tty, CLOSING_DELAY);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
tty_driver_flush_buffer(tty);
|
|
||||||
tty_ldisc_flush(tty);
|
|
||||||
|
|
||||||
firm_report_tx_done(port);
|
firm_report_tx_done(port);
|
||||||
|
|
||||||
firm_close(port);
|
firm_close(port);
|
||||||
|
|
||||||
/* shutdown our bulk reads and writes */
|
/* shutdown our bulk reads and writes */
|
||||||
|
@ -775,10 +749,7 @@ static void whiteheat_close(struct tty_struct *tty,
|
||||||
}
|
}
|
||||||
spin_unlock_irq(&info->lock);
|
spin_unlock_irq(&info->lock);
|
||||||
mutex_unlock(&info->deathwarrant);
|
mutex_unlock(&info->deathwarrant);
|
||||||
|
|
||||||
stop_command_port(port->serial);
|
stop_command_port(port->serial);
|
||||||
|
|
||||||
tty->closing = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -224,8 +224,7 @@ struct usb_serial_driver {
|
||||||
/* Called by console with tty = NULL and by tty */
|
/* Called by console with tty = NULL and by tty */
|
||||||
int (*open)(struct tty_struct *tty,
|
int (*open)(struct tty_struct *tty,
|
||||||
struct usb_serial_port *port, struct file *filp);
|
struct usb_serial_port *port, struct file *filp);
|
||||||
void (*close)(struct tty_struct *tty,
|
void (*close)(struct usb_serial_port *port);
|
||||||
struct usb_serial_port *port, struct file *filp);
|
|
||||||
int (*write)(struct tty_struct *tty, struct usb_serial_port *port,
|
int (*write)(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
const unsigned char *buf, int count);
|
const unsigned char *buf, int count);
|
||||||
/* Called only by the tty layer */
|
/* Called only by the tty layer */
|
||||||
|
@ -241,6 +240,10 @@ struct usb_serial_driver {
|
||||||
int (*tiocmget)(struct tty_struct *tty, struct file *file);
|
int (*tiocmget)(struct tty_struct *tty, struct file *file);
|
||||||
int (*tiocmset)(struct tty_struct *tty, struct file *file,
|
int (*tiocmset)(struct tty_struct *tty, struct file *file,
|
||||||
unsigned int set, unsigned int clear);
|
unsigned int set, unsigned int clear);
|
||||||
|
/* Called by the tty layer for port level work. There may or may not
|
||||||
|
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);
|
||||||
/* USB events */
|
/* USB events */
|
||||||
void (*read_int_callback)(struct urb *urb);
|
void (*read_int_callback)(struct urb *urb);
|
||||||
void (*write_int_callback)(struct urb *urb);
|
void (*write_int_callback)(struct urb *urb);
|
||||||
|
@ -283,8 +286,7 @@ extern int usb_serial_generic_open(struct tty_struct *tty,
|
||||||
struct usb_serial_port *port, struct file *filp);
|
struct usb_serial_port *port, struct file *filp);
|
||||||
extern int usb_serial_generic_write(struct tty_struct *tty,
|
extern int usb_serial_generic_write(struct tty_struct *tty,
|
||||||
struct usb_serial_port *port, const unsigned char *buf, int count);
|
struct usb_serial_port *port, const unsigned char *buf, int count);
|
||||||
extern void usb_serial_generic_close(struct tty_struct *tty,
|
extern void usb_serial_generic_close(struct usb_serial_port *port);
|
||||||
struct usb_serial_port *port, struct file *filp);
|
|
||||||
extern int usb_serial_generic_resume(struct usb_serial *serial);
|
extern int usb_serial_generic_resume(struct usb_serial *serial);
|
||||||
extern int usb_serial_generic_write_room(struct tty_struct *tty);
|
extern int usb_serial_generic_write_room(struct tty_struct *tty);
|
||||||
extern int usb_serial_generic_chars_in_buffer(struct tty_struct *tty);
|
extern int usb_serial_generic_chars_in_buffer(struct tty_struct *tty);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче