blob: cea104c2f1faafce7c3c85147fe34c320510a0e5 [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, \
42 portNotOpenError, writeTimeoutError, 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 Mikowicz98c6a832018-07-13 16:57:19 -070056
Chris Liechti6dc58e82016-08-29 23:02:13 +020057
58# some systems support an extra flag to enable the two in POSIX unsupported
Chris Liechti11538242016-09-06 22:20:09 +020059# paritiy settings for MARK and SPACE
Chris Liechti6dc58e82016-08-29 23:02:13 +020060CMSPAR = 0 # default, for unsupported platforms, override below
61
Chris Liechtid6847af2015-08-06 17:54:30 +020062# try to detect the OS so that a device can be selected...
63# this code block should supply a device() and set_special_baudrate() function
64# for the platform
65plat = sys.platform.lower()
66
Chris Liechtiba45c522016-02-06 23:53:23 +010067if plat[:5] == 'linux': # Linux (confirmed) # noqa
Chris Liechtid6847af2015-08-06 17:54:30 +020068 import array
69
Chris Liechti6dc58e82016-08-29 23:02:13 +020070 # extra termios flags
71 CMSPAR = 0o10000000000 # Use "stick" (mark/space) parity
72
Chris Liechtid6847af2015-08-06 17:54:30 +020073 # baudrate ioctls
74 TCGETS2 = 0x802C542A
75 TCSETS2 = 0x402C542B
76 BOTHER = 0o010000
77
78 # RS485 ioctls
79 TIOCGRS485 = 0x542E
80 TIOCSRS485 = 0x542F
Chris Liechti033f17c2015-08-30 21:28:04 +020081 SER_RS485_ENABLED = 0b00000001
82 SER_RS485_RTS_ON_SEND = 0b00000010
Chris Liechtid6847af2015-08-06 17:54:30 +020083 SER_RS485_RTS_AFTER_SEND = 0b00000100
Chris Liechti033f17c2015-08-30 21:28:04 +020084 SER_RS485_RX_DURING_TX = 0b00010000
Chris Liechtid6847af2015-08-06 17:54:30 +020085
86 class PlatformSpecific(PlatformSpecificBase):
87 BAUDRATE_CONSTANTS = {
88 0: 0o000000, # hang up
89 50: 0o000001,
90 75: 0o000002,
91 110: 0o000003,
92 134: 0o000004,
93 150: 0o000005,
94 200: 0o000006,
95 300: 0o000007,
96 600: 0o000010,
97 1200: 0o000011,
98 1800: 0o000012,
99 2400: 0o000013,
100 4800: 0o000014,
101 9600: 0o000015,
102 19200: 0o000016,
103 38400: 0o000017,
104 57600: 0o010001,
105 115200: 0o010002,
106 230400: 0o010003,
107 460800: 0o010004,
108 500000: 0o010005,
109 576000: 0o010006,
110 921600: 0o010007,
111 1000000: 0o010010,
112 1152000: 0o010011,
113 1500000: 0o010012,
114 2000000: 0o010013,
115 2500000: 0o010014,
116 3000000: 0o010015,
117 3500000: 0o010016,
118 4000000: 0o010017
119 }
120
Jan Kantert1b2658a2018-05-07 21:17:37 +0200121 def set_low_latency_mode(self, low_latency_settings):
122 buf = array.array('i', [0] * 32)
123
124 try:
125 # get serial_struct
126 fcntl.ioctl(self.fd, termios.TIOCGSERIAL, buf)
127
128 # set or unset ASYNC_LOW_LATENCY flag
129 if low_latency_settings:
130 buf[4] |= 0x2000
131 else:
132 buf[4] &= ~0x2000
133
134 # set serial_struct
135 fcntl.ioctl(self.fd, termios.TIOCSSERIAL, buf)
136 except IOError as e:
137 raise ValueError('Failed to update ASYNC_LOW_LATENCY flag to {}: {}'.format(low_latency_settings, e))
138
Chris Liechtid6847af2015-08-06 17:54:30 +0200139 def _set_special_baudrate(self, baudrate):
140 # right size is 44 on x86_64, allow for some growth
141 buf = array.array('i', [0] * 64)
142 try:
143 # get serial_struct
144 fcntl.ioctl(self.fd, TCGETS2, buf)
145 # set custom speed
146 buf[2] &= ~termios.CBAUD
147 buf[2] |= BOTHER
148 buf[9] = buf[10] = baudrate
149
150 # set serial_struct
Chris Liechti033f17c2015-08-30 21:28:04 +0200151 fcntl.ioctl(self.fd, TCSETS2, buf)
Chris Liechtid6847af2015-08-06 17:54:30 +0200152 except IOError as e:
Chris Liechti984c5c52016-02-15 23:48:45 +0100153 raise ValueError('Failed to set custom baud rate ({}): {}'.format(baudrate, e))
Chris Liechtid6847af2015-08-06 17:54:30 +0200154
155 def _set_rs485_mode(self, rs485_settings):
Chris Liechti033f17c2015-08-30 21:28:04 +0200156 buf = array.array('i', [0] * 8) # flags, delaytx, delayrx, padding
Chris Liechtid6847af2015-08-06 17:54:30 +0200157 try:
158 fcntl.ioctl(self.fd, TIOCGRS485, buf)
Chris Liechti7a554462016-03-24 21:17:22 +0100159 buf[0] |= SER_RS485_ENABLED
Chris Liechtid6847af2015-08-06 17:54:30 +0200160 if rs485_settings is not None:
161 if rs485_settings.loopback:
162 buf[0] |= SER_RS485_RX_DURING_TX
163 else:
164 buf[0] &= ~SER_RS485_RX_DURING_TX
165 if rs485_settings.rts_level_for_tx:
166 buf[0] |= SER_RS485_RTS_ON_SEND
167 else:
168 buf[0] &= ~SER_RS485_RTS_ON_SEND
169 if rs485_settings.rts_level_for_rx:
170 buf[0] |= SER_RS485_RTS_AFTER_SEND
171 else:
172 buf[0] &= ~SER_RS485_RTS_AFTER_SEND
Chris Liechti279201b2016-06-09 20:27:05 +0200173 if rs485_settings.delay_before_tx is not None:
174 buf[1] = int(rs485_settings.delay_before_tx * 1000)
175 if rs485_settings.delay_before_rx is not None:
176 buf[2] = int(rs485_settings.delay_before_rx * 1000)
Chris Liechtid6847af2015-08-06 17:54:30 +0200177 else:
178 buf[0] = 0 # clear SER_RS485_ENABLED
Chris Liechti033f17c2015-08-30 21:28:04 +0200179 fcntl.ioctl(self.fd, TIOCSRS485, buf)
Chris Liechtid6847af2015-08-06 17:54:30 +0200180 except IOError as e:
Chris Liechti984c5c52016-02-15 23:48:45 +0100181 raise ValueError('Failed to set RS485 mode: {}'.format(e))
Chris Liechtid6847af2015-08-06 17:54:30 +0200182
183
184elif plat == 'cygwin': # cygwin/win32 (confirmed)
185
186 class PlatformSpecific(PlatformSpecificBase):
187 BAUDRATE_CONSTANTS = {
188 128000: 0x01003,
189 256000: 0x01005,
190 500000: 0x01007,
191 576000: 0x01008,
192 921600: 0x01009,
193 1000000: 0x0100a,
194 1152000: 0x0100b,
195 1500000: 0x0100c,
196 2000000: 0x0100d,
197 2500000: 0x0100e,
198 3000000: 0x0100f
199 }
200
Chris Liechtid6847af2015-08-06 17:54:30 +0200201
202elif plat[:6] == 'darwin': # OS X
203 import array
Chris Liechti033f17c2015-08-30 21:28:04 +0200204 IOSSIOSPEED = 0x80045402 # _IOW('T', 2, speed_t)
Chris Liechtid6847af2015-08-06 17:54:30 +0200205
206 class PlatformSpecific(PlatformSpecificBase):
Chris Liechtid6847af2015-08-06 17:54:30 +0200207 osx_version = os.uname()[2].split('.')
Kaelan Mikowiczfca918d2018-07-14 23:21:33 -0700208 TIOCSBRK = 0x2000747B # _IO('t', 123)
209 TIOCCBRK = 0x2000747A # _IO('t', 122)
210
Chris Liechtid6847af2015-08-06 17:54:30 +0200211 # Tiger or above can support arbitrary serial speeds
212 if int(osx_version[0]) >= 8:
213 def _set_special_baudrate(self, baudrate):
214 # use IOKit-specific call to set up high speeds
215 buf = array.array('i', [baudrate])
216 fcntl.ioctl(self.fd, IOSSIOSPEED, buf, 1)
217
Kaelan Mikowicz98c6a832018-07-13 16:57:19 -0700218 def _update_break_state(self):
219 """\
220 Set break: Controls TXD. When active, no transmitting is possible.
221 """
222 if self._break_state:
Kaelan Mikowiczfca918d2018-07-14 23:21:33 -0700223 fcntl.ioctl(self.fd, PlatformSpecific.TIOCSBRK)
Kaelan Mikowicz98c6a832018-07-13 16:57:19 -0700224 else:
Kaelan Mikowiczfca918d2018-07-14 23:21:33 -0700225 fcntl.ioctl(self.fd, PlatformSpecific.TIOCCBRK)
Kaelan Mikowicz98c6a832018-07-13 16:57:19 -0700226
Chris Liechti21a306b2016-10-09 23:41:26 +0200227elif plat[:3] == 'bsd' or \
228 plat[:7] == 'freebsd' or \
229 plat[:6] == 'netbsd' or \
230 plat[:7] == 'openbsd':
231
232 class ReturnBaudrate(object):
233 def __getitem__(self, key):
234 return key
235
236 class PlatformSpecific(PlatformSpecificBase):
237 # Only tested on FreeBSD:
238 # The baud rate may be passed in as
239 # a literal value.
240 BAUDRATE_CONSTANTS = ReturnBaudrate()
241
Kaelan Mikowiczfca918d2018-07-14 23:21:33 -0700242 TIOCSBRK = 0x2000747B # _IO('t', 123)
243 TIOCCBRK = 0x2000747A # _IO('t', 122)
244
245
246 def _update_break_state(self):
247 """\
248 Set break: Controls TXD. When active, no transmitting is possible.
249 """
250 if self._break_state:
251 fcntl.ioctl(self.fd, PlatformSpecific.TIOCSBRK)
252 else:
253 fcntl.ioctl(self.fd, PlatformSpecific.TIOCCBRK)
254
Chris Liechtid6847af2015-08-06 17:54:30 +0200255else:
256 class PlatformSpecific(PlatformSpecificBase):
257 pass
cliechti89b4af12002-02-12 23:24:41 +0000258
cliechti89b4af12002-02-12 23:24:41 +0000259
cliechti58b481c2009-02-16 20:42:32 +0000260# load some constants for later use.
Chris Liechti11465c82015-08-04 15:55:22 +0200261# try to use values from termios, use defaults from linux otherwise
Chris Liechti033f17c2015-08-30 21:28:04 +0200262TIOCMGET = getattr(termios, 'TIOCMGET', 0x5415)
263TIOCMBIS = getattr(termios, 'TIOCMBIS', 0x5416)
264TIOCMBIC = getattr(termios, 'TIOCMBIC', 0x5417)
265TIOCMSET = getattr(termios, 'TIOCMSET', 0x5418)
cliechti89b4af12002-02-12 23:24:41 +0000266
Chris Liechti033f17c2015-08-30 21:28:04 +0200267# TIOCM_LE = getattr(termios, 'TIOCM_LE', 0x001)
Chris Liechtid6847af2015-08-06 17:54:30 +0200268TIOCM_DTR = getattr(termios, 'TIOCM_DTR', 0x002)
269TIOCM_RTS = getattr(termios, 'TIOCM_RTS', 0x004)
Chris Liechti033f17c2015-08-30 21:28:04 +0200270# TIOCM_ST = getattr(termios, 'TIOCM_ST', 0x008)
271# TIOCM_SR = getattr(termios, 'TIOCM_SR', 0x010)
cliechti89b4af12002-02-12 23:24:41 +0000272
Chris Liechtid6847af2015-08-06 17:54:30 +0200273TIOCM_CTS = getattr(termios, 'TIOCM_CTS', 0x020)
274TIOCM_CAR = getattr(termios, 'TIOCM_CAR', 0x040)
275TIOCM_RNG = getattr(termios, 'TIOCM_RNG', 0x080)
276TIOCM_DSR = getattr(termios, 'TIOCM_DSR', 0x100)
Chris Liechti033f17c2015-08-30 21:28:04 +0200277TIOCM_CD = getattr(termios, 'TIOCM_CD', TIOCM_CAR)
278TIOCM_RI = getattr(termios, 'TIOCM_RI', TIOCM_RNG)
279# TIOCM_OUT1 = getattr(termios, 'TIOCM_OUT1', 0x2000)
280# TIOCM_OUT2 = getattr(termios, 'TIOCM_OUT2', 0x4000)
Chris Liechti11465c82015-08-04 15:55:22 +0200281if hasattr(termios, 'TIOCINQ'):
282 TIOCINQ = termios.TIOCINQ
cliechti28b8fd02011-12-28 21:39:42 +0000283else:
Chris Liechtid6847af2015-08-06 17:54:30 +0200284 TIOCINQ = getattr(termios, 'FIONREAD', 0x541B)
Chris Liechti033f17c2015-08-30 21:28:04 +0200285TIOCOUTQ = getattr(termios, 'TIOCOUTQ', 0x5411)
cliechti89b4af12002-02-12 23:24:41 +0000286
287TIOCM_zero_str = struct.pack('I', 0)
288TIOCM_RTS_str = struct.pack('I', TIOCM_RTS)
289TIOCM_DTR_str = struct.pack('I', TIOCM_DTR)
290
Chris Liechti033f17c2015-08-30 21:28:04 +0200291TIOCSBRK = getattr(termios, 'TIOCSBRK', 0x5427)
292TIOCCBRK = getattr(termios, 'TIOCCBRK', 0x5428)
cliechti997b63c2008-06-21 00:09:31 +0000293
cliechti89b4af12002-02-12 23:24:41 +0000294
Chris Liechtief6b7b42015-08-06 22:19:26 +0200295class Serial(SerialBase, PlatformSpecific):
cliechti7d448562014-08-03 21:57:45 +0000296 """\
Chris Liechti033f17c2015-08-30 21:28:04 +0200297 Serial port class POSIX implementation. Serial port configuration is
cliechtid6bf52c2003-10-01 02:28:12 +0000298 done with termios and fcntl. Runs on Linux and many other Un*x like
cliechtif0a81d42014-08-04 14:03:53 +0000299 systems.
300 """
cliechtid6bf52c2003-10-01 02:28:12 +0000301
302 def open(self):
cliechti7d448562014-08-03 21:57:45 +0000303 """\
304 Open port with current settings. This may throw a SerialException
305 if the port cannot be opened."""
cliechtid6bf52c2003-10-01 02:28:12 +0000306 if self._port is None:
307 raise SerialException("Port must be configured before it can be used.")
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200308 if self.is_open:
cliechti02ef43a2011-03-24 23:33:12 +0000309 raise SerialException("Port is already open.")
310 self.fd = None
cliechti58b481c2009-02-16 20:42:32 +0000311 # open
cliechti4616bf12002-04-08 23:13:14 +0000312 try:
Chris Liechti033f17c2015-08-30 21:28:04 +0200313 self.fd = os.open(self.portstr, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK)
Chris Liechti68340d72015-08-03 14:15:48 +0200314 except OSError as msg:
cliechti4616bf12002-04-08 23:13:14 +0000315 self.fd = None
Chris Liechti984c5c52016-02-15 23:48:45 +0100316 raise SerialException(msg.errno, "could not open port {}: {}".format(self._port, msg))
Chris Liechti11465c82015-08-04 15:55:22 +0200317 #~ fcntl.fcntl(self.fd, fcntl.F_SETFL, 0) # set blocking
cliechti58b481c2009-02-16 20:42:32 +0000318
cliechtib2f5fc82006-10-20 00:09:07 +0000319 try:
Chris Liechti94284702015-11-15 01:21:48 +0100320 self._reconfigure_port(force_update=True)
cliechtib2f5fc82006-10-20 00:09:07 +0000321 except:
cliechti2750b832009-07-28 00:13:52 +0000322 try:
323 os.close(self.fd)
324 except:
325 # ignore any exception when closing the port
326 # also to keep original exception that happened when setting up
327 pass
cliechtib2f5fc82006-10-20 00:09:07 +0000328 self.fd = None
cliechtif0a4f0f2009-07-21 21:12:37 +0000329 raise
cliechtib2f5fc82006-10-20 00:09:07 +0000330 else:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200331 self.is_open = True
Chris Liechtif2fdeb92016-05-07 23:57:50 +0200332 try:
333 if not self._dsrdtr:
334 self._update_dtr_state()
335 if not self._rtscts:
336 self._update_rts_state()
337 except IOError as e:
Chris Liechtie1029622016-10-02 23:54:36 +0200338 if e.errno in (errno.EINVAL, errno.ENOTTY):
339 # ignore Invalid argument and Inappropriate ioctl
Chris Liechtif2fdeb92016-05-07 23:57:50 +0200340 pass
341 else:
342 raise
Chris Liechtief1fe252015-08-27 23:25:21 +0200343 self.reset_input_buffer()
Chris Liechti42ab2b42016-05-15 23:35:05 +0200344 self.pipe_abort_read_r, self.pipe_abort_read_w = os.pipe()
Chris Liechti13949c62016-05-16 22:45:38 +0200345 self.pipe_abort_write_r, self.pipe_abort_write_w = os.pipe()
Chris Liechti68cecce2016-06-03 23:52:34 +0200346 fcntl.fcntl(self.pipe_abort_read_r, fcntl.F_SETFL, os.O_NONBLOCK)
347 fcntl.fcntl(self.pipe_abort_write_r, fcntl.F_SETFL, os.O_NONBLOCK)
cliechti58b481c2009-02-16 20:42:32 +0000348
Chris Liechti94284702015-11-15 01:21:48 +0100349 def _reconfigure_port(self, force_update=False):
cliechtib2f5fc82006-10-20 00:09:07 +0000350 """Set communication parameters on opened port."""
cliechtic6178262004-03-22 22:04:52 +0000351 if self.fd is None:
cliechtia9a093e2010-01-02 03:05:08 +0000352 raise SerialException("Can only operate on a valid file descriptor")
Chris Liechti1c4bc812017-03-08 02:44:04 +0100353
Rob Gaddi636cc642017-02-24 11:39:46 -0800354 # if exclusive lock is requested, create it before we modify anything else
355 if self._exclusive is not None:
356 if self._exclusive:
357 try:
358 fcntl.flock(self.fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
359 except IOError as msg:
360 raise SerialException(msg.errno, "Could not exclusively lock port {}: {}".format(self._port, msg))
361 else:
362 fcntl.flock(self.fd, fcntl.LOCK_UN)
Chris Liechti1c4bc812017-03-08 02:44:04 +0100363
cliechtie8c45422008-06-20 23:23:14 +0000364 custom_baud = None
cliechti58b481c2009-02-16 20:42:32 +0000365
cliechti2750b832009-07-28 00:13:52 +0000366 vmin = vtime = 0 # timeout is done via select
Chris Liechti518b0d32015-08-30 02:20:39 +0200367 if self._inter_byte_timeout is not None:
cliechti679bfa62008-06-20 23:58:15 +0000368 vmin = 1
Chris Liechti518b0d32015-08-30 02:20:39 +0200369 vtime = int(self._inter_byte_timeout * 10)
cliechti6ce7ab12002-11-07 02:15:00 +0000370 try:
cliechti4d0af5e2011-08-05 02:18:16 +0000371 orig_attr = termios.tcgetattr(self.fd)
372 iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
Chris Liechti68340d72015-08-03 14:15:48 +0200373 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 +0100374 raise SerialException("Could not configure port: {}".format(msg))
cliechti58b481c2009-02-16 20:42:32 +0000375 # set up raw mode / no echo / binary
Chris Liechti033f17c2015-08-30 21:28:04 +0200376 cflag |= (termios.CLOCAL | termios.CREAD)
377 lflag &= ~(termios.ICANON | termios.ECHO | termios.ECHOE |
378 termios.ECHOK | termios.ECHONL |
379 termios.ISIG | termios.IEXTEN) # |termios.ECHOPRT
380 for flag in ('ECHOCTL', 'ECHOKE'): # netbsd workaround for Erk
Chris Liechti11465c82015-08-04 15:55:22 +0200381 if hasattr(termios, flag):
382 lflag &= ~getattr(termios, flag)
cliechti58b481c2009-02-16 20:42:32 +0000383
Chris Liechti033f17c2015-08-30 21:28:04 +0200384 oflag &= ~(termios.OPOST | termios.ONLCR | termios.OCRNL)
385 iflag &= ~(termios.INLCR | termios.IGNCR | termios.ICRNL | termios.IGNBRK)
Chris Liechti11465c82015-08-04 15:55:22 +0200386 if hasattr(termios, 'IUCLC'):
387 iflag &= ~termios.IUCLC
388 if hasattr(termios, 'PARMRK'):
389 iflag &= ~termios.PARMRK
cliechti58b481c2009-02-16 20:42:32 +0000390
cliechtif0a4f0f2009-07-21 21:12:37 +0000391 # setup baud rate
cliechti89b4af12002-02-12 23:24:41 +0000392 try:
Chris Liechti984c5c52016-02-15 23:48:45 +0100393 ispeed = ospeed = getattr(termios, 'B{}'.format(self._baudrate))
cliechti895e8302004-04-20 02:40:28 +0000394 except AttributeError:
cliechtif1559d02007-11-08 23:43:58 +0000395 try:
Chris Liechtid6847af2015-08-06 17:54:30 +0200396 ispeed = ospeed = self.BAUDRATE_CONSTANTS[self._baudrate]
cliechtif1559d02007-11-08 23:43:58 +0000397 except KeyError:
cliechtie8c45422008-06-20 23:23:14 +0000398 #~ raise ValueError('Invalid baud rate: %r' % self._baudrate)
cliechtif0a4f0f2009-07-21 21:12:37 +0000399 # may need custom baud rate, it isn't in our list.
Chris Liechti11465c82015-08-04 15:55:22 +0200400 ispeed = ospeed = getattr(termios, 'B38400')
cliechtif0a4f0f2009-07-21 21:12:37 +0000401 try:
Chris Liechti033f17c2015-08-30 21:28:04 +0200402 custom_baud = int(self._baudrate) # store for later
cliechtif0a4f0f2009-07-21 21:12:37 +0000403 except ValueError:
Chris Liechti984c5c52016-02-15 23:48:45 +0100404 raise ValueError('Invalid baud rate: {!r}'.format(self._baudrate))
cliechtif0a4f0f2009-07-21 21:12:37 +0000405 else:
406 if custom_baud < 0:
Chris Liechti984c5c52016-02-15 23:48:45 +0100407 raise ValueError('Invalid baud rate: {!r}'.format(self._baudrate))
cliechti58b481c2009-02-16 20:42:32 +0000408
409 # setup char len
Chris Liechti11465c82015-08-04 15:55:22 +0200410 cflag &= ~termios.CSIZE
cliechtid6bf52c2003-10-01 02:28:12 +0000411 if self._bytesize == 8:
Chris Liechti11465c82015-08-04 15:55:22 +0200412 cflag |= termios.CS8
cliechtid6bf52c2003-10-01 02:28:12 +0000413 elif self._bytesize == 7:
Chris Liechti11465c82015-08-04 15:55:22 +0200414 cflag |= termios.CS7
cliechtid6bf52c2003-10-01 02:28:12 +0000415 elif self._bytesize == 6:
Chris Liechti11465c82015-08-04 15:55:22 +0200416 cflag |= termios.CS6
cliechtid6bf52c2003-10-01 02:28:12 +0000417 elif self._bytesize == 5:
Chris Liechti11465c82015-08-04 15:55:22 +0200418 cflag |= termios.CS5
cliechti89b4af12002-02-12 23:24:41 +0000419 else:
Chris Liechti984c5c52016-02-15 23:48:45 +0100420 raise ValueError('Invalid char len: {!r}'.format(self._bytesize))
cliechtif0a81d42014-08-04 14:03:53 +0000421 # setup stop bits
Chris Liechti033f17c2015-08-30 21:28:04 +0200422 if self._stopbits == serial.STOPBITS_ONE:
Chris Liechti11465c82015-08-04 15:55:22 +0200423 cflag &= ~(termios.CSTOPB)
Chris Liechti033f17c2015-08-30 21:28:04 +0200424 elif self._stopbits == serial.STOPBITS_ONE_POINT_FIVE:
425 cflag |= (termios.CSTOPB) # XXX same as TWO.. there is no POSIX support for 1.5
426 elif self._stopbits == serial.STOPBITS_TWO:
427 cflag |= (termios.CSTOPB)
cliechti89b4af12002-02-12 23:24:41 +0000428 else:
Chris Liechti984c5c52016-02-15 23:48:45 +0100429 raise ValueError('Invalid stop bit specification: {!r}'.format(self._stopbits))
cliechti58b481c2009-02-16 20:42:32 +0000430 # setup parity
Chris Liechti033f17c2015-08-30 21:28:04 +0200431 iflag &= ~(termios.INPCK | termios.ISTRIP)
432 if self._parity == serial.PARITY_NONE:
Chris Liechti6dc58e82016-08-29 23:02:13 +0200433 cflag &= ~(termios.PARENB | termios.PARODD | CMSPAR)
Chris Liechti033f17c2015-08-30 21:28:04 +0200434 elif self._parity == serial.PARITY_EVEN:
Chris Liechti6dc58e82016-08-29 23:02:13 +0200435 cflag &= ~(termios.PARODD | CMSPAR)
Chris Liechti033f17c2015-08-30 21:28:04 +0200436 cflag |= (termios.PARENB)
437 elif self._parity == serial.PARITY_ODD:
Chris Liechti6dc58e82016-08-29 23:02:13 +0200438 cflag &= ~CMSPAR
Chris Liechti033f17c2015-08-30 21:28:04 +0200439 cflag |= (termios.PARENB | termios.PARODD)
Chris Liechti6dc58e82016-08-29 23:02:13 +0200440 elif self._parity == serial.PARITY_MARK and CMSPAR:
Chris Liechti033f17c2015-08-30 21:28:04 +0200441 cflag |= (termios.PARENB | CMSPAR | termios.PARODD)
Chris Liechti6dc58e82016-08-29 23:02:13 +0200442 elif self._parity == serial.PARITY_SPACE and CMSPAR:
Chris Liechti033f17c2015-08-30 21:28:04 +0200443 cflag |= (termios.PARENB | CMSPAR)
Chris Liechti11465c82015-08-04 15:55:22 +0200444 cflag &= ~(termios.PARODD)
cliechti89b4af12002-02-12 23:24:41 +0000445 else:
Chris Liechti984c5c52016-02-15 23:48:45 +0100446 raise ValueError('Invalid parity: {!r}'.format(self._parity))
cliechti58b481c2009-02-16 20:42:32 +0000447 # setup flow control
448 # xonxoff
Chris Liechti11465c82015-08-04 15:55:22 +0200449 if hasattr(termios, 'IXANY'):
cliechtid6bf52c2003-10-01 02:28:12 +0000450 if self._xonxoff:
Chris Liechti033f17c2015-08-30 21:28:04 +0200451 iflag |= (termios.IXON | termios.IXOFF) # |termios.IXANY)
cliechti89b4af12002-02-12 23:24:41 +0000452 else:
Chris Liechti033f17c2015-08-30 21:28:04 +0200453 iflag &= ~(termios.IXON | termios.IXOFF | termios.IXANY)
cliechti89b4af12002-02-12 23:24:41 +0000454 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000455 if self._xonxoff:
Chris Liechti033f17c2015-08-30 21:28:04 +0200456 iflag |= (termios.IXON | termios.IXOFF)
cliechti89b4af12002-02-12 23:24:41 +0000457 else:
Chris Liechti033f17c2015-08-30 21:28:04 +0200458 iflag &= ~(termios.IXON | termios.IXOFF)
cliechti58b481c2009-02-16 20:42:32 +0000459 # rtscts
Chris Liechti11465c82015-08-04 15:55:22 +0200460 if hasattr(termios, 'CRTSCTS'):
cliechtid6bf52c2003-10-01 02:28:12 +0000461 if self._rtscts:
Chris Liechti033f17c2015-08-30 21:28:04 +0200462 cflag |= (termios.CRTSCTS)
cliechti89b4af12002-02-12 23:24:41 +0000463 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200464 cflag &= ~(termios.CRTSCTS)
465 elif hasattr(termios, 'CNEW_RTSCTS'): # try it with alternate constant name
cliechtid6bf52c2003-10-01 02:28:12 +0000466 if self._rtscts:
Chris Liechti033f17c2015-08-30 21:28:04 +0200467 cflag |= (termios.CNEW_RTSCTS)
cliechtid4743692002-04-08 22:39:53 +0000468 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200469 cflag &= ~(termios.CNEW_RTSCTS)
cliechti2750b832009-07-28 00:13:52 +0000470 # XXX should there be a warning if setting up rtscts (and xonxoff etc) fails??
cliechti58b481c2009-02-16 20:42:32 +0000471
472 # buffer
cliechtif0a81d42014-08-04 14:03:53 +0000473 # vmin "minimal number of characters to be read. 0 for non blocking"
cliechtid6bf52c2003-10-01 02:28:12 +0000474 if vmin < 0 or vmin > 255:
Chris Liechti984c5c52016-02-15 23:48:45 +0100475 raise ValueError('Invalid vmin: {!r}'.format(vmin))
Chris Liechti11465c82015-08-04 15:55:22 +0200476 cc[termios.VMIN] = vmin
cliechti58b481c2009-02-16 20:42:32 +0000477 # vtime
cliechtid6bf52c2003-10-01 02:28:12 +0000478 if vtime < 0 or vtime > 255:
Chris Liechti984c5c52016-02-15 23:48:45 +0100479 raise ValueError('Invalid vtime: {!r}'.format(vtime))
Chris Liechti11465c82015-08-04 15:55:22 +0200480 cc[termios.VTIME] = vtime
cliechti58b481c2009-02-16 20:42:32 +0000481 # activate settings
Chris Liechti94284702015-11-15 01:21:48 +0100482 if force_update or [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] != orig_attr:
Chris Liechti033f17c2015-08-30 21:28:04 +0200483 termios.tcsetattr(
Chris Liechti9eaa40c2016-02-12 23:32:59 +0100484 self.fd,
485 termios.TCSANOW,
486 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
cliechti58b481c2009-02-16 20:42:32 +0000487
cliechtie8c45422008-06-20 23:23:14 +0000488 # apply custom baud rate, if any
489 if custom_baud is not None:
Chris Liechtid6847af2015-08-06 17:54:30 +0200490 self._set_special_baudrate(custom_baud)
491
492 if self._rs485_mode is not None:
493 self._set_rs485_mode(self._rs485_mode)
cliechti89b4af12002-02-12 23:24:41 +0000494
495 def close(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000496 """Close port"""
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200497 if self.is_open:
cliechtic6178262004-03-22 22:04:52 +0000498 if self.fd is not None:
cliechtid6bf52c2003-10-01 02:28:12 +0000499 os.close(self.fd)
500 self.fd = None
Chris Liechtib658eac2016-05-22 20:51:44 +0200501 os.close(self.pipe_abort_read_w)
502 os.close(self.pipe_abort_read_r)
503 os.close(self.pipe_abort_write_w)
504 os.close(self.pipe_abort_write_r)
505 self.pipe_abort_read_r, self.pipe_abort_read_w = None, None
506 self.pipe_abort_write_r, self.pipe_abort_write_w = None, None
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200507 self.is_open = False
cliechtid6bf52c2003-10-01 02:28:12 +0000508
509 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechti95c62212002-03-04 22:17:53 +0000510
Chris Liechtief1fe252015-08-27 23:25:21 +0200511 @property
512 def in_waiting(self):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200513 """Return the number of bytes currently in the input buffer."""
Chris Liechti11465c82015-08-04 15:55:22 +0200514 #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str)
cliechtif5831e02002-12-05 23:15:27 +0000515 s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200516 return struct.unpack('I', s)[0]
cliechti89b4af12002-02-12 23:24:41 +0000517
cliechtia9a093e2010-01-02 03:05:08 +0000518 # select based implementation, proved to work on many systems
519 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000520 """\
521 Read size bytes from the serial port. If a timeout is set it may
522 return less characters as requested. With no timeout it will block
523 until the requested number of bytes is read.
524 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200525 if not self.is_open:
526 raise portNotOpenError
cliechtia9a093e2010-01-02 03:05:08 +0000527 read = bytearray()
Chris Liechti935a2622016-08-30 23:39:15 +0200528 timeout = Timeout(self._timeout)
cliechtia9a093e2010-01-02 03:05:08 +0000529 while len(read) < size:
cliechti8d744de2013-10-11 14:31:13 +0000530 try:
Chris Liechti935a2622016-08-30 23:39:15 +0200531 ready, _, _ = select.select([self.fd, self.pipe_abort_read_r], [], [], timeout.time_left())
Chris Liechti42ab2b42016-05-15 23:35:05 +0200532 if self.pipe_abort_read_r in ready:
Chris Liechti68cecce2016-06-03 23:52:34 +0200533 os.read(self.pipe_abort_read_r, 1000)
Chris Liechti42ab2b42016-05-15 23:35:05 +0200534 break
cliechti8d744de2013-10-11 14:31:13 +0000535 # If select was used with a timeout, and the timeout occurs, it
536 # returns with empty lists -> thus abort read operation.
Chris Liechti033f17c2015-08-30 21:28:04 +0200537 # For timeout == 0 (non-blocking operation) also abort when
538 # there is nothing to read.
cliechti8d744de2013-10-11 14:31:13 +0000539 if not ready:
540 break # timeout
Chris Liechti033f17c2015-08-30 21:28:04 +0200541 buf = os.read(self.fd, size - len(read))
cliechti8d744de2013-10-11 14:31:13 +0000542 # read should always return some data as select reported it was
543 # ready to read when we get to this point.
544 if not buf:
545 # Disconnected devices, at least on Linux, show the
546 # behavior that they are always ready to read immediately
547 # but reading returns nothing.
Chris Liechti92df95a2016-02-09 23:30:37 +0100548 raise SerialException(
549 'device reports readiness to read but returned no data '
550 '(device disconnected or multiple access on port?)')
cliechti8d744de2013-10-11 14:31:13 +0000551 read.extend(buf)
Chris Liechti68340d72015-08-03 14:15:48 +0200552 except OSError as e:
Chris Liechti033f17c2015-08-30 21:28:04 +0200553 # this is for Python 3.x where select.error is a subclass of
Chris Liechti17660ee2017-05-04 23:39:05 +0200554 # OSError ignore BlockingIOErrors and EINTR. other errors are shown
555 # https://www.python.org/dev/peps/pep-0475.
556 if e.errno not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
Chris Liechti984c5c52016-02-15 23:48:45 +0100557 raise SerialException('read failed: {}'.format(e))
Chris Liechti68340d72015-08-03 14:15:48 +0200558 except select.error as e:
cliechtic7cd7212014-08-03 21:34:38 +0000559 # this is for Python 2.x
Chris Liechti17660ee2017-05-04 23:39:05 +0200560 # ignore BlockingIOErrors and EINTR. all errors are shown
cliechti8d744de2013-10-11 14:31:13 +0000561 # see also http://www.python.org/dev/peps/pep-3151/#select
Chris Liechti1c8dbee2017-05-05 03:26:51 +0200562 if e[0] 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 Liechti935a2622016-08-30 23:39:15 +0200564 if timeout.expired():
565 break
cliechtia9a093e2010-01-02 03:05:08 +0000566 return bytes(read)
cliechti89b4af12002-02-12 23:24:41 +0000567
Chris Liechti42ab2b42016-05-15 23:35:05 +0200568 def cancel_read(self):
Chris Liechti9c326282017-07-15 01:58:56 +0200569 if self.is_open:
570 os.write(self.pipe_abort_read_w, b"x")
Chris Liechti42ab2b42016-05-15 23:35:05 +0200571
Chris Liechti13949c62016-05-16 22:45:38 +0200572 def cancel_write(self):
Chris Liechti9c326282017-07-15 01:58:56 +0200573 if self.is_open:
574 os.write(self.pipe_abort_write_w, b"x")
Chris Liechti13949c62016-05-16 22:45:38 +0200575
cliechti4a567a02009-07-27 22:09:31 +0000576 def write(self, data):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200577 """Output the given byte string over the serial port."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200578 if not self.is_open:
579 raise portNotOpenError
cliechti38077122013-10-16 02:57:27 +0000580 d = to_bytes(data)
Chris Liechtie0063f12016-12-17 23:44:18 +0100581 tx_len = length = len(d)
Chris Liechti935a2622016-08-30 23:39:15 +0200582 timeout = Timeout(self._write_timeout)
cliechti9f7c2352013-10-11 01:13:46 +0000583 while tx_len > 0:
cliechti5d4d0bd2004-11-13 03:27:39 +0000584 try:
cliechti5d4d0bd2004-11-13 03:27:39 +0000585 n = os.write(self.fd, d)
Chris Liechti935a2622016-08-30 23:39:15 +0200586 if timeout.is_non_blocking:
Robert Smallshire325a7382016-03-25 21:18:38 +0100587 # Zero timeout indicates non-blocking - simply return the
588 # number of bytes of data actually written
589 return n
Chris Liechti935a2622016-08-30 23:39:15 +0200590 elif not timeout.is_infinite:
cliechti3cf46d62009-08-07 00:19:57 +0000591 # when timeout is set, use select to wait for being ready
592 # with the time left as timeout
Chris Liechti935a2622016-08-30 23:39:15 +0200593 if timeout.expired():
cliechti3cf46d62009-08-07 00:19:57 +0000594 raise writeTimeoutError
Chris Liechti935a2622016-08-30 23:39:15 +0200595 abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], timeout.time_left())
Chris Liechti13949c62016-05-16 22:45:38 +0200596 if abort:
Chris Liechti68cecce2016-06-03 23:52:34 +0200597 os.read(self.pipe_abort_write_r, 1000)
Chris Liechti13949c62016-05-16 22:45:38 +0200598 break
cliechti5d4d0bd2004-11-13 03:27:39 +0000599 if not ready:
600 raise writeTimeoutError
cliechti88c62442013-10-12 04:03:16 +0000601 else:
Chris Liechti935a2622016-08-30 23:39:15 +0200602 assert timeout.time_left() is None
cliechti88c62442013-10-12 04:03:16 +0000603 # wait for write operation
Chris Liechti13949c62016-05-16 22:45:38 +0200604 abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], None)
605 if abort:
606 os.read(self.pipe_abort_write_r, 1)
607 break
cliechti88c62442013-10-12 04:03:16 +0000608 if not ready:
609 raise SerialException('write failed (select)')
cliechti5d4d0bd2004-11-13 03:27:39 +0000610 d = d[n:]
cliechti9f7c2352013-10-11 01:13:46 +0000611 tx_len -= n
Chris Liechti675f7e12015-08-03 15:48:41 +0200612 except SerialException:
613 raise
Chris Liechti10d79d92017-05-05 00:05:23 +0200614 except OSError as e:
615 # this is for Python 3.x where select.error is a subclass of
616 # OSError ignore BlockingIOErrors and EINTR. other errors are shown
617 # https://www.python.org/dev/peps/pep-0475.
618 if e.errno not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
619 raise SerialException('write failed: {}'.format(e))
620 except select.error as e:
621 # this is for Python 2.x
622 # ignore BlockingIOErrors and EINTR. all errors are shown
623 # see also http://www.python.org/dev/peps/pep-3151/#select
Chris Liechti1c8dbee2017-05-05 03:26:51 +0200624 if e[0] not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
Chris Liechti10d79d92017-05-05 00:05:23 +0200625 raise SerialException('write failed: {}'.format(e))
Chris Liechtifc70fd72017-05-05 02:59:06 +0200626 if not timeout.is_non_blocking and timeout.expired():
Chris Liechti10d79d92017-05-05 00:05:23 +0200627 raise writeTimeoutError
Chris Liechtie0063f12016-12-17 23:44:18 +0100628 return length - len(d)
cliechtid6bf52c2003-10-01 02:28:12 +0000629
cliechtia30a8a02003-10-05 12:28:13 +0000630 def flush(self):
cliechti7d448562014-08-03 21:57:45 +0000631 """\
632 Flush of file like objects. In this case, wait until all data
633 is written.
634 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200635 if not self.is_open:
636 raise portNotOpenError
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200637 termios.tcdrain(self.fd)
cliechtia30a8a02003-10-05 12:28:13 +0000638
Chris Liechtief1fe252015-08-27 23:25:21 +0200639 def reset_input_buffer(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000640 """Clear input buffer, discarding all that is in the buffer."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200641 if not self.is_open:
642 raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200643 termios.tcflush(self.fd, termios.TCIFLUSH)
cliechti89b4af12002-02-12 23:24:41 +0000644
Chris Liechtief1fe252015-08-27 23:25:21 +0200645 def reset_output_buffer(self):
cliechti7d448562014-08-03 21:57:45 +0000646 """\
647 Clear output buffer, aborting the current output and discarding all
648 that is in the buffer.
649 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200650 if not self.is_open:
651 raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200652 termios.tcflush(self.fd, termios.TCOFLUSH)
cliechti89b4af12002-02-12 23:24:41 +0000653
Chris Liechtief1fe252015-08-27 23:25:21 +0200654 def send_break(self, duration=0.25):
cliechti7d448562014-08-03 21:57:45 +0000655 """\
656 Send break condition. Timed, returns to idle state after given
657 duration.
658 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200659 if not self.is_open:
660 raise portNotOpenError
661 termios.tcsendbreak(self.fd, int(duration / 0.25))
cliechti89b4af12002-02-12 23:24:41 +0000662
Chris Liechtief1fe252015-08-27 23:25:21 +0200663 def _update_break_state(self):
cliechti7d448562014-08-03 21:57:45 +0000664 """\
665 Set break: Controls TXD. When active, no transmitting is possible.
666 """
Chris Liechtief1fe252015-08-27 23:25:21 +0200667 if self._break_state:
cliechti997b63c2008-06-21 00:09:31 +0000668 fcntl.ioctl(self.fd, TIOCSBRK)
669 else:
670 fcntl.ioctl(self.fd, TIOCCBRK)
671
Chris Liechtief1fe252015-08-27 23:25:21 +0200672 def _update_rts_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000673 """Set terminal status line: Request To Send"""
Chris Liechtif7534c82016-05-07 23:35:54 +0200674 if self._rts_state:
675 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_RTS_str)
676 else:
677 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_RTS_str)
cliechtid6bf52c2003-10-01 02:28:12 +0000678
Chris Liechtief1fe252015-08-27 23:25:21 +0200679 def _update_dtr_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000680 """Set terminal status line: Data Terminal Ready"""
Chris Liechtif7534c82016-05-07 23:35:54 +0200681 if self._dtr_state:
682 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str)
683 else:
684 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_DTR_str)
cliechtid6bf52c2003-10-01 02:28:12 +0000685
Chris Liechtief1fe252015-08-27 23:25:21 +0200686 @property
687 def cts(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000688 """Read terminal status line: Clear To Send"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200689 if not self.is_open:
690 raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000691 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200692 return struct.unpack('I', s)[0] & TIOCM_CTS != 0
cliechtid6bf52c2003-10-01 02:28:12 +0000693
Chris Liechtief1fe252015-08-27 23:25:21 +0200694 @property
695 def dsr(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000696 """Read terminal status line: Data Set Ready"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200697 if not self.is_open:
698 raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000699 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200700 return struct.unpack('I', s)[0] & TIOCM_DSR != 0
cliechtid6bf52c2003-10-01 02:28:12 +0000701
Chris Liechtief1fe252015-08-27 23:25:21 +0200702 @property
703 def ri(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000704 """Read terminal status line: Ring Indicator"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200705 if not self.is_open:
706 raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000707 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200708 return struct.unpack('I', s)[0] & TIOCM_RI != 0
cliechti89b4af12002-02-12 23:24:41 +0000709
Chris Liechtief1fe252015-08-27 23:25:21 +0200710 @property
711 def cd(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000712 """Read terminal status line: Carrier Detect"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200713 if not self.is_open:
714 raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000715 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200716 return struct.unpack('I', s)[0] & TIOCM_CD != 0
cliechti89b4af12002-02-12 23:24:41 +0000717
cliechtia30a8a02003-10-05 12:28:13 +0000718 # - - platform specific - - - -
719
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200720 @property
721 def out_waiting(self):
722 """Return the number of bytes currently in the output buffer."""
Chris Liechti11465c82015-08-04 15:55:22 +0200723 #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str)
cliechti28b8fd02011-12-28 21:39:42 +0000724 s = fcntl.ioctl(self.fd, TIOCOUTQ, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200725 return struct.unpack('I', s)[0]
cliechti28b8fd02011-12-28 21:39:42 +0000726
cliechti8753bbc2005-01-15 20:32:51 +0000727 def fileno(self):
cliechti2f0f8a32011-12-28 22:10:00 +0000728 """\
729 For easier use of the serial port instance with select.
730 WARNING: this function is not portable to different platforms!
731 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200732 if not self.is_open:
733 raise portNotOpenError
cliechti8753bbc2005-01-15 20:32:51 +0000734 return self.fd
cliechti89b4af12002-02-12 23:24:41 +0000735
Chris Liechti518b0d32015-08-30 02:20:39 +0200736 def set_input_flow_control(self, enable=True):
cliechti2f0f8a32011-12-28 22:10:00 +0000737 """\
738 Manually control flow - when software flow control is enabled.
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200739 This will send XON (true) or XOFF (false) to the other device.
cliechti2f0f8a32011-12-28 22:10:00 +0000740 WARNING: this function is not portable to different platforms!
741 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200742 if not self.is_open:
743 raise portNotOpenError
cliechti4a601342011-12-29 02:22:17 +0000744 if enable:
Chris Liechti11465c82015-08-04 15:55:22 +0200745 termios.tcflow(self.fd, termios.TCION)
cliechti57e48a62009-08-03 22:29:58 +0000746 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200747 termios.tcflow(self.fd, termios.TCIOFF)
cliechti57e48a62009-08-03 22:29:58 +0000748
Chris Liechti518b0d32015-08-30 02:20:39 +0200749 def set_output_flow_control(self, enable=True):
cliechti2f0f8a32011-12-28 22:10:00 +0000750 """\
751 Manually control flow of outgoing data - when hardware or software flow
752 control is enabled.
753 WARNING: this function is not portable to different platforms!
754 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200755 if not self.is_open:
756 raise portNotOpenError
cliechti2f0f8a32011-12-28 22:10:00 +0000757 if enable:
Chris Liechti11465c82015-08-04 15:55:22 +0200758 termios.tcflow(self.fd, termios.TCOON)
cliechti2f0f8a32011-12-28 22:10:00 +0000759 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200760 termios.tcflow(self.fd, termios.TCOOFF)
cliechti2f0f8a32011-12-28 22:10:00 +0000761
Chris Liechti59848422016-06-04 22:28:14 +0200762 def nonblocking(self):
763 """DEPRECATED - has no use"""
764 import warnings
765 warnings.warn("nonblocking() has no effect, already nonblocking", DeprecationWarning)
766
cliechtif81362e2009-07-25 03:44:33 +0000767
cliechtia9a093e2010-01-02 03:05:08 +0000768class PosixPollSerial(Serial):
cliechti7d448562014-08-03 21:57:45 +0000769 """\
cliechtif0a81d42014-08-04 14:03:53 +0000770 Poll based read implementation. Not all systems support poll properly.
771 However this one has better handling of errors, such as a device
cliechti7d448562014-08-03 21:57:45 +0000772 disconnecting while it's in use (e.g. USB-serial unplugged).
773 """
cliechtia9a093e2010-01-02 03:05:08 +0000774
775 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000776 """\
777 Read size bytes from the serial port. If a timeout is set it may
778 return less characters as requested. With no timeout it will block
779 until the requested number of bytes is read.
780 """
Chris Liechtiacac2362016-03-29 22:37:48 +0200781 if not self.is_open:
Chris Liechti033f17c2015-08-30 21:28:04 +0200782 raise portNotOpenError
cliechtia9a093e2010-01-02 03:05:08 +0000783 read = bytearray()
Chris Liechtia5726382017-08-24 23:43:23 +0200784 timeout = Timeout(self._timeout)
cliechtia9a093e2010-01-02 03:05:08 +0000785 poll = select.poll()
Chris Liechti033f17c2015-08-30 21:28:04 +0200786 poll.register(self.fd, select.POLLIN | select.POLLERR | select.POLLHUP | select.POLLNVAL)
Chris Liechtia5726382017-08-24 23:43:23 +0200787 poll.register(self.pipe_abort_read_r, select.POLLIN | select.POLLERR | select.POLLHUP | select.POLLNVAL)
cliechtia9a093e2010-01-02 03:05:08 +0000788 if size > 0:
789 while len(read) < size:
790 # print "\tread(): size",size, "have", len(read) #debug
791 # wait until device becomes ready to read (or something fails)
Chris Liechtia5726382017-08-24 23:43:23 +0200792 for fd, event in poll.poll(None if timeout.is_infinite else (timeout.time_left() * 1000)):
793 if fd == self.pipe_abort_read_r:
794 break
Chris Liechti033f17c2015-08-30 21:28:04 +0200795 if event & (select.POLLERR | select.POLLHUP | select.POLLNVAL):
cliechtia9a093e2010-01-02 03:05:08 +0000796 raise SerialException('device reports error (poll)')
797 # we don't care if it is select.POLLIN or timeout, that's
798 # handled below
Chris Liechtia5726382017-08-24 23:43:23 +0200799 if fd == self.pipe_abort_read_r:
800 os.read(self.pipe_abort_read_r, 1000)
801 break
cliechtia9a093e2010-01-02 03:05:08 +0000802 buf = os.read(self.fd, size - len(read))
803 read.extend(buf)
Chris Liechtia5726382017-08-24 23:43:23 +0200804 if timeout.expired() \
805 or (self._inter_byte_timeout is not None and self._inter_byte_timeout > 0) and not buf:
cliechtia9a093e2010-01-02 03:05:08 +0000806 break # early abort on timeout
807 return bytes(read)
808
cliechtif81362e2009-07-25 03:44:33 +0000809
Chris Liechti4cf54702015-10-18 00:21:56 +0200810class VTIMESerial(Serial):
811 """\
812 Implement timeout using vtime of tty device instead of using select.
813 This means that no inter character timeout can be specified and that
814 the error handling is degraded.
815
816 Overall timeout is disabled when inter-character timeout is used.
Chris Liechti22d39002018-05-08 03:39:20 +0200817
818 Note that this implementation does NOT support cancel_read(), it will
819 just ignore that.
Chris Liechti4cf54702015-10-18 00:21:56 +0200820 """
821
Chris Liechti94284702015-11-15 01:21:48 +0100822 def _reconfigure_port(self, force_update=True):
Chris Liechti4cf54702015-10-18 00:21:56 +0200823 """Set communication parameters on opened port."""
824 super(VTIMESerial, self)._reconfigure_port()
Chris Liechtid6bcaaf2016-02-01 22:55:26 +0100825 fcntl.fcntl(self.fd, fcntl.F_SETFL, 0) # clear O_NONBLOCK
Chris Liechti4cf54702015-10-18 00:21:56 +0200826
827 if self._inter_byte_timeout is not None:
828 vmin = 1
829 vtime = int(self._inter_byte_timeout * 10)
Chris Liechti3ec9c412016-08-08 01:06:46 +0200830 elif self._timeout is None:
831 vmin = 1
832 vtime = 0
Chris Liechti4cf54702015-10-18 00:21:56 +0200833 else:
834 vmin = 0
835 vtime = int(self._timeout * 10)
836 try:
837 orig_attr = termios.tcgetattr(self.fd)
838 iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
839 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 +0100840 raise serial.SerialException("Could not configure port: {}".format(msg))
Chris Liechti4cf54702015-10-18 00:21:56 +0200841
842 if vtime < 0 or vtime > 255:
Chris Liechti984c5c52016-02-15 23:48:45 +0100843 raise ValueError('Invalid vtime: {!r}'.format(vtime))
Chris Liechti4cf54702015-10-18 00:21:56 +0200844 cc[termios.VTIME] = vtime
845 cc[termios.VMIN] = vmin
846
847 termios.tcsetattr(
848 self.fd,
849 termios.TCSANOW,
850 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
851
Chris Liechti4cf54702015-10-18 00:21:56 +0200852 def read(self, size=1):
853 """\
854 Read size bytes from the serial port. If a timeout is set it may
855 return less characters as requested. With no timeout it will block
856 until the requested number of bytes is read.
857 """
858 if not self.is_open:
859 raise portNotOpenError
860 read = bytearray()
861 while len(read) < size:
862 buf = os.read(self.fd, size - len(read))
863 if not buf:
864 break
865 read.extend(buf)
866 return bytes(read)
Chris Liechti3ec9c412016-08-08 01:06:46 +0200867
868 # hack to make hasattr return false
869 cancel_read = property()