lkml.org 
[lkml]   [2009]   [Oct]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH 6/7] ark3116: (3rd try) Callbacks for interrupt and bulk read
    Signed-off-by: Bart Hartgers <bart.hartgers@gmail.com>
    ---
    Index: linux-2.6.32-rc4/drivers/usb/serial/ark3116.c
    ===================================================================
    --- linux-2.6.32-rc4.orig/drivers/usb/serial/ark3116.c 2009-10-25 13:39:15.000000000 +0100
    +++ linux-2.6.32-rc4/drivers/usb/serial/ark3116.c 2009-10-25 13:46:48.000000000 +0100
    @@ -626,6 +626,190 @@ static void ark3116_break_ctl(struct tty
    mutex_unlock(&priv->lock);
    }

    +static void ark3116_update_msr(struct usb_serial_port *port, __u8 msr)
    +{
    + struct ark3116_private *priv = usb_get_serial_port_data(port);
    +
    + atomic_set(&priv->msr, msr);
    +
    + 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_combine_lsr(struct usb_serial_port *port, __u8 lsr)
    +{
    + struct ark3116_private *priv = usb_get_serial_port_data(port);
    +
    + /* combine bits */
    + ark3116_atomic_set_clear(lsr, 0, &priv->lsr);
    +
    + 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_combine_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;
    + __u8 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 */
    +
    + lsr = atomic_read(&priv->lsr);
    + /* clear error bits; works because update_lsr ors the bits */
    + atomic_sub( lsr & UART_LSR_BRK_ERROR_BITS, &priv->lsr);
    +
    + 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,
    @@ -652,6 +836,8 @@ static struct usb_serial_driver ark3116_
    .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)
    --


    \
     
     \ /
      Last update: 2009-10-25 18:57    [W:0.030 / U:0.608 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site