blob: 26fecbd7b87e71d5932f48acc85ae5586c0d86ce [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>
cliechti89b4af12002-02-12 23:24:41 +00008# this is distributed under a free software license, see license.txt
9#
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 Liechti33f0ec52015-08-06 16:37:21 +020015import errno
16import fcntl
Chris Liechtiaf6d0462015-08-03 17:21:14 +020017import io
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
cliechti3172d3d2009-07-21 22:33:40 +000027# try to detect the OS so that a device can be selected...
cliechti53c9fd42009-07-23 23:51:51 +000028# this code block should supply a device() and set_special_baudrate() function
29# for the platform
cliechtid6bf52c2003-10-01 02:28:12 +000030plat = sys.platform.lower()
cliechti89b4af12002-02-12 23:24:41 +000031
cliechti3172d3d2009-07-21 22:33:40 +000032if plat[:5] == 'linux': # Linux (confirmed)
Chris Liechti33f0ec52015-08-06 16:37:21 +020033 import array
cliechti53c9fd42009-07-23 23:51:51 +000034
cliechti89b4af12002-02-12 23:24:41 +000035 def device(port):
36 return '/dev/ttyS%d' % port
37
cliechti1877c522013-10-11 14:02:26 +000038 TCGETS2 = 0x802C542A
39 TCSETS2 = 0x402C542B
40 BOTHER = 0o010000
cliechti53c9fd42009-07-23 23:51:51 +000041
42 def set_special_baudrate(port, baudrate):
cliechti1877c522013-10-11 14:02:26 +000043 # right size is 44 on x86_64, allow for some growth
cliechti1877c522013-10-11 14:02:26 +000044 buf = array.array('i', [0] * 64)
cliechti53c9fd42009-07-23 23:51:51 +000045
cliechti53c9fd42009-07-23 23:51:51 +000046 try:
cliechti95772d32013-10-11 14:38:13 +000047 # get serial_struct
Chris Liechti11465c82015-08-04 15:55:22 +020048 fcntl.ioctl(port.fd, TCGETS2, buf)
cliechti95772d32013-10-11 14:38:13 +000049 # set custom speed
Chris Liechti11465c82015-08-04 15:55:22 +020050 buf[2] &= ~termios.CBAUD
cliechti95772d32013-10-11 14:38:13 +000051 buf[2] |= BOTHER
52 buf[9] = buf[10] = baudrate
53
54 # set serial_struct
Chris Liechti11465c82015-08-04 15:55:22 +020055 res = fcntl.ioctl(port.fd, TCSETS2, buf)
Chris Liechti68340d72015-08-03 14:15:48 +020056 except IOError as e:
cliechti95772d32013-10-11 14:38:13 +000057 raise ValueError('Failed to set custom baud rate (%s): %s' % (baudrate, e))
cliechti53c9fd42009-07-23 23:51:51 +000058
cliechti99220a02009-08-14 00:21:25 +000059 baudrate_constants = {
Chris Liechti68340d72015-08-03 14:15:48 +020060 0: 0o000000, # hang up
61 50: 0o000001,
62 75: 0o000002,
63 110: 0o000003,
64 134: 0o000004,
65 150: 0o000005,
66 200: 0o000006,
67 300: 0o000007,
68 600: 0o000010,
69 1200: 0o000011,
70 1800: 0o000012,
71 2400: 0o000013,
72 4800: 0o000014,
73 9600: 0o000015,
74 19200: 0o000016,
75 38400: 0o000017,
76 57600: 0o010001,
77 115200: 0o010002,
78 230400: 0o010003,
79 460800: 0o010004,
80 500000: 0o010005,
81 576000: 0o010006,
82 921600: 0o010007,
83 1000000: 0o010010,
84 1152000: 0o010011,
85 1500000: 0o010012,
86 2000000: 0o010013,
87 2500000: 0o010014,
88 3000000: 0o010015,
89 3500000: 0o010016,
90 4000000: 0o010017
cliechti99220a02009-08-14 00:21:25 +000091 }
92
Chris Liechti33f0ec52015-08-06 16:37:21 +020093 # RS485 ioctls
94 TIOCGRS485 = 0x542E
95 TIOCSRS485 = 0x542F
96 SER_RS485_ENABLED = 0b00000001
97 SER_RS485_RTS_ON_SEND = 0b00000010
98 SER_RS485_RTS_AFTER_SEND = 0b00000100
99 SER_RS485_RX_DURING_TX = 0b00010000
100
101 def set_rs485_mode(port, rs485_settings):
102 buf = array.array('i', [0] * 8) # flags, delaytx, delayrx, padding
103
104 try:
105 fcntl.ioctl(port.fd, TIOCGRS485, buf)
106 if rs485_settings is not None:
107 if rs485_settings.loopback:
108 buf[0] |= SER_RS485_RX_DURING_TX
109 else:
110 buf[0] &= ~SER_RS485_RX_DURING_TX
111 if rs485_settings.rts_level_for_tx:
112 buf[0] |= SER_RS485_RTS_ON_SEND
113 else:
114 buf[0] &= ~SER_RS485_RTS_ON_SEND
115 if rs485_settings.rts_level_for_rx:
116 buf[0] |= SER_RS485_RTS_AFTER_SEND
117 else:
118 buf[0] &= ~SER_RS485_RTS_AFTER_SEND
119 buf[1] = int(rs485_settings.delay_rts_before_send * 1000)
120 buf[2] = int(rs485_settings.delay_rts_after_send * 1000)
121 else:
122 buf[0] = 0 # clear SER_RS485_ENABLED
123 res = fcntl.ioctl(port.fd, TIOCSRS485, buf)
124 except IOError as e:
125 raise ValueError('Failed to set RS485 mode: %s' % (e,))
126
127
cliechti53c9fd42009-07-23 23:51:51 +0000128elif plat == 'cygwin': # cygwin/win32 (confirmed)
129
cliechtif281fde2002-06-07 21:53:40 +0000130 def device(port):
cliechtif5831e02002-12-05 23:15:27 +0000131 return '/dev/com%d' % (port + 1)
cliechtif281fde2002-06-07 21:53:40 +0000132
cliechti53c9fd42009-07-23 23:51:51 +0000133 def set_special_baudrate(port, baudrate):
cliechti99220a02009-08-14 00:21:25 +0000134 raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
cliechti53c9fd42009-07-23 23:51:51 +0000135
cliechtia505de32013-05-31 01:27:25 +0000136 baudrate_constants = {
137 128000: 0x01003,
138 256000: 0x01005,
139 500000: 0x01007,
140 576000: 0x01008,
141 921600: 0x01009,
142 1000000: 0x0100a,
143 1152000: 0x0100b,
144 1500000: 0x0100c,
145 2000000: 0x0100d,
146 2500000: 0x0100e,
147 3000000: 0x0100f
148 }
cliechti53c9fd42009-07-23 23:51:51 +0000149
cliechti4a601342011-12-29 02:22:17 +0000150elif plat[:7] == 'openbsd': # OpenBSD
cliechti53c9fd42009-07-23 23:51:51 +0000151
cliechti89b4af12002-02-12 23:24:41 +0000152 def device(port):
cliechti4a601342011-12-29 02:22:17 +0000153 return '/dev/cua%02d' % port
cliechti89b4af12002-02-12 23:24:41 +0000154
cliechti53c9fd42009-07-23 23:51:51 +0000155 def set_special_baudrate(port, baudrate):
156 raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
157
cliechti99220a02009-08-14 00:21:25 +0000158 baudrate_constants = {}
159
cliechti89b4af12002-02-12 23:24:41 +0000160elif plat[:3] == 'bsd' or \
cliechti4a601342011-12-29 02:22:17 +0000161 plat[:7] == 'freebsd':
cliechti53c9fd42009-07-23 23:51:51 +0000162
cliechti89b4af12002-02-12 23:24:41 +0000163 def device(port):
cliechtieaa96882008-06-16 22:59:20 +0000164 return '/dev/cuad%d' % port
cliechti89b4af12002-02-12 23:24:41 +0000165
cliechti53c9fd42009-07-23 23:51:51 +0000166 def set_special_baudrate(port, baudrate):
167 raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
168
cliechti99220a02009-08-14 00:21:25 +0000169 baudrate_constants = {}
170
cliechti53c9fd42009-07-23 23:51:51 +0000171elif plat[:6] == 'darwin': # OS X
Chris Liechti33f0ec52015-08-06 16:37:21 +0200172 import array
cliechti53c9fd42009-07-23 23:51:51 +0000173
174 version = os.uname()[2].split('.')
175 # Tiger or above can support arbitrary serial speeds
176 if int(version[0]) >= 8:
cliechti53c9fd42009-07-23 23:51:51 +0000177 def set_special_baudrate(port, baudrate):
178 # use IOKit-specific call to set up high speeds
cliechti53c9fd42009-07-23 23:51:51 +0000179 buf = array.array('i', [baudrate])
180 IOSSIOSPEED = 0x80045402 #_IOW('T', 2, speed_t)
181 fcntl.ioctl(port.fd, IOSSIOSPEED, buf, 1)
182 else: # version < 8
183 def set_special_baudrate(port, baudrate):
184 raise ValueError("baud rate not supported")
185
186 def device(port):
187 return '/dev/cuad%d' % port
188
cliechti99220a02009-08-14 00:21:25 +0000189 baudrate_constants = {}
190
cliechti53c9fd42009-07-23 23:51:51 +0000191
cliechti3172d3d2009-07-21 22:33:40 +0000192elif plat[:6] == 'netbsd': # NetBSD 1.6 testing by Erk
cliechti53c9fd42009-07-23 23:51:51 +0000193
cliechti835996a2004-06-02 19:45:07 +0000194 def device(port):
195 return '/dev/dty%02d' % port
196
cliechti53c9fd42009-07-23 23:51:51 +0000197 def set_special_baudrate(port, baudrate):
198 raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
199
cliechti99220a02009-08-14 00:21:25 +0000200 baudrate_constants = {}
201
cliechti3172d3d2009-07-21 22:33:40 +0000202elif plat[:4] == 'irix': # IRIX (partially tested)
cliechti53c9fd42009-07-23 23:51:51 +0000203
cliechti89b4af12002-02-12 23:24:41 +0000204 def device(port):
cliechtie2418e92006-06-05 20:03:17 +0000205 return '/dev/ttyf%d' % (port+1) #XXX different device names depending on flow control
cliechti89b4af12002-02-12 23:24:41 +0000206
cliechti53c9fd42009-07-23 23:51:51 +0000207 def set_special_baudrate(port, baudrate):
208 raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
209
cliechti99220a02009-08-14 00:21:25 +0000210 baudrate_constants = {}
211
cliechti3172d3d2009-07-21 22:33:40 +0000212elif plat[:2] == 'hp': # HP-UX (not tested)
cliechti53c9fd42009-07-23 23:51:51 +0000213
cliechti89b4af12002-02-12 23:24:41 +0000214 def device(port):
215 return '/dev/tty%dp0' % (port+1)
216
cliechti53c9fd42009-07-23 23:51:51 +0000217 def set_special_baudrate(port, baudrate):
218 raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
219
cliechti99220a02009-08-14 00:21:25 +0000220 baudrate_constants = {}
221
cliechti3172d3d2009-07-21 22:33:40 +0000222elif plat[:5] == 'sunos': # Solaris/SunOS (confirmed)
cliechti53c9fd42009-07-23 23:51:51 +0000223
cliechti89b4af12002-02-12 23:24:41 +0000224 def device(port):
225 return '/dev/tty%c' % (ord('a')+port)
cliechti58b481c2009-02-16 20:42:32 +0000226
cliechti53c9fd42009-07-23 23:51:51 +0000227 def set_special_baudrate(port, baudrate):
228 raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
229
cliechti99220a02009-08-14 00:21:25 +0000230 baudrate_constants = {}
231
cliechti3172d3d2009-07-21 22:33:40 +0000232elif plat[:3] == 'aix': # AIX
cliechti53c9fd42009-07-23 23:51:51 +0000233
cliechti40e1b072005-03-12 12:05:26 +0000234 def device(port):
235 return '/dev/tty%d' % (port)
cliechti89b4af12002-02-12 23:24:41 +0000236
cliechti53c9fd42009-07-23 23:51:51 +0000237 def set_special_baudrate(port, baudrate):
238 raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
239
cliechti99220a02009-08-14 00:21:25 +0000240 baudrate_constants = {}
241
cliechti89b4af12002-02-12 23:24:41 +0000242else:
cliechtia9a093e2010-01-02 03:05:08 +0000243 # platform detection has failed...
cliechti7aaead32009-07-23 14:02:41 +0000244 sys.stderr.write("""\
245don't know how to number ttys on this system.
cliechti895e8302004-04-20 02:40:28 +0000246! Use an explicit path (eg /dev/ttyS1) or send this information to
247! the author of this module:
cliechti89b4af12002-02-12 23:24:41 +0000248
cliechti895e8302004-04-20 02:40:28 +0000249sys.platform = %r
250os.name = %r
251serialposix.py version = %s
cliechti89b4af12002-02-12 23:24:41 +0000252
253also add the device name of the serial port and where the
254counting starts for the first serial port.
255e.g. 'first serial port: /dev/ttyS0'
256and with a bit luck you can get this module running...
cliechti7aaead32009-07-23 14:02:41 +0000257""" % (sys.platform, os.name, VERSION))
cliechti58b481c2009-02-16 20:42:32 +0000258 # no exception, just continue with a brave attempt to build a device name
259 # even if the device name is not correct for the platform it has chances
cliechti3172d3d2009-07-21 22:33:40 +0000260 # to work using a string with the real device name as port parameter.
cliechtid6bf52c2003-10-01 02:28:12 +0000261 def device(portum):
262 return '/dev/ttyS%d' % portnum
cliechti53c9fd42009-07-23 23:51:51 +0000263 def set_special_baudrate(port, baudrate):
264 raise SerialException("sorry don't know how to handle non standard baud rate on this platform")
cliechti99220a02009-08-14 00:21:25 +0000265 baudrate_constants = {}
cliechtid6bf52c2003-10-01 02:28:12 +0000266 #~ raise Exception, "this module does not run on this platform, sorry."
cliechti89b4af12002-02-12 23:24:41 +0000267
cliechti58b481c2009-02-16 20:42:32 +0000268# whats up with "aix", "beos", ....
269# they should work, just need to know the device names.
cliechti89b4af12002-02-12 23:24:41 +0000270
271
cliechti58b481c2009-02-16 20:42:32 +0000272# load some constants for later use.
Chris Liechti11465c82015-08-04 15:55:22 +0200273# try to use values from termios, use defaults from linux otherwise
274TIOCMGET = hasattr(termios, 'TIOCMGET') and termios.TIOCMGET or 0x5415
275TIOCMBIS = hasattr(termios, 'TIOCMBIS') and termios.TIOCMBIS or 0x5416
276TIOCMBIC = hasattr(termios, 'TIOCMBIC') and termios.TIOCMBIC or 0x5417
277TIOCMSET = hasattr(termios, 'TIOCMSET') and termios.TIOCMSET or 0x5418
cliechti89b4af12002-02-12 23:24:41 +0000278
Chris Liechti11465c82015-08-04 15:55:22 +0200279#TIOCM_LE = hasattr(termios, 'TIOCM_LE') and termios.TIOCM_LE or 0x001
280TIOCM_DTR = hasattr(termios, 'TIOCM_DTR') and termios.TIOCM_DTR or 0x002
281TIOCM_RTS = hasattr(termios, 'TIOCM_RTS') and termios.TIOCM_RTS or 0x004
282#TIOCM_ST = hasattr(termios, 'TIOCM_ST') and termios.TIOCM_ST or 0x008
283#TIOCM_SR = hasattr(termios, 'TIOCM_SR') and termios.TIOCM_SR or 0x010
cliechti89b4af12002-02-12 23:24:41 +0000284
Chris Liechti11465c82015-08-04 15:55:22 +0200285TIOCM_CTS = hasattr(termios, 'TIOCM_CTS') and termios.TIOCM_CTS or 0x020
286TIOCM_CAR = hasattr(termios, 'TIOCM_CAR') and termios.TIOCM_CAR or 0x040
287TIOCM_RNG = hasattr(termios, 'TIOCM_RNG') and termios.TIOCM_RNG or 0x080
288TIOCM_DSR = hasattr(termios, 'TIOCM_DSR') and termios.TIOCM_DSR or 0x100
289TIOCM_CD = hasattr(termios, 'TIOCM_CD') and termios.TIOCM_CD or TIOCM_CAR
290TIOCM_RI = hasattr(termios, 'TIOCM_RI') and termios.TIOCM_RI or TIOCM_RNG
291#TIOCM_OUT1 = hasattr(termios, 'TIOCM_OUT1') and termios.TIOCM_OUT1 or 0x2000
292#TIOCM_OUT2 = hasattr(termios, 'TIOCM_OUT2') and termios.TIOCM_OUT2 or 0x4000
293if hasattr(termios, 'TIOCINQ'):
294 TIOCINQ = termios.TIOCINQ
cliechti28b8fd02011-12-28 21:39:42 +0000295else:
Chris Liechti11465c82015-08-04 15:55:22 +0200296 TIOCINQ = hasattr(termios, 'FIONREAD') and termios.FIONREAD or 0x541B
297TIOCOUTQ = hasattr(termios, 'TIOCOUTQ') and termios.TIOCOUTQ or 0x5411
cliechti89b4af12002-02-12 23:24:41 +0000298
299TIOCM_zero_str = struct.pack('I', 0)
300TIOCM_RTS_str = struct.pack('I', TIOCM_RTS)
301TIOCM_DTR_str = struct.pack('I', TIOCM_DTR)
302
Chris Liechti11465c82015-08-04 15:55:22 +0200303TIOCSBRK = hasattr(termios, 'TIOCSBRK') and termios.TIOCSBRK or 0x5427
304TIOCCBRK = hasattr(termios, 'TIOCCBRK') and termios.TIOCCBRK or 0x5428
cliechti997b63c2008-06-21 00:09:31 +0000305
Chris Liechti68340d72015-08-03 14:15:48 +0200306CMSPAR = 0o10000000000 # Use "stick" (mark/space) parity
cliechtiaec27ab2014-07-31 22:21:24 +0000307
cliechti89b4af12002-02-12 23:24:41 +0000308
Chris Liechtiaf6d0462015-08-03 17:21:14 +0200309class Serial(SerialBase, io.RawIOBase):
cliechti7d448562014-08-03 21:57:45 +0000310 """\
311 Serial port class POSIX implementation. Serial port configuration is
cliechtid6bf52c2003-10-01 02:28:12 +0000312 done with termios and fcntl. Runs on Linux and many other Un*x like
cliechtif0a81d42014-08-04 14:03:53 +0000313 systems.
314 """
cliechtid6bf52c2003-10-01 02:28:12 +0000315
316 def open(self):
cliechti7d448562014-08-03 21:57:45 +0000317 """\
318 Open port with current settings. This may throw a SerialException
319 if the port cannot be opened."""
cliechtid6bf52c2003-10-01 02:28:12 +0000320 if self._port is None:
321 raise SerialException("Port must be configured before it can be used.")
cliechti02ef43a2011-03-24 23:33:12 +0000322 if self._isOpen:
323 raise SerialException("Port is already open.")
324 self.fd = None
cliechti58b481c2009-02-16 20:42:32 +0000325 # open
cliechti4616bf12002-04-08 23:13:14 +0000326 try:
327 self.fd = os.open(self.portstr, os.O_RDWR|os.O_NOCTTY|os.O_NONBLOCK)
Chris Liechti68340d72015-08-03 14:15:48 +0200328 except OSError as msg:
cliechti4616bf12002-04-08 23:13:14 +0000329 self.fd = None
cliechtiaf84daa2013-10-10 23:57:00 +0000330 raise SerialException(msg.errno, "could not open port %s: %s" % (self._port, msg))
Chris Liechti11465c82015-08-04 15:55:22 +0200331 #~ fcntl.fcntl(self.fd, fcntl.F_SETFL, 0) # set blocking
cliechti58b481c2009-02-16 20:42:32 +0000332
cliechtib2f5fc82006-10-20 00:09:07 +0000333 try:
334 self._reconfigurePort()
335 except:
cliechti2750b832009-07-28 00:13:52 +0000336 try:
337 os.close(self.fd)
338 except:
339 # ignore any exception when closing the port
340 # also to keep original exception that happened when setting up
341 pass
cliechtib2f5fc82006-10-20 00:09:07 +0000342 self.fd = None
cliechtif0a4f0f2009-07-21 21:12:37 +0000343 raise
cliechtib2f5fc82006-10-20 00:09:07 +0000344 else:
345 self._isOpen = True
cliechti5c9b0722013-10-17 03:19:39 +0000346 self.flushInput()
cliechti58b481c2009-02-16 20:42:32 +0000347
348
cliechtid6bf52c2003-10-01 02:28:12 +0000349 def _reconfigurePort(self):
cliechtib2f5fc82006-10-20 00:09:07 +0000350 """Set communication parameters on opened port."""
cliechtic6178262004-03-22 22:04:52 +0000351 if self.fd is None:
cliechtia9a093e2010-01-02 03:05:08 +0000352 raise SerialException("Can only operate on a valid file descriptor")
cliechtie8c45422008-06-20 23:23:14 +0000353 custom_baud = None
cliechti58b481c2009-02-16 20:42:32 +0000354
cliechti2750b832009-07-28 00:13:52 +0000355 vmin = vtime = 0 # timeout is done via select
cliechti679bfa62008-06-20 23:58:15 +0000356 if self._interCharTimeout is not None:
357 vmin = 1
358 vtime = int(self._interCharTimeout * 10)
cliechti6ce7ab12002-11-07 02:15:00 +0000359 try:
cliechti4d0af5e2011-08-05 02:18:16 +0000360 orig_attr = termios.tcgetattr(self.fd)
361 iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
Chris Liechti68340d72015-08-03 14:15:48 +0200362 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 +0000363 raise SerialException("Could not configure port: %s" % msg)
cliechti58b481c2009-02-16 20:42:32 +0000364 # set up raw mode / no echo / binary
Chris Liechti11465c82015-08-04 15:55:22 +0200365 cflag |= (termios.CLOCAL|termios.CREAD)
366 lflag &= ~(termios.ICANON|termios.ECHO|termios.ECHOE|termios.ECHOK|termios.ECHONL|
367 termios.ISIG|termios.IEXTEN) #|termios.ECHOPRT
cliechti2750b832009-07-28 00:13:52 +0000368 for flag in ('ECHOCTL', 'ECHOKE'): # netbsd workaround for Erk
Chris Liechti11465c82015-08-04 15:55:22 +0200369 if hasattr(termios, flag):
370 lflag &= ~getattr(termios, flag)
cliechti58b481c2009-02-16 20:42:32 +0000371
Chris Liechti11465c82015-08-04 15:55:22 +0200372 oflag &= ~(termios.OPOST|termios.ONLCR|termios.OCRNL)
373 iflag &= ~(termios.INLCR|termios.IGNCR|termios.ICRNL|termios.IGNBRK)
374 if hasattr(termios, 'IUCLC'):
375 iflag &= ~termios.IUCLC
376 if hasattr(termios, 'PARMRK'):
377 iflag &= ~termios.PARMRK
cliechti58b481c2009-02-16 20:42:32 +0000378
cliechtif0a4f0f2009-07-21 21:12:37 +0000379 # setup baud rate
cliechti89b4af12002-02-12 23:24:41 +0000380 try:
Chris Liechti11465c82015-08-04 15:55:22 +0200381 ispeed = ospeed = getattr(termios, 'B%s' % (self._baudrate))
cliechti895e8302004-04-20 02:40:28 +0000382 except AttributeError:
cliechtif1559d02007-11-08 23:43:58 +0000383 try:
384 ispeed = ospeed = baudrate_constants[self._baudrate]
385 except KeyError:
cliechtie8c45422008-06-20 23:23:14 +0000386 #~ raise ValueError('Invalid baud rate: %r' % self._baudrate)
cliechtif0a4f0f2009-07-21 21:12:37 +0000387 # may need custom baud rate, it isn't in our list.
Chris Liechti11465c82015-08-04 15:55:22 +0200388 ispeed = ospeed = getattr(termios, 'B38400')
cliechtif0a4f0f2009-07-21 21:12:37 +0000389 try:
390 custom_baud = int(self._baudrate) # store for later
391 except ValueError:
392 raise ValueError('Invalid baud rate: %r' % self._baudrate)
393 else:
394 if custom_baud < 0:
395 raise ValueError('Invalid baud rate: %r' % self._baudrate)
cliechti58b481c2009-02-16 20:42:32 +0000396
397 # setup char len
Chris Liechti11465c82015-08-04 15:55:22 +0200398 cflag &= ~termios.CSIZE
cliechtid6bf52c2003-10-01 02:28:12 +0000399 if self._bytesize == 8:
Chris Liechti11465c82015-08-04 15:55:22 +0200400 cflag |= termios.CS8
cliechtid6bf52c2003-10-01 02:28:12 +0000401 elif self._bytesize == 7:
Chris Liechti11465c82015-08-04 15:55:22 +0200402 cflag |= termios.CS7
cliechtid6bf52c2003-10-01 02:28:12 +0000403 elif self._bytesize == 6:
Chris Liechti11465c82015-08-04 15:55:22 +0200404 cflag |= termios.CS6
cliechtid6bf52c2003-10-01 02:28:12 +0000405 elif self._bytesize == 5:
Chris Liechti11465c82015-08-04 15:55:22 +0200406 cflag |= termios.CS5
cliechti89b4af12002-02-12 23:24:41 +0000407 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000408 raise ValueError('Invalid char len: %r' % self._bytesize)
cliechtif0a81d42014-08-04 14:03:53 +0000409 # setup stop bits
cliechtid6bf52c2003-10-01 02:28:12 +0000410 if self._stopbits == STOPBITS_ONE:
Chris Liechti11465c82015-08-04 15:55:22 +0200411 cflag &= ~(termios.CSTOPB)
cliechti58b481c2009-02-16 20:42:32 +0000412 elif self._stopbits == STOPBITS_ONE_POINT_FIVE:
Chris Liechti11465c82015-08-04 15:55:22 +0200413 cflag |= (termios.CSTOPB) # XXX same as TWO.. there is no POSIX support for 1.5
cliechtid6bf52c2003-10-01 02:28:12 +0000414 elif self._stopbits == STOPBITS_TWO:
Chris Liechti11465c82015-08-04 15:55:22 +0200415 cflag |= (termios.CSTOPB)
cliechti89b4af12002-02-12 23:24:41 +0000416 else:
cliechti3172d3d2009-07-21 22:33:40 +0000417 raise ValueError('Invalid stop bit specification: %r' % self._stopbits)
cliechti58b481c2009-02-16 20:42:32 +0000418 # setup parity
Chris Liechti11465c82015-08-04 15:55:22 +0200419 iflag &= ~(termios.INPCK|termios.ISTRIP)
cliechtid6bf52c2003-10-01 02:28:12 +0000420 if self._parity == PARITY_NONE:
Chris Liechti11465c82015-08-04 15:55:22 +0200421 cflag &= ~(termios.PARENB|termios.PARODD)
cliechtid6bf52c2003-10-01 02:28:12 +0000422 elif self._parity == PARITY_EVEN:
Chris Liechti11465c82015-08-04 15:55:22 +0200423 cflag &= ~(termios.PARODD)
424 cflag |= (termios.PARENB)
cliechtid6bf52c2003-10-01 02:28:12 +0000425 elif self._parity == PARITY_ODD:
Chris Liechti11465c82015-08-04 15:55:22 +0200426 cflag |= (termios.PARENB|termios.PARODD)
cliechtiaec27ab2014-07-31 22:21:24 +0000427 elif self._parity == PARITY_MARK and plat[:5] == 'linux':
Chris Liechti11465c82015-08-04 15:55:22 +0200428 cflag |= (termios.PARENB|CMSPAR|termios.PARODD)
cliechtiaec27ab2014-07-31 22:21:24 +0000429 elif self._parity == PARITY_SPACE and plat[:5] == 'linux':
Chris Liechti11465c82015-08-04 15:55:22 +0200430 cflag |= (termios.PARENB|CMSPAR)
431 cflag &= ~(termios.PARODD)
cliechti89b4af12002-02-12 23:24:41 +0000432 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000433 raise ValueError('Invalid parity: %r' % self._parity)
cliechti58b481c2009-02-16 20:42:32 +0000434 # setup flow control
435 # xonxoff
Chris Liechti11465c82015-08-04 15:55:22 +0200436 if hasattr(termios, 'IXANY'):
cliechtid6bf52c2003-10-01 02:28:12 +0000437 if self._xonxoff:
Chris Liechti11465c82015-08-04 15:55:22 +0200438 iflag |= (termios.IXON|termios.IXOFF) #|termios.IXANY)
cliechti89b4af12002-02-12 23:24:41 +0000439 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200440 iflag &= ~(termios.IXON|termios.IXOFF|termios.IXANY)
cliechti89b4af12002-02-12 23:24:41 +0000441 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000442 if self._xonxoff:
Chris Liechti11465c82015-08-04 15:55:22 +0200443 iflag |= (termios.IXON|termios.IXOFF)
cliechti89b4af12002-02-12 23:24:41 +0000444 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200445 iflag &= ~(termios.IXON|termios.IXOFF)
cliechti58b481c2009-02-16 20:42:32 +0000446 # rtscts
Chris Liechti11465c82015-08-04 15:55:22 +0200447 if hasattr(termios, 'CRTSCTS'):
cliechtid6bf52c2003-10-01 02:28:12 +0000448 if self._rtscts:
Chris Liechti11465c82015-08-04 15:55:22 +0200449 cflag |= (termios.CRTSCTS)
cliechti89b4af12002-02-12 23:24:41 +0000450 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200451 cflag &= ~(termios.CRTSCTS)
452 elif hasattr(termios, 'CNEW_RTSCTS'): # try it with alternate constant name
cliechtid6bf52c2003-10-01 02:28:12 +0000453 if self._rtscts:
Chris Liechti11465c82015-08-04 15:55:22 +0200454 cflag |= (termios.CNEW_RTSCTS)
cliechtid4743692002-04-08 22:39:53 +0000455 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200456 cflag &= ~(termios.CNEW_RTSCTS)
cliechti2750b832009-07-28 00:13:52 +0000457 # XXX should there be a warning if setting up rtscts (and xonxoff etc) fails??
cliechti58b481c2009-02-16 20:42:32 +0000458
Chris Liechti33f0ec52015-08-06 16:37:21 +0200459 # XXX linux only
460 if self._rs485_mode is not None:
461 set_rs485_mode(self, self._rs485_mode)
462
cliechti58b481c2009-02-16 20:42:32 +0000463 # buffer
cliechtif0a81d42014-08-04 14:03:53 +0000464 # vmin "minimal number of characters to be read. 0 for non blocking"
cliechtid6bf52c2003-10-01 02:28:12 +0000465 if vmin < 0 or vmin > 255:
466 raise ValueError('Invalid vmin: %r ' % vmin)
Chris Liechti11465c82015-08-04 15:55:22 +0200467 cc[termios.VMIN] = vmin
cliechti58b481c2009-02-16 20:42:32 +0000468 # vtime
cliechtid6bf52c2003-10-01 02:28:12 +0000469 if vtime < 0 or vtime > 255:
470 raise ValueError('Invalid vtime: %r' % vtime)
Chris Liechti11465c82015-08-04 15:55:22 +0200471 cc[termios.VTIME] = vtime
cliechti58b481c2009-02-16 20:42:32 +0000472 # activate settings
cliechti4d0af5e2011-08-05 02:18:16 +0000473 if [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] != orig_attr:
Chris Liechti11465c82015-08-04 15:55:22 +0200474 termios.tcsetattr(self.fd, termios.TCSANOW, [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
cliechti58b481c2009-02-16 20:42:32 +0000475
cliechtie8c45422008-06-20 23:23:14 +0000476 # apply custom baud rate, if any
477 if custom_baud is not None:
cliechti53c9fd42009-07-23 23:51:51 +0000478 set_special_baudrate(self, custom_baud)
cliechti89b4af12002-02-12 23:24:41 +0000479
480 def close(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000481 """Close port"""
482 if self._isOpen:
cliechtic6178262004-03-22 22:04:52 +0000483 if self.fd is not None:
cliechtid6bf52c2003-10-01 02:28:12 +0000484 os.close(self.fd)
485 self.fd = None
486 self._isOpen = False
cliechti89b4af12002-02-12 23:24:41 +0000487
cliechtid6bf52c2003-10-01 02:28:12 +0000488 def makeDeviceName(self, port):
489 return device(port)
490
491 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechti95c62212002-03-04 22:17:53 +0000492
cliechti89b4af12002-02-12 23:24:41 +0000493 def inWaiting(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000494 """Return the number of characters currently in the input buffer."""
Chris Liechti11465c82015-08-04 15:55:22 +0200495 #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str)
cliechtif5831e02002-12-05 23:15:27 +0000496 s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str)
cliechti89b4af12002-02-12 23:24:41 +0000497 return struct.unpack('I',s)[0]
498
cliechtia9a093e2010-01-02 03:05:08 +0000499 # select based implementation, proved to work on many systems
500 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000501 """\
502 Read size bytes from the serial port. If a timeout is set it may
503 return less characters as requested. With no timeout it will block
504 until the requested number of bytes is read.
505 """
cliechti899c9c42011-06-14 23:01:23 +0000506 if not self._isOpen: raise portNotOpenError
cliechtia9a093e2010-01-02 03:05:08 +0000507 read = bytearray()
508 while len(read) < size:
cliechti8d744de2013-10-11 14:31:13 +0000509 try:
510 ready,_,_ = select.select([self.fd],[],[], self._timeout)
511 # If select was used with a timeout, and the timeout occurs, it
512 # returns with empty lists -> thus abort read operation.
513 # For timeout == 0 (non-blocking operation) also abort when there
514 # is nothing to read.
515 if not ready:
516 break # timeout
517 buf = os.read(self.fd, size-len(read))
518 # read should always return some data as select reported it was
519 # ready to read when we get to this point.
520 if not buf:
521 # Disconnected devices, at least on Linux, show the
522 # behavior that they are always ready to read immediately
523 # but reading returns nothing.
524 raise SerialException('device reports readiness to read but returned no data (device disconnected or multiple access on port?)')
525 read.extend(buf)
Chris Liechti68340d72015-08-03 14:15:48 +0200526 except OSError as e:
cliechtic7cd7212014-08-03 21:34:38 +0000527 # this is for Python 3.x where select.error is a subclass of OSError
528 # ignore EAGAIN errors. all other errors are shown
529 if e.errno != errno.EAGAIN:
530 raise SerialException('read failed: %s' % (e,))
Chris Liechti68340d72015-08-03 14:15:48 +0200531 except select.error as e:
cliechtic7cd7212014-08-03 21:34:38 +0000532 # this is for Python 2.x
cliechti8d744de2013-10-11 14:31:13 +0000533 # ignore EAGAIN errors. all other errors are shown
534 # see also http://www.python.org/dev/peps/pep-3151/#select
535 if e[0] != errno.EAGAIN:
536 raise SerialException('read failed: %s' % (e,))
cliechtia9a093e2010-01-02 03:05:08 +0000537 return bytes(read)
cliechti89b4af12002-02-12 23:24:41 +0000538
cliechti4a567a02009-07-27 22:09:31 +0000539 def write(self, data):
cliechtid6bf52c2003-10-01 02:28:12 +0000540 """Output the given string over the serial port."""
cliechti899c9c42011-06-14 23:01:23 +0000541 if not self._isOpen: raise portNotOpenError
cliechti38077122013-10-16 02:57:27 +0000542 d = to_bytes(data)
543 tx_len = len(d)
cliechti3cf46d62009-08-07 00:19:57 +0000544 if self._writeTimeout is not None and self._writeTimeout > 0:
545 timeout = time.time() + self._writeTimeout
546 else:
547 timeout = None
cliechti9f7c2352013-10-11 01:13:46 +0000548 while tx_len > 0:
cliechti5d4d0bd2004-11-13 03:27:39 +0000549 try:
cliechti5d4d0bd2004-11-13 03:27:39 +0000550 n = os.write(self.fd, d)
cliechti3cf46d62009-08-07 00:19:57 +0000551 if timeout:
552 # when timeout is set, use select to wait for being ready
553 # with the time left as timeout
554 timeleft = timeout - time.time()
555 if timeleft < 0:
556 raise writeTimeoutError
557 _, ready, _ = select.select([], [self.fd], [], timeleft)
cliechti5d4d0bd2004-11-13 03:27:39 +0000558 if not ready:
559 raise writeTimeoutError
cliechti88c62442013-10-12 04:03:16 +0000560 else:
561 # wait for write operation
562 _, ready, _ = select.select([], [self.fd], [], None)
563 if not ready:
564 raise SerialException('write failed (select)')
cliechti5d4d0bd2004-11-13 03:27:39 +0000565 d = d[n:]
cliechti9f7c2352013-10-11 01:13:46 +0000566 tx_len -= n
Chris Liechti675f7e12015-08-03 15:48:41 +0200567 except SerialException:
568 raise
Chris Liechti68340d72015-08-03 14:15:48 +0200569 except OSError as v:
cliechti5d4d0bd2004-11-13 03:27:39 +0000570 if v.errno != errno.EAGAIN:
cliechti65722c92009-08-07 00:48:53 +0000571 raise SerialException('write failed: %s' % (v,))
cliechtif81362e2009-07-25 03:44:33 +0000572 return len(data)
cliechtid6bf52c2003-10-01 02:28:12 +0000573
cliechtia30a8a02003-10-05 12:28:13 +0000574 def flush(self):
cliechti7d448562014-08-03 21:57:45 +0000575 """\
576 Flush of file like objects. In this case, wait until all data
577 is written.
578 """
cliechtia30a8a02003-10-05 12:28:13 +0000579 self.drainOutput()
580
cliechti89b4af12002-02-12 23:24:41 +0000581 def flushInput(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000582 """Clear input buffer, discarding all that is in the buffer."""
cliechti899c9c42011-06-14 23:01:23 +0000583 if not self._isOpen: raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200584 termios.tcflush(self.fd, termios.TCIFLUSH)
cliechti89b4af12002-02-12 23:24:41 +0000585
586 def flushOutput(self):
cliechti7d448562014-08-03 21:57:45 +0000587 """\
588 Clear output buffer, aborting the current output and discarding all
589 that is in the buffer.
590 """
cliechti899c9c42011-06-14 23:01:23 +0000591 if not self._isOpen: raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200592 termios.tcflush(self.fd, termios.TCOFLUSH)
cliechti89b4af12002-02-12 23:24:41 +0000593
cliechtiaaa04602006-02-05 23:02:46 +0000594 def sendBreak(self, duration=0.25):
cliechti7d448562014-08-03 21:57:45 +0000595 """\
596 Send break condition. Timed, returns to idle state after given
597 duration.
598 """
cliechti899c9c42011-06-14 23:01:23 +0000599 if not self._isOpen: raise portNotOpenError
cliechtiaaa04602006-02-05 23:02:46 +0000600 termios.tcsendbreak(self.fd, int(duration/0.25))
cliechti89b4af12002-02-12 23:24:41 +0000601
cliechti997b63c2008-06-21 00:09:31 +0000602 def setBreak(self, level=1):
cliechti7d448562014-08-03 21:57:45 +0000603 """\
604 Set break: Controls TXD. When active, no transmitting is possible.
605 """
cliechti997b63c2008-06-21 00:09:31 +0000606 if self.fd is None: raise portNotOpenError
607 if level:
608 fcntl.ioctl(self.fd, TIOCSBRK)
609 else:
610 fcntl.ioctl(self.fd, TIOCCBRK)
611
cliechti93db61b2006-08-26 19:16:18 +0000612 def setRTS(self, level=1):
cliechtid6bf52c2003-10-01 02:28:12 +0000613 """Set terminal status line: Request To Send"""
cliechti899c9c42011-06-14 23:01:23 +0000614 if not self._isOpen: raise portNotOpenError
cliechtib2f5fc82006-10-20 00:09:07 +0000615 if level:
cliechtid6bf52c2003-10-01 02:28:12 +0000616 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_RTS_str)
617 else:
618 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_RTS_str)
619
cliechti93db61b2006-08-26 19:16:18 +0000620 def setDTR(self, level=1):
cliechtid6bf52c2003-10-01 02:28:12 +0000621 """Set terminal status line: Data Terminal Ready"""
cliechti899c9c42011-06-14 23:01:23 +0000622 if not self._isOpen: raise portNotOpenError
cliechtib2f5fc82006-10-20 00:09:07 +0000623 if level:
cliechtid6bf52c2003-10-01 02:28:12 +0000624 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str)
625 else:
626 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_DTR_str)
627
628 def getCTS(self):
629 """Read terminal status line: Clear To Send"""
cliechti899c9c42011-06-14 23:01:23 +0000630 if not self._isOpen: raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000631 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
632 return struct.unpack('I',s)[0] & TIOCM_CTS != 0
633
634 def getDSR(self):
635 """Read terminal status line: Data Set Ready"""
cliechti899c9c42011-06-14 23:01:23 +0000636 if not self._isOpen: raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000637 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
638 return struct.unpack('I',s)[0] & TIOCM_DSR != 0
639
cliechtid6bf52c2003-10-01 02:28:12 +0000640 def getRI(self):
641 """Read terminal status line: Ring Indicator"""
cliechti899c9c42011-06-14 23:01:23 +0000642 if not self._isOpen: raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000643 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
cliechtid6bf52c2003-10-01 02:28:12 +0000644 return struct.unpack('I',s)[0] & TIOCM_RI != 0
cliechti89b4af12002-02-12 23:24:41 +0000645
646 def getCD(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000647 """Read terminal status line: Carrier Detect"""
cliechti899c9c42011-06-14 23:01:23 +0000648 if not self._isOpen: raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000649 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
cliechtid6bf52c2003-10-01 02:28:12 +0000650 return struct.unpack('I',s)[0] & TIOCM_CD != 0
cliechti89b4af12002-02-12 23:24:41 +0000651
cliechtia30a8a02003-10-05 12:28:13 +0000652 # - - platform specific - - - -
653
cliechti28b8fd02011-12-28 21:39:42 +0000654 def outWaiting(self):
655 """Return the number of characters currently in the output buffer."""
Chris Liechti11465c82015-08-04 15:55:22 +0200656 #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str)
cliechti28b8fd02011-12-28 21:39:42 +0000657 s = fcntl.ioctl(self.fd, TIOCOUTQ, TIOCM_zero_str)
658 return struct.unpack('I',s)[0]
659
cliechtia30a8a02003-10-05 12:28:13 +0000660 def drainOutput(self):
661 """internal - not portable!"""
cliechti899c9c42011-06-14 23:01:23 +0000662 if not self._isOpen: raise portNotOpenError
cliechtia30a8a02003-10-05 12:28:13 +0000663 termios.tcdrain(self.fd)
664
665 def nonblocking(self):
666 """internal - not portable!"""
cliechti899c9c42011-06-14 23:01:23 +0000667 if not self._isOpen: raise portNotOpenError
Chris Liechti11465c82015-08-04 15:55:22 +0200668 fcntl.fcntl(self.fd, fcntl.F_SETFL, os.O_NONBLOCK)
cliechtia30a8a02003-10-05 12:28:13 +0000669
cliechti8753bbc2005-01-15 20:32:51 +0000670 def fileno(self):
cliechti2f0f8a32011-12-28 22:10:00 +0000671 """\
672 For easier use of the serial port instance with select.
673 WARNING: this function is not portable to different platforms!
674 """
cliechti899c9c42011-06-14 23:01:23 +0000675 if not self._isOpen: raise portNotOpenError
cliechti8753bbc2005-01-15 20:32:51 +0000676 return self.fd
cliechti89b4af12002-02-12 23:24:41 +0000677
cliechti2f0f8a32011-12-28 22:10:00 +0000678 def setXON(self, level=True):
679 """\
680 Manually control flow - when software flow control is enabled.
681 This will send XON (true) and XOFF (false) to the other device.
682 WARNING: this function is not portable to different platforms!
683 """
Chris Liechti905d5072015-08-03 21:41:49 +0200684 if not self._isOpen: raise portNotOpenError
cliechti4a601342011-12-29 02:22:17 +0000685 if enable:
Chris Liechti11465c82015-08-04 15:55:22 +0200686 termios.tcflow(self.fd, termios.TCION)
cliechti57e48a62009-08-03 22:29:58 +0000687 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200688 termios.tcflow(self.fd, termios.TCIOFF)
cliechti57e48a62009-08-03 22:29:58 +0000689
cliechti2f0f8a32011-12-28 22:10:00 +0000690 def flowControlOut(self, enable):
691 """\
692 Manually control flow of outgoing data - when hardware or software flow
693 control is enabled.
694 WARNING: this function is not portable to different platforms!
695 """
696 if not self._isOpen: raise portNotOpenError
697 if enable:
Chris Liechti11465c82015-08-04 15:55:22 +0200698 termios.tcflow(self.fd, termios.TCOON)
cliechti2f0f8a32011-12-28 22:10:00 +0000699 else:
Chris Liechti11465c82015-08-04 15:55:22 +0200700 termios.tcflow(self.fd, termios.TCOOFF)
cliechti2f0f8a32011-12-28 22:10:00 +0000701
cliechtif81362e2009-07-25 03:44:33 +0000702
cliechtif81362e2009-07-25 03:44:33 +0000703
cliechtia9a093e2010-01-02 03:05:08 +0000704class PosixPollSerial(Serial):
cliechti7d448562014-08-03 21:57:45 +0000705 """\
cliechtif0a81d42014-08-04 14:03:53 +0000706 Poll based read implementation. Not all systems support poll properly.
707 However this one has better handling of errors, such as a device
cliechti7d448562014-08-03 21:57:45 +0000708 disconnecting while it's in use (e.g. USB-serial unplugged).
709 """
cliechtia9a093e2010-01-02 03:05:08 +0000710
711 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000712 """\
713 Read size bytes from the serial port. If a timeout is set it may
714 return less characters as requested. With no timeout it will block
715 until the requested number of bytes is read.
716 """
cliechtia9a093e2010-01-02 03:05:08 +0000717 if self.fd is None: raise portNotOpenError
718 read = bytearray()
719 poll = select.poll()
720 poll.register(self.fd, select.POLLIN|select.POLLERR|select.POLLHUP|select.POLLNVAL)
721 if size > 0:
722 while len(read) < size:
723 # print "\tread(): size",size, "have", len(read) #debug
724 # wait until device becomes ready to read (or something fails)
cliechti4cd0d2e2010-07-21 01:15:25 +0000725 for fd, event in poll.poll(self._timeout*1000):
cliechtia9a093e2010-01-02 03:05:08 +0000726 if event & (select.POLLERR|select.POLLHUP|select.POLLNVAL):
727 raise SerialException('device reports error (poll)')
728 # we don't care if it is select.POLLIN or timeout, that's
729 # handled below
730 buf = os.read(self.fd, size - len(read))
731 read.extend(buf)
732 if ((self._timeout is not None and self._timeout >= 0) or
733 (self._interCharTimeout is not None and self._interCharTimeout > 0)) and not buf:
734 break # early abort on timeout
735 return bytes(read)
736
cliechtif81362e2009-07-25 03:44:33 +0000737
cliechti89b4af12002-02-12 23:24:41 +0000738if __name__ == '__main__':
739 s = Serial(0,
cliechti53c9fd42009-07-23 23:51:51 +0000740 baudrate=19200, # baud rate
741 bytesize=EIGHTBITS, # number of data bits
cliechti3172d3d2009-07-21 22:33:40 +0000742 parity=PARITY_EVEN, # enable parity checking
cliechti53c9fd42009-07-23 23:51:51 +0000743 stopbits=STOPBITS_ONE, # number of stop bits
cliechti3172d3d2009-07-21 22:33:40 +0000744 timeout=3, # set a timeout value, None for waiting forever
745 xonxoff=0, # enable software flow control
746 rtscts=0, # enable RTS/CTS flow control
cliechti89b4af12002-02-12 23:24:41 +0000747 )
748 s.setRTS(1)
749 s.setDTR(1)
750 s.flushInput()
751 s.flushOutput()
752 s.write('hello')
cliechti109486b2009-08-02 00:00:11 +0000753 sys.stdout.write('%r\n' % s.read(5))
754 sys.stdout.write('%s\n' % s.inWaiting())
cliechti89b4af12002-02-12 23:24:41 +0000755 del s
cliechti4569bac2007-11-08 21:57:19 +0000756