blob: 769cb4bf5ddc59681e1b6749f6c86f8c52eda140 [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 Liechtie13d0f62016-04-25 23:30:44 +02006# (C) 2001-2016 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 Liechtie13d0f62016-04-25 23:30:44 +020015# Collection of port names (was previously used by number_to_device which was
16# removed.
17# - Linux /dev/ttyS%d (confirmed)
18# - cygwin/win32 /dev/com%d (confirmed)
19# - openbsd (OpenBSD) /dev/cua%02d
20# - bsd*, freebsd* /dev/cuad%d
21# - darwin (OS X) /dev/cuad%d
22# - netbsd /dev/dty%02d (NetBSD 1.6 testing by Erk)
23# - irix (IRIX) /dev/ttyf%d (partially tested) names depending on flow control
24# - hp (HP-UX) /dev/tty%dp0 (not tested)
25# - sunos (Solaris/SunOS) /dev/tty%c (letters, 'a'..'z') (confirmed)
26# - aix (AIX) /dev/tty%d
27
28
Chris Liechti9eaa40c2016-02-12 23:32:59 +010029# pylint: disable=abstract-method
Chris Liechti33f0ec52015-08-06 16:37:21 +020030import errno
31import fcntl
Chris Liechti33f0ec52015-08-06 16:37:21 +020032import os
33import select
34import struct
35import sys
36import termios
Chris Liechti033f17c2015-08-30 21:28:04 +020037
38import serial
Chris Liechti935a2622016-08-30 23:39:15 +020039from serial.serialutil import SerialBase, SerialException, to_bytes, \
40 portNotOpenError, writeTimeoutError, Timeout
cliechti89b4af12002-02-12 23:24:41 +000041
cliechti89b4af12002-02-12 23:24:41 +000042
Chris Liechtid6847af2015-08-06 17:54:30 +020043class PlatformSpecificBase(object):
44 BAUDRATE_CONSTANTS = {}
cliechti89b4af12002-02-12 23:24:41 +000045
Chris Liechtid6847af2015-08-06 17:54:30 +020046 def _set_special_baudrate(self, baudrate):
47 raise NotImplementedError('non-standard baudrates are not supported on this platform')
48
49 def _set_rs485_mode(self, rs485_settings):
50 raise NotImplementedError('RS485 not supported on this platform')
51
Jan Kantert1b2658a2018-05-07 21:17:37 +020052 def set_low_latency_mode(self, low_latency_settings):
53 raise NotImplementedError('Low latency not supported on this platform')
54
Chris Liechti6dc58e82016-08-29 23:02:13 +020055
56# some systems support an extra flag to enable the two in POSIX unsupported
Chris Liechti11538242016-09-06 22:20:09 +020057# paritiy settings for MARK and SPACE
Chris Liechti6dc58e82016-08-29 23:02:13 +020058CMSPAR = 0 # default, for unsupported platforms, override below
59
Chris Liechtid6847af2015-08-06 17:54:30 +020060# try to detect the OS so that a device can be selected...
61# this code block should supply a device() and set_special_baudrate() function
62# for the platform
63plat = sys.platform.lower()
64
Chris Liechtiba45c522016-02-06 23:53:23 +010065if plat[:5] == 'linux': # Linux (confirmed) # noqa
Chris Liechtid6847af2015-08-06 17:54:30 +020066 import array
67
Chris Liechti6dc58e82016-08-29 23:02:13 +020068 # extra termios flags
69 CMSPAR = 0o10000000000 # Use "stick" (mark/space) parity
70
Chris Liechtid6847af2015-08-06 17:54:30 +020071 # baudrate ioctls
72 TCGETS2 = 0x802C542A
73 TCSETS2 = 0x402C542B
74 BOTHER = 0o010000
75
76 # RS485 ioctls
77 TIOCGRS485 = 0x542E
78 TIOCSRS485 = 0x542F
Chris Liechti033f17c2015-08-30 21:28:04 +020079 SER_RS485_ENABLED = 0b00000001
80 SER_RS485_RTS_ON_SEND = 0b00000010
Chris Liechtid6847af2015-08-06 17:54:30 +020081 SER_RS485_RTS_AFTER_SEND = 0b00000100
Chris Liechti033f17c2015-08-30 21:28:04 +020082 SER_RS485_RX_DURING_TX = 0b00010000
Chris Liechtid6847af2015-08-06 17:54:30 +020083
84 class PlatformSpecific(PlatformSpecificBase):
85 BAUDRATE_CONSTANTS = {
86 0: 0o000000, # hang up
87 50: 0o000001,
88 75: 0o000002,
89 110: 0o000003,
90 134: 0o000004,
91 150: 0o000005,
92 200: 0o000006,
93 300: 0o000007,
94 600: 0o000010,
95 1200: 0o000011,
96 1800: 0o000012,
97 2400: 0o000013,
98 4800: 0o000014,
99 9600: 0o000015,
100 19200: 0o000016,
101 38400: 0o000017,
102 57600: 0o010001,
103 115200: 0o010002,
104 230400: 0o010003,
105 460800: 0o010004,
106 500000: 0o010005,
107 576000: 0o010006,
108 921600: 0o010007,
109 1000000: 0o010010,
110 1152000: 0o010011,
111 1500000: 0o010012,
112 2000000: 0o010013,
113 2500000: 0o010014,
114 3000000: 0o010015,
115 3500000: 0o010016,
116 4000000: 0o010017
117 }
118
Jan Kantert1b2658a2018-05-07 21:17:37 +0200119 def set_low_latency_mode(self, low_latency_settings):
120 buf = array.array('i', [0] * 32)
121
122 try:
123 # get serial_struct
124 fcntl.ioctl(self.fd, termios.TIOCGSERIAL, buf)
125
126 # set or unset ASYNC_LOW_LATENCY flag
127 if low_latency_settings:
128 buf[4] |= 0x2000
129 else:
130 buf[4] &= ~0x2000
131
132 # set serial_struct
133 fcntl.ioctl(self.fd, termios.TIOCSSERIAL, buf)
134 except IOError as e:
135 raise ValueError('Failed to update ASYNC_LOW_LATENCY flag to {}: {}'.format(low_latency_settings, e))
136
Chris Liechtid6847af2015-08-06 17:54:30 +0200137 def _set_special_baudrate(self, baudrate):
138 # right size is 44 on x86_64, allow for some growth
139 buf = array.array('i', [0] * 64)
140 try:
141 # get serial_struct
142 fcntl.ioctl(self.fd, TCGETS2, buf)
143 # set custom speed
144 buf[2] &= ~termios.CBAUD
145 buf[2] |= BOTHER
146 buf[9] = buf[10] = baudrate
147
148 # set serial_struct
Chris Liechti033f17c2015-08-30 21:28:04 +0200149 fcntl.ioctl(self.fd, TCSETS2, buf)
Chris Liechtid6847af2015-08-06 17:54:30 +0200150 except IOError as e:
Chris Liechti984c5c52016-02-15 23:48:45 +0100151 raise ValueError('Failed to set custom baud rate ({}): {}'.format(baudrate, e))
Chris Liechtid6847af2015-08-06 17:54:30 +0200152
153 def _set_rs485_mode(self, rs485_settings):
Chris Liechti033f17c2015-08-30 21:28:04 +0200154 buf = array.array('i', [0] * 8) # flags, delaytx, delayrx, padding
Chris Liechtid6847af2015-08-06 17:54:30 +0200155 try:
156 fcntl.ioctl(self.fd, TIOCGRS485, buf)
Chris Liechti7a554462016-03-24 21:17:22 +0100157 buf[0] |= SER_RS485_ENABLED
Chris Liechtid6847af2015-08-06 17:54:30 +0200158 if rs485_settings is not None:
159 if rs485_settings.loopback:
160 buf[0] |= SER_RS485_RX_DURING_TX
161 else:
162 buf[0] &= ~SER_RS485_RX_DURING_TX
163 if rs485_settings.rts_level_for_tx:
164 buf[0] |= SER_RS485_RTS_ON_SEND
165 else:
166 buf[0] &= ~SER_RS485_RTS_ON_SEND
167 if rs485_settings.rts_level_for_rx:
168 buf[0] |= SER_RS485_RTS_AFTER_SEND
169 else:
170 buf[0] &= ~SER_RS485_RTS_AFTER_SEND
Chris Liechti279201b2016-06-09 20:27:05 +0200171 if rs485_settings.delay_before_tx is not None:
172 buf[1] = int(rs485_settings.delay_before_tx * 1000)
173 if rs485_settings.delay_before_rx is not None:
174 buf[2] = int(rs485_settings.delay_before_rx * 1000)
Chris Liechtid6847af2015-08-06 17:54:30 +0200175 else:
176 buf[0] = 0 # clear SER_RS485_ENABLED
Chris Liechti033f17c2015-08-30 21:28:04 +0200177 fcntl.ioctl(self.fd, TIOCSRS485, buf)
Chris Liechtid6847af2015-08-06 17:54:30 +0200178 except IOError as e:
Chris Liechti984c5c52016-02-15 23:48:45 +0100179 raise ValueError('Failed to set RS485 mode: {}'.format(e))
Chris Liechtid6847af2015-08-06 17:54:30 +0200180
181
182elif plat == 'cygwin': # cygwin/win32 (confirmed)
183
184 class PlatformSpecific(PlatformSpecificBase):
185 BAUDRATE_CONSTANTS = {
186 128000: 0x01003,
187 256000: 0x01005,
188 500000: 0x01007,
189 576000: 0x01008,
190 921600: 0x01009,
191 1000000: 0x0100a,
192 1152000: 0x0100b,
193 1500000: 0x0100c,
194 2000000: 0x0100d,
195 2500000: 0x0100e,
196 3000000: 0x0100f
197 }
198
Chris Liechtid6847af2015-08-06 17:54:30 +0200199
200elif plat[:6] == 'darwin': # OS X
201 import array
Chris Liechti033f17c2015-08-30 21:28:04 +0200202 IOSSIOSPEED = 0x80045402 # _IOW('T', 2, speed_t)
Chris Liechtid6847af2015-08-06 17:54:30 +0200203
204 class PlatformSpecific(PlatformSpecificBase):
Chris Liechtid6847af2015-08-06 17:54:30 +0200205 osx_version = os.uname()[2].split('.')
206 # Tiger or above can support arbitrary serial speeds
207 if int(osx_version[0]) >= 8:
208 def _set_special_baudrate(self, baudrate):
209 # use IOKit-specific call to set up high speeds
210 buf = array.array('i', [baudrate])
211 fcntl.ioctl(self.fd, IOSSIOSPEED, buf, 1)
212
Chris Liechti21a306b2016-10-09 23:41:26 +0200213elif plat[:3] == 'bsd' or \
214 plat[:7] == 'freebsd' or \
215 plat[:6] == 'netbsd' or \
216 plat[:7] == 'openbsd':
217
218 class ReturnBaudrate(object):
219 def __getitem__(self, key):
220 return key
221
222 class PlatformSpecific(PlatformSpecificBase):
223 # Only tested on FreeBSD:
224 # The baud rate may be passed in as
225 # a literal value.
226 BAUDRATE_CONSTANTS = ReturnBaudrate()
227
Chris Liechtid6847af2015-08-06 17:54:30 +0200228else:
229 class PlatformSpecific(PlatformSpecificBase):
230 pass
cliechti89b4af12002-02-12 23:24:41 +0000231
cliechti89b4af12002-02-12 23:24:41 +0000232
cliechti58b481c2009-02-16 20:42:32 +0000233# load some constants for later use.
Chris Liechti11465c82015-08-04 15:55:22 +0200234# try to use values from termios, use defaults from linux otherwise
Chris Liechti033f17c2015-08-30 21:28:04 +0200235TIOCMGET = getattr(termios, 'TIOCMGET', 0x5415)
236TIOCMBIS = getattr(termios, 'TIOCMBIS', 0x5416)
237TIOCMBIC = getattr(termios, 'TIOCMBIC', 0x5417)
238TIOCMSET = getattr(termios, 'TIOCMSET', 0x5418)
cliechti89b4af12002-02-12 23:24:41 +0000239
Chris Liechti033f17c2015-08-30 21:28:04 +0200240# TIOCM_LE = getattr(termios, 'TIOCM_LE', 0x001)
Chris Liechtid6847af2015-08-06 17:54:30 +0200241TIOCM_DTR = getattr(termios, 'TIOCM_DTR', 0x002)
242TIOCM_RTS = getattr(termios, 'TIOCM_RTS', 0x004)
Chris Liechti033f17c2015-08-30 21:28:04 +0200243# TIOCM_ST = getattr(termios, 'TIOCM_ST', 0x008)
244# TIOCM_SR = getattr(termios, 'TIOCM_SR', 0x010)
cliechti89b4af12002-02-12 23:24:41 +0000245
Chris Liechtid6847af2015-08-06 17:54:30 +0200246TIOCM_CTS = getattr(termios, 'TIOCM_CTS', 0x020)
247TIOCM_CAR = getattr(termios, 'TIOCM_CAR', 0x040)
248TIOCM_RNG = getattr(termios, 'TIOCM_RNG', 0x080)
249TIOCM_DSR = getattr(termios, 'TIOCM_DSR', 0x100)
Chris Liechti033f17c2015-08-30 21:28:04 +0200250TIOCM_CD = getattr(termios, 'TIOCM_CD', TIOCM_CAR)
251TIOCM_RI = getattr(termios, 'TIOCM_RI', TIOCM_RNG)
252# TIOCM_OUT1 = getattr(termios, 'TIOCM_OUT1', 0x2000)
253# TIOCM_OUT2 = getattr(termios, 'TIOCM_OUT2', 0x4000)
Chris Liechti11465c82015-08-04 15:55:22 +0200254if hasattr(termios, 'TIOCINQ'):
255 TIOCINQ = termios.TIOCINQ
cliechti28b8fd02011-12-28 21:39:42 +0000256else:
Chris Liechtid6847af2015-08-06 17:54:30 +0200257 TIOCINQ = getattr(termios, 'FIONREAD', 0x541B)
Chris Liechti033f17c2015-08-30 21:28:04 +0200258TIOCOUTQ = getattr(termios, 'TIOCOUTQ', 0x5411)
cliechti89b4af12002-02-12 23:24:41 +0000259
260TIOCM_zero_str = struct.pack('I', 0)
261TIOCM_RTS_str = struct.pack('I', TIOCM_RTS)
262TIOCM_DTR_str = struct.pack('I', TIOCM_DTR)
263
Chris Liechti033f17c2015-08-30 21:28:04 +0200264TIOCSBRK = getattr(termios, 'TIOCSBRK', 0x5427)
265TIOCCBRK = getattr(termios, 'TIOCCBRK', 0x5428)
cliechti997b63c2008-06-21 00:09:31 +0000266
cliechti89b4af12002-02-12 23:24:41 +0000267
Chris Liechtief6b7b42015-08-06 22:19:26 +0200268class Serial(SerialBase, PlatformSpecific):
cliechti7d448562014-08-03 21:57:45 +0000269 """\
Chris Liechti033f17c2015-08-30 21:28:04 +0200270 Serial port class POSIX implementation. Serial port configuration is
cliechtid6bf52c2003-10-01 02:28:12 +0000271 done with termios and fcntl. Runs on Linux and many other Un*x like
cliechtif0a81d42014-08-04 14:03:53 +0000272 systems.
273 """
cliechtid6bf52c2003-10-01 02:28:12 +0000274
275 def open(self):
cliechti7d448562014-08-03 21:57:45 +0000276 """\
277 Open port with current settings. This may throw a SerialException
278 if the port cannot be opened."""
cliechtid6bf52c2003-10-01 02:28:12 +0000279 if self._port is None:
280 raise SerialException("Port must be configured before it can be used.")
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200281 if self.is_open:
cliechti02ef43a2011-03-24 23:33:12 +0000282 raise SerialException("Port is already open.")
283 self.fd = None
cliechti58b481c2009-02-16 20:42:32 +0000284 # open
cliechti4616bf12002-04-08 23:13:14 +0000285 try:
Chris Liechti033f17c2015-08-30 21:28:04 +0200286 self.fd = os.open(self.portstr, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK)
Chris Liechti68340d72015-08-03 14:15:48 +0200287 except OSError as msg:
cliechti4616bf12002-04-08 23:13:14 +0000288 self.fd = None
Chris Liechti984c5c52016-02-15 23:48:45 +0100289 raise SerialException(msg.errno, "could not open port {}: {}".format(self._port, msg))
Chris Liechti11465c82015-08-04 15:55:22 +0200290 #~ fcntl.fcntl(self.fd, fcntl.F_SETFL, 0) # set blocking
cliechti58b481c2009-02-16 20:42:32 +0000291
cliechtib2f5fc82006-10-20 00:09:07 +0000292 try:
Chris Liechti94284702015-11-15 01:21:48 +0100293 self._reconfigure_port(force_update=True)
cliechtib2f5fc82006-10-20 00:09:07 +0000294 except:
cliechti2750b832009-07-28 00:13:52 +0000295 try:
296 os.close(self.fd)
297 except:
298 # ignore any exception when closing the port
299 # also to keep original exception that happened when setting up
300 pass
cliechtib2f5fc82006-10-20 00:09:07 +0000301 self.fd = None
cliechtif0a4f0f2009-07-21 21:12:37 +0000302 raise
cliechtib2f5fc82006-10-20 00:09:07 +0000303 else:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200304 self.is_open = True
Chris Liechtif2fdeb92016-05-07 23:57:50 +0200305 try:
306 if not self._dsrdtr:
307 self._update_dtr_state()
308 if not self._rtscts:
309 self._update_rts_state()
310 except IOError as e:
Chris Liechtie1029622016-10-02 23:54:36 +0200311 if e.errno in (errno.EINVAL, errno.ENOTTY):
312 # ignore Invalid argument and Inappropriate ioctl
Chris Liechtif2fdeb92016-05-07 23:57:50 +0200313 pass
314 else:
315 raise
Chris Liechtief1fe252015-08-27 23:25:21 +0200316 self.reset_input_buffer()
Chris Liechti42ab2b42016-05-15 23:35:05 +0200317 self.pipe_abort_read_r, self.pipe_abort_read_w = os.pipe()
Chris Liechti13949c62016-05-16 22:45:38 +0200318 self.pipe_abort_write_r, self.pipe_abort_write_w = os.pipe()
Chris Liechti68cecce2016-06-03 23:52:34 +0200319 fcntl.fcntl(self.pipe_abort_read_r, fcntl.F_SETFL, os.O_NONBLOCK)
320 fcntl.fcntl(self.pipe_abort_write_r, fcntl.F_SETFL, os.O_NONBLOCK)
cliechti58b481c2009-02-16 20:42:32 +0000321
Chris Liechti94284702015-11-15 01:21:48 +0100322 def _reconfigure_port(self, force_update=False):
cliechtib2f5fc82006-10-20 00:09:07 +0000323 """Set communication parameters on opened port."""
cliechtic6178262004-03-22 22:04:52 +0000324 if self.fd is None:
cliechtia9a093e2010-01-02 03:05:08 +0000325 raise SerialException("Can only operate on a valid file descriptor")
Chris Liechti1c4bc812017-03-08 02:44:04 +0100326
Rob Gaddi636cc642017-02-24 11:39:46 -0800327 # if exclusive lock is requested, create it before we modify anything else
328 if self._exclusive is not None:
329 if self._exclusive:
330 try:
331 fcntl.flock(self.fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
332 except IOError as msg:
333 raise SerialException(msg.errno, "Could not exclusively lock port {}: {}".format(self._port, msg))
334 else:
335 fcntl.flock(self.fd, fcntl.LOCK_UN)
Chris Liechti1c4bc812017-03-08 02:44:04 +0100336
cliechtie8c45422008-06-20 23:23:14 +0000337 custom_baud = None
cliechti58b481c2009-02-16 20:42:32 +0000338
cliechti2750b832009-07-28 00:13:52 +0000339 vmin = vtime = 0 # timeout is done via select
Chris Liechti518b0d32015-08-30 02:20:39 +0200340 if self._inter_byte_timeout is not None:
cliechti679bfa62008-06-20 23:58:15 +0000341 vmin = 1
Chris Liechti518b0d32015-08-30 02:20:39 +0200342 vtime = int(self._inter_byte_timeout * 10)
cliechti6ce7ab12002-11-07 02:15:00 +0000343 try:
cliechti4d0af5e2011-08-05 02:18:16 +0000344 orig_attr = termios.tcgetattr(self.fd)
345 iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
Chris Liechti68340d72015-08-03 14:15:48 +0200346 except termios.error as msg: # if a port is nonexistent but has a /dev file, it'll fail here
Chris Liechti984c5c52016-02-15 23:48:45 +0100347 raise SerialException("Could not configure port: {}".format(msg))
cliechti58b481c2009-02-16 20:42:32 +0000348 # set up raw mode / no echo / binary
Chris Liechti033f17c2015-08-30 21:28:04 +0200349 cflag |= (termios.CLOCAL | termios.CREAD)
350 lflag &= ~(termios.ICANON | termios.ECHO | termios.ECHOE |
351 termios.ECHOK | termios.ECHONL |
352 termios.ISIG | termios.IEXTEN) # |termios.ECHOPRT
353 for flag in ('ECHOCTL', 'ECHOKE'): # netbsd workaround for Erk
Chris Liechti11465c82015-08-04 15:55:22 +0200354 if hasattr(termios, flag):
355 lflag &= ~getattr(termios, flag)
cliechti58b481c2009-02-16 20:42:32 +0000356
Chris Liechti033f17c2015-08-30 21:28:04 +0200357 oflag &= ~(termios.OPOST | termios.ONLCR | termios.OCRNL)
358 iflag &= ~(termios.INLCR | termios.IGNCR | termios.ICRNL | termios.IGNBRK)
Chris Liechti11465c82015-08-04 15:55:22 +0200359 if hasattr(termios, 'IUCLC'):
360 iflag &= ~termios.IUCLC
361 if hasattr(termios, 'PARMRK'):
362 iflag &= ~termios.PARMRK
cliechti58b481c2009-02-16 20:42:32 +0000363
cliechtif0a4f0f2009-07-21 21:12:37 +0000364 # setup baud rate
cliechti89b4af12002-02-12 23:24:41 +0000365 try:
Chris Liechti984c5c52016-02-15 23:48:45 +0100366 ispeed = ospeed = getattr(termios, 'B{}'.format(self._baudrate))
cliechti895e8302004-04-20 02:40:28 +0000367 except AttributeError:
cliechtif1559d02007-11-08 23:43:58 +0000368 try:
Chris Liechtid6847af2015-08-06 17:54:30 +0200369 ispeed = ospeed = self.BAUDRATE_CONSTANTS[self._baudrate]
cliechtif1559d02007-11-08 23:43:58 +0000370 except KeyError:
cliechtie8c45422008-06-20 23:23:14 +0000371 #~ raise ValueError('Invalid baud rate: %r' % self._baudrate)
cliechtif0a4f0f2009-07-21 21:12:37 +0000372 # may need custom baud rate, it isn't in our list.
Chris Liechti11465c82015-08-04 15:55:22 +0200373 ispeed = ospeed = getattr(termios, 'B38400')
cliechtif0a4f0f2009-07-21 21:12:37 +0000374 try:
Chris Liechti033f17c2015-08-30 21:28:04 +0200375 custom_baud = int(self._baudrate) # store for later
cliechtif0a4f0f2009-07-21 21:12:37 +0000376 except ValueError:
Chris Liechti984c5c52016-02-15 23:48:45 +0100377 raise ValueError('Invalid baud rate: {!r}'.format(self._baudrate))
cliechtif0a4f0f2009-07-21 21:12:37 +0000378 else:
379 if custom_baud < 0:
Chris Liechti984c5c52016-02-15 23:48:45 +0100380 raise ValueError('Invalid baud rate: {!r}'.format(self._baudrate))
cliechti58b481c2009-02-16 20:42:32 +0000381
382 # setup char len
Chris Liechti11465c82015-08-04 15:55:22 +0200383 cflag &= ~termios.CSIZE
cliechtid6bf52c2003-10-01 02:28:12 +0000384 if self._bytesize == 8:
Chris Liechti11465c82015-08-04 15:55:22 +0200385 cflag |= termios.CS8
cliechtid6bf52c2003-10-01 02:28:12 +0000386 elif self._bytesize == 7:
Chris Liechti11465c82015-08-04 15:55:22 +0200387 cflag |= termios.CS7
cliechtid6bf52c2003-10-01 02:28:12 +0000388 elif self._bytesize == 6:
Chris Liechti11465c82015-08-04 15:55:22 +0200389 cflag |= termios.CS6
cliechtid6bf52c2003-10-01 02:28:12 +0000390 elif self._bytesize == 5:
Chris Liechti11465c82015-08-04 15:55:22 +0200391 cflag |= termios.CS5
cliechti89b4af12002-02-12 23:24:41 +0000392 else:
Chris Liechti984c5c52016-02-15 23:48:45 +0100393 raise ValueError('Invalid char len: {!r}'.format(self._bytesize))
cliechtif0a81d42014-08-04 14:03:53 +0000394 # setup stop bits
Chris Liechti033f17c2015-08-30 21:28:04 +0200395 if self._stopbits == serial.STOPBITS_ONE:
Chris Liechti11465c82015-08-04 15:55:22 +0200396 cflag &= ~(termios.CSTOPB)
Chris Liechti033f17c2015-08-30 21:28:04 +0200397 elif self._stopbits == serial.STOPBITS_ONE_POINT_FIVE:
398 cflag |= (termios.CSTOPB) # XXX same as TWO.. there is no POSIX support for 1.5
399 elif self._stopbits == serial.STOPBITS_TWO:
400 cflag |= (termios.CSTOPB)
cliechti89b4af12002-02-12 23:24:41 +0000401 else:
Chris Liechti984c5c52016-02-15 23:48:45 +0100402 raise ValueError('Invalid stop bit specification: {!r}'.format(self._stopbits))
cliechti58b481c2009-02-16 20:42:32 +0000403 # setup parity
Chris Liechti033f17c2015-08-30 21:28:04 +0200404 iflag &= ~(termios.INPCK | termios.ISTRIP)
405 if self._parity == serial.PARITY_NONE:
Chris Liechti6dc58e82016-08-29 23:02:13 +0200406 cflag &= ~(termios.PARENB | termios.PARODD | CMSPAR)
Chris Liechti033f17c2015-08-30 21:28:04 +0200407 elif self._parity == serial.PARITY_EVEN:
Chris Liechti6dc58e82016-08-29 23:02:13 +0200408 cflag &= ~(termios.PARODD | CMSPAR)
Chris Liechti033f17c2015-08-30 21:28:04 +0200409 cflag |= (termios.PARENB)
410 elif self._parity == serial.PARITY_ODD:
Chris Liechti6dc58e82016-08-29 23:02:13 +0200411 cflag &= ~CMSPAR
Chris Liechti033f17c2015-08-30 21:28:04 +0200412 cflag |= (termios.PARENB | termios.PARODD)
Chris Liechti6dc58e82016-08-29 23:02:13 +0200413 elif self._parity == serial.PARITY_MARK and CMSPAR:
Chris Liechti033f17c2015-08-30 21:28:04 +0200414 cflag |= (termios.PARENB | CMSPAR | termios.PARODD)
Chris Liechti6dc58e82016-08-29 23:02:13 +0200415 elif self._parity == serial.PARITY_SPACE and CMSPAR:
Chris Liechti033f17c2015-08-30 21:28:04 +0200416 cflag |= (termios.PARENB | CMSPAR)
Chris Liechti11465c82015-08-04 15:55:22 +0200417 cflag &= ~(termios.PARODD)
cliechti89b4af12002-02-12 23:24:41 +0000418 else:
Chris Liechti984c5c52016-02-15 23:48:45 +0100419 raise ValueError('Invalid parity: {!r}'.format(self._parity))
cliechti58b481c2009-02-16 20:42:32 +0000420 # setup flow control
421 # xonxoff
Chris Liechti11465c82015-08-04 15:55:22 +0200422 if hasattr(termios, 'IXANY'):
cliechtid6bf52c2003-10-01 02:28:12 +0000423 if self._xonxoff:
Chris Liechti033f17c2015-08-30 21:28:04 +0200424 iflag |= (termios.IXON | termios.IXOFF) # |termios.IXANY)
cliechti89b4af12002-02-12 23:24:41 +0000425 else:
Chris Liechti033f17c2015-08-30 21:28:04 +0200426 iflag &= ~(termios.IXON | termios.IXOFF | termios.IXANY)
cliechti89b4af12002-02-12 23:24:41 +0000427 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000428 if self._xonxoff:
Chris Liechti033f17c2015-08-30 21:28:04 +0200429 iflag |= (termios.IXON | termios.IXOFF)
cliechti89b4af12002-02-12 23:24:41 +0000430 else:
Chris Liechti033f17c2015-08-30 21:28:04 +0200431 iflag &= ~(termios.IXON | termios.IXOFF)
cliechti58b481c2009-02-16 20:42:32 +0000432 # rtscts
Chris Liechti11465c82015-08-04 15:55:22 +0200433 if hasattr(termios, 'CRTSCTS'):
cliechtid6bf52c2003-10-01 02:28:12 +0000434 if self._rtscts:
Chris Liechti033f17c2015-08-30 21:28:04 +0200435 cflag |= (termios.CRTSCTS)
cliechti89b4af12002-02-12 23:24:41 +0000436 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200437 cflag &= ~(termios.CRTSCTS)
438 elif hasattr(termios, 'CNEW_RTSCTS'): # try it with alternate constant name
cliechtid6bf52c2003-10-01 02:28:12 +0000439 if self._rtscts:
Chris Liechti033f17c2015-08-30 21:28:04 +0200440 cflag |= (termios.CNEW_RTSCTS)
cliechtid4743692002-04-08 22:39:53 +0000441 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200442 cflag &= ~(termios.CNEW_RTSCTS)
cliechti2750b832009-07-28 00:13:52 +0000443 # XXX should there be a warning if setting up rtscts (and xonxoff etc) fails??
cliechti58b481c2009-02-16 20:42:32 +0000444
445 # buffer
cliechtif0a81d42014-08-04 14:03:53 +0000446 # vmin "minimal number of characters to be read. 0 for non blocking"
cliechtid6bf52c2003-10-01 02:28:12 +0000447 if vmin < 0 or vmin > 255:
Chris Liechti984c5c52016-02-15 23:48:45 +0100448 raise ValueError('Invalid vmin: {!r}'.format(vmin))
Chris Liechti11465c82015-08-04 15:55:22 +0200449 cc[termios.VMIN] = vmin
cliechti58b481c2009-02-16 20:42:32 +0000450 # vtime
cliechtid6bf52c2003-10-01 02:28:12 +0000451 if vtime < 0 or vtime > 255:
Chris Liechti984c5c52016-02-15 23:48:45 +0100452 raise ValueError('Invalid vtime: {!r}'.format(vtime))
Chris Liechti11465c82015-08-04 15:55:22 +0200453 cc[termios.VTIME] = vtime
cliechti58b481c2009-02-16 20:42:32 +0000454 # activate settings
Chris Liechti94284702015-11-15 01:21:48 +0100455 if force_update or [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] != orig_attr:
Chris Liechti033f17c2015-08-30 21:28:04 +0200456 termios.tcsetattr(
Chris Liechti9eaa40c2016-02-12 23:32:59 +0100457 self.fd,
458 termios.TCSANOW,
459 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
cliechti58b481c2009-02-16 20:42:32 +0000460
cliechtie8c45422008-06-20 23:23:14 +0000461 # apply custom baud rate, if any
462 if custom_baud is not None:
Chris Liechtid6847af2015-08-06 17:54:30 +0200463 self._set_special_baudrate(custom_baud)
464
465 if self._rs485_mode is not None:
466 self._set_rs485_mode(self._rs485_mode)
cliechti89b4af12002-02-12 23:24:41 +0000467
468 def close(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000469 """Close port"""
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200470 if self.is_open:
cliechtic6178262004-03-22 22:04:52 +0000471 if self.fd is not None:
cliechtid6bf52c2003-10-01 02:28:12 +0000472 os.close(self.fd)
473 self.fd = None
Chris Liechtib658eac2016-05-22 20:51:44 +0200474 os.close(self.pipe_abort_read_w)
475 os.close(self.pipe_abort_read_r)
476 os.close(self.pipe_abort_write_w)
477 os.close(self.pipe_abort_write_r)
478 self.pipe_abort_read_r, self.pipe_abort_read_w = None, None
479 self.pipe_abort_write_r, self.pipe_abort_write_w = None, None
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200480 self.is_open = False
cliechtid6bf52c2003-10-01 02:28:12 +0000481
482 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechti95c62212002-03-04 22:17:53 +0000483
Chris Liechtief1fe252015-08-27 23:25:21 +0200484 @property
485 def in_waiting(self):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200486 """Return the number of bytes currently in the input buffer."""
Chris Liechti11465c82015-08-04 15:55:22 +0200487 #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str)
cliechtif5831e02002-12-05 23:15:27 +0000488 s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200489 return struct.unpack('I', s)[0]
cliechti89b4af12002-02-12 23:24:41 +0000490
cliechtia9a093e2010-01-02 03:05:08 +0000491 # select based implementation, proved to work on many systems
492 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000493 """\
494 Read size bytes from the serial port. If a timeout is set it may
495 return less characters as requested. With no timeout it will block
496 until the requested number of bytes is read.
497 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200498 if not self.is_open:
499 raise portNotOpenError
cliechtia9a093e2010-01-02 03:05:08 +0000500 read = bytearray()
Chris Liechti935a2622016-08-30 23:39:15 +0200501 timeout = Timeout(self._timeout)
cliechtia9a093e2010-01-02 03:05:08 +0000502 while len(read) < size:
cliechti8d744de2013-10-11 14:31:13 +0000503 try:
Chris Liechti935a2622016-08-30 23:39:15 +0200504 ready, _, _ = select.select([self.fd, self.pipe_abort_read_r], [], [], timeout.time_left())
Chris Liechti42ab2b42016-05-15 23:35:05 +0200505 if self.pipe_abort_read_r in ready:
Chris Liechti68cecce2016-06-03 23:52:34 +0200506 os.read(self.pipe_abort_read_r, 1000)
Chris Liechti42ab2b42016-05-15 23:35:05 +0200507 break
cliechti8d744de2013-10-11 14:31:13 +0000508 # If select was used with a timeout, and the timeout occurs, it
509 # returns with empty lists -> thus abort read operation.
Chris Liechti033f17c2015-08-30 21:28:04 +0200510 # For timeout == 0 (non-blocking operation) also abort when
511 # there is nothing to read.
cliechti8d744de2013-10-11 14:31:13 +0000512 if not ready:
513 break # timeout
Chris Liechti033f17c2015-08-30 21:28:04 +0200514 buf = os.read(self.fd, size - len(read))
cliechti8d744de2013-10-11 14:31:13 +0000515 # read should always return some data as select reported it was
516 # ready to read when we get to this point.
517 if not buf:
518 # Disconnected devices, at least on Linux, show the
519 # behavior that they are always ready to read immediately
520 # but reading returns nothing.
Chris Liechti92df95a2016-02-09 23:30:37 +0100521 raise SerialException(
522 'device reports readiness to read but returned no data '
523 '(device disconnected or multiple access on port?)')
cliechti8d744de2013-10-11 14:31:13 +0000524 read.extend(buf)
Chris Liechti68340d72015-08-03 14:15:48 +0200525 except OSError as e:
Chris Liechti033f17c2015-08-30 21:28:04 +0200526 # this is for Python 3.x where select.error is a subclass of
Chris Liechti17660ee2017-05-04 23:39:05 +0200527 # OSError ignore BlockingIOErrors and EINTR. other errors are shown
528 # https://www.python.org/dev/peps/pep-0475.
529 if e.errno not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
Chris Liechti984c5c52016-02-15 23:48:45 +0100530 raise SerialException('read failed: {}'.format(e))
Chris Liechti68340d72015-08-03 14:15:48 +0200531 except select.error as e:
cliechtic7cd7212014-08-03 21:34:38 +0000532 # this is for Python 2.x
Chris Liechti17660ee2017-05-04 23:39:05 +0200533 # ignore BlockingIOErrors and EINTR. all errors are shown
cliechti8d744de2013-10-11 14:31:13 +0000534 # see also http://www.python.org/dev/peps/pep-3151/#select
Chris Liechti1c8dbee2017-05-05 03:26:51 +0200535 if e[0] not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
Chris Liechti984c5c52016-02-15 23:48:45 +0100536 raise SerialException('read failed: {}'.format(e))
Chris Liechti935a2622016-08-30 23:39:15 +0200537 if timeout.expired():
538 break
cliechtia9a093e2010-01-02 03:05:08 +0000539 return bytes(read)
cliechti89b4af12002-02-12 23:24:41 +0000540
Chris Liechti42ab2b42016-05-15 23:35:05 +0200541 def cancel_read(self):
Chris Liechti9c326282017-07-15 01:58:56 +0200542 if self.is_open:
543 os.write(self.pipe_abort_read_w, b"x")
Chris Liechti42ab2b42016-05-15 23:35:05 +0200544
Chris Liechti13949c62016-05-16 22:45:38 +0200545 def cancel_write(self):
Chris Liechti9c326282017-07-15 01:58:56 +0200546 if self.is_open:
547 os.write(self.pipe_abort_write_w, b"x")
Chris Liechti13949c62016-05-16 22:45:38 +0200548
cliechti4a567a02009-07-27 22:09:31 +0000549 def write(self, data):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200550 """Output the given byte string over the serial port."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200551 if not self.is_open:
552 raise portNotOpenError
cliechti38077122013-10-16 02:57:27 +0000553 d = to_bytes(data)
Chris Liechtie0063f12016-12-17 23:44:18 +0100554 tx_len = length = len(d)
Chris Liechti935a2622016-08-30 23:39:15 +0200555 timeout = Timeout(self._write_timeout)
cliechti9f7c2352013-10-11 01:13:46 +0000556 while tx_len > 0:
cliechti5d4d0bd2004-11-13 03:27:39 +0000557 try:
cliechti5d4d0bd2004-11-13 03:27:39 +0000558 n = os.write(self.fd, d)
Chris Liechti935a2622016-08-30 23:39:15 +0200559 if timeout.is_non_blocking:
Robert Smallshire325a7382016-03-25 21:18:38 +0100560 # Zero timeout indicates non-blocking - simply return the
561 # number of bytes of data actually written
562 return n
Chris Liechti935a2622016-08-30 23:39:15 +0200563 elif not timeout.is_infinite:
cliechti3cf46d62009-08-07 00:19:57 +0000564 # when timeout is set, use select to wait for being ready
565 # with the time left as timeout
Chris Liechti935a2622016-08-30 23:39:15 +0200566 if timeout.expired():
cliechti3cf46d62009-08-07 00:19:57 +0000567 raise writeTimeoutError
Chris Liechti935a2622016-08-30 23:39:15 +0200568 abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], timeout.time_left())
Chris Liechti13949c62016-05-16 22:45:38 +0200569 if abort:
Chris Liechti68cecce2016-06-03 23:52:34 +0200570 os.read(self.pipe_abort_write_r, 1000)
Chris Liechti13949c62016-05-16 22:45:38 +0200571 break
cliechti5d4d0bd2004-11-13 03:27:39 +0000572 if not ready:
573 raise writeTimeoutError
cliechti88c62442013-10-12 04:03:16 +0000574 else:
Chris Liechti935a2622016-08-30 23:39:15 +0200575 assert timeout.time_left() is None
cliechti88c62442013-10-12 04:03:16 +0000576 # wait for write operation
Chris Liechti13949c62016-05-16 22:45:38 +0200577 abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], None)
578 if abort:
579 os.read(self.pipe_abort_write_r, 1)
580 break
cliechti88c62442013-10-12 04:03:16 +0000581 if not ready:
582 raise SerialException('write failed (select)')
cliechti5d4d0bd2004-11-13 03:27:39 +0000583 d = d[n:]
cliechti9f7c2352013-10-11 01:13:46 +0000584 tx_len -= n
Chris Liechti675f7e12015-08-03 15:48:41 +0200585 except SerialException:
586 raise
Chris Liechti10d79d92017-05-05 00:05:23 +0200587 except OSError as e:
588 # this is for Python 3.x where select.error is a subclass of
589 # OSError ignore BlockingIOErrors and EINTR. other errors are shown
590 # https://www.python.org/dev/peps/pep-0475.
591 if e.errno not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
592 raise SerialException('write failed: {}'.format(e))
593 except select.error as e:
594 # this is for Python 2.x
595 # ignore BlockingIOErrors and EINTR. all errors are shown
596 # see also http://www.python.org/dev/peps/pep-3151/#select
Chris Liechti1c8dbee2017-05-05 03:26:51 +0200597 if e[0] not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
Chris Liechti10d79d92017-05-05 00:05:23 +0200598 raise SerialException('write failed: {}'.format(e))
Chris Liechtifc70fd72017-05-05 02:59:06 +0200599 if not timeout.is_non_blocking and timeout.expired():
Chris Liechti10d79d92017-05-05 00:05:23 +0200600 raise writeTimeoutError
Chris Liechtie0063f12016-12-17 23:44:18 +0100601 return length - len(d)
cliechtid6bf52c2003-10-01 02:28:12 +0000602
cliechtia30a8a02003-10-05 12:28:13 +0000603 def flush(self):
cliechti7d448562014-08-03 21:57:45 +0000604 """\
605 Flush of file like objects. In this case, wait until all data
606 is written.
607 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200608 if not self.is_open:
609 raise portNotOpenError
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200610 termios.tcdrain(self.fd)
cliechtia30a8a02003-10-05 12:28:13 +0000611
Chris Liechtief1fe252015-08-27 23:25:21 +0200612 def reset_input_buffer(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000613 """Clear input buffer, discarding all that is in the buffer."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200614 if not self.is_open:
615 raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200616 termios.tcflush(self.fd, termios.TCIFLUSH)
cliechti89b4af12002-02-12 23:24:41 +0000617
Chris Liechtief1fe252015-08-27 23:25:21 +0200618 def reset_output_buffer(self):
cliechti7d448562014-08-03 21:57:45 +0000619 """\
620 Clear output buffer, aborting the current output and discarding all
621 that is in the buffer.
622 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200623 if not self.is_open:
624 raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200625 termios.tcflush(self.fd, termios.TCOFLUSH)
cliechti89b4af12002-02-12 23:24:41 +0000626
Chris Liechtief1fe252015-08-27 23:25:21 +0200627 def send_break(self, duration=0.25):
cliechti7d448562014-08-03 21:57:45 +0000628 """\
629 Send break condition. Timed, returns to idle state after given
630 duration.
631 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200632 if not self.is_open:
633 raise portNotOpenError
634 termios.tcsendbreak(self.fd, int(duration / 0.25))
cliechti89b4af12002-02-12 23:24:41 +0000635
Chris Liechtief1fe252015-08-27 23:25:21 +0200636 def _update_break_state(self):
cliechti7d448562014-08-03 21:57:45 +0000637 """\
638 Set break: Controls TXD. When active, no transmitting is possible.
639 """
Chris Liechtief1fe252015-08-27 23:25:21 +0200640 if self._break_state:
cliechti997b63c2008-06-21 00:09:31 +0000641 fcntl.ioctl(self.fd, TIOCSBRK)
642 else:
643 fcntl.ioctl(self.fd, TIOCCBRK)
644
Chris Liechtief1fe252015-08-27 23:25:21 +0200645 def _update_rts_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000646 """Set terminal status line: Request To Send"""
Chris Liechtif7534c82016-05-07 23:35:54 +0200647 if self._rts_state:
648 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_RTS_str)
649 else:
650 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_RTS_str)
cliechtid6bf52c2003-10-01 02:28:12 +0000651
Chris Liechtief1fe252015-08-27 23:25:21 +0200652 def _update_dtr_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000653 """Set terminal status line: Data Terminal Ready"""
Chris Liechtif7534c82016-05-07 23:35:54 +0200654 if self._dtr_state:
655 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str)
656 else:
657 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_DTR_str)
cliechtid6bf52c2003-10-01 02:28:12 +0000658
Chris Liechtief1fe252015-08-27 23:25:21 +0200659 @property
660 def cts(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000661 """Read terminal status line: Clear To Send"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200662 if not self.is_open:
663 raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000664 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200665 return struct.unpack('I', s)[0] & TIOCM_CTS != 0
cliechtid6bf52c2003-10-01 02:28:12 +0000666
Chris Liechtief1fe252015-08-27 23:25:21 +0200667 @property
668 def dsr(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000669 """Read terminal status line: Data Set Ready"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200670 if not self.is_open:
671 raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000672 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200673 return struct.unpack('I', s)[0] & TIOCM_DSR != 0
cliechtid6bf52c2003-10-01 02:28:12 +0000674
Chris Liechtief1fe252015-08-27 23:25:21 +0200675 @property
676 def ri(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000677 """Read terminal status line: Ring Indicator"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200678 if not self.is_open:
679 raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000680 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200681 return struct.unpack('I', s)[0] & TIOCM_RI != 0
cliechti89b4af12002-02-12 23:24:41 +0000682
Chris Liechtief1fe252015-08-27 23:25:21 +0200683 @property
684 def cd(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000685 """Read terminal status line: Carrier Detect"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200686 if not self.is_open:
687 raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000688 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200689 return struct.unpack('I', s)[0] & TIOCM_CD != 0
cliechti89b4af12002-02-12 23:24:41 +0000690
cliechtia30a8a02003-10-05 12:28:13 +0000691 # - - platform specific - - - -
692
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200693 @property
694 def out_waiting(self):
695 """Return the number of bytes currently in the output buffer."""
Chris Liechti11465c82015-08-04 15:55:22 +0200696 #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str)
cliechti28b8fd02011-12-28 21:39:42 +0000697 s = fcntl.ioctl(self.fd, TIOCOUTQ, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200698 return struct.unpack('I', s)[0]
cliechti28b8fd02011-12-28 21:39:42 +0000699
cliechti8753bbc2005-01-15 20:32:51 +0000700 def fileno(self):
cliechti2f0f8a32011-12-28 22:10:00 +0000701 """\
702 For easier use of the serial port instance with select.
703 WARNING: this function is not portable to different platforms!
704 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200705 if not self.is_open:
706 raise portNotOpenError
cliechti8753bbc2005-01-15 20:32:51 +0000707 return self.fd
cliechti89b4af12002-02-12 23:24:41 +0000708
Chris Liechti518b0d32015-08-30 02:20:39 +0200709 def set_input_flow_control(self, enable=True):
cliechti2f0f8a32011-12-28 22:10:00 +0000710 """\
711 Manually control flow - when software flow control is enabled.
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200712 This will send XON (true) or XOFF (false) to the other device.
cliechti2f0f8a32011-12-28 22:10:00 +0000713 WARNING: this function is not portable to different platforms!
714 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200715 if not self.is_open:
716 raise portNotOpenError
cliechti4a601342011-12-29 02:22:17 +0000717 if enable:
Chris Liechti11465c82015-08-04 15:55:22 +0200718 termios.tcflow(self.fd, termios.TCION)
cliechti57e48a62009-08-03 22:29:58 +0000719 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200720 termios.tcflow(self.fd, termios.TCIOFF)
cliechti57e48a62009-08-03 22:29:58 +0000721
Chris Liechti518b0d32015-08-30 02:20:39 +0200722 def set_output_flow_control(self, enable=True):
cliechti2f0f8a32011-12-28 22:10:00 +0000723 """\
724 Manually control flow of outgoing data - when hardware or software flow
725 control is enabled.
726 WARNING: this function is not portable to different platforms!
727 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200728 if not self.is_open:
729 raise portNotOpenError
cliechti2f0f8a32011-12-28 22:10:00 +0000730 if enable:
Chris Liechti11465c82015-08-04 15:55:22 +0200731 termios.tcflow(self.fd, termios.TCOON)
cliechti2f0f8a32011-12-28 22:10:00 +0000732 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200733 termios.tcflow(self.fd, termios.TCOOFF)
cliechti2f0f8a32011-12-28 22:10:00 +0000734
Chris Liechti59848422016-06-04 22:28:14 +0200735 def nonblocking(self):
736 """DEPRECATED - has no use"""
737 import warnings
738 warnings.warn("nonblocking() has no effect, already nonblocking", DeprecationWarning)
739
cliechtif81362e2009-07-25 03:44:33 +0000740
cliechtia9a093e2010-01-02 03:05:08 +0000741class PosixPollSerial(Serial):
cliechti7d448562014-08-03 21:57:45 +0000742 """\
cliechtif0a81d42014-08-04 14:03:53 +0000743 Poll based read implementation. Not all systems support poll properly.
744 However this one has better handling of errors, such as a device
cliechti7d448562014-08-03 21:57:45 +0000745 disconnecting while it's in use (e.g. USB-serial unplugged).
746 """
cliechtia9a093e2010-01-02 03:05:08 +0000747
748 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000749 """\
750 Read size bytes from the serial port. If a timeout is set it may
751 return less characters as requested. With no timeout it will block
752 until the requested number of bytes is read.
753 """
Chris Liechtiacac2362016-03-29 22:37:48 +0200754 if not self.is_open:
Chris Liechti033f17c2015-08-30 21:28:04 +0200755 raise portNotOpenError
cliechtia9a093e2010-01-02 03:05:08 +0000756 read = bytearray()
Chris Liechtia5726382017-08-24 23:43:23 +0200757 timeout = Timeout(self._timeout)
cliechtia9a093e2010-01-02 03:05:08 +0000758 poll = select.poll()
Chris Liechti033f17c2015-08-30 21:28:04 +0200759 poll.register(self.fd, select.POLLIN | select.POLLERR | select.POLLHUP | select.POLLNVAL)
Chris Liechtia5726382017-08-24 23:43:23 +0200760 poll.register(self.pipe_abort_read_r, select.POLLIN | select.POLLERR | select.POLLHUP | select.POLLNVAL)
cliechtia9a093e2010-01-02 03:05:08 +0000761 if size > 0:
762 while len(read) < size:
763 # print "\tread(): size",size, "have", len(read) #debug
764 # wait until device becomes ready to read (or something fails)
Chris Liechtia5726382017-08-24 23:43:23 +0200765 for fd, event in poll.poll(None if timeout.is_infinite else (timeout.time_left() * 1000)):
766 if fd == self.pipe_abort_read_r:
767 break
Chris Liechti033f17c2015-08-30 21:28:04 +0200768 if event & (select.POLLERR | select.POLLHUP | select.POLLNVAL):
cliechtia9a093e2010-01-02 03:05:08 +0000769 raise SerialException('device reports error (poll)')
770 # we don't care if it is select.POLLIN or timeout, that's
771 # handled below
Chris Liechtia5726382017-08-24 23:43:23 +0200772 if fd == self.pipe_abort_read_r:
773 os.read(self.pipe_abort_read_r, 1000)
774 break
cliechtia9a093e2010-01-02 03:05:08 +0000775 buf = os.read(self.fd, size - len(read))
776 read.extend(buf)
Chris Liechtia5726382017-08-24 23:43:23 +0200777 if timeout.expired() \
778 or (self._inter_byte_timeout is not None and self._inter_byte_timeout > 0) and not buf:
cliechtia9a093e2010-01-02 03:05:08 +0000779 break # early abort on timeout
780 return bytes(read)
781
cliechtif81362e2009-07-25 03:44:33 +0000782
Chris Liechti4cf54702015-10-18 00:21:56 +0200783class VTIMESerial(Serial):
784 """\
785 Implement timeout using vtime of tty device instead of using select.
786 This means that no inter character timeout can be specified and that
787 the error handling is degraded.
788
789 Overall timeout is disabled when inter-character timeout is used.
790 """
791
Chris Liechti94284702015-11-15 01:21:48 +0100792 def _reconfigure_port(self, force_update=True):
Chris Liechti4cf54702015-10-18 00:21:56 +0200793 """Set communication parameters on opened port."""
794 super(VTIMESerial, self)._reconfigure_port()
Chris Liechtid6bcaaf2016-02-01 22:55:26 +0100795 fcntl.fcntl(self.fd, fcntl.F_SETFL, 0) # clear O_NONBLOCK
Chris Liechti4cf54702015-10-18 00:21:56 +0200796
797 if self._inter_byte_timeout is not None:
798 vmin = 1
799 vtime = int(self._inter_byte_timeout * 10)
Chris Liechti3ec9c412016-08-08 01:06:46 +0200800 elif self._timeout is None:
801 vmin = 1
802 vtime = 0
Chris Liechti4cf54702015-10-18 00:21:56 +0200803 else:
804 vmin = 0
805 vtime = int(self._timeout * 10)
806 try:
807 orig_attr = termios.tcgetattr(self.fd)
808 iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
809 except termios.error as msg: # if a port is nonexistent but has a /dev file, it'll fail here
Chris Liechti984c5c52016-02-15 23:48:45 +0100810 raise serial.SerialException("Could not configure port: {}".format(msg))
Chris Liechti4cf54702015-10-18 00:21:56 +0200811
812 if vtime < 0 or vtime > 255:
Chris Liechti984c5c52016-02-15 23:48:45 +0100813 raise ValueError('Invalid vtime: {!r}'.format(vtime))
Chris Liechti4cf54702015-10-18 00:21:56 +0200814 cc[termios.VTIME] = vtime
815 cc[termios.VMIN] = vmin
816
817 termios.tcsetattr(
818 self.fd,
819 termios.TCSANOW,
820 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
821
Chris Liechti4cf54702015-10-18 00:21:56 +0200822 def read(self, size=1):
823 """\
824 Read size bytes from the serial port. If a timeout is set it may
825 return less characters as requested. With no timeout it will block
826 until the requested number of bytes is read.
827 """
828 if not self.is_open:
829 raise portNotOpenError
830 read = bytearray()
831 while len(read) < size:
832 buf = os.read(self.fd, size - len(read))
833 if not buf:
834 break
835 read.extend(buf)
836 return bytes(read)
Chris Liechti3ec9c412016-08-08 01:06:46 +0200837
838 # hack to make hasattr return false
839 cancel_read = property()