blob: 131e31bda851b6a7c3966808e04177f528a7d567 [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#
cliechtia9a093e2010-01-02 03:05:08 +00007# (C) 2001-2010 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
cliechti3cf46d62009-08-07 00:19:57 +000015import sys, os, fcntl, termios, struct, select, errno, time
cliechti39cfb7b2011-08-22 00:30:07 +000016from serial.serialutil import *
cliechti89b4af12002-02-12 23:24:41 +000017
cliechti53c9fd42009-07-23 23:51:51 +000018# Do check the Python version as some constants have moved.
cliechti89b4af12002-02-12 23:24:41 +000019if (sys.hexversion < 0x020100f0):
20 import TERMIOS
21else:
22 TERMIOS = termios
23
24if (sys.hexversion < 0x020200f0):
25 import FCNTL
26else:
27 FCNTL = fcntl
28
cliechti3172d3d2009-07-21 22:33:40 +000029# try to detect the OS so that a device can be selected...
cliechti53c9fd42009-07-23 23:51:51 +000030# this code block should supply a device() and set_special_baudrate() function
31# for the platform
cliechtid6bf52c2003-10-01 02:28:12 +000032plat = sys.platform.lower()
cliechti89b4af12002-02-12 23:24:41 +000033
cliechti3172d3d2009-07-21 22:33:40 +000034if plat[:5] == 'linux': # Linux (confirmed)
cliechti53c9fd42009-07-23 23:51:51 +000035
cliechti89b4af12002-02-12 23:24:41 +000036 def device(port):
37 return '/dev/ttyS%d' % port
38
cliechti1877c522013-10-11 14:02:26 +000039 TCGETS2 = 0x802C542A
40 TCSETS2 = 0x402C542B
41 BOTHER = 0o010000
cliechti53c9fd42009-07-23 23:51:51 +000042
43 def set_special_baudrate(port, baudrate):
cliechti1877c522013-10-11 14:02:26 +000044 # right size is 44 on x86_64, allow for some growth
cliechti53c9fd42009-07-23 23:51:51 +000045 import array
cliechti1877c522013-10-11 14:02:26 +000046 buf = array.array('i', [0] * 64)
cliechti53c9fd42009-07-23 23:51:51 +000047
cliechti53c9fd42009-07-23 23:51:51 +000048 try:
cliechti95772d32013-10-11 14:38:13 +000049 # get serial_struct
50 FCNTL.ioctl(port.fd, TCGETS2, buf)
51 # set custom speed
52 buf[2] &= ~TERMIOS.CBAUD
53 buf[2] |= BOTHER
54 buf[9] = buf[10] = baudrate
55
56 # set serial_struct
cliechti1877c522013-10-11 14:02:26 +000057 res = FCNTL.ioctl(port.fd, TCSETS2, buf)
cliechti95772d32013-10-11 14:38:13 +000058 except IOError, e:
59 raise ValueError('Failed to set custom baud rate (%s): %s' % (baudrate, e))
cliechti53c9fd42009-07-23 23:51:51 +000060
cliechti99220a02009-08-14 00:21:25 +000061 baudrate_constants = {
62 0: 0000000, # hang up
63 50: 0000001,
64 75: 0000002,
65 110: 0000003,
66 134: 0000004,
67 150: 0000005,
68 200: 0000006,
69 300: 0000007,
70 600: 0000010,
71 1200: 0000011,
72 1800: 0000012,
73 2400: 0000013,
74 4800: 0000014,
75 9600: 0000015,
76 19200: 0000016,
77 38400: 0000017,
78 57600: 0010001,
79 115200: 0010002,
80 230400: 0010003,
81 460800: 0010004,
82 500000: 0010005,
83 576000: 0010006,
84 921600: 0010007,
85 1000000: 0010010,
86 1152000: 0010011,
87 1500000: 0010012,
88 2000000: 0010013,
89 2500000: 0010014,
90 3000000: 0010015,
91 3500000: 0010016,
92 4000000: 0010017
93 }
94
cliechti53c9fd42009-07-23 23:51:51 +000095elif plat == 'cygwin': # cygwin/win32 (confirmed)
96
cliechtif281fde2002-06-07 21:53:40 +000097 def device(port):
cliechtif5831e02002-12-05 23:15:27 +000098 return '/dev/com%d' % (port + 1)
cliechtif281fde2002-06-07 21:53:40 +000099
cliechti53c9fd42009-07-23 23:51:51 +0000100 def set_special_baudrate(port, baudrate):
cliechti99220a02009-08-14 00:21:25 +0000101 raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
cliechti53c9fd42009-07-23 23:51:51 +0000102
cliechtia505de32013-05-31 01:27:25 +0000103 baudrate_constants = {
104 128000: 0x01003,
105 256000: 0x01005,
106 500000: 0x01007,
107 576000: 0x01008,
108 921600: 0x01009,
109 1000000: 0x0100a,
110 1152000: 0x0100b,
111 1500000: 0x0100c,
112 2000000: 0x0100d,
113 2500000: 0x0100e,
114 3000000: 0x0100f
115 }
cliechti53c9fd42009-07-23 23:51:51 +0000116
cliechti4a601342011-12-29 02:22:17 +0000117elif plat[:7] == 'openbsd': # OpenBSD
cliechti53c9fd42009-07-23 23:51:51 +0000118
cliechti89b4af12002-02-12 23:24:41 +0000119 def device(port):
cliechti4a601342011-12-29 02:22:17 +0000120 return '/dev/cua%02d' % port
cliechti89b4af12002-02-12 23:24:41 +0000121
cliechti53c9fd42009-07-23 23:51:51 +0000122 def set_special_baudrate(port, baudrate):
123 raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
124
cliechti99220a02009-08-14 00:21:25 +0000125 baudrate_constants = {}
126
cliechti89b4af12002-02-12 23:24:41 +0000127elif plat[:3] == 'bsd' or \
cliechti4a601342011-12-29 02:22:17 +0000128 plat[:7] == 'freebsd':
cliechti53c9fd42009-07-23 23:51:51 +0000129
cliechti89b4af12002-02-12 23:24:41 +0000130 def device(port):
cliechtieaa96882008-06-16 22:59:20 +0000131 return '/dev/cuad%d' % port
cliechti89b4af12002-02-12 23:24:41 +0000132
cliechti53c9fd42009-07-23 23:51:51 +0000133 def set_special_baudrate(port, baudrate):
134 raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
135
cliechti99220a02009-08-14 00:21:25 +0000136 baudrate_constants = {}
137
cliechti53c9fd42009-07-23 23:51:51 +0000138elif plat[:6] == 'darwin': # OS X
139
140 version = os.uname()[2].split('.')
141 # Tiger or above can support arbitrary serial speeds
142 if int(version[0]) >= 8:
cliechti53c9fd42009-07-23 23:51:51 +0000143 def set_special_baudrate(port, baudrate):
144 # use IOKit-specific call to set up high speeds
145 import array, fcntl
146 buf = array.array('i', [baudrate])
147 IOSSIOSPEED = 0x80045402 #_IOW('T', 2, speed_t)
148 fcntl.ioctl(port.fd, IOSSIOSPEED, buf, 1)
149 else: # version < 8
150 def set_special_baudrate(port, baudrate):
151 raise ValueError("baud rate not supported")
152
153 def device(port):
154 return '/dev/cuad%d' % port
155
cliechti99220a02009-08-14 00:21:25 +0000156 baudrate_constants = {}
157
cliechti53c9fd42009-07-23 23:51:51 +0000158
cliechti3172d3d2009-07-21 22:33:40 +0000159elif plat[:6] == 'netbsd': # NetBSD 1.6 testing by Erk
cliechti53c9fd42009-07-23 23:51:51 +0000160
cliechti835996a2004-06-02 19:45:07 +0000161 def device(port):
162 return '/dev/dty%02d' % port
163
cliechti53c9fd42009-07-23 23:51:51 +0000164 def set_special_baudrate(port, baudrate):
165 raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
166
cliechti99220a02009-08-14 00:21:25 +0000167 baudrate_constants = {}
168
cliechti3172d3d2009-07-21 22:33:40 +0000169elif plat[:4] == 'irix': # IRIX (partially tested)
cliechti53c9fd42009-07-23 23:51:51 +0000170
cliechti89b4af12002-02-12 23:24:41 +0000171 def device(port):
cliechtie2418e92006-06-05 20:03:17 +0000172 return '/dev/ttyf%d' % (port+1) #XXX different device names depending on flow control
cliechti89b4af12002-02-12 23:24:41 +0000173
cliechti53c9fd42009-07-23 23:51:51 +0000174 def set_special_baudrate(port, baudrate):
175 raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
176
cliechti99220a02009-08-14 00:21:25 +0000177 baudrate_constants = {}
178
cliechti3172d3d2009-07-21 22:33:40 +0000179elif plat[:2] == 'hp': # HP-UX (not tested)
cliechti53c9fd42009-07-23 23:51:51 +0000180
cliechti89b4af12002-02-12 23:24:41 +0000181 def device(port):
182 return '/dev/tty%dp0' % (port+1)
183
cliechti53c9fd42009-07-23 23:51:51 +0000184 def set_special_baudrate(port, baudrate):
185 raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
186
cliechti99220a02009-08-14 00:21:25 +0000187 baudrate_constants = {}
188
cliechti3172d3d2009-07-21 22:33:40 +0000189elif plat[:5] == 'sunos': # Solaris/SunOS (confirmed)
cliechti53c9fd42009-07-23 23:51:51 +0000190
cliechti89b4af12002-02-12 23:24:41 +0000191 def device(port):
192 return '/dev/tty%c' % (ord('a')+port)
cliechti58b481c2009-02-16 20:42:32 +0000193
cliechti53c9fd42009-07-23 23:51:51 +0000194 def set_special_baudrate(port, baudrate):
195 raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
196
cliechti99220a02009-08-14 00:21:25 +0000197 baudrate_constants = {}
198
cliechti3172d3d2009-07-21 22:33:40 +0000199elif plat[:3] == 'aix': # AIX
cliechti53c9fd42009-07-23 23:51:51 +0000200
cliechti40e1b072005-03-12 12:05:26 +0000201 def device(port):
202 return '/dev/tty%d' % (port)
cliechti89b4af12002-02-12 23:24:41 +0000203
cliechti53c9fd42009-07-23 23:51:51 +0000204 def set_special_baudrate(port, baudrate):
205 raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
206
cliechti99220a02009-08-14 00:21:25 +0000207 baudrate_constants = {}
208
cliechti89b4af12002-02-12 23:24:41 +0000209else:
cliechtia9a093e2010-01-02 03:05:08 +0000210 # platform detection has failed...
cliechti7aaead32009-07-23 14:02:41 +0000211 sys.stderr.write("""\
212don't know how to number ttys on this system.
cliechti895e8302004-04-20 02:40:28 +0000213! Use an explicit path (eg /dev/ttyS1) or send this information to
214! the author of this module:
cliechti89b4af12002-02-12 23:24:41 +0000215
cliechti895e8302004-04-20 02:40:28 +0000216sys.platform = %r
217os.name = %r
218serialposix.py version = %s
cliechti89b4af12002-02-12 23:24:41 +0000219
220also add the device name of the serial port and where the
221counting starts for the first serial port.
222e.g. 'first serial port: /dev/ttyS0'
223and with a bit luck you can get this module running...
cliechti7aaead32009-07-23 14:02:41 +0000224""" % (sys.platform, os.name, VERSION))
cliechti58b481c2009-02-16 20:42:32 +0000225 # no exception, just continue with a brave attempt to build a device name
226 # even if the device name is not correct for the platform it has chances
cliechti3172d3d2009-07-21 22:33:40 +0000227 # to work using a string with the real device name as port parameter.
cliechtid6bf52c2003-10-01 02:28:12 +0000228 def device(portum):
229 return '/dev/ttyS%d' % portnum
cliechti53c9fd42009-07-23 23:51:51 +0000230 def set_special_baudrate(port, baudrate):
231 raise SerialException("sorry don't know how to handle non standard baud rate on this platform")
cliechti99220a02009-08-14 00:21:25 +0000232 baudrate_constants = {}
cliechtid6bf52c2003-10-01 02:28:12 +0000233 #~ raise Exception, "this module does not run on this platform, sorry."
cliechti89b4af12002-02-12 23:24:41 +0000234
cliechti58b481c2009-02-16 20:42:32 +0000235# whats up with "aix", "beos", ....
236# they should work, just need to know the device names.
cliechti89b4af12002-02-12 23:24:41 +0000237
238
cliechti58b481c2009-02-16 20:42:32 +0000239# load some constants for later use.
240# try to use values from TERMIOS, use defaults from linux otherwise
cliechti8901aef2002-11-19 01:15:05 +0000241TIOCMGET = hasattr(TERMIOS, 'TIOCMGET') and TERMIOS.TIOCMGET or 0x5415
242TIOCMBIS = hasattr(TERMIOS, 'TIOCMBIS') and TERMIOS.TIOCMBIS or 0x5416
243TIOCMBIC = hasattr(TERMIOS, 'TIOCMBIC') and TERMIOS.TIOCMBIC or 0x5417
244TIOCMSET = hasattr(TERMIOS, 'TIOCMSET') and TERMIOS.TIOCMSET or 0x5418
cliechti89b4af12002-02-12 23:24:41 +0000245
cliechti8901aef2002-11-19 01:15:05 +0000246#TIOCM_LE = hasattr(TERMIOS, 'TIOCM_LE') and TERMIOS.TIOCM_LE or 0x001
247TIOCM_DTR = hasattr(TERMIOS, 'TIOCM_DTR') and TERMIOS.TIOCM_DTR or 0x002
248TIOCM_RTS = hasattr(TERMIOS, 'TIOCM_RTS') and TERMIOS.TIOCM_RTS or 0x004
249#TIOCM_ST = hasattr(TERMIOS, 'TIOCM_ST') and TERMIOS.TIOCM_ST or 0x008
250#TIOCM_SR = hasattr(TERMIOS, 'TIOCM_SR') and TERMIOS.TIOCM_SR or 0x010
cliechti89b4af12002-02-12 23:24:41 +0000251
cliechti8901aef2002-11-19 01:15:05 +0000252TIOCM_CTS = hasattr(TERMIOS, 'TIOCM_CTS') and TERMIOS.TIOCM_CTS or 0x020
253TIOCM_CAR = hasattr(TERMIOS, 'TIOCM_CAR') and TERMIOS.TIOCM_CAR or 0x040
254TIOCM_RNG = hasattr(TERMIOS, 'TIOCM_RNG') and TERMIOS.TIOCM_RNG or 0x080
255TIOCM_DSR = hasattr(TERMIOS, 'TIOCM_DSR') and TERMIOS.TIOCM_DSR or 0x100
256TIOCM_CD = hasattr(TERMIOS, 'TIOCM_CD') and TERMIOS.TIOCM_CD or TIOCM_CAR
257TIOCM_RI = hasattr(TERMIOS, 'TIOCM_RI') and TERMIOS.TIOCM_RI or TIOCM_RNG
258#TIOCM_OUT1 = hasattr(TERMIOS, 'TIOCM_OUT1') and TERMIOS.TIOCM_OUT1 or 0x2000
259#TIOCM_OUT2 = hasattr(TERMIOS, 'TIOCM_OUT2') and TERMIOS.TIOCM_OUT2 or 0x4000
cliechti28b8fd02011-12-28 21:39:42 +0000260if hasattr(TERMIOS, 'TIOCINQ'):
261 TIOCINQ = TERMIOS.TIOCINQ
262else:
263 TIOCINQ = hasattr(TERMIOS, 'FIONREAD') and TERMIOS.FIONREAD or 0x541B
264TIOCOUTQ = hasattr(TERMIOS, 'TIOCOUTQ') and TERMIOS.TIOCOUTQ or 0x5411
cliechti89b4af12002-02-12 23:24:41 +0000265
266TIOCM_zero_str = struct.pack('I', 0)
267TIOCM_RTS_str = struct.pack('I', TIOCM_RTS)
268TIOCM_DTR_str = struct.pack('I', TIOCM_DTR)
269
cliechti997b63c2008-06-21 00:09:31 +0000270TIOCSBRK = hasattr(TERMIOS, 'TIOCSBRK') and TERMIOS.TIOCSBRK or 0x5427
271TIOCCBRK = hasattr(TERMIOS, 'TIOCCBRK') and TERMIOS.TIOCCBRK or 0x5428
272
cliechti89b4af12002-02-12 23:24:41 +0000273
cliechtif81362e2009-07-25 03:44:33 +0000274class PosixSerial(SerialBase):
cliechtid6bf52c2003-10-01 02:28:12 +0000275 """Serial port class POSIX implementation. Serial port configuration is
276 done with termios and fcntl. Runs on Linux and many other Un*x like
277 systems."""
278
279 def open(self):
280 """Open port with current settings. This may throw a SerialException
281 if the port cannot be opened."""
282 if self._port is None:
283 raise SerialException("Port must be configured before it can be used.")
cliechti02ef43a2011-03-24 23:33:12 +0000284 if self._isOpen:
285 raise SerialException("Port is already open.")
286 self.fd = None
cliechti58b481c2009-02-16 20:42:32 +0000287 # open
cliechti4616bf12002-04-08 23:13:14 +0000288 try:
289 self.fd = os.open(self.portstr, os.O_RDWR|os.O_NOCTTY|os.O_NONBLOCK)
cliechtiaf84daa2013-10-10 23:57:00 +0000290 except IOError, msg:
cliechti4616bf12002-04-08 23:13:14 +0000291 self.fd = None
cliechtiaf84daa2013-10-10 23:57:00 +0000292 raise SerialException(msg.errno, "could not open port %s: %s" % (self._port, msg))
cliechti2750b832009-07-28 00:13:52 +0000293 #~ fcntl.fcntl(self.fd, FCNTL.F_SETFL, 0) # set blocking
cliechti58b481c2009-02-16 20:42:32 +0000294
cliechtib2f5fc82006-10-20 00:09:07 +0000295 try:
296 self._reconfigurePort()
297 except:
cliechti2750b832009-07-28 00:13:52 +0000298 try:
299 os.close(self.fd)
300 except:
301 # ignore any exception when closing the port
302 # also to keep original exception that happened when setting up
303 pass
cliechtib2f5fc82006-10-20 00:09:07 +0000304 self.fd = None
cliechtif0a4f0f2009-07-21 21:12:37 +0000305 raise
cliechtib2f5fc82006-10-20 00:09:07 +0000306 else:
307 self._isOpen = True
cliechti62611612004-04-20 01:55:43 +0000308 #~ self.flushInput()
cliechti58b481c2009-02-16 20:42:32 +0000309
310
cliechtid6bf52c2003-10-01 02:28:12 +0000311 def _reconfigurePort(self):
cliechtib2f5fc82006-10-20 00:09:07 +0000312 """Set communication parameters on opened port."""
cliechtic6178262004-03-22 22:04:52 +0000313 if self.fd is None:
cliechtia9a093e2010-01-02 03:05:08 +0000314 raise SerialException("Can only operate on a valid file descriptor")
cliechtie8c45422008-06-20 23:23:14 +0000315 custom_baud = None
cliechti58b481c2009-02-16 20:42:32 +0000316
cliechti2750b832009-07-28 00:13:52 +0000317 vmin = vtime = 0 # timeout is done via select
cliechti679bfa62008-06-20 23:58:15 +0000318 if self._interCharTimeout is not None:
319 vmin = 1
320 vtime = int(self._interCharTimeout * 10)
cliechti6ce7ab12002-11-07 02:15:00 +0000321 try:
cliechti4d0af5e2011-08-05 02:18:16 +0000322 orig_attr = termios.tcgetattr(self.fd)
323 iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
cliechti2750b832009-07-28 00:13:52 +0000324 except termios.error, msg: # if a port is nonexistent but has a /dev file, it'll fail here
cliechtid6bf52c2003-10-01 02:28:12 +0000325 raise SerialException("Could not configure port: %s" % msg)
cliechti58b481c2009-02-16 20:42:32 +0000326 # set up raw mode / no echo / binary
cliechtid6bf52c2003-10-01 02:28:12 +0000327 cflag |= (TERMIOS.CLOCAL|TERMIOS.CREAD)
328 lflag &= ~(TERMIOS.ICANON|TERMIOS.ECHO|TERMIOS.ECHOE|TERMIOS.ECHOK|TERMIOS.ECHONL|
cliechti835996a2004-06-02 19:45:07 +0000329 TERMIOS.ISIG|TERMIOS.IEXTEN) #|TERMIOS.ECHOPRT
cliechti2750b832009-07-28 00:13:52 +0000330 for flag in ('ECHOCTL', 'ECHOKE'): # netbsd workaround for Erk
cliechti835996a2004-06-02 19:45:07 +0000331 if hasattr(TERMIOS, flag):
332 lflag &= ~getattr(TERMIOS, flag)
cliechti58b481c2009-02-16 20:42:32 +0000333
cliechtid6bf52c2003-10-01 02:28:12 +0000334 oflag &= ~(TERMIOS.OPOST)
cliechti895e8302004-04-20 02:40:28 +0000335 iflag &= ~(TERMIOS.INLCR|TERMIOS.IGNCR|TERMIOS.ICRNL|TERMIOS.IGNBRK)
cliechti89b4af12002-02-12 23:24:41 +0000336 if hasattr(TERMIOS, 'IUCLC'):
cliechti895e8302004-04-20 02:40:28 +0000337 iflag &= ~TERMIOS.IUCLC
cliechti3e57b3d2005-08-12 21:04:44 +0000338 if hasattr(TERMIOS, 'PARMRK'):
339 iflag &= ~TERMIOS.PARMRK
cliechti58b481c2009-02-16 20:42:32 +0000340
cliechtif0a4f0f2009-07-21 21:12:37 +0000341 # setup baud rate
cliechti89b4af12002-02-12 23:24:41 +0000342 try:
cliechti2750b832009-07-28 00:13:52 +0000343 ispeed = ospeed = getattr(TERMIOS, 'B%s' % (self._baudrate))
cliechti895e8302004-04-20 02:40:28 +0000344 except AttributeError:
cliechtif1559d02007-11-08 23:43:58 +0000345 try:
346 ispeed = ospeed = baudrate_constants[self._baudrate]
347 except KeyError:
cliechtie8c45422008-06-20 23:23:14 +0000348 #~ raise ValueError('Invalid baud rate: %r' % self._baudrate)
cliechtif0a4f0f2009-07-21 21:12:37 +0000349 # may need custom baud rate, it isn't in our list.
cliechtie8c45422008-06-20 23:23:14 +0000350 ispeed = ospeed = getattr(TERMIOS, 'B38400')
cliechtif0a4f0f2009-07-21 21:12:37 +0000351 try:
352 custom_baud = int(self._baudrate) # store for later
353 except ValueError:
354 raise ValueError('Invalid baud rate: %r' % self._baudrate)
355 else:
356 if custom_baud < 0:
357 raise ValueError('Invalid baud rate: %r' % self._baudrate)
cliechti58b481c2009-02-16 20:42:32 +0000358
359 # setup char len
cliechtid6bf52c2003-10-01 02:28:12 +0000360 cflag &= ~TERMIOS.CSIZE
361 if self._bytesize == 8:
362 cflag |= TERMIOS.CS8
363 elif self._bytesize == 7:
364 cflag |= TERMIOS.CS7
365 elif self._bytesize == 6:
366 cflag |= TERMIOS.CS6
367 elif self._bytesize == 5:
368 cflag |= TERMIOS.CS5
cliechti89b4af12002-02-12 23:24:41 +0000369 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000370 raise ValueError('Invalid char len: %r' % self._bytesize)
cliechti58b481c2009-02-16 20:42:32 +0000371 # setup stopbits
cliechtid6bf52c2003-10-01 02:28:12 +0000372 if self._stopbits == STOPBITS_ONE:
373 cflag &= ~(TERMIOS.CSTOPB)
cliechti58b481c2009-02-16 20:42:32 +0000374 elif self._stopbits == STOPBITS_ONE_POINT_FIVE:
375 cflag |= (TERMIOS.CSTOPB) # XXX same as TWO.. there is no POSIX support for 1.5
cliechtid6bf52c2003-10-01 02:28:12 +0000376 elif self._stopbits == STOPBITS_TWO:
377 cflag |= (TERMIOS.CSTOPB)
cliechti89b4af12002-02-12 23:24:41 +0000378 else:
cliechti3172d3d2009-07-21 22:33:40 +0000379 raise ValueError('Invalid stop bit specification: %r' % self._stopbits)
cliechti58b481c2009-02-16 20:42:32 +0000380 # setup parity
cliechtid6bf52c2003-10-01 02:28:12 +0000381 iflag &= ~(TERMIOS.INPCK|TERMIOS.ISTRIP)
382 if self._parity == PARITY_NONE:
383 cflag &= ~(TERMIOS.PARENB|TERMIOS.PARODD)
384 elif self._parity == PARITY_EVEN:
385 cflag &= ~(TERMIOS.PARODD)
386 cflag |= (TERMIOS.PARENB)
387 elif self._parity == PARITY_ODD:
388 cflag |= (TERMIOS.PARENB|TERMIOS.PARODD)
cliechti89b4af12002-02-12 23:24:41 +0000389 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000390 raise ValueError('Invalid parity: %r' % self._parity)
cliechti58b481c2009-02-16 20:42:32 +0000391 # setup flow control
392 # xonxoff
cliechti89b4af12002-02-12 23:24:41 +0000393 if hasattr(TERMIOS, 'IXANY'):
cliechtid6bf52c2003-10-01 02:28:12 +0000394 if self._xonxoff:
cliechti62611612004-04-20 01:55:43 +0000395 iflag |= (TERMIOS.IXON|TERMIOS.IXOFF) #|TERMIOS.IXANY)
cliechti89b4af12002-02-12 23:24:41 +0000396 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000397 iflag &= ~(TERMIOS.IXON|TERMIOS.IXOFF|TERMIOS.IXANY)
cliechti89b4af12002-02-12 23:24:41 +0000398 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000399 if self._xonxoff:
400 iflag |= (TERMIOS.IXON|TERMIOS.IXOFF)
cliechti89b4af12002-02-12 23:24:41 +0000401 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000402 iflag &= ~(TERMIOS.IXON|TERMIOS.IXOFF)
cliechti58b481c2009-02-16 20:42:32 +0000403 # rtscts
cliechti89b4af12002-02-12 23:24:41 +0000404 if hasattr(TERMIOS, 'CRTSCTS'):
cliechtid6bf52c2003-10-01 02:28:12 +0000405 if self._rtscts:
406 cflag |= (TERMIOS.CRTSCTS)
cliechti89b4af12002-02-12 23:24:41 +0000407 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000408 cflag &= ~(TERMIOS.CRTSCTS)
cliechti2750b832009-07-28 00:13:52 +0000409 elif hasattr(TERMIOS, 'CNEW_RTSCTS'): # try it with alternate constant name
cliechtid6bf52c2003-10-01 02:28:12 +0000410 if self._rtscts:
411 cflag |= (TERMIOS.CNEW_RTSCTS)
cliechtid4743692002-04-08 22:39:53 +0000412 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000413 cflag &= ~(TERMIOS.CNEW_RTSCTS)
cliechti2750b832009-07-28 00:13:52 +0000414 # XXX should there be a warning if setting up rtscts (and xonxoff etc) fails??
cliechti58b481c2009-02-16 20:42:32 +0000415
416 # buffer
417 # vmin "minimal number of characters to be read. = for non blocking"
cliechtid6bf52c2003-10-01 02:28:12 +0000418 if vmin < 0 or vmin > 255:
419 raise ValueError('Invalid vmin: %r ' % vmin)
420 cc[TERMIOS.VMIN] = vmin
cliechti58b481c2009-02-16 20:42:32 +0000421 # vtime
cliechtid6bf52c2003-10-01 02:28:12 +0000422 if vtime < 0 or vtime > 255:
423 raise ValueError('Invalid vtime: %r' % vtime)
424 cc[TERMIOS.VTIME] = vtime
cliechti58b481c2009-02-16 20:42:32 +0000425 # activate settings
cliechti4d0af5e2011-08-05 02:18:16 +0000426 if [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] != orig_attr:
427 termios.tcsetattr(self.fd, TERMIOS.TCSANOW, [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
cliechti58b481c2009-02-16 20:42:32 +0000428
cliechtie8c45422008-06-20 23:23:14 +0000429 # apply custom baud rate, if any
430 if custom_baud is not None:
cliechti53c9fd42009-07-23 23:51:51 +0000431 set_special_baudrate(self, custom_baud)
cliechti89b4af12002-02-12 23:24:41 +0000432
433 def close(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000434 """Close port"""
435 if self._isOpen:
cliechtic6178262004-03-22 22:04:52 +0000436 if self.fd is not None:
cliechtid6bf52c2003-10-01 02:28:12 +0000437 os.close(self.fd)
438 self.fd = None
439 self._isOpen = False
cliechti89b4af12002-02-12 23:24:41 +0000440
cliechtid6bf52c2003-10-01 02:28:12 +0000441 def makeDeviceName(self, port):
442 return device(port)
443
444 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechti95c62212002-03-04 22:17:53 +0000445
cliechti89b4af12002-02-12 23:24:41 +0000446 def inWaiting(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000447 """Return the number of characters currently in the input buffer."""
cliechtif5831e02002-12-05 23:15:27 +0000448 #~ s = fcntl.ioctl(self.fd, TERMIOS.FIONREAD, TIOCM_zero_str)
449 s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str)
cliechti89b4af12002-02-12 23:24:41 +0000450 return struct.unpack('I',s)[0]
451
cliechtia9a093e2010-01-02 03:05:08 +0000452 # select based implementation, proved to work on many systems
453 def read(self, size=1):
454 """Read size bytes from the serial port. If a timeout is set it may
455 return less characters as requested. With no timeout it will block
456 until the requested number of bytes is read."""
cliechti899c9c42011-06-14 23:01:23 +0000457 if not self._isOpen: raise portNotOpenError
cliechtia9a093e2010-01-02 03:05:08 +0000458 read = bytearray()
459 while len(read) < size:
cliechti8d744de2013-10-11 14:31:13 +0000460 try:
461 ready,_,_ = select.select([self.fd],[],[], self._timeout)
462 # If select was used with a timeout, and the timeout occurs, it
463 # returns with empty lists -> thus abort read operation.
464 # For timeout == 0 (non-blocking operation) also abort when there
465 # is nothing to read.
466 if not ready:
467 break # timeout
468 buf = os.read(self.fd, size-len(read))
469 # read should always return some data as select reported it was
470 # ready to read when we get to this point.
471 if not buf:
472 # Disconnected devices, at least on Linux, show the
473 # behavior that they are always ready to read immediately
474 # but reading returns nothing.
475 raise SerialException('device reports readiness to read but returned no data (device disconnected or multiple access on port?)')
476 read.extend(buf)
477 except select.error, e:
478 # ignore EAGAIN errors. all other errors are shown
479 # see also http://www.python.org/dev/peps/pep-3151/#select
480 if e[0] != errno.EAGAIN:
481 raise SerialException('read failed: %s' % (e,))
482 except OSError, e:
483 # ignore EAGAIN errors. all other errors are shown
484 if e.errno != errno.EAGAIN:
485 raise SerialException('read failed: %s' % (e,))
cliechtia9a093e2010-01-02 03:05:08 +0000486 return bytes(read)
cliechti89b4af12002-02-12 23:24:41 +0000487
cliechti4a567a02009-07-27 22:09:31 +0000488 def write(self, data):
cliechtid6bf52c2003-10-01 02:28:12 +0000489 """Output the given string over the serial port."""
cliechti899c9c42011-06-14 23:01:23 +0000490 if not self._isOpen: raise portNotOpenError
cliechti9f7c2352013-10-11 01:13:46 +0000491 tx_len = len(data)
cliechtid6bf52c2003-10-01 02:28:12 +0000492 d = data
cliechti3cf46d62009-08-07 00:19:57 +0000493 if self._writeTimeout is not None and self._writeTimeout > 0:
494 timeout = time.time() + self._writeTimeout
495 else:
496 timeout = None
cliechti9f7c2352013-10-11 01:13:46 +0000497 while tx_len > 0:
cliechti5d4d0bd2004-11-13 03:27:39 +0000498 try:
cliechti5d4d0bd2004-11-13 03:27:39 +0000499 n = os.write(self.fd, d)
cliechti3cf46d62009-08-07 00:19:57 +0000500 if timeout:
501 # when timeout is set, use select to wait for being ready
502 # with the time left as timeout
503 timeleft = timeout - time.time()
504 if timeleft < 0:
505 raise writeTimeoutError
506 _, ready, _ = select.select([], [self.fd], [], timeleft)
cliechti5d4d0bd2004-11-13 03:27:39 +0000507 if not ready:
508 raise writeTimeoutError
509 d = d[n:]
cliechti9f7c2352013-10-11 01:13:46 +0000510 tx_len -= n
cliechti4a567a02009-07-27 22:09:31 +0000511 except OSError, v:
cliechti5d4d0bd2004-11-13 03:27:39 +0000512 if v.errno != errno.EAGAIN:
cliechti65722c92009-08-07 00:48:53 +0000513 raise SerialException('write failed: %s' % (v,))
cliechtif81362e2009-07-25 03:44:33 +0000514 return len(data)
cliechtid6bf52c2003-10-01 02:28:12 +0000515
cliechtia30a8a02003-10-05 12:28:13 +0000516 def flush(self):
517 """Flush of file like objects. In this case, wait until all data
518 is written."""
519 self.drainOutput()
520
cliechti89b4af12002-02-12 23:24:41 +0000521 def flushInput(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000522 """Clear input buffer, discarding all that is in the buffer."""
cliechti899c9c42011-06-14 23:01:23 +0000523 if not self._isOpen: raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000524 termios.tcflush(self.fd, TERMIOS.TCIFLUSH)
525
526 def flushOutput(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000527 """Clear output buffer, aborting the current output and
528 discarding all that is in the buffer."""
cliechti899c9c42011-06-14 23:01:23 +0000529 if not self._isOpen: raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000530 termios.tcflush(self.fd, TERMIOS.TCOFLUSH)
531
cliechtiaaa04602006-02-05 23:02:46 +0000532 def sendBreak(self, duration=0.25):
cliechti997b63c2008-06-21 00:09:31 +0000533 """Send break condition. Timed, returns to idle state after given duration."""
cliechti899c9c42011-06-14 23:01:23 +0000534 if not self._isOpen: raise portNotOpenError
cliechtiaaa04602006-02-05 23:02:46 +0000535 termios.tcsendbreak(self.fd, int(duration/0.25))
cliechti89b4af12002-02-12 23:24:41 +0000536
cliechti997b63c2008-06-21 00:09:31 +0000537 def setBreak(self, level=1):
cliechtidfec0c82009-07-21 01:35:41 +0000538 """Set break: Controls TXD. When active, no transmitting is possible."""
cliechti997b63c2008-06-21 00:09:31 +0000539 if self.fd is None: raise portNotOpenError
540 if level:
541 fcntl.ioctl(self.fd, TIOCSBRK)
542 else:
543 fcntl.ioctl(self.fd, TIOCCBRK)
544
cliechti93db61b2006-08-26 19:16:18 +0000545 def setRTS(self, level=1):
cliechtid6bf52c2003-10-01 02:28:12 +0000546 """Set terminal status line: Request To Send"""
cliechti899c9c42011-06-14 23:01:23 +0000547 if not self._isOpen: raise portNotOpenError
cliechtib2f5fc82006-10-20 00:09:07 +0000548 if level:
cliechtid6bf52c2003-10-01 02:28:12 +0000549 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_RTS_str)
550 else:
551 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_RTS_str)
552
cliechti93db61b2006-08-26 19:16:18 +0000553 def setDTR(self, level=1):
cliechtid6bf52c2003-10-01 02:28:12 +0000554 """Set terminal status line: Data Terminal Ready"""
cliechti899c9c42011-06-14 23:01:23 +0000555 if not self._isOpen: raise portNotOpenError
cliechtib2f5fc82006-10-20 00:09:07 +0000556 if level:
cliechtid6bf52c2003-10-01 02:28:12 +0000557 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str)
558 else:
559 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_DTR_str)
560
561 def getCTS(self):
562 """Read terminal status line: Clear To Send"""
cliechti899c9c42011-06-14 23:01:23 +0000563 if not self._isOpen: raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000564 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
565 return struct.unpack('I',s)[0] & TIOCM_CTS != 0
566
567 def getDSR(self):
568 """Read terminal status line: Data Set Ready"""
cliechti899c9c42011-06-14 23:01:23 +0000569 if not self._isOpen: raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000570 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
571 return struct.unpack('I',s)[0] & TIOCM_DSR != 0
572
cliechtid6bf52c2003-10-01 02:28:12 +0000573 def getRI(self):
574 """Read terminal status line: Ring Indicator"""
cliechti899c9c42011-06-14 23:01:23 +0000575 if not self._isOpen: raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000576 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
cliechtid6bf52c2003-10-01 02:28:12 +0000577 return struct.unpack('I',s)[0] & TIOCM_RI != 0
cliechti89b4af12002-02-12 23:24:41 +0000578
579 def getCD(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000580 """Read terminal status line: Carrier Detect"""
cliechti899c9c42011-06-14 23:01:23 +0000581 if not self._isOpen: raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000582 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
cliechtid6bf52c2003-10-01 02:28:12 +0000583 return struct.unpack('I',s)[0] & TIOCM_CD != 0
cliechti89b4af12002-02-12 23:24:41 +0000584
cliechtia30a8a02003-10-05 12:28:13 +0000585 # - - platform specific - - - -
586
cliechti28b8fd02011-12-28 21:39:42 +0000587 def outWaiting(self):
588 """Return the number of characters currently in the output buffer."""
589 #~ s = fcntl.ioctl(self.fd, TERMIOS.FIONREAD, TIOCM_zero_str)
590 s = fcntl.ioctl(self.fd, TIOCOUTQ, TIOCM_zero_str)
591 return struct.unpack('I',s)[0]
592
cliechtia30a8a02003-10-05 12:28:13 +0000593 def drainOutput(self):
594 """internal - not portable!"""
cliechti899c9c42011-06-14 23:01:23 +0000595 if not self._isOpen: raise portNotOpenError
cliechtia30a8a02003-10-05 12:28:13 +0000596 termios.tcdrain(self.fd)
597
598 def nonblocking(self):
599 """internal - not portable!"""
cliechti899c9c42011-06-14 23:01:23 +0000600 if not self._isOpen: raise portNotOpenError
cliechti198b7e72010-05-25 00:38:23 +0000601 fcntl.fcntl(self.fd, FCNTL.F_SETFL, os.O_NONBLOCK)
cliechtia30a8a02003-10-05 12:28:13 +0000602
cliechti8753bbc2005-01-15 20:32:51 +0000603 def fileno(self):
cliechti2f0f8a32011-12-28 22:10:00 +0000604 """\
605 For easier use of the serial port instance with select.
606 WARNING: this function is not portable to different platforms!
607 """
cliechti899c9c42011-06-14 23:01:23 +0000608 if not self._isOpen: raise portNotOpenError
cliechti8753bbc2005-01-15 20:32:51 +0000609 return self.fd
cliechti89b4af12002-02-12 23:24:41 +0000610
cliechti2f0f8a32011-12-28 22:10:00 +0000611 def setXON(self, level=True):
612 """\
613 Manually control flow - when software flow control is enabled.
614 This will send XON (true) and XOFF (false) to the other device.
615 WARNING: this function is not portable to different platforms!
616 """
617 if not self.hComPort: raise portNotOpenError
cliechti4a601342011-12-29 02:22:17 +0000618 if enable:
cliechti57e48a62009-08-03 22:29:58 +0000619 termios.tcflow(self.fd, TERMIOS.TCION)
620 else:
621 termios.tcflow(self.fd, TERMIOS.TCIOFF)
622
cliechti2f0f8a32011-12-28 22:10:00 +0000623 def flowControlOut(self, enable):
624 """\
625 Manually control flow of outgoing data - when hardware or software flow
626 control is enabled.
627 WARNING: this function is not portable to different platforms!
628 """
629 if not self._isOpen: raise portNotOpenError
630 if enable:
631 termios.tcflow(self.fd, TERMIOS.TCOON)
632 else:
633 termios.tcflow(self.fd, TERMIOS.TCOOFF)
634
cliechtif81362e2009-07-25 03:44:33 +0000635
636# assemble Serial class with the platform specifc implementation and the base
cliechti4a567a02009-07-27 22:09:31 +0000637# for file-like behavior. for Python 2.6 and newer, that provide the new I/O
638# library, derrive from io.RawIOBase
639try:
640 import io
641except ImportError:
642 # classic version with our own file-like emulation
643 class Serial(PosixSerial, FileLike):
644 pass
645else:
646 # io library present
647 class Serial(PosixSerial, io.RawIOBase):
cliechtif81362e2009-07-25 03:44:33 +0000648 pass
649
cliechtia9a093e2010-01-02 03:05:08 +0000650class PosixPollSerial(Serial):
651 """poll based read implementation. not all systems support poll properly.
652 however this one has better handling of errors, such as a device
653 disconnecting while it's in use (e.g. USB-serial unplugged)"""
654
655 def read(self, size=1):
656 """Read size bytes from the serial port. If a timeout is set it may
657 return less characters as requested. With no timeout it will block
658 until the requested number of bytes is read."""
659 if self.fd is None: raise portNotOpenError
660 read = bytearray()
661 poll = select.poll()
662 poll.register(self.fd, select.POLLIN|select.POLLERR|select.POLLHUP|select.POLLNVAL)
663 if size > 0:
664 while len(read) < size:
665 # print "\tread(): size",size, "have", len(read) #debug
666 # wait until device becomes ready to read (or something fails)
cliechti4cd0d2e2010-07-21 01:15:25 +0000667 for fd, event in poll.poll(self._timeout*1000):
cliechtia9a093e2010-01-02 03:05:08 +0000668 if event & (select.POLLERR|select.POLLHUP|select.POLLNVAL):
669 raise SerialException('device reports error (poll)')
670 # we don't care if it is select.POLLIN or timeout, that's
671 # handled below
672 buf = os.read(self.fd, size - len(read))
673 read.extend(buf)
674 if ((self._timeout is not None and self._timeout >= 0) or
675 (self._interCharTimeout is not None and self._interCharTimeout > 0)) and not buf:
676 break # early abort on timeout
677 return bytes(read)
678
cliechtif81362e2009-07-25 03:44:33 +0000679
cliechti89b4af12002-02-12 23:24:41 +0000680if __name__ == '__main__':
681 s = Serial(0,
cliechti53c9fd42009-07-23 23:51:51 +0000682 baudrate=19200, # baud rate
683 bytesize=EIGHTBITS, # number of data bits
cliechti3172d3d2009-07-21 22:33:40 +0000684 parity=PARITY_EVEN, # enable parity checking
cliechti53c9fd42009-07-23 23:51:51 +0000685 stopbits=STOPBITS_ONE, # number of stop bits
cliechti3172d3d2009-07-21 22:33:40 +0000686 timeout=3, # set a timeout value, None for waiting forever
687 xonxoff=0, # enable software flow control
688 rtscts=0, # enable RTS/CTS flow control
cliechti89b4af12002-02-12 23:24:41 +0000689 )
690 s.setRTS(1)
691 s.setDTR(1)
692 s.flushInput()
693 s.flushOutput()
694 s.write('hello')
cliechti109486b2009-08-02 00:00:11 +0000695 sys.stdout.write('%r\n' % s.read(5))
696 sys.stdout.write('%s\n' % s.inWaiting())
cliechti89b4af12002-02-12 23:24:41 +0000697 del s
cliechti4569bac2007-11-08 21:57:19 +0000698