diff --git a/pcl_expect/pyserial.py b/pcl_expect/pyserial.py
new file mode 100644
index 0000000000000000000000000000000000000000..c5c009501f986f7ea9d82f334164396c77d51d75
--- /dev/null
+++ b/pcl_expect/pyserial.py
@@ -0,0 +1,67 @@
+import serial
+
+import pcl_expect
+
+__all__ = [
+    "Serial",
+    ]
+
+class Serial(pcl_expect.Expectable):
+    """Read input from a serial port using the pySerial module.
+
+       pySerial is available from http://pyserial.sourceforge.net/
+
+       Once you have created a pcl_expect.Serial object, you can
+       access the underlying serial.Serial object via the serial
+       attribute.  However, this class will not work if the file
+       descriptor changes or if the serial port is closed, so don't do
+       anything that closes the port.  For example, don't assign to
+       the port attribute.  It is OK to change the baudrate et c.
+
+       The timeout of the underlying serial.Serial object must be 0
+       all the time.  The constructor will set it to 0 automatically.
+       Don't alter it.
+
+       Reading from or writing to the underlying object may cause
+       confusion.  Use the send() method of pcl_expect.Serial to send
+       data to the serial port.
+
+       You should use the close() method when you want to close the
+       port.  If you just discard the Serial object a file descriptor
+       leak will result.
+
+    """
+
+    def __init__(self, *args, **kwargs):
+        """Open a serial port using pySerial.
+
+           All arguments are passed to serial.Serial.  See the
+           documentation for that class.
+
+           Raises ValueError unless the arguments you supply causes
+           the port to be opened.
+
+           This constructor will set the timeout to 0.  If you supply
+           another timeout value (even None) it will be silently
+           overwritten by this constructor.  Please don't set a new
+           timeout value.
+
+        """
+
+        self.serial = serial.Serial(*args, **kwargs)
+        self.serial.timeout = 0
+        if not self.serial._isOpen:
+            raise ValueError("Closed serial objects are not supported")
+        pcl_expect.Expectable.__init__(self, self.serial.fd)
+
+    def _read(self):
+        return self.serial.read(8192), False
+
+    def send(self, s):
+        """Send a string to the serial port."""
+        self.serial.write(s)
+
+    def close(self):
+        """Close the port."""
+        pcl_expect.Expectable.close(self)
+        self.serial.close()