summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcliechti <cliechti@f19166aa-fa4f-0410-85c2-fa1106f25c8a>2009-10-27 00:23:23 +0000
committercliechti <cliechti@f19166aa-fa4f-0410-85c2-fa1106f25c8a>2009-10-27 00:23:23 +0000
commit666d2793d01acf8f95ffa396146f2899651318ee (patch)
tree1ba61ec49c9180c6259ef3fbc9d03031298645f0
parent5735a079f93830b1c3e608a6703d6a006065a06e (diff)
downloadpyserial-git-666d2793d01acf8f95ffa396146f2899651318ee.tar.gz
revert to select based read for all platforms except Linux
-rw-r--r--pyserial/CHANGES.txt3
-rw-r--r--pyserial/serial/serialposix.py71
2 files changed, 50 insertions, 24 deletions
diff --git a/pyserial/CHANGES.txt b/pyserial/CHANGES.txt
index 83795f9..480b35f 100644
--- a/pyserial/CHANGES.txt
+++ b/pyserial/CHANGES.txt
@@ -317,6 +317,9 @@ New Features:
- add ``serial.serial_for_url`` factory function (support for native ports and
``rfc2217``, ``socket`` and ``loop`` URLs)
- add ``getSettingsDict`` and ``applySettingsDict`` serial object methods
+- use a ``poll`` based implementation on Linux, instead of a ``select``based
+ like on other posix systems. It provides better error handling, but ``poll``
+ is not supported well on all platforms.
Bugfixes:
diff --git a/pyserial/serial/serialposix.py b/pyserial/serial/serialposix.py
index 38d1dba..f822211 100644
--- a/pyserial/serial/serialposix.py
+++ b/pyserial/serial/serialposix.py
@@ -431,30 +431,53 @@ class PosixSerial(SerialBase):
s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str)
return struct.unpack('I',s)[0]
- def read(self, size=1):
- """Read size bytes from the serial port. If a timeout is set it may
- return less characters as requested. With no timeout it will block
- until the requested number of bytes is read."""
- if self.fd is None: raise portNotOpenError
- read = bytearray()
- poll = select.poll()
- poll.register(self.fd, select.POLLIN|select.POLLERR|select.POLLHUP|select.POLLNVAL)
- inp = None
- if size > 0:
- while len(read) < size:
- # print "\tread(): size",size, "have", len(read) #debug
- # wait until device becomes ready to read (or something fails)
- for fd, event in poll.poll(self._timeout):
- if event & (select.POLLERR|select.POLLHUP|select.POLLNVAL):
- raise SerialException('device reports error (poll)')
- # we don't care if it is select.POLLIN or timeout, that's
- # handled below
- buf = os.read(self.fd, size - len(read))
- read.extend(buf)
- if ((self._timeout is not None and self._timeout >= 0) or
- (self._interCharTimeout is not None and self._interCharTimeout > 0)) and not buf:
- break # early abort on timeout
- return bytes(read)
+ if plat[:5] != 'linux':
+ #~ print "XXX USING SELECT"
+ # select based implementation, proved to work on many systems
+ def read(self, size=1):
+ """Read size bytes from the serial port. If a timeout is set it may
+ return less characters as requested. With no timeout it will block
+ until the requested number of bytes is read."""
+ if self.fd is None: raise portNotOpenError
+ read = ''
+ if size > 0:
+ while len(read) < size:
+ ready,_,_ = select.select([self.fd],[],[], self._timeout)
+ if not ready:
+ break # timeout
+ buf = os.read(self.fd, size-len(read))
+ read = read + buf
+ if (self._timeout >= 0 or self._interCharTimeout > 0) and not buf:
+ break # early abort on timeout
+ return bytes(read)
+ else:
+ #~ print "XXX USING POLL"
+ # poll based implementation. not all systems support poll properly.
+ # however this one has better handling of errors, such as a device
+ # disconnecting while it's in use (i.e. USB-serial unplugged)
+ def read(self, size=1):
+ """Read size bytes from the serial port. If a timeout is set it may
+ return less characters as requested. With no timeout it will block
+ until the requested number of bytes is read."""
+ if self.fd is None: raise portNotOpenError
+ read = bytearray()
+ poll = select.poll()
+ poll.register(self.fd, select.POLLIN|select.POLLERR|select.POLLHUP|select.POLLNVAL)
+ if size > 0:
+ while len(read) < size:
+ # print "\tread(): size",size, "have", len(read) #debug
+ # wait until device becomes ready to read (or something fails)
+ for fd, event in poll.poll(self._timeout):
+ if event & (select.POLLERR|select.POLLHUP|select.POLLNVAL):
+ raise SerialException('device reports error (poll)')
+ # we don't care if it is select.POLLIN or timeout, that's
+ # handled below
+ buf = os.read(self.fd, size - len(read))
+ read.extend(buf)
+ if ((self._timeout is not None and self._timeout >= 0) or
+ (self._interCharTimeout is not None and self._interCharTimeout > 0)) and not buf:
+ break # early abort on timeout
+ return bytes(read)
def write(self, data):
"""Output the given string over the serial port."""