blob: 62c0b589298b330ac7be6c4006dec5710d7056b8 [file] [log] [blame]
cliechti89b4af12002-02-12 23:24:41 +00001#!/usr/bin/env python
cliechti58b481c2009-02-16 20:42:32 +00002#
cliechtic54b2c82008-06-21 01:59:08 +00003# Python Serial Port Extension for Win32, Linux, BSD, Jython
4# module for serial IO for POSIX compatible systems, like Linux
5# see __init__.py
cliechti89b4af12002-02-12 23:24:41 +00006#
Chris Liechti68340d72015-08-03 14:15:48 +02007# (C) 2001-2015 Chris Liechti <cliechti@gmx.net>
Chris Liechtifbdd8a02015-08-09 02:37:45 +02008#
9# SPDX-License-Identifier: BSD-3-Clause
cliechti89b4af12002-02-12 23:24:41 +000010#
cliechtic54b2c82008-06-21 01:59:08 +000011# parts based on code from Grant B. Edwards <grante@visi.com>:
cliechti89b4af12002-02-12 23:24:41 +000012# ftp://ftp.visi.com/users/grante/python/PosixSerial.py
cliechti53c9fd42009-07-23 23:51:51 +000013#
cliechti89b4af12002-02-12 23:24:41 +000014# references: http://www.easysw.com/~mike/serial/serial.html
15
Chris Liechti33f0ec52015-08-06 16:37:21 +020016import errno
17import fcntl
Chris Liechti33f0ec52015-08-06 16:37:21 +020018import os
19import select
20import struct
21import sys
22import termios
23import time
cliechti39cfb7b2011-08-22 00:30:07 +000024from serial.serialutil import *
cliechti89b4af12002-02-12 23:24:41 +000025
cliechti89b4af12002-02-12 23:24:41 +000026
Chris Liechtid6847af2015-08-06 17:54:30 +020027class PlatformSpecificBase(object):
28 BAUDRATE_CONSTANTS = {}
cliechti89b4af12002-02-12 23:24:41 +000029
Chris Liechtid6847af2015-08-06 17:54:30 +020030 def number_to_device(self, port_number):
31 sys.stderr.write("""\
cliechti7aaead32009-07-23 14:02:41 +000032don't know how to number ttys on this system.
cliechti895e8302004-04-20 02:40:28 +000033! Use an explicit path (eg /dev/ttyS1) or send this information to
34! the author of this module:
cliechti89b4af12002-02-12 23:24:41 +000035
cliechti895e8302004-04-20 02:40:28 +000036sys.platform = %r
37os.name = %r
38serialposix.py version = %s
cliechti89b4af12002-02-12 23:24:41 +000039
40also add the device name of the serial port and where the
41counting starts for the first serial port.
42e.g. 'first serial port: /dev/ttyS0'
43and with a bit luck you can get this module running...
cliechti7aaead32009-07-23 14:02:41 +000044""" % (sys.platform, os.name, VERSION))
Chris Liechtid6847af2015-08-06 17:54:30 +020045 raise NotImplementedError('no number-to-device mapping defined on this platform')
46
47 def _set_special_baudrate(self, baudrate):
48 raise NotImplementedError('non-standard baudrates are not supported on this platform')
49
50 def _set_rs485_mode(self, rs485_settings):
51 raise NotImplementedError('RS485 not supported on this platform')
52
53# try to detect the OS so that a device can be selected...
54# this code block should supply a device() and set_special_baudrate() function
55# for the platform
56plat = sys.platform.lower()
57
58if plat[:5] == 'linux': # Linux (confirmed)
59 import array
60
61 # baudrate ioctls
62 TCGETS2 = 0x802C542A
63 TCSETS2 = 0x402C542B
64 BOTHER = 0o010000
65
66 # RS485 ioctls
67 TIOCGRS485 = 0x542E
68 TIOCSRS485 = 0x542F
69 SER_RS485_ENABLED = 0b00000001
70 SER_RS485_RTS_ON_SEND = 0b00000010
71 SER_RS485_RTS_AFTER_SEND = 0b00000100
72 SER_RS485_RX_DURING_TX = 0b00010000
73
74
75 class PlatformSpecific(PlatformSpecificBase):
76 BAUDRATE_CONSTANTS = {
77 0: 0o000000, # hang up
78 50: 0o000001,
79 75: 0o000002,
80 110: 0o000003,
81 134: 0o000004,
82 150: 0o000005,
83 200: 0o000006,
84 300: 0o000007,
85 600: 0o000010,
86 1200: 0o000011,
87 1800: 0o000012,
88 2400: 0o000013,
89 4800: 0o000014,
90 9600: 0o000015,
91 19200: 0o000016,
92 38400: 0o000017,
93 57600: 0o010001,
94 115200: 0o010002,
95 230400: 0o010003,
96 460800: 0o010004,
97 500000: 0o010005,
98 576000: 0o010006,
99 921600: 0o010007,
100 1000000: 0o010010,
101 1152000: 0o010011,
102 1500000: 0o010012,
103 2000000: 0o010013,
104 2500000: 0o010014,
105 3000000: 0o010015,
106 3500000: 0o010016,
107 4000000: 0o010017
108 }
109
110 def number_to_device(self, port_number):
111 return '/dev/ttyS%d' % (port_number,)
112
113 def _set_special_baudrate(self, baudrate):
114 # right size is 44 on x86_64, allow for some growth
115 buf = array.array('i', [0] * 64)
116 try:
117 # get serial_struct
118 fcntl.ioctl(self.fd, TCGETS2, buf)
119 # set custom speed
120 buf[2] &= ~termios.CBAUD
121 buf[2] |= BOTHER
122 buf[9] = buf[10] = baudrate
123
124 # set serial_struct
125 res = fcntl.ioctl(self.fd, TCSETS2, buf)
126 except IOError as e:
127 raise ValueError('Failed to set custom baud rate (%s): %s' % (baudrate, e))
128
129 def _set_rs485_mode(self, rs485_settings):
130 buf = array.array('i', [0] * 8) # flags, delaytx, delayrx, padding
131 try:
132 fcntl.ioctl(self.fd, TIOCGRS485, buf)
133 if rs485_settings is not None:
134 if rs485_settings.loopback:
135 buf[0] |= SER_RS485_RX_DURING_TX
136 else:
137 buf[0] &= ~SER_RS485_RX_DURING_TX
138 if rs485_settings.rts_level_for_tx:
139 buf[0] |= SER_RS485_RTS_ON_SEND
140 else:
141 buf[0] &= ~SER_RS485_RTS_ON_SEND
142 if rs485_settings.rts_level_for_rx:
143 buf[0] |= SER_RS485_RTS_AFTER_SEND
144 else:
145 buf[0] &= ~SER_RS485_RTS_AFTER_SEND
146 buf[1] = int(rs485_settings.delay_rts_before_send * 1000)
147 buf[2] = int(rs485_settings.delay_rts_after_send * 1000)
148 else:
149 buf[0] = 0 # clear SER_RS485_ENABLED
150 res = fcntl.ioctl(self.fd, TIOCSRS485, buf)
151 except IOError as e:
152 raise ValueError('Failed to set RS485 mode: %s' % (e,))
153
154
155elif plat == 'cygwin': # cygwin/win32 (confirmed)
156
157 class PlatformSpecific(PlatformSpecificBase):
158 BAUDRATE_CONSTANTS = {
159 128000: 0x01003,
160 256000: 0x01005,
161 500000: 0x01007,
162 576000: 0x01008,
163 921600: 0x01009,
164 1000000: 0x0100a,
165 1152000: 0x0100b,
166 1500000: 0x0100c,
167 2000000: 0x0100d,
168 2500000: 0x0100e,
169 3000000: 0x0100f
170 }
171
172 def number_to_device(self, port_number):
173 return '/dev/com%d' % (port_number + 1,)
174
175
176elif plat[:7] == 'openbsd': # OpenBSD
177 class PlatformSpecific(PlatformSpecificBase):
178 def number_to_device(self, port_number):
179 return '/dev/cua%02d' % (port_number,)
180
181elif plat[:3] == 'bsd' or plat[:7] == 'freebsd':
182 class PlatformSpecific(PlatformSpecificBase):
183 def number_to_device(self, port_number):
184 return '/dev/cuad%d' % (port_number,)
185
186elif plat[:6] == 'darwin': # OS X
187 import array
188 IOSSIOSPEED = 0x80045402 #_IOW('T', 2, speed_t)
189
190 class PlatformSpecific(PlatformSpecificBase):
191 def number_to_device(self, port_number):
192 return '/dev/cuad%d' % (port_number,)
193
194 osx_version = os.uname()[2].split('.')
195 # Tiger or above can support arbitrary serial speeds
196 if int(osx_version[0]) >= 8:
197 def _set_special_baudrate(self, baudrate):
198 # use IOKit-specific call to set up high speeds
199 buf = array.array('i', [baudrate])
200 fcntl.ioctl(self.fd, IOSSIOSPEED, buf, 1)
201
202
203elif plat[:6] == 'netbsd': # NetBSD 1.6 testing by Erk
204 class PlatformSpecific(PlatformSpecificBase):
205 def number_to_device(self, port_number):
206 return '/dev/dty%02d' % (port_number,)
207
208elif plat[:4] == 'irix': # IRIX (partially tested)
209 class PlatformSpecific(PlatformSpecificBase):
210 def number_to_device(self, port_number):
211 return '/dev/ttyf%d' % (port_number + 1,) #XXX different device names depending on flow control
212
213elif plat[:2] == 'hp': # HP-UX (not tested)
214 class PlatformSpecific(PlatformSpecificBase):
215 def number_to_device(self, port_number):
216 return '/dev/tty%dp0' % (port_number + 1,)
217
218elif plat[:5] == 'sunos': # Solaris/SunOS (confirmed)
219 class PlatformSpecific(PlatformSpecificBase):
220 def number_to_device(self, port_number):
221 return '/dev/tty%c' % (ord('a') + port_number,)
222
223elif plat[:3] == 'aix': # AIX
224 class PlatformSpecific(PlatformSpecificBase):
225 def number_to_device(self, port_number):
226 return '/dev/tty%d' % (port_number,)
227
228else:
229 class PlatformSpecific(PlatformSpecificBase):
230 pass
cliechti89b4af12002-02-12 23:24:41 +0000231
cliechti58b481c2009-02-16 20:42:32 +0000232# whats up with "aix", "beos", ....
233# they should work, just need to know the device names.
cliechti89b4af12002-02-12 23:24:41 +0000234
235
cliechti58b481c2009-02-16 20:42:32 +0000236# load some constants for later use.
Chris Liechti11465c82015-08-04 15:55:22 +0200237# try to use values from termios, use defaults from linux otherwise
Chris Liechtid6847af2015-08-06 17:54:30 +0200238TIOCMGET = getattr(termios, 'TIOCMGET', 0x5415)
239TIOCMBIS = getattr(termios, 'TIOCMBIS', 0x5416)
240TIOCMBIC = getattr(termios, 'TIOCMBIC', 0x5417)
241TIOCMSET = getattr(termios, 'TIOCMSET', 0x5418)
cliechti89b4af12002-02-12 23:24:41 +0000242
Chris Liechtid6847af2015-08-06 17:54:30 +0200243#TIOCM_LE = getattr(termios, 'TIOCM_LE', 0x001)
244TIOCM_DTR = getattr(termios, 'TIOCM_DTR', 0x002)
245TIOCM_RTS = getattr(termios, 'TIOCM_RTS', 0x004)
246#TIOCM_ST = getattr(termios, 'TIOCM_ST', 0x008)
247#TIOCM_SR = getattr(termios, 'TIOCM_SR', 0x010)
cliechti89b4af12002-02-12 23:24:41 +0000248
Chris Liechtid6847af2015-08-06 17:54:30 +0200249TIOCM_CTS = getattr(termios, 'TIOCM_CTS', 0x020)
250TIOCM_CAR = getattr(termios, 'TIOCM_CAR', 0x040)
251TIOCM_RNG = getattr(termios, 'TIOCM_RNG', 0x080)
252TIOCM_DSR = getattr(termios, 'TIOCM_DSR', 0x100)
253TIOCM_CD = getattr(termios, 'TIOCM_CD', TIOCM_CAR)
254TIOCM_RI = getattr(termios, 'TIOCM_RI', TIOCM_RNG)
255#TIOCM_OUT1 = getattr(termios, 'TIOCM_OUT1', 0x2000)
256#TIOCM_OUT2 = getattr(termios, 'TIOCM_OUT2', 0x4000)
Chris Liechti11465c82015-08-04 15:55:22 +0200257if hasattr(termios, 'TIOCINQ'):
258 TIOCINQ = termios.TIOCINQ
cliechti28b8fd02011-12-28 21:39:42 +0000259else:
Chris Liechtid6847af2015-08-06 17:54:30 +0200260 TIOCINQ = getattr(termios, 'FIONREAD', 0x541B)
261TIOCOUTQ = getattr(termios, 'TIOCOUTQ', 0x5411)
cliechti89b4af12002-02-12 23:24:41 +0000262
263TIOCM_zero_str = struct.pack('I', 0)
264TIOCM_RTS_str = struct.pack('I', TIOCM_RTS)
265TIOCM_DTR_str = struct.pack('I', TIOCM_DTR)
266
Chris Liechtid6847af2015-08-06 17:54:30 +0200267TIOCSBRK = getattr(termios, 'TIOCSBRK', 0x5427)
268TIOCCBRK = getattr(termios, 'TIOCCBRK', 0x5428)
cliechti997b63c2008-06-21 00:09:31 +0000269
Chris Liechti68340d72015-08-03 14:15:48 +0200270CMSPAR = 0o10000000000 # Use "stick" (mark/space) parity
cliechtiaec27ab2014-07-31 22:21:24 +0000271
cliechti89b4af12002-02-12 23:24:41 +0000272
Chris Liechtief6b7b42015-08-06 22:19:26 +0200273class Serial(SerialBase, PlatformSpecific):
cliechti7d448562014-08-03 21:57:45 +0000274 """\
275 Serial port class POSIX implementation. Serial port configuration is
cliechtid6bf52c2003-10-01 02:28:12 +0000276 done with termios and fcntl. Runs on Linux and many other Un*x like
cliechtif0a81d42014-08-04 14:03:53 +0000277 systems.
278 """
cliechtid6bf52c2003-10-01 02:28:12 +0000279
280 def open(self):
cliechti7d448562014-08-03 21:57:45 +0000281 """\
282 Open port with current settings. This may throw a SerialException
283 if the port cannot be opened."""
cliechtid6bf52c2003-10-01 02:28:12 +0000284 if self._port is None:
285 raise SerialException("Port must be configured before it can be used.")
cliechti02ef43a2011-03-24 23:33:12 +0000286 if self._isOpen:
287 raise SerialException("Port is already open.")
288 self.fd = None
cliechti58b481c2009-02-16 20:42:32 +0000289 # open
cliechti4616bf12002-04-08 23:13:14 +0000290 try:
291 self.fd = os.open(self.portstr, os.O_RDWR|os.O_NOCTTY|os.O_NONBLOCK)
Chris Liechti68340d72015-08-03 14:15:48 +0200292 except OSError as msg:
cliechti4616bf12002-04-08 23:13:14 +0000293 self.fd = None
cliechtiaf84daa2013-10-10 23:57:00 +0000294 raise SerialException(msg.errno, "could not open port %s: %s" % (self._port, msg))
Chris Liechti11465c82015-08-04 15:55:22 +0200295 #~ fcntl.fcntl(self.fd, fcntl.F_SETFL, 0) # set blocking
cliechti58b481c2009-02-16 20:42:32 +0000296
cliechtib2f5fc82006-10-20 00:09:07 +0000297 try:
298 self._reconfigurePort()
299 except:
cliechti2750b832009-07-28 00:13:52 +0000300 try:
301 os.close(self.fd)
302 except:
303 # ignore any exception when closing the port
304 # also to keep original exception that happened when setting up
305 pass
cliechtib2f5fc82006-10-20 00:09:07 +0000306 self.fd = None
cliechtif0a4f0f2009-07-21 21:12:37 +0000307 raise
cliechtib2f5fc82006-10-20 00:09:07 +0000308 else:
309 self._isOpen = True
Chris Liechtief1fe252015-08-27 23:25:21 +0200310 if not self.dsrdtr:
311 self._update_dtr_state()
312 if not self.rtscts:
313 self._update_rts_state()
314 self.reset_input_buffer()
cliechti58b481c2009-02-16 20:42:32 +0000315
316
cliechtid6bf52c2003-10-01 02:28:12 +0000317 def _reconfigurePort(self):
cliechtib2f5fc82006-10-20 00:09:07 +0000318 """Set communication parameters on opened port."""
cliechtic6178262004-03-22 22:04:52 +0000319 if self.fd is None:
cliechtia9a093e2010-01-02 03:05:08 +0000320 raise SerialException("Can only operate on a valid file descriptor")
cliechtie8c45422008-06-20 23:23:14 +0000321 custom_baud = None
cliechti58b481c2009-02-16 20:42:32 +0000322
cliechti2750b832009-07-28 00:13:52 +0000323 vmin = vtime = 0 # timeout is done via select
cliechti679bfa62008-06-20 23:58:15 +0000324 if self._interCharTimeout is not None:
325 vmin = 1
326 vtime = int(self._interCharTimeout * 10)
cliechti6ce7ab12002-11-07 02:15:00 +0000327 try:
cliechti4d0af5e2011-08-05 02:18:16 +0000328 orig_attr = termios.tcgetattr(self.fd)
329 iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
Chris Liechti68340d72015-08-03 14:15:48 +0200330 except termios.error as msg: # if a port is nonexistent but has a /dev file, it'll fail here
cliechtid6bf52c2003-10-01 02:28:12 +0000331 raise SerialException("Could not configure port: %s" % msg)
cliechti58b481c2009-02-16 20:42:32 +0000332 # set up raw mode / no echo / binary
Chris Liechti11465c82015-08-04 15:55:22 +0200333 cflag |= (termios.CLOCAL|termios.CREAD)
334 lflag &= ~(termios.ICANON|termios.ECHO|termios.ECHOE|termios.ECHOK|termios.ECHONL|
335 termios.ISIG|termios.IEXTEN) #|termios.ECHOPRT
cliechti2750b832009-07-28 00:13:52 +0000336 for flag in ('ECHOCTL', 'ECHOKE'): # netbsd workaround for Erk
Chris Liechti11465c82015-08-04 15:55:22 +0200337 if hasattr(termios, flag):
338 lflag &= ~getattr(termios, flag)
cliechti58b481c2009-02-16 20:42:32 +0000339
Chris Liechti11465c82015-08-04 15:55:22 +0200340 oflag &= ~(termios.OPOST|termios.ONLCR|termios.OCRNL)
341 iflag &= ~(termios.INLCR|termios.IGNCR|termios.ICRNL|termios.IGNBRK)
342 if hasattr(termios, 'IUCLC'):
343 iflag &= ~termios.IUCLC
344 if hasattr(termios, 'PARMRK'):
345 iflag &= ~termios.PARMRK
cliechti58b481c2009-02-16 20:42:32 +0000346
cliechtif0a4f0f2009-07-21 21:12:37 +0000347 # setup baud rate
cliechti89b4af12002-02-12 23:24:41 +0000348 try:
Chris Liechti11465c82015-08-04 15:55:22 +0200349 ispeed = ospeed = getattr(termios, 'B%s' % (self._baudrate))
cliechti895e8302004-04-20 02:40:28 +0000350 except AttributeError:
cliechtif1559d02007-11-08 23:43:58 +0000351 try:
Chris Liechtid6847af2015-08-06 17:54:30 +0200352 ispeed = ospeed = self.BAUDRATE_CONSTANTS[self._baudrate]
cliechtif1559d02007-11-08 23:43:58 +0000353 except KeyError:
cliechtie8c45422008-06-20 23:23:14 +0000354 #~ raise ValueError('Invalid baud rate: %r' % self._baudrate)
cliechtif0a4f0f2009-07-21 21:12:37 +0000355 # may need custom baud rate, it isn't in our list.
Chris Liechti11465c82015-08-04 15:55:22 +0200356 ispeed = ospeed = getattr(termios, 'B38400')
cliechtif0a4f0f2009-07-21 21:12:37 +0000357 try:
358 custom_baud = int(self._baudrate) # store for later
359 except ValueError:
360 raise ValueError('Invalid baud rate: %r' % self._baudrate)
361 else:
362 if custom_baud < 0:
363 raise ValueError('Invalid baud rate: %r' % self._baudrate)
cliechti58b481c2009-02-16 20:42:32 +0000364
365 # setup char len
Chris Liechti11465c82015-08-04 15:55:22 +0200366 cflag &= ~termios.CSIZE
cliechtid6bf52c2003-10-01 02:28:12 +0000367 if self._bytesize == 8:
Chris Liechti11465c82015-08-04 15:55:22 +0200368 cflag |= termios.CS8
cliechtid6bf52c2003-10-01 02:28:12 +0000369 elif self._bytesize == 7:
Chris Liechti11465c82015-08-04 15:55:22 +0200370 cflag |= termios.CS7
cliechtid6bf52c2003-10-01 02:28:12 +0000371 elif self._bytesize == 6:
Chris Liechti11465c82015-08-04 15:55:22 +0200372 cflag |= termios.CS6
cliechtid6bf52c2003-10-01 02:28:12 +0000373 elif self._bytesize == 5:
Chris Liechti11465c82015-08-04 15:55:22 +0200374 cflag |= termios.CS5
cliechti89b4af12002-02-12 23:24:41 +0000375 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000376 raise ValueError('Invalid char len: %r' % self._bytesize)
cliechtif0a81d42014-08-04 14:03:53 +0000377 # setup stop bits
cliechtid6bf52c2003-10-01 02:28:12 +0000378 if self._stopbits == STOPBITS_ONE:
Chris Liechti11465c82015-08-04 15:55:22 +0200379 cflag &= ~(termios.CSTOPB)
cliechti58b481c2009-02-16 20:42:32 +0000380 elif self._stopbits == STOPBITS_ONE_POINT_FIVE:
Chris Liechti11465c82015-08-04 15:55:22 +0200381 cflag |= (termios.CSTOPB) # XXX same as TWO.. there is no POSIX support for 1.5
cliechtid6bf52c2003-10-01 02:28:12 +0000382 elif self._stopbits == STOPBITS_TWO:
Chris Liechti11465c82015-08-04 15:55:22 +0200383 cflag |= (termios.CSTOPB)
cliechti89b4af12002-02-12 23:24:41 +0000384 else:
cliechti3172d3d2009-07-21 22:33:40 +0000385 raise ValueError('Invalid stop bit specification: %r' % self._stopbits)
cliechti58b481c2009-02-16 20:42:32 +0000386 # setup parity
Chris Liechti11465c82015-08-04 15:55:22 +0200387 iflag &= ~(termios.INPCK|termios.ISTRIP)
cliechtid6bf52c2003-10-01 02:28:12 +0000388 if self._parity == PARITY_NONE:
Chris Liechti11465c82015-08-04 15:55:22 +0200389 cflag &= ~(termios.PARENB|termios.PARODD)
cliechtid6bf52c2003-10-01 02:28:12 +0000390 elif self._parity == PARITY_EVEN:
Chris Liechti11465c82015-08-04 15:55:22 +0200391 cflag &= ~(termios.PARODD)
392 cflag |= (termios.PARENB)
cliechtid6bf52c2003-10-01 02:28:12 +0000393 elif self._parity == PARITY_ODD:
Chris Liechti11465c82015-08-04 15:55:22 +0200394 cflag |= (termios.PARENB|termios.PARODD)
cliechtiaec27ab2014-07-31 22:21:24 +0000395 elif self._parity == PARITY_MARK and plat[:5] == 'linux':
Chris Liechti11465c82015-08-04 15:55:22 +0200396 cflag |= (termios.PARENB|CMSPAR|termios.PARODD)
cliechtiaec27ab2014-07-31 22:21:24 +0000397 elif self._parity == PARITY_SPACE and plat[:5] == 'linux':
Chris Liechti11465c82015-08-04 15:55:22 +0200398 cflag |= (termios.PARENB|CMSPAR)
399 cflag &= ~(termios.PARODD)
cliechti89b4af12002-02-12 23:24:41 +0000400 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000401 raise ValueError('Invalid parity: %r' % self._parity)
cliechti58b481c2009-02-16 20:42:32 +0000402 # setup flow control
403 # xonxoff
Chris Liechti11465c82015-08-04 15:55:22 +0200404 if hasattr(termios, 'IXANY'):
cliechtid6bf52c2003-10-01 02:28:12 +0000405 if self._xonxoff:
Chris Liechti11465c82015-08-04 15:55:22 +0200406 iflag |= (termios.IXON|termios.IXOFF) #|termios.IXANY)
cliechti89b4af12002-02-12 23:24:41 +0000407 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200408 iflag &= ~(termios.IXON|termios.IXOFF|termios.IXANY)
cliechti89b4af12002-02-12 23:24:41 +0000409 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000410 if self._xonxoff:
Chris Liechti11465c82015-08-04 15:55:22 +0200411 iflag |= (termios.IXON|termios.IXOFF)
cliechti89b4af12002-02-12 23:24:41 +0000412 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200413 iflag &= ~(termios.IXON|termios.IXOFF)
cliechti58b481c2009-02-16 20:42:32 +0000414 # rtscts
Chris Liechti11465c82015-08-04 15:55:22 +0200415 if hasattr(termios, 'CRTSCTS'):
cliechtid6bf52c2003-10-01 02:28:12 +0000416 if self._rtscts:
Chris Liechti11465c82015-08-04 15:55:22 +0200417 cflag |= (termios.CRTSCTS)
cliechti89b4af12002-02-12 23:24:41 +0000418 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200419 cflag &= ~(termios.CRTSCTS)
420 elif hasattr(termios, 'CNEW_RTSCTS'): # try it with alternate constant name
cliechtid6bf52c2003-10-01 02:28:12 +0000421 if self._rtscts:
Chris Liechti11465c82015-08-04 15:55:22 +0200422 cflag |= (termios.CNEW_RTSCTS)
cliechtid4743692002-04-08 22:39:53 +0000423 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200424 cflag &= ~(termios.CNEW_RTSCTS)
cliechti2750b832009-07-28 00:13:52 +0000425 # XXX should there be a warning if setting up rtscts (and xonxoff etc) fails??
cliechti58b481c2009-02-16 20:42:32 +0000426
427 # buffer
cliechtif0a81d42014-08-04 14:03:53 +0000428 # vmin "minimal number of characters to be read. 0 for non blocking"
cliechtid6bf52c2003-10-01 02:28:12 +0000429 if vmin < 0 or vmin > 255:
430 raise ValueError('Invalid vmin: %r ' % vmin)
Chris Liechti11465c82015-08-04 15:55:22 +0200431 cc[termios.VMIN] = vmin
cliechti58b481c2009-02-16 20:42:32 +0000432 # vtime
cliechtid6bf52c2003-10-01 02:28:12 +0000433 if vtime < 0 or vtime > 255:
434 raise ValueError('Invalid vtime: %r' % vtime)
Chris Liechti11465c82015-08-04 15:55:22 +0200435 cc[termios.VTIME] = vtime
cliechti58b481c2009-02-16 20:42:32 +0000436 # activate settings
cliechti4d0af5e2011-08-05 02:18:16 +0000437 if [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] != orig_attr:
Chris Liechti11465c82015-08-04 15:55:22 +0200438 termios.tcsetattr(self.fd, termios.TCSANOW, [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
cliechti58b481c2009-02-16 20:42:32 +0000439
cliechtie8c45422008-06-20 23:23:14 +0000440 # apply custom baud rate, if any
441 if custom_baud is not None:
Chris Liechtid6847af2015-08-06 17:54:30 +0200442 self._set_special_baudrate(custom_baud)
443
444 if self._rs485_mode is not None:
445 self._set_rs485_mode(self._rs485_mode)
cliechti89b4af12002-02-12 23:24:41 +0000446
447 def close(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000448 """Close port"""
449 if self._isOpen:
cliechtic6178262004-03-22 22:04:52 +0000450 if self.fd is not None:
cliechtid6bf52c2003-10-01 02:28:12 +0000451 os.close(self.fd)
452 self.fd = None
453 self._isOpen = False
cliechti89b4af12002-02-12 23:24:41 +0000454
cliechtid6bf52c2003-10-01 02:28:12 +0000455 def makeDeviceName(self, port):
Chris Liechtid6847af2015-08-06 17:54:30 +0200456 return self.number_to_device(port)
cliechtid6bf52c2003-10-01 02:28:12 +0000457
458 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechti95c62212002-03-04 22:17:53 +0000459
Chris Liechtief1fe252015-08-27 23:25:21 +0200460 @property
461 def in_waiting(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000462 """Return the number of characters currently in the input buffer."""
Chris Liechti11465c82015-08-04 15:55:22 +0200463 #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str)
cliechtif5831e02002-12-05 23:15:27 +0000464 s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str)
cliechti89b4af12002-02-12 23:24:41 +0000465 return struct.unpack('I',s)[0]
466
cliechtia9a093e2010-01-02 03:05:08 +0000467 # select based implementation, proved to work on many systems
468 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000469 """\
470 Read size bytes from the serial port. If a timeout is set it may
471 return less characters as requested. With no timeout it will block
472 until the requested number of bytes is read.
473 """
cliechti899c9c42011-06-14 23:01:23 +0000474 if not self._isOpen: raise portNotOpenError
cliechtia9a093e2010-01-02 03:05:08 +0000475 read = bytearray()
476 while len(read) < size:
cliechti8d744de2013-10-11 14:31:13 +0000477 try:
478 ready,_,_ = select.select([self.fd],[],[], self._timeout)
479 # If select was used with a timeout, and the timeout occurs, it
480 # returns with empty lists -> thus abort read operation.
481 # For timeout == 0 (non-blocking operation) also abort when there
482 # is nothing to read.
483 if not ready:
484 break # timeout
485 buf = os.read(self.fd, size-len(read))
486 # read should always return some data as select reported it was
487 # ready to read when we get to this point.
488 if not buf:
489 # Disconnected devices, at least on Linux, show the
490 # behavior that they are always ready to read immediately
491 # but reading returns nothing.
492 raise SerialException('device reports readiness to read but returned no data (device disconnected or multiple access on port?)')
493 read.extend(buf)
Chris Liechti68340d72015-08-03 14:15:48 +0200494 except OSError as e:
cliechtic7cd7212014-08-03 21:34:38 +0000495 # this is for Python 3.x where select.error is a subclass of OSError
496 # ignore EAGAIN errors. all other errors are shown
497 if e.errno != errno.EAGAIN:
498 raise SerialException('read failed: %s' % (e,))
Chris Liechti68340d72015-08-03 14:15:48 +0200499 except select.error as e:
cliechtic7cd7212014-08-03 21:34:38 +0000500 # this is for Python 2.x
cliechti8d744de2013-10-11 14:31:13 +0000501 # ignore EAGAIN errors. all other errors are shown
502 # see also http://www.python.org/dev/peps/pep-3151/#select
503 if e[0] != errno.EAGAIN:
504 raise SerialException('read failed: %s' % (e,))
cliechtia9a093e2010-01-02 03:05:08 +0000505 return bytes(read)
cliechti89b4af12002-02-12 23:24:41 +0000506
cliechti4a567a02009-07-27 22:09:31 +0000507 def write(self, data):
cliechtid6bf52c2003-10-01 02:28:12 +0000508 """Output the given string over the serial port."""
cliechti899c9c42011-06-14 23:01:23 +0000509 if not self._isOpen: raise portNotOpenError
cliechti38077122013-10-16 02:57:27 +0000510 d = to_bytes(data)
511 tx_len = len(d)
cliechti3cf46d62009-08-07 00:19:57 +0000512 if self._writeTimeout is not None and self._writeTimeout > 0:
513 timeout = time.time() + self._writeTimeout
514 else:
515 timeout = None
cliechti9f7c2352013-10-11 01:13:46 +0000516 while tx_len > 0:
cliechti5d4d0bd2004-11-13 03:27:39 +0000517 try:
cliechti5d4d0bd2004-11-13 03:27:39 +0000518 n = os.write(self.fd, d)
cliechti3cf46d62009-08-07 00:19:57 +0000519 if timeout:
520 # when timeout is set, use select to wait for being ready
521 # with the time left as timeout
522 timeleft = timeout - time.time()
523 if timeleft < 0:
524 raise writeTimeoutError
525 _, ready, _ = select.select([], [self.fd], [], timeleft)
cliechti5d4d0bd2004-11-13 03:27:39 +0000526 if not ready:
527 raise writeTimeoutError
cliechti88c62442013-10-12 04:03:16 +0000528 else:
529 # wait for write operation
530 _, ready, _ = select.select([], [self.fd], [], None)
531 if not ready:
532 raise SerialException('write failed (select)')
cliechti5d4d0bd2004-11-13 03:27:39 +0000533 d = d[n:]
cliechti9f7c2352013-10-11 01:13:46 +0000534 tx_len -= n
Chris Liechti675f7e12015-08-03 15:48:41 +0200535 except SerialException:
536 raise
Chris Liechti68340d72015-08-03 14:15:48 +0200537 except OSError as v:
cliechti5d4d0bd2004-11-13 03:27:39 +0000538 if v.errno != errno.EAGAIN:
cliechti65722c92009-08-07 00:48:53 +0000539 raise SerialException('write failed: %s' % (v,))
cliechtif81362e2009-07-25 03:44:33 +0000540 return len(data)
cliechtid6bf52c2003-10-01 02:28:12 +0000541
cliechtia30a8a02003-10-05 12:28:13 +0000542 def flush(self):
cliechti7d448562014-08-03 21:57:45 +0000543 """\
544 Flush of file like objects. In this case, wait until all data
545 is written.
546 """
cliechtia30a8a02003-10-05 12:28:13 +0000547 self.drainOutput()
548
Chris Liechtief1fe252015-08-27 23:25:21 +0200549 def reset_input_buffer(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000550 """Clear input buffer, discarding all that is in the buffer."""
cliechti899c9c42011-06-14 23:01:23 +0000551 if not self._isOpen: raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200552 termios.tcflush(self.fd, termios.TCIFLUSH)
cliechti89b4af12002-02-12 23:24:41 +0000553
Chris Liechtief1fe252015-08-27 23:25:21 +0200554 def reset_output_buffer(self):
cliechti7d448562014-08-03 21:57:45 +0000555 """\
556 Clear output buffer, aborting the current output and discarding all
557 that is in the buffer.
558 """
cliechti899c9c42011-06-14 23:01:23 +0000559 if not self._isOpen: raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200560 termios.tcflush(self.fd, termios.TCOFLUSH)
cliechti89b4af12002-02-12 23:24:41 +0000561
Chris Liechtief1fe252015-08-27 23:25:21 +0200562 def send_break(self, duration=0.25):
cliechti7d448562014-08-03 21:57:45 +0000563 """\
564 Send break condition. Timed, returns to idle state after given
565 duration.
566 """
cliechti899c9c42011-06-14 23:01:23 +0000567 if not self._isOpen: raise portNotOpenError
cliechtiaaa04602006-02-05 23:02:46 +0000568 termios.tcsendbreak(self.fd, int(duration/0.25))
cliechti89b4af12002-02-12 23:24:41 +0000569
Chris Liechtief1fe252015-08-27 23:25:21 +0200570 def _update_break_state(self):
cliechti7d448562014-08-03 21:57:45 +0000571 """\
572 Set break: Controls TXD. When active, no transmitting is possible.
573 """
Chris Liechtief1fe252015-08-27 23:25:21 +0200574 if self._break_state:
cliechti997b63c2008-06-21 00:09:31 +0000575 fcntl.ioctl(self.fd, TIOCSBRK)
576 else:
577 fcntl.ioctl(self.fd, TIOCCBRK)
578
Chris Liechtief1fe252015-08-27 23:25:21 +0200579 def _update_rts_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000580 """Set terminal status line: Request To Send"""
Chris Liechtief1fe252015-08-27 23:25:21 +0200581 if self._rts_state:
cliechtid6bf52c2003-10-01 02:28:12 +0000582 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_RTS_str)
583 else:
584 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_RTS_str)
585
Chris Liechtief1fe252015-08-27 23:25:21 +0200586 def _update_dtr_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000587 """Set terminal status line: Data Terminal Ready"""
Chris Liechtief1fe252015-08-27 23:25:21 +0200588 if self._dtr_state:
cliechtid6bf52c2003-10-01 02:28:12 +0000589 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str)
590 else:
591 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_DTR_str)
592
Chris Liechtief1fe252015-08-27 23:25:21 +0200593 @property
594 def cts(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000595 """Read terminal status line: Clear To Send"""
cliechti899c9c42011-06-14 23:01:23 +0000596 if not self._isOpen: raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000597 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
598 return struct.unpack('I',s)[0] & TIOCM_CTS != 0
599
Chris Liechtief1fe252015-08-27 23:25:21 +0200600 @property
601 def dsr(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000602 """Read terminal status line: Data Set Ready"""
cliechti899c9c42011-06-14 23:01:23 +0000603 if not self._isOpen: raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000604 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
605 return struct.unpack('I',s)[0] & TIOCM_DSR != 0
606
Chris Liechtief1fe252015-08-27 23:25:21 +0200607 @property
608 def ri(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000609 """Read terminal status line: Ring Indicator"""
cliechti899c9c42011-06-14 23:01:23 +0000610 if not self._isOpen: raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000611 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
cliechtid6bf52c2003-10-01 02:28:12 +0000612 return struct.unpack('I',s)[0] & TIOCM_RI != 0
cliechti89b4af12002-02-12 23:24:41 +0000613
Chris Liechtief1fe252015-08-27 23:25:21 +0200614 @property
615 def cd(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000616 """Read terminal status line: Carrier Detect"""
cliechti899c9c42011-06-14 23:01:23 +0000617 if not self._isOpen: raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000618 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
cliechtid6bf52c2003-10-01 02:28:12 +0000619 return struct.unpack('I',s)[0] & TIOCM_CD != 0
cliechti89b4af12002-02-12 23:24:41 +0000620
cliechtia30a8a02003-10-05 12:28:13 +0000621 # - - platform specific - - - -
622
cliechti28b8fd02011-12-28 21:39:42 +0000623 def outWaiting(self):
624 """Return the number of characters currently in the output buffer."""
Chris Liechti11465c82015-08-04 15:55:22 +0200625 #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str)
cliechti28b8fd02011-12-28 21:39:42 +0000626 s = fcntl.ioctl(self.fd, TIOCOUTQ, TIOCM_zero_str)
627 return struct.unpack('I',s)[0]
628
cliechtia30a8a02003-10-05 12:28:13 +0000629 def drainOutput(self):
630 """internal - not portable!"""
cliechti899c9c42011-06-14 23:01:23 +0000631 if not self._isOpen: raise portNotOpenError
cliechtia30a8a02003-10-05 12:28:13 +0000632 termios.tcdrain(self.fd)
633
634 def nonblocking(self):
635 """internal - not portable!"""
cliechti899c9c42011-06-14 23:01:23 +0000636 if not self._isOpen: raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200637 fcntl.fcntl(self.fd, fcntl.F_SETFL, os.O_NONBLOCK)
cliechtia30a8a02003-10-05 12:28:13 +0000638
cliechti8753bbc2005-01-15 20:32:51 +0000639 def fileno(self):
cliechti2f0f8a32011-12-28 22:10:00 +0000640 """\
641 For easier use of the serial port instance with select.
642 WARNING: this function is not portable to different platforms!
643 """
cliechti899c9c42011-06-14 23:01:23 +0000644 if not self._isOpen: raise portNotOpenError
cliechti8753bbc2005-01-15 20:32:51 +0000645 return self.fd
cliechti89b4af12002-02-12 23:24:41 +0000646
cliechti2f0f8a32011-12-28 22:10:00 +0000647 def setXON(self, level=True):
648 """\
649 Manually control flow - when software flow control is enabled.
650 This will send XON (true) and XOFF (false) to the other device.
651 WARNING: this function is not portable to different platforms!
652 """
Chris Liechti905d5072015-08-03 21:41:49 +0200653 if not self._isOpen: raise portNotOpenError
cliechti4a601342011-12-29 02:22:17 +0000654 if enable:
Chris Liechti11465c82015-08-04 15:55:22 +0200655 termios.tcflow(self.fd, termios.TCION)
cliechti57e48a62009-08-03 22:29:58 +0000656 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200657 termios.tcflow(self.fd, termios.TCIOFF)
cliechti57e48a62009-08-03 22:29:58 +0000658
cliechti2f0f8a32011-12-28 22:10:00 +0000659 def flowControlOut(self, enable):
660 """\
661 Manually control flow of outgoing data - when hardware or software flow
662 control is enabled.
663 WARNING: this function is not portable to different platforms!
664 """
665 if not self._isOpen: raise portNotOpenError
666 if enable:
Chris Liechti11465c82015-08-04 15:55:22 +0200667 termios.tcflow(self.fd, termios.TCOON)
cliechti2f0f8a32011-12-28 22:10:00 +0000668 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200669 termios.tcflow(self.fd, termios.TCOOFF)
cliechti2f0f8a32011-12-28 22:10:00 +0000670
cliechtif81362e2009-07-25 03:44:33 +0000671
cliechtif81362e2009-07-25 03:44:33 +0000672
cliechtia9a093e2010-01-02 03:05:08 +0000673class PosixPollSerial(Serial):
cliechti7d448562014-08-03 21:57:45 +0000674 """\
cliechtif0a81d42014-08-04 14:03:53 +0000675 Poll based read implementation. Not all systems support poll properly.
676 However this one has better handling of errors, such as a device
cliechti7d448562014-08-03 21:57:45 +0000677 disconnecting while it's in use (e.g. USB-serial unplugged).
678 """
cliechtia9a093e2010-01-02 03:05:08 +0000679
680 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000681 """\
682 Read size bytes from the serial port. If a timeout is set it may
683 return less characters as requested. With no timeout it will block
684 until the requested number of bytes is read.
685 """
cliechtia9a093e2010-01-02 03:05:08 +0000686 if self.fd is None: raise portNotOpenError
687 read = bytearray()
688 poll = select.poll()
689 poll.register(self.fd, select.POLLIN|select.POLLERR|select.POLLHUP|select.POLLNVAL)
690 if size > 0:
691 while len(read) < size:
692 # print "\tread(): size",size, "have", len(read) #debug
693 # wait until device becomes ready to read (or something fails)
cliechti4cd0d2e2010-07-21 01:15:25 +0000694 for fd, event in poll.poll(self._timeout*1000):
cliechtia9a093e2010-01-02 03:05:08 +0000695 if event & (select.POLLERR|select.POLLHUP|select.POLLNVAL):
696 raise SerialException('device reports error (poll)')
697 # we don't care if it is select.POLLIN or timeout, that's
698 # handled below
699 buf = os.read(self.fd, size - len(read))
700 read.extend(buf)
701 if ((self._timeout is not None and self._timeout >= 0) or
702 (self._interCharTimeout is not None and self._interCharTimeout > 0)) and not buf:
703 break # early abort on timeout
704 return bytes(read)
705
cliechtif81362e2009-07-25 03:44:33 +0000706
cliechti89b4af12002-02-12 23:24:41 +0000707if __name__ == '__main__':
708 s = Serial(0,
cliechti53c9fd42009-07-23 23:51:51 +0000709 baudrate=19200, # baud rate
710 bytesize=EIGHTBITS, # number of data bits
cliechti3172d3d2009-07-21 22:33:40 +0000711 parity=PARITY_EVEN, # enable parity checking
cliechti53c9fd42009-07-23 23:51:51 +0000712 stopbits=STOPBITS_ONE, # number of stop bits
cliechti3172d3d2009-07-21 22:33:40 +0000713 timeout=3, # set a timeout value, None for waiting forever
714 xonxoff=0, # enable software flow control
715 rtscts=0, # enable RTS/CTS flow control
cliechti89b4af12002-02-12 23:24:41 +0000716 )
717 s.setRTS(1)
718 s.setDTR(1)
719 s.flushInput()
720 s.flushOutput()
721 s.write('hello')
cliechti109486b2009-08-02 00:00:11 +0000722 sys.stdout.write('%r\n' % s.read(5))
723 sys.stdout.write('%s\n' % s.inWaiting())
cliechti89b4af12002-02-12 23:24:41 +0000724 del s
cliechti4569bac2007-11-08 21:57:19 +0000725