blob: 0bf3df55f9334a42976922d813636caa644d5efd [file] [log] [blame]
cliechti89b4af12002-02-12 23:24:41 +00001#!/usr/bin/env python
cliechti58b481c2009-02-16 20:42:32 +00002#
Chris Liechti3e02f702015-12-16 23:06:04 +01003# backend for serial IO for POSIX compatible systems, like Linux, OSX
cliechti89b4af12002-02-12 23:24:41 +00004#
Chris Liechti3e02f702015-12-16 23:06:04 +01005# This file is part of pySerial. https://github.com/pyserial/pyserial
Chris Liechtie13d0f62016-04-25 23:30:44 +02006# (C) 2001-2016 Chris Liechti <cliechti@gmx.net>
Chris Liechtifbdd8a02015-08-09 02:37:45 +02007#
8# SPDX-License-Identifier: BSD-3-Clause
cliechti89b4af12002-02-12 23:24:41 +00009#
cliechtic54b2c82008-06-21 01:59:08 +000010# parts based on code from Grant B. Edwards <grante@visi.com>:
cliechti89b4af12002-02-12 23:24:41 +000011# ftp://ftp.visi.com/users/grante/python/PosixSerial.py
cliechti53c9fd42009-07-23 23:51:51 +000012#
cliechti89b4af12002-02-12 23:24:41 +000013# references: http://www.easysw.com/~mike/serial/serial.html
14
Chris Liechtie13d0f62016-04-25 23:30:44 +020015# Collection of port names (was previously used by number_to_device which was
16# removed.
17# - Linux /dev/ttyS%d (confirmed)
18# - cygwin/win32 /dev/com%d (confirmed)
19# - openbsd (OpenBSD) /dev/cua%02d
20# - bsd*, freebsd* /dev/cuad%d
21# - darwin (OS X) /dev/cuad%d
22# - netbsd /dev/dty%02d (NetBSD 1.6 testing by Erk)
23# - irix (IRIX) /dev/ttyf%d (partially tested) names depending on flow control
24# - hp (HP-UX) /dev/tty%dp0 (not tested)
25# - sunos (Solaris/SunOS) /dev/tty%c (letters, 'a'..'z') (confirmed)
26# - aix (AIX) /dev/tty%d
27
28
Chris Liechti9eaa40c2016-02-12 23:32:59 +010029# pylint: disable=abstract-method
Chris Liechti33f0ec52015-08-06 16:37:21 +020030import errno
31import fcntl
Chris Liechti33f0ec52015-08-06 16:37:21 +020032import os
33import select
34import struct
35import sys
36import termios
37import time
Chris Liechti033f17c2015-08-30 21:28:04 +020038
39import serial
40from serial.serialutil import SerialBase, SerialException, to_bytes, portNotOpenError, writeTimeoutError
cliechti89b4af12002-02-12 23:24:41 +000041
cliechti89b4af12002-02-12 23:24:41 +000042
Chris Liechtid6847af2015-08-06 17:54:30 +020043class PlatformSpecificBase(object):
44 BAUDRATE_CONSTANTS = {}
cliechti89b4af12002-02-12 23:24:41 +000045
Chris Liechtid6847af2015-08-06 17:54:30 +020046 def _set_special_baudrate(self, baudrate):
47 raise NotImplementedError('non-standard baudrates are not supported on this platform')
48
49 def _set_rs485_mode(self, rs485_settings):
50 raise NotImplementedError('RS485 not supported on this platform')
51
52# try to detect the OS so that a device can be selected...
53# this code block should supply a device() and set_special_baudrate() function
54# for the platform
55plat = sys.platform.lower()
56
Chris Liechtiba45c522016-02-06 23:53:23 +010057if plat[:5] == 'linux': # Linux (confirmed) # noqa
Chris Liechtid6847af2015-08-06 17:54:30 +020058 import array
59
60 # baudrate ioctls
61 TCGETS2 = 0x802C542A
62 TCSETS2 = 0x402C542B
63 BOTHER = 0o010000
64
65 # RS485 ioctls
66 TIOCGRS485 = 0x542E
67 TIOCSRS485 = 0x542F
Chris Liechti033f17c2015-08-30 21:28:04 +020068 SER_RS485_ENABLED = 0b00000001
69 SER_RS485_RTS_ON_SEND = 0b00000010
Chris Liechtid6847af2015-08-06 17:54:30 +020070 SER_RS485_RTS_AFTER_SEND = 0b00000100
Chris Liechti033f17c2015-08-30 21:28:04 +020071 SER_RS485_RX_DURING_TX = 0b00010000
Chris Liechtid6847af2015-08-06 17:54:30 +020072
73 class PlatformSpecific(PlatformSpecificBase):
74 BAUDRATE_CONSTANTS = {
75 0: 0o000000, # hang up
76 50: 0o000001,
77 75: 0o000002,
78 110: 0o000003,
79 134: 0o000004,
80 150: 0o000005,
81 200: 0o000006,
82 300: 0o000007,
83 600: 0o000010,
84 1200: 0o000011,
85 1800: 0o000012,
86 2400: 0o000013,
87 4800: 0o000014,
88 9600: 0o000015,
89 19200: 0o000016,
90 38400: 0o000017,
91 57600: 0o010001,
92 115200: 0o010002,
93 230400: 0o010003,
94 460800: 0o010004,
95 500000: 0o010005,
96 576000: 0o010006,
97 921600: 0o010007,
98 1000000: 0o010010,
99 1152000: 0o010011,
100 1500000: 0o010012,
101 2000000: 0o010013,
102 2500000: 0o010014,
103 3000000: 0o010015,
104 3500000: 0o010016,
105 4000000: 0o010017
106 }
107
Chris Liechtid6847af2015-08-06 17:54:30 +0200108 def _set_special_baudrate(self, baudrate):
109 # right size is 44 on x86_64, allow for some growth
110 buf = array.array('i', [0] * 64)
111 try:
112 # get serial_struct
113 fcntl.ioctl(self.fd, TCGETS2, buf)
114 # set custom speed
115 buf[2] &= ~termios.CBAUD
116 buf[2] |= BOTHER
117 buf[9] = buf[10] = baudrate
118
119 # set serial_struct
Chris Liechti033f17c2015-08-30 21:28:04 +0200120 fcntl.ioctl(self.fd, TCSETS2, buf)
Chris Liechtid6847af2015-08-06 17:54:30 +0200121 except IOError as e:
Chris Liechti984c5c52016-02-15 23:48:45 +0100122 raise ValueError('Failed to set custom baud rate ({}): {}'.format(baudrate, e))
Chris Liechtid6847af2015-08-06 17:54:30 +0200123
124 def _set_rs485_mode(self, rs485_settings):
Chris Liechti033f17c2015-08-30 21:28:04 +0200125 buf = array.array('i', [0] * 8) # flags, delaytx, delayrx, padding
Chris Liechtid6847af2015-08-06 17:54:30 +0200126 try:
127 fcntl.ioctl(self.fd, TIOCGRS485, buf)
Chris Liechti7a554462016-03-24 21:17:22 +0100128 buf[0] |= SER_RS485_ENABLED
Chris Liechtid6847af2015-08-06 17:54:30 +0200129 if rs485_settings is not None:
130 if rs485_settings.loopback:
131 buf[0] |= SER_RS485_RX_DURING_TX
132 else:
133 buf[0] &= ~SER_RS485_RX_DURING_TX
134 if rs485_settings.rts_level_for_tx:
135 buf[0] |= SER_RS485_RTS_ON_SEND
136 else:
137 buf[0] &= ~SER_RS485_RTS_ON_SEND
138 if rs485_settings.rts_level_for_rx:
139 buf[0] |= SER_RS485_RTS_AFTER_SEND
140 else:
141 buf[0] &= ~SER_RS485_RTS_AFTER_SEND
Chris Liechti279201b2016-06-09 20:27:05 +0200142 if rs485_settings.delay_before_tx is not None:
143 buf[1] = int(rs485_settings.delay_before_tx * 1000)
144 if rs485_settings.delay_before_rx is not None:
145 buf[2] = int(rs485_settings.delay_before_rx * 1000)
Chris Liechtid6847af2015-08-06 17:54:30 +0200146 else:
147 buf[0] = 0 # clear SER_RS485_ENABLED
Chris Liechti033f17c2015-08-30 21:28:04 +0200148 fcntl.ioctl(self.fd, TIOCSRS485, buf)
Chris Liechtid6847af2015-08-06 17:54:30 +0200149 except IOError as e:
Chris Liechti984c5c52016-02-15 23:48:45 +0100150 raise ValueError('Failed to set RS485 mode: {}'.format(e))
Chris Liechtid6847af2015-08-06 17:54:30 +0200151
152
153elif plat == 'cygwin': # cygwin/win32 (confirmed)
154
155 class PlatformSpecific(PlatformSpecificBase):
156 BAUDRATE_CONSTANTS = {
157 128000: 0x01003,
158 256000: 0x01005,
159 500000: 0x01007,
160 576000: 0x01008,
161 921600: 0x01009,
162 1000000: 0x0100a,
163 1152000: 0x0100b,
164 1500000: 0x0100c,
165 2000000: 0x0100d,
166 2500000: 0x0100e,
167 3000000: 0x0100f
168 }
169
Chris Liechtid6847af2015-08-06 17:54:30 +0200170
171elif plat[:6] == 'darwin': # OS X
172 import array
Chris Liechti033f17c2015-08-30 21:28:04 +0200173 IOSSIOSPEED = 0x80045402 # _IOW('T', 2, speed_t)
Chris Liechtid6847af2015-08-06 17:54:30 +0200174
175 class PlatformSpecific(PlatformSpecificBase):
Chris Liechtid6847af2015-08-06 17:54:30 +0200176 osx_version = os.uname()[2].split('.')
177 # Tiger or above can support arbitrary serial speeds
178 if int(osx_version[0]) >= 8:
179 def _set_special_baudrate(self, baudrate):
180 # use IOKit-specific call to set up high speeds
181 buf = array.array('i', [baudrate])
182 fcntl.ioctl(self.fd, IOSSIOSPEED, buf, 1)
183
Chris Liechtid6847af2015-08-06 17:54:30 +0200184else:
185 class PlatformSpecific(PlatformSpecificBase):
186 pass
cliechti89b4af12002-02-12 23:24:41 +0000187
cliechti89b4af12002-02-12 23:24:41 +0000188
cliechti58b481c2009-02-16 20:42:32 +0000189# load some constants for later use.
Chris Liechti11465c82015-08-04 15:55:22 +0200190# try to use values from termios, use defaults from linux otherwise
Chris Liechti033f17c2015-08-30 21:28:04 +0200191TIOCMGET = getattr(termios, 'TIOCMGET', 0x5415)
192TIOCMBIS = getattr(termios, 'TIOCMBIS', 0x5416)
193TIOCMBIC = getattr(termios, 'TIOCMBIC', 0x5417)
194TIOCMSET = getattr(termios, 'TIOCMSET', 0x5418)
cliechti89b4af12002-02-12 23:24:41 +0000195
Chris Liechti033f17c2015-08-30 21:28:04 +0200196# TIOCM_LE = getattr(termios, 'TIOCM_LE', 0x001)
Chris Liechtid6847af2015-08-06 17:54:30 +0200197TIOCM_DTR = getattr(termios, 'TIOCM_DTR', 0x002)
198TIOCM_RTS = getattr(termios, 'TIOCM_RTS', 0x004)
Chris Liechti033f17c2015-08-30 21:28:04 +0200199# TIOCM_ST = getattr(termios, 'TIOCM_ST', 0x008)
200# TIOCM_SR = getattr(termios, 'TIOCM_SR', 0x010)
cliechti89b4af12002-02-12 23:24:41 +0000201
Chris Liechtid6847af2015-08-06 17:54:30 +0200202TIOCM_CTS = getattr(termios, 'TIOCM_CTS', 0x020)
203TIOCM_CAR = getattr(termios, 'TIOCM_CAR', 0x040)
204TIOCM_RNG = getattr(termios, 'TIOCM_RNG', 0x080)
205TIOCM_DSR = getattr(termios, 'TIOCM_DSR', 0x100)
Chris Liechti033f17c2015-08-30 21:28:04 +0200206TIOCM_CD = getattr(termios, 'TIOCM_CD', TIOCM_CAR)
207TIOCM_RI = getattr(termios, 'TIOCM_RI', TIOCM_RNG)
208# TIOCM_OUT1 = getattr(termios, 'TIOCM_OUT1', 0x2000)
209# TIOCM_OUT2 = getattr(termios, 'TIOCM_OUT2', 0x4000)
Chris Liechti11465c82015-08-04 15:55:22 +0200210if hasattr(termios, 'TIOCINQ'):
211 TIOCINQ = termios.TIOCINQ
cliechti28b8fd02011-12-28 21:39:42 +0000212else:
Chris Liechtid6847af2015-08-06 17:54:30 +0200213 TIOCINQ = getattr(termios, 'FIONREAD', 0x541B)
Chris Liechti033f17c2015-08-30 21:28:04 +0200214TIOCOUTQ = getattr(termios, 'TIOCOUTQ', 0x5411)
cliechti89b4af12002-02-12 23:24:41 +0000215
216TIOCM_zero_str = struct.pack('I', 0)
217TIOCM_RTS_str = struct.pack('I', TIOCM_RTS)
218TIOCM_DTR_str = struct.pack('I', TIOCM_DTR)
219
Chris Liechti033f17c2015-08-30 21:28:04 +0200220TIOCSBRK = getattr(termios, 'TIOCSBRK', 0x5427)
221TIOCCBRK = getattr(termios, 'TIOCCBRK', 0x5428)
cliechti997b63c2008-06-21 00:09:31 +0000222
Chris Liechti033f17c2015-08-30 21:28:04 +0200223CMSPAR = 0o10000000000 # Use "stick" (mark/space) parity
cliechtiaec27ab2014-07-31 22:21:24 +0000224
cliechti89b4af12002-02-12 23:24:41 +0000225
Chris Liechtief6b7b42015-08-06 22:19:26 +0200226class Serial(SerialBase, PlatformSpecific):
cliechti7d448562014-08-03 21:57:45 +0000227 """\
Chris Liechti033f17c2015-08-30 21:28:04 +0200228 Serial port class POSIX implementation. Serial port configuration is
cliechtid6bf52c2003-10-01 02:28:12 +0000229 done with termios and fcntl. Runs on Linux and many other Un*x like
cliechtif0a81d42014-08-04 14:03:53 +0000230 systems.
231 """
cliechtid6bf52c2003-10-01 02:28:12 +0000232
233 def open(self):
cliechti7d448562014-08-03 21:57:45 +0000234 """\
235 Open port with current settings. This may throw a SerialException
236 if the port cannot be opened."""
cliechtid6bf52c2003-10-01 02:28:12 +0000237 if self._port is None:
238 raise SerialException("Port must be configured before it can be used.")
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200239 if self.is_open:
cliechti02ef43a2011-03-24 23:33:12 +0000240 raise SerialException("Port is already open.")
241 self.fd = None
cliechti58b481c2009-02-16 20:42:32 +0000242 # open
cliechti4616bf12002-04-08 23:13:14 +0000243 try:
Chris Liechti033f17c2015-08-30 21:28:04 +0200244 self.fd = os.open(self.portstr, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK)
Chris Liechti68340d72015-08-03 14:15:48 +0200245 except OSError as msg:
cliechti4616bf12002-04-08 23:13:14 +0000246 self.fd = None
Chris Liechti984c5c52016-02-15 23:48:45 +0100247 raise SerialException(msg.errno, "could not open port {}: {}".format(self._port, msg))
Chris Liechti11465c82015-08-04 15:55:22 +0200248 #~ fcntl.fcntl(self.fd, fcntl.F_SETFL, 0) # set blocking
cliechti58b481c2009-02-16 20:42:32 +0000249
cliechtib2f5fc82006-10-20 00:09:07 +0000250 try:
Chris Liechti94284702015-11-15 01:21:48 +0100251 self._reconfigure_port(force_update=True)
cliechtib2f5fc82006-10-20 00:09:07 +0000252 except:
cliechti2750b832009-07-28 00:13:52 +0000253 try:
254 os.close(self.fd)
255 except:
256 # ignore any exception when closing the port
257 # also to keep original exception that happened when setting up
258 pass
cliechtib2f5fc82006-10-20 00:09:07 +0000259 self.fd = None
cliechtif0a4f0f2009-07-21 21:12:37 +0000260 raise
cliechtib2f5fc82006-10-20 00:09:07 +0000261 else:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200262 self.is_open = True
Chris Liechtif2fdeb92016-05-07 23:57:50 +0200263 try:
264 if not self._dsrdtr:
265 self._update_dtr_state()
266 if not self._rtscts:
267 self._update_rts_state()
268 except IOError as e:
269 if e.errno == 22: # ignore Invalid argument
270 pass
271 else:
272 raise
Chris Liechtief1fe252015-08-27 23:25:21 +0200273 self.reset_input_buffer()
Chris Liechti42ab2b42016-05-15 23:35:05 +0200274 self.pipe_abort_read_r, self.pipe_abort_read_w = os.pipe()
Chris Liechti13949c62016-05-16 22:45:38 +0200275 self.pipe_abort_write_r, self.pipe_abort_write_w = os.pipe()
Chris Liechti68cecce2016-06-03 23:52:34 +0200276 fcntl.fcntl(self.pipe_abort_read_r, fcntl.F_SETFL, os.O_NONBLOCK)
277 fcntl.fcntl(self.pipe_abort_write_r, fcntl.F_SETFL, os.O_NONBLOCK)
cliechti58b481c2009-02-16 20:42:32 +0000278
Chris Liechti94284702015-11-15 01:21:48 +0100279 def _reconfigure_port(self, force_update=False):
cliechtib2f5fc82006-10-20 00:09:07 +0000280 """Set communication parameters on opened port."""
cliechtic6178262004-03-22 22:04:52 +0000281 if self.fd is None:
cliechtia9a093e2010-01-02 03:05:08 +0000282 raise SerialException("Can only operate on a valid file descriptor")
cliechtie8c45422008-06-20 23:23:14 +0000283 custom_baud = None
cliechti58b481c2009-02-16 20:42:32 +0000284
cliechti2750b832009-07-28 00:13:52 +0000285 vmin = vtime = 0 # timeout is done via select
Chris Liechti518b0d32015-08-30 02:20:39 +0200286 if self._inter_byte_timeout is not None:
cliechti679bfa62008-06-20 23:58:15 +0000287 vmin = 1
Chris Liechti518b0d32015-08-30 02:20:39 +0200288 vtime = int(self._inter_byte_timeout * 10)
cliechti6ce7ab12002-11-07 02:15:00 +0000289 try:
cliechti4d0af5e2011-08-05 02:18:16 +0000290 orig_attr = termios.tcgetattr(self.fd)
291 iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
Chris Liechti68340d72015-08-03 14:15:48 +0200292 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 +0100293 raise SerialException("Could not configure port: {}".format(msg))
cliechti58b481c2009-02-16 20:42:32 +0000294 # set up raw mode / no echo / binary
Chris Liechti033f17c2015-08-30 21:28:04 +0200295 cflag |= (termios.CLOCAL | termios.CREAD)
296 lflag &= ~(termios.ICANON | termios.ECHO | termios.ECHOE |
297 termios.ECHOK | termios.ECHONL |
298 termios.ISIG | termios.IEXTEN) # |termios.ECHOPRT
299 for flag in ('ECHOCTL', 'ECHOKE'): # netbsd workaround for Erk
Chris Liechti11465c82015-08-04 15:55:22 +0200300 if hasattr(termios, flag):
301 lflag &= ~getattr(termios, flag)
cliechti58b481c2009-02-16 20:42:32 +0000302
Chris Liechti033f17c2015-08-30 21:28:04 +0200303 oflag &= ~(termios.OPOST | termios.ONLCR | termios.OCRNL)
304 iflag &= ~(termios.INLCR | termios.IGNCR | termios.ICRNL | termios.IGNBRK)
Chris Liechti11465c82015-08-04 15:55:22 +0200305 if hasattr(termios, 'IUCLC'):
306 iflag &= ~termios.IUCLC
307 if hasattr(termios, 'PARMRK'):
308 iflag &= ~termios.PARMRK
cliechti58b481c2009-02-16 20:42:32 +0000309
cliechtif0a4f0f2009-07-21 21:12:37 +0000310 # setup baud rate
cliechti89b4af12002-02-12 23:24:41 +0000311 try:
Chris Liechti984c5c52016-02-15 23:48:45 +0100312 ispeed = ospeed = getattr(termios, 'B{}'.format(self._baudrate))
cliechti895e8302004-04-20 02:40:28 +0000313 except AttributeError:
cliechtif1559d02007-11-08 23:43:58 +0000314 try:
Chris Liechtid6847af2015-08-06 17:54:30 +0200315 ispeed = ospeed = self.BAUDRATE_CONSTANTS[self._baudrate]
cliechtif1559d02007-11-08 23:43:58 +0000316 except KeyError:
cliechtie8c45422008-06-20 23:23:14 +0000317 #~ raise ValueError('Invalid baud rate: %r' % self._baudrate)
cliechtif0a4f0f2009-07-21 21:12:37 +0000318 # may need custom baud rate, it isn't in our list.
Chris Liechti11465c82015-08-04 15:55:22 +0200319 ispeed = ospeed = getattr(termios, 'B38400')
cliechtif0a4f0f2009-07-21 21:12:37 +0000320 try:
Chris Liechti033f17c2015-08-30 21:28:04 +0200321 custom_baud = int(self._baudrate) # store for later
cliechtif0a4f0f2009-07-21 21:12:37 +0000322 except ValueError:
Chris Liechti984c5c52016-02-15 23:48:45 +0100323 raise ValueError('Invalid baud rate: {!r}'.format(self._baudrate))
cliechtif0a4f0f2009-07-21 21:12:37 +0000324 else:
325 if custom_baud < 0:
Chris Liechti984c5c52016-02-15 23:48:45 +0100326 raise ValueError('Invalid baud rate: {!r}'.format(self._baudrate))
cliechti58b481c2009-02-16 20:42:32 +0000327
328 # setup char len
Chris Liechti11465c82015-08-04 15:55:22 +0200329 cflag &= ~termios.CSIZE
cliechtid6bf52c2003-10-01 02:28:12 +0000330 if self._bytesize == 8:
Chris Liechti11465c82015-08-04 15:55:22 +0200331 cflag |= termios.CS8
cliechtid6bf52c2003-10-01 02:28:12 +0000332 elif self._bytesize == 7:
Chris Liechti11465c82015-08-04 15:55:22 +0200333 cflag |= termios.CS7
cliechtid6bf52c2003-10-01 02:28:12 +0000334 elif self._bytesize == 6:
Chris Liechti11465c82015-08-04 15:55:22 +0200335 cflag |= termios.CS6
cliechtid6bf52c2003-10-01 02:28:12 +0000336 elif self._bytesize == 5:
Chris Liechti11465c82015-08-04 15:55:22 +0200337 cflag |= termios.CS5
cliechti89b4af12002-02-12 23:24:41 +0000338 else:
Chris Liechti984c5c52016-02-15 23:48:45 +0100339 raise ValueError('Invalid char len: {!r}'.format(self._bytesize))
cliechtif0a81d42014-08-04 14:03:53 +0000340 # setup stop bits
Chris Liechti033f17c2015-08-30 21:28:04 +0200341 if self._stopbits == serial.STOPBITS_ONE:
Chris Liechti11465c82015-08-04 15:55:22 +0200342 cflag &= ~(termios.CSTOPB)
Chris Liechti033f17c2015-08-30 21:28:04 +0200343 elif self._stopbits == serial.STOPBITS_ONE_POINT_FIVE:
344 cflag |= (termios.CSTOPB) # XXX same as TWO.. there is no POSIX support for 1.5
345 elif self._stopbits == serial.STOPBITS_TWO:
346 cflag |= (termios.CSTOPB)
cliechti89b4af12002-02-12 23:24:41 +0000347 else:
Chris Liechti984c5c52016-02-15 23:48:45 +0100348 raise ValueError('Invalid stop bit specification: {!r}'.format(self._stopbits))
cliechti58b481c2009-02-16 20:42:32 +0000349 # setup parity
Chris Liechti033f17c2015-08-30 21:28:04 +0200350 iflag &= ~(termios.INPCK | termios.ISTRIP)
351 if self._parity == serial.PARITY_NONE:
352 cflag &= ~(termios.PARENB | termios.PARODD)
353 elif self._parity == serial.PARITY_EVEN:
Chris Liechti11465c82015-08-04 15:55:22 +0200354 cflag &= ~(termios.PARODD)
Chris Liechti033f17c2015-08-30 21:28:04 +0200355 cflag |= (termios.PARENB)
356 elif self._parity == serial.PARITY_ODD:
357 cflag |= (termios.PARENB | termios.PARODD)
358 elif self._parity == serial.PARITY_MARK and plat[:5] == 'linux':
359 cflag |= (termios.PARENB | CMSPAR | termios.PARODD)
360 elif self._parity == serial.PARITY_SPACE and plat[:5] == 'linux':
361 cflag |= (termios.PARENB | CMSPAR)
Chris Liechti11465c82015-08-04 15:55:22 +0200362 cflag &= ~(termios.PARODD)
cliechti89b4af12002-02-12 23:24:41 +0000363 else:
Chris Liechti984c5c52016-02-15 23:48:45 +0100364 raise ValueError('Invalid parity: {!r}'.format(self._parity))
cliechti58b481c2009-02-16 20:42:32 +0000365 # setup flow control
366 # xonxoff
Chris Liechti11465c82015-08-04 15:55:22 +0200367 if hasattr(termios, 'IXANY'):
cliechtid6bf52c2003-10-01 02:28:12 +0000368 if self._xonxoff:
Chris Liechti033f17c2015-08-30 21:28:04 +0200369 iflag |= (termios.IXON | termios.IXOFF) # |termios.IXANY)
cliechti89b4af12002-02-12 23:24:41 +0000370 else:
Chris Liechti033f17c2015-08-30 21:28:04 +0200371 iflag &= ~(termios.IXON | termios.IXOFF | termios.IXANY)
cliechti89b4af12002-02-12 23:24:41 +0000372 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000373 if self._xonxoff:
Chris Liechti033f17c2015-08-30 21:28:04 +0200374 iflag |= (termios.IXON | termios.IXOFF)
cliechti89b4af12002-02-12 23:24:41 +0000375 else:
Chris Liechti033f17c2015-08-30 21:28:04 +0200376 iflag &= ~(termios.IXON | termios.IXOFF)
cliechti58b481c2009-02-16 20:42:32 +0000377 # rtscts
Chris Liechti11465c82015-08-04 15:55:22 +0200378 if hasattr(termios, 'CRTSCTS'):
cliechtid6bf52c2003-10-01 02:28:12 +0000379 if self._rtscts:
Chris Liechti033f17c2015-08-30 21:28:04 +0200380 cflag |= (termios.CRTSCTS)
cliechti89b4af12002-02-12 23:24:41 +0000381 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200382 cflag &= ~(termios.CRTSCTS)
383 elif hasattr(termios, 'CNEW_RTSCTS'): # try it with alternate constant name
cliechtid6bf52c2003-10-01 02:28:12 +0000384 if self._rtscts:
Chris Liechti033f17c2015-08-30 21:28:04 +0200385 cflag |= (termios.CNEW_RTSCTS)
cliechtid4743692002-04-08 22:39:53 +0000386 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200387 cflag &= ~(termios.CNEW_RTSCTS)
cliechti2750b832009-07-28 00:13:52 +0000388 # XXX should there be a warning if setting up rtscts (and xonxoff etc) fails??
cliechti58b481c2009-02-16 20:42:32 +0000389
390 # buffer
cliechtif0a81d42014-08-04 14:03:53 +0000391 # vmin "minimal number of characters to be read. 0 for non blocking"
cliechtid6bf52c2003-10-01 02:28:12 +0000392 if vmin < 0 or vmin > 255:
Chris Liechti984c5c52016-02-15 23:48:45 +0100393 raise ValueError('Invalid vmin: {!r}'.format(vmin))
Chris Liechti11465c82015-08-04 15:55:22 +0200394 cc[termios.VMIN] = vmin
cliechti58b481c2009-02-16 20:42:32 +0000395 # vtime
cliechtid6bf52c2003-10-01 02:28:12 +0000396 if vtime < 0 or vtime > 255:
Chris Liechti984c5c52016-02-15 23:48:45 +0100397 raise ValueError('Invalid vtime: {!r}'.format(vtime))
Chris Liechti11465c82015-08-04 15:55:22 +0200398 cc[termios.VTIME] = vtime
cliechti58b481c2009-02-16 20:42:32 +0000399 # activate settings
Chris Liechti94284702015-11-15 01:21:48 +0100400 if force_update or [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] != orig_attr:
Chris Liechti033f17c2015-08-30 21:28:04 +0200401 termios.tcsetattr(
Chris Liechti9eaa40c2016-02-12 23:32:59 +0100402 self.fd,
403 termios.TCSANOW,
404 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
cliechti58b481c2009-02-16 20:42:32 +0000405
cliechtie8c45422008-06-20 23:23:14 +0000406 # apply custom baud rate, if any
407 if custom_baud is not None:
Chris Liechtid6847af2015-08-06 17:54:30 +0200408 self._set_special_baudrate(custom_baud)
409
410 if self._rs485_mode is not None:
411 self._set_rs485_mode(self._rs485_mode)
cliechti89b4af12002-02-12 23:24:41 +0000412
413 def close(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000414 """Close port"""
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200415 if self.is_open:
cliechtic6178262004-03-22 22:04:52 +0000416 if self.fd is not None:
cliechtid6bf52c2003-10-01 02:28:12 +0000417 os.close(self.fd)
418 self.fd = None
Chris Liechtib658eac2016-05-22 20:51:44 +0200419 os.close(self.pipe_abort_read_w)
420 os.close(self.pipe_abort_read_r)
421 os.close(self.pipe_abort_write_w)
422 os.close(self.pipe_abort_write_r)
423 self.pipe_abort_read_r, self.pipe_abort_read_w = None, None
424 self.pipe_abort_write_r, self.pipe_abort_write_w = None, None
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200425 self.is_open = False
cliechtid6bf52c2003-10-01 02:28:12 +0000426
427 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechti95c62212002-03-04 22:17:53 +0000428
Chris Liechtief1fe252015-08-27 23:25:21 +0200429 @property
430 def in_waiting(self):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200431 """Return the number of bytes currently in the input buffer."""
Chris Liechti11465c82015-08-04 15:55:22 +0200432 #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str)
cliechtif5831e02002-12-05 23:15:27 +0000433 s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200434 return struct.unpack('I', s)[0]
cliechti89b4af12002-02-12 23:24:41 +0000435
cliechtia9a093e2010-01-02 03:05:08 +0000436 # select based implementation, proved to work on many systems
437 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000438 """\
439 Read size bytes from the serial port. If a timeout is set it may
440 return less characters as requested. With no timeout it will block
441 until the requested number of bytes is read.
442 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200443 if not self.is_open:
444 raise portNotOpenError
cliechtia9a093e2010-01-02 03:05:08 +0000445 read = bytearray()
Cristiano De Altic30622f2015-12-12 11:00:01 +0100446 timeout = self._timeout
cliechtia9a093e2010-01-02 03:05:08 +0000447 while len(read) < size:
cliechti8d744de2013-10-11 14:31:13 +0000448 try:
Cristiano De Altic30622f2015-12-12 11:00:01 +0100449 start_time = time.time()
Chris Liechti42ab2b42016-05-15 23:35:05 +0200450 ready, _, _ = select.select([self.fd, self.pipe_abort_read_r], [], [], timeout)
451 if self.pipe_abort_read_r in ready:
Chris Liechti68cecce2016-06-03 23:52:34 +0200452 os.read(self.pipe_abort_read_r, 1000)
Chris Liechti42ab2b42016-05-15 23:35:05 +0200453 break
cliechti8d744de2013-10-11 14:31:13 +0000454 # If select was used with a timeout, and the timeout occurs, it
455 # returns with empty lists -> thus abort read operation.
Chris Liechti033f17c2015-08-30 21:28:04 +0200456 # For timeout == 0 (non-blocking operation) also abort when
457 # there is nothing to read.
cliechti8d744de2013-10-11 14:31:13 +0000458 if not ready:
459 break # timeout
Chris Liechti033f17c2015-08-30 21:28:04 +0200460 buf = os.read(self.fd, size - len(read))
cliechti8d744de2013-10-11 14:31:13 +0000461 # read should always return some data as select reported it was
462 # ready to read when we get to this point.
463 if not buf:
464 # Disconnected devices, at least on Linux, show the
465 # behavior that they are always ready to read immediately
466 # but reading returns nothing.
Chris Liechti92df95a2016-02-09 23:30:37 +0100467 raise SerialException(
468 'device reports readiness to read but returned no data '
469 '(device disconnected or multiple access on port?)')
cliechti8d744de2013-10-11 14:31:13 +0000470 read.extend(buf)
Chris Liechti68340d72015-08-03 14:15:48 +0200471 except OSError as e:
Chris Liechti033f17c2015-08-30 21:28:04 +0200472 # this is for Python 3.x where select.error is a subclass of
473 # OSError ignore EAGAIN errors. all other errors are shown
nexcvon50ec2232016-05-24 15:48:46 +0800474 if e.errno != errno.EAGAIN and e.errno != errno.EINTR:
Chris Liechti984c5c52016-02-15 23:48:45 +0100475 raise SerialException('read failed: {}'.format(e))
Chris Liechti68340d72015-08-03 14:15:48 +0200476 except select.error as e:
cliechtic7cd7212014-08-03 21:34:38 +0000477 # this is for Python 2.x
cliechti8d744de2013-10-11 14:31:13 +0000478 # ignore EAGAIN errors. all other errors are shown
479 # see also http://www.python.org/dev/peps/pep-3151/#select
480 if e[0] != errno.EAGAIN:
Chris Liechti984c5c52016-02-15 23:48:45 +0100481 raise SerialException('read failed: {}'.format(e))
nexcvon50ec2232016-05-24 15:48:46 +0800482 if timeout is not None:
483 timeout -= time.time() - start_time
484 if timeout <= 0:
485 break
cliechtia9a093e2010-01-02 03:05:08 +0000486 return bytes(read)
cliechti89b4af12002-02-12 23:24:41 +0000487
Chris Liechti42ab2b42016-05-15 23:35:05 +0200488 def cancel_read(self):
489 os.write(self.pipe_abort_read_w, b"x")
490
Chris Liechti13949c62016-05-16 22:45:38 +0200491 def cancel_write(self):
492 os.write(self.pipe_abort_write_w, b"x")
493
cliechti4a567a02009-07-27 22:09:31 +0000494 def write(self, data):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200495 """Output the given byte string over the serial port."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200496 if not self.is_open:
497 raise portNotOpenError
cliechti38077122013-10-16 02:57:27 +0000498 d = to_bytes(data)
499 tx_len = len(d)
Robert Smallshire325a7382016-03-25 21:18:38 +0100500 timeout = self._write_timeout
501 if timeout and timeout > 0: # Avoid comparing None with zero
502 timeout += time.time()
cliechti9f7c2352013-10-11 01:13:46 +0000503 while tx_len > 0:
cliechti5d4d0bd2004-11-13 03:27:39 +0000504 try:
cliechti5d4d0bd2004-11-13 03:27:39 +0000505 n = os.write(self.fd, d)
Robert Smallshire325a7382016-03-25 21:18:38 +0100506 if timeout == 0:
507 # Zero timeout indicates non-blocking - simply return the
508 # number of bytes of data actually written
509 return n
510 elif timeout and timeout > 0: # Avoid comparing None with zero
cliechti3cf46d62009-08-07 00:19:57 +0000511 # when timeout is set, use select to wait for being ready
512 # with the time left as timeout
513 timeleft = timeout - time.time()
514 if timeleft < 0:
515 raise writeTimeoutError
Chris Liechti13949c62016-05-16 22:45:38 +0200516 abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], timeleft)
517 if abort:
Chris Liechti68cecce2016-06-03 23:52:34 +0200518 os.read(self.pipe_abort_write_r, 1000)
Chris Liechti13949c62016-05-16 22:45:38 +0200519 break
cliechti5d4d0bd2004-11-13 03:27:39 +0000520 if not ready:
521 raise writeTimeoutError
cliechti88c62442013-10-12 04:03:16 +0000522 else:
Robert Smallshire325a7382016-03-25 21:18:38 +0100523 assert timeout is None
cliechti88c62442013-10-12 04:03:16 +0000524 # wait for write operation
Chris Liechti13949c62016-05-16 22:45:38 +0200525 abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], None)
526 if abort:
527 os.read(self.pipe_abort_write_r, 1)
528 break
cliechti88c62442013-10-12 04:03:16 +0000529 if not ready:
530 raise SerialException('write failed (select)')
cliechti5d4d0bd2004-11-13 03:27:39 +0000531 d = d[n:]
cliechti9f7c2352013-10-11 01:13:46 +0000532 tx_len -= n
Chris Liechti675f7e12015-08-03 15:48:41 +0200533 except SerialException:
534 raise
Chris Liechti68340d72015-08-03 14:15:48 +0200535 except OSError as v:
cliechti5d4d0bd2004-11-13 03:27:39 +0000536 if v.errno != errno.EAGAIN:
Chris Liechti984c5c52016-02-15 23:48:45 +0100537 raise SerialException('write failed: {}'.format(v))
Chris Liechtic6362db2015-12-13 23:44:35 +0100538 # still calculate and check timeout
539 if timeout and timeout - time.time() < 0:
540 raise writeTimeoutError
cliechtif81362e2009-07-25 03:44:33 +0000541 return len(data)
cliechtid6bf52c2003-10-01 02:28:12 +0000542
cliechtia30a8a02003-10-05 12:28:13 +0000543 def flush(self):
cliechti7d448562014-08-03 21:57:45 +0000544 """\
545 Flush of file like objects. In this case, wait until all data
546 is written.
547 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200548 if not self.is_open:
549 raise portNotOpenError
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200550 termios.tcdrain(self.fd)
cliechtia30a8a02003-10-05 12:28:13 +0000551
Chris Liechtief1fe252015-08-27 23:25:21 +0200552 def reset_input_buffer(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000553 """Clear input buffer, discarding all that is in the buffer."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200554 if not self.is_open:
555 raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200556 termios.tcflush(self.fd, termios.TCIFLUSH)
cliechti89b4af12002-02-12 23:24:41 +0000557
Chris Liechtief1fe252015-08-27 23:25:21 +0200558 def reset_output_buffer(self):
cliechti7d448562014-08-03 21:57:45 +0000559 """\
560 Clear output buffer, aborting the current output and discarding all
561 that is in the buffer.
562 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200563 if not self.is_open:
564 raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200565 termios.tcflush(self.fd, termios.TCOFLUSH)
cliechti89b4af12002-02-12 23:24:41 +0000566
Chris Liechtief1fe252015-08-27 23:25:21 +0200567 def send_break(self, duration=0.25):
cliechti7d448562014-08-03 21:57:45 +0000568 """\
569 Send break condition. Timed, returns to idle state after given
570 duration.
571 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200572 if not self.is_open:
573 raise portNotOpenError
574 termios.tcsendbreak(self.fd, int(duration / 0.25))
cliechti89b4af12002-02-12 23:24:41 +0000575
Chris Liechtief1fe252015-08-27 23:25:21 +0200576 def _update_break_state(self):
cliechti7d448562014-08-03 21:57:45 +0000577 """\
578 Set break: Controls TXD. When active, no transmitting is possible.
579 """
Chris Liechtief1fe252015-08-27 23:25:21 +0200580 if self._break_state:
cliechti997b63c2008-06-21 00:09:31 +0000581 fcntl.ioctl(self.fd, TIOCSBRK)
582 else:
583 fcntl.ioctl(self.fd, TIOCCBRK)
584
Chris Liechtief1fe252015-08-27 23:25:21 +0200585 def _update_rts_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000586 """Set terminal status line: Request To Send"""
Chris Liechtif7534c82016-05-07 23:35:54 +0200587 if self._rts_state:
588 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_RTS_str)
589 else:
590 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_RTS_str)
cliechtid6bf52c2003-10-01 02:28:12 +0000591
Chris Liechtief1fe252015-08-27 23:25:21 +0200592 def _update_dtr_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000593 """Set terminal status line: Data Terminal Ready"""
Chris Liechtif7534c82016-05-07 23:35:54 +0200594 if self._dtr_state:
595 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str)
596 else:
597 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_DTR_str)
cliechtid6bf52c2003-10-01 02:28:12 +0000598
Chris Liechtief1fe252015-08-27 23:25:21 +0200599 @property
600 def cts(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000601 """Read terminal status line: Clear To Send"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200602 if not self.is_open:
603 raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000604 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200605 return struct.unpack('I', s)[0] & TIOCM_CTS != 0
cliechtid6bf52c2003-10-01 02:28:12 +0000606
Chris Liechtief1fe252015-08-27 23:25:21 +0200607 @property
608 def dsr(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000609 """Read terminal status line: Data Set Ready"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200610 if not self.is_open:
611 raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000612 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200613 return struct.unpack('I', s)[0] & TIOCM_DSR != 0
cliechtid6bf52c2003-10-01 02:28:12 +0000614
Chris Liechtief1fe252015-08-27 23:25:21 +0200615 @property
616 def ri(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000617 """Read terminal status line: Ring Indicator"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200618 if not self.is_open:
619 raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000620 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200621 return struct.unpack('I', s)[0] & TIOCM_RI != 0
cliechti89b4af12002-02-12 23:24:41 +0000622
Chris Liechtief1fe252015-08-27 23:25:21 +0200623 @property
624 def cd(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000625 """Read terminal status line: Carrier Detect"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200626 if not self.is_open:
627 raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000628 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200629 return struct.unpack('I', s)[0] & TIOCM_CD != 0
cliechti89b4af12002-02-12 23:24:41 +0000630
cliechtia30a8a02003-10-05 12:28:13 +0000631 # - - platform specific - - - -
632
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200633 @property
634 def out_waiting(self):
635 """Return the number of bytes currently in the output buffer."""
Chris Liechti11465c82015-08-04 15:55:22 +0200636 #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str)
cliechti28b8fd02011-12-28 21:39:42 +0000637 s = fcntl.ioctl(self.fd, TIOCOUTQ, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200638 return struct.unpack('I', s)[0]
cliechti28b8fd02011-12-28 21:39:42 +0000639
cliechti8753bbc2005-01-15 20:32:51 +0000640 def fileno(self):
cliechti2f0f8a32011-12-28 22:10:00 +0000641 """\
642 For easier use of the serial port instance with select.
643 WARNING: this function is not portable to different platforms!
644 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200645 if not self.is_open:
646 raise portNotOpenError
cliechti8753bbc2005-01-15 20:32:51 +0000647 return self.fd
cliechti89b4af12002-02-12 23:24:41 +0000648
Chris Liechti518b0d32015-08-30 02:20:39 +0200649 def set_input_flow_control(self, enable=True):
cliechti2f0f8a32011-12-28 22:10:00 +0000650 """\
651 Manually control flow - when software flow control is enabled.
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200652 This will send XON (true) or XOFF (false) to the other device.
cliechti2f0f8a32011-12-28 22:10:00 +0000653 WARNING: this function is not portable to different platforms!
654 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200655 if not self.is_open:
656 raise portNotOpenError
cliechti4a601342011-12-29 02:22:17 +0000657 if enable:
Chris Liechti11465c82015-08-04 15:55:22 +0200658 termios.tcflow(self.fd, termios.TCION)
cliechti57e48a62009-08-03 22:29:58 +0000659 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200660 termios.tcflow(self.fd, termios.TCIOFF)
cliechti57e48a62009-08-03 22:29:58 +0000661
Chris Liechti518b0d32015-08-30 02:20:39 +0200662 def set_output_flow_control(self, enable=True):
cliechti2f0f8a32011-12-28 22:10:00 +0000663 """\
664 Manually control flow of outgoing data - when hardware or software flow
665 control is enabled.
666 WARNING: this function is not portable to different platforms!
667 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200668 if not self.is_open:
669 raise portNotOpenError
cliechti2f0f8a32011-12-28 22:10:00 +0000670 if enable:
Chris Liechti11465c82015-08-04 15:55:22 +0200671 termios.tcflow(self.fd, termios.TCOON)
cliechti2f0f8a32011-12-28 22:10:00 +0000672 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200673 termios.tcflow(self.fd, termios.TCOOFF)
cliechti2f0f8a32011-12-28 22:10:00 +0000674
Chris Liechti59848422016-06-04 22:28:14 +0200675 def nonblocking(self):
676 """DEPRECATED - has no use"""
677 import warnings
678 warnings.warn("nonblocking() has no effect, already nonblocking", DeprecationWarning)
679
cliechtif81362e2009-07-25 03:44:33 +0000680
cliechtia9a093e2010-01-02 03:05:08 +0000681class PosixPollSerial(Serial):
cliechti7d448562014-08-03 21:57:45 +0000682 """\
cliechtif0a81d42014-08-04 14:03:53 +0000683 Poll based read implementation. Not all systems support poll properly.
684 However this one has better handling of errors, such as a device
cliechti7d448562014-08-03 21:57:45 +0000685 disconnecting while it's in use (e.g. USB-serial unplugged).
686 """
cliechtia9a093e2010-01-02 03:05:08 +0000687
688 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000689 """\
690 Read size bytes from the serial port. If a timeout is set it may
691 return less characters as requested. With no timeout it will block
692 until the requested number of bytes is read.
693 """
Chris Liechtiacac2362016-03-29 22:37:48 +0200694 if not self.is_open:
Chris Liechti033f17c2015-08-30 21:28:04 +0200695 raise portNotOpenError
cliechtia9a093e2010-01-02 03:05:08 +0000696 read = bytearray()
697 poll = select.poll()
Chris Liechti033f17c2015-08-30 21:28:04 +0200698 poll.register(self.fd, select.POLLIN | select.POLLERR | select.POLLHUP | select.POLLNVAL)
cliechtia9a093e2010-01-02 03:05:08 +0000699 if size > 0:
700 while len(read) < size:
701 # print "\tread(): size",size, "have", len(read) #debug
702 # wait until device becomes ready to read (or something fails)
Chris Liechti033f17c2015-08-30 21:28:04 +0200703 for fd, event in poll.poll(self._timeout * 1000):
704 if event & (select.POLLERR | select.POLLHUP | select.POLLNVAL):
cliechtia9a093e2010-01-02 03:05:08 +0000705 raise SerialException('device reports error (poll)')
706 # we don't care if it is select.POLLIN or timeout, that's
707 # handled below
708 buf = os.read(self.fd, size - len(read))
709 read.extend(buf)
Chris Liechti518b0d32015-08-30 02:20:39 +0200710 if ((self._timeout is not None and self._timeout >= 0) or
Chris Liechti033f17c2015-08-30 21:28:04 +0200711 (self._inter_byte_timeout is not None and self._inter_byte_timeout > 0)) and not buf:
cliechtia9a093e2010-01-02 03:05:08 +0000712 break # early abort on timeout
713 return bytes(read)
714
cliechtif81362e2009-07-25 03:44:33 +0000715
Chris Liechti4cf54702015-10-18 00:21:56 +0200716class VTIMESerial(Serial):
717 """\
718 Implement timeout using vtime of tty device instead of using select.
719 This means that no inter character timeout can be specified and that
720 the error handling is degraded.
721
722 Overall timeout is disabled when inter-character timeout is used.
723 """
724
Chris Liechti94284702015-11-15 01:21:48 +0100725 def _reconfigure_port(self, force_update=True):
Chris Liechti4cf54702015-10-18 00:21:56 +0200726 """Set communication parameters on opened port."""
727 super(VTIMESerial, self)._reconfigure_port()
Chris Liechtid6bcaaf2016-02-01 22:55:26 +0100728 fcntl.fcntl(self.fd, fcntl.F_SETFL, 0) # clear O_NONBLOCK
Chris Liechti4cf54702015-10-18 00:21:56 +0200729
730 if self._inter_byte_timeout is not None:
731 vmin = 1
732 vtime = int(self._inter_byte_timeout * 10)
733 else:
734 vmin = 0
735 vtime = int(self._timeout * 10)
736 try:
737 orig_attr = termios.tcgetattr(self.fd)
738 iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
739 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 +0100740 raise serial.SerialException("Could not configure port: {}".format(msg))
Chris Liechti4cf54702015-10-18 00:21:56 +0200741
742 if vtime < 0 or vtime > 255:
Chris Liechti984c5c52016-02-15 23:48:45 +0100743 raise ValueError('Invalid vtime: {!r}'.format(vtime))
Chris Liechti4cf54702015-10-18 00:21:56 +0200744 cc[termios.VTIME] = vtime
745 cc[termios.VMIN] = vmin
746
747 termios.tcsetattr(
748 self.fd,
749 termios.TCSANOW,
750 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
751
Chris Liechti4cf54702015-10-18 00:21:56 +0200752 def read(self, size=1):
753 """\
754 Read size bytes from the serial port. If a timeout is set it may
755 return less characters as requested. With no timeout it will block
756 until the requested number of bytes is read.
757 """
758 if not self.is_open:
759 raise portNotOpenError
760 read = bytearray()
761 while len(read) < size:
762 buf = os.read(self.fd, size - len(read))
763 if not buf:
764 break
765 read.extend(buf)
766 return bytes(read)