Hello, All: This patch adds useful TIOCMIWAIT ioctl to the ftdi_sio driver. It was generated against 2.4.18pre4, intended for 2.4 tree, and can be added to 2.5 as well.
diff -Naur -X /home/dmitri/dontdiff
linux-2.4.18pre4-official/drivers/usb/serial/ftdi_sio.c
linux/drivers/usb/serial/ftdi_sio.c
--- linux-2.4.18pre4-official/drivers/usb/serial/ftdi_sio.c Thu Jan 17 20:19:37
2002
+++ linux/drivers/usb/serial/ftdi_sio.c Thu Jan 17 20:18:56 2002
@@ -155,7 +155,12 @@
ftdi_type_t ftdi_type;
__u16 last_set_data_urb_value ; /* the last data state set - needed for doing
a break */
int write_offset;
+ wait_queue_head_t delta_msr_wait;
+ char prev_status, diff_status;
};
+#define FTDI_STATUS_B0_MASK (FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI |
+FTDI_RS0_RLSD)
+#define FTDI_STATUS_B1_MASK (FTDI_RS_BI)
+
/* function prototypes for a FTDI serial converter */
static int ftdi_sio_startup (struct usb_serial *serial);
static int ftdi_8U232AM_startup (struct usb_serial *serial);
@@ -273,6 +278,7 @@
priv->ftdi_type = sio;
priv->write_offset = 1;
+ priv->prev_status = priv->diff_status = 0;
return (0);
}
@@ -291,6 +297,7 @@
priv->ftdi_type = F8U232AM;
priv->write_offset = 0;
+ init_waitqueue_head(&priv->delta_msr_wait);
return (0);
}
@@ -548,6 +555,7 @@
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct usb_serial *serial;
struct tty_struct *tty = port->tty ;
+ struct ftdi_private *priv = (struct ftdi_private *) port->private;
char error_flag;
unsigned char *data = urb->transfer_buffer;
@@ -584,6 +592,16 @@
/* See acm.c - you do a tty_hangup - eg tty_hangup(tty) */
/* if CD is dropped and the line is not CLOCAL then we should hangup */
+ /* Compare new line status to the old one, signal if different */
+ if (priv != NULL) {
+ char new_status = data[0] & FTDI_STATUS_B0_MASK;
+ if (new_status != priv->prev_status) {
+ priv->diff_status |= new_status ^ priv->prev_status;
+ wake_up_interruptible(&priv->delta_msr_wait);
+ priv->prev_status = new_status;
+ }
+ }
+
/* Handle errors and break */
error_flag = TTY_NORMAL;
/* Although the device uses a bitmask and hence can have multiple */
@@ -970,6 +988,45 @@
*
*/
+ /*
+ * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+ * - mask passed in arg for lines of interest
+ * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+ * Caller should use TIOCGICOUNT to see which one it was.
+ *
+ * This code is borrowed from linux/drivers/char/serial.c
+ */
+ case TIOCMIWAIT:
+ while (priv != NULL) {
+ interruptible_sleep_on(&priv->delta_msr_wait);
+ /* see if a signal did it */
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ else {
+ char diff = priv->diff_status;
+
+ if (diff == 0) {
+ return -EIO; /* no change => error */
+ }
+
+ /* Consume all events */
+ priv->diff_status = 0;
+
+ /* Return 0 if caller wanted to know about these bits
+*/
+ if ( ((arg & TIOCM_RNG) && (diff & FTDI_RS0_RI)) ||
+ ((arg & TIOCM_DSR) && (diff & FTDI_RS0_DSR)) ||
+ ((arg & TIOCM_CD) && (diff & FTDI_RS0_RLSD)) ||
+ ((arg & TIOCM_CTS) && (diff & FTDI_RS0_CTS)) ) {
+ return 0;
+ }
+ /*
+ * Otherwise caller can't care less about what
+happened,
+ * and so we continue to wait for more events.
+ */
+ }
+ }
+ /* NOTREACHED */
+
default:
/* This is not an error - turns out the higher layers will do
* some ioctls itself (see comment above)
diff -Naur -X /home/dmitri/dontdiff
linux-2.4.18pre4-official/drivers/usb/serial/ftdi_sio.h
linux/drivers/usb/serial/ftdi_sio.h
--- linux-2.4.18pre4-official/drivers/usb/serial/ftdi_sio.h Thu Jan 17 20:19:37
2002
+++ linux/drivers/usb/serial/ftdi_sio.h Thu Jan 17 20:18:56 2002
@@ -438,6 +438,11 @@
* B7 Error in RCVR FIFO
*
*/
+#define FTDI_RS0_CTS (1 << 4)
+#define FTDI_RS0_DSR (1 << 5)
+#define FTDI_RS0_RI (1 << 6)
+#define FTDI_RS0_RLSD (1 << 7)
+
#define FTDI_RS_DR 1
#define FTDI_RS_OE (1<<1)
#define FTDI_RS_PE (1<<2)
msg04058/pgp00000.pgp
Description: PGP signature
