blob: cf7a691d562f5c0748652ab3bfb113b7d21f31ea [file] [log] [blame]
cliechti89b4af12002-02-12 23:24:41 +00001#!/usr/bin/env python
cliechti58b481c2009-02-16 20:42:32 +00002#
cliechtic54b2c82008-06-21 01:59:08 +00003# Python Serial Port Extension for Win32, Linux, BSD, Jython
4# module for serial IO for POSIX compatible systems, like Linux
5# see __init__.py
cliechti89b4af12002-02-12 23:24:41 +00006#
Chris Liechti68340d72015-08-03 14:15:48 +02007# (C) 2001-2015 Chris Liechti <cliechti@gmx.net>
Chris Liechtifbdd8a02015-08-09 02:37:45 +02008#
9# SPDX-License-Identifier: BSD-3-Clause
cliechti89b4af12002-02-12 23:24:41 +000010#
cliechtic54b2c82008-06-21 01:59:08 +000011# parts based on code from Grant B. Edwards <grante@visi.com>:
cliechti89b4af12002-02-12 23:24:41 +000012# ftp://ftp.visi.com/users/grante/python/PosixSerial.py
cliechti53c9fd42009-07-23 23:51:51 +000013#
cliechti89b4af12002-02-12 23:24:41 +000014# references: http://www.easysw.com/~mike/serial/serial.html
15
Chris Liechti33f0ec52015-08-06 16:37:21 +020016import errno
17import fcntl
Chris Liechti33f0ec52015-08-06 16:37:21 +020018import os
19import select
20import struct
21import sys
22import termios
23import time
Chris Liechti033f17c2015-08-30 21:28:04 +020024
25import serial
26from serial.serialutil import SerialBase, SerialException, to_bytes, portNotOpenError, writeTimeoutError
cliechti89b4af12002-02-12 23:24:41 +000027
cliechti89b4af12002-02-12 23:24:41 +000028
Chris Liechtid6847af2015-08-06 17:54:30 +020029class PlatformSpecificBase(object):
30 BAUDRATE_CONSTANTS = {}
cliechti89b4af12002-02-12 23:24:41 +000031
Chris Liechtid6847af2015-08-06 17:54:30 +020032 def number_to_device(self, port_number):
33 sys.stderr.write("""\
cliechti7aaead32009-07-23 14:02:41 +000034don't know how to number ttys on this system.
cliechti895e8302004-04-20 02:40:28 +000035! Use an explicit path (eg /dev/ttyS1) or send this information to
36! the author of this module:
cliechti89b4af12002-02-12 23:24:41 +000037
cliechti895e8302004-04-20 02:40:28 +000038sys.platform = %r
39os.name = %r
40serialposix.py version = %s
cliechti89b4af12002-02-12 23:24:41 +000041
42also add the device name of the serial port and where the
43counting starts for the first serial port.
44e.g. 'first serial port: /dev/ttyS0'
45and with a bit luck you can get this module running...
Chris Liechti033f17c2015-08-30 21:28:04 +020046""" % (sys.platform, os.name, serial.VERSION))
Chris Liechtid6847af2015-08-06 17:54:30 +020047 raise NotImplementedError('no number-to-device mapping defined on this platform')
48
49 def _set_special_baudrate(self, baudrate):
50 raise NotImplementedError('non-standard baudrates are not supported on this platform')
51
52 def _set_rs485_mode(self, rs485_settings):
53 raise NotImplementedError('RS485 not supported on this platform')
54
55# try to detect the OS so that a device can be selected...
56# this code block should supply a device() and set_special_baudrate() function
57# for the platform
58plat = sys.platform.lower()
59
Chris Liechti033f17c2015-08-30 21:28:04 +020060if plat[:5] == 'linux': # Linux (confirmed)
Chris Liechtid6847af2015-08-06 17:54:30 +020061 import array
62
63 # baudrate ioctls
64 TCGETS2 = 0x802C542A
65 TCSETS2 = 0x402C542B
66 BOTHER = 0o010000
67
68 # RS485 ioctls
69 TIOCGRS485 = 0x542E
70 TIOCSRS485 = 0x542F
Chris Liechti033f17c2015-08-30 21:28:04 +020071 SER_RS485_ENABLED = 0b00000001
72 SER_RS485_RTS_ON_SEND = 0b00000010
Chris Liechtid6847af2015-08-06 17:54:30 +020073 SER_RS485_RTS_AFTER_SEND = 0b00000100
Chris Liechti033f17c2015-08-30 21:28:04 +020074 SER_RS485_RX_DURING_TX = 0b00010000
Chris Liechtid6847af2015-08-06 17:54:30 +020075
76 class PlatformSpecific(PlatformSpecificBase):
77 BAUDRATE_CONSTANTS = {
78 0: 0o000000, # hang up
79 50: 0o000001,
80 75: 0o000002,
81 110: 0o000003,
82 134: 0o000004,
83 150: 0o000005,
84 200: 0o000006,
85 300: 0o000007,
86 600: 0o000010,
87 1200: 0o000011,
88 1800: 0o000012,
89 2400: 0o000013,
90 4800: 0o000014,
91 9600: 0o000015,
92 19200: 0o000016,
93 38400: 0o000017,
94 57600: 0o010001,
95 115200: 0o010002,
96 230400: 0o010003,
97 460800: 0o010004,
98 500000: 0o010005,
99 576000: 0o010006,
100 921600: 0o010007,
101 1000000: 0o010010,
102 1152000: 0o010011,
103 1500000: 0o010012,
104 2000000: 0o010013,
105 2500000: 0o010014,
106 3000000: 0o010015,
107 3500000: 0o010016,
108 4000000: 0o010017
109 }
110
111 def number_to_device(self, port_number):
112 return '/dev/ttyS%d' % (port_number,)
113
114 def _set_special_baudrate(self, baudrate):
115 # right size is 44 on x86_64, allow for some growth
116 buf = array.array('i', [0] * 64)
117 try:
118 # get serial_struct
119 fcntl.ioctl(self.fd, TCGETS2, buf)
120 # set custom speed
121 buf[2] &= ~termios.CBAUD
122 buf[2] |= BOTHER
123 buf[9] = buf[10] = baudrate
124
125 # set serial_struct
Chris Liechti033f17c2015-08-30 21:28:04 +0200126 fcntl.ioctl(self.fd, TCSETS2, buf)
Chris Liechtid6847af2015-08-06 17:54:30 +0200127 except IOError as e:
128 raise ValueError('Failed to set custom baud rate (%s): %s' % (baudrate, e))
129
130 def _set_rs485_mode(self, rs485_settings):
Chris Liechti033f17c2015-08-30 21:28:04 +0200131 buf = array.array('i', [0] * 8) # flags, delaytx, delayrx, padding
Chris Liechtid6847af2015-08-06 17:54:30 +0200132 try:
133 fcntl.ioctl(self.fd, TIOCGRS485, buf)
134 if rs485_settings is not None:
135 if rs485_settings.loopback:
136 buf[0] |= SER_RS485_RX_DURING_TX
137 else:
138 buf[0] &= ~SER_RS485_RX_DURING_TX
139 if rs485_settings.rts_level_for_tx:
140 buf[0] |= SER_RS485_RTS_ON_SEND
141 else:
142 buf[0] &= ~SER_RS485_RTS_ON_SEND
143 if rs485_settings.rts_level_for_rx:
144 buf[0] |= SER_RS485_RTS_AFTER_SEND
145 else:
146 buf[0] &= ~SER_RS485_RTS_AFTER_SEND
147 buf[1] = int(rs485_settings.delay_rts_before_send * 1000)
148 buf[2] = int(rs485_settings.delay_rts_after_send * 1000)
149 else:
150 buf[0] = 0 # clear SER_RS485_ENABLED
Chris Liechti033f17c2015-08-30 21:28:04 +0200151 fcntl.ioctl(self.fd, TIOCSRS485, buf)
Chris Liechtid6847af2015-08-06 17:54:30 +0200152 except IOError as e:
153 raise ValueError('Failed to set RS485 mode: %s' % (e,))
154
155
156elif plat == 'cygwin': # cygwin/win32 (confirmed)
157
158 class PlatformSpecific(PlatformSpecificBase):
159 BAUDRATE_CONSTANTS = {
160 128000: 0x01003,
161 256000: 0x01005,
162 500000: 0x01007,
163 576000: 0x01008,
164 921600: 0x01009,
165 1000000: 0x0100a,
166 1152000: 0x0100b,
167 1500000: 0x0100c,
168 2000000: 0x0100d,
169 2500000: 0x0100e,
170 3000000: 0x0100f
171 }
172
173 def number_to_device(self, port_number):
174 return '/dev/com%d' % (port_number + 1,)
175
176
177elif plat[:7] == 'openbsd': # OpenBSD
178 class PlatformSpecific(PlatformSpecificBase):
179 def number_to_device(self, port_number):
180 return '/dev/cua%02d' % (port_number,)
181
182elif plat[:3] == 'bsd' or plat[:7] == 'freebsd':
183 class PlatformSpecific(PlatformSpecificBase):
184 def number_to_device(self, port_number):
185 return '/dev/cuad%d' % (port_number,)
186
187elif plat[:6] == 'darwin': # OS X
188 import array
Chris Liechti033f17c2015-08-30 21:28:04 +0200189 IOSSIOSPEED = 0x80045402 # _IOW('T', 2, speed_t)
Chris Liechtid6847af2015-08-06 17:54:30 +0200190
191 class PlatformSpecific(PlatformSpecificBase):
192 def number_to_device(self, port_number):
193 return '/dev/cuad%d' % (port_number,)
194
195 osx_version = os.uname()[2].split('.')
196 # Tiger or above can support arbitrary serial speeds
197 if int(osx_version[0]) >= 8:
198 def _set_special_baudrate(self, baudrate):
199 # use IOKit-specific call to set up high speeds
200 buf = array.array('i', [baudrate])
201 fcntl.ioctl(self.fd, IOSSIOSPEED, buf, 1)
202
203
204elif plat[:6] == 'netbsd': # NetBSD 1.6 testing by Erk
205 class PlatformSpecific(PlatformSpecificBase):
206 def number_to_device(self, port_number):
207 return '/dev/dty%02d' % (port_number,)
208
209elif plat[:4] == 'irix': # IRIX (partially tested)
210 class PlatformSpecific(PlatformSpecificBase):
211 def number_to_device(self, port_number):
Chris Liechti033f17c2015-08-30 21:28:04 +0200212 return '/dev/ttyf%d' % (port_number + 1,) # XXX different device names depending on flow control
Chris Liechtid6847af2015-08-06 17:54:30 +0200213
214elif plat[:2] == 'hp': # HP-UX (not tested)
215 class PlatformSpecific(PlatformSpecificBase):
216 def number_to_device(self, port_number):
217 return '/dev/tty%dp0' % (port_number + 1,)
218
219elif plat[:5] == 'sunos': # Solaris/SunOS (confirmed)
220 class PlatformSpecific(PlatformSpecificBase):
221 def number_to_device(self, port_number):
222 return '/dev/tty%c' % (ord('a') + port_number,)
223
224elif plat[:3] == 'aix': # AIX
225 class PlatformSpecific(PlatformSpecificBase):
226 def number_to_device(self, port_number):
227 return '/dev/tty%d' % (port_number,)
228
229else:
230 class PlatformSpecific(PlatformSpecificBase):
231 pass
cliechti89b4af12002-02-12 23:24:41 +0000232
cliechti58b481c2009-02-16 20:42:32 +0000233# whats up with "aix", "beos", ....
234# they should work, just need to know the device names.
cliechti89b4af12002-02-12 23:24:41 +0000235
236
cliechti58b481c2009-02-16 20:42:32 +0000237# load some constants for later use.
Chris Liechti11465c82015-08-04 15:55:22 +0200238# try to use values from termios, use defaults from linux otherwise
Chris Liechti033f17c2015-08-30 21:28:04 +0200239TIOCMGET = getattr(termios, 'TIOCMGET', 0x5415)
240TIOCMBIS = getattr(termios, 'TIOCMBIS', 0x5416)
241TIOCMBIC = getattr(termios, 'TIOCMBIC', 0x5417)
242TIOCMSET = getattr(termios, 'TIOCMSET', 0x5418)
cliechti89b4af12002-02-12 23:24:41 +0000243
Chris Liechti033f17c2015-08-30 21:28:04 +0200244# TIOCM_LE = getattr(termios, 'TIOCM_LE', 0x001)
Chris Liechtid6847af2015-08-06 17:54:30 +0200245TIOCM_DTR = getattr(termios, 'TIOCM_DTR', 0x002)
246TIOCM_RTS = getattr(termios, 'TIOCM_RTS', 0x004)
Chris Liechti033f17c2015-08-30 21:28:04 +0200247# TIOCM_ST = getattr(termios, 'TIOCM_ST', 0x008)
248# TIOCM_SR = getattr(termios, 'TIOCM_SR', 0x010)
cliechti89b4af12002-02-12 23:24:41 +0000249
Chris Liechtid6847af2015-08-06 17:54:30 +0200250TIOCM_CTS = getattr(termios, 'TIOCM_CTS', 0x020)
251TIOCM_CAR = getattr(termios, 'TIOCM_CAR', 0x040)
252TIOCM_RNG = getattr(termios, 'TIOCM_RNG', 0x080)
253TIOCM_DSR = getattr(termios, 'TIOCM_DSR', 0x100)
Chris Liechti033f17c2015-08-30 21:28:04 +0200254TIOCM_CD = getattr(termios, 'TIOCM_CD', TIOCM_CAR)
255TIOCM_RI = getattr(termios, 'TIOCM_RI', TIOCM_RNG)
256# TIOCM_OUT1 = getattr(termios, 'TIOCM_OUT1', 0x2000)
257# TIOCM_OUT2 = getattr(termios, 'TIOCM_OUT2', 0x4000)
Chris Liechti11465c82015-08-04 15:55:22 +0200258if hasattr(termios, 'TIOCINQ'):
259 TIOCINQ = termios.TIOCINQ
cliechti28b8fd02011-12-28 21:39:42 +0000260else:
Chris Liechtid6847af2015-08-06 17:54:30 +0200261 TIOCINQ = getattr(termios, 'FIONREAD', 0x541B)
Chris Liechti033f17c2015-08-30 21:28:04 +0200262TIOCOUTQ = getattr(termios, 'TIOCOUTQ', 0x5411)
cliechti89b4af12002-02-12 23:24:41 +0000263
264TIOCM_zero_str = struct.pack('I', 0)
265TIOCM_RTS_str = struct.pack('I', TIOCM_RTS)
266TIOCM_DTR_str = struct.pack('I', TIOCM_DTR)
267
Chris Liechti033f17c2015-08-30 21:28:04 +0200268TIOCSBRK = getattr(termios, 'TIOCSBRK', 0x5427)
269TIOCCBRK = getattr(termios, 'TIOCCBRK', 0x5428)
cliechti997b63c2008-06-21 00:09:31 +0000270
Chris Liechti033f17c2015-08-30 21:28:04 +0200271CMSPAR = 0o10000000000 # Use "stick" (mark/space) parity
cliechtiaec27ab2014-07-31 22:21:24 +0000272
cliechti89b4af12002-02-12 23:24:41 +0000273
Chris Liechtief6b7b42015-08-06 22:19:26 +0200274class Serial(SerialBase, PlatformSpecific):
cliechti7d448562014-08-03 21:57:45 +0000275 """\
Chris Liechti033f17c2015-08-30 21:28:04 +0200276 Serial port class POSIX implementation. Serial port configuration is
cliechtid6bf52c2003-10-01 02:28:12 +0000277 done with termios and fcntl. Runs on Linux and many other Un*x like
cliechtif0a81d42014-08-04 14:03:53 +0000278 systems.
279 """
cliechtid6bf52c2003-10-01 02:28:12 +0000280
281 def open(self):
cliechti7d448562014-08-03 21:57:45 +0000282 """\
283 Open port with current settings. This may throw a SerialException
284 if the port cannot be opened."""
cliechtid6bf52c2003-10-01 02:28:12 +0000285 if self._port is None:
286 raise SerialException("Port must be configured before it can be used.")
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200287 if self.is_open:
cliechti02ef43a2011-03-24 23:33:12 +0000288 raise SerialException("Port is already open.")
289 self.fd = None
cliechti58b481c2009-02-16 20:42:32 +0000290 # open
cliechti4616bf12002-04-08 23:13:14 +0000291 try:
Chris Liechti033f17c2015-08-30 21:28:04 +0200292 self.fd = os.open(self.portstr, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK)
Chris Liechti68340d72015-08-03 14:15:48 +0200293 except OSError as msg:
cliechti4616bf12002-04-08 23:13:14 +0000294 self.fd = None
cliechtiaf84daa2013-10-10 23:57:00 +0000295 raise SerialException(msg.errno, "could not open port %s: %s" % (self._port, msg))
Chris Liechti11465c82015-08-04 15:55:22 +0200296 #~ fcntl.fcntl(self.fd, fcntl.F_SETFL, 0) # set blocking
cliechti58b481c2009-02-16 20:42:32 +0000297
cliechtib2f5fc82006-10-20 00:09:07 +0000298 try:
Chris Liechti94284702015-11-15 01:21:48 +0100299 self._reconfigure_port(force_update=True)
cliechtib2f5fc82006-10-20 00:09:07 +0000300 except:
cliechti2750b832009-07-28 00:13:52 +0000301 try:
302 os.close(self.fd)
303 except:
304 # ignore any exception when closing the port
305 # also to keep original exception that happened when setting up
306 pass
cliechtib2f5fc82006-10-20 00:09:07 +0000307 self.fd = None
cliechtif0a4f0f2009-07-21 21:12:37 +0000308 raise
cliechtib2f5fc82006-10-20 00:09:07 +0000309 else:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200310 self.is_open = True
311 if not self._dsrdtr:
Chris Liechtief1fe252015-08-27 23:25:21 +0200312 self._update_dtr_state()
Chris Liechtidc2beec2015-09-18 21:25:28 +0200313 if not self._rtscts:
Chris Liechtief1fe252015-08-27 23:25:21 +0200314 self._update_rts_state()
315 self.reset_input_buffer()
cliechti58b481c2009-02-16 20:42:32 +0000316
Chris Liechti94284702015-11-15 01:21:48 +0100317 def _reconfigure_port(self, force_update=False):
cliechtib2f5fc82006-10-20 00:09:07 +0000318 """Set communication parameters on opened port."""
cliechtic6178262004-03-22 22:04:52 +0000319 if self.fd is None:
cliechtia9a093e2010-01-02 03:05:08 +0000320 raise SerialException("Can only operate on a valid file descriptor")
cliechtie8c45422008-06-20 23:23:14 +0000321 custom_baud = None
cliechti58b481c2009-02-16 20:42:32 +0000322
cliechti2750b832009-07-28 00:13:52 +0000323 vmin = vtime = 0 # timeout is done via select
Chris Liechti518b0d32015-08-30 02:20:39 +0200324 if self._inter_byte_timeout is not None:
cliechti679bfa62008-06-20 23:58:15 +0000325 vmin = 1
Chris Liechti518b0d32015-08-30 02:20:39 +0200326 vtime = int(self._inter_byte_timeout * 10)
cliechti6ce7ab12002-11-07 02:15:00 +0000327 try:
cliechti4d0af5e2011-08-05 02:18:16 +0000328 orig_attr = termios.tcgetattr(self.fd)
329 iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
Chris Liechti68340d72015-08-03 14:15:48 +0200330 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 +0000331 raise SerialException("Could not configure port: %s" % msg)
cliechti58b481c2009-02-16 20:42:32 +0000332 # set up raw mode / no echo / binary
Chris Liechti033f17c2015-08-30 21:28:04 +0200333 cflag |= (termios.CLOCAL | termios.CREAD)
334 lflag &= ~(termios.ICANON | termios.ECHO | termios.ECHOE |
335 termios.ECHOK | termios.ECHONL |
336 termios.ISIG | termios.IEXTEN) # |termios.ECHOPRT
337 for flag in ('ECHOCTL', 'ECHOKE'): # netbsd workaround for Erk
Chris Liechti11465c82015-08-04 15:55:22 +0200338 if hasattr(termios, flag):
339 lflag &= ~getattr(termios, flag)
cliechti58b481c2009-02-16 20:42:32 +0000340
Chris Liechti033f17c2015-08-30 21:28:04 +0200341 oflag &= ~(termios.OPOST | termios.ONLCR | termios.OCRNL)
342 iflag &= ~(termios.INLCR | termios.IGNCR | termios.ICRNL | termios.IGNBRK)
Chris Liechti11465c82015-08-04 15:55:22 +0200343 if hasattr(termios, 'IUCLC'):
344 iflag &= ~termios.IUCLC
345 if hasattr(termios, 'PARMRK'):
346 iflag &= ~termios.PARMRK
cliechti58b481c2009-02-16 20:42:32 +0000347
cliechtif0a4f0f2009-07-21 21:12:37 +0000348 # setup baud rate
cliechti89b4af12002-02-12 23:24:41 +0000349 try:
Chris Liechti11465c82015-08-04 15:55:22 +0200350 ispeed = ospeed = getattr(termios, 'B%s' % (self._baudrate))
cliechti895e8302004-04-20 02:40:28 +0000351 except AttributeError:
cliechtif1559d02007-11-08 23:43:58 +0000352 try:
Chris Liechtid6847af2015-08-06 17:54:30 +0200353 ispeed = ospeed = self.BAUDRATE_CONSTANTS[self._baudrate]
cliechtif1559d02007-11-08 23:43:58 +0000354 except KeyError:
cliechtie8c45422008-06-20 23:23:14 +0000355 #~ raise ValueError('Invalid baud rate: %r' % self._baudrate)
cliechtif0a4f0f2009-07-21 21:12:37 +0000356 # may need custom baud rate, it isn't in our list.
Chris Liechti11465c82015-08-04 15:55:22 +0200357 ispeed = ospeed = getattr(termios, 'B38400')
cliechtif0a4f0f2009-07-21 21:12:37 +0000358 try:
Chris Liechti033f17c2015-08-30 21:28:04 +0200359 custom_baud = int(self._baudrate) # store for later
cliechtif0a4f0f2009-07-21 21:12:37 +0000360 except ValueError:
361 raise ValueError('Invalid baud rate: %r' % self._baudrate)
362 else:
363 if custom_baud < 0:
364 raise ValueError('Invalid baud rate: %r' % self._baudrate)
cliechti58b481c2009-02-16 20:42:32 +0000365
366 # setup char len
Chris Liechti11465c82015-08-04 15:55:22 +0200367 cflag &= ~termios.CSIZE
cliechtid6bf52c2003-10-01 02:28:12 +0000368 if self._bytesize == 8:
Chris Liechti11465c82015-08-04 15:55:22 +0200369 cflag |= termios.CS8
cliechtid6bf52c2003-10-01 02:28:12 +0000370 elif self._bytesize == 7:
Chris Liechti11465c82015-08-04 15:55:22 +0200371 cflag |= termios.CS7
cliechtid6bf52c2003-10-01 02:28:12 +0000372 elif self._bytesize == 6:
Chris Liechti11465c82015-08-04 15:55:22 +0200373 cflag |= termios.CS6
cliechtid6bf52c2003-10-01 02:28:12 +0000374 elif self._bytesize == 5:
Chris Liechti11465c82015-08-04 15:55:22 +0200375 cflag |= termios.CS5
cliechti89b4af12002-02-12 23:24:41 +0000376 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000377 raise ValueError('Invalid char len: %r' % self._bytesize)
cliechtif0a81d42014-08-04 14:03:53 +0000378 # setup stop bits
Chris Liechti033f17c2015-08-30 21:28:04 +0200379 if self._stopbits == serial.STOPBITS_ONE:
Chris Liechti11465c82015-08-04 15:55:22 +0200380 cflag &= ~(termios.CSTOPB)
Chris Liechti033f17c2015-08-30 21:28:04 +0200381 elif self._stopbits == serial.STOPBITS_ONE_POINT_FIVE:
382 cflag |= (termios.CSTOPB) # XXX same as TWO.. there is no POSIX support for 1.5
383 elif self._stopbits == serial.STOPBITS_TWO:
384 cflag |= (termios.CSTOPB)
cliechti89b4af12002-02-12 23:24:41 +0000385 else:
cliechti3172d3d2009-07-21 22:33:40 +0000386 raise ValueError('Invalid stop bit specification: %r' % self._stopbits)
cliechti58b481c2009-02-16 20:42:32 +0000387 # setup parity
Chris Liechti033f17c2015-08-30 21:28:04 +0200388 iflag &= ~(termios.INPCK | termios.ISTRIP)
389 if self._parity == serial.PARITY_NONE:
390 cflag &= ~(termios.PARENB | termios.PARODD)
391 elif self._parity == serial.PARITY_EVEN:
Chris Liechti11465c82015-08-04 15:55:22 +0200392 cflag &= ~(termios.PARODD)
Chris Liechti033f17c2015-08-30 21:28:04 +0200393 cflag |= (termios.PARENB)
394 elif self._parity == serial.PARITY_ODD:
395 cflag |= (termios.PARENB | termios.PARODD)
396 elif self._parity == serial.PARITY_MARK and plat[:5] == 'linux':
397 cflag |= (termios.PARENB | CMSPAR | termios.PARODD)
398 elif self._parity == serial.PARITY_SPACE and plat[:5] == 'linux':
399 cflag |= (termios.PARENB | CMSPAR)
Chris Liechti11465c82015-08-04 15:55:22 +0200400 cflag &= ~(termios.PARODD)
cliechti89b4af12002-02-12 23:24:41 +0000401 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000402 raise ValueError('Invalid parity: %r' % self._parity)
cliechti58b481c2009-02-16 20:42:32 +0000403 # setup flow control
404 # xonxoff
Chris Liechti11465c82015-08-04 15:55:22 +0200405 if hasattr(termios, 'IXANY'):
cliechtid6bf52c2003-10-01 02:28:12 +0000406 if self._xonxoff:
Chris Liechti033f17c2015-08-30 21:28:04 +0200407 iflag |= (termios.IXON | termios.IXOFF) # |termios.IXANY)
cliechti89b4af12002-02-12 23:24:41 +0000408 else:
Chris Liechti033f17c2015-08-30 21:28:04 +0200409 iflag &= ~(termios.IXON | termios.IXOFF | termios.IXANY)
cliechti89b4af12002-02-12 23:24:41 +0000410 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000411 if self._xonxoff:
Chris Liechti033f17c2015-08-30 21:28:04 +0200412 iflag |= (termios.IXON | termios.IXOFF)
cliechti89b4af12002-02-12 23:24:41 +0000413 else:
Chris Liechti033f17c2015-08-30 21:28:04 +0200414 iflag &= ~(termios.IXON | termios.IXOFF)
cliechti58b481c2009-02-16 20:42:32 +0000415 # rtscts
Chris Liechti11465c82015-08-04 15:55:22 +0200416 if hasattr(termios, 'CRTSCTS'):
cliechtid6bf52c2003-10-01 02:28:12 +0000417 if self._rtscts:
Chris Liechti033f17c2015-08-30 21:28:04 +0200418 cflag |= (termios.CRTSCTS)
cliechti89b4af12002-02-12 23:24:41 +0000419 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200420 cflag &= ~(termios.CRTSCTS)
421 elif hasattr(termios, 'CNEW_RTSCTS'): # try it with alternate constant name
cliechtid6bf52c2003-10-01 02:28:12 +0000422 if self._rtscts:
Chris Liechti033f17c2015-08-30 21:28:04 +0200423 cflag |= (termios.CNEW_RTSCTS)
cliechtid4743692002-04-08 22:39:53 +0000424 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200425 cflag &= ~(termios.CNEW_RTSCTS)
cliechti2750b832009-07-28 00:13:52 +0000426 # XXX should there be a warning if setting up rtscts (and xonxoff etc) fails??
cliechti58b481c2009-02-16 20:42:32 +0000427
428 # buffer
cliechtif0a81d42014-08-04 14:03:53 +0000429 # vmin "minimal number of characters to be read. 0 for non blocking"
cliechtid6bf52c2003-10-01 02:28:12 +0000430 if vmin < 0 or vmin > 255:
431 raise ValueError('Invalid vmin: %r ' % vmin)
Chris Liechti11465c82015-08-04 15:55:22 +0200432 cc[termios.VMIN] = vmin
cliechti58b481c2009-02-16 20:42:32 +0000433 # vtime
cliechtid6bf52c2003-10-01 02:28:12 +0000434 if vtime < 0 or vtime > 255:
435 raise ValueError('Invalid vtime: %r' % vtime)
Chris Liechti11465c82015-08-04 15:55:22 +0200436 cc[termios.VTIME] = vtime
cliechti58b481c2009-02-16 20:42:32 +0000437 # activate settings
Chris Liechti94284702015-11-15 01:21:48 +0100438 if force_update or [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] != orig_attr:
Chris Liechti033f17c2015-08-30 21:28:04 +0200439 termios.tcsetattr(
440 self.fd,
441 termios.TCSANOW,
442 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
cliechti58b481c2009-02-16 20:42:32 +0000443
cliechtie8c45422008-06-20 23:23:14 +0000444 # apply custom baud rate, if any
445 if custom_baud is not None:
Chris Liechtid6847af2015-08-06 17:54:30 +0200446 self._set_special_baudrate(custom_baud)
447
448 if self._rs485_mode is not None:
449 self._set_rs485_mode(self._rs485_mode)
cliechti89b4af12002-02-12 23:24:41 +0000450
451 def close(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000452 """Close port"""
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200453 if self.is_open:
cliechtic6178262004-03-22 22:04:52 +0000454 if self.fd is not None:
cliechtid6bf52c2003-10-01 02:28:12 +0000455 os.close(self.fd)
456 self.fd = None
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200457 self.is_open = False
cliechtid6bf52c2003-10-01 02:28:12 +0000458
459 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechti95c62212002-03-04 22:17:53 +0000460
Chris Liechtief1fe252015-08-27 23:25:21 +0200461 @property
462 def in_waiting(self):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200463 """Return the number of bytes currently in the input buffer."""
Chris Liechti11465c82015-08-04 15:55:22 +0200464 #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str)
cliechtif5831e02002-12-05 23:15:27 +0000465 s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200466 return struct.unpack('I', s)[0]
cliechti89b4af12002-02-12 23:24:41 +0000467
cliechtia9a093e2010-01-02 03:05:08 +0000468 # select based implementation, proved to work on many systems
469 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000470 """\
471 Read size bytes from the serial port. If a timeout is set it may
472 return less characters as requested. With no timeout it will block
473 until the requested number of bytes is read.
474 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200475 if not self.is_open:
476 raise portNotOpenError
cliechtia9a093e2010-01-02 03:05:08 +0000477 read = bytearray()
Cristiano De Altic30622f2015-12-12 11:00:01 +0100478 timeout = self._timeout
cliechtia9a093e2010-01-02 03:05:08 +0000479 while len(read) < size:
cliechti8d744de2013-10-11 14:31:13 +0000480 try:
Cristiano De Altic30622f2015-12-12 11:00:01 +0100481 start_time = time.time()
482 ready, _, _ = select.select([self.fd], [], [], timeout)
cliechti8d744de2013-10-11 14:31:13 +0000483 # If select was used with a timeout, and the timeout occurs, it
484 # returns with empty lists -> thus abort read operation.
Chris Liechti033f17c2015-08-30 21:28:04 +0200485 # For timeout == 0 (non-blocking operation) also abort when
486 # there is nothing to read.
cliechti8d744de2013-10-11 14:31:13 +0000487 if not ready:
488 break # timeout
Chris Liechti033f17c2015-08-30 21:28:04 +0200489 buf = os.read(self.fd, size - len(read))
cliechti8d744de2013-10-11 14:31:13 +0000490 # read should always return some data as select reported it was
491 # ready to read when we get to this point.
492 if not buf:
493 # Disconnected devices, at least on Linux, show the
494 # behavior that they are always ready to read immediately
495 # but reading returns nothing.
496 raise SerialException('device reports readiness to read but returned no data (device disconnected or multiple access on port?)')
497 read.extend(buf)
Cristiano De Altic30622f2015-12-12 11:00:01 +0100498 if timeout is not None:
499 timeout -= time.time() - start_time
500 if timeout <= 0:
501 break
Chris Liechti68340d72015-08-03 14:15:48 +0200502 except OSError as e:
Chris Liechti033f17c2015-08-30 21:28:04 +0200503 # this is for Python 3.x where select.error is a subclass of
504 # OSError ignore EAGAIN errors. all other errors are shown
cliechtic7cd7212014-08-03 21:34:38 +0000505 if e.errno != errno.EAGAIN:
506 raise SerialException('read failed: %s' % (e,))
Chris Liechti68340d72015-08-03 14:15:48 +0200507 except select.error as e:
cliechtic7cd7212014-08-03 21:34:38 +0000508 # this is for Python 2.x
cliechti8d744de2013-10-11 14:31:13 +0000509 # ignore EAGAIN errors. all other errors are shown
510 # see also http://www.python.org/dev/peps/pep-3151/#select
511 if e[0] != errno.EAGAIN:
512 raise SerialException('read failed: %s' % (e,))
cliechtia9a093e2010-01-02 03:05:08 +0000513 return bytes(read)
cliechti89b4af12002-02-12 23:24:41 +0000514
cliechti4a567a02009-07-27 22:09:31 +0000515 def write(self, data):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200516 """Output the given byte string over the serial port."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200517 if not self.is_open:
518 raise portNotOpenError
cliechti38077122013-10-16 02:57:27 +0000519 d = to_bytes(data)
520 tx_len = len(d)
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200521 if self._write_timeout is not None and self._write_timeout > 0:
522 timeout = time.time() + self._write_timeout
cliechti3cf46d62009-08-07 00:19:57 +0000523 else:
524 timeout = None
cliechti9f7c2352013-10-11 01:13:46 +0000525 while tx_len > 0:
cliechti5d4d0bd2004-11-13 03:27:39 +0000526 try:
cliechti5d4d0bd2004-11-13 03:27:39 +0000527 n = os.write(self.fd, d)
cliechti3cf46d62009-08-07 00:19:57 +0000528 if timeout:
529 # when timeout is set, use select to wait for being ready
530 # with the time left as timeout
531 timeleft = timeout - time.time()
532 if timeleft < 0:
533 raise writeTimeoutError
534 _, ready, _ = select.select([], [self.fd], [], timeleft)
cliechti5d4d0bd2004-11-13 03:27:39 +0000535 if not ready:
536 raise writeTimeoutError
cliechti88c62442013-10-12 04:03:16 +0000537 else:
538 # wait for write operation
539 _, ready, _ = select.select([], [self.fd], [], None)
540 if not ready:
541 raise SerialException('write failed (select)')
cliechti5d4d0bd2004-11-13 03:27:39 +0000542 d = d[n:]
cliechti9f7c2352013-10-11 01:13:46 +0000543 tx_len -= n
Chris Liechti675f7e12015-08-03 15:48:41 +0200544 except SerialException:
545 raise
Chris Liechti68340d72015-08-03 14:15:48 +0200546 except OSError as v:
cliechti5d4d0bd2004-11-13 03:27:39 +0000547 if v.errno != errno.EAGAIN:
cliechti65722c92009-08-07 00:48:53 +0000548 raise SerialException('write failed: %s' % (v,))
Chris Liechtic6362db2015-12-13 23:44:35 +0100549 # still calculate and check timeout
550 if timeout and timeout - time.time() < 0:
551 raise writeTimeoutError
cliechtif81362e2009-07-25 03:44:33 +0000552 return len(data)
cliechtid6bf52c2003-10-01 02:28:12 +0000553
cliechtia30a8a02003-10-05 12:28:13 +0000554 def flush(self):
cliechti7d448562014-08-03 21:57:45 +0000555 """\
556 Flush of file like objects. In this case, wait until all data
557 is written.
558 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200559 if not self.is_open:
560 raise portNotOpenError
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200561 termios.tcdrain(self.fd)
cliechtia30a8a02003-10-05 12:28:13 +0000562
Chris Liechtief1fe252015-08-27 23:25:21 +0200563 def reset_input_buffer(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000564 """Clear input buffer, discarding all that is in the buffer."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200565 if not self.is_open:
566 raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200567 termios.tcflush(self.fd, termios.TCIFLUSH)
cliechti89b4af12002-02-12 23:24:41 +0000568
Chris Liechtief1fe252015-08-27 23:25:21 +0200569 def reset_output_buffer(self):
cliechti7d448562014-08-03 21:57:45 +0000570 """\
571 Clear output buffer, aborting the current output and discarding all
572 that is in the buffer.
573 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200574 if not self.is_open:
575 raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200576 termios.tcflush(self.fd, termios.TCOFLUSH)
cliechti89b4af12002-02-12 23:24:41 +0000577
Chris Liechtief1fe252015-08-27 23:25:21 +0200578 def send_break(self, duration=0.25):
cliechti7d448562014-08-03 21:57:45 +0000579 """\
580 Send break condition. Timed, returns to idle state after given
581 duration.
582 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200583 if not self.is_open:
584 raise portNotOpenError
585 termios.tcsendbreak(self.fd, int(duration / 0.25))
cliechti89b4af12002-02-12 23:24:41 +0000586
Chris Liechtief1fe252015-08-27 23:25:21 +0200587 def _update_break_state(self):
cliechti7d448562014-08-03 21:57:45 +0000588 """\
589 Set break: Controls TXD. When active, no transmitting is possible.
590 """
Chris Liechtief1fe252015-08-27 23:25:21 +0200591 if self._break_state:
cliechti997b63c2008-06-21 00:09:31 +0000592 fcntl.ioctl(self.fd, TIOCSBRK)
593 else:
594 fcntl.ioctl(self.fd, TIOCCBRK)
595
Chris Liechtief1fe252015-08-27 23:25:21 +0200596 def _update_rts_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000597 """Set terminal status line: Request To Send"""
Chris Liechtief1fe252015-08-27 23:25:21 +0200598 if self._rts_state:
cliechtid6bf52c2003-10-01 02:28:12 +0000599 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_RTS_str)
600 else:
601 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_RTS_str)
602
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 Liechtief1fe252015-08-27 23:25:21 +0200605 if self._dtr_state:
cliechtid6bf52c2003-10-01 02:28:12 +0000606 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str)
607 else:
608 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_DTR_str)
609
Chris Liechtief1fe252015-08-27 23:25:21 +0200610 @property
611 def cts(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000612 """Read terminal status line: Clear To Send"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200613 if not self.is_open:
614 raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000615 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200616 return struct.unpack('I', s)[0] & TIOCM_CTS != 0
cliechtid6bf52c2003-10-01 02:28:12 +0000617
Chris Liechtief1fe252015-08-27 23:25:21 +0200618 @property
619 def dsr(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000620 """Read terminal status line: Data Set Ready"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200621 if not self.is_open:
622 raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000623 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200624 return struct.unpack('I', s)[0] & TIOCM_DSR != 0
cliechtid6bf52c2003-10-01 02:28:12 +0000625
Chris Liechtief1fe252015-08-27 23:25:21 +0200626 @property
627 def ri(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000628 """Read terminal status line: Ring Indicator"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200629 if not self.is_open:
630 raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000631 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200632 return struct.unpack('I', s)[0] & TIOCM_RI != 0
cliechti89b4af12002-02-12 23:24:41 +0000633
Chris Liechtief1fe252015-08-27 23:25:21 +0200634 @property
635 def cd(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000636 """Read terminal status line: Carrier Detect"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200637 if not self.is_open:
638 raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000639 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200640 return struct.unpack('I', s)[0] & TIOCM_CD != 0
cliechti89b4af12002-02-12 23:24:41 +0000641
cliechtia30a8a02003-10-05 12:28:13 +0000642 # - - platform specific - - - -
643
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200644 @property
645 def out_waiting(self):
646 """Return the number of bytes currently in the output buffer."""
Chris Liechti11465c82015-08-04 15:55:22 +0200647 #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str)
cliechti28b8fd02011-12-28 21:39:42 +0000648 s = fcntl.ioctl(self.fd, TIOCOUTQ, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200649 return struct.unpack('I', s)[0]
cliechti28b8fd02011-12-28 21:39:42 +0000650
cliechtia30a8a02003-10-05 12:28:13 +0000651 def nonblocking(self):
652 """internal - not portable!"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200653 if not self.is_open:
654 raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200655 fcntl.fcntl(self.fd, fcntl.F_SETFL, os.O_NONBLOCK)
cliechtia30a8a02003-10-05 12:28:13 +0000656
cliechti8753bbc2005-01-15 20:32:51 +0000657 def fileno(self):
cliechti2f0f8a32011-12-28 22:10:00 +0000658 """\
659 For easier use of the serial port instance with select.
660 WARNING: this function is not portable to different platforms!
661 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200662 if not self.is_open:
663 raise portNotOpenError
cliechti8753bbc2005-01-15 20:32:51 +0000664 return self.fd
cliechti89b4af12002-02-12 23:24:41 +0000665
Chris Liechti518b0d32015-08-30 02:20:39 +0200666 def set_input_flow_control(self, enable=True):
cliechti2f0f8a32011-12-28 22:10:00 +0000667 """\
668 Manually control flow - when software flow control is enabled.
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200669 This will send XON (true) or XOFF (false) to the other device.
cliechti2f0f8a32011-12-28 22:10:00 +0000670 WARNING: this function is not portable to different platforms!
671 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200672 if not self.is_open:
673 raise portNotOpenError
cliechti4a601342011-12-29 02:22:17 +0000674 if enable:
Chris Liechti11465c82015-08-04 15:55:22 +0200675 termios.tcflow(self.fd, termios.TCION)
cliechti57e48a62009-08-03 22:29:58 +0000676 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200677 termios.tcflow(self.fd, termios.TCIOFF)
cliechti57e48a62009-08-03 22:29:58 +0000678
Chris Liechti518b0d32015-08-30 02:20:39 +0200679 def set_output_flow_control(self, enable=True):
cliechti2f0f8a32011-12-28 22:10:00 +0000680 """\
681 Manually control flow of outgoing data - when hardware or software flow
682 control is enabled.
683 WARNING: this function is not portable to different platforms!
684 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200685 if not self.is_open:
686 raise portNotOpenError
cliechti2f0f8a32011-12-28 22:10:00 +0000687 if enable:
Chris Liechti11465c82015-08-04 15:55:22 +0200688 termios.tcflow(self.fd, termios.TCOON)
cliechti2f0f8a32011-12-28 22:10:00 +0000689 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200690 termios.tcflow(self.fd, termios.TCOOFF)
cliechti2f0f8a32011-12-28 22:10:00 +0000691
cliechtif81362e2009-07-25 03:44:33 +0000692
cliechtia9a093e2010-01-02 03:05:08 +0000693class PosixPollSerial(Serial):
cliechti7d448562014-08-03 21:57:45 +0000694 """\
cliechtif0a81d42014-08-04 14:03:53 +0000695 Poll based read implementation. Not all systems support poll properly.
696 However this one has better handling of errors, such as a device
cliechti7d448562014-08-03 21:57:45 +0000697 disconnecting while it's in use (e.g. USB-serial unplugged).
698 """
cliechtia9a093e2010-01-02 03:05:08 +0000699
700 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000701 """\
702 Read size bytes from the serial port. If a timeout is set it may
703 return less characters as requested. With no timeout it will block
704 until the requested number of bytes is read.
705 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200706 if self.fd is None:
707 raise portNotOpenError
cliechtia9a093e2010-01-02 03:05:08 +0000708 read = bytearray()
709 poll = select.poll()
Chris Liechti033f17c2015-08-30 21:28:04 +0200710 poll.register(self.fd, select.POLLIN | select.POLLERR | select.POLLHUP | select.POLLNVAL)
cliechtia9a093e2010-01-02 03:05:08 +0000711 if size > 0:
712 while len(read) < size:
713 # print "\tread(): size",size, "have", len(read) #debug
714 # wait until device becomes ready to read (or something fails)
Chris Liechti033f17c2015-08-30 21:28:04 +0200715 for fd, event in poll.poll(self._timeout * 1000):
716 if event & (select.POLLERR | select.POLLHUP | select.POLLNVAL):
cliechtia9a093e2010-01-02 03:05:08 +0000717 raise SerialException('device reports error (poll)')
718 # we don't care if it is select.POLLIN or timeout, that's
719 # handled below
720 buf = os.read(self.fd, size - len(read))
721 read.extend(buf)
Chris Liechti518b0d32015-08-30 02:20:39 +0200722 if ((self._timeout is not None and self._timeout >= 0) or
Chris Liechti033f17c2015-08-30 21:28:04 +0200723 (self._inter_byte_timeout is not None and self._inter_byte_timeout > 0)) and not buf:
cliechtia9a093e2010-01-02 03:05:08 +0000724 break # early abort on timeout
725 return bytes(read)
726
cliechtif81362e2009-07-25 03:44:33 +0000727
Chris Liechti4cf54702015-10-18 00:21:56 +0200728class VTIMESerial(Serial):
729 """\
730 Implement timeout using vtime of tty device instead of using select.
731 This means that no inter character timeout can be specified and that
732 the error handling is degraded.
733
734 Overall timeout is disabled when inter-character timeout is used.
735 """
736
Chris Liechti94284702015-11-15 01:21:48 +0100737 def _reconfigure_port(self, force_update=True):
Chris Liechti4cf54702015-10-18 00:21:56 +0200738 """Set communication parameters on opened port."""
739 super(VTIMESerial, self)._reconfigure_port()
740 fcntl.fcntl(self.fd, fcntl.F_SETFL, 0) # clear O_NONBLOCK
741
742 if self._inter_byte_timeout is not None:
743 vmin = 1
744 vtime = int(self._inter_byte_timeout * 10)
745 else:
746 vmin = 0
747 vtime = int(self._timeout * 10)
748 try:
749 orig_attr = termios.tcgetattr(self.fd)
750 iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
751 except termios.error as msg: # if a port is nonexistent but has a /dev file, it'll fail here
752 raise serial.SerialException("Could not configure port: %s" % msg)
753
754 if vtime < 0 or vtime > 255:
755 raise ValueError('Invalid vtime: %r' % vtime)
756 cc[termios.VTIME] = vtime
757 cc[termios.VMIN] = vmin
758
759 termios.tcsetattr(
760 self.fd,
761 termios.TCSANOW,
762 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
763
764
765 def read(self, size=1):
766 """\
767 Read size bytes from the serial port. If a timeout is set it may
768 return less characters as requested. With no timeout it will block
769 until the requested number of bytes is read.
770 """
771 if not self.is_open:
772 raise portNotOpenError
773 read = bytearray()
774 while len(read) < size:
775 buf = os.read(self.fd, size - len(read))
776 if not buf:
777 break
778 read.extend(buf)
779 return bytes(read)
780
781
cliechti89b4af12002-02-12 23:24:41 +0000782if __name__ == '__main__':
783 s = Serial(0,
Chris Liechti033f17c2015-08-30 21:28:04 +0200784 baudrate=19200, # baud rate
785 bytesize=serial.EIGHTBITS, # number of data bits
786 parity=serial.PARITY_EVEN, # enable parity checking
787 stopbits=serial.STOPBITS_ONE, # number of stop bits
788 timeout=3, # set a timeout value, None for waiting forever
789 xonxoff=0, # enable software flow control
790 rtscts=0, # enable RTS/CTS flow control
cliechti89b4af12002-02-12 23:24:41 +0000791 )
Chris Liechti033f17c2015-08-30 21:28:04 +0200792 s.rts = True
793 s.dtr = True
794 s.reset_input_buffer()
795 s.reset_output_buffer()
cliechti89b4af12002-02-12 23:24:41 +0000796 s.write('hello')
cliechti109486b2009-08-02 00:00:11 +0000797 sys.stdout.write('%r\n' % s.read(5))
798 sys.stdout.write('%s\n' % s.inWaiting())
cliechti89b4af12002-02-12 23:24:41 +0000799 del s