diff options
| author | Johan Hovold <jhovold@gmail.com> | 2010-05-15 11:53:53 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-05-20 16:21:48 -0400 |
| commit | 2afd8287c6e2ac6c1affb46d009cfd866dffed77 (patch) | |
| tree | 0222e5ebe9c2a7b1ec415de20cec222700f0d646 | |
| parent | f2f8b7fe5a7542df8e3c906fcc9897b596bbf1fc (diff) | |
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>
| -rw-r--r-- | 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 c39673608c35..36df35295db2 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2000 William Greathouse (wgreathouse@smva.com) | 4 | * Copyright (C) 2000 William Greathouse (wgreathouse@smva.com) |
| 5 | * Copyright (C) 2000-2001 Greg Kroah-Hartman (greg@kroah.com) | 5 | * Copyright (C) 2000-2001 Greg Kroah-Hartman (greg@kroah.com) |
| 6 | * Copyright (C) 2010 Johan Hovold (jhovold@gmail.com) | ||
| 6 | * | 7 | * |
| 7 | * This program is largely derived from work by the linux-usb group | 8 | * This program is largely derived from work by the linux-usb group |
| 8 | * and associated source files. Please see the usb/serial files for | 9 | * and associated source files. Please see the usb/serial files for |
| @@ -84,7 +85,7 @@ static int debug; | |||
| 84 | /* | 85 | /* |
| 85 | * Version Information | 86 | * Version Information |
| 86 | */ | 87 | */ |
| 87 | #define DRIVER_VERSION "v1.2" | 88 | #define DRIVER_VERSION "v1.3" |
| 88 | #define DRIVER_AUTHOR "William Greathouse <wgreathouse@smva.com>" | 89 | #define DRIVER_AUTHOR "William Greathouse <wgreathouse@smva.com>" |
| 89 | #define DRIVER_DESC "USB Belkin Serial converter driver" | 90 | #define DRIVER_DESC "USB Belkin Serial converter driver" |
| 90 | 91 | ||
| @@ -95,6 +96,7 @@ static int belkin_sa_open(struct tty_struct *tty, | |||
| 95 | struct usb_serial_port *port); | 96 | struct usb_serial_port *port); |
| 96 | static void belkin_sa_close(struct usb_serial_port *port); | 97 | static void belkin_sa_close(struct usb_serial_port *port); |
| 97 | static void belkin_sa_read_int_callback(struct urb *urb); | 98 | static void belkin_sa_read_int_callback(struct urb *urb); |
| 99 | static void belkin_sa_process_read_urb(struct urb *urb); | ||
| 98 | static void belkin_sa_set_termios(struct tty_struct *tty, | 100 | static void belkin_sa_set_termios(struct tty_struct *tty, |
| 99 | struct usb_serial_port *port, struct ktermios * old); | 101 | struct usb_serial_port *port, struct ktermios * old); |
| 100 | static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state); | 102 | static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state); |
| @@ -135,7 +137,7 @@ static struct usb_serial_driver belkin_device = { | |||
| 135 | .open = belkin_sa_open, | 137 | .open = belkin_sa_open, |
| 136 | .close = belkin_sa_close, | 138 | .close = belkin_sa_close, |
| 137 | .read_int_callback = belkin_sa_read_int_callback, | 139 | .read_int_callback = belkin_sa_read_int_callback, |
| 138 | /* How we get the status info */ | 140 | .process_read_urb = belkin_sa_process_read_urb, |
| 139 | .set_termios = belkin_sa_set_termios, | 141 | .set_termios = belkin_sa_set_termios, |
| 140 | .break_ctl = belkin_sa_break_ctl, | 142 | .break_ctl = belkin_sa_break_ctl, |
| 141 | .tiocmget = belkin_sa_tiocmget, | 143 | .tiocmget = belkin_sa_tiocmget, |
| @@ -289,31 +291,7 @@ static void belkin_sa_read_int_callback(struct urb *urb) | |||
| 289 | else | 291 | else |
| 290 | priv->control_state &= ~TIOCM_CD; | 292 | priv->control_state &= ~TIOCM_CD; |
| 291 | 293 | ||
| 292 | /* Now to report any errors */ | ||
| 293 | priv->last_lsr = data[BELKIN_SA_LSR_INDEX]; | 294 | priv->last_lsr = data[BELKIN_SA_LSR_INDEX]; |
| 294 | #if 0 | ||
| 295 | /* | ||
| 296 | * fill in the flip buffer here, but I do not know the relation | ||
| 297 | * to the current/next receive buffer or characters. I need | ||
| 298 | * to look in to this before committing any code. | ||
| 299 | */ | ||
| 300 | if (priv->last_lsr & BELKIN_SA_LSR_ERR) { | ||
| 301 | tty = tty_port_tty_get(&port->port); | ||
| 302 | /* Overrun Error */ | ||
| 303 | if (priv->last_lsr & BELKIN_SA_LSR_OE) { | ||
| 304 | } | ||
| 305 | /* Parity Error */ | ||
| 306 | if (priv->last_lsr & BELKIN_SA_LSR_PE) { | ||
| 307 | } | ||
| 308 | /* Framing Error */ | ||
| 309 | if (priv->last_lsr & BELKIN_SA_LSR_FE) { | ||
| 310 | } | ||
| 311 | /* Break Indicator */ | ||
| 312 | if (priv->last_lsr & BELKIN_SA_LSR_BI) { | ||
| 313 | } | ||
| 314 | tty_kref_put(tty); | ||
| 315 | } | ||
| 316 | #endif | ||
| 317 | spin_unlock_irqrestore(&priv->lock, flags); | 295 | spin_unlock_irqrestore(&priv->lock, flags); |
| 318 | exit: | 296 | exit: |
| 319 | retval = usb_submit_urb(urb, GFP_ATOMIC); | 297 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
| @@ -322,6 +300,53 @@ exit: | |||
| 322 | "result %d\n", __func__, retval); | 300 | "result %d\n", __func__, retval); |
| 323 | } | 301 | } |
| 324 | 302 | ||
| 303 | static void belkin_sa_process_read_urb(struct urb *urb) | ||
| 304 | { | ||
| 305 | struct usb_serial_port *port = urb->context; | ||
| 306 | struct belkin_sa_private *priv = usb_get_serial_port_data(port); | ||
| 307 | struct tty_struct *tty; | ||
| 308 | unsigned char *data = urb->transfer_buffer; | ||
| 309 | unsigned long flags; | ||
| 310 | unsigned char status; | ||
| 311 | char tty_flag; | ||
| 312 | |||
| 313 | /* Update line status */ | ||
| 314 | tty_flag = TTY_NORMAL; | ||
| 315 | |||
| 316 | spin_lock_irqsave(&priv->lock, flags); | ||
| 317 | status = priv->last_lsr; | ||
| 318 | priv->last_lsr &= ~BELKIN_SA_LSR_ERR; | ||
| 319 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 320 | |||
| 321 | if (!urb->actual_length) | ||
| 322 | return; | ||
| 323 | |||
| 324 | tty = tty_port_tty_get(&port->port); | ||
| 325 | if (!tty) | ||
| 326 | return; | ||
| 327 | |||
| 328 | if (status & BELKIN_SA_LSR_ERR) { | ||
| 329 | /* Break takes precedence over parity, which takes precedence | ||
| 330 | * over framing errors. */ | ||
| 331 | if (status & BELKIN_SA_LSR_BI) | ||
| 332 | tty_flag = TTY_BREAK; | ||
| 333 | else if (status & BELKIN_SA_LSR_PE) | ||
| 334 | tty_flag = TTY_PARITY; | ||
| 335 | else if (status & BELKIN_SA_LSR_FE) | ||
| 336 | tty_flag = TTY_FRAME; | ||
| 337 | dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag); | ||
| 338 | |||
| 339 | /* Overrun is special, not associated with a char. */ | ||
| 340 | if (status & BELKIN_SA_LSR_OE) | ||
| 341 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | ||
| 342 | } | ||
| 343 | |||
| 344 | tty_insert_flip_string_fixed_flag(tty, data, tty_flag, | ||
| 345 | urb->actual_length); | ||
| 346 | tty_flip_buffer_push(tty); | ||
| 347 | tty_kref_put(tty); | ||
| 348 | } | ||
| 349 | |||
| 325 | static void belkin_sa_set_termios(struct tty_struct *tty, | 350 | static void belkin_sa_set_termios(struct tty_struct *tty, |
| 326 | struct usb_serial_port *port, struct ktermios *old_termios) | 351 | struct usb_serial_port *port, struct ktermios *old_termios) |
| 327 | { | 352 | { |
