blob: d9eec35c7c5b5d0b4f302d2724c6c60478b5c5e9 [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#
cliechti58b481c2009-02-16 20:42:32 +00007# (C) 2001-2009 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
cliechtib5bbf142005-01-15 21:00:48 +000015import sys, os, fcntl, termios, struct, select, errno
cliechtid6bf52c2003-10-01 02:28:12 +000016from 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
cliechti53c9fd42009-07-23 23:51:51 +000029baudrate_constants = {
30 0: 0000000, # hang up
31 50: 0000001,
32 75: 0000002,
33 110: 0000003,
34 134: 0000004,
35 150: 0000005,
36 200: 0000006,
37 300: 0000007,
38 600: 0000010,
39 1200: 0000011,
40 1800: 0000012,
41 2400: 0000013,
42 4800: 0000014,
43 9600: 0000015,
44 19200: 0000016,
45 38400: 0000017,
46 57600: 0010001,
47 115200: 0010002,
48 230400: 0010003,
49 460800: 0010004,
50 500000: 0010005,
51 576000: 0010006,
52 921600: 0010007,
53 1000000: 0010010,
54 1152000: 0010011,
55 1500000: 0010012,
56 2000000: 0010013,
57 2500000: 0010014,
58 3000000: 0010015,
59 3500000: 0010016,
60 4000000: 0010017
61}
62
cliechti3172d3d2009-07-21 22:33:40 +000063# try to detect the OS so that a device can be selected...
cliechti53c9fd42009-07-23 23:51:51 +000064# this code block should supply a device() and set_special_baudrate() function
65# for the platform
cliechtid6bf52c2003-10-01 02:28:12 +000066plat = sys.platform.lower()
cliechti89b4af12002-02-12 23:24:41 +000067
cliechti3172d3d2009-07-21 22:33:40 +000068if plat[:5] == 'linux': # Linux (confirmed)
cliechti53c9fd42009-07-23 23:51:51 +000069
cliechti89b4af12002-02-12 23:24:41 +000070 def device(port):
71 return '/dev/ttyS%d' % port
72
cliechti53c9fd42009-07-23 23:51:51 +000073 ASYNC_SPD_MASK = 0x1030
74 ASYNC_SPD_CUST = 0x0030
75
76 def set_special_baudrate(port, baudrate):
77 import array
78 buf = array.array('i', [0] * 32)
79
80 # get serial_struct
81 FCNTL.ioctl(port.fd, TERMIOS.TIOCGSERIAL, buf)
82
83 # set custom divisor
84 buf[6] = buf[7] / baudrate
85
86 # update flags
87 buf[4] &= ~ASYNC_SPD_MASK
88 buf[4] |= ASYNC_SPD_CUST
89
90 # set serial_struct
91 try:
92 res = FCNTL.ioctl(port.fd, TERMIOS.TIOCSSERIAL, buf)
93 except IOError:
94 raise ValueError('Failed to set custom baud rate: %r' % baudrate)
95
96elif plat == 'cygwin': # cygwin/win32 (confirmed)
97
cliechtif281fde2002-06-07 21:53:40 +000098 def device(port):
cliechtif5831e02002-12-05 23:15:27 +000099 return '/dev/com%d' % (port + 1)
cliechtif281fde2002-06-07 21:53:40 +0000100
cliechti53c9fd42009-07-23 23:51:51 +0000101 ASYNC_SPD_MASK = 0x1030
102 ASYNC_SPD_CUST = 0x0030
103
104 # XXX untested!
105 def set_special_baudrate(port, baudrate):
106 import array
107 buf = array.array('i', [0] * 32)
108
109 # get serial_struct
110 FCNTL.ioctl(port.fd, TERMIOS.TIOCGSERIAL, buf)
111
112 # set custom divisor
113 buf[6] = buf[7] / baudrate
114
115 # update flags
116 buf[4] &= ~ASYNC_SPD_MASK
117 buf[4] |= ASYNC_SPD_CUST
118
119 # set serial_struct
120 try:
121 res = FCNTL.ioctl(port.fd, TERMIOS.TIOCSSERIAL, buf)
122 except IOError:
123 raise ValueError('Failed to set custom baud rate: %r' % baudrate)
124
cliechti3172d3d2009-07-21 22:33:40 +0000125elif plat == 'openbsd3': # BSD (confirmed)
cliechti53c9fd42009-07-23 23:51:51 +0000126
cliechti89b4af12002-02-12 23:24:41 +0000127 def device(port):
128 return '/dev/ttyp%d' % port
129
cliechti53c9fd42009-07-23 23:51:51 +0000130 def set_special_baudrate(port, baudrate):
131 raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
132
cliechti89b4af12002-02-12 23:24:41 +0000133elif plat[:3] == 'bsd' or \
cliechti89b4af12002-02-12 23:24:41 +0000134 plat[:7] == 'freebsd' or \
cliechti53c9fd42009-07-23 23:51:51 +0000135 plat[:7] == 'openbsd': # BSD (confirmed for freebsd4: cuaa%d)
136
cliechti89b4af12002-02-12 23:24:41 +0000137 def device(port):
cliechtieaa96882008-06-16 22:59:20 +0000138 return '/dev/cuad%d' % port
cliechti89b4af12002-02-12 23:24:41 +0000139
cliechti53c9fd42009-07-23 23:51:51 +0000140 def set_special_baudrate(port, baudrate):
141 raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
142
143elif plat[:6] == 'darwin': # OS X
144
145 version = os.uname()[2].split('.')
146 # Tiger or above can support arbitrary serial speeds
147 if int(version[0]) >= 8:
148 # remove all speeds not supported with TERMIOS so that pyserial never
149 # attempts to use them directly
150 for b in baudrate_constants.keys():
151 if b > 230400:
152 del baudrate_constants[b]
153
154 def set_special_baudrate(port, baudrate):
155 # use IOKit-specific call to set up high speeds
156 import array, fcntl
157 buf = array.array('i', [baudrate])
158 IOSSIOSPEED = 0x80045402 #_IOW('T', 2, speed_t)
159 fcntl.ioctl(port.fd, IOSSIOSPEED, buf, 1)
160 else: # version < 8
161 def set_special_baudrate(port, baudrate):
162 raise ValueError("baud rate not supported")
163
164 def device(port):
165 return '/dev/cuad%d' % port
166
167
cliechti3172d3d2009-07-21 22:33:40 +0000168elif plat[:6] == 'netbsd': # NetBSD 1.6 testing by Erk
cliechti53c9fd42009-07-23 23:51:51 +0000169
cliechti835996a2004-06-02 19:45:07 +0000170 def device(port):
171 return '/dev/dty%02d' % port
172
cliechti53c9fd42009-07-23 23:51:51 +0000173 def set_special_baudrate(port, baudrate):
174 raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
175
cliechti3172d3d2009-07-21 22:33:40 +0000176elif plat[:4] == 'irix': # IRIX (partially tested)
cliechti53c9fd42009-07-23 23:51:51 +0000177
cliechti89b4af12002-02-12 23:24:41 +0000178 def device(port):
cliechtie2418e92006-06-05 20:03:17 +0000179 return '/dev/ttyf%d' % (port+1) #XXX different device names depending on flow control
cliechti89b4af12002-02-12 23:24:41 +0000180
cliechti53c9fd42009-07-23 23:51:51 +0000181 def set_special_baudrate(port, baudrate):
182 raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
183
cliechti3172d3d2009-07-21 22:33:40 +0000184elif plat[:2] == 'hp': # HP-UX (not tested)
cliechti53c9fd42009-07-23 23:51:51 +0000185
cliechti89b4af12002-02-12 23:24:41 +0000186 def device(port):
187 return '/dev/tty%dp0' % (port+1)
188
cliechti53c9fd42009-07-23 23:51:51 +0000189 def set_special_baudrate(port, baudrate):
190 raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
191
cliechti3172d3d2009-07-21 22:33:40 +0000192elif plat[:5] == 'sunos': # Solaris/SunOS (confirmed)
cliechti53c9fd42009-07-23 23:51:51 +0000193
cliechti89b4af12002-02-12 23:24:41 +0000194 def device(port):
195 return '/dev/tty%c' % (ord('a')+port)
cliechti58b481c2009-02-16 20:42:32 +0000196
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
cliechti3172d3d2009-07-21 22:33:40 +0000200elif plat[:3] == 'aix': # AIX
cliechti53c9fd42009-07-23 23:51:51 +0000201
cliechti40e1b072005-03-12 12:05:26 +0000202 def device(port):
203 return '/dev/tty%d' % (port)
cliechti89b4af12002-02-12 23:24:41 +0000204
cliechti53c9fd42009-07-23 23:51:51 +0000205 def set_special_baudrate(port, baudrate):
206 raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
207
cliechti89b4af12002-02-12 23:24:41 +0000208else:
209 #platform detection has failed...
cliechti7aaead32009-07-23 14:02:41 +0000210 sys.stderr.write("""\
211don't know how to number ttys on this system.
cliechti895e8302004-04-20 02:40:28 +0000212! Use an explicit path (eg /dev/ttyS1) or send this information to
213! the author of this module:
cliechti89b4af12002-02-12 23:24:41 +0000214
cliechti895e8302004-04-20 02:40:28 +0000215sys.platform = %r
216os.name = %r
217serialposix.py version = %s
cliechti89b4af12002-02-12 23:24:41 +0000218
219also add the device name of the serial port and where the
220counting starts for the first serial port.
221e.g. 'first serial port: /dev/ttyS0'
222and with a bit luck you can get this module running...
cliechti7aaead32009-07-23 14:02:41 +0000223""" % (sys.platform, os.name, VERSION))
cliechti58b481c2009-02-16 20:42:32 +0000224 # no exception, just continue with a brave attempt to build a device name
225 # even if the device name is not correct for the platform it has chances
cliechti3172d3d2009-07-21 22:33:40 +0000226 # to work using a string with the real device name as port parameter.
cliechtid6bf52c2003-10-01 02:28:12 +0000227 def device(portum):
228 return '/dev/ttyS%d' % portnum
cliechti53c9fd42009-07-23 23:51:51 +0000229 def set_special_baudrate(port, baudrate):
230 raise SerialException("sorry don't know how to handle non standard baud rate on this platform")
cliechtid6bf52c2003-10-01 02:28:12 +0000231 #~ raise Exception, "this module does not run on this platform, sorry."
cliechti89b4af12002-02-12 23:24:41 +0000232
cliechti58b481c2009-02-16 20:42:32 +0000233# whats up with "aix", "beos", ....
234# they should work, just need to know the device names.
cliechti89b4af12002-02-12 23:24:41 +0000235
236
cliechti58b481c2009-02-16 20:42:32 +0000237# load some constants for later use.
238# try to use values from TERMIOS, use defaults from linux otherwise
cliechti8901aef2002-11-19 01:15:05 +0000239TIOCMGET = hasattr(TERMIOS, 'TIOCMGET') and TERMIOS.TIOCMGET or 0x5415
240TIOCMBIS = hasattr(TERMIOS, 'TIOCMBIS') and TERMIOS.TIOCMBIS or 0x5416
241TIOCMBIC = hasattr(TERMIOS, 'TIOCMBIC') and TERMIOS.TIOCMBIC or 0x5417
242TIOCMSET = hasattr(TERMIOS, 'TIOCMSET') and TERMIOS.TIOCMSET or 0x5418
cliechti89b4af12002-02-12 23:24:41 +0000243
cliechti8901aef2002-11-19 01:15:05 +0000244#TIOCM_LE = hasattr(TERMIOS, 'TIOCM_LE') and TERMIOS.TIOCM_LE or 0x001
245TIOCM_DTR = hasattr(TERMIOS, 'TIOCM_DTR') and TERMIOS.TIOCM_DTR or 0x002
246TIOCM_RTS = hasattr(TERMIOS, 'TIOCM_RTS') and TERMIOS.TIOCM_RTS or 0x004
247#TIOCM_ST = hasattr(TERMIOS, 'TIOCM_ST') and TERMIOS.TIOCM_ST or 0x008
248#TIOCM_SR = hasattr(TERMIOS, 'TIOCM_SR') and TERMIOS.TIOCM_SR or 0x010
cliechti89b4af12002-02-12 23:24:41 +0000249
cliechti8901aef2002-11-19 01:15:05 +0000250TIOCM_CTS = hasattr(TERMIOS, 'TIOCM_CTS') and TERMIOS.TIOCM_CTS or 0x020
251TIOCM_CAR = hasattr(TERMIOS, 'TIOCM_CAR') and TERMIOS.TIOCM_CAR or 0x040
252TIOCM_RNG = hasattr(TERMIOS, 'TIOCM_RNG') and TERMIOS.TIOCM_RNG or 0x080
253TIOCM_DSR = hasattr(TERMIOS, 'TIOCM_DSR') and TERMIOS.TIOCM_DSR or 0x100
254TIOCM_CD = hasattr(TERMIOS, 'TIOCM_CD') and TERMIOS.TIOCM_CD or TIOCM_CAR
255TIOCM_RI = hasattr(TERMIOS, 'TIOCM_RI') and TERMIOS.TIOCM_RI or TIOCM_RNG
256#TIOCM_OUT1 = hasattr(TERMIOS, 'TIOCM_OUT1') and TERMIOS.TIOCM_OUT1 or 0x2000
257#TIOCM_OUT2 = hasattr(TERMIOS, 'TIOCM_OUT2') and TERMIOS.TIOCM_OUT2 or 0x4000
cliechtif5831e02002-12-05 23:15:27 +0000258TIOCINQ = hasattr(TERMIOS, 'FIONREAD') and TERMIOS.FIONREAD or 0x541B
cliechti89b4af12002-02-12 23:24:41 +0000259
260TIOCM_zero_str = struct.pack('I', 0)
261TIOCM_RTS_str = struct.pack('I', TIOCM_RTS)
262TIOCM_DTR_str = struct.pack('I', TIOCM_DTR)
263
cliechti997b63c2008-06-21 00:09:31 +0000264TIOCSBRK = hasattr(TERMIOS, 'TIOCSBRK') and TERMIOS.TIOCSBRK or 0x5427
265TIOCCBRK = hasattr(TERMIOS, 'TIOCCBRK') and TERMIOS.TIOCCBRK or 0x5428
266
cliechti89b4af12002-02-12 23:24:41 +0000267
cliechtif81362e2009-07-25 03:44:33 +0000268class PosixSerial(SerialBase):
cliechtid6bf52c2003-10-01 02:28:12 +0000269 """Serial port class POSIX implementation. Serial port configuration is
270 done with termios and fcntl. Runs on Linux and many other Un*x like
271 systems."""
272
273 def open(self):
274 """Open port with current settings. This may throw a SerialException
275 if the port cannot be opened."""
cliechtif81362e2009-07-25 03:44:33 +0000276 self.fd = None
cliechtid6bf52c2003-10-01 02:28:12 +0000277 if self._port is None:
278 raise SerialException("Port must be configured before it can be used.")
cliechti58b481c2009-02-16 20:42:32 +0000279 # open
cliechti4616bf12002-04-08 23:13:14 +0000280 try:
281 self.fd = os.open(self.portstr, os.O_RDWR|os.O_NOCTTY|os.O_NONBLOCK)
282 except Exception, msg:
283 self.fd = None
cliechti93db61b2006-08-26 19:16:18 +0000284 raise SerialException("could not open port %s: %s" % (self._port, msg))
cliechti2750b832009-07-28 00:13:52 +0000285 #~ fcntl.fcntl(self.fd, FCNTL.F_SETFL, 0) # set blocking
cliechti58b481c2009-02-16 20:42:32 +0000286
cliechtib2f5fc82006-10-20 00:09:07 +0000287 try:
288 self._reconfigurePort()
289 except:
cliechti2750b832009-07-28 00:13:52 +0000290 try:
291 os.close(self.fd)
292 except:
293 # ignore any exception when closing the port
294 # also to keep original exception that happened when setting up
295 pass
cliechtib2f5fc82006-10-20 00:09:07 +0000296 self.fd = None
cliechtif0a4f0f2009-07-21 21:12:37 +0000297 raise
cliechtib2f5fc82006-10-20 00:09:07 +0000298 else:
299 self._isOpen = True
cliechti62611612004-04-20 01:55:43 +0000300 #~ self.flushInput()
cliechti58b481c2009-02-16 20:42:32 +0000301
302
cliechtid6bf52c2003-10-01 02:28:12 +0000303 def _reconfigurePort(self):
cliechtib2f5fc82006-10-20 00:09:07 +0000304 """Set communication parameters on opened port."""
cliechtic6178262004-03-22 22:04:52 +0000305 if self.fd is None:
cliechtid6bf52c2003-10-01 02:28:12 +0000306 raise SerialException("Can only operate on a valid port handle")
cliechtie8c45422008-06-20 23:23:14 +0000307 custom_baud = None
cliechti58b481c2009-02-16 20:42:32 +0000308
cliechti2750b832009-07-28 00:13:52 +0000309 vmin = vtime = 0 # timeout is done via select
cliechti679bfa62008-06-20 23:58:15 +0000310 if self._interCharTimeout is not None:
311 vmin = 1
312 vtime = int(self._interCharTimeout * 10)
cliechti6ce7ab12002-11-07 02:15:00 +0000313 try:
cliechtid6bf52c2003-10-01 02:28:12 +0000314 iflag, oflag, cflag, lflag, ispeed, ospeed, cc = termios.tcgetattr(self.fd)
cliechti2750b832009-07-28 00:13:52 +0000315 except termios.error, msg: # if a port is nonexistent but has a /dev file, it'll fail here
cliechtid6bf52c2003-10-01 02:28:12 +0000316 raise SerialException("Could not configure port: %s" % msg)
cliechti58b481c2009-02-16 20:42:32 +0000317 # set up raw mode / no echo / binary
cliechtid6bf52c2003-10-01 02:28:12 +0000318 cflag |= (TERMIOS.CLOCAL|TERMIOS.CREAD)
319 lflag &= ~(TERMIOS.ICANON|TERMIOS.ECHO|TERMIOS.ECHOE|TERMIOS.ECHOK|TERMIOS.ECHONL|
cliechti835996a2004-06-02 19:45:07 +0000320 TERMIOS.ISIG|TERMIOS.IEXTEN) #|TERMIOS.ECHOPRT
cliechti2750b832009-07-28 00:13:52 +0000321 for flag in ('ECHOCTL', 'ECHOKE'): # netbsd workaround for Erk
cliechti835996a2004-06-02 19:45:07 +0000322 if hasattr(TERMIOS, flag):
323 lflag &= ~getattr(TERMIOS, flag)
cliechti58b481c2009-02-16 20:42:32 +0000324
cliechtid6bf52c2003-10-01 02:28:12 +0000325 oflag &= ~(TERMIOS.OPOST)
cliechti895e8302004-04-20 02:40:28 +0000326 iflag &= ~(TERMIOS.INLCR|TERMIOS.IGNCR|TERMIOS.ICRNL|TERMIOS.IGNBRK)
cliechti89b4af12002-02-12 23:24:41 +0000327 if hasattr(TERMIOS, 'IUCLC'):
cliechti895e8302004-04-20 02:40:28 +0000328 iflag &= ~TERMIOS.IUCLC
cliechti3e57b3d2005-08-12 21:04:44 +0000329 if hasattr(TERMIOS, 'PARMRK'):
330 iflag &= ~TERMIOS.PARMRK
cliechti58b481c2009-02-16 20:42:32 +0000331
cliechtif0a4f0f2009-07-21 21:12:37 +0000332 # setup baud rate
cliechti89b4af12002-02-12 23:24:41 +0000333 try:
cliechti2750b832009-07-28 00:13:52 +0000334 ispeed = ospeed = getattr(TERMIOS, 'B%s' % (self._baudrate))
cliechti895e8302004-04-20 02:40:28 +0000335 except AttributeError:
cliechtif1559d02007-11-08 23:43:58 +0000336 try:
337 ispeed = ospeed = baudrate_constants[self._baudrate]
338 except KeyError:
cliechtie8c45422008-06-20 23:23:14 +0000339 #~ raise ValueError('Invalid baud rate: %r' % self._baudrate)
cliechtif0a4f0f2009-07-21 21:12:37 +0000340 # may need custom baud rate, it isn't in our list.
cliechtie8c45422008-06-20 23:23:14 +0000341 ispeed = ospeed = getattr(TERMIOS, 'B38400')
cliechtif0a4f0f2009-07-21 21:12:37 +0000342 try:
343 custom_baud = int(self._baudrate) # store for later
344 except ValueError:
345 raise ValueError('Invalid baud rate: %r' % self._baudrate)
346 else:
347 if custom_baud < 0:
348 raise ValueError('Invalid baud rate: %r' % self._baudrate)
cliechti58b481c2009-02-16 20:42:32 +0000349
350 # setup char len
cliechtid6bf52c2003-10-01 02:28:12 +0000351 cflag &= ~TERMIOS.CSIZE
352 if self._bytesize == 8:
353 cflag |= TERMIOS.CS8
354 elif self._bytesize == 7:
355 cflag |= TERMIOS.CS7
356 elif self._bytesize == 6:
357 cflag |= TERMIOS.CS6
358 elif self._bytesize == 5:
359 cflag |= TERMIOS.CS5
cliechti89b4af12002-02-12 23:24:41 +0000360 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000361 raise ValueError('Invalid char len: %r' % self._bytesize)
cliechti58b481c2009-02-16 20:42:32 +0000362 # setup stopbits
cliechtid6bf52c2003-10-01 02:28:12 +0000363 if self._stopbits == STOPBITS_ONE:
364 cflag &= ~(TERMIOS.CSTOPB)
cliechti58b481c2009-02-16 20:42:32 +0000365 elif self._stopbits == STOPBITS_ONE_POINT_FIVE:
366 cflag |= (TERMIOS.CSTOPB) # XXX same as TWO.. there is no POSIX support for 1.5
cliechtid6bf52c2003-10-01 02:28:12 +0000367 elif self._stopbits == STOPBITS_TWO:
368 cflag |= (TERMIOS.CSTOPB)
cliechti89b4af12002-02-12 23:24:41 +0000369 else:
cliechti3172d3d2009-07-21 22:33:40 +0000370 raise ValueError('Invalid stop bit specification: %r' % self._stopbits)
cliechti58b481c2009-02-16 20:42:32 +0000371 # setup parity
cliechtid6bf52c2003-10-01 02:28:12 +0000372 iflag &= ~(TERMIOS.INPCK|TERMIOS.ISTRIP)
373 if self._parity == PARITY_NONE:
374 cflag &= ~(TERMIOS.PARENB|TERMIOS.PARODD)
375 elif self._parity == PARITY_EVEN:
376 cflag &= ~(TERMIOS.PARODD)
377 cflag |= (TERMIOS.PARENB)
378 elif self._parity == PARITY_ODD:
379 cflag |= (TERMIOS.PARENB|TERMIOS.PARODD)
cliechti89b4af12002-02-12 23:24:41 +0000380 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000381 raise ValueError('Invalid parity: %r' % self._parity)
cliechti58b481c2009-02-16 20:42:32 +0000382 # setup flow control
383 # xonxoff
cliechti89b4af12002-02-12 23:24:41 +0000384 if hasattr(TERMIOS, 'IXANY'):
cliechtid6bf52c2003-10-01 02:28:12 +0000385 if self._xonxoff:
cliechti62611612004-04-20 01:55:43 +0000386 iflag |= (TERMIOS.IXON|TERMIOS.IXOFF) #|TERMIOS.IXANY)
cliechti89b4af12002-02-12 23:24:41 +0000387 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000388 iflag &= ~(TERMIOS.IXON|TERMIOS.IXOFF|TERMIOS.IXANY)
cliechti89b4af12002-02-12 23:24:41 +0000389 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000390 if self._xonxoff:
391 iflag |= (TERMIOS.IXON|TERMIOS.IXOFF)
cliechti89b4af12002-02-12 23:24:41 +0000392 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000393 iflag &= ~(TERMIOS.IXON|TERMIOS.IXOFF)
cliechti58b481c2009-02-16 20:42:32 +0000394 # rtscts
cliechti89b4af12002-02-12 23:24:41 +0000395 if hasattr(TERMIOS, 'CRTSCTS'):
cliechtid6bf52c2003-10-01 02:28:12 +0000396 if self._rtscts:
397 cflag |= (TERMIOS.CRTSCTS)
cliechti89b4af12002-02-12 23:24:41 +0000398 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000399 cflag &= ~(TERMIOS.CRTSCTS)
cliechti2750b832009-07-28 00:13:52 +0000400 elif hasattr(TERMIOS, 'CNEW_RTSCTS'): # try it with alternate constant name
cliechtid6bf52c2003-10-01 02:28:12 +0000401 if self._rtscts:
402 cflag |= (TERMIOS.CNEW_RTSCTS)
cliechtid4743692002-04-08 22:39:53 +0000403 else:
cliechtid6bf52c2003-10-01 02:28:12 +0000404 cflag &= ~(TERMIOS.CNEW_RTSCTS)
cliechti2750b832009-07-28 00:13:52 +0000405 # XXX should there be a warning if setting up rtscts (and xonxoff etc) fails??
cliechti58b481c2009-02-16 20:42:32 +0000406
407 # buffer
408 # vmin "minimal number of characters to be read. = for non blocking"
cliechtid6bf52c2003-10-01 02:28:12 +0000409 if vmin < 0 or vmin > 255:
410 raise ValueError('Invalid vmin: %r ' % vmin)
411 cc[TERMIOS.VMIN] = vmin
cliechti58b481c2009-02-16 20:42:32 +0000412 # vtime
cliechtid6bf52c2003-10-01 02:28:12 +0000413 if vtime < 0 or vtime > 255:
414 raise ValueError('Invalid vtime: %r' % vtime)
415 cc[TERMIOS.VTIME] = vtime
cliechti58b481c2009-02-16 20:42:32 +0000416 # activate settings
cliechtid6bf52c2003-10-01 02:28:12 +0000417 termios.tcsetattr(self.fd, TERMIOS.TCSANOW, [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
cliechti58b481c2009-02-16 20:42:32 +0000418
cliechtie8c45422008-06-20 23:23:14 +0000419 # apply custom baud rate, if any
420 if custom_baud is not None:
cliechti53c9fd42009-07-23 23:51:51 +0000421 set_special_baudrate(self, custom_baud)
cliechti89b4af12002-02-12 23:24:41 +0000422
423 def close(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000424 """Close port"""
425 if self._isOpen:
cliechtic6178262004-03-22 22:04:52 +0000426 if self.fd is not None:
cliechtid6bf52c2003-10-01 02:28:12 +0000427 os.close(self.fd)
428 self.fd = None
429 self._isOpen = False
cliechti89b4af12002-02-12 23:24:41 +0000430
cliechtid6bf52c2003-10-01 02:28:12 +0000431 def makeDeviceName(self, port):
432 return device(port)
433
434 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechti95c62212002-03-04 22:17:53 +0000435
cliechti89b4af12002-02-12 23:24:41 +0000436 def inWaiting(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000437 """Return the number of characters currently in the input buffer."""
cliechtif5831e02002-12-05 23:15:27 +0000438 #~ s = fcntl.ioctl(self.fd, TERMIOS.FIONREAD, TIOCM_zero_str)
439 s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str)
cliechti89b4af12002-02-12 23:24:41 +0000440 return struct.unpack('I',s)[0]
441
cliechti4a567a02009-07-27 22:09:31 +0000442 def read(self, size=1):
cliechtid6bf52c2003-10-01 02:28:12 +0000443 """Read size bytes from the serial port. If a timeout is set it may
444 return less characters as requested. With no timeout it will block
445 until the requested number of bytes is read."""
cliechtic6178262004-03-22 22:04:52 +0000446 if self.fd is None: raise portNotOpenError
cliechti4a567a02009-07-27 22:09:31 +0000447 read = bytearray()
cliechti8d5dbe22002-04-24 20:44:13 +0000448 inp = None
cliechti89b4af12002-02-12 23:24:41 +0000449 if size > 0:
450 while len(read) < size:
cliechti58b481c2009-02-16 20:42:32 +0000451 # print "\tread(): size",size, "have", len(read) #debug
cliechti4a567a02009-07-27 22:09:31 +0000452 ready,_,_ = select.select([self.fd], [], [], self._timeout)
cliechtia9e4e952002-05-26 01:20:22 +0000453 if not ready:
cliechti58b481c2009-02-16 20:42:32 +0000454 break # timeout
cliechti4a567a02009-07-27 22:09:31 +0000455 buf = os.read(self.fd, size - len(read))
456 read.extend(buf)
cliechti2750b832009-07-28 00:13:52 +0000457 if ((self._timeout is not None and self._timeout >= 0) or
458 (self._interCharTimeout is not None and self._interCharTimeout > 0)) and not buf:
cliechti58b481c2009-02-16 20:42:32 +0000459 break # early abort on timeout
cliechti4a567a02009-07-27 22:09:31 +0000460 return bytes(read)
cliechti89b4af12002-02-12 23:24:41 +0000461
cliechti4a567a02009-07-27 22:09:31 +0000462 def write(self, data):
cliechtid6bf52c2003-10-01 02:28:12 +0000463 """Output the given string over the serial port."""
cliechtic6178262004-03-22 22:04:52 +0000464 if self.fd is None: raise portNotOpenError
cliechtiddd78132009-07-28 01:13:28 +0000465 if not isinstance(data, (bytes, bytearray)):
466 raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data)))
cliechtid6bf52c2003-10-01 02:28:12 +0000467 t = len(data)
468 d = data
cliechtic6178262004-03-22 22:04:52 +0000469 while t > 0:
cliechti5d4d0bd2004-11-13 03:27:39 +0000470 try:
471 if self._writeTimeout is not None and self._writeTimeout > 0:
cliechti4a567a02009-07-27 22:09:31 +0000472 _, ready, _ = select.select([], [self.fd], [], self._writeTimeout)
cliechti5d4d0bd2004-11-13 03:27:39 +0000473 if not ready:
474 raise writeTimeoutError
475 n = os.write(self.fd, d)
476 if self._writeTimeout is not None and self._writeTimeout > 0:
cliechti4a567a02009-07-27 22:09:31 +0000477 _, ready, _ = select.select([], [self.fd], [], self._writeTimeout)
cliechti5d4d0bd2004-11-13 03:27:39 +0000478 if not ready:
479 raise writeTimeoutError
480 d = d[n:]
481 t = t - n
cliechti4a567a02009-07-27 22:09:31 +0000482 except OSError, v:
cliechti5d4d0bd2004-11-13 03:27:39 +0000483 if v.errno != errno.EAGAIN:
484 raise
cliechtif81362e2009-07-25 03:44:33 +0000485 return len(data)
cliechtid6bf52c2003-10-01 02:28:12 +0000486
cliechtia30a8a02003-10-05 12:28:13 +0000487 def flush(self):
488 """Flush of file like objects. In this case, wait until all data
489 is written."""
490 self.drainOutput()
491
cliechti89b4af12002-02-12 23:24:41 +0000492 def flushInput(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000493 """Clear input buffer, discarding all that is in the buffer."""
cliechtic6178262004-03-22 22:04:52 +0000494 if self.fd is None:
cliechti89b4af12002-02-12 23:24:41 +0000495 raise portNotOpenError
496 termios.tcflush(self.fd, TERMIOS.TCIFLUSH)
497
498 def flushOutput(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000499 """Clear output buffer, aborting the current output and
500 discarding all that is in the buffer."""
cliechtic6178262004-03-22 22:04:52 +0000501 if self.fd is None:
cliechti89b4af12002-02-12 23:24:41 +0000502 raise portNotOpenError
503 termios.tcflush(self.fd, TERMIOS.TCOFLUSH)
504
cliechtiaaa04602006-02-05 23:02:46 +0000505 def sendBreak(self, duration=0.25):
cliechti997b63c2008-06-21 00:09:31 +0000506 """Send break condition. Timed, returns to idle state after given duration."""
cliechtic6178262004-03-22 22:04:52 +0000507 if self.fd is None:
cliechti89b4af12002-02-12 23:24:41 +0000508 raise portNotOpenError
cliechtiaaa04602006-02-05 23:02:46 +0000509 termios.tcsendbreak(self.fd, int(duration/0.25))
cliechti89b4af12002-02-12 23:24:41 +0000510
cliechti997b63c2008-06-21 00:09:31 +0000511 def setBreak(self, level=1):
cliechtidfec0c82009-07-21 01:35:41 +0000512 """Set break: Controls TXD. When active, no transmitting is possible."""
cliechti997b63c2008-06-21 00:09:31 +0000513 if self.fd is None: raise portNotOpenError
514 if level:
515 fcntl.ioctl(self.fd, TIOCSBRK)
516 else:
517 fcntl.ioctl(self.fd, TIOCCBRK)
518
cliechti93db61b2006-08-26 19:16:18 +0000519 def setRTS(self, level=1):
cliechtid6bf52c2003-10-01 02:28:12 +0000520 """Set terminal status line: Request To Send"""
cliechtic6178262004-03-22 22:04:52 +0000521 if self.fd is None: raise portNotOpenError
cliechtib2f5fc82006-10-20 00:09:07 +0000522 if level:
cliechtid6bf52c2003-10-01 02:28:12 +0000523 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_RTS_str)
524 else:
525 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_RTS_str)
526
cliechti93db61b2006-08-26 19:16:18 +0000527 def setDTR(self, level=1):
cliechtid6bf52c2003-10-01 02:28:12 +0000528 """Set terminal status line: Data Terminal Ready"""
cliechtic6178262004-03-22 22:04:52 +0000529 if self.fd is None: raise portNotOpenError
cliechtib2f5fc82006-10-20 00:09:07 +0000530 if level:
cliechtid6bf52c2003-10-01 02:28:12 +0000531 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str)
532 else:
533 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_DTR_str)
534
535 def getCTS(self):
536 """Read terminal status line: Clear To Send"""
cliechtic6178262004-03-22 22:04:52 +0000537 if self.fd is None: raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000538 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
539 return struct.unpack('I',s)[0] & TIOCM_CTS != 0
540
541 def getDSR(self):
542 """Read terminal status line: Data Set Ready"""
cliechtic6178262004-03-22 22:04:52 +0000543 if self.fd is None: raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000544 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
545 return struct.unpack('I',s)[0] & TIOCM_DSR != 0
546
cliechtid6bf52c2003-10-01 02:28:12 +0000547 def getRI(self):
548 """Read terminal status line: Ring Indicator"""
cliechtic6178262004-03-22 22:04:52 +0000549 if self.fd is None: raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000550 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
cliechtid6bf52c2003-10-01 02:28:12 +0000551 return struct.unpack('I',s)[0] & TIOCM_RI != 0
cliechti89b4af12002-02-12 23:24:41 +0000552
553 def getCD(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000554 """Read terminal status line: Carrier Detect"""
cliechtic6178262004-03-22 22:04:52 +0000555 if self.fd is None: raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000556 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
cliechtid6bf52c2003-10-01 02:28:12 +0000557 return struct.unpack('I',s)[0] & TIOCM_CD != 0
cliechti89b4af12002-02-12 23:24:41 +0000558
cliechtia30a8a02003-10-05 12:28:13 +0000559 # - - platform specific - - - -
560
561 def drainOutput(self):
562 """internal - not portable!"""
cliechtic6178262004-03-22 22:04:52 +0000563 if self.fd is None: raise portNotOpenError
cliechtia30a8a02003-10-05 12:28:13 +0000564 termios.tcdrain(self.fd)
565
566 def nonblocking(self):
567 """internal - not portable!"""
cliechtic6178262004-03-22 22:04:52 +0000568 if self.fd is None:
cliechtia30a8a02003-10-05 12:28:13 +0000569 raise portNotOpenError
570 fcntl.fcntl(self.fd, FCNTL.F_SETFL, FCNTL.O_NONBLOCK)
571
cliechti8753bbc2005-01-15 20:32:51 +0000572 def fileno(self):
cliechtifab09872009-02-07 00:25:44 +0000573 """For easier use of the serial port instance with select.
cliechti8753bbc2005-01-15 20:32:51 +0000574 WARNING: this function is not portable to different platforms!"""
575 if self.fd is None: raise portNotOpenError
576 return self.fd
cliechti89b4af12002-02-12 23:24:41 +0000577
cliechtif81362e2009-07-25 03:44:33 +0000578
579# assemble Serial class with the platform specifc implementation and the base
cliechti4a567a02009-07-27 22:09:31 +0000580# for file-like behavior. for Python 2.6 and newer, that provide the new I/O
581# library, derrive from io.RawIOBase
582try:
583 import io
584except ImportError:
585 # classic version with our own file-like emulation
586 class Serial(PosixSerial, FileLike):
587 pass
588else:
589 # io library present
590 class Serial(PosixSerial, io.RawIOBase):
cliechtif81362e2009-07-25 03:44:33 +0000591 pass
592
593
cliechti89b4af12002-02-12 23:24:41 +0000594if __name__ == '__main__':
595 s = Serial(0,
cliechti53c9fd42009-07-23 23:51:51 +0000596 baudrate=19200, # baud rate
597 bytesize=EIGHTBITS, # number of data bits
cliechti3172d3d2009-07-21 22:33:40 +0000598 parity=PARITY_EVEN, # enable parity checking
cliechti53c9fd42009-07-23 23:51:51 +0000599 stopbits=STOPBITS_ONE, # number of stop bits
cliechti3172d3d2009-07-21 22:33:40 +0000600 timeout=3, # set a timeout value, None for waiting forever
601 xonxoff=0, # enable software flow control
602 rtscts=0, # enable RTS/CTS flow control
cliechti89b4af12002-02-12 23:24:41 +0000603 )
604 s.setRTS(1)
605 s.setDTR(1)
606 s.flushInput()
607 s.flushOutput()
608 s.write('hello')
cliechti109486b2009-08-02 00:00:11 +0000609 sys.stdout.write('%r\n' % s.read(5))
610 sys.stdout.write('%s\n' % s.inWaiting())
cliechti89b4af12002-02-12 23:24:41 +0000611 del s
cliechti4569bac2007-11-08 21:57:19 +0000612