|
@@ -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)
|
|
|
{
|