}
 EXPORT_SYMBOL_GPL(usb_serial_generic_unthrottle);
 
+static bool usb_serial_generic_msr_changed(struct tty_struct *tty,
+                               unsigned long arg, struct async_icount *cprev)
+{
+       struct usb_serial_port *port = tty->driver_data;
+       struct async_icount cnow;
+       unsigned long flags;
+       bool ret;
+
+       /*
+        * Use tty-port initialised flag to detect all hangups including the
+        * one generated at USB-device disconnect.
+        *
+        * FIXME: Remove hupping check once tty_port_hangup calls shutdown
+        *        (which clears the initialised flag) before wake up.
+        */
+       if (test_bit(TTY_HUPPING, &tty->flags))
+               return true;
+       if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags))
+               return true;
+
+       spin_lock_irqsave(&port->lock, flags);
+       cnow = port->icount;                            /* atomic copy*/
+       spin_unlock_irqrestore(&port->lock, flags);
+
+       ret =   ((arg & TIOCM_RNG) && (cnow.rng != cprev->rng)) ||
+               ((arg & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) ||
+               ((arg & TIOCM_CD)  && (cnow.dcd != cprev->dcd)) ||
+               ((arg & TIOCM_CTS) && (cnow.cts != cprev->cts));
+
+       *cprev = cnow;
+
+       return ret;
+}
+
+int usb_serial_generic_tiocmiwait(struct tty_struct *tty, unsigned long arg)
+{
+       struct usb_serial_port *port = tty->driver_data;
+       struct async_icount cnow;
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&port->lock, flags);
+       cnow = port->icount;                            /* atomic copy */
+       spin_unlock_irqrestore(&port->lock, flags);
+
+       ret = wait_event_interruptible(port->port.delta_msr_wait,
+                       usb_serial_generic_msr_changed(tty, arg, &cnow));
+       if (!ret) {
+               if (test_bit(TTY_HUPPING, &tty->flags))
+                       ret = -EIO;
+               if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags))
+                       ret = -EIO;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(usb_serial_generic_tiocmiwait);
+
 #ifdef CONFIG_MAGIC_SYSRQ
 int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch)
 {
 
 
 #include <linux/kref.h>
 #include <linux/mutex.h>
+#include <linux/serial.h>
 #include <linux/sysrq.h>
 #include <linux/kfifo.h>
 
  * @bulk_out_buffers: pointers to the bulk out buffers for this port
  * @write_urbs: pointers to the bulk out urbs for this port
  * @write_urbs_free: status bitmap the for bulk out urbs
+ * @icount: interrupt counters
  * @tx_bytes: number of bytes currently in host stack queues
  * @bulk_out_endpointAddress: endpoint address for the bulk out pipe for this
  *     port.
        unsigned long           write_urbs_free;
        __u8                    bulk_out_endpointAddress;
 
+       struct async_icount     icount;
        int                     tx_bytes;
 
        unsigned long           flags;
 extern void usb_serial_generic_write_bulk_callback(struct urb *urb);
 extern void usb_serial_generic_throttle(struct tty_struct *tty);
 extern void usb_serial_generic_unthrottle(struct tty_struct *tty);
+extern int usb_serial_generic_tiocmiwait(struct tty_struct *tty,
+                                                       unsigned long arg);
 extern int usb_serial_generic_register(void);
 extern void usb_serial_generic_deregister(void);
 extern int usb_serial_generic_submit_read_urbs(struct usb_serial_port *port,