aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/ark3116.c
diff options
context:
space:
mode:
authorbart.hartgers@gmail.com <bart.hartgers@gmail.com>2009-10-28 05:43:29 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-12-11 14:55:21 -0500
commit62d826c8ddafb0a55eb6c5255779ddb782dc5507 (patch)
treebe3837a935c0731bd98af0fcc4b3c66d35b49140 /drivers/usb/serial/ark3116.c
parent546b742968e7789c60efe0eec71896c45eeb6893 (diff)
USB: ark3116: Callbacks for interrupt and bulk read
Signed-off-by: Bart Hartgers <bart.hartgers@gmail.com> Cc: Mike McCormack <mikem@ring3k.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/ark3116.c')
-rw-r--r--drivers/usb/serial/ark3116.c194
1 files changed, 194 insertions, 0 deletions
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index a7c26990ec67..067daf4db646 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -605,6 +605,198 @@ static void ark3116_break_ctl(struct tty_struct *tty, int break_state)
605 mutex_unlock(&priv->hw_lock); 605 mutex_unlock(&priv->hw_lock);
606} 606}
607 607
608static void ark3116_update_msr(struct usb_serial_port *port, __u8 msr)
609{
610 struct ark3116_private *priv = usb_get_serial_port_data(port);
611 unsigned long flags;
612
613 spin_lock_irqsave(&priv->status_lock, flags);
614 priv->msr = msr;
615 spin_unlock_irqrestore(&priv->status_lock, flags);
616
617 if (msr & UART_MSR_ANY_DELTA) {
618 /* update input line counters */
619 if (msr & UART_MSR_DCTS)
620 priv->icount.cts++;
621 if (msr & UART_MSR_DDSR)
622 priv->icount.dsr++;
623 if (msr & UART_MSR_DDCD)
624 priv->icount.dcd++;
625 if (msr & UART_MSR_TERI)
626 priv->icount.rng++;
627 wake_up_interruptible(&priv->delta_msr_wait);
628 }
629}
630
631static void ark3116_update_lsr(struct usb_serial_port *port, __u8 lsr)
632{
633 struct ark3116_private *priv = usb_get_serial_port_data(port);
634 unsigned long flags;
635
636 spin_lock_irqsave(&priv->status_lock, flags);
637 /* combine bits */
638 priv->lsr |= lsr;
639 spin_unlock_irqrestore(&priv->status_lock, flags);
640
641 if (lsr&UART_LSR_BRK_ERROR_BITS) {
642 if (lsr & UART_LSR_BI)
643 priv->icount.brk++;
644 if (lsr & UART_LSR_FE)
645 priv->icount.frame++;
646 if (lsr & UART_LSR_PE)
647 priv->icount.parity++;
648 if (lsr & UART_LSR_OE)
649 priv->icount.overrun++;
650 }
651}
652
653static void ark3116_read_int_callback(struct urb *urb)
654{
655 struct usb_serial_port *port = urb->context;
656 int status = urb->status;
657 const __u8 *data = urb->transfer_buffer;
658 int result;
659
660 switch (status) {
661 case -ECONNRESET:
662 case -ENOENT:
663 case -ESHUTDOWN:
664 /* this urb is terminated, clean up */
665 dbg("%s - urb shutting down with status: %d",
666 __func__, status);
667 return;
668 default:
669 dbg("%s - nonzero urb status received: %d",
670 __func__, status);
671 break;
672 case 0: /* success */
673 /* discovered this by trail and error... */
674 if ((urb->actual_length == 4) && (data[0] == 0xe8)) {
675 const __u8 id = data[1]&UART_IIR_ID;
676 dbg("%s: iir=%02x", __func__, data[1]);
677 if (id == UART_IIR_MSI) {
678 dbg("%s: msr=%02x", __func__, data[3]);
679 ark3116_update_msr(port, data[3]);
680 break;
681 } else if (id == UART_IIR_RLSI) {
682 dbg("%s: lsr=%02x", __func__, data[2]);
683 ark3116_update_lsr(port, data[2]);
684 break;
685 }
686 }
687 /*
688 * Not sure what this data meant...
689 */
690 usb_serial_debug_data(debug, &port->dev,
691 __func__,
692 urb->actual_length,
693 urb->transfer_buffer);
694 break;
695 }
696
697 result = usb_submit_urb(urb, GFP_ATOMIC);
698 if (result)
699 dev_err(&urb->dev->dev,
700 "%s - Error %d submitting interrupt urb\n",
701 __func__, result);
702}
703
704
705/* Data comes in via the bulk (data) URB, erors/interrupts via the int URB.
706 * This means that we cannot be sure which data byte has an associated error
707 * condition, so we report an error for all data in the next bulk read.
708 *
709 * Actually, there might even be a window between the bulk data leaving the
710 * ark and reading/resetting the lsr in the read_bulk_callback where an
711 * interrupt for the next data block could come in.
712 * Without somekind of ordering on the ark, we would have to report the
713 * error for the next block of data as well...
714 * For now, let's pretend this can't happen.
715 */
716
717static void send_to_tty(struct tty_struct *tty,
718 const unsigned char *chars,
719 size_t size, char flag)
720{
721 if (size == 0)
722 return;
723 if (flag == TTY_NORMAL) {
724 tty_insert_flip_string(tty, chars, size);
725 } else {
726 int i;
727 for (i = 0; i < size; ++i)
728 tty_insert_flip_char(tty, chars[i], flag);
729 }
730}
731
732static void ark3116_read_bulk_callback(struct urb *urb)
733{
734 struct usb_serial_port *port = urb->context;
735 struct ark3116_private *priv = usb_get_serial_port_data(port);
736 const __u8 *data = urb->transfer_buffer;
737 int status = urb->status;
738 struct tty_struct *tty;
739 unsigned long flags;
740 int result;
741 char flag;
742 __u32 lsr;
743
744 switch (status) {
745 case -ECONNRESET:
746 case -ENOENT:
747 case -ESHUTDOWN:
748 /* this urb is terminated, clean up */
749 dbg("%s - urb shutting down with status: %d",
750 __func__, status);
751 return;
752 default:
753 dbg("%s - nonzero urb status received: %d",
754 __func__, status);
755 break;
756 case 0: /* success */
757
758 spin_lock_irqsave(&priv->status_lock, flags);
759 lsr = priv->lsr;
760 /* clear error bits */
761 priv->lsr &= ~UART_LSR_BRK_ERROR_BITS;
762 spin_unlock_irqrestore(&priv->status_lock, flags);
763
764 if (unlikely(lsr & UART_LSR_BI))
765 flag = TTY_BREAK;
766 else if (unlikely(lsr & UART_LSR_PE))
767 flag = TTY_PARITY;
768 else if (unlikely(lsr & UART_LSR_FE))
769 flag = TTY_FRAME;
770 else
771 flag = TTY_NORMAL;
772
773 tty = tty_port_tty_get(&port->port);
774 if (tty) {
775 tty_buffer_request_room(tty, urb->actual_length + 1);
776 /* overrun is special, not associated with a char */
777 if (unlikely(lsr & UART_LSR_OE))
778 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
779 send_to_tty(tty, data, urb->actual_length, flag);
780 tty_flip_buffer_push(tty);
781 tty_kref_put(tty);
782 }
783
784 /* Throttle the device if requested by tty */
785 spin_lock_irqsave(&port->lock, flags);
786 port->throttled = port->throttle_req;
787 if (port->throttled) {
788 spin_unlock_irqrestore(&port->lock, flags);
789 return;
790 } else
791 spin_unlock_irqrestore(&port->lock, flags);
792 }
793 /* Continue reading from device */
794 result = usb_submit_urb(urb, GFP_ATOMIC);
795 if (result)
796 dev_err(&urb->dev->dev, "%s - failed resubmitting"
797 " read urb, error %d\n", __func__, result);
798}
799
608static struct usb_driver ark3116_driver = { 800static struct usb_driver ark3116_driver = {
609 .name = "ark3116", 801 .name = "ark3116",
610 .probe = usb_serial_probe, 802 .probe = usb_serial_probe,
@@ -631,6 +823,8 @@ static struct usb_serial_driver ark3116_device = {
631 .open = ark3116_open, 823 .open = ark3116_open,
632 .close = ark3116_close, 824 .close = ark3116_close,
633 .break_ctl = ark3116_break_ctl, 825 .break_ctl = ark3116_break_ctl,
826 .read_int_callback = ark3116_read_int_callback,
827 .read_bulk_callback = ark3116_read_bulk_callback,
634}; 828};
635 829
636static int __init ark3116_init(void) 830static int __init ark3116_init(void)