blob: 82fe59abfe4dd326afd15e8705eaea3ef476d36b [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
Chris Liechti6dc58e82016-08-29 23:02:13 +020054
55# some systems support an extra flag to enable the two in POSIX unsupported
Chris Liechti11538242016-09-06 22:20:09 +020056# paritiy settings for MARK and SPACE
Chris Liechti6dc58e82016-08-29 23:02:13 +020057CMSPAR = 0 # default, for unsupported platforms, override below
58
Chris Liechtid6847af2015-08-06 17:54:30 +020059# try to detect the OS so that a device can be selected...
60# this code block should supply a device() and set_special_baudrate() function
61# for the platform
62plat = sys.platform.lower()
63
Chris Liechtiba45c522016-02-06 23:53:23 +010064if plat[:5] == 'linux': # Linux (confirmed) # noqa
Chris Liechtid6847af2015-08-06 17:54:30 +020065 import array
66
Chris Liechti6dc58e82016-08-29 23:02:13 +020067 # extra termios flags
68 CMSPAR = 0o10000000000 # Use "stick" (mark/space) parity
69
Chris Liechtid6847af2015-08-06 17:54:30 +020070 # baudrate ioctls
71 TCGETS2 = 0x802C542A
72 TCSETS2 = 0x402C542B
73 BOTHER = 0o010000
74
75 # RS485 ioctls
76 TIOCGRS485 = 0x542E
77 TIOCSRS485 = 0x542F
Chris Liechti033f17c2015-08-30 21:28:04 +020078 SER_RS485_ENABLED = 0b00000001
79 SER_RS485_RTS_ON_SEND = 0b00000010
Chris Liechtid6847af2015-08-06 17:54:30 +020080 SER_RS485_RTS_AFTER_SEND = 0b00000100
Chris Liechti033f17c2015-08-30 21:28:04 +020081 SER_RS485_RX_DURING_TX = 0b00010000
Chris Liechtid6847af2015-08-06 17:54:30 +020082
83 class PlatformSpecific(PlatformSpecificBase):
84 BAUDRATE_CONSTANTS = {
85 0: 0o000000, # hang up
86 50: 0o000001,
87 75: 0o000002,
88 110: 0o000003,
89 134: 0o000004,
90 150: 0o000005,
91 200: 0o000006,
92 300: 0o000007,
93 600: 0o000010,
94 1200: 0o000011,
95 1800: 0o000012,
96 2400: 0o000013,
97 4800: 0o000014,
98 9600: 0o000015,
99 19200: 0o000016,
100 38400: 0o000017,
101 57600: 0o010001,
102 115200: 0o010002,
103 230400: 0o010003,
104 460800: 0o010004,
105 500000: 0o010005,
106 576000: 0o010006,
107 921600: 0o010007,
108 1000000: 0o010010,
109 1152000: 0o010011,
110 1500000: 0o010012,
111 2000000: 0o010013,
112 2500000: 0o010014,
113 3000000: 0o010015,
114 3500000: 0o010016,
115 4000000: 0o010017
116 }
117
Chris Liechtid6847af2015-08-06 17:54:30 +0200118 def _set_special_baudrate(self, baudrate):
119 # right size is 44 on x86_64, allow for some growth
120 buf = array.array('i', [0] * 64)
121 try:
122 # get serial_struct
123 fcntl.ioctl(self.fd, TCGETS2, buf)
124 # set custom speed
125 buf[2] &= ~termios.CBAUD
126 buf[2] |= BOTHER
127 buf[9] = buf[10] = baudrate
128
129 # set serial_struct
Chris Liechti033f17c2015-08-30 21:28:04 +0200130 fcntl.ioctl(self.fd, TCSETS2, buf)
Chris Liechtid6847af2015-08-06 17:54:30 +0200131 except IOError as e:
Chris Liechti984c5c52016-02-15 23:48:45 +0100132 raise ValueError('Failed to set custom baud rate ({}): {}'.format(baudrate, e))
Chris Liechtid6847af2015-08-06 17:54:30 +0200133
134 def _set_rs485_mode(self, rs485_settings):
Chris Liechti033f17c2015-08-30 21:28:04 +0200135 buf = array.array('i', [0] * 8) # flags, delaytx, delayrx, padding
Chris Liechtid6847af2015-08-06 17:54:30 +0200136 try:
137 fcntl.ioctl(self.fd, TIOCGRS485, buf)
Chris Liechti7a554462016-03-24 21:17:22 +0100138 buf[0] |= SER_RS485_ENABLED
Chris Liechtid6847af2015-08-06 17:54:30 +0200139 if rs485_settings is not None:
140 if rs485_settings.loopback:
141 buf[0] |= SER_RS485_RX_DURING_TX
142 else:
143 buf[0] &= ~SER_RS485_RX_DURING_TX
144 if rs485_settings.rts_level_for_tx:
145 buf[0] |= SER_RS485_RTS_ON_SEND
146 else:
147 buf[0] &= ~SER_RS485_RTS_ON_SEND
148 if rs485_settings.rts_level_for_rx:
149 buf[0] |= SER_RS485_RTS_AFTER_SEND
150 else:
151 buf[0] &= ~SER_RS485_RTS_AFTER_SEND
Chris Liechti279201b2016-06-09 20:27:05 +0200152 if rs485_settings.delay_before_tx is not None:
153 buf[1] = int(rs485_settings.delay_before_tx * 1000)
154 if rs485_settings.delay_before_rx is not None:
155 buf[2] = int(rs485_settings.delay_before_rx * 1000)
Chris Liechtid6847af2015-08-06 17:54:30 +0200156 else:
157 buf[0] = 0 # clear SER_RS485_ENABLED
Chris Liechti033f17c2015-08-30 21:28:04 +0200158 fcntl.ioctl(self.fd, TIOCSRS485, buf)
Chris Liechtid6847af2015-08-06 17:54:30 +0200159 except IOError as e:
Chris Liechti984c5c52016-02-15 23:48:45 +0100160 raise ValueError('Failed to set RS485 mode: {}'.format(e))
Chris Liechtid6847af2015-08-06 17:54:30 +0200161
162
163elif plat == 'cygwin': # cygwin/win32 (confirmed)
164
165 class PlatformSpecific(PlatformSpecificBase):
166 BAUDRATE_CONSTANTS = {
167 128000: 0x01003,
168 256000: 0x01005,
169 500000: 0x01007,
170 576000: 0x01008,
171 921600: 0x01009,
172 1000000: 0x0100a,
173 1152000: 0x0100b,
174 1500000: 0x0100c,
175 2000000: 0x0100d,
176 2500000: 0x0100e,
177 3000000: 0x0100f
178 }
179
Chris Liechtid6847af2015-08-06 17:54:30 +0200180
181elif plat[:6] == 'darwin': # OS X
182 import array
Chris Liechti033f17c2015-08-30 21:28:04 +0200183 IOSSIOSPEED = 0x80045402 # _IOW('T', 2, speed_t)
Chris Liechtid6847af2015-08-06 17:54:30 +0200184
185 class PlatformSpecific(PlatformSpecificBase):
Chris Liechtid6847af2015-08-06 17:54:30 +0200186 osx_version = os.uname()[2].split('.')
187 # Tiger or above can support arbitrary serial speeds
188 if int(osx_version[0]) >= 8:
189 def _set_special_baudrate(self, baudrate):
190 # use IOKit-specific call to set up high speeds
191 buf = array.array('i', [baudrate])
192 fcntl.ioctl(self.fd, IOSSIOSPEED, buf, 1)
193
Chris Liechti21a306b2016-10-09 23:41:26 +0200194elif plat[:3] == 'bsd' or \
195 plat[:7] == 'freebsd' or \
196 plat[:6] == 'netbsd' or \
197 plat[:7] == 'openbsd':
198
199 class ReturnBaudrate(object):
200 def __getitem__(self, key):
201 return key
202
203 class PlatformSpecific(PlatformSpecificBase):
204 # Only tested on FreeBSD:
205 # The baud rate may be passed in as
206 # a literal value.
207 BAUDRATE_CONSTANTS = ReturnBaudrate()
208
Chris Liechtid6847af2015-08-06 17:54:30 +0200209else:
210 class PlatformSpecific(PlatformSpecificBase):
211 pass
cliechti89b4af12002-02-12 23:24:41 +0000212
cliechti89b4af12002-02-12 23:24:41 +0000213
cliechti58b481c2009-02-16 20:42:32 +0000214# load some constants for later use.
Chris Liechti11465c82015-08-04 15:55:22 +0200215# try to use values from termios, use defaults from linux otherwise
Chris Liechti033f17c2015-08-30 21:28:04 +0200216TIOCMGET = getattr(termios, 'TIOCMGET', 0x5415)
217TIOCMBIS = getattr(termios, 'TIOCMBIS', 0x5416)
218TIOCMBIC = getattr(termios, 'TIOCMBIC', 0x5417)
219TIOCMSET = getattr(termios, 'TIOCMSET', 0x5418)
cliechti89b4af12002-02-12 23:24:41 +0000220
Chris Liechti033f17c2015-08-30 21:28:04 +0200221# TIOCM_LE = getattr(termios, 'TIOCM_LE', 0x001)
Chris Liechtid6847af2015-08-06 17:54:30 +0200222TIOCM_DTR = getattr(termios, 'TIOCM_DTR', 0x002)
223TIOCM_RTS = getattr(termios, 'TIOCM_RTS', 0x004)
Chris Liechti033f17c2015-08-30 21:28:04 +0200224# TIOCM_ST = getattr(termios, 'TIOCM_ST', 0x008)
225# TIOCM_SR = getattr(termios, 'TIOCM_SR', 0x010)
cliechti89b4af12002-02-12 23:24:41 +0000226
Chris Liechtid6847af2015-08-06 17:54:30 +0200227TIOCM_CTS = getattr(termios, 'TIOCM_CTS', 0x020)
228TIOCM_CAR = getattr(termios, 'TIOCM_CAR', 0x040)
229TIOCM_RNG = getattr(termios, 'TIOCM_RNG', 0x080)
230TIOCM_DSR = getattr(termios, 'TIOCM_DSR', 0x100)
Chris Liechti033f17c2015-08-30 21:28:04 +0200231TIOCM_CD = getattr(termios, 'TIOCM_CD', TIOCM_CAR)
232TIOCM_RI = getattr(termios, 'TIOCM_RI', TIOCM_RNG)
233# TIOCM_OUT1 = getattr(termios, 'TIOCM_OUT1', 0x2000)
234# TIOCM_OUT2 = getattr(termios, 'TIOCM_OUT2', 0x4000)
Chris Liechti11465c82015-08-04 15:55:22 +0200235if hasattr(termios, 'TIOCINQ'):
236 TIOCINQ = termios.TIOCINQ
cliechti28b8fd02011-12-28 21:39:42 +0000237else:
Chris Liechtid6847af2015-08-06 17:54:30 +0200238 TIOCINQ = getattr(termios, 'FIONREAD', 0x541B)
Chris Liechti033f17c2015-08-30 21:28:04 +0200239TIOCOUTQ = getattr(termios, 'TIOCOUTQ', 0x5411)
cliechti89b4af12002-02-12 23:24:41 +0000240
241TIOCM_zero_str = struct.pack('I', 0)
242TIOCM_RTS_str = struct.pack('I', TIOCM_RTS)
243TIOCM_DTR_str = struct.pack('I', TIOCM_DTR)
244
Chris Liechti033f17c2015-08-30 21:28:04 +0200245TIOCSBRK = getattr(termios, 'TIOCSBRK', 0x5427)
246TIOCCBRK = getattr(termios, 'TIOCCBRK', 0x5428)
cliechti997b63c2008-06-21 00:09:31 +0000247
cliechti89b4af12002-02-12 23:24:41 +0000248
Chris Liechtief6b7b42015-08-06 22:19:26 +0200249class Serial(SerialBase, PlatformSpecific):
cliechti7d448562014-08-03 21:57:45 +0000250 """\
Chris Liechti033f17c2015-08-30 21:28:04 +0200251 Serial port class POSIX implementation. Serial port configuration is
cliechtid6bf52c2003-10-01 02:28:12 +0000252 done with termios and fcntl. Runs on Linux and many other Un*x like
cliechtif0a81d42014-08-04 14:03:53 +0000253 systems.
254 """
cliechtid6bf52c2003-10-01 02:28:12 +0000255
256 def open(self):
cliechti7d448562014-08-03 21:57:45 +0000257 """\
258 Open port with current settings. This may throw a SerialException
259 if the port cannot be opened."""
cliechtid6bf52c2003-10-01 02:28:12 +0000260 if self._port is None:
261 raise SerialException("Port must be configured before it can be used.")
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200262 if self.is_open:
cliechti02ef43a2011-03-24 23:33:12 +0000263 raise SerialException("Port is already open.")
264 self.fd = None
cliechti58b481c2009-02-16 20:42:32 +0000265 # open
cliechti4616bf12002-04-08 23:13:14 +0000266 try:
Chris Liechti033f17c2015-08-30 21:28:04 +0200267 self.fd = os.open(self.portstr, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK)
Chris Liechti68340d72015-08-03 14:15:48 +0200268 except OSError as msg:
cliechti4616bf12002-04-08 23:13:14 +0000269 self.fd = None
Chris Liechti984c5c52016-02-15 23:48:45 +0100270 raise SerialException(msg.errno, "could not open port {}: {}".format(self._port, msg))
Chris Liechti11465c82015-08-04 15:55:22 +0200271 #~ fcntl.fcntl(self.fd, fcntl.F_SETFL, 0) # set blocking
cliechti58b481c2009-02-16 20:42:32 +0000272
cliechtib2f5fc82006-10-20 00:09:07 +0000273 try:
Chris Liechti94284702015-11-15 01:21:48 +0100274 self._reconfigure_port(force_update=True)
cliechtib2f5fc82006-10-20 00:09:07 +0000275 except:
cliechti2750b832009-07-28 00:13:52 +0000276 try:
277 os.close(self.fd)
278 except:
279 # ignore any exception when closing the port
280 # also to keep original exception that happened when setting up
281 pass
cliechtib2f5fc82006-10-20 00:09:07 +0000282 self.fd = None
cliechtif0a4f0f2009-07-21 21:12:37 +0000283 raise
cliechtib2f5fc82006-10-20 00:09:07 +0000284 else:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200285 self.is_open = True
Chris Liechtif2fdeb92016-05-07 23:57:50 +0200286 try:
287 if not self._dsrdtr:
288 self._update_dtr_state()
289 if not self._rtscts:
290 self._update_rts_state()
291 except IOError as e:
Chris Liechtie1029622016-10-02 23:54:36 +0200292 if e.errno in (errno.EINVAL, errno.ENOTTY):
293 # ignore Invalid argument and Inappropriate ioctl
Chris Liechtif2fdeb92016-05-07 23:57:50 +0200294 pass
295 else:
296 raise
Chris Liechtief1fe252015-08-27 23:25:21 +0200297 self.reset_input_buffer()
Chris Liechti42ab2b42016-05-15 23:35:05 +0200298 self.pipe_abort_read_r, self.pipe_abort_read_w = os.pipe()
Chris Liechti13949c62016-05-16 22:45:38 +0200299 self.pipe_abort_write_r, self.pipe_abort_write_w = os.pipe()
Chris Liechti68cecce2016-06-03 23:52:34 +0200300 fcntl.fcntl(self.pipe_abort_read_r, fcntl.F_SETFL, os.O_NONBLOCK)
301 fcntl.fcntl(self.pipe_abort_write_r, fcntl.F_SETFL, os.O_NONBLOCK)
cliechti58b481c2009-02-16 20:42:32 +0000302
Chris Liechti94284702015-11-15 01:21:48 +0100303 def _reconfigure_port(self, force_update=False):
cliechtib2f5fc82006-10-20 00:09:07 +0000304 """Set communication parameters on opened port."""
cliechtic6178262004-03-22 22:04:52 +0000305 if self.fd is None:
cliechtia9a093e2010-01-02 03:05:08 +0000306 raise SerialException("Can only operate on a valid file descriptor")
Chris Liechti1c4bc812017-03-08 02:44:04 +0100307
Rob Gaddi636cc642017-02-24 11:39:46 -0800308 # if exclusive lock is requested, create it before we modify anything else
309 if self._exclusive is not None:
310 if self._exclusive:
311 try:
312 fcntl.flock(self.fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
313 except IOError as msg:
314 raise SerialException(msg.errno, "Could not exclusively lock port {}: {}".format(self._port, msg))
315 else:
316 fcntl.flock(self.fd, fcntl.LOCK_UN)
Chris Liechti1c4bc812017-03-08 02:44:04 +0100317
cliechtie8c45422008-06-20 23:23:14 +0000318 custom_baud = None
cliechti58b481c2009-02-16 20:42:32 +0000319
cliechti2750b832009-07-28 00:13:52 +0000320 vmin = vtime = 0 # timeout is done via select
Chris Liechti518b0d32015-08-30 02:20:39 +0200321 if self._inter_byte_timeout is not None:
cliechti679bfa62008-06-20 23:58:15 +0000322 vmin = 1
Chris Liechti518b0d32015-08-30 02:20:39 +0200323 vtime = int(self._inter_byte_timeout * 10)
cliechti6ce7ab12002-11-07 02:15:00 +0000324 try:
cliechti4d0af5e2011-08-05 02:18:16 +0000325 orig_attr = termios.tcgetattr(self.fd)
326 iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
Chris Liechti68340d72015-08-03 14:15:48 +0200327 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 +0100328 raise SerialException("Could not configure port: {}".format(msg))
cliechti58b481c2009-02-16 20:42:32 +0000329 # set up raw mode / no echo / binary
Chris Liechti033f17c2015-08-30 21:28:04 +0200330 cflag |= (termios.CLOCAL | termios.CREAD)
331 lflag &= ~(termios.ICANON | termios.ECHO | termios.ECHOE |
332 termios.ECHOK | termios.ECHONL |
333 termios.ISIG | termios.IEXTEN) # |termios.ECHOPRT
334 for flag in ('ECHOCTL', 'ECHOKE'): # netbsd workaround for Erk
Chris Liechti11465c82015-08-04 15:55:22 +0200335 if hasattr(termios, flag):
336 lflag &= ~getattr(termios, flag)
cliechti58b481c2009-02-16 20:42:32 +0000337
Chris Liechti033f17c2015-08-30 21:28:04 +0200338 oflag &= ~(termios.OPOST | termios.ONLCR | termios.OCRNL)
339 iflag &= ~(termios.INLCR | termios.IGNCR | termios.ICRNL | termios.IGNBRK)
Chris Liechti11465c82015-08-04 15:55:22 +0200340 if hasattr(termios, 'IUCLC'):
341 iflag &= ~termios.IUCLC
342 if hasattr(termios, 'PARMRK'):
343 iflag &= ~termios.PARMRK
cliechti58b481c2009-02-16 20:42:32 +0000344
cliechtif0a4f0f2009-07-21 21:12:37 +0000345 # setup baud rate
cliechti89b4af12002-02-12 23:24:41 +0000346 try:
Chris Liechti984c5c52016-02-15 23:48:45 +0100347 ispeed = ospeed = getattr(termios, 'B{}'.format(self._baudrate))
cliechti895e8302004-04-20 02:40:28 +0000348 except AttributeError:
cliechtif1559d02007-11-08 23:43:58 +0000349 try:
Chris Liechtid6847af2015-08-06 17:54:30 +0200350 ispeed = ospeed = self.BAUDRATE_CONSTANTS[self._baudrate]
cliechtif1559d02007-11-08 23:43:58 +0000351 except KeyError:
cliechtie8c45422008-06-20 23:23:14 +0000352 #~ raise ValueError('Invalid baud rate: %r' % self._baudrate)
cliechtif0a4f0f2009-07-21 21:12:37 +0000353 # may need custom baud rate, it isn't in our list.
Chris Liechti11465c82015-08-04 15:55:22 +0200354 ispeed = ospeed = getattr(termios, 'B38400')
cliechtif0a4f0f2009-07-21 21:12:37 +0000355 try:
Chris Liechti033f17c2015-08-30 21:28:04 +0200356 custom_baud = int(self._baudrate) # store for later
cliechtif0a4f0f2009-07-21 21:12:37 +0000357 except ValueError:
Chris Liechti984c5c52016-02-15 23:48:45 +0100358 raise ValueError('Invalid baud rate: {!r}'.format(self._baudrate))
cliechtif0a4f0f2009-07-21 21:12:37 +0000359 else:
360 if custom_baud < 0:
Chris Liechti984c5c52016-02-15 23:48:45 +0100361 raise ValueError('Invalid baud rate: {!r}'.format(self._baudrate))
cliechti58b481c2009-02-16 20:42:32 +0000362
363 # setup char len
Chris Liechti11465c82015-08-04 15:55:22 +0200364 cflag &= ~termios.CSIZE
cliechtid6bf52c2003-10-01 02:28:12 +0000365 if self._bytesize == 8:
Chris Liechti11465c82015-08-04 15:55:22 +0200366 cflag |= termios.CS8
cliechtid6bf52c2003-10-01 02:28:12 +0000367 elif self._bytesize == 7:
Chris Liechti11465c82015-08-04 15:55:22 +0200368 cflag |= termios.CS7
cliechtid6bf52c2003-10-01 02:28:12 +0000369 elif self._bytesize == 6:
Chris Liechti11465c82015-08-04 15:55:22 +0200370 cflag |= termios.CS6
cliechtid6bf52c2003-10-01 02:28:12 +0000371 elif self._bytesize == 5:
Chris Liechti11465c82015-08-04 15:55:22 +0200372 cflag |= termios.CS5
cliechti89b4af12002-02-12 23:24:41 +0000373 else:
Chris Liechti984c5c52016-02-15 23:48:45 +0100374 raise ValueError('Invalid char len: {!r}'.format(self._bytesize))
cliechtif0a81d42014-08-04 14:03:53 +0000375 # setup stop bits
Chris Liechti033f17c2015-08-30 21:28:04 +0200376 if self._stopbits == serial.STOPBITS_ONE:
Chris Liechti11465c82015-08-04 15:55:22 +0200377 cflag &= ~(termios.CSTOPB)
Chris Liechti033f17c2015-08-30 21:28:04 +0200378 elif self._stopbits == serial.STOPBITS_ONE_POINT_FIVE:
379 cflag |= (termios.CSTOPB) # XXX same as TWO.. there is no POSIX support for 1.5
380 elif self._stopbits == serial.STOPBITS_TWO:
381 cflag |= (termios.CSTOPB)
cliechti89b4af12002-02-12 23:24:41 +0000382 else:
Chris Liechti984c5c52016-02-15 23:48:45 +0100383 raise ValueError('Invalid stop bit specification: {!r}'.format(self._stopbits))
cliechti58b481c2009-02-16 20:42:32 +0000384 # setup parity
Chris Liechti033f17c2015-08-30 21:28:04 +0200385 iflag &= ~(termios.INPCK | termios.ISTRIP)
386 if self._parity == serial.PARITY_NONE:
Chris Liechti6dc58e82016-08-29 23:02:13 +0200387 cflag &= ~(termios.PARENB | termios.PARODD | CMSPAR)
Chris Liechti033f17c2015-08-30 21:28:04 +0200388 elif self._parity == serial.PARITY_EVEN:
Chris Liechti6dc58e82016-08-29 23:02:13 +0200389 cflag &= ~(termios.PARODD | CMSPAR)
Chris Liechti033f17c2015-08-30 21:28:04 +0200390 cflag |= (termios.PARENB)
391 elif self._parity == serial.PARITY_ODD:
Chris Liechti6dc58e82016-08-29 23:02:13 +0200392 cflag &= ~CMSPAR
Chris Liechti033f17c2015-08-30 21:28:04 +0200393 cflag |= (termios.PARENB | termios.PARODD)
Chris Liechti6dc58e82016-08-29 23:02:13 +0200394 elif self._parity == serial.PARITY_MARK and CMSPAR:
Chris Liechti033f17c2015-08-30 21:28:04 +0200395 cflag |= (termios.PARENB | CMSPAR | termios.PARODD)
Chris Liechti6dc58e82016-08-29 23:02:13 +0200396 elif self._parity == serial.PARITY_SPACE and CMSPAR:
Chris Liechti033f17c2015-08-30 21:28:04 +0200397 cflag |= (termios.PARENB | CMSPAR)
Chris Liechti11465c82015-08-04 15:55:22 +0200398 cflag &= ~(termios.PARODD)
cliechti89b4af12002-02-12 23:24:41 +0000399 else:
Chris Liechti984c5c52016-02-15 23:48:45 +0100400 raise ValueError('Invalid parity: {!r}'.format(self._parity))
cliechti58b481c2009-02-16 20:42:32 +0000401 # setup flow control
402 # xonxoff
Chris Liechti11465c82015-08-04 15:55:22 +0200403 if hasattr(termios, 'IXANY'):
cliechtid6bf52c2003-10-01 02:28:12 +0000404 if self._xonxoff:
Chris Liechti033f17c2015-08-30 21:28:04 +0200405 iflag |= (termios.IXON | termios.IXOFF) # |termios.IXANY)
cliechti89b4af12002-02-12 23:24:41 +0000406 else:
Chris Liechti033f17c2015-08-30 21:28:04 +0200407 iflag &= ~(termios.IXON | termios.IXOFF | termios.IXANY)
cliechti89b4af12002-02-12 23:24:41 +0000408 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000409 if self._xonxoff:
Chris Liechti033f17c2015-08-30 21:28:04 +0200410 iflag |= (termios.IXON | termios.IXOFF)
cliechti89b4af12002-02-12 23:24:41 +0000411 else:
Chris Liechti033f17c2015-08-30 21:28:04 +0200412 iflag &= ~(termios.IXON | termios.IXOFF)
cliechti58b481c2009-02-16 20:42:32 +0000413 # rtscts
Chris Liechti11465c82015-08-04 15:55:22 +0200414 if hasattr(termios, 'CRTSCTS'):
cliechtid6bf52c2003-10-01 02:28:12 +0000415 if self._rtscts:
Chris Liechti033f17c2015-08-30 21:28:04 +0200416 cflag |= (termios.CRTSCTS)
cliechti89b4af12002-02-12 23:24:41 +0000417 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200418 cflag &= ~(termios.CRTSCTS)
419 elif hasattr(termios, 'CNEW_RTSCTS'): # try it with alternate constant name
cliechtid6bf52c2003-10-01 02:28:12 +0000420 if self._rtscts:
Chris Liechti033f17c2015-08-30 21:28:04 +0200421 cflag |= (termios.CNEW_RTSCTS)
cliechtid4743692002-04-08 22:39:53 +0000422 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200423 cflag &= ~(termios.CNEW_RTSCTS)
cliechti2750b832009-07-28 00:13:52 +0000424 # XXX should there be a warning if setting up rtscts (and xonxoff etc) fails??
cliechti58b481c2009-02-16 20:42:32 +0000425
426 # buffer
cliechtif0a81d42014-08-04 14:03:53 +0000427 # vmin "minimal number of characters to be read. 0 for non blocking"
cliechtid6bf52c2003-10-01 02:28:12 +0000428 if vmin < 0 or vmin > 255:
Chris Liechti984c5c52016-02-15 23:48:45 +0100429 raise ValueError('Invalid vmin: {!r}'.format(vmin))
Chris Liechti11465c82015-08-04 15:55:22 +0200430 cc[termios.VMIN] = vmin
cliechti58b481c2009-02-16 20:42:32 +0000431 # vtime
cliechtid6bf52c2003-10-01 02:28:12 +0000432 if vtime < 0 or vtime > 255:
Chris Liechti984c5c52016-02-15 23:48:45 +0100433 raise ValueError('Invalid vtime: {!r}'.format(vtime))
Chris Liechti11465c82015-08-04 15:55:22 +0200434 cc[termios.VTIME] = vtime
cliechti58b481c2009-02-16 20:42:32 +0000435 # activate settings
Chris Liechti94284702015-11-15 01:21:48 +0100436 if force_update or [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] != orig_attr:
Chris Liechti033f17c2015-08-30 21:28:04 +0200437 termios.tcsetattr(
Chris Liechti9eaa40c2016-02-12 23:32:59 +0100438 self.fd,
439 termios.TCSANOW,
440 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
cliechti58b481c2009-02-16 20:42:32 +0000441
cliechtie8c45422008-06-20 23:23:14 +0000442 # apply custom baud rate, if any
443 if custom_baud is not None:
Chris Liechtid6847af2015-08-06 17:54:30 +0200444 self._set_special_baudrate(custom_baud)
445
446 if self._rs485_mode is not None:
447 self._set_rs485_mode(self._rs485_mode)
cliechti89b4af12002-02-12 23:24:41 +0000448
449 def close(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000450 """Close port"""
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200451 if self.is_open:
cliechtic6178262004-03-22 22:04:52 +0000452 if self.fd is not None:
cliechtid6bf52c2003-10-01 02:28:12 +0000453 os.close(self.fd)
454 self.fd = None
Chris Liechtib658eac2016-05-22 20:51:44 +0200455 os.close(self.pipe_abort_read_w)
456 os.close(self.pipe_abort_read_r)
457 os.close(self.pipe_abort_write_w)
458 os.close(self.pipe_abort_write_r)
459 self.pipe_abort_read_r, self.pipe_abort_read_w = None, None
460 self.pipe_abort_write_r, self.pipe_abort_write_w = None, None
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200461 self.is_open = False
cliechtid6bf52c2003-10-01 02:28:12 +0000462
463 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechti95c62212002-03-04 22:17:53 +0000464
Chris Liechtief1fe252015-08-27 23:25:21 +0200465 @property
466 def in_waiting(self):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200467 """Return the number of bytes currently in the input buffer."""
Chris Liechti11465c82015-08-04 15:55:22 +0200468 #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str)
cliechtif5831e02002-12-05 23:15:27 +0000469 s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200470 return struct.unpack('I', s)[0]
cliechti89b4af12002-02-12 23:24:41 +0000471
cliechtia9a093e2010-01-02 03:05:08 +0000472 # select based implementation, proved to work on many systems
473 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000474 """\
475 Read size bytes from the serial port. If a timeout is set it may
476 return less characters as requested. With no timeout it will block
477 until the requested number of bytes is read.
478 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200479 if not self.is_open:
480 raise portNotOpenError
cliechtia9a093e2010-01-02 03:05:08 +0000481 read = bytearray()
Chris Liechti935a2622016-08-30 23:39:15 +0200482 timeout = Timeout(self._timeout)
cliechtia9a093e2010-01-02 03:05:08 +0000483 while len(read) < size:
cliechti8d744de2013-10-11 14:31:13 +0000484 try:
Chris Liechti935a2622016-08-30 23:39:15 +0200485 ready, _, _ = select.select([self.fd, self.pipe_abort_read_r], [], [], timeout.time_left())
Chris Liechti42ab2b42016-05-15 23:35:05 +0200486 if self.pipe_abort_read_r in ready:
Chris Liechti68cecce2016-06-03 23:52:34 +0200487 os.read(self.pipe_abort_read_r, 1000)
Chris Liechti42ab2b42016-05-15 23:35:05 +0200488 break
cliechti8d744de2013-10-11 14:31:13 +0000489 # If select was used with a timeout, and the timeout occurs, it
490 # returns with empty lists -> thus abort read operation.
Chris Liechti033f17c2015-08-30 21:28:04 +0200491 # For timeout == 0 (non-blocking operation) also abort when
492 # there is nothing to read.
cliechti8d744de2013-10-11 14:31:13 +0000493 if not ready:
494 break # timeout
Chris Liechti033f17c2015-08-30 21:28:04 +0200495 buf = os.read(self.fd, size - len(read))
cliechti8d744de2013-10-11 14:31:13 +0000496 # read should always return some data as select reported it was
497 # ready to read when we get to this point.
498 if not buf:
499 # Disconnected devices, at least on Linux, show the
500 # behavior that they are always ready to read immediately
501 # but reading returns nothing.
Chris Liechti92df95a2016-02-09 23:30:37 +0100502 raise SerialException(
503 'device reports readiness to read but returned no data '
504 '(device disconnected or multiple access on port?)')
cliechti8d744de2013-10-11 14:31:13 +0000505 read.extend(buf)
Chris Liechti68340d72015-08-03 14:15:48 +0200506 except OSError as e:
Chris Liechti033f17c2015-08-30 21:28:04 +0200507 # this is for Python 3.x where select.error is a subclass of
Chris Liechti17660ee2017-05-04 23:39:05 +0200508 # OSError ignore BlockingIOErrors and EINTR. other errors are shown
509 # https://www.python.org/dev/peps/pep-0475.
510 if e.errno not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
Chris Liechti984c5c52016-02-15 23:48:45 +0100511 raise SerialException('read failed: {}'.format(e))
Chris Liechti68340d72015-08-03 14:15:48 +0200512 except select.error as e:
cliechtic7cd7212014-08-03 21:34:38 +0000513 # this is for Python 2.x
Chris Liechti17660ee2017-05-04 23:39:05 +0200514 # ignore BlockingIOErrors and EINTR. all errors are shown
cliechti8d744de2013-10-11 14:31:13 +0000515 # see also http://www.python.org/dev/peps/pep-3151/#select
Chris Liechti1c8dbee2017-05-05 03:26:51 +0200516 if e[0] not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
Chris Liechti984c5c52016-02-15 23:48:45 +0100517 raise SerialException('read failed: {}'.format(e))
Chris Liechti935a2622016-08-30 23:39:15 +0200518 if timeout.expired():
519 break
cliechtia9a093e2010-01-02 03:05:08 +0000520 return bytes(read)
cliechti89b4af12002-02-12 23:24:41 +0000521
Chris Liechti42ab2b42016-05-15 23:35:05 +0200522 def cancel_read(self):
Chris Liechti9c326282017-07-15 01:58:56 +0200523 if self.is_open:
524 os.write(self.pipe_abort_read_w, b"x")
Chris Liechti42ab2b42016-05-15 23:35:05 +0200525
Chris Liechti13949c62016-05-16 22:45:38 +0200526 def cancel_write(self):
Chris Liechti9c326282017-07-15 01:58:56 +0200527 if self.is_open:
528 os.write(self.pipe_abort_write_w, b"x")
Chris Liechti13949c62016-05-16 22:45:38 +0200529
cliechti4a567a02009-07-27 22:09:31 +0000530 def write(self, data):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200531 """Output the given byte string over the serial port."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200532 if not self.is_open:
533 raise portNotOpenError
cliechti38077122013-10-16 02:57:27 +0000534 d = to_bytes(data)
Chris Liechtie0063f12016-12-17 23:44:18 +0100535 tx_len = length = len(d)
Chris Liechti935a2622016-08-30 23:39:15 +0200536 timeout = Timeout(self._write_timeout)
cliechti9f7c2352013-10-11 01:13:46 +0000537 while tx_len > 0:
cliechti5d4d0bd2004-11-13 03:27:39 +0000538 try:
cliechti5d4d0bd2004-11-13 03:27:39 +0000539 n = os.write(self.fd, d)
Chris Liechti935a2622016-08-30 23:39:15 +0200540 if timeout.is_non_blocking:
Robert Smallshire325a7382016-03-25 21:18:38 +0100541 # Zero timeout indicates non-blocking - simply return the
542 # number of bytes of data actually written
543 return n
Chris Liechti935a2622016-08-30 23:39:15 +0200544 elif not timeout.is_infinite:
cliechti3cf46d62009-08-07 00:19:57 +0000545 # when timeout is set, use select to wait for being ready
546 # with the time left as timeout
Chris Liechti935a2622016-08-30 23:39:15 +0200547 if timeout.expired():
cliechti3cf46d62009-08-07 00:19:57 +0000548 raise writeTimeoutError
Chris Liechti935a2622016-08-30 23:39:15 +0200549 abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], timeout.time_left())
Chris Liechti13949c62016-05-16 22:45:38 +0200550 if abort:
Chris Liechti68cecce2016-06-03 23:52:34 +0200551 os.read(self.pipe_abort_write_r, 1000)
Chris Liechti13949c62016-05-16 22:45:38 +0200552 break
cliechti5d4d0bd2004-11-13 03:27:39 +0000553 if not ready:
554 raise writeTimeoutError
cliechti88c62442013-10-12 04:03:16 +0000555 else:
Chris Liechti935a2622016-08-30 23:39:15 +0200556 assert timeout.time_left() is None
cliechti88c62442013-10-12 04:03:16 +0000557 # wait for write operation
Chris Liechti13949c62016-05-16 22:45:38 +0200558 abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], None)
559 if abort:
560 os.read(self.pipe_abort_write_r, 1)
561 break
cliechti88c62442013-10-12 04:03:16 +0000562 if not ready:
563 raise SerialException('write failed (select)')
cliechti5d4d0bd2004-11-13 03:27:39 +0000564 d = d[n:]
cliechti9f7c2352013-10-11 01:13:46 +0000565 tx_len -= n
Chris Liechti675f7e12015-08-03 15:48:41 +0200566 except SerialException:
567 raise
Chris Liechti10d79d92017-05-05 00:05:23 +0200568 except OSError as e:
569 # this is for Python 3.x where select.error is a subclass of
570 # OSError ignore BlockingIOErrors and EINTR. other errors are shown
571 # https://www.python.org/dev/peps/pep-0475.
572 if e.errno not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
573 raise SerialException('write failed: {}'.format(e))
574 except select.error as e:
575 # this is for Python 2.x
576 # ignore BlockingIOErrors and EINTR. all errors are shown
577 # see also http://www.python.org/dev/peps/pep-3151/#select
Chris Liechti1c8dbee2017-05-05 03:26:51 +0200578 if e[0] not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
Chris Liechti10d79d92017-05-05 00:05:23 +0200579 raise SerialException('write failed: {}'.format(e))
Chris Liechtifc70fd72017-05-05 02:59:06 +0200580 if not timeout.is_non_blocking and timeout.expired():
Chris Liechti10d79d92017-05-05 00:05:23 +0200581 raise writeTimeoutError
Chris Liechtie0063f12016-12-17 23:44:18 +0100582 return length - len(d)
cliechtid6bf52c2003-10-01 02:28:12 +0000583
cliechtia30a8a02003-10-05 12:28:13 +0000584 def flush(self):
cliechti7d448562014-08-03 21:57:45 +0000585 """\
586 Flush of file like objects. In this case, wait until all data
587 is written.
588 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200589 if not self.is_open:
590 raise portNotOpenError
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200591 termios.tcdrain(self.fd)
cliechtia30a8a02003-10-05 12:28:13 +0000592
Chris Liechtief1fe252015-08-27 23:25:21 +0200593 def reset_input_buffer(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000594 """Clear input buffer, discarding all that is in the buffer."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200595 if not self.is_open:
596 raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200597 termios.tcflush(self.fd, termios.TCIFLUSH)
cliechti89b4af12002-02-12 23:24:41 +0000598
Chris Liechtief1fe252015-08-27 23:25:21 +0200599 def reset_output_buffer(self):
cliechti7d448562014-08-03 21:57:45 +0000600 """\
601 Clear output buffer, aborting the current output and discarding all
602 that is in the buffer.
603 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200604 if not self.is_open:
605 raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200606 termios.tcflush(self.fd, termios.TCOFLUSH)
cliechti89b4af12002-02-12 23:24:41 +0000607
Chris Liechtief1fe252015-08-27 23:25:21 +0200608 def send_break(self, duration=0.25):
cliechti7d448562014-08-03 21:57:45 +0000609 """\
610 Send break condition. Timed, returns to idle state after given
611 duration.
612 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200613 if not self.is_open:
614 raise portNotOpenError
615 termios.tcsendbreak(self.fd, int(duration / 0.25))
cliechti89b4af12002-02-12 23:24:41 +0000616
Chris Liechtief1fe252015-08-27 23:25:21 +0200617 def _update_break_state(self):
cliechti7d448562014-08-03 21:57:45 +0000618 """\
619 Set break: Controls TXD. When active, no transmitting is possible.
620 """
Chris Liechtief1fe252015-08-27 23:25:21 +0200621 if self._break_state:
cliechti997b63c2008-06-21 00:09:31 +0000622 fcntl.ioctl(self.fd, TIOCSBRK)
623 else:
624 fcntl.ioctl(self.fd, TIOCCBRK)
625
Chris Liechtief1fe252015-08-27 23:25:21 +0200626 def _update_rts_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000627 """Set terminal status line: Request To Send"""
Chris Liechtif7534c82016-05-07 23:35:54 +0200628 if self._rts_state:
629 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_RTS_str)
630 else:
631 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_RTS_str)
cliechtid6bf52c2003-10-01 02:28:12 +0000632
Chris Liechtief1fe252015-08-27 23:25:21 +0200633 def _update_dtr_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000634 """Set terminal status line: Data Terminal Ready"""
Chris Liechtif7534c82016-05-07 23:35:54 +0200635 if self._dtr_state:
636 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str)
637 else:
638 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_DTR_str)
cliechtid6bf52c2003-10-01 02:28:12 +0000639
Chris Liechtief1fe252015-08-27 23:25:21 +0200640 @property
641 def cts(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000642 """Read terminal status line: Clear To Send"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200643 if not self.is_open:
644 raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000645 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200646 return struct.unpack('I', s)[0] & TIOCM_CTS != 0
cliechtid6bf52c2003-10-01 02:28:12 +0000647
Chris Liechtief1fe252015-08-27 23:25:21 +0200648 @property
649 def dsr(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000650 """Read terminal status line: Data Set Ready"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200651 if not self.is_open:
652 raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000653 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200654 return struct.unpack('I', s)[0] & TIOCM_DSR != 0
cliechtid6bf52c2003-10-01 02:28:12 +0000655
Chris Liechtief1fe252015-08-27 23:25:21 +0200656 @property
657 def ri(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000658 """Read terminal status line: Ring Indicator"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200659 if not self.is_open:
660 raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000661 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200662 return struct.unpack('I', s)[0] & TIOCM_RI != 0
cliechti89b4af12002-02-12 23:24:41 +0000663
Chris Liechtief1fe252015-08-27 23:25:21 +0200664 @property
665 def cd(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000666 """Read terminal status line: Carrier Detect"""
Chris Liechti033f17c2015-08-30 21:28:04 +0200667 if not self.is_open:
668 raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000669 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200670 return struct.unpack('I', s)[0] & TIOCM_CD != 0
cliechti89b4af12002-02-12 23:24:41 +0000671
cliechtia30a8a02003-10-05 12:28:13 +0000672 # - - platform specific - - - -
673
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200674 @property
675 def out_waiting(self):
676 """Return the number of bytes currently in the output buffer."""
Chris Liechti11465c82015-08-04 15:55:22 +0200677 #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str)
cliechti28b8fd02011-12-28 21:39:42 +0000678 s = fcntl.ioctl(self.fd, TIOCOUTQ, TIOCM_zero_str)
Chris Liechti033f17c2015-08-30 21:28:04 +0200679 return struct.unpack('I', s)[0]
cliechti28b8fd02011-12-28 21:39:42 +0000680
cliechti8753bbc2005-01-15 20:32:51 +0000681 def fileno(self):
cliechti2f0f8a32011-12-28 22:10:00 +0000682 """\
683 For easier use of the serial port instance with select.
684 WARNING: this function is not portable to different platforms!
685 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200686 if not self.is_open:
687 raise portNotOpenError
cliechti8753bbc2005-01-15 20:32:51 +0000688 return self.fd
cliechti89b4af12002-02-12 23:24:41 +0000689
Chris Liechti518b0d32015-08-30 02:20:39 +0200690 def set_input_flow_control(self, enable=True):
cliechti2f0f8a32011-12-28 22:10:00 +0000691 """\
692 Manually control flow - when software flow control is enabled.
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200693 This will send XON (true) or XOFF (false) to the other device.
cliechti2f0f8a32011-12-28 22:10:00 +0000694 WARNING: this function is not portable to different platforms!
695 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200696 if not self.is_open:
697 raise portNotOpenError
cliechti4a601342011-12-29 02:22:17 +0000698 if enable:
Chris Liechti11465c82015-08-04 15:55:22 +0200699 termios.tcflow(self.fd, termios.TCION)
cliechti57e48a62009-08-03 22:29:58 +0000700 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200701 termios.tcflow(self.fd, termios.TCIOFF)
cliechti57e48a62009-08-03 22:29:58 +0000702
Chris Liechti518b0d32015-08-30 02:20:39 +0200703 def set_output_flow_control(self, enable=True):
cliechti2f0f8a32011-12-28 22:10:00 +0000704 """\
705 Manually control flow of outgoing data - when hardware or software flow
706 control is enabled.
707 WARNING: this function is not portable to different platforms!
708 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200709 if not self.is_open:
710 raise portNotOpenError
cliechti2f0f8a32011-12-28 22:10:00 +0000711 if enable:
Chris Liechti11465c82015-08-04 15:55:22 +0200712 termios.tcflow(self.fd, termios.TCOON)
cliechti2f0f8a32011-12-28 22:10:00 +0000713 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200714 termios.tcflow(self.fd, termios.TCOOFF)
cliechti2f0f8a32011-12-28 22:10:00 +0000715
Chris Liechti59848422016-06-04 22:28:14 +0200716 def nonblocking(self):
717 """DEPRECATED - has no use"""
718 import warnings
719 warnings.warn("nonblocking() has no effect, already nonblocking", DeprecationWarning)
720
cliechtif81362e2009-07-25 03:44:33 +0000721
cliechtia9a093e2010-01-02 03:05:08 +0000722class PosixPollSerial(Serial):
cliechti7d448562014-08-03 21:57:45 +0000723 """\
cliechtif0a81d42014-08-04 14:03:53 +0000724 Poll based read implementation. Not all systems support poll properly.
725 However this one has better handling of errors, such as a device
cliechti7d448562014-08-03 21:57:45 +0000726 disconnecting while it's in use (e.g. USB-serial unplugged).
727 """
cliechtia9a093e2010-01-02 03:05:08 +0000728
729 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000730 """\
731 Read size bytes from the serial port. If a timeout is set it may
732 return less characters as requested. With no timeout it will block
733 until the requested number of bytes is read.
734 """
Chris Liechtiacac2362016-03-29 22:37:48 +0200735 if not self.is_open:
Chris Liechti033f17c2015-08-30 21:28:04 +0200736 raise portNotOpenError
cliechtia9a093e2010-01-02 03:05:08 +0000737 read = bytearray()
Chris Liechtia5726382017-08-24 23:43:23 +0200738 timeout = Timeout(self._timeout)
cliechtia9a093e2010-01-02 03:05:08 +0000739 poll = select.poll()
Chris Liechti033f17c2015-08-30 21:28:04 +0200740 poll.register(self.fd, select.POLLIN | select.POLLERR | select.POLLHUP | select.POLLNVAL)
Chris Liechtia5726382017-08-24 23:43:23 +0200741 poll.register(self.pipe_abort_read_r, select.POLLIN | select.POLLERR | select.POLLHUP | select.POLLNVAL)
cliechtia9a093e2010-01-02 03:05:08 +0000742 if size > 0:
743 while len(read) < size:
744 # print "\tread(): size",size, "have", len(read) #debug
745 # wait until device becomes ready to read (or something fails)
Chris Liechtia5726382017-08-24 23:43:23 +0200746 for fd, event in poll.poll(None if timeout.is_infinite else (timeout.time_left() * 1000)):
747 if fd == self.pipe_abort_read_r:
748 break
Chris Liechti033f17c2015-08-30 21:28:04 +0200749 if event & (select.POLLERR | select.POLLHUP | select.POLLNVAL):
cliechtia9a093e2010-01-02 03:05:08 +0000750 raise SerialException('device reports error (poll)')
751 # we don't care if it is select.POLLIN or timeout, that's
752 # handled below
Chris Liechtia5726382017-08-24 23:43:23 +0200753 if fd == self.pipe_abort_read_r:
754 os.read(self.pipe_abort_read_r, 1000)
755 break
cliechtia9a093e2010-01-02 03:05:08 +0000756 buf = os.read(self.fd, size - len(read))
757 read.extend(buf)
Chris Liechtia5726382017-08-24 23:43:23 +0200758 if timeout.expired() \
759 or (self._inter_byte_timeout is not None and self._inter_byte_timeout > 0) and not buf:
cliechtia9a093e2010-01-02 03:05:08 +0000760 break # early abort on timeout
761 return bytes(read)
762
cliechtif81362e2009-07-25 03:44:33 +0000763
Chris Liechti4cf54702015-10-18 00:21:56 +0200764class VTIMESerial(Serial):
765 """\
766 Implement timeout using vtime of tty device instead of using select.
767 This means that no inter character timeout can be specified and that
768 the error handling is degraded.
769
770 Overall timeout is disabled when inter-character timeout is used.
771 """
772
Chris Liechti94284702015-11-15 01:21:48 +0100773 def _reconfigure_port(self, force_update=True):
Chris Liechti4cf54702015-10-18 00:21:56 +0200774 """Set communication parameters on opened port."""
775 super(VTIMESerial, self)._reconfigure_port()
Chris Liechtid6bcaaf2016-02-01 22:55:26 +0100776 fcntl.fcntl(self.fd, fcntl.F_SETFL, 0) # clear O_NONBLOCK
Chris Liechti4cf54702015-10-18 00:21:56 +0200777
778 if self._inter_byte_timeout is not None:
779 vmin = 1
780 vtime = int(self._inter_byte_timeout * 10)
Chris Liechti3ec9c412016-08-08 01:06:46 +0200781 elif self._timeout is None:
782 vmin = 1
783 vtime = 0
Chris Liechti4cf54702015-10-18 00:21:56 +0200784 else:
785 vmin = 0
786 vtime = int(self._timeout * 10)
787 try:
788 orig_attr = termios.tcgetattr(self.fd)
789 iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
790 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 +0100791 raise serial.SerialException("Could not configure port: {}".format(msg))
Chris Liechti4cf54702015-10-18 00:21:56 +0200792
793 if vtime < 0 or vtime > 255:
Chris Liechti984c5c52016-02-15 23:48:45 +0100794 raise ValueError('Invalid vtime: {!r}'.format(vtime))
Chris Liechti4cf54702015-10-18 00:21:56 +0200795 cc[termios.VTIME] = vtime
796 cc[termios.VMIN] = vmin
797
798 termios.tcsetattr(
799 self.fd,
800 termios.TCSANOW,
801 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
802
Chris Liechti4cf54702015-10-18 00:21:56 +0200803 def read(self, size=1):
804 """\
805 Read size bytes from the serial port. If a timeout is set it may
806 return less characters as requested. With no timeout it will block
807 until the requested number of bytes is read.
808 """
809 if not self.is_open:
810 raise portNotOpenError
811 read = bytearray()
812 while len(read) < size:
813 buf = os.read(self.fd, size - len(read))
814 if not buf:
815 break
816 read.extend(buf)
817 return bytes(read)
Chris Liechti3ec9c412016-08-08 01:06:46 +0200818
819 # hack to make hasattr return false
820 cancel_read = property()