blob: 2f125c3ee70d9ebd9170d345f7a4a8e6bbb0804f [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
Kurt McKee057387c2018-02-07 22:10:38 -060029from __future__ import absolute_import
30
Chris Liechti9eaa40c2016-02-12 23:32:59 +010031# pylint: disable=abstract-method
Chris Liechti33f0ec52015-08-06 16:37:21 +020032import errno
33import fcntl
Chris Liechti33f0ec52015-08-06 16:37:21 +020034import os
35import select
36import struct
37import sys
38import termios
Chris Liechti033f17c2015-08-30 21:28:04 +020039
40import serial
Chris Liechti935a2622016-08-30 23:39:15 +020041from serial.serialutil import SerialBase, SerialException, to_bytes, \
Chris Liechtie99bda32020-09-14 03:59:52 +020042 PortNotOpenError, SerialTimeoutException, Timeout
cliechti89b4af12002-02-12 23:24:41 +000043
cliechti89b4af12002-02-12 23:24:41 +000044
Chris Liechtid6847af2015-08-06 17:54:30 +020045class PlatformSpecificBase(object):
46 BAUDRATE_CONSTANTS = {}
cliechti89b4af12002-02-12 23:24:41 +000047
Chris Liechtid6847af2015-08-06 17:54:30 +020048 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
Jan Kantert1b2658a2018-05-07 21:17:37 +020054 def set_low_latency_mode(self, low_latency_settings):
55 raise NotImplementedError('Low latency not supported on this platform')
Kaelan Mikowiczd82d0e12018-07-16 11:15:30 -070056
57 def _update_break_state(self):
58 """\
59 Set break: Controls TXD. When active, no transmitting is possible.
60 """
61 if self._break_state:
62 fcntl.ioctl(self.fd, TIOCSBRK)
63 else:
64 fcntl.ioctl(self.fd, TIOCCBRK)
Kaelan Mikowicz98c6a832018-07-13 16:57:19 -070065
Chris Liechti6dc58e82016-08-29 23:02:13 +020066
67# some systems support an extra flag to enable the two in POSIX unsupported
Chris Liechti11538242016-09-06 22:20:09 +020068# paritiy settings for MARK and SPACE
Chris Liechti6dc58e82016-08-29 23:02:13 +020069CMSPAR = 0 # default, for unsupported platforms, override below
70
Chris Liechtid6847af2015-08-06 17:54:30 +020071# try to detect the OS so that a device can be selected...
72# this code block should supply a device() and set_special_baudrate() function
73# for the platform
74plat = sys.platform.lower()
75
Chris Liechtiba45c522016-02-06 23:53:23 +010076if plat[:5] == 'linux': # Linux (confirmed) # noqa
Chris Liechtid6847af2015-08-06 17:54:30 +020077 import array
78
Chris Liechti6dc58e82016-08-29 23:02:13 +020079 # extra termios flags
80 CMSPAR = 0o10000000000 # Use "stick" (mark/space) parity
81
Chris Liechtid6847af2015-08-06 17:54:30 +020082 # baudrate ioctls
83 TCGETS2 = 0x802C542A
84 TCSETS2 = 0x402C542B
85 BOTHER = 0o010000
86
87 # RS485 ioctls
88 TIOCGRS485 = 0x542E
89 TIOCSRS485 = 0x542F
Chris Liechti033f17c2015-08-30 21:28:04 +020090 SER_RS485_ENABLED = 0b00000001
91 SER_RS485_RTS_ON_SEND = 0b00000010
Chris Liechtid6847af2015-08-06 17:54:30 +020092 SER_RS485_RTS_AFTER_SEND = 0b00000100
Chris Liechti033f17c2015-08-30 21:28:04 +020093 SER_RS485_RX_DURING_TX = 0b00010000
Chris Liechtid6847af2015-08-06 17:54:30 +020094
95 class PlatformSpecific(PlatformSpecificBase):
96 BAUDRATE_CONSTANTS = {
97 0: 0o000000, # hang up
98 50: 0o000001,
99 75: 0o000002,
100 110: 0o000003,
101 134: 0o000004,
102 150: 0o000005,
103 200: 0o000006,
104 300: 0o000007,
105 600: 0o000010,
106 1200: 0o000011,
107 1800: 0o000012,
108 2400: 0o000013,
109 4800: 0o000014,
110 9600: 0o000015,
111 19200: 0o000016,
112 38400: 0o000017,
113 57600: 0o010001,
114 115200: 0o010002,
115 230400: 0o010003,
116 460800: 0o010004,
117 500000: 0o010005,
118 576000: 0o010006,
119 921600: 0o010007,
120 1000000: 0o010010,
121 1152000: 0o010011,
122 1500000: 0o010012,
123 2000000: 0o010013,
124 2500000: 0o010014,
125 3000000: 0o010015,
126 3500000: 0o010016,
127 4000000: 0o010017
128 }
129
Jan Kantert1b2658a2018-05-07 21:17:37 +0200130 def set_low_latency_mode(self, low_latency_settings):
131 buf = array.array('i', [0] * 32)
132
133 try:
134 # get serial_struct
135 fcntl.ioctl(self.fd, termios.TIOCGSERIAL, buf)
136
137 # set or unset ASYNC_LOW_LATENCY flag
138 if low_latency_settings:
139 buf[4] |= 0x2000
140 else:
141 buf[4] &= ~0x2000
142
143 # set serial_struct
144 fcntl.ioctl(self.fd, termios.TIOCSSERIAL, buf)
145 except IOError as e:
146 raise ValueError('Failed to update ASYNC_LOW_LATENCY flag to {}: {}'.format(low_latency_settings, e))
147
Chris Liechtid6847af2015-08-06 17:54:30 +0200148 def _set_special_baudrate(self, baudrate):
149 # right size is 44 on x86_64, allow for some growth
150 buf = array.array('i', [0] * 64)
151 try:
152 # get serial_struct
153 fcntl.ioctl(self.fd, TCGETS2, buf)
154 # set custom speed
155 buf[2] &= ~termios.CBAUD
156 buf[2] |= BOTHER
157 buf[9] = buf[10] = baudrate
158
159 # set serial_struct
Chris Liechti033f17c2015-08-30 21:28:04 +0200160 fcntl.ioctl(self.fd, TCSETS2, buf)
Chris Liechtid6847af2015-08-06 17:54:30 +0200161 except IOError as e:
Chris Liechti984c5c52016-02-15 23:48:45 +0100162 raise ValueError('Failed to set custom baud rate ({}): {}'.format(baudrate, e))
Chris Liechtid6847af2015-08-06 17:54:30 +0200163
164 def _set_rs485_mode(self, rs485_settings):
Chris Liechti033f17c2015-08-30 21:28:04 +0200165 buf = array.array('i', [0] * 8) # flags, delaytx, delayrx, padding
Chris Liechtid6847af2015-08-06 17:54:30 +0200166 try:
167 fcntl.ioctl(self.fd, TIOCGRS485, buf)
Chris Liechti7a554462016-03-24 21:17:22 +0100168 buf[0] |= SER_RS485_ENABLED
Chris Liechtid6847af2015-08-06 17:54:30 +0200169 if rs485_settings is not None:
170 if rs485_settings.loopback:
171 buf[0] |= SER_RS485_RX_DURING_TX
172 else:
173 buf[0] &= ~SER_RS485_RX_DURING_TX
174 if rs485_settings.rts_level_for_tx:
175 buf[0] |= SER_RS485_RTS_ON_SEND
176 else:
177 buf[0] &= ~SER_RS485_RTS_ON_SEND
178 if rs485_settings.rts_level_for_rx:
179 buf[0] |= SER_RS485_RTS_AFTER_SEND
180 else:
181 buf[0] &= ~SER_RS485_RTS_AFTER_SEND
Chris Liechti279201b2016-06-09 20:27:05 +0200182 if rs485_settings.delay_before_tx is not None:
183 buf[1] = int(rs485_settings.delay_before_tx * 1000)
184 if rs485_settings.delay_before_rx is not None:
185 buf[2] = int(rs485_settings.delay_before_rx * 1000)
Chris Liechtid6847af2015-08-06 17:54:30 +0200186 else:
187 buf[0] = 0 # clear SER_RS485_ENABLED
Chris Liechti033f17c2015-08-30 21:28:04 +0200188 fcntl.ioctl(self.fd, TIOCSRS485, buf)
Chris Liechtid6847af2015-08-06 17:54:30 +0200189 except IOError as e:
Chris Liechti984c5c52016-02-15 23:48:45 +0100190 raise ValueError('Failed to set RS485 mode: {}'.format(e))
Chris Liechtid6847af2015-08-06 17:54:30 +0200191
192
193elif plat == 'cygwin': # cygwin/win32 (confirmed)
194
195 class PlatformSpecific(PlatformSpecificBase):
196 BAUDRATE_CONSTANTS = {
197 128000: 0x01003,
198 256000: 0x01005,
199 500000: 0x01007,
200 576000: 0x01008,
201 921600: 0x01009,
202 1000000: 0x0100a,
203 1152000: 0x0100b,
204 1500000: 0x0100c,
205 2000000: 0x0100d,
206 2500000: 0x0100e,
207 3000000: 0x0100f
208 }
209
Chris Liechtid6847af2015-08-06 17:54:30 +0200210
211elif plat[:6] == 'darwin': # OS X
212 import array
Chris Liechti033f17c2015-08-30 21:28:04 +0200213 IOSSIOSPEED = 0x80045402 # _IOW('T', 2, speed_t)
Chris Liechtid6847af2015-08-06 17:54:30 +0200214
215 class PlatformSpecific(PlatformSpecificBase):
Chris Liechtid6847af2015-08-06 17:54:30 +0200216 osx_version = os.uname()[2].split('.')
Kaelan Mikowiczfca918d2018-07-14 23:21:33 -0700217 TIOCSBRK = 0x2000747B # _IO('t', 123)
218 TIOCCBRK = 0x2000747A # _IO('t', 122)
219
Chris Liechtid6847af2015-08-06 17:54:30 +0200220 # Tiger or above can support arbitrary serial speeds
221 if int(osx_version[0]) >= 8:
222 def _set_special_baudrate(self, baudrate):
223 # use IOKit-specific call to set up high speeds
224 buf = array.array('i', [baudrate])
225 fcntl.ioctl(self.fd, IOSSIOSPEED, buf, 1)
226
Kaelan Mikowicz98c6a832018-07-13 16:57:19 -0700227 def _update_break_state(self):
228 """\
229 Set break: Controls TXD. When active, no transmitting is possible.
230 """
231 if self._break_state:
Kaelan Mikowiczfca918d2018-07-14 23:21:33 -0700232 fcntl.ioctl(self.fd, PlatformSpecific.TIOCSBRK)
Kaelan Mikowicz98c6a832018-07-13 16:57:19 -0700233 else:
Kaelan Mikowiczfca918d2018-07-14 23:21:33 -0700234 fcntl.ioctl(self.fd, PlatformSpecific.TIOCCBRK)
Kaelan Mikowicz98c6a832018-07-13 16:57:19 -0700235
Chris Liechti21a306b2016-10-09 23:41:26 +0200236elif plat[:3] == 'bsd' or \
237 plat[:7] == 'freebsd' or \
238 plat[:6] == 'netbsd' or \
239 plat[:7] == 'openbsd':
240
241 class ReturnBaudrate(object):
242 def __getitem__(self, key):
243 return key
244
245 class PlatformSpecific(PlatformSpecificBase):
246 # Only tested on FreeBSD:
247 # The baud rate may be passed in as
248 # a literal value.
249 BAUDRATE_CONSTANTS = ReturnBaudrate()
250
Kaelan Mikowiczfca918d2018-07-14 23:21:33 -0700251 TIOCSBRK = 0x2000747B # _IO('t', 123)
252 TIOCCBRK = 0x2000747A # _IO('t', 122)
253
254
255 def _update_break_state(self):
256 """\
257 Set break: Controls TXD. When active, no transmitting is possible.
258 """
259 if self._break_state:
260 fcntl.ioctl(self.fd, PlatformSpecific.TIOCSBRK)
261 else:
262 fcntl.ioctl(self.fd, PlatformSpecific.TIOCCBRK)
263
Chris Liechtid6847af2015-08-06 17:54:30 +0200264else:
265 class PlatformSpecific(PlatformSpecificBase):
266 pass
cliechti89b4af12002-02-12 23:24:41 +0000267
cliechti89b4af12002-02-12 23:24:41 +0000268
cliechti58b481c2009-02-16 20:42:32 +0000269# load some constants for later use.
Chris Liechti11465c82015-08-04 15:55:22 +0200270# try to use values from termios, use defaults from linux otherwise
Chris Liechti033f17c2015-08-30 21:28:04 +0200271TIOCMGET = getattr(termios, 'TIOCMGET', 0x5415)
272TIOCMBIS = getattr(termios, 'TIOCMBIS', 0x5416)
273TIOCMBIC = getattr(termios, 'TIOCMBIC', 0x5417)
274TIOCMSET = getattr(termios, 'TIOCMSET', 0x5418)
cliechti89b4af12002-02-12 23:24:41 +0000275
Chris Liechti033f17c2015-08-30 21:28:04 +0200276# TIOCM_LE = getattr(termios, 'TIOCM_LE', 0x001)
Chris Liechtid6847af2015-08-06 17:54:30 +0200277TIOCM_DTR = getattr(termios, 'TIOCM_DTR', 0x002)
278TIOCM_RTS = getattr(termios, 'TIOCM_RTS', 0x004)
Chris Liechti033f17c2015-08-30 21:28:04 +0200279# TIOCM_ST = getattr(termios, 'TIOCM_ST', 0x008)
280# TIOCM_SR = getattr(termios, 'TIOCM_SR', 0x010)
cliechti89b4af12002-02-12 23:24:41 +0000281
Chris Liechtid6847af2015-08-06 17:54:30 +0200282TIOCM_CTS = getattr(termios, 'TIOCM_CTS', 0x020)
283TIOCM_CAR = getattr(termios, 'TIOCM_CAR', 0x040)
284TIOCM_RNG = getattr(termios, 'TIOCM_RNG', 0x080)
285TIOCM_DSR = getattr(termios, 'TIOCM_DSR', 0x100)
Chris Liechti033f17c2015-08-30 21:28:04 +0200286TIOCM_CD = getattr(termios, 'TIOCM_CD', TIOCM_CAR)
287TIOCM_RI = getattr(termios, 'TIOCM_RI', TIOCM_RNG)
288# TIOCM_OUT1 = getattr(termios, 'TIOCM_OUT1', 0x2000)
289# TIOCM_OUT2 = getattr(termios, 'TIOCM_OUT2', 0x4000)
Chris Liechti11465c82015-08-04 15:55:22 +0200290if hasattr(termios, 'TIOCINQ'):
291 TIOCINQ = termios.TIOCINQ
cliechti28b8fd02011-12-28 21:39:42 +0000292else:
Chris Liechtid6847af2015-08-06 17:54:30 +0200293 TIOCINQ = getattr(termios, 'FIONREAD', 0x541B)
Chris Liechti033f17c2015-08-30 21:28:04 +0200294TIOCOUTQ = getattr(termios, 'TIOCOUTQ', 0x5411)
cliechti89b4af12002-02-12 23:24:41 +0000295
296TIOCM_zero_str = struct.pack('I', 0)
297TIOCM_RTS_str = struct.pack('I', TIOCM_RTS)
298TIOCM_DTR_str = struct.pack('I', TIOCM_DTR)
299
Chris Liechti033f17c2015-08-30 21:28:04 +0200300TIOCSBRK = getattr(termios, 'TIOCSBRK', 0x5427)
301TIOCCBRK = getattr(termios, 'TIOCCBRK', 0x5428)
cliechti997b63c2008-06-21 00:09:31 +0000302
cliechti89b4af12002-02-12 23:24:41 +0000303
Chris Liechtief6b7b42015-08-06 22:19:26 +0200304class Serial(SerialBase, PlatformSpecific):
cliechti7d448562014-08-03 21:57:45 +0000305 """\
Chris Liechti033f17c2015-08-30 21:28:04 +0200306 Serial port class POSIX implementation. Serial port configuration is
cliechtid6bf52c2003-10-01 02:28:12 +0000307 done with termios and fcntl. Runs on Linux and many other Un*x like
cliechtif0a81d42014-08-04 14:03:53 +0000308 systems.
309 """
cliechtid6bf52c2003-10-01 02:28:12 +0000310
311 def open(self):
cliechti7d448562014-08-03 21:57:45 +0000312 """\
313 Open port with current settings. This may throw a SerialException
314 if the port cannot be opened."""
cliechtid6bf52c2003-10-01 02:28:12 +0000315 if self._port is None:
316 raise SerialException("Port must be configured before it can be used.")
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200317 if self.is_open:
cliechti02ef43a2011-03-24 23:33:12 +0000318 raise SerialException("Port is already open.")
319 self.fd = None
cliechti58b481c2009-02-16 20:42:32 +0000320 # open
cliechti4616bf12002-04-08 23:13:14 +0000321 try:
Chris Liechti033f17c2015-08-30 21:28:04 +0200322 self.fd = os.open(self.portstr, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK)
Chris Liechti68340d72015-08-03 14:15:48 +0200323 except OSError as msg:
cliechti4616bf12002-04-08 23:13:14 +0000324 self.fd = None
Chris Liechti984c5c52016-02-15 23:48:45 +0100325 raise SerialException(msg.errno, "could not open port {}: {}".format(self._port, msg))
Chris Liechti11465c82015-08-04 15:55:22 +0200326 #~ fcntl.fcntl(self.fd, fcntl.F_SETFL, 0) # set blocking
cliechti58b481c2009-02-16 20:42:32 +0000327
cliechtib2f5fc82006-10-20 00:09:07 +0000328 try:
Chris Liechti94284702015-11-15 01:21:48 +0100329 self._reconfigure_port(force_update=True)
cliechtib2f5fc82006-10-20 00:09:07 +0000330 except:
cliechti2750b832009-07-28 00:13:52 +0000331 try:
332 os.close(self.fd)
333 except:
334 # ignore any exception when closing the port
335 # also to keep original exception that happened when setting up
336 pass
cliechtib2f5fc82006-10-20 00:09:07 +0000337 self.fd = None
cliechtif0a4f0f2009-07-21 21:12:37 +0000338 raise
cliechtib2f5fc82006-10-20 00:09:07 +0000339 else:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200340 self.is_open = True
Chris Liechtif2fdeb92016-05-07 23:57:50 +0200341 try:
342 if not self._dsrdtr:
343 self._update_dtr_state()
344 if not self._rtscts:
345 self._update_rts_state()
346 except IOError as e:
Chris Liechtie1029622016-10-02 23:54:36 +0200347 if e.errno in (errno.EINVAL, errno.ENOTTY):
348 # ignore Invalid argument and Inappropriate ioctl
Chris Liechtif2fdeb92016-05-07 23:57:50 +0200349 pass
350 else:
351 raise
Chris Liechtief1fe252015-08-27 23:25:21 +0200352 self.reset_input_buffer()
Chris Liechti42ab2b42016-05-15 23:35:05 +0200353 self.pipe_abort_read_r, self.pipe_abort_read_w = os.pipe()
Chris Liechti13949c62016-05-16 22:45:38 +0200354 self.pipe_abort_write_r, self.pipe_abort_write_w = os.pipe()
Chris Liechti68cecce2016-06-03 23:52:34 +0200355 fcntl.fcntl(self.pipe_abort_read_r, fcntl.F_SETFL, os.O_NONBLOCK)
356 fcntl.fcntl(self.pipe_abort_write_r, fcntl.F_SETFL, os.O_NONBLOCK)
cliechti58b481c2009-02-16 20:42:32 +0000357
Chris Liechti94284702015-11-15 01:21:48 +0100358 def _reconfigure_port(self, force_update=False):
cliechtib2f5fc82006-10-20 00:09:07 +0000359 """Set communication parameters on opened port."""
cliechtic6178262004-03-22 22:04:52 +0000360 if self.fd is None:
cliechtia9a093e2010-01-02 03:05:08 +0000361 raise SerialException("Can only operate on a valid file descriptor")
Chris Liechti1c4bc812017-03-08 02:44:04 +0100362
Rob Gaddi636cc642017-02-24 11:39:46 -0800363 # if exclusive lock is requested, create it before we modify anything else
364 if self._exclusive is not None:
365 if self._exclusive:
366 try:
367 fcntl.flock(self.fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
368 except IOError as msg:
369 raise SerialException(msg.errno, "Could not exclusively lock port {}: {}".format(self._port, msg))
370 else:
371 fcntl.flock(self.fd, fcntl.LOCK_UN)
Chris Liechti1c4bc812017-03-08 02:44:04 +0100372
cliechtie8c45422008-06-20 23:23:14 +0000373 custom_baud = None
cliechti58b481c2009-02-16 20:42:32 +0000374
cliechti2750b832009-07-28 00:13:52 +0000375 vmin = vtime = 0 # timeout is done via select
Chris Liechti518b0d32015-08-30 02:20:39 +0200376 if self._inter_byte_timeout is not None:
cliechti679bfa62008-06-20 23:58:15 +0000377 vmin = 1
Chris Liechti518b0d32015-08-30 02:20:39 +0200378 vtime = int(self._inter_byte_timeout * 10)
cliechti6ce7ab12002-11-07 02:15:00 +0000379 try:
cliechti4d0af5e2011-08-05 02:18:16 +0000380 orig_attr = termios.tcgetattr(self.fd)
381 iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
Chris Liechti68340d72015-08-03 14:15:48 +0200382 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 +0100383 raise SerialException("Could not configure port: {}".format(msg))
cliechti58b481c2009-02-16 20:42:32 +0000384 # set up raw mode / no echo / binary
Chris Liechti033f17c2015-08-30 21:28:04 +0200385 cflag |= (termios.CLOCAL | termios.CREAD)
386 lflag &= ~(termios.ICANON | termios.ECHO | termios.ECHOE |
387 termios.ECHOK | termios.ECHONL |
388 termios.ISIG | termios.IEXTEN) # |termios.ECHOPRT
389 for flag in ('ECHOCTL', 'ECHOKE'): # netbsd workaround for Erk
Chris Liechti11465c82015-08-04 15:55:22 +0200390 if hasattr(termios, flag):
391 lflag &= ~getattr(termios, flag)
cliechti58b481c2009-02-16 20:42:32 +0000392
Chris Liechti033f17c2015-08-30 21:28:04 +0200393 oflag &= ~(termios.OPOST | termios.ONLCR | termios.OCRNL)
394 iflag &= ~(termios.INLCR | termios.IGNCR | termios.ICRNL | termios.IGNBRK)
Chris Liechti11465c82015-08-04 15:55:22 +0200395 if hasattr(termios, 'IUCLC'):
396 iflag &= ~termios.IUCLC
397 if hasattr(termios, 'PARMRK'):
398 iflag &= ~termios.PARMRK
cliechti58b481c2009-02-16 20:42:32 +0000399
cliechtif0a4f0f2009-07-21 21:12:37 +0000400 # setup baud rate
cliechti89b4af12002-02-12 23:24:41 +0000401 try:
Chris Liechti984c5c52016-02-15 23:48:45 +0100402 ispeed = ospeed = getattr(termios, 'B{}'.format(self._baudrate))
cliechti895e8302004-04-20 02:40:28 +0000403 except AttributeError:
cliechtif1559d02007-11-08 23:43:58 +0000404 try:
Chris Liechtid6847af2015-08-06 17:54:30 +0200405 ispeed = ospeed = self.BAUDRATE_CONSTANTS[self._baudrate]
cliechtif1559d02007-11-08 23:43:58 +0000406 except KeyError:
cliechtie8c45422008-06-20 23:23:14 +0000407 #~ raise ValueError('Invalid baud rate: %r' % self._baudrate)
Tim Nordell0085e1e2020-08-21 15:20:44 -0500408
409 # See if BOTHER is defined for this platform; if it is, use
410 # this for a speed not defined in the baudrate constants list.
411 try:
412 ispeed = ospeed = BOTHER
413 except NameError:
414 # may need custom baud rate, it isn't in our list.
415 ispeed = ospeed = getattr(termios, 'B38400')
416
cliechtif0a4f0f2009-07-21 21:12:37 +0000417 try:
Chris Liechti033f17c2015-08-30 21:28:04 +0200418 custom_baud = int(self._baudrate) # store for later
cliechtif0a4f0f2009-07-21 21:12:37 +0000419 except ValueError:
Chris Liechti984c5c52016-02-15 23:48:45 +0100420 raise ValueError('Invalid baud rate: {!r}'.format(self._baudrate))
cliechtif0a4f0f2009-07-21 21:12:37 +0000421 else:
422 if custom_baud < 0:
Chris Liechti984c5c52016-02-15 23:48:45 +0100423 raise ValueError('Invalid baud rate: {!r}'.format(self._baudrate))
cliechti58b481c2009-02-16 20:42:32 +0000424
425 # setup char len
Chris Liechti11465c82015-08-04 15:55:22 +0200426 cflag &= ~termios.CSIZE
cliechtid6bf52c2003-10-01 02:28:12 +0000427 if self._bytesize == 8:
Chris Liechti11465c82015-08-04 15:55:22 +0200428 cflag |= termios.CS8
cliechtid6bf52c2003-10-01 02:28:12 +0000429 elif self._bytesize == 7:
Chris Liechti11465c82015-08-04 15:55:22 +0200430 cflag |= termios.CS7
cliechtid6bf52c2003-10-01 02:28:12 +0000431 elif self._bytesize == 6:
Chris Liechti11465c82015-08-04 15:55:22 +0200432 cflag |= termios.CS6
cliechtid6bf52c2003-10-01 02:28:12 +0000433 elif self._bytesize == 5:
Chris Liechti11465c82015-08-04 15:55:22 +0200434 cflag |= termios.CS5
cliechti89b4af12002-02-12 23:24:41 +0000435 else:
Chris Liechti984c5c52016-02-15 23:48:45 +0100436 raise ValueError('Invalid char len: {!r}'.format(self._bytesize))
cliechtif0a81d42014-08-04 14:03:53 +0000437 # setup stop bits
Chris Liechti033f17c2015-08-30 21:28:04 +0200438 if self._stopbits == serial.STOPBITS_ONE:
Chris Liechti11465c82015-08-04 15:55:22 +0200439 cflag &= ~(termios.CSTOPB)
Chris Liechti033f17c2015-08-30 21:28:04 +0200440 elif self._stopbits == serial.STOPBITS_ONE_POINT_FIVE:
441 cflag |= (termios.CSTOPB) # XXX same as TWO.. there is no POSIX support for 1.5
442 elif self._stopbits == serial.STOPBITS_TWO:
443 cflag |= (termios.CSTOPB)
cliechti89b4af12002-02-12 23:24:41 +0000444 else:
Chris Liechti984c5c52016-02-15 23:48:45 +0100445 raise ValueError('Invalid stop bit specification: {!r}'.format(self._stopbits))
cliechti58b481c2009-02-16 20:42:32 +0000446 # setup parity
Chris Liechti033f17c2015-08-30 21:28:04 +0200447 iflag &= ~(termios.INPCK | termios.ISTRIP)
448 if self._parity == serial.PARITY_NONE:
Chris Liechti6dc58e82016-08-29 23:02:13 +0200449 cflag &= ~(termios.PARENB | termios.PARODD | CMSPAR)
Chris Liechti033f17c2015-08-30 21:28:04 +0200450 elif self._parity == serial.PARITY_EVEN:
Chris Liechti6dc58e82016-08-29 23:02:13 +0200451 cflag &= ~(termios.PARODD | CMSPAR)
Chris Liechti033f17c2015-08-30 21:28:04 +0200452 cflag |= (termios.PARENB)
453 elif self._parity == serial.PARITY_ODD:
Chris Liechti6dc58e82016-08-29 23:02:13 +0200454 cflag &= ~CMSPAR
Chris Liechti033f17c2015-08-30 21:28:04 +0200455 cflag |= (termios.PARENB | termios.PARODD)
Chris Liechti6dc58e82016-08-29 23:02:13 +0200456 elif self._parity == serial.PARITY_MARK and CMSPAR:
Chris Liechti033f17c2015-08-30 21:28:04 +0200457 cflag |= (termios.PARENB | CMSPAR | termios.PARODD)
Chris Liechti6dc58e82016-08-29 23:02:13 +0200458 elif self._parity == serial.PARITY_SPACE and CMSPAR:
Chris Liechti033f17c2015-08-30 21:28:04 +0200459 cflag |= (termios.PARENB | CMSPAR)
Chris Liechti11465c82015-08-04 15:55:22 +0200460 cflag &= ~(termios.PARODD)
cliechti89b4af12002-02-12 23:24:41 +0000461 else:
Chris Liechti984c5c52016-02-15 23:48:45 +0100462 raise ValueError('Invalid parity: {!r}'.format(self._parity))
cliechti58b481c2009-02-16 20:42:32 +0000463 # setup flow control
464 # xonxoff
Chris Liechti11465c82015-08-04 15:55:22 +0200465 if hasattr(termios, 'IXANY'):
cliechtid6bf52c2003-10-01 02:28:12 +0000466 if self._xonxoff:
Chris Liechti033f17c2015-08-30 21:28:04 +0200467 iflag |= (termios.IXON | termios.IXOFF) # |termios.IXANY)
cliechti89b4af12002-02-12 23:24:41 +0000468 else:
Chris Liechti033f17c2015-08-30 21:28:04 +0200469 iflag &= ~(termios.IXON | termios.IXOFF | termios.IXANY)
cliechti89b4af12002-02-12 23:24:41 +0000470 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000471 if self._xonxoff:
Chris Liechti033f17c2015-08-30 21:28:04 +0200472 iflag |= (termios.IXON | termios.IXOFF)
cliechti89b4af12002-02-12 23:24:41 +0000473 else:
Chris Liechti033f17c2015-08-30 21:28:04 +0200474 iflag &= ~(termios.IXON | termios.IXOFF)
cliechti58b481c2009-02-16 20:42:32 +0000475 # rtscts
Chris Liechti11465c82015-08-04 15:55:22 +0200476 if hasattr(termios, 'CRTSCTS'):
cliechtid6bf52c2003-10-01 02:28:12 +0000477 if self._rtscts:
Chris Liechti033f17c2015-08-30 21:28:04 +0200478 cflag |= (termios.CRTSCTS)
cliechti89b4af12002-02-12 23:24:41 +0000479 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200480 cflag &= ~(termios.CRTSCTS)
481 elif hasattr(termios, 'CNEW_RTSCTS'): # try it with alternate constant name
cliechtid6bf52c2003-10-01 02:28:12 +0000482 if self._rtscts:
Chris Liechti033f17c2015-08-30 21:28:04 +0200483 cflag |= (termios.CNEW_RTSCTS)
cliechtid4743692002-04-08 22:39:53 +0000484 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200485 cflag &= ~(termios.CNEW_RTSCTS)
cliechti2750b832009-07-28 00:13:52 +0000486 # XXX should there be a warning if setting up rtscts (and xonxoff etc) fails??
cliechti58b481c2009-02-16 20:42:32 +0000487
488 # buffer
cliechtif0a81d42014-08-04 14:03:53 +0000489 # vmin "minimal number of characters to be read. 0 for non blocking"
cliechtid6bf52c2003-10-01 02:28:12 +0000490 if vmin < 0 or vmin > 255:
Chris Liechti984c5c52016-02-15 23:48:45 +0100491 raise ValueError('Invalid vmin: {!r}'.format(vmin))
Chris Liechti11465c82015-08-04 15:55:22 +0200492 cc[termios.VMIN] = vmin
cliechti58b481c2009-02-16 20:42:32 +0000493 # vtime
cliechtid6bf52c2003-10-01 02:28:12 +0000494 if vtime < 0 or vtime > 255:
Chris Liechti984c5c52016-02-15 23:48:45 +0100495 raise ValueError('Invalid vtime: {!r}'.format(vtime))
Chris Liechti11465c82015-08-04 15:55:22 +0200496 cc[termios.VTIME] = vtime
cliechti58b481c2009-02-16 20:42:32 +0000497 # activate settings
Chris Liechti94284702015-11-15 01:21:48 +0100498 if force_update or [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] != orig_attr:
Chris Liechti033f17c2015-08-30 21:28:04 +0200499 termios.tcsetattr(
Chris Liechti9eaa40c2016-02-12 23:32:59 +0100500 self.fd,
501 termios.TCSANOW,
502 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
cliechti58b481c2009-02-16 20:42:32 +0000503
cliechtie8c45422008-06-20 23:23:14 +0000504 # apply custom baud rate, if any
505 if custom_baud is not None:
Chris Liechtid6847af2015-08-06 17:54:30 +0200506 self._set_special_baudrate(custom_baud)
507
508 if self._rs485_mode is not None:
509 self._set_rs485_mode(self._rs485_mode)
cliechti89b4af12002-02-12 23:24:41 +0000510
511 def close(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000512 """Close port"""
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200513 if self.is_open:
cliechtic6178262004-03-22 22:04:52 +0000514 if self.fd is not None:
cliechtid6bf52c2003-10-01 02:28:12 +0000515 os.close(self.fd)
516 self.fd = None
Chris Liechtib658eac2016-05-22 20:51:44 +0200517 os.close(self.pipe_abort_read_w)
518 os.close(self.pipe_abort_read_r)
519 os.close(self.pipe_abort_write_w)
520 os.close(self.pipe_abort_write_r)
521 self.pipe_abort_read_r, self.pipe_abort_read_w = None, None
522 self.pipe_abort_write_r, self.pipe_abort_write_w = None, None
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200523 self.is_open = False
cliechtid6bf52c2003-10-01 02:28:12 +0000524
525 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechti95c62212002-03-04 22:17:53 +0000526
Chris Liechtief1fe252015-08-27 23:25:21 +0200527 @property
528 def in_waiting(self):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200529 """Return the number of bytes currently in the input buffer."""
Chris Liechti11465c82015-08-04 15:55:22 +0200530 #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str)
cliechtif5831e02002-12-05 23:15:27 +0000531 s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200532 return struct.unpack('I', s)[0]
cliechti89b4af12002-02-12 23:24:41 +0000533
cliechtia9a093e2010-01-02 03:05:08 +0000534 # select based implementation, proved to work on many systems
535 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000536 """\
537 Read size bytes from the serial port. If a timeout is set it may
538 return less characters as requested. With no timeout it will block
539 until the requested number of bytes is read.
540 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200541 if not self.is_open:
Chris Liechtie99bda32020-09-14 03:59:52 +0200542 raise PortNotOpenError()
cliechtia9a093e2010-01-02 03:05:08 +0000543 read = bytearray()
Chris Liechti935a2622016-08-30 23:39:15 +0200544 timeout = Timeout(self._timeout)
cliechtia9a093e2010-01-02 03:05:08 +0000545 while len(read) < size:
cliechti8d744de2013-10-11 14:31:13 +0000546 try:
Chris Liechti935a2622016-08-30 23:39:15 +0200547 ready, _, _ = select.select([self.fd, self.pipe_abort_read_r], [], [], timeout.time_left())
Chris Liechti42ab2b42016-05-15 23:35:05 +0200548 if self.pipe_abort_read_r in ready:
Chris Liechti68cecce2016-06-03 23:52:34 +0200549 os.read(self.pipe_abort_read_r, 1000)
Chris Liechti42ab2b42016-05-15 23:35:05 +0200550 break
cliechti8d744de2013-10-11 14:31:13 +0000551 # If select was used with a timeout, and the timeout occurs, it
552 # returns with empty lists -> thus abort read operation.
Chris Liechti033f17c2015-08-30 21:28:04 +0200553 # For timeout == 0 (non-blocking operation) also abort when
554 # there is nothing to read.
cliechti8d744de2013-10-11 14:31:13 +0000555 if not ready:
556 break # timeout
Chris Liechti033f17c2015-08-30 21:28:04 +0200557 buf = os.read(self.fd, size - len(read))
Chris Liechti68340d72015-08-03 14:15:48 +0200558 except OSError as e:
Chris Liechti033f17c2015-08-30 21:28:04 +0200559 # this is for Python 3.x where select.error is a subclass of
Chris Liechti17660ee2017-05-04 23:39:05 +0200560 # OSError ignore BlockingIOErrors and EINTR. other errors are shown
561 # https://www.python.org/dev/peps/pep-0475.
562 if e.errno not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
Chris Liechti984c5c52016-02-15 23:48:45 +0100563 raise SerialException('read failed: {}'.format(e))
Chris Liechti68340d72015-08-03 14:15:48 +0200564 except select.error as e:
cliechtic7cd7212014-08-03 21:34:38 +0000565 # this is for Python 2.x
Chris Liechti17660ee2017-05-04 23:39:05 +0200566 # ignore BlockingIOErrors and EINTR. all errors are shown
cliechti8d744de2013-10-11 14:31:13 +0000567 # see also http://www.python.org/dev/peps/pep-3151/#select
Chris Liechti1c8dbee2017-05-05 03:26:51 +0200568 if e[0] not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
Chris Liechti984c5c52016-02-15 23:48:45 +0100569 raise SerialException('read failed: {}'.format(e))
Christian Häggströmb92365a2020-03-30 13:42:15 +0200570 else:
571 # read should always return some data as select reported it was
572 # ready to read when we get to this point.
573 if not buf:
574 # Disconnected devices, at least on Linux, show the
575 # behavior that they are always ready to read immediately
576 # but reading returns nothing.
577 raise SerialException(
578 'device reports readiness to read but returned no data '
579 '(device disconnected or multiple access on port?)')
580 read.extend(buf)
581
Chris Liechti935a2622016-08-30 23:39:15 +0200582 if timeout.expired():
583 break
cliechtia9a093e2010-01-02 03:05:08 +0000584 return bytes(read)
cliechti89b4af12002-02-12 23:24:41 +0000585
Chris Liechti42ab2b42016-05-15 23:35:05 +0200586 def cancel_read(self):
Chris Liechti9c326282017-07-15 01:58:56 +0200587 if self.is_open:
588 os.write(self.pipe_abort_read_w, b"x")
Chris Liechti42ab2b42016-05-15 23:35:05 +0200589
Chris Liechti13949c62016-05-16 22:45:38 +0200590 def cancel_write(self):
Chris Liechti9c326282017-07-15 01:58:56 +0200591 if self.is_open:
592 os.write(self.pipe_abort_write_w, b"x")
Chris Liechti13949c62016-05-16 22:45:38 +0200593
cliechti4a567a02009-07-27 22:09:31 +0000594 def write(self, data):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200595 """Output the given byte string over the serial port."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200596 if not self.is_open:
Chris Liechtie99bda32020-09-14 03:59:52 +0200597 raise PortNotOpenError()
cliechti38077122013-10-16 02:57:27 +0000598 d = to_bytes(data)
Chris Liechtie0063f12016-12-17 23:44:18 +0100599 tx_len = length = len(d)
Chris Liechti935a2622016-08-30 23:39:15 +0200600 timeout = Timeout(self._write_timeout)
cliechti9f7c2352013-10-11 01:13:46 +0000601 while tx_len > 0:
cliechti5d4d0bd2004-11-13 03:27:39 +0000602 try:
cliechti5d4d0bd2004-11-13 03:27:39 +0000603 n = os.write(self.fd, d)
Chris Liechti935a2622016-08-30 23:39:15 +0200604 if timeout.is_non_blocking:
Robert Smallshire325a7382016-03-25 21:18:38 +0100605 # Zero timeout indicates non-blocking - simply return the
606 # number of bytes of data actually written
607 return n
Chris Liechti935a2622016-08-30 23:39:15 +0200608 elif not timeout.is_infinite:
cliechti3cf46d62009-08-07 00:19:57 +0000609 # when timeout is set, use select to wait for being ready
610 # with the time left as timeout
Chris Liechti935a2622016-08-30 23:39:15 +0200611 if timeout.expired():
Chris Liechtie99bda32020-09-14 03:59:52 +0200612 raise SerialTimeoutException('Write timeout')
Chris Liechti935a2622016-08-30 23:39:15 +0200613 abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], timeout.time_left())
Chris Liechti13949c62016-05-16 22:45:38 +0200614 if abort:
Chris Liechti68cecce2016-06-03 23:52:34 +0200615 os.read(self.pipe_abort_write_r, 1000)
Chris Liechti13949c62016-05-16 22:45:38 +0200616 break
cliechti5d4d0bd2004-11-13 03:27:39 +0000617 if not ready:
Chris Liechtie99bda32020-09-14 03:59:52 +0200618 raise SerialTimeoutException('Write timeout')
cliechti88c62442013-10-12 04:03:16 +0000619 else:
Chris Liechti935a2622016-08-30 23:39:15 +0200620 assert timeout.time_left() is None
cliechti88c62442013-10-12 04:03:16 +0000621 # wait for write operation
Chris Liechti13949c62016-05-16 22:45:38 +0200622 abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], None)
623 if abort:
624 os.read(self.pipe_abort_write_r, 1)
625 break
cliechti88c62442013-10-12 04:03:16 +0000626 if not ready:
627 raise SerialException('write failed (select)')
cliechti5d4d0bd2004-11-13 03:27:39 +0000628 d = d[n:]
cliechti9f7c2352013-10-11 01:13:46 +0000629 tx_len -= n
Chris Liechti675f7e12015-08-03 15:48:41 +0200630 except SerialException:
631 raise
Chris Liechti10d79d92017-05-05 00:05:23 +0200632 except OSError as e:
633 # this is for Python 3.x where select.error is a subclass of
634 # OSError ignore BlockingIOErrors and EINTR. other errors are shown
635 # https://www.python.org/dev/peps/pep-0475.
636 if e.errno not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
637 raise SerialException('write failed: {}'.format(e))
638 except select.error as e:
639 # this is for Python 2.x
640 # ignore BlockingIOErrors and EINTR. all errors are shown
641 # see also http://www.python.org/dev/peps/pep-3151/#select
Chris Liechti1c8dbee2017-05-05 03:26:51 +0200642 if e[0] not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
Chris Liechti10d79d92017-05-05 00:05:23 +0200643 raise SerialException('write failed: {}'.format(e))
Chris Liechtifc70fd72017-05-05 02:59:06 +0200644 if not timeout.is_non_blocking and timeout.expired():
Chris Liechtie99bda32020-09-14 03:59:52 +0200645 raise SerialTimeoutException('Write timeout')
Chris Liechtie0063f12016-12-17 23:44:18 +0100646 return length - len(d)
cliechtid6bf52c2003-10-01 02:28:12 +0000647
cliechtia30a8a02003-10-05 12:28:13 +0000648 def flush(self):
cliechti7d448562014-08-03 21:57:45 +0000649 """\
650 Flush of file like objects. In this case, wait until all data
651 is written.
652 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200653 if not self.is_open:
Chris Liechtie99bda32020-09-14 03:59:52 +0200654 raise PortNotOpenError()
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200655 termios.tcdrain(self.fd)
cliechtia30a8a02003-10-05 12:28:13 +0000656
Chris Liechtief1fe252015-08-27 23:25:21 +0200657 def reset_input_buffer(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000658 """Clear input buffer, discarding all that is in the buffer."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200659 if not self.is_open:
Chris Liechtie99bda32020-09-14 03:59:52 +0200660 raise PortNotOpenError()
Chris Liechti11465c82015-08-04 15:55:22 +0200661 termios.tcflush(self.fd, termios.TCIFLUSH)
cliechti89b4af12002-02-12 23:24:41 +0000662
Chris Liechtief1fe252015-08-27 23:25:21 +0200663 def reset_output_buffer(self):
cliechti7d448562014-08-03 21:57:45 +0000664 """\
665 Clear output buffer, aborting the current output and discarding all
666 that is in the buffer.
667 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200668 if not self.is_open:
Chris Liechtie99bda32020-09-14 03:59:52 +0200669 raise PortNotOpenError()
Chris Liechti11465c82015-08-04 15:55:22 +0200670 termios.tcflush(self.fd, termios.TCOFLUSH)
cliechti89b4af12002-02-12 23:24:41 +0000671
Chris Liechtief1fe252015-08-27 23:25:21 +0200672 def send_break(self, duration=0.25):
cliechti7d448562014-08-03 21:57:45 +0000673 """\
674 Send break condition. Timed, returns to idle state after given
675 duration.
676 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200677 if not self.is_open:
Chris Liechtie99bda32020-09-14 03:59:52 +0200678 raise PortNotOpenError()
Chris Liechti033f17c2015-08-30 21:28:04 +0200679 termios.tcsendbreak(self.fd, int(duration / 0.25))
cliechti89b4af12002-02-12 23:24:41 +0000680
Chris Liechtief1fe252015-08-27 23:25:21 +0200681 def _update_rts_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000682 """Set terminal status line: Request To Send"""
Chris Liechtif7534c82016-05-07 23:35:54 +0200683 if self._rts_state:
684 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_RTS_str)
685 else:
686 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_RTS_str)
cliechtid6bf52c2003-10-01 02:28:12 +0000687
Chris Liechtief1fe252015-08-27 23:25:21 +0200688 def _update_dtr_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000689 """Set terminal status line: Data Terminal Ready"""
Chris Liechtif7534c82016-05-07 23:35:54 +0200690 if self._dtr_state:
691 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str)
692 else:
693 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_DTR_str)
cliechtid6bf52c2003-10-01 02:28:12 +0000694
Chris Liechtief1fe252015-08-27 23:25:21 +0200695 @property
696 def cts(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000697 """Read terminal status line: Clear To Send"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200698 if not self.is_open:
Chris Liechtie99bda32020-09-14 03:59:52 +0200699 raise PortNotOpenError()
cliechtid6bf52c2003-10-01 02:28:12 +0000700 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200701 return struct.unpack('I', s)[0] & TIOCM_CTS != 0
cliechtid6bf52c2003-10-01 02:28:12 +0000702
Chris Liechtief1fe252015-08-27 23:25:21 +0200703 @property
704 def dsr(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000705 """Read terminal status line: Data Set Ready"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200706 if not self.is_open:
Chris Liechtie99bda32020-09-14 03:59:52 +0200707 raise PortNotOpenError()
cliechtid6bf52c2003-10-01 02:28:12 +0000708 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200709 return struct.unpack('I', s)[0] & TIOCM_DSR != 0
cliechtid6bf52c2003-10-01 02:28:12 +0000710
Chris Liechtief1fe252015-08-27 23:25:21 +0200711 @property
712 def ri(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000713 """Read terminal status line: Ring Indicator"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200714 if not self.is_open:
Chris Liechtie99bda32020-09-14 03:59:52 +0200715 raise PortNotOpenError()
cliechti89b4af12002-02-12 23:24:41 +0000716 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200717 return struct.unpack('I', s)[0] & TIOCM_RI != 0
cliechti89b4af12002-02-12 23:24:41 +0000718
Chris Liechtief1fe252015-08-27 23:25:21 +0200719 @property
720 def cd(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000721 """Read terminal status line: Carrier Detect"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200722 if not self.is_open:
Chris Liechtie99bda32020-09-14 03:59:52 +0200723 raise PortNotOpenError()
cliechti89b4af12002-02-12 23:24:41 +0000724 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200725 return struct.unpack('I', s)[0] & TIOCM_CD != 0
cliechti89b4af12002-02-12 23:24:41 +0000726
cliechtia30a8a02003-10-05 12:28:13 +0000727 # - - platform specific - - - -
728
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200729 @property
730 def out_waiting(self):
731 """Return the number of bytes currently in the output buffer."""
Chris Liechti11465c82015-08-04 15:55:22 +0200732 #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str)
cliechti28b8fd02011-12-28 21:39:42 +0000733 s = fcntl.ioctl(self.fd, TIOCOUTQ, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200734 return struct.unpack('I', s)[0]
cliechti28b8fd02011-12-28 21:39:42 +0000735
cliechti8753bbc2005-01-15 20:32:51 +0000736 def fileno(self):
cliechti2f0f8a32011-12-28 22:10:00 +0000737 """\
738 For easier use of the serial port instance with select.
739 WARNING: this function is not portable to different platforms!
740 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200741 if not self.is_open:
Chris Liechtie99bda32020-09-14 03:59:52 +0200742 raise PortNotOpenError()
cliechti8753bbc2005-01-15 20:32:51 +0000743 return self.fd
cliechti89b4af12002-02-12 23:24:41 +0000744
Chris Liechti518b0d32015-08-30 02:20:39 +0200745 def set_input_flow_control(self, enable=True):
cliechti2f0f8a32011-12-28 22:10:00 +0000746 """\
747 Manually control flow - when software flow control is enabled.
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200748 This will send XON (true) or XOFF (false) to the other device.
cliechti2f0f8a32011-12-28 22:10:00 +0000749 WARNING: this function is not portable to different platforms!
750 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200751 if not self.is_open:
Chris Liechtie99bda32020-09-14 03:59:52 +0200752 raise PortNotOpenError()
cliechti4a601342011-12-29 02:22:17 +0000753 if enable:
Chris Liechti11465c82015-08-04 15:55:22 +0200754 termios.tcflow(self.fd, termios.TCION)
cliechti57e48a62009-08-03 22:29:58 +0000755 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200756 termios.tcflow(self.fd, termios.TCIOFF)
cliechti57e48a62009-08-03 22:29:58 +0000757
Chris Liechti518b0d32015-08-30 02:20:39 +0200758 def set_output_flow_control(self, enable=True):
cliechti2f0f8a32011-12-28 22:10:00 +0000759 """\
760 Manually control flow of outgoing data - when hardware or software flow
761 control is enabled.
762 WARNING: this function is not portable to different platforms!
763 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200764 if not self.is_open:
Chris Liechtie99bda32020-09-14 03:59:52 +0200765 raise PortNotOpenError()
cliechti2f0f8a32011-12-28 22:10:00 +0000766 if enable:
Chris Liechti11465c82015-08-04 15:55:22 +0200767 termios.tcflow(self.fd, termios.TCOON)
cliechti2f0f8a32011-12-28 22:10:00 +0000768 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200769 termios.tcflow(self.fd, termios.TCOOFF)
cliechti2f0f8a32011-12-28 22:10:00 +0000770
Chris Liechti59848422016-06-04 22:28:14 +0200771 def nonblocking(self):
772 """DEPRECATED - has no use"""
773 import warnings
774 warnings.warn("nonblocking() has no effect, already nonblocking", DeprecationWarning)
775
cliechtif81362e2009-07-25 03:44:33 +0000776
cliechtia9a093e2010-01-02 03:05:08 +0000777class PosixPollSerial(Serial):
cliechti7d448562014-08-03 21:57:45 +0000778 """\
cliechtif0a81d42014-08-04 14:03:53 +0000779 Poll based read implementation. Not all systems support poll properly.
780 However this one has better handling of errors, such as a device
cliechti7d448562014-08-03 21:57:45 +0000781 disconnecting while it's in use (e.g. USB-serial unplugged).
782 """
cliechtia9a093e2010-01-02 03:05:08 +0000783
784 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000785 """\
786 Read size bytes from the serial port. If a timeout is set it may
787 return less characters as requested. With no timeout it will block
788 until the requested number of bytes is read.
789 """
Chris Liechtiacac2362016-03-29 22:37:48 +0200790 if not self.is_open:
Chris Liechtie99bda32020-09-14 03:59:52 +0200791 raise PortNotOpenError()
cliechtia9a093e2010-01-02 03:05:08 +0000792 read = bytearray()
Chris Liechtia5726382017-08-24 23:43:23 +0200793 timeout = Timeout(self._timeout)
cliechtia9a093e2010-01-02 03:05:08 +0000794 poll = select.poll()
Chris Liechti033f17c2015-08-30 21:28:04 +0200795 poll.register(self.fd, select.POLLIN | select.POLLERR | select.POLLHUP | select.POLLNVAL)
Chris Liechtia5726382017-08-24 23:43:23 +0200796 poll.register(self.pipe_abort_read_r, select.POLLIN | select.POLLERR | select.POLLHUP | select.POLLNVAL)
cliechtia9a093e2010-01-02 03:05:08 +0000797 if size > 0:
798 while len(read) < size:
799 # print "\tread(): size",size, "have", len(read) #debug
800 # wait until device becomes ready to read (or something fails)
Chris Liechtia5726382017-08-24 23:43:23 +0200801 for fd, event in poll.poll(None if timeout.is_infinite else (timeout.time_left() * 1000)):
802 if fd == self.pipe_abort_read_r:
803 break
Chris Liechti033f17c2015-08-30 21:28:04 +0200804 if event & (select.POLLERR | select.POLLHUP | select.POLLNVAL):
cliechtia9a093e2010-01-02 03:05:08 +0000805 raise SerialException('device reports error (poll)')
806 # we don't care if it is select.POLLIN or timeout, that's
807 # handled below
Chris Liechtia5726382017-08-24 23:43:23 +0200808 if fd == self.pipe_abort_read_r:
809 os.read(self.pipe_abort_read_r, 1000)
810 break
cliechtia9a093e2010-01-02 03:05:08 +0000811 buf = os.read(self.fd, size - len(read))
812 read.extend(buf)
Chris Liechtia5726382017-08-24 23:43:23 +0200813 if timeout.expired() \
814 or (self._inter_byte_timeout is not None and self._inter_byte_timeout > 0) and not buf:
cliechtia9a093e2010-01-02 03:05:08 +0000815 break # early abort on timeout
816 return bytes(read)
817
cliechtif81362e2009-07-25 03:44:33 +0000818
Chris Liechti4cf54702015-10-18 00:21:56 +0200819class VTIMESerial(Serial):
820 """\
821 Implement timeout using vtime of tty device instead of using select.
822 This means that no inter character timeout can be specified and that
823 the error handling is degraded.
824
825 Overall timeout is disabled when inter-character timeout is used.
Chris Liechti22d39002018-05-08 03:39:20 +0200826
827 Note that this implementation does NOT support cancel_read(), it will
828 just ignore that.
Chris Liechti4cf54702015-10-18 00:21:56 +0200829 """
830
Chris Liechti94284702015-11-15 01:21:48 +0100831 def _reconfigure_port(self, force_update=True):
Chris Liechti4cf54702015-10-18 00:21:56 +0200832 """Set communication parameters on opened port."""
833 super(VTIMESerial, self)._reconfigure_port()
Chris Liechtid6bcaaf2016-02-01 22:55:26 +0100834 fcntl.fcntl(self.fd, fcntl.F_SETFL, 0) # clear O_NONBLOCK
Chris Liechti4cf54702015-10-18 00:21:56 +0200835
836 if self._inter_byte_timeout is not None:
837 vmin = 1
838 vtime = int(self._inter_byte_timeout * 10)
Chris Liechti3ec9c412016-08-08 01:06:46 +0200839 elif self._timeout is None:
840 vmin = 1
841 vtime = 0
Chris Liechti4cf54702015-10-18 00:21:56 +0200842 else:
843 vmin = 0
844 vtime = int(self._timeout * 10)
845 try:
846 orig_attr = termios.tcgetattr(self.fd)
847 iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
848 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 +0100849 raise serial.SerialException("Could not configure port: {}".format(msg))
Chris Liechti4cf54702015-10-18 00:21:56 +0200850
851 if vtime < 0 or vtime > 255:
Chris Liechti984c5c52016-02-15 23:48:45 +0100852 raise ValueError('Invalid vtime: {!r}'.format(vtime))
Chris Liechti4cf54702015-10-18 00:21:56 +0200853 cc[termios.VTIME] = vtime
854 cc[termios.VMIN] = vmin
855
856 termios.tcsetattr(
857 self.fd,
858 termios.TCSANOW,
859 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
860
Chris Liechti4cf54702015-10-18 00:21:56 +0200861 def read(self, size=1):
862 """\
863 Read size bytes from the serial port. If a timeout is set it may
864 return less characters as requested. With no timeout it will block
865 until the requested number of bytes is read.
866 """
867 if not self.is_open:
Chris Liechtie99bda32020-09-14 03:59:52 +0200868 raise PortNotOpenError()
Chris Liechti4cf54702015-10-18 00:21:56 +0200869 read = bytearray()
870 while len(read) < size:
871 buf = os.read(self.fd, size - len(read))
872 if not buf:
873 break
874 read.extend(buf)
875 return bytes(read)
Chris Liechti3ec9c412016-08-08 01:06:46 +0200876
877 # hack to make hasattr return false
878 cancel_read = property()