Loading drivers/usb/serial/ark3116.c +194 −0 Original line number Diff line number Diff line Loading @@ -605,6 +605,198 @@ static void ark3116_break_ctl(struct tty_struct *tty, int break_state) mutex_unlock(&priv->hw_lock); } static void ark3116_update_msr(struct usb_serial_port *port, __u8 msr) { struct ark3116_private *priv = usb_get_serial_port_data(port); unsigned long flags; spin_lock_irqsave(&priv->status_lock, flags); priv->msr = msr; spin_unlock_irqrestore(&priv->status_lock, flags); if (msr & UART_MSR_ANY_DELTA) { /* update input line counters */ if (msr & UART_MSR_DCTS) priv->icount.cts++; if (msr & UART_MSR_DDSR) priv->icount.dsr++; if (msr & UART_MSR_DDCD) priv->icount.dcd++; if (msr & UART_MSR_TERI) priv->icount.rng++; wake_up_interruptible(&priv->delta_msr_wait); } } static void ark3116_update_lsr(struct usb_serial_port *port, __u8 lsr) { struct ark3116_private *priv = usb_get_serial_port_data(port); unsigned long flags; spin_lock_irqsave(&priv->status_lock, flags); /* combine bits */ priv->lsr |= lsr; spin_unlock_irqrestore(&priv->status_lock, flags); if (lsr&UART_LSR_BRK_ERROR_BITS) { if (lsr & UART_LSR_BI) priv->icount.brk++; if (lsr & UART_LSR_FE) priv->icount.frame++; if (lsr & UART_LSR_PE) priv->icount.parity++; if (lsr & UART_LSR_OE) priv->icount.overrun++; } } static void ark3116_read_int_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; int status = urb->status; const __u8 *data = urb->transfer_buffer; int result; switch (status) { case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ dbg("%s - urb shutting down with status: %d", __func__, status); return; default: dbg("%s - nonzero urb status received: %d", __func__, status); break; case 0: /* success */ /* discovered this by trail and error... */ if ((urb->actual_length == 4) && (data[0] == 0xe8)) { const __u8 id = data[1]&UART_IIR_ID; dbg("%s: iir=%02x", __func__, data[1]); if (id == UART_IIR_MSI) { dbg("%s: msr=%02x", __func__, data[3]); ark3116_update_msr(port, data[3]); break; } else if (id == UART_IIR_RLSI) { dbg("%s: lsr=%02x", __func__, data[2]); ark3116_update_lsr(port, data[2]); break; } } /* * Not sure what this data meant... */ usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, urb->transfer_buffer); break; } result = usb_submit_urb(urb, GFP_ATOMIC); if (result) dev_err(&urb->dev->dev, "%s - Error %d submitting interrupt urb\n", __func__, result); } /* Data comes in via the bulk (data) URB, erors/interrupts via the int URB. * This means that we cannot be sure which data byte has an associated error * condition, so we report an error for all data in the next bulk read. * * Actually, there might even be a window between the bulk data leaving the * ark and reading/resetting the lsr in the read_bulk_callback where an * interrupt for the next data block could come in. * Without somekind of ordering on the ark, we would have to report the * error for the next block of data as well... * For now, let's pretend this can't happen. */ static void send_to_tty(struct tty_struct *tty, const unsigned char *chars, size_t size, char flag) { if (size == 0) return; if (flag == TTY_NORMAL) { tty_insert_flip_string(tty, chars, size); } else { int i; for (i = 0; i < size; ++i) tty_insert_flip_char(tty, chars[i], flag); } } static void ark3116_read_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct ark3116_private *priv = usb_get_serial_port_data(port); const __u8 *data = urb->transfer_buffer; int status = urb->status; struct tty_struct *tty; unsigned long flags; int result; char flag; __u32 lsr; switch (status) { case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ dbg("%s - urb shutting down with status: %d", __func__, status); return; default: dbg("%s - nonzero urb status received: %d", __func__, status); break; case 0: /* success */ spin_lock_irqsave(&priv->status_lock, flags); lsr = priv->lsr; /* clear error bits */ priv->lsr &= ~UART_LSR_BRK_ERROR_BITS; spin_unlock_irqrestore(&priv->status_lock, flags); if (unlikely(lsr & UART_LSR_BI)) flag = TTY_BREAK; else if (unlikely(lsr & UART_LSR_PE)) flag = TTY_PARITY; else if (unlikely(lsr & UART_LSR_FE)) flag = TTY_FRAME; else flag = TTY_NORMAL; tty = tty_port_tty_get(&port->port); if (tty) { tty_buffer_request_room(tty, urb->actual_length + 1); /* overrun is special, not associated with a char */ if (unlikely(lsr & UART_LSR_OE)) tty_insert_flip_char(tty, 0, TTY_OVERRUN); send_to_tty(tty, data, urb->actual_length, flag); tty_flip_buffer_push(tty); tty_kref_put(tty); } /* Throttle the device if requested by tty */ spin_lock_irqsave(&port->lock, flags); port->throttled = port->throttle_req; if (port->throttled) { spin_unlock_irqrestore(&port->lock, flags); return; } else spin_unlock_irqrestore(&port->lock, flags); } /* Continue reading from device */ result = usb_submit_urb(urb, GFP_ATOMIC); if (result) dev_err(&urb->dev->dev, "%s - failed resubmitting" " read urb, error %d\n", __func__, result); } static struct usb_driver ark3116_driver = { .name = "ark3116", .probe = usb_serial_probe, Loading @@ -631,6 +823,8 @@ static struct usb_serial_driver ark3116_device = { .open = ark3116_open, .close = ark3116_close, .break_ctl = ark3116_break_ctl, .read_int_callback = ark3116_read_int_callback, .read_bulk_callback = ark3116_read_bulk_callback, }; static int __init ark3116_init(void) Loading Loading
drivers/usb/serial/ark3116.c +194 −0 Original line number Diff line number Diff line Loading @@ -605,6 +605,198 @@ static void ark3116_break_ctl(struct tty_struct *tty, int break_state) mutex_unlock(&priv->hw_lock); } static void ark3116_update_msr(struct usb_serial_port *port, __u8 msr) { struct ark3116_private *priv = usb_get_serial_port_data(port); unsigned long flags; spin_lock_irqsave(&priv->status_lock, flags); priv->msr = msr; spin_unlock_irqrestore(&priv->status_lock, flags); if (msr & UART_MSR_ANY_DELTA) { /* update input line counters */ if (msr & UART_MSR_DCTS) priv->icount.cts++; if (msr & UART_MSR_DDSR) priv->icount.dsr++; if (msr & UART_MSR_DDCD) priv->icount.dcd++; if (msr & UART_MSR_TERI) priv->icount.rng++; wake_up_interruptible(&priv->delta_msr_wait); } } static void ark3116_update_lsr(struct usb_serial_port *port, __u8 lsr) { struct ark3116_private *priv = usb_get_serial_port_data(port); unsigned long flags; spin_lock_irqsave(&priv->status_lock, flags); /* combine bits */ priv->lsr |= lsr; spin_unlock_irqrestore(&priv->status_lock, flags); if (lsr&UART_LSR_BRK_ERROR_BITS) { if (lsr & UART_LSR_BI) priv->icount.brk++; if (lsr & UART_LSR_FE) priv->icount.frame++; if (lsr & UART_LSR_PE) priv->icount.parity++; if (lsr & UART_LSR_OE) priv->icount.overrun++; } } static void ark3116_read_int_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; int status = urb->status; const __u8 *data = urb->transfer_buffer; int result; switch (status) { case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ dbg("%s - urb shutting down with status: %d", __func__, status); return; default: dbg("%s - nonzero urb status received: %d", __func__, status); break; case 0: /* success */ /* discovered this by trail and error... */ if ((urb->actual_length == 4) && (data[0] == 0xe8)) { const __u8 id = data[1]&UART_IIR_ID; dbg("%s: iir=%02x", __func__, data[1]); if (id == UART_IIR_MSI) { dbg("%s: msr=%02x", __func__, data[3]); ark3116_update_msr(port, data[3]); break; } else if (id == UART_IIR_RLSI) { dbg("%s: lsr=%02x", __func__, data[2]); ark3116_update_lsr(port, data[2]); break; } } /* * Not sure what this data meant... */ usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, urb->transfer_buffer); break; } result = usb_submit_urb(urb, GFP_ATOMIC); if (result) dev_err(&urb->dev->dev, "%s - Error %d submitting interrupt urb\n", __func__, result); } /* Data comes in via the bulk (data) URB, erors/interrupts via the int URB. * This means that we cannot be sure which data byte has an associated error * condition, so we report an error for all data in the next bulk read. * * Actually, there might even be a window between the bulk data leaving the * ark and reading/resetting the lsr in the read_bulk_callback where an * interrupt for the next data block could come in. * Without somekind of ordering on the ark, we would have to report the * error for the next block of data as well... * For now, let's pretend this can't happen. */ static void send_to_tty(struct tty_struct *tty, const unsigned char *chars, size_t size, char flag) { if (size == 0) return; if (flag == TTY_NORMAL) { tty_insert_flip_string(tty, chars, size); } else { int i; for (i = 0; i < size; ++i) tty_insert_flip_char(tty, chars[i], flag); } } static void ark3116_read_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct ark3116_private *priv = usb_get_serial_port_data(port); const __u8 *data = urb->transfer_buffer; int status = urb->status; struct tty_struct *tty; unsigned long flags; int result; char flag; __u32 lsr; switch (status) { case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ dbg("%s - urb shutting down with status: %d", __func__, status); return; default: dbg("%s - nonzero urb status received: %d", __func__, status); break; case 0: /* success */ spin_lock_irqsave(&priv->status_lock, flags); lsr = priv->lsr; /* clear error bits */ priv->lsr &= ~UART_LSR_BRK_ERROR_BITS; spin_unlock_irqrestore(&priv->status_lock, flags); if (unlikely(lsr & UART_LSR_BI)) flag = TTY_BREAK; else if (unlikely(lsr & UART_LSR_PE)) flag = TTY_PARITY; else if (unlikely(lsr & UART_LSR_FE)) flag = TTY_FRAME; else flag = TTY_NORMAL; tty = tty_port_tty_get(&port->port); if (tty) { tty_buffer_request_room(tty, urb->actual_length + 1); /* overrun is special, not associated with a char */ if (unlikely(lsr & UART_LSR_OE)) tty_insert_flip_char(tty, 0, TTY_OVERRUN); send_to_tty(tty, data, urb->actual_length, flag); tty_flip_buffer_push(tty); tty_kref_put(tty); } /* Throttle the device if requested by tty */ spin_lock_irqsave(&port->lock, flags); port->throttled = port->throttle_req; if (port->throttled) { spin_unlock_irqrestore(&port->lock, flags); return; } else spin_unlock_irqrestore(&port->lock, flags); } /* Continue reading from device */ result = usb_submit_urb(urb, GFP_ATOMIC); if (result) dev_err(&urb->dev->dev, "%s - failed resubmitting" " read urb, error %d\n", __func__, result); } static struct usb_driver ark3116_driver = { .name = "ark3116", .probe = usb_serial_probe, Loading @@ -631,6 +823,8 @@ static struct usb_serial_driver ark3116_device = { .open = ark3116_open, .close = ark3116_close, .break_ctl = ark3116_break_ctl, .read_int_callback = ark3116_read_int_callback, .read_bulk_callback = ark3116_read_bulk_callback, }; static int __init ark3116_init(void) Loading