blob: 7e432c7336b0154b2252ca0d700adc3cfad2813f [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 Liechtiba45c522016-02-06 23:53:23 +010059if plat[:5] == 'linux': # Linux (confirmed) # noqa
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.
Chris Liechti92df95a2016-02-09 23:30:37 +0100495 raise SerialException(
496 'device reports readiness to read but returned no data '
497 '(device disconnected or multiple access on port?)')
cliechti8d744de2013-10-11 14:31:13 +0000498 read.extend(buf)
Cristiano De Altic30622f2015-12-12 11:00:01 +0100499 if timeout is not None:
500 timeout -= time.time() - start_time
501 if timeout <= 0:
502 break
Chris Liechti68340d72015-08-03 14:15:48 +0200503 except OSError as e:
Chris Liechti033f17c2015-08-30 21:28:04 +0200504 # this is for Python 3.x where select.error is a subclass of
505 # OSError ignore EAGAIN errors. all other errors are shown
cliechtic7cd7212014-08-03 21:34:38 +0000506 if e.errno != errno.EAGAIN:
507 raise SerialException('read failed: %s' % (e,))
Chris Liechti68340d72015-08-03 14:15:48 +0200508 except select.error as e:
cliechtic7cd7212014-08-03 21:34:38 +0000509 # this is for Python 2.x
cliechti8d744de2013-10-11 14:31:13 +0000510 # ignore EAGAIN errors. all other errors are shown
511 # see also http://www.python.org/dev/peps/pep-3151/#select
512 if e[0] != errno.EAGAIN:
513 raise SerialException('read failed: %s' % (e,))
cliechtia9a093e2010-01-02 03:05:08 +0000514 return bytes(read)
cliechti89b4af12002-02-12 23:24:41 +0000515
cliechti4a567a02009-07-27 22:09:31 +0000516 def write(self, data):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200517 """Output the given byte string over the serial port."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200518 if not self.is_open:
519 raise portNotOpenError
cliechti38077122013-10-16 02:57:27 +0000520 d = to_bytes(data)
521 tx_len = len(d)
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200522 if self._write_timeout is not None and self._write_timeout > 0:
523 timeout = time.time() + self._write_timeout
cliechti3cf46d62009-08-07 00:19:57 +0000524 else:
525 timeout = None
cliechti9f7c2352013-10-11 01:13:46 +0000526 while tx_len > 0:
cliechti5d4d0bd2004-11-13 03:27:39 +0000527 try:
cliechti5d4d0bd2004-11-13 03:27:39 +0000528 n = os.write(self.fd, d)
cliechti3cf46d62009-08-07 00:19:57 +0000529 if timeout:
530 # when timeout is set, use select to wait for being ready
531 # with the time left as timeout
532 timeleft = timeout - time.time()
533 if timeleft < 0:
534 raise writeTimeoutError
535 _, ready, _ = select.select([], [self.fd], [], timeleft)
cliechti5d4d0bd2004-11-13 03:27:39 +0000536 if not ready:
537 raise writeTimeoutError
cliechti88c62442013-10-12 04:03:16 +0000538 else:
539 # wait for write operation
540 _, ready, _ = select.select([], [self.fd], [], None)
541 if not ready:
542 raise SerialException('write failed (select)')
cliechti5d4d0bd2004-11-13 03:27:39 +0000543 d = d[n:]
cliechti9f7c2352013-10-11 01:13:46 +0000544 tx_len -= n
Chris Liechti675f7e12015-08-03 15:48:41 +0200545 except SerialException:
546 raise
Chris Liechti68340d72015-08-03 14:15:48 +0200547 except OSError as v:
cliechti5d4d0bd2004-11-13 03:27:39 +0000548 if v.errno != errno.EAGAIN:
cliechti65722c92009-08-07 00:48:53 +0000549 raise SerialException('write failed: %s' % (v,))
Chris Liechtic6362db2015-12-13 23:44:35 +0100550 # still calculate and check timeout
551 if timeout and timeout - time.time() < 0:
552 raise writeTimeoutError
cliechtif81362e2009-07-25 03:44:33 +0000553 return len(data)
cliechtid6bf52c2003-10-01 02:28:12 +0000554
cliechtia30a8a02003-10-05 12:28:13 +0000555 def flush(self):
cliechti7d448562014-08-03 21:57:45 +0000556 """\
557 Flush of file like objects. In this case, wait until all data
558 is written.
559 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200560 if not self.is_open:
561 raise portNotOpenError
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200562 termios.tcdrain(self.fd)
cliechtia30a8a02003-10-05 12:28:13 +0000563
Chris Liechtief1fe252015-08-27 23:25:21 +0200564 def reset_input_buffer(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000565 """Clear input buffer, discarding all that is in the buffer."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200566 if not self.is_open:
567 raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200568 termios.tcflush(self.fd, termios.TCIFLUSH)
cliechti89b4af12002-02-12 23:24:41 +0000569
Chris Liechtief1fe252015-08-27 23:25:21 +0200570 def reset_output_buffer(self):
cliechti7d448562014-08-03 21:57:45 +0000571 """\
572 Clear output buffer, aborting the current output and discarding all
573 that is in the buffer.
574 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200575 if not self.is_open:
576 raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200577 termios.tcflush(self.fd, termios.TCOFLUSH)
cliechti89b4af12002-02-12 23:24:41 +0000578
Chris Liechtief1fe252015-08-27 23:25:21 +0200579 def send_break(self, duration=0.25):
cliechti7d448562014-08-03 21:57:45 +0000580 """\
581 Send break condition. Timed, returns to idle state after given
582 duration.
583 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200584 if not self.is_open:
585 raise portNotOpenError
586 termios.tcsendbreak(self.fd, int(duration / 0.25))
cliechti89b4af12002-02-12 23:24:41 +0000587
Chris Liechtief1fe252015-08-27 23:25:21 +0200588 def _update_break_state(self):
cliechti7d448562014-08-03 21:57:45 +0000589 """\
590 Set break: Controls TXD. When active, no transmitting is possible.
591 """
Chris Liechtief1fe252015-08-27 23:25:21 +0200592 if self._break_state:
cliechti997b63c2008-06-21 00:09:31 +0000593 fcntl.ioctl(self.fd, TIOCSBRK)
594 else:
595 fcntl.ioctl(self.fd, TIOCCBRK)
596
Chris Liechtief1fe252015-08-27 23:25:21 +0200597 def _update_rts_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000598 """Set terminal status line: Request To Send"""
Chris Liechti4cf65392016-01-21 23:57:02 +0100599 if self._rts_state is not None:
600 if self._rts_state:
601 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_RTS_str)
602 else:
603 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_RTS_str)
cliechtid6bf52c2003-10-01 02:28:12 +0000604
Chris Liechtief1fe252015-08-27 23:25:21 +0200605 def _update_dtr_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000606 """Set terminal status line: Data Terminal Ready"""
Chris Liechti4cf65392016-01-21 23:57:02 +0100607 if self._dtr_state is not None:
608 if self._dtr_state:
609 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str)
610 else:
611 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_DTR_str)
cliechtid6bf52c2003-10-01 02:28:12 +0000612
Chris Liechtief1fe252015-08-27 23:25:21 +0200613 @property
614 def cts(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000615 """Read terminal status line: Clear To Send"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200616 if not self.is_open:
617 raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000618 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200619 return struct.unpack('I', s)[0] & TIOCM_CTS != 0
cliechtid6bf52c2003-10-01 02:28:12 +0000620
Chris Liechtief1fe252015-08-27 23:25:21 +0200621 @property
622 def dsr(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000623 """Read terminal status line: Data Set Ready"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200624 if not self.is_open:
625 raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000626 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200627 return struct.unpack('I', s)[0] & TIOCM_DSR != 0
cliechtid6bf52c2003-10-01 02:28:12 +0000628
Chris Liechtief1fe252015-08-27 23:25:21 +0200629 @property
630 def ri(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000631 """Read terminal status line: Ring Indicator"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200632 if not self.is_open:
633 raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000634 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200635 return struct.unpack('I', s)[0] & TIOCM_RI != 0
cliechti89b4af12002-02-12 23:24:41 +0000636
Chris Liechtief1fe252015-08-27 23:25:21 +0200637 @property
638 def cd(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000639 """Read terminal status line: Carrier Detect"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200640 if not self.is_open:
641 raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000642 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200643 return struct.unpack('I', s)[0] & TIOCM_CD != 0
cliechti89b4af12002-02-12 23:24:41 +0000644
cliechtia30a8a02003-10-05 12:28:13 +0000645 # - - platform specific - - - -
646
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200647 @property
648 def out_waiting(self):
649 """Return the number of bytes currently in the output buffer."""
Chris Liechti11465c82015-08-04 15:55:22 +0200650 #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str)
cliechti28b8fd02011-12-28 21:39:42 +0000651 s = fcntl.ioctl(self.fd, TIOCOUTQ, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200652 return struct.unpack('I', s)[0]
cliechti28b8fd02011-12-28 21:39:42 +0000653
cliechtia30a8a02003-10-05 12:28:13 +0000654 def nonblocking(self):
655 """internal - not portable!"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200656 if not self.is_open:
657 raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200658 fcntl.fcntl(self.fd, fcntl.F_SETFL, os.O_NONBLOCK)
cliechtia30a8a02003-10-05 12:28:13 +0000659
cliechti8753bbc2005-01-15 20:32:51 +0000660 def fileno(self):
cliechti2f0f8a32011-12-28 22:10:00 +0000661 """\
662 For easier use of the serial port instance with select.
663 WARNING: this function is not portable to different platforms!
664 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200665 if not self.is_open:
666 raise portNotOpenError
cliechti8753bbc2005-01-15 20:32:51 +0000667 return self.fd
cliechti89b4af12002-02-12 23:24:41 +0000668
Chris Liechti518b0d32015-08-30 02:20:39 +0200669 def set_input_flow_control(self, enable=True):
cliechti2f0f8a32011-12-28 22:10:00 +0000670 """\
671 Manually control flow - when software flow control is enabled.
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200672 This will send XON (true) or XOFF (false) to the other device.
cliechti2f0f8a32011-12-28 22:10:00 +0000673 WARNING: this function is not portable to different platforms!
674 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200675 if not self.is_open:
676 raise portNotOpenError
cliechti4a601342011-12-29 02:22:17 +0000677 if enable:
Chris Liechti11465c82015-08-04 15:55:22 +0200678 termios.tcflow(self.fd, termios.TCION)
cliechti57e48a62009-08-03 22:29:58 +0000679 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200680 termios.tcflow(self.fd, termios.TCIOFF)
cliechti57e48a62009-08-03 22:29:58 +0000681
Chris Liechti518b0d32015-08-30 02:20:39 +0200682 def set_output_flow_control(self, enable=True):
cliechti2f0f8a32011-12-28 22:10:00 +0000683 """\
684 Manually control flow of outgoing data - when hardware or software flow
685 control is enabled.
686 WARNING: this function is not portable to different platforms!
687 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200688 if not self.is_open:
689 raise portNotOpenError
cliechti2f0f8a32011-12-28 22:10:00 +0000690 if enable:
Chris Liechti11465c82015-08-04 15:55:22 +0200691 termios.tcflow(self.fd, termios.TCOON)
cliechti2f0f8a32011-12-28 22:10:00 +0000692 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200693 termios.tcflow(self.fd, termios.TCOOFF)
cliechti2f0f8a32011-12-28 22:10:00 +0000694
cliechtif81362e2009-07-25 03:44:33 +0000695
cliechtia9a093e2010-01-02 03:05:08 +0000696class PosixPollSerial(Serial):
cliechti7d448562014-08-03 21:57:45 +0000697 """\
cliechtif0a81d42014-08-04 14:03:53 +0000698 Poll based read implementation. Not all systems support poll properly.
699 However this one has better handling of errors, such as a device
cliechti7d448562014-08-03 21:57:45 +0000700 disconnecting while it's in use (e.g. USB-serial unplugged).
701 """
cliechtia9a093e2010-01-02 03:05:08 +0000702
703 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000704 """\
705 Read size bytes from the serial port. If a timeout is set it may
706 return less characters as requested. With no timeout it will block
707 until the requested number of bytes is read.
708 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200709 if self.fd is None:
710 raise portNotOpenError
cliechtia9a093e2010-01-02 03:05:08 +0000711 read = bytearray()
712 poll = select.poll()
Chris Liechti033f17c2015-08-30 21:28:04 +0200713 poll.register(self.fd, select.POLLIN | select.POLLERR | select.POLLHUP | select.POLLNVAL)
cliechtia9a093e2010-01-02 03:05:08 +0000714 if size > 0:
715 while len(read) < size:
716 # print "\tread(): size",size, "have", len(read) #debug
717 # wait until device becomes ready to read (or something fails)
Chris Liechti033f17c2015-08-30 21:28:04 +0200718 for fd, event in poll.poll(self._timeout * 1000):
719 if event & (select.POLLERR | select.POLLHUP | select.POLLNVAL):
cliechtia9a093e2010-01-02 03:05:08 +0000720 raise SerialException('device reports error (poll)')
721 # we don't care if it is select.POLLIN or timeout, that's
722 # handled below
723 buf = os.read(self.fd, size - len(read))
724 read.extend(buf)
Chris Liechti518b0d32015-08-30 02:20:39 +0200725 if ((self._timeout is not None and self._timeout >= 0) or
Chris Liechti033f17c2015-08-30 21:28:04 +0200726 (self._inter_byte_timeout is not None and self._inter_byte_timeout > 0)) and not buf:
cliechtia9a093e2010-01-02 03:05:08 +0000727 break # early abort on timeout
728 return bytes(read)
729
cliechtif81362e2009-07-25 03:44:33 +0000730
Chris Liechti4cf54702015-10-18 00:21:56 +0200731class VTIMESerial(Serial):
732 """\
733 Implement timeout using vtime of tty device instead of using select.
734 This means that no inter character timeout can be specified and that
735 the error handling is degraded.
736
737 Overall timeout is disabled when inter-character timeout is used.
738 """
739
Chris Liechti94284702015-11-15 01:21:48 +0100740 def _reconfigure_port(self, force_update=True):
Chris Liechti4cf54702015-10-18 00:21:56 +0200741 """Set communication parameters on opened port."""
742 super(VTIMESerial, self)._reconfigure_port()
Chris Liechtid6bcaaf2016-02-01 22:55:26 +0100743 fcntl.fcntl(self.fd, fcntl.F_SETFL, 0) # clear O_NONBLOCK
Chris Liechti4cf54702015-10-18 00:21:56 +0200744
745 if self._inter_byte_timeout is not None:
746 vmin = 1
747 vtime = int(self._inter_byte_timeout * 10)
748 else:
749 vmin = 0
750 vtime = int(self._timeout * 10)
751 try:
752 orig_attr = termios.tcgetattr(self.fd)
753 iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
754 except termios.error as msg: # if a port is nonexistent but has a /dev file, it'll fail here
755 raise serial.SerialException("Could not configure port: %s" % msg)
756
757 if vtime < 0 or vtime > 255:
758 raise ValueError('Invalid vtime: %r' % vtime)
759 cc[termios.VTIME] = vtime
760 cc[termios.VMIN] = vmin
761
762 termios.tcsetattr(
763 self.fd,
764 termios.TCSANOW,
765 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
766
Chris Liechti4cf54702015-10-18 00:21:56 +0200767 def read(self, size=1):
768 """\
769 Read size bytes from the serial port. If a timeout is set it may
770 return less characters as requested. With no timeout it will block
771 until the requested number of bytes is read.
772 """
773 if not self.is_open:
774 raise portNotOpenError
775 read = bytearray()
776 while len(read) < size:
777 buf = os.read(self.fd, size - len(read))
778 if not buf:
779 break
780 read.extend(buf)
781 return bytes(read)