blob: df7363399ce6dba5c3f03f22ec008baaf18ac18e [file] [log] [blame]
cliechti89b4af12002-02-12 23:24:41 +00001#!/usr/bin/env python
cliechti58b481c2009-02-16 20:42:32 +00002#
Chris Liechti3e02f702015-12-16 23:06:04 +01003# backend for serial IO for POSIX compatible systems, like Linux, OSX
cliechti89b4af12002-02-12 23:24:41 +00004#
Chris Liechti3e02f702015-12-16 23:06:04 +01005# This file is part of pySerial. https://github.com/pyserial/pyserial
Chris Liechti68340d72015-08-03 14:15:48 +02006# (C) 2001-2015 Chris Liechti <cliechti@gmx.net>
Chris Liechtifbdd8a02015-08-09 02:37:45 +02007#
8# SPDX-License-Identifier: BSD-3-Clause
cliechti89b4af12002-02-12 23:24:41 +00009#
cliechtic54b2c82008-06-21 01:59:08 +000010# parts based on code from Grant B. Edwards <grante@visi.com>:
cliechti89b4af12002-02-12 23:24:41 +000011# ftp://ftp.visi.com/users/grante/python/PosixSerial.py
cliechti53c9fd42009-07-23 23:51:51 +000012#
cliechti89b4af12002-02-12 23:24:41 +000013# references: http://www.easysw.com/~mike/serial/serial.html
14
Chris Liechti33f0ec52015-08-06 16:37:21 +020015import errno
16import fcntl
Chris Liechti33f0ec52015-08-06 16:37:21 +020017import os
18import select
19import struct
20import sys
21import termios
22import time
Chris Liechti033f17c2015-08-30 21:28:04 +020023
24import serial
25from serial.serialutil import SerialBase, SerialException, to_bytes, portNotOpenError, writeTimeoutError
cliechti89b4af12002-02-12 23:24:41 +000026
cliechti89b4af12002-02-12 23:24:41 +000027
Chris Liechtid6847af2015-08-06 17:54:30 +020028class PlatformSpecificBase(object):
29 BAUDRATE_CONSTANTS = {}
cliechti89b4af12002-02-12 23:24:41 +000030
Chris Liechtid6847af2015-08-06 17:54:30 +020031 def number_to_device(self, port_number):
32 sys.stderr.write("""\
cliechti7aaead32009-07-23 14:02:41 +000033don't know how to number ttys on this system.
cliechti895e8302004-04-20 02:40:28 +000034! Use an explicit path (eg /dev/ttyS1) or send this information to
35! the author of this module:
cliechti89b4af12002-02-12 23:24:41 +000036
cliechti895e8302004-04-20 02:40:28 +000037sys.platform = %r
38os.name = %r
39serialposix.py version = %s
cliechti89b4af12002-02-12 23:24:41 +000040
41also add the device name of the serial port and where the
42counting starts for the first serial port.
43e.g. 'first serial port: /dev/ttyS0'
44and with a bit luck you can get this module running...
Chris Liechti033f17c2015-08-30 21:28:04 +020045""" % (sys.platform, os.name, serial.VERSION))
Chris Liechtid6847af2015-08-06 17:54:30 +020046 raise NotImplementedError('no number-to-device mapping defined on this platform')
47
48 def _set_special_baudrate(self, baudrate):
49 raise NotImplementedError('non-standard baudrates are not supported on this platform')
50
51 def _set_rs485_mode(self, rs485_settings):
52 raise NotImplementedError('RS485 not supported on this platform')
53
54# try to detect the OS so that a device can be selected...
55# this code block should supply a device() and set_special_baudrate() function
56# for the platform
57plat = sys.platform.lower()
58
Chris Liechti033f17c2015-08-30 21:28:04 +020059if plat[:5] == 'linux': # Linux (confirmed)
Chris Liechtid6847af2015-08-06 17:54:30 +020060 import array
61
62 # baudrate ioctls
63 TCGETS2 = 0x802C542A
64 TCSETS2 = 0x402C542B
65 BOTHER = 0o010000
66
67 # RS485 ioctls
68 TIOCGRS485 = 0x542E
69 TIOCSRS485 = 0x542F
Chris Liechti033f17c2015-08-30 21:28:04 +020070 SER_RS485_ENABLED = 0b00000001
71 SER_RS485_RTS_ON_SEND = 0b00000010
Chris Liechtid6847af2015-08-06 17:54:30 +020072 SER_RS485_RTS_AFTER_SEND = 0b00000100
Chris Liechti033f17c2015-08-30 21:28:04 +020073 SER_RS485_RX_DURING_TX = 0b00010000
Chris Liechtid6847af2015-08-06 17:54:30 +020074
75 class PlatformSpecific(PlatformSpecificBase):
76 BAUDRATE_CONSTANTS = {
77 0: 0o000000, # hang up
78 50: 0o000001,
79 75: 0o000002,
80 110: 0o000003,
81 134: 0o000004,
82 150: 0o000005,
83 200: 0o000006,
84 300: 0o000007,
85 600: 0o000010,
86 1200: 0o000011,
87 1800: 0o000012,
88 2400: 0o000013,
89 4800: 0o000014,
90 9600: 0o000015,
91 19200: 0o000016,
92 38400: 0o000017,
93 57600: 0o010001,
94 115200: 0o010002,
95 230400: 0o010003,
96 460800: 0o010004,
97 500000: 0o010005,
98 576000: 0o010006,
99 921600: 0o010007,
100 1000000: 0o010010,
101 1152000: 0o010011,
102 1500000: 0o010012,
103 2000000: 0o010013,
104 2500000: 0o010014,
105 3000000: 0o010015,
106 3500000: 0o010016,
107 4000000: 0o010017
108 }
109
110 def number_to_device(self, port_number):
111 return '/dev/ttyS%d' % (port_number,)
112
113 def _set_special_baudrate(self, baudrate):
114 # right size is 44 on x86_64, allow for some growth
115 buf = array.array('i', [0] * 64)
116 try:
117 # get serial_struct
118 fcntl.ioctl(self.fd, TCGETS2, buf)
119 # set custom speed
120 buf[2] &= ~termios.CBAUD
121 buf[2] |= BOTHER
122 buf[9] = buf[10] = baudrate
123
124 # set serial_struct
Chris Liechti033f17c2015-08-30 21:28:04 +0200125 fcntl.ioctl(self.fd, TCSETS2, buf)
Chris Liechtid6847af2015-08-06 17:54:30 +0200126 except IOError as e:
127 raise ValueError('Failed to set custom baud rate (%s): %s' % (baudrate, e))
128
129 def _set_rs485_mode(self, rs485_settings):
Chris Liechti033f17c2015-08-30 21:28:04 +0200130 buf = array.array('i', [0] * 8) # flags, delaytx, delayrx, padding
Chris Liechtid6847af2015-08-06 17:54:30 +0200131 try:
132 fcntl.ioctl(self.fd, TIOCGRS485, buf)
133 if rs485_settings is not None:
134 if rs485_settings.loopback:
135 buf[0] |= SER_RS485_RX_DURING_TX
136 else:
137 buf[0] &= ~SER_RS485_RX_DURING_TX
138 if rs485_settings.rts_level_for_tx:
139 buf[0] |= SER_RS485_RTS_ON_SEND
140 else:
141 buf[0] &= ~SER_RS485_RTS_ON_SEND
142 if rs485_settings.rts_level_for_rx:
143 buf[0] |= SER_RS485_RTS_AFTER_SEND
144 else:
145 buf[0] &= ~SER_RS485_RTS_AFTER_SEND
146 buf[1] = int(rs485_settings.delay_rts_before_send * 1000)
147 buf[2] = int(rs485_settings.delay_rts_after_send * 1000)
148 else:
149 buf[0] = 0 # clear SER_RS485_ENABLED
Chris Liechti033f17c2015-08-30 21:28:04 +0200150 fcntl.ioctl(self.fd, TIOCSRS485, buf)
Chris Liechtid6847af2015-08-06 17:54:30 +0200151 except IOError as e:
152 raise ValueError('Failed to set RS485 mode: %s' % (e,))
153
154
155elif plat == 'cygwin': # cygwin/win32 (confirmed)
156
157 class PlatformSpecific(PlatformSpecificBase):
158 BAUDRATE_CONSTANTS = {
159 128000: 0x01003,
160 256000: 0x01005,
161 500000: 0x01007,
162 576000: 0x01008,
163 921600: 0x01009,
164 1000000: 0x0100a,
165 1152000: 0x0100b,
166 1500000: 0x0100c,
167 2000000: 0x0100d,
168 2500000: 0x0100e,
169 3000000: 0x0100f
170 }
171
172 def number_to_device(self, port_number):
173 return '/dev/com%d' % (port_number + 1,)
174
175
176elif plat[:7] == 'openbsd': # OpenBSD
177 class PlatformSpecific(PlatformSpecificBase):
178 def number_to_device(self, port_number):
179 return '/dev/cua%02d' % (port_number,)
180
181elif plat[:3] == 'bsd' or plat[:7] == 'freebsd':
182 class PlatformSpecific(PlatformSpecificBase):
183 def number_to_device(self, port_number):
184 return '/dev/cuad%d' % (port_number,)
185
186elif plat[:6] == 'darwin': # OS X
187 import array
Chris Liechti033f17c2015-08-30 21:28:04 +0200188 IOSSIOSPEED = 0x80045402 # _IOW('T', 2, speed_t)
Chris Liechtid6847af2015-08-06 17:54:30 +0200189
190 class PlatformSpecific(PlatformSpecificBase):
191 def number_to_device(self, port_number):
192 return '/dev/cuad%d' % (port_number,)
193
194 osx_version = os.uname()[2].split('.')
195 # Tiger or above can support arbitrary serial speeds
196 if int(osx_version[0]) >= 8:
197 def _set_special_baudrate(self, baudrate):
198 # use IOKit-specific call to set up high speeds
199 buf = array.array('i', [baudrate])
200 fcntl.ioctl(self.fd, IOSSIOSPEED, buf, 1)
201
202
203elif plat[:6] == 'netbsd': # NetBSD 1.6 testing by Erk
204 class PlatformSpecific(PlatformSpecificBase):
205 def number_to_device(self, port_number):
206 return '/dev/dty%02d' % (port_number,)
207
208elif plat[:4] == 'irix': # IRIX (partially tested)
209 class PlatformSpecific(PlatformSpecificBase):
210 def number_to_device(self, port_number):
Chris Liechti033f17c2015-08-30 21:28:04 +0200211 return '/dev/ttyf%d' % (port_number + 1,) # XXX different device names depending on flow control
Chris Liechtid6847af2015-08-06 17:54:30 +0200212
213elif plat[:2] == 'hp': # HP-UX (not tested)
214 class PlatformSpecific(PlatformSpecificBase):
215 def number_to_device(self, port_number):
216 return '/dev/tty%dp0' % (port_number + 1,)
217
218elif plat[:5] == 'sunos': # Solaris/SunOS (confirmed)
219 class PlatformSpecific(PlatformSpecificBase):
220 def number_to_device(self, port_number):
221 return '/dev/tty%c' % (ord('a') + port_number,)
222
223elif plat[:3] == 'aix': # AIX
224 class PlatformSpecific(PlatformSpecificBase):
225 def number_to_device(self, port_number):
226 return '/dev/tty%d' % (port_number,)
227
228else:
229 class PlatformSpecific(PlatformSpecificBase):
230 pass
cliechti89b4af12002-02-12 23:24:41 +0000231
cliechti58b481c2009-02-16 20:42:32 +0000232# whats up with "aix", "beos", ....
233# they should work, just need to know the device names.
cliechti89b4af12002-02-12 23:24:41 +0000234
235
cliechti58b481c2009-02-16 20:42:32 +0000236# load some constants for later use.
Chris Liechti11465c82015-08-04 15:55:22 +0200237# try to use values from termios, use defaults from linux otherwise
Chris Liechti033f17c2015-08-30 21:28:04 +0200238TIOCMGET = getattr(termios, 'TIOCMGET', 0x5415)
239TIOCMBIS = getattr(termios, 'TIOCMBIS', 0x5416)
240TIOCMBIC = getattr(termios, 'TIOCMBIC', 0x5417)
241TIOCMSET = getattr(termios, 'TIOCMSET', 0x5418)
cliechti89b4af12002-02-12 23:24:41 +0000242
Chris Liechti033f17c2015-08-30 21:28:04 +0200243# TIOCM_LE = getattr(termios, 'TIOCM_LE', 0x001)
Chris Liechtid6847af2015-08-06 17:54:30 +0200244TIOCM_DTR = getattr(termios, 'TIOCM_DTR', 0x002)
245TIOCM_RTS = getattr(termios, 'TIOCM_RTS', 0x004)
Chris Liechti033f17c2015-08-30 21:28:04 +0200246# TIOCM_ST = getattr(termios, 'TIOCM_ST', 0x008)
247# TIOCM_SR = getattr(termios, 'TIOCM_SR', 0x010)
cliechti89b4af12002-02-12 23:24:41 +0000248
Chris Liechtid6847af2015-08-06 17:54:30 +0200249TIOCM_CTS = getattr(termios, 'TIOCM_CTS', 0x020)
250TIOCM_CAR = getattr(termios, 'TIOCM_CAR', 0x040)
251TIOCM_RNG = getattr(termios, 'TIOCM_RNG', 0x080)
252TIOCM_DSR = getattr(termios, 'TIOCM_DSR', 0x100)
Chris Liechti033f17c2015-08-30 21:28:04 +0200253TIOCM_CD = getattr(termios, 'TIOCM_CD', TIOCM_CAR)
254TIOCM_RI = getattr(termios, 'TIOCM_RI', TIOCM_RNG)
255# TIOCM_OUT1 = getattr(termios, 'TIOCM_OUT1', 0x2000)
256# TIOCM_OUT2 = getattr(termios, 'TIOCM_OUT2', 0x4000)
Chris Liechti11465c82015-08-04 15:55:22 +0200257if hasattr(termios, 'TIOCINQ'):
258 TIOCINQ = termios.TIOCINQ
cliechti28b8fd02011-12-28 21:39:42 +0000259else:
Chris Liechtid6847af2015-08-06 17:54:30 +0200260 TIOCINQ = getattr(termios, 'FIONREAD', 0x541B)
Chris Liechti033f17c2015-08-30 21:28:04 +0200261TIOCOUTQ = getattr(termios, 'TIOCOUTQ', 0x5411)
cliechti89b4af12002-02-12 23:24:41 +0000262
263TIOCM_zero_str = struct.pack('I', 0)
264TIOCM_RTS_str = struct.pack('I', TIOCM_RTS)
265TIOCM_DTR_str = struct.pack('I', TIOCM_DTR)
266
Chris Liechti033f17c2015-08-30 21:28:04 +0200267TIOCSBRK = getattr(termios, 'TIOCSBRK', 0x5427)
268TIOCCBRK = getattr(termios, 'TIOCCBRK', 0x5428)
cliechti997b63c2008-06-21 00:09:31 +0000269
Chris Liechti033f17c2015-08-30 21:28:04 +0200270CMSPAR = 0o10000000000 # Use "stick" (mark/space) parity
cliechtiaec27ab2014-07-31 22:21:24 +0000271
cliechti89b4af12002-02-12 23:24:41 +0000272
Chris Liechtief6b7b42015-08-06 22:19:26 +0200273class Serial(SerialBase, PlatformSpecific):
cliechti7d448562014-08-03 21:57:45 +0000274 """\
Chris Liechti033f17c2015-08-30 21:28:04 +0200275 Serial port class POSIX implementation. Serial port configuration is
cliechtid6bf52c2003-10-01 02:28:12 +0000276 done with termios and fcntl. Runs on Linux and many other Un*x like
cliechtif0a81d42014-08-04 14:03:53 +0000277 systems.
278 """
cliechtid6bf52c2003-10-01 02:28:12 +0000279
280 def open(self):
cliechti7d448562014-08-03 21:57:45 +0000281 """\
282 Open port with current settings. This may throw a SerialException
283 if the port cannot be opened."""
cliechtid6bf52c2003-10-01 02:28:12 +0000284 if self._port is None:
285 raise SerialException("Port must be configured before it can be used.")
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200286 if self.is_open:
cliechti02ef43a2011-03-24 23:33:12 +0000287 raise SerialException("Port is already open.")
288 self.fd = None
cliechti58b481c2009-02-16 20:42:32 +0000289 # open
cliechti4616bf12002-04-08 23:13:14 +0000290 try:
Chris Liechti033f17c2015-08-30 21:28:04 +0200291 self.fd = os.open(self.portstr, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK)
Chris Liechti68340d72015-08-03 14:15:48 +0200292 except OSError as msg:
cliechti4616bf12002-04-08 23:13:14 +0000293 self.fd = None
cliechtiaf84daa2013-10-10 23:57:00 +0000294 raise SerialException(msg.errno, "could not open port %s: %s" % (self._port, msg))
Chris Liechti11465c82015-08-04 15:55:22 +0200295 #~ fcntl.fcntl(self.fd, fcntl.F_SETFL, 0) # set blocking
cliechti58b481c2009-02-16 20:42:32 +0000296
cliechtib2f5fc82006-10-20 00:09:07 +0000297 try:
Chris Liechti94284702015-11-15 01:21:48 +0100298 self._reconfigure_port(force_update=True)
cliechtib2f5fc82006-10-20 00:09:07 +0000299 except:
cliechti2750b832009-07-28 00:13:52 +0000300 try:
301 os.close(self.fd)
302 except:
303 # ignore any exception when closing the port
304 # also to keep original exception that happened when setting up
305 pass
cliechtib2f5fc82006-10-20 00:09:07 +0000306 self.fd = None
cliechtif0a4f0f2009-07-21 21:12:37 +0000307 raise
cliechtib2f5fc82006-10-20 00:09:07 +0000308 else:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200309 self.is_open = True
310 if not self._dsrdtr:
Chris Liechtief1fe252015-08-27 23:25:21 +0200311 self._update_dtr_state()
Chris Liechtidc2beec2015-09-18 21:25:28 +0200312 if not self._rtscts:
Chris Liechtief1fe252015-08-27 23:25:21 +0200313 self._update_rts_state()
314 self.reset_input_buffer()
cliechti58b481c2009-02-16 20:42:32 +0000315
Chris Liechti94284702015-11-15 01:21:48 +0100316 def _reconfigure_port(self, force_update=False):
cliechtib2f5fc82006-10-20 00:09:07 +0000317 """Set communication parameters on opened port."""
cliechtic6178262004-03-22 22:04:52 +0000318 if self.fd is None:
cliechtia9a093e2010-01-02 03:05:08 +0000319 raise SerialException("Can only operate on a valid file descriptor")
cliechtie8c45422008-06-20 23:23:14 +0000320 custom_baud = None
cliechti58b481c2009-02-16 20:42:32 +0000321
cliechti2750b832009-07-28 00:13:52 +0000322 vmin = vtime = 0 # timeout is done via select
Chris Liechti518b0d32015-08-30 02:20:39 +0200323 if self._inter_byte_timeout is not None:
cliechti679bfa62008-06-20 23:58:15 +0000324 vmin = 1
Chris Liechti518b0d32015-08-30 02:20:39 +0200325 vtime = int(self._inter_byte_timeout * 10)
cliechti6ce7ab12002-11-07 02:15:00 +0000326 try:
cliechti4d0af5e2011-08-05 02:18:16 +0000327 orig_attr = termios.tcgetattr(self.fd)
328 iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
Chris Liechti68340d72015-08-03 14:15:48 +0200329 except termios.error as msg: # if a port is nonexistent but has a /dev file, it'll fail here
cliechtid6bf52c2003-10-01 02:28:12 +0000330 raise SerialException("Could not configure port: %s" % msg)
cliechti58b481c2009-02-16 20:42:32 +0000331 # set up raw mode / no echo / binary
Chris Liechti033f17c2015-08-30 21:28:04 +0200332 cflag |= (termios.CLOCAL | termios.CREAD)
333 lflag &= ~(termios.ICANON | termios.ECHO | termios.ECHOE |
334 termios.ECHOK | termios.ECHONL |
335 termios.ISIG | termios.IEXTEN) # |termios.ECHOPRT
336 for flag in ('ECHOCTL', 'ECHOKE'): # netbsd workaround for Erk
Chris Liechti11465c82015-08-04 15:55:22 +0200337 if hasattr(termios, flag):
338 lflag &= ~getattr(termios, flag)
cliechti58b481c2009-02-16 20:42:32 +0000339
Chris Liechti033f17c2015-08-30 21:28:04 +0200340 oflag &= ~(termios.OPOST | termios.ONLCR | termios.OCRNL)
341 iflag &= ~(termios.INLCR | termios.IGNCR | termios.ICRNL | termios.IGNBRK)
Chris Liechti11465c82015-08-04 15:55:22 +0200342 if hasattr(termios, 'IUCLC'):
343 iflag &= ~termios.IUCLC
344 if hasattr(termios, 'PARMRK'):
345 iflag &= ~termios.PARMRK
cliechti58b481c2009-02-16 20:42:32 +0000346
cliechtif0a4f0f2009-07-21 21:12:37 +0000347 # setup baud rate
cliechti89b4af12002-02-12 23:24:41 +0000348 try:
Chris Liechti11465c82015-08-04 15:55:22 +0200349 ispeed = ospeed = getattr(termios, 'B%s' % (self._baudrate))
cliechti895e8302004-04-20 02:40:28 +0000350 except AttributeError:
cliechtif1559d02007-11-08 23:43:58 +0000351 try:
Chris Liechtid6847af2015-08-06 17:54:30 +0200352 ispeed = ospeed = self.BAUDRATE_CONSTANTS[self._baudrate]
cliechtif1559d02007-11-08 23:43:58 +0000353 except KeyError:
cliechtie8c45422008-06-20 23:23:14 +0000354 #~ raise ValueError('Invalid baud rate: %r' % self._baudrate)
cliechtif0a4f0f2009-07-21 21:12:37 +0000355 # may need custom baud rate, it isn't in our list.
Chris Liechti11465c82015-08-04 15:55:22 +0200356 ispeed = ospeed = getattr(termios, 'B38400')
cliechtif0a4f0f2009-07-21 21:12:37 +0000357 try:
Chris Liechti033f17c2015-08-30 21:28:04 +0200358 custom_baud = int(self._baudrate) # store for later
cliechtif0a4f0f2009-07-21 21:12:37 +0000359 except ValueError:
360 raise ValueError('Invalid baud rate: %r' % self._baudrate)
361 else:
362 if custom_baud < 0:
363 raise ValueError('Invalid baud rate: %r' % self._baudrate)
cliechti58b481c2009-02-16 20:42:32 +0000364
365 # setup char len
Chris Liechti11465c82015-08-04 15:55:22 +0200366 cflag &= ~termios.CSIZE
cliechtid6bf52c2003-10-01 02:28:12 +0000367 if self._bytesize == 8:
Chris Liechti11465c82015-08-04 15:55:22 +0200368 cflag |= termios.CS8
cliechtid6bf52c2003-10-01 02:28:12 +0000369 elif self._bytesize == 7:
Chris Liechti11465c82015-08-04 15:55:22 +0200370 cflag |= termios.CS7
cliechtid6bf52c2003-10-01 02:28:12 +0000371 elif self._bytesize == 6:
Chris Liechti11465c82015-08-04 15:55:22 +0200372 cflag |= termios.CS6
cliechtid6bf52c2003-10-01 02:28:12 +0000373 elif self._bytesize == 5:
Chris Liechti11465c82015-08-04 15:55:22 +0200374 cflag |= termios.CS5
cliechti89b4af12002-02-12 23:24:41 +0000375 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000376 raise ValueError('Invalid char len: %r' % self._bytesize)
cliechtif0a81d42014-08-04 14:03:53 +0000377 # setup stop bits
Chris Liechti033f17c2015-08-30 21:28:04 +0200378 if self._stopbits == serial.STOPBITS_ONE:
Chris Liechti11465c82015-08-04 15:55:22 +0200379 cflag &= ~(termios.CSTOPB)
Chris Liechti033f17c2015-08-30 21:28:04 +0200380 elif self._stopbits == serial.STOPBITS_ONE_POINT_FIVE:
381 cflag |= (termios.CSTOPB) # XXX same as TWO.. there is no POSIX support for 1.5
382 elif self._stopbits == serial.STOPBITS_TWO:
383 cflag |= (termios.CSTOPB)
cliechti89b4af12002-02-12 23:24:41 +0000384 else:
cliechti3172d3d2009-07-21 22:33:40 +0000385 raise ValueError('Invalid stop bit specification: %r' % self._stopbits)
cliechti58b481c2009-02-16 20:42:32 +0000386 # setup parity
Chris Liechti033f17c2015-08-30 21:28:04 +0200387 iflag &= ~(termios.INPCK | termios.ISTRIP)
388 if self._parity == serial.PARITY_NONE:
389 cflag &= ~(termios.PARENB | termios.PARODD)
390 elif self._parity == serial.PARITY_EVEN:
Chris Liechti11465c82015-08-04 15:55:22 +0200391 cflag &= ~(termios.PARODD)
Chris Liechti033f17c2015-08-30 21:28:04 +0200392 cflag |= (termios.PARENB)
393 elif self._parity == serial.PARITY_ODD:
394 cflag |= (termios.PARENB | termios.PARODD)
395 elif self._parity == serial.PARITY_MARK and plat[:5] == 'linux':
396 cflag |= (termios.PARENB | CMSPAR | termios.PARODD)
397 elif self._parity == serial.PARITY_SPACE and plat[:5] == 'linux':
398 cflag |= (termios.PARENB | CMSPAR)
Chris Liechti11465c82015-08-04 15:55:22 +0200399 cflag &= ~(termios.PARODD)
cliechti89b4af12002-02-12 23:24:41 +0000400 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000401 raise ValueError('Invalid parity: %r' % self._parity)
cliechti58b481c2009-02-16 20:42:32 +0000402 # setup flow control
403 # xonxoff
Chris Liechti11465c82015-08-04 15:55:22 +0200404 if hasattr(termios, 'IXANY'):
cliechtid6bf52c2003-10-01 02:28:12 +0000405 if self._xonxoff:
Chris Liechti033f17c2015-08-30 21:28:04 +0200406 iflag |= (termios.IXON | termios.IXOFF) # |termios.IXANY)
cliechti89b4af12002-02-12 23:24:41 +0000407 else:
Chris Liechti033f17c2015-08-30 21:28:04 +0200408 iflag &= ~(termios.IXON | termios.IXOFF | termios.IXANY)
cliechti89b4af12002-02-12 23:24:41 +0000409 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000410 if self._xonxoff:
Chris Liechti033f17c2015-08-30 21:28:04 +0200411 iflag |= (termios.IXON | termios.IXOFF)
cliechti89b4af12002-02-12 23:24:41 +0000412 else:
Chris Liechti033f17c2015-08-30 21:28:04 +0200413 iflag &= ~(termios.IXON | termios.IXOFF)
cliechti58b481c2009-02-16 20:42:32 +0000414 # rtscts
Chris Liechti11465c82015-08-04 15:55:22 +0200415 if hasattr(termios, 'CRTSCTS'):
cliechtid6bf52c2003-10-01 02:28:12 +0000416 if self._rtscts:
Chris Liechti033f17c2015-08-30 21:28:04 +0200417 cflag |= (termios.CRTSCTS)
cliechti89b4af12002-02-12 23:24:41 +0000418 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200419 cflag &= ~(termios.CRTSCTS)
420 elif hasattr(termios, 'CNEW_RTSCTS'): # try it with alternate constant name
cliechtid6bf52c2003-10-01 02:28:12 +0000421 if self._rtscts:
Chris Liechti033f17c2015-08-30 21:28:04 +0200422 cflag |= (termios.CNEW_RTSCTS)
cliechtid4743692002-04-08 22:39:53 +0000423 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200424 cflag &= ~(termios.CNEW_RTSCTS)
cliechti2750b832009-07-28 00:13:52 +0000425 # XXX should there be a warning if setting up rtscts (and xonxoff etc) fails??
cliechti58b481c2009-02-16 20:42:32 +0000426
427 # buffer
cliechtif0a81d42014-08-04 14:03:53 +0000428 # vmin "minimal number of characters to be read. 0 for non blocking"
cliechtid6bf52c2003-10-01 02:28:12 +0000429 if vmin < 0 or vmin > 255:
430 raise ValueError('Invalid vmin: %r ' % vmin)
Chris Liechti11465c82015-08-04 15:55:22 +0200431 cc[termios.VMIN] = vmin
cliechti58b481c2009-02-16 20:42:32 +0000432 # vtime
cliechtid6bf52c2003-10-01 02:28:12 +0000433 if vtime < 0 or vtime > 255:
434 raise ValueError('Invalid vtime: %r' % vtime)
Chris Liechti11465c82015-08-04 15:55:22 +0200435 cc[termios.VTIME] = vtime
cliechti58b481c2009-02-16 20:42:32 +0000436 # activate settings
Chris Liechti94284702015-11-15 01:21:48 +0100437 if force_update or [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] != orig_attr:
Chris Liechti033f17c2015-08-30 21:28:04 +0200438 termios.tcsetattr(
439 self.fd,
440 termios.TCSANOW,
441 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
cliechti58b481c2009-02-16 20:42:32 +0000442
cliechtie8c45422008-06-20 23:23:14 +0000443 # apply custom baud rate, if any
444 if custom_baud is not None:
Chris Liechtid6847af2015-08-06 17:54:30 +0200445 self._set_special_baudrate(custom_baud)
446
447 if self._rs485_mode is not None:
448 self._set_rs485_mode(self._rs485_mode)
cliechti89b4af12002-02-12 23:24:41 +0000449
450 def close(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000451 """Close port"""
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200452 if self.is_open:
cliechtic6178262004-03-22 22:04:52 +0000453 if self.fd is not None:
cliechtid6bf52c2003-10-01 02:28:12 +0000454 os.close(self.fd)
455 self.fd = None
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200456 self.is_open = False
cliechtid6bf52c2003-10-01 02:28:12 +0000457
458 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechti95c62212002-03-04 22:17:53 +0000459
Chris Liechtief1fe252015-08-27 23:25:21 +0200460 @property
461 def in_waiting(self):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200462 """Return the number of bytes currently in the input buffer."""
Chris Liechti11465c82015-08-04 15:55:22 +0200463 #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str)
cliechtif5831e02002-12-05 23:15:27 +0000464 s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200465 return struct.unpack('I', s)[0]
cliechti89b4af12002-02-12 23:24:41 +0000466
cliechtia9a093e2010-01-02 03:05:08 +0000467 # select based implementation, proved to work on many systems
468 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000469 """\
470 Read size bytes from the serial port. If a timeout is set it may
471 return less characters as requested. With no timeout it will block
472 until the requested number of bytes is read.
473 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200474 if not self.is_open:
475 raise portNotOpenError
cliechtia9a093e2010-01-02 03:05:08 +0000476 read = bytearray()
Cristiano De Altic30622f2015-12-12 11:00:01 +0100477 timeout = self._timeout
cliechtia9a093e2010-01-02 03:05:08 +0000478 while len(read) < size:
cliechti8d744de2013-10-11 14:31:13 +0000479 try:
Cristiano De Altic30622f2015-12-12 11:00:01 +0100480 start_time = time.time()
481 ready, _, _ = select.select([self.fd], [], [], timeout)
cliechti8d744de2013-10-11 14:31:13 +0000482 # If select was used with a timeout, and the timeout occurs, it
483 # returns with empty lists -> thus abort read operation.
Chris Liechti033f17c2015-08-30 21:28:04 +0200484 # For timeout == 0 (non-blocking operation) also abort when
485 # there is nothing to read.
cliechti8d744de2013-10-11 14:31:13 +0000486 if not ready:
487 break # timeout
Chris Liechti033f17c2015-08-30 21:28:04 +0200488 buf = os.read(self.fd, size - len(read))
cliechti8d744de2013-10-11 14:31:13 +0000489 # read should always return some data as select reported it was
490 # ready to read when we get to this point.
491 if not buf:
492 # Disconnected devices, at least on Linux, show the
493 # behavior that they are always ready to read immediately
494 # but reading returns nothing.
495 raise SerialException('device reports readiness to read but returned no data (device disconnected or multiple access on port?)')
496 read.extend(buf)
Cristiano De Altic30622f2015-12-12 11:00:01 +0100497 if timeout is not None:
498 timeout -= time.time() - start_time
499 if timeout <= 0:
500 break
Chris Liechti68340d72015-08-03 14:15:48 +0200501 except OSError as e:
Chris Liechti033f17c2015-08-30 21:28:04 +0200502 # this is for Python 3.x where select.error is a subclass of
503 # OSError ignore EAGAIN errors. all other errors are shown
cliechtic7cd7212014-08-03 21:34:38 +0000504 if e.errno != errno.EAGAIN:
505 raise SerialException('read failed: %s' % (e,))
Chris Liechti68340d72015-08-03 14:15:48 +0200506 except select.error as e:
cliechtic7cd7212014-08-03 21:34:38 +0000507 # this is for Python 2.x
cliechti8d744de2013-10-11 14:31:13 +0000508 # ignore EAGAIN errors. all other errors are shown
509 # see also http://www.python.org/dev/peps/pep-3151/#select
510 if e[0] != errno.EAGAIN:
511 raise SerialException('read failed: %s' % (e,))
cliechtia9a093e2010-01-02 03:05:08 +0000512 return bytes(read)
cliechti89b4af12002-02-12 23:24:41 +0000513
cliechti4a567a02009-07-27 22:09:31 +0000514 def write(self, data):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200515 """Output the given byte string over the serial port."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200516 if not self.is_open:
517 raise portNotOpenError
cliechti38077122013-10-16 02:57:27 +0000518 d = to_bytes(data)
519 tx_len = len(d)
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200520 if self._write_timeout is not None and self._write_timeout > 0:
521 timeout = time.time() + self._write_timeout
cliechti3cf46d62009-08-07 00:19:57 +0000522 else:
523 timeout = None
cliechti9f7c2352013-10-11 01:13:46 +0000524 while tx_len > 0:
cliechti5d4d0bd2004-11-13 03:27:39 +0000525 try:
cliechti5d4d0bd2004-11-13 03:27:39 +0000526 n = os.write(self.fd, d)
cliechti3cf46d62009-08-07 00:19:57 +0000527 if timeout:
528 # when timeout is set, use select to wait for being ready
529 # with the time left as timeout
530 timeleft = timeout - time.time()
531 if timeleft < 0:
532 raise writeTimeoutError
533 _, ready, _ = select.select([], [self.fd], [], timeleft)
cliechti5d4d0bd2004-11-13 03:27:39 +0000534 if not ready:
535 raise writeTimeoutError
cliechti88c62442013-10-12 04:03:16 +0000536 else:
537 # wait for write operation
538 _, ready, _ = select.select([], [self.fd], [], None)
539 if not ready:
540 raise SerialException('write failed (select)')
cliechti5d4d0bd2004-11-13 03:27:39 +0000541 d = d[n:]
cliechti9f7c2352013-10-11 01:13:46 +0000542 tx_len -= n
Chris Liechti675f7e12015-08-03 15:48:41 +0200543 except SerialException:
544 raise
Chris Liechti68340d72015-08-03 14:15:48 +0200545 except OSError as v:
cliechti5d4d0bd2004-11-13 03:27:39 +0000546 if v.errno != errno.EAGAIN:
cliechti65722c92009-08-07 00:48:53 +0000547 raise SerialException('write failed: %s' % (v,))
Chris Liechtic6362db2015-12-13 23:44:35 +0100548 # still calculate and check timeout
549 if timeout and timeout - time.time() < 0:
550 raise writeTimeoutError
cliechtif81362e2009-07-25 03:44:33 +0000551 return len(data)
cliechtid6bf52c2003-10-01 02:28:12 +0000552
cliechtia30a8a02003-10-05 12:28:13 +0000553 def flush(self):
cliechti7d448562014-08-03 21:57:45 +0000554 """\
555 Flush of file like objects. In this case, wait until all data
556 is written.
557 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200558 if not self.is_open:
559 raise portNotOpenError
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200560 termios.tcdrain(self.fd)
cliechtia30a8a02003-10-05 12:28:13 +0000561
Chris Liechtief1fe252015-08-27 23:25:21 +0200562 def reset_input_buffer(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000563 """Clear input buffer, discarding all that is in the buffer."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200564 if not self.is_open:
565 raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200566 termios.tcflush(self.fd, termios.TCIFLUSH)
cliechti89b4af12002-02-12 23:24:41 +0000567
Chris Liechtief1fe252015-08-27 23:25:21 +0200568 def reset_output_buffer(self):
cliechti7d448562014-08-03 21:57:45 +0000569 """\
570 Clear output buffer, aborting the current output and discarding all
571 that is in the buffer.
572 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200573 if not self.is_open:
574 raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200575 termios.tcflush(self.fd, termios.TCOFLUSH)
cliechti89b4af12002-02-12 23:24:41 +0000576
Chris Liechtief1fe252015-08-27 23:25:21 +0200577 def send_break(self, duration=0.25):
cliechti7d448562014-08-03 21:57:45 +0000578 """\
579 Send break condition. Timed, returns to idle state after given
580 duration.
581 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200582 if not self.is_open:
583 raise portNotOpenError
584 termios.tcsendbreak(self.fd, int(duration / 0.25))
cliechti89b4af12002-02-12 23:24:41 +0000585
Chris Liechtief1fe252015-08-27 23:25:21 +0200586 def _update_break_state(self):
cliechti7d448562014-08-03 21:57:45 +0000587 """\
588 Set break: Controls TXD. When active, no transmitting is possible.
589 """
Chris Liechtief1fe252015-08-27 23:25:21 +0200590 if self._break_state:
cliechti997b63c2008-06-21 00:09:31 +0000591 fcntl.ioctl(self.fd, TIOCSBRK)
592 else:
593 fcntl.ioctl(self.fd, TIOCCBRK)
594
Chris Liechtief1fe252015-08-27 23:25:21 +0200595 def _update_rts_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000596 """Set terminal status line: Request To Send"""
Chris Liechti4cf65392016-01-21 23:57:02 +0100597 if self._rts_state is not None:
598 if self._rts_state:
599 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_RTS_str)
600 else:
601 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_RTS_str)
cliechtid6bf52c2003-10-01 02:28:12 +0000602
Chris Liechtief1fe252015-08-27 23:25:21 +0200603 def _update_dtr_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000604 """Set terminal status line: Data Terminal Ready"""
Chris Liechti4cf65392016-01-21 23:57:02 +0100605 if self._dtr_state is not None:
606 if self._dtr_state:
607 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str)
608 else:
609 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_DTR_str)
cliechtid6bf52c2003-10-01 02:28:12 +0000610
Chris Liechtief1fe252015-08-27 23:25:21 +0200611 @property
612 def cts(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000613 """Read terminal status line: Clear To Send"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200614 if not self.is_open:
615 raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000616 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200617 return struct.unpack('I', s)[0] & TIOCM_CTS != 0
cliechtid6bf52c2003-10-01 02:28:12 +0000618
Chris Liechtief1fe252015-08-27 23:25:21 +0200619 @property
620 def dsr(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000621 """Read terminal status line: Data Set Ready"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200622 if not self.is_open:
623 raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000624 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200625 return struct.unpack('I', s)[0] & TIOCM_DSR != 0
cliechtid6bf52c2003-10-01 02:28:12 +0000626
Chris Liechtief1fe252015-08-27 23:25:21 +0200627 @property
628 def ri(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000629 """Read terminal status line: Ring Indicator"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200630 if not self.is_open:
631 raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000632 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200633 return struct.unpack('I', s)[0] & TIOCM_RI != 0
cliechti89b4af12002-02-12 23:24:41 +0000634
Chris Liechtief1fe252015-08-27 23:25:21 +0200635 @property
636 def cd(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000637 """Read terminal status line: Carrier Detect"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200638 if not self.is_open:
639 raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000640 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200641 return struct.unpack('I', s)[0] & TIOCM_CD != 0
cliechti89b4af12002-02-12 23:24:41 +0000642
cliechtia30a8a02003-10-05 12:28:13 +0000643 # - - platform specific - - - -
644
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200645 @property
646 def out_waiting(self):
647 """Return the number of bytes currently in the output buffer."""
Chris Liechti11465c82015-08-04 15:55:22 +0200648 #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str)
cliechti28b8fd02011-12-28 21:39:42 +0000649 s = fcntl.ioctl(self.fd, TIOCOUTQ, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200650 return struct.unpack('I', s)[0]
cliechti28b8fd02011-12-28 21:39:42 +0000651
cliechtia30a8a02003-10-05 12:28:13 +0000652 def nonblocking(self):
653 """internal - not portable!"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200654 if not self.is_open:
655 raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200656 fcntl.fcntl(self.fd, fcntl.F_SETFL, os.O_NONBLOCK)
cliechtia30a8a02003-10-05 12:28:13 +0000657
cliechti8753bbc2005-01-15 20:32:51 +0000658 def fileno(self):
cliechti2f0f8a32011-12-28 22:10:00 +0000659 """\
660 For easier use of the serial port instance with select.
661 WARNING: this function is not portable to different platforms!
662 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200663 if not self.is_open:
664 raise portNotOpenError
cliechti8753bbc2005-01-15 20:32:51 +0000665 return self.fd
cliechti89b4af12002-02-12 23:24:41 +0000666
Chris Liechti518b0d32015-08-30 02:20:39 +0200667 def set_input_flow_control(self, enable=True):
cliechti2f0f8a32011-12-28 22:10:00 +0000668 """\
669 Manually control flow - when software flow control is enabled.
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200670 This will send XON (true) or XOFF (false) to the other device.
cliechti2f0f8a32011-12-28 22:10:00 +0000671 WARNING: this function is not portable to different platforms!
672 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200673 if not self.is_open:
674 raise portNotOpenError
cliechti4a601342011-12-29 02:22:17 +0000675 if enable:
Chris Liechti11465c82015-08-04 15:55:22 +0200676 termios.tcflow(self.fd, termios.TCION)
cliechti57e48a62009-08-03 22:29:58 +0000677 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200678 termios.tcflow(self.fd, termios.TCIOFF)
cliechti57e48a62009-08-03 22:29:58 +0000679
Chris Liechti518b0d32015-08-30 02:20:39 +0200680 def set_output_flow_control(self, enable=True):
cliechti2f0f8a32011-12-28 22:10:00 +0000681 """\
682 Manually control flow of outgoing data - when hardware or software flow
683 control is enabled.
684 WARNING: this function is not portable to different platforms!
685 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200686 if not self.is_open:
687 raise portNotOpenError
cliechti2f0f8a32011-12-28 22:10:00 +0000688 if enable:
Chris Liechti11465c82015-08-04 15:55:22 +0200689 termios.tcflow(self.fd, termios.TCOON)
cliechti2f0f8a32011-12-28 22:10:00 +0000690 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200691 termios.tcflow(self.fd, termios.TCOOFF)
cliechti2f0f8a32011-12-28 22:10:00 +0000692
cliechtif81362e2009-07-25 03:44:33 +0000693
cliechtia9a093e2010-01-02 03:05:08 +0000694class PosixPollSerial(Serial):
cliechti7d448562014-08-03 21:57:45 +0000695 """\
cliechtif0a81d42014-08-04 14:03:53 +0000696 Poll based read implementation. Not all systems support poll properly.
697 However this one has better handling of errors, such as a device
cliechti7d448562014-08-03 21:57:45 +0000698 disconnecting while it's in use (e.g. USB-serial unplugged).
699 """
cliechtia9a093e2010-01-02 03:05:08 +0000700
701 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000702 """\
703 Read size bytes from the serial port. If a timeout is set it may
704 return less characters as requested. With no timeout it will block
705 until the requested number of bytes is read.
706 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200707 if self.fd is None:
708 raise portNotOpenError
cliechtia9a093e2010-01-02 03:05:08 +0000709 read = bytearray()
710 poll = select.poll()
Chris Liechti033f17c2015-08-30 21:28:04 +0200711 poll.register(self.fd, select.POLLIN | select.POLLERR | select.POLLHUP | select.POLLNVAL)
cliechtia9a093e2010-01-02 03:05:08 +0000712 if size > 0:
713 while len(read) < size:
714 # print "\tread(): size",size, "have", len(read) #debug
715 # wait until device becomes ready to read (or something fails)
Chris Liechti033f17c2015-08-30 21:28:04 +0200716 for fd, event in poll.poll(self._timeout * 1000):
717 if event & (select.POLLERR | select.POLLHUP | select.POLLNVAL):
cliechtia9a093e2010-01-02 03:05:08 +0000718 raise SerialException('device reports error (poll)')
719 # we don't care if it is select.POLLIN or timeout, that's
720 # handled below
721 buf = os.read(self.fd, size - len(read))
722 read.extend(buf)
Chris Liechti518b0d32015-08-30 02:20:39 +0200723 if ((self._timeout is not None and self._timeout >= 0) or
Chris Liechti033f17c2015-08-30 21:28:04 +0200724 (self._inter_byte_timeout is not None and self._inter_byte_timeout > 0)) and not buf:
cliechtia9a093e2010-01-02 03:05:08 +0000725 break # early abort on timeout
726 return bytes(read)
727
cliechtif81362e2009-07-25 03:44:33 +0000728
Chris Liechti4cf54702015-10-18 00:21:56 +0200729class VTIMESerial(Serial):
730 """\
731 Implement timeout using vtime of tty device instead of using select.
732 This means that no inter character timeout can be specified and that
733 the error handling is degraded.
734
735 Overall timeout is disabled when inter-character timeout is used.
736 """
737
Chris Liechti94284702015-11-15 01:21:48 +0100738 def _reconfigure_port(self, force_update=True):
Chris Liechti4cf54702015-10-18 00:21:56 +0200739 """Set communication parameters on opened port."""
740 super(VTIMESerial, self)._reconfigure_port()
741 fcntl.fcntl(self.fd, fcntl.F_SETFL, 0) # clear O_NONBLOCK
742
743 if self._inter_byte_timeout is not None:
744 vmin = 1
745 vtime = int(self._inter_byte_timeout * 10)
746 else:
747 vmin = 0
748 vtime = int(self._timeout * 10)
749 try:
750 orig_attr = termios.tcgetattr(self.fd)
751 iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
752 except termios.error as msg: # if a port is nonexistent but has a /dev file, it'll fail here
753 raise serial.SerialException("Could not configure port: %s" % msg)
754
755 if vtime < 0 or vtime > 255:
756 raise ValueError('Invalid vtime: %r' % vtime)
757 cc[termios.VTIME] = vtime
758 cc[termios.VMIN] = vmin
759
760 termios.tcsetattr(
761 self.fd,
762 termios.TCSANOW,
763 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
764
765
766 def read(self, size=1):
767 """\
768 Read size bytes from the serial port. If a timeout is set it may
769 return less characters as requested. With no timeout it will block
770 until the requested number of bytes is read.
771 """
772 if not self.is_open:
773 raise portNotOpenError
774 read = bytearray()
775 while len(read) < size:
776 buf = os.read(self.fd, size - len(read))
777 if not buf:
778 break
779 read.extend(buf)
780 return bytes(read)