aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/mct_u232.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/usb/serial/mct_u232.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'drivers/usb/serial/mct_u232.c')
-rw-r--r--drivers/usb/serial/mct_u232.c122
1 files changed, 114 insertions, 8 deletions
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 7aa01b95b1d4..ba0d28727ccb 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -78,6 +78,8 @@
78#include <asm/unaligned.h> 78#include <asm/unaligned.h>
79#include <linux/usb.h> 79#include <linux/usb.h>
80#include <linux/usb/serial.h> 80#include <linux/usb/serial.h>
81#include <linux/serial.h>
82#include <linux/ioctl.h>
81#include "mct_u232.h" 83#include "mct_u232.h"
82 84
83/* 85/*
@@ -101,9 +103,13 @@ static void mct_u232_read_int_callback(struct urb *urb);
101static void mct_u232_set_termios(struct tty_struct *tty, 103static void mct_u232_set_termios(struct tty_struct *tty,
102 struct usb_serial_port *port, struct ktermios *old); 104 struct usb_serial_port *port, struct ktermios *old);
103static void mct_u232_break_ctl(struct tty_struct *tty, int break_state); 105static void mct_u232_break_ctl(struct tty_struct *tty, int break_state);
104static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file); 106static int mct_u232_tiocmget(struct tty_struct *tty);
105static int mct_u232_tiocmset(struct tty_struct *tty, struct file *file, 107static int mct_u232_tiocmset(struct tty_struct *tty,
106 unsigned int set, unsigned int clear); 108 unsigned int set, unsigned int clear);
109static int mct_u232_ioctl(struct tty_struct *tty,
110 unsigned int cmd, unsigned long arg);
111static int mct_u232_get_icount(struct tty_struct *tty,
112 struct serial_icounter_struct *icount);
107static void mct_u232_throttle(struct tty_struct *tty); 113static void mct_u232_throttle(struct tty_struct *tty);
108static void mct_u232_unthrottle(struct tty_struct *tty); 114static void mct_u232_unthrottle(struct tty_struct *tty);
109 115
@@ -150,9 +156,10 @@ static struct usb_serial_driver mct_u232_device = {
150 .tiocmset = mct_u232_tiocmset, 156 .tiocmset = mct_u232_tiocmset,
151 .attach = mct_u232_startup, 157 .attach = mct_u232_startup,
152 .release = mct_u232_release, 158 .release = mct_u232_release,
159 .ioctl = mct_u232_ioctl,
160 .get_icount = mct_u232_get_icount,
153}; 161};
154 162
155
156struct mct_u232_private { 163struct mct_u232_private {
157 spinlock_t lock; 164 spinlock_t lock;
158 unsigned int control_state; /* Modem Line Setting (TIOCM) */ 165 unsigned int control_state; /* Modem Line Setting (TIOCM) */
@@ -160,6 +167,9 @@ struct mct_u232_private {
160 unsigned char last_lsr; /* Line Status Register */ 167 unsigned char last_lsr; /* Line Status Register */
161 unsigned char last_msr; /* Modem Status Register */ 168 unsigned char last_msr; /* Modem Status Register */
162 unsigned int rx_flags; /* Throttling flags */ 169 unsigned int rx_flags; /* Throttling flags */
170 struct async_icount icount;
171 wait_queue_head_t msr_wait; /* for handling sleeping while waiting
172 for msr change to happen */
163}; 173};
164 174
165#define THROTTLED 0x01 175#define THROTTLED 0x01
@@ -386,6 +396,20 @@ static int mct_u232_get_modem_stat(struct usb_serial *serial,
386 return rc; 396 return rc;
387} /* mct_u232_get_modem_stat */ 397} /* mct_u232_get_modem_stat */
388 398
399static void mct_u232_msr_to_icount(struct async_icount *icount,
400 unsigned char msr)
401{
402 /* Translate Control Line states */
403 if (msr & MCT_U232_MSR_DDSR)
404 icount->dsr++;
405 if (msr & MCT_U232_MSR_DCTS)
406 icount->cts++;
407 if (msr & MCT_U232_MSR_DRI)
408 icount->rng++;
409 if (msr & MCT_U232_MSR_DCD)
410 icount->dcd++;
411} /* mct_u232_msr_to_icount */
412
389static void mct_u232_msr_to_state(unsigned int *control_state, 413static void mct_u232_msr_to_state(unsigned int *control_state,
390 unsigned char msr) 414 unsigned char msr)
391{ 415{
@@ -422,6 +446,7 @@ static int mct_u232_startup(struct usb_serial *serial)
422 if (!priv) 446 if (!priv)
423 return -ENOMEM; 447 return -ENOMEM;
424 spin_lock_init(&priv->lock); 448 spin_lock_init(&priv->lock);
449 init_waitqueue_head(&priv->msr_wait);
425 usb_set_serial_port_data(serial->port[0], priv); 450 usb_set_serial_port_data(serial->port[0], priv);
426 451
427 init_waitqueue_head(&serial->port[0]->write_wait); 452 init_waitqueue_head(&serial->port[0]->write_wait);
@@ -549,9 +574,12 @@ static void mct_u232_close(struct usb_serial_port *port)
549{ 574{
550 dbg("%s port %d", __func__, port->number); 575 dbg("%s port %d", __func__, port->number);
551 576
552 usb_serial_generic_close(port); 577 if (port->serial->dev) {
553 if (port->serial->dev) 578 /* shutdown our urbs */
579 usb_kill_urb(port->write_urb);
580 usb_kill_urb(port->read_urb);
554 usb_kill_urb(port->interrupt_in_urb); 581 usb_kill_urb(port->interrupt_in_urb);
582 }
555} /* mct_u232_close */ 583} /* mct_u232_close */
556 584
557 585
@@ -618,6 +646,8 @@ static void mct_u232_read_int_callback(struct urb *urb)
618 /* Record Control Line states */ 646 /* Record Control Line states */
619 mct_u232_msr_to_state(&priv->control_state, priv->last_msr); 647 mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
620 648
649 mct_u232_msr_to_icount(&priv->icount, priv->last_msr);
650
621#if 0 651#if 0
622 /* Not yet handled. See belkin_sa.c for further information */ 652 /* Not yet handled. See belkin_sa.c for further information */
623 /* Now to report any errors */ 653 /* Now to report any errors */
@@ -644,6 +674,7 @@ static void mct_u232_read_int_callback(struct urb *urb)
644 tty_kref_put(tty); 674 tty_kref_put(tty);
645 } 675 }
646#endif 676#endif
677 wake_up_interruptible(&priv->msr_wait);
647 spin_unlock_irqrestore(&priv->lock, flags); 678 spin_unlock_irqrestore(&priv->lock, flags);
648exit: 679exit:
649 retval = usb_submit_urb(urb, GFP_ATOMIC); 680 retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -759,7 +790,7 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
759} /* mct_u232_break_ctl */ 790} /* mct_u232_break_ctl */
760 791
761 792
762static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file) 793static int mct_u232_tiocmget(struct tty_struct *tty)
763{ 794{
764 struct usb_serial_port *port = tty->driver_data; 795 struct usb_serial_port *port = tty->driver_data;
765 struct mct_u232_private *priv = usb_get_serial_port_data(port); 796 struct mct_u232_private *priv = usb_get_serial_port_data(port);
@@ -775,7 +806,7 @@ static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file)
775 return control_state; 806 return control_state;
776} 807}
777 808
778static int mct_u232_tiocmset(struct tty_struct *tty, struct file *file, 809static int mct_u232_tiocmset(struct tty_struct *tty,
779 unsigned int set, unsigned int clear) 810 unsigned int set, unsigned int clear)
780{ 811{
781 struct usb_serial_port *port = tty->driver_data; 812 struct usb_serial_port *port = tty->driver_data;
@@ -823,7 +854,6 @@ static void mct_u232_throttle(struct tty_struct *tty)
823 } 854 }
824} 855}
825 856
826
827static void mct_u232_unthrottle(struct tty_struct *tty) 857static void mct_u232_unthrottle(struct tty_struct *tty)
828{ 858{
829 struct usb_serial_port *port = tty->driver_data; 859 struct usb_serial_port *port = tty->driver_data;
@@ -844,6 +874,82 @@ static void mct_u232_unthrottle(struct tty_struct *tty)
844 } 874 }
845} 875}
846 876
877static int mct_u232_ioctl(struct tty_struct *tty,
878 unsigned int cmd, unsigned long arg)
879{
880 DEFINE_WAIT(wait);
881 struct usb_serial_port *port = tty->driver_data;
882 struct mct_u232_private *mct_u232_port = usb_get_serial_port_data(port);
883 struct async_icount cnow, cprev;
884 unsigned long flags;
885
886 dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
887
888 switch (cmd) {
889
890 case TIOCMIWAIT:
891
892 dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
893
894 spin_lock_irqsave(&mct_u232_port->lock, flags);
895 cprev = mct_u232_port->icount;
896 spin_unlock_irqrestore(&mct_u232_port->lock, flags);
897 for ( ; ; ) {
898 prepare_to_wait(&mct_u232_port->msr_wait,
899 &wait, TASK_INTERRUPTIBLE);
900 schedule();
901 finish_wait(&mct_u232_port->msr_wait, &wait);
902 /* see if a signal did it */
903 if (signal_pending(current))
904 return -ERESTARTSYS;
905 spin_lock_irqsave(&mct_u232_port->lock, flags);
906 cnow = mct_u232_port->icount;
907 spin_unlock_irqrestore(&mct_u232_port->lock, flags);
908 if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
909 cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
910 return -EIO; /* no change => error */
911 if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
912 ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
913 ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
914 ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
915 return 0;
916 }
917 cprev = cnow;
918 }
919
920 }
921 return -ENOIOCTLCMD;
922}
923
924static int mct_u232_get_icount(struct tty_struct *tty,
925 struct serial_icounter_struct *icount)
926{
927 struct usb_serial_port *port = tty->driver_data;
928 struct mct_u232_private *mct_u232_port = usb_get_serial_port_data(port);
929 struct async_icount *ic = &mct_u232_port->icount;
930 unsigned long flags;
931
932 spin_lock_irqsave(&mct_u232_port->lock, flags);
933
934 icount->cts = ic->cts;
935 icount->dsr = ic->dsr;
936 icount->rng = ic->rng;
937 icount->dcd = ic->dcd;
938 icount->rx = ic->rx;
939 icount->tx = ic->tx;
940 icount->frame = ic->frame;
941 icount->overrun = ic->overrun;
942 icount->parity = ic->parity;
943 icount->brk = ic->brk;
944 icount->buf_overrun = ic->buf_overrun;
945
946 spin_unlock_irqrestore(&mct_u232_port->lock, flags);
947
948 dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d",
949 __func__, port->number, icount->rx, icount->tx);
950 return 0;
951}
952
847static int __init mct_u232_init(void) 953static int __init mct_u232_init(void)
848{ 954{
849 int retval; 955 int retval;