USB: belkin_sa: implement line status handling
Use process_read_urb to implement line status handling. Compile-only tested. Signed-off-by: Johan Hovold <jhovold@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Родитель
f2f8b7fe5a
Коммит
2afd8287c6
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2000 William Greathouse (wgreathouse@smva.com)
|
||||
* Copyright (C) 2000-2001 Greg Kroah-Hartman (greg@kroah.com)
|
||||
* Copyright (C) 2010 Johan Hovold (jhovold@gmail.com)
|
||||
*
|
||||
* This program is largely derived from work by the linux-usb group
|
||||
* and associated source files. Please see the usb/serial files for
|
||||
|
@ -84,7 +85,7 @@ static int debug;
|
|||
/*
|
||||
* Version Information
|
||||
*/
|
||||
#define DRIVER_VERSION "v1.2"
|
||||
#define DRIVER_VERSION "v1.3"
|
||||
#define DRIVER_AUTHOR "William Greathouse <wgreathouse@smva.com>"
|
||||
#define DRIVER_DESC "USB Belkin Serial converter driver"
|
||||
|
||||
|
@ -95,6 +96,7 @@ static int belkin_sa_open(struct tty_struct *tty,
|
|||
struct usb_serial_port *port);
|
||||
static void belkin_sa_close(struct usb_serial_port *port);
|
||||
static void belkin_sa_read_int_callback(struct urb *urb);
|
||||
static void belkin_sa_process_read_urb(struct urb *urb);
|
||||
static void belkin_sa_set_termios(struct tty_struct *tty,
|
||||
struct usb_serial_port *port, struct ktermios * old);
|
||||
static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state);
|
||||
|
@ -135,7 +137,7 @@ static struct usb_serial_driver belkin_device = {
|
|||
.open = belkin_sa_open,
|
||||
.close = belkin_sa_close,
|
||||
.read_int_callback = belkin_sa_read_int_callback,
|
||||
/* How we get the status info */
|
||||
.process_read_urb = belkin_sa_process_read_urb,
|
||||
.set_termios = belkin_sa_set_termios,
|
||||
.break_ctl = belkin_sa_break_ctl,
|
||||
.tiocmget = belkin_sa_tiocmget,
|
||||
|
@ -289,31 +291,7 @@ static void belkin_sa_read_int_callback(struct urb *urb)
|
|||
else
|
||||
priv->control_state &= ~TIOCM_CD;
|
||||
|
||||
/* Now to report any errors */
|
||||
priv->last_lsr = data[BELKIN_SA_LSR_INDEX];
|
||||
#if 0
|
||||
/*
|
||||
* fill in the flip buffer here, but I do not know the relation
|
||||
* to the current/next receive buffer or characters. I need
|
||||
* to look in to this before committing any code.
|
||||
*/
|
||||
if (priv->last_lsr & BELKIN_SA_LSR_ERR) {
|
||||
tty = tty_port_tty_get(&port->port);
|
||||
/* Overrun Error */
|
||||
if (priv->last_lsr & BELKIN_SA_LSR_OE) {
|
||||
}
|
||||
/* Parity Error */
|
||||
if (priv->last_lsr & BELKIN_SA_LSR_PE) {
|
||||
}
|
||||
/* Framing Error */
|
||||
if (priv->last_lsr & BELKIN_SA_LSR_FE) {
|
||||
}
|
||||
/* Break Indicator */
|
||||
if (priv->last_lsr & BELKIN_SA_LSR_BI) {
|
||||
}
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
#endif
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
exit:
|
||||
retval = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
|
@ -322,6 +300,53 @@ exit:
|
|||
"result %d\n", __func__, retval);
|
||||
}
|
||||
|
||||
static void belkin_sa_process_read_urb(struct urb *urb)
|
||||
{
|
||||
struct usb_serial_port *port = urb->context;
|
||||
struct belkin_sa_private *priv = usb_get_serial_port_data(port);
|
||||
struct tty_struct *tty;
|
||||
unsigned char *data = urb->transfer_buffer;
|
||||
unsigned long flags;
|
||||
unsigned char status;
|
||||
char tty_flag;
|
||||
|
||||
/* Update line status */
|
||||
tty_flag = TTY_NORMAL;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
status = priv->last_lsr;
|
||||
priv->last_lsr &= ~BELKIN_SA_LSR_ERR;
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
if (!urb->actual_length)
|
||||
return;
|
||||
|
||||
tty = tty_port_tty_get(&port->port);
|
||||
if (!tty)
|
||||
return;
|
||||
|
||||
if (status & BELKIN_SA_LSR_ERR) {
|
||||
/* Break takes precedence over parity, which takes precedence
|
||||
* over framing errors. */
|
||||
if (status & BELKIN_SA_LSR_BI)
|
||||
tty_flag = TTY_BREAK;
|
||||
else if (status & BELKIN_SA_LSR_PE)
|
||||
tty_flag = TTY_PARITY;
|
||||
else if (status & BELKIN_SA_LSR_FE)
|
||||
tty_flag = TTY_FRAME;
|
||||
dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag);
|
||||
|
||||
/* Overrun is special, not associated with a char. */
|
||||
if (status & BELKIN_SA_LSR_OE)
|
||||
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
|
||||
}
|
||||
|
||||
tty_insert_flip_string_fixed_flag(tty, data, tty_flag,
|
||||
urb->actual_length);
|
||||
tty_flip_buffer_push(tty);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
||||
static void belkin_sa_set_termios(struct tty_struct *tty,
|
||||
struct usb_serial_port *port, struct ktermios *old_termios)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче