[PATCH 205/229] USB: belkin_sa: implement line status handling

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Johan Hovold <jhovold@xxxxxxxxx>

Use process_read_urb to implement line status handling.

Compile-only tested.

Signed-off-by: Johan Hovold <jhovold@xxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>
---
 drivers/usb/serial/belkin_sa.c |   77 ++++++++++++++++++++++++++-------------
 1 files changed, 51 insertions(+), 26 deletions(-)

diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index c396736..36df352 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2000		William Greathouse (wgreathouse@xxxxxxxx)
  *  Copyright (C) 2000-2001 	Greg Kroah-Hartman (greg@xxxxxxxxx)
+ *  Copyright (C) 2010		Johan Hovold (jhovold@xxxxxxxxx)
  *
  *  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@xxxxxxxx>"
 #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)
 {
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux