15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#!/usr/bin/env python
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Python Serial Port Extension for Win32, Linux, BSD, Jython
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# module for serial IO for POSIX compatible systems, like Linux
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# see __init__.py
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# (C) 2001-2010 Chris Liechti <cliechti@gmx.net>
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# this is distributed under a free software license, see license.txt
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# parts based on code from Grant B. Edwards  <grante@visi.com>:
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#  ftp://ftp.visi.com/users/grante/python/PosixSerial.py
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# references: http://www.easysw.com/~mike/serial/serial.html
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)import sys, os, fcntl, termios, struct, select, errno, time
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)from serial.serialutil import *
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Do check the Python version as some constants have moved.
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)if (sys.hexversion < 0x020100f0):
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    import TERMIOS
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)else:
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TERMIOS = termios
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)if (sys.hexversion < 0x020200f0):
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    import FCNTL
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)else:
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FCNTL = fcntl
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# try to detect the OS so that a device can be selected...
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# this code block should supply a device() and set_special_baudrate() function
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# for the platform
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)plat = sys.platform.lower()
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)if   plat[:5] == 'linux':    # Linux (confirmed)
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def device(port):
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return '/dev/ttyS%d' % port
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TCGETS2 = 0x802C542A
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TCSETS2 = 0x402C542B
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    BOTHER = 0o010000
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def set_special_baudrate(port, baudrate):
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # right size is 44 on x86_64, allow for some growth
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        import array
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        buf = array.array('i', [0] * 64)
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        try:
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            # get serial_struct
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            FCNTL.ioctl(port.fd, TCGETS2, buf)
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            # set custom speed
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            buf[2] &= ~TERMIOS.CBAUD
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            buf[2] |= BOTHER
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            buf[9] = buf[10] = baudrate
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            # set serial_struct
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            res = FCNTL.ioctl(port.fd, TCSETS2, buf)
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        except IOError, e:
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            raise ValueError('Failed to set custom baud rate (%s): %s' % (baudrate, e))
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    baudrate_constants = {
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        0:       0000000,  # hang up
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        50:      0000001,
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        75:      0000002,
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        110:     0000003,
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        134:     0000004,
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        150:     0000005,
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        200:     0000006,
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        300:     0000007,
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        600:     0000010,
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        1200:    0000011,
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        1800:    0000012,
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        2400:    0000013,
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        4800:    0000014,
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        9600:    0000015,
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        19200:   0000016,
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        38400:   0000017,
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        57600:   0010001,
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        115200:  0010002,
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        230400:  0010003,
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        460800:  0010004,
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        500000:  0010005,
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        576000:  0010006,
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        921600:  0010007,
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        1000000: 0010010,
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        1152000: 0010011,
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        1500000: 0010012,
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        2000000: 0010013,
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        2500000: 0010014,
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        3000000: 0010015,
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        3500000: 0010016,
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        4000000: 0010017
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)elif plat == 'cygwin':       # cygwin/win32 (confirmed)
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def device(port):
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return '/dev/com%d' % (port + 1)
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def set_special_baudrate(port, baudrate):
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    baudrate_constants = {
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        128000: 0x01003,
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        256000: 0x01005,
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        500000: 0x01007,
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        576000: 0x01008,
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        921600: 0x01009,
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        1000000: 0x0100a,
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        1152000: 0x0100b,
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        1500000: 0x0100c,
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        2000000: 0x0100d,
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        2500000: 0x0100e,
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        3000000: 0x0100f
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)elif plat[:7] == 'openbsd':    # OpenBSD
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def device(port):
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return '/dev/cua%02d' % port
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def set_special_baudrate(port, baudrate):
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    baudrate_constants = {}
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)elif plat[:3] == 'bsd' or  \
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    plat[:7] == 'freebsd':
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def device(port):
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return '/dev/cuad%d' % port
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def set_special_baudrate(port, baudrate):
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    baudrate_constants = {}
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)elif plat[:6] == 'darwin':   # OS X
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    version = os.uname()[2].split('.')
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    # Tiger or above can support arbitrary serial speeds
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if int(version[0]) >= 8:
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        def set_special_baudrate(port, baudrate):
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            # use IOKit-specific call to set up high speeds
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            import array, fcntl
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            buf = array.array('i', [baudrate])
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            IOSSIOSPEED = 0x80045402 #_IOW('T', 2, speed_t)
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            fcntl.ioctl(port.fd, IOSSIOSPEED, buf, 1)
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    else: # version < 8
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        def set_special_baudrate(port, baudrate):
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            raise ValueError("baud rate not supported")
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def device(port):
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return '/dev/cuad%d' % port
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    baudrate_constants = {}
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)elif plat[:6] == 'netbsd':   # NetBSD 1.6 testing by Erk
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def device(port):
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return '/dev/dty%02d' % port
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def set_special_baudrate(port, baudrate):
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    baudrate_constants = {}
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)elif plat[:4] == 'irix':     # IRIX (partially tested)
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def device(port):
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return '/dev/ttyf%d' % (port+1) #XXX different device names depending on flow control
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def set_special_baudrate(port, baudrate):
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    baudrate_constants = {}
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)elif plat[:2] == 'hp':       # HP-UX (not tested)
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def device(port):
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return '/dev/tty%dp0' % (port+1)
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def set_special_baudrate(port, baudrate):
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    baudrate_constants = {}
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)elif plat[:5] == 'sunos':    # Solaris/SunOS (confirmed)
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def device(port):
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return '/dev/tty%c' % (ord('a')+port)
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def set_special_baudrate(port, baudrate):
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    baudrate_constants = {}
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)elif plat[:3] == 'aix':      # AIX
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def device(port):
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return '/dev/tty%d' % (port)
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def set_special_baudrate(port, baudrate):
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    baudrate_constants = {}
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)else:
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    # platform detection has failed...
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    sys.stderr.write("""\
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)don't know how to number ttys on this system.
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)! Use an explicit path (eg /dev/ttyS1) or send this information to
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)! the author of this module:
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)sys.platform = %r
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)os.name = %r
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)serialposix.py version = %s
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)also add the device name of the serial port and where the
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)counting starts for the first serial port.
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)e.g. 'first serial port: /dev/ttyS0'
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)and with a bit luck you can get this module running...
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)""" % (sys.platform, os.name, VERSION))
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    # no exception, just continue with a brave attempt to build a device name
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    # even if the device name is not correct for the platform it has chances
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    # to work using a string with the real device name as port parameter.
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def device(portum):
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return '/dev/ttyS%d' % portnum
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def set_special_baudrate(port, baudrate):
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        raise SerialException("sorry don't know how to handle non standard baud rate on this platform")
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    baudrate_constants = {}
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    #~ raise Exception, "this module does not run on this platform, sorry."
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# whats up with "aix", "beos", ....
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# they should work, just need to know the device names.
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# load some constants for later use.
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# try to use values from TERMIOS, use defaults from linux otherwise
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TIOCMGET  = hasattr(TERMIOS, 'TIOCMGET') and TERMIOS.TIOCMGET or 0x5415
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TIOCMBIS  = hasattr(TERMIOS, 'TIOCMBIS') and TERMIOS.TIOCMBIS or 0x5416
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TIOCMBIC  = hasattr(TERMIOS, 'TIOCMBIC') and TERMIOS.TIOCMBIC or 0x5417
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TIOCMSET  = hasattr(TERMIOS, 'TIOCMSET') and TERMIOS.TIOCMSET or 0x5418
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#TIOCM_LE = hasattr(TERMIOS, 'TIOCM_LE') and TERMIOS.TIOCM_LE or 0x001
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TIOCM_DTR = hasattr(TERMIOS, 'TIOCM_DTR') and TERMIOS.TIOCM_DTR or 0x002
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TIOCM_RTS = hasattr(TERMIOS, 'TIOCM_RTS') and TERMIOS.TIOCM_RTS or 0x004
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#TIOCM_ST = hasattr(TERMIOS, 'TIOCM_ST') and TERMIOS.TIOCM_ST or 0x008
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#TIOCM_SR = hasattr(TERMIOS, 'TIOCM_SR') and TERMIOS.TIOCM_SR or 0x010
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TIOCM_CTS = hasattr(TERMIOS, 'TIOCM_CTS') and TERMIOS.TIOCM_CTS or 0x020
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TIOCM_CAR = hasattr(TERMIOS, 'TIOCM_CAR') and TERMIOS.TIOCM_CAR or 0x040
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TIOCM_RNG = hasattr(TERMIOS, 'TIOCM_RNG') and TERMIOS.TIOCM_RNG or 0x080
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TIOCM_DSR = hasattr(TERMIOS, 'TIOCM_DSR') and TERMIOS.TIOCM_DSR or 0x100
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TIOCM_CD  = hasattr(TERMIOS, 'TIOCM_CD') and TERMIOS.TIOCM_CD or TIOCM_CAR
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TIOCM_RI  = hasattr(TERMIOS, 'TIOCM_RI') and TERMIOS.TIOCM_RI or TIOCM_RNG
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#TIOCM_OUT1 = hasattr(TERMIOS, 'TIOCM_OUT1') and TERMIOS.TIOCM_OUT1 or 0x2000
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#TIOCM_OUT2 = hasattr(TERMIOS, 'TIOCM_OUT2') and TERMIOS.TIOCM_OUT2 or 0x4000
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)if hasattr(TERMIOS, 'TIOCINQ'):
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TIOCINQ = TERMIOS.TIOCINQ
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)else:
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TIOCINQ = hasattr(TERMIOS, 'FIONREAD') and TERMIOS.FIONREAD or 0x541B
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TIOCOUTQ   = hasattr(TERMIOS, 'TIOCOUTQ') and TERMIOS.TIOCOUTQ or 0x5411
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TIOCM_zero_str = struct.pack('I', 0)
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TIOCM_RTS_str = struct.pack('I', TIOCM_RTS)
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TIOCM_DTR_str = struct.pack('I', TIOCM_DTR)
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TIOCSBRK  = hasattr(TERMIOS, 'TIOCSBRK') and TERMIOS.TIOCSBRK or 0x5427
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TIOCCBRK  = hasattr(TERMIOS, 'TIOCCBRK') and TERMIOS.TIOCCBRK or 0x5428
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class PosixSerial(SerialBase):
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    """Serial port class POSIX implementation. Serial port configuration is
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    done with termios and fcntl. Runs on Linux and many other Un*x like
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    systems."""
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def open(self):
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """Open port with current settings. This may throw a SerialException
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           if the port cannot be opened."""
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if self._port is None:
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            raise SerialException("Port must be configured before it can be used.")
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if self._isOpen:
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            raise SerialException("Port is already open.")
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        self.fd = None
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # open
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        try:
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            self.fd = os.open(self.portstr, os.O_RDWR|os.O_NOCTTY|os.O_NONBLOCK)
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        except IOError, msg:
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            self.fd = None
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            raise SerialException(msg.errno, "could not open port %s: %s" % (self._port, msg))
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        #~ fcntl.fcntl(self.fd, FCNTL.F_SETFL, 0)  # set blocking
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        try:
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            self._reconfigurePort()
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        except:
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            try:
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                os.close(self.fd)
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            except:
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                # ignore any exception when closing the port
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                # also to keep original exception that happened when setting up
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                pass
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            self.fd = None
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            raise
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        else:
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            self._isOpen = True
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        self.flushInput()
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def _reconfigurePort(self):
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """Set communication parameters on opened port."""
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if self.fd is None:
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            raise SerialException("Can only operate on a valid file descriptor")
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        custom_baud = None
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        vmin = vtime = 0                # timeout is done via select
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if self._interCharTimeout is not None:
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            vmin = 1
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            vtime = int(self._interCharTimeout * 10)
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        try:
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            orig_attr = termios.tcgetattr(self.fd)
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        except termios.error, msg:      # if a port is nonexistent but has a /dev file, it'll fail here
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            raise SerialException("Could not configure port: %s" % msg)
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # set up raw mode / no echo / binary
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        cflag |=  (TERMIOS.CLOCAL|TERMIOS.CREAD)
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        lflag &= ~(TERMIOS.ICANON|TERMIOS.ECHO|TERMIOS.ECHOE|TERMIOS.ECHOK|TERMIOS.ECHONL|
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     TERMIOS.ISIG|TERMIOS.IEXTEN) #|TERMIOS.ECHOPRT
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        for flag in ('ECHOCTL', 'ECHOKE'): # netbsd workaround for Erk
3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            if hasattr(TERMIOS, flag):
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                lflag &= ~getattr(TERMIOS, flag)
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        oflag &= ~(TERMIOS.OPOST)
3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        iflag &= ~(TERMIOS.INLCR|TERMIOS.IGNCR|TERMIOS.ICRNL|TERMIOS.IGNBRK)
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if hasattr(TERMIOS, 'IUCLC'):
3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            iflag &= ~TERMIOS.IUCLC
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if hasattr(TERMIOS, 'PARMRK'):
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            iflag &= ~TERMIOS.PARMRK
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # setup baud rate
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        try:
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            ispeed = ospeed = getattr(TERMIOS, 'B%s' % (self._baudrate))
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        except AttributeError:
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            try:
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                ispeed = ospeed = baudrate_constants[self._baudrate]
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            except KeyError:
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                #~ raise ValueError('Invalid baud rate: %r' % self._baudrate)
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                # may need custom baud rate, it isn't in our list.
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                ispeed = ospeed = getattr(TERMIOS, 'B38400')
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                try:
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    custom_baud = int(self._baudrate) # store for later
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                except ValueError:
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    raise ValueError('Invalid baud rate: %r' % self._baudrate)
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                else:
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    if custom_baud < 0:
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        raise ValueError('Invalid baud rate: %r' % self._baudrate)
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # setup char len
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        cflag &= ~TERMIOS.CSIZE
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if self._bytesize == 8:
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            cflag |= TERMIOS.CS8
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        elif self._bytesize == 7:
3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            cflag |= TERMIOS.CS7
3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        elif self._bytesize == 6:
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            cflag |= TERMIOS.CS6
3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        elif self._bytesize == 5:
3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            cflag |= TERMIOS.CS5
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        else:
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            raise ValueError('Invalid char len: %r' % self._bytesize)
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # setup stopbits
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if self._stopbits == STOPBITS_ONE:
3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            cflag &= ~(TERMIOS.CSTOPB)
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        elif self._stopbits == STOPBITS_ONE_POINT_FIVE:
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            cflag |=  (TERMIOS.CSTOPB)  # XXX same as TWO.. there is no POSIX support for 1.5
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        elif self._stopbits == STOPBITS_TWO:
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            cflag |=  (TERMIOS.CSTOPB)
3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        else:
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            raise ValueError('Invalid stop bit specification: %r' % self._stopbits)
3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # setup parity
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        iflag &= ~(TERMIOS.INPCK|TERMIOS.ISTRIP)
3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if self._parity == PARITY_NONE:
3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            cflag &= ~(TERMIOS.PARENB|TERMIOS.PARODD)
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        elif self._parity == PARITY_EVEN:
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            cflag &= ~(TERMIOS.PARODD)
3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            cflag |=  (TERMIOS.PARENB)
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        elif self._parity == PARITY_ODD:
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            cflag |=  (TERMIOS.PARENB|TERMIOS.PARODD)
3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        else:
3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            raise ValueError('Invalid parity: %r' % self._parity)
3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # setup flow control
3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # xonxoff
3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if hasattr(TERMIOS, 'IXANY'):
3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            if self._xonxoff:
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                iflag |=  (TERMIOS.IXON|TERMIOS.IXOFF) #|TERMIOS.IXANY)
3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            else:
3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                iflag &= ~(TERMIOS.IXON|TERMIOS.IXOFF|TERMIOS.IXANY)
3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        else:
3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            if self._xonxoff:
4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                iflag |=  (TERMIOS.IXON|TERMIOS.IXOFF)
4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            else:
4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                iflag &= ~(TERMIOS.IXON|TERMIOS.IXOFF)
4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # rtscts
4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if hasattr(TERMIOS, 'CRTSCTS'):
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            if self._rtscts:
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                cflag |=  (TERMIOS.CRTSCTS)
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            else:
4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                cflag &= ~(TERMIOS.CRTSCTS)
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        elif hasattr(TERMIOS, 'CNEW_RTSCTS'):   # try it with alternate constant name
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            if self._rtscts:
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                cflag |=  (TERMIOS.CNEW_RTSCTS)
4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            else:
4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                cflag &= ~(TERMIOS.CNEW_RTSCTS)
4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # XXX should there be a warning if setting up rtscts (and xonxoff etc) fails??
4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # buffer
4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # vmin "minimal number of characters to be read. = for non blocking"
4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if vmin < 0 or vmin > 255:
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            raise ValueError('Invalid vmin: %r ' % vmin)
4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        cc[TERMIOS.VMIN] = vmin
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # vtime
4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if vtime < 0 or vtime > 255:
4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            raise ValueError('Invalid vtime: %r' % vtime)
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        cc[TERMIOS.VTIME] = vtime
4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # activate settings
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] != orig_attr:
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            termios.tcsetattr(self.fd, TERMIOS.TCSANOW, [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # apply custom baud rate, if any
4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if custom_baud is not None:
4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            set_special_baudrate(self, custom_baud)
4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def close(self):
4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """Close port"""
4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if self._isOpen:
4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            if self.fd is not None:
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                os.close(self.fd)
4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                self.fd = None
4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            self._isOpen = False
4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def makeDeviceName(self, port):
4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return device(port)
4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def inWaiting(self):
4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """Return the number of characters currently in the input buffer."""
4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        #~ s = fcntl.ioctl(self.fd, TERMIOS.FIONREAD, TIOCM_zero_str)
4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str)
4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return struct.unpack('I',s)[0]
4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    # select based implementation, proved to work on many systems
4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def read(self, size=1):
4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """Read size bytes from the serial port. If a timeout is set it may
4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           return less characters as requested. With no timeout it will block
4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           until the requested number of bytes is read."""
4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if not self._isOpen: raise portNotOpenError
4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        read = bytearray()
4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        while len(read) < size:
4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            try:
4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                ready,_,_ = select.select([self.fd],[],[], self._timeout)
4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                # If select was used with a timeout, and the timeout occurs, it
4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                # returns with empty lists -> thus abort read operation.
4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                # For timeout == 0 (non-blocking operation) also abort when there
4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                # is nothing to read.
4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                if not ready:
4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    break   # timeout
4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                buf = os.read(self.fd, size-len(read))
4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                # read should always return some data as select reported it was
4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                # ready to read when we get to this point.
4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                if not buf:
4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    # Disconnected devices, at least on Linux, show the
4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    # behavior that they are always ready to read immediately
4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    # but reading returns nothing.
4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    raise SerialException('device reports readiness to read but returned no data (device disconnected or multiple access on port?)')
4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                read.extend(buf)
4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            except select.error, e:
4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                # ignore EAGAIN errors. all other errors are shown
4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                # see also http://www.python.org/dev/peps/pep-3151/#select
4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                if e[0] != errno.EAGAIN:
4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    raise SerialException('read failed: %s' % (e,))
4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            except OSError, e:
4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                # ignore EAGAIN errors. all other errors are shown
4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                if e.errno != errno.EAGAIN:
4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    raise SerialException('read failed: %s' % (e,))
4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return bytes(read)
4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def write(self, data):
4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """Output the given string over the serial port."""
4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if not self._isOpen: raise portNotOpenError
4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        d = to_bytes(data)
4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        tx_len = len(d)
4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if self._writeTimeout is not None and self._writeTimeout > 0:
4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            timeout = time.time() + self._writeTimeout
4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        else:
4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            timeout = None
4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        while tx_len > 0:
4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            try:
4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                n = os.write(self.fd, d)
5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                if timeout:
5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    # when timeout is set, use select to wait for being ready
5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    # with the time left as timeout
5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    timeleft = timeout - time.time()
5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    if timeleft < 0:
5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        raise writeTimeoutError
5065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    _, ready, _ = select.select([], [self.fd], [], timeleft)
5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    if not ready:
5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        raise writeTimeoutError
5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                else:
5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    # wait for write operation
5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    _, ready, _ = select.select([], [self.fd], [], None)
5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    if not ready:
5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        raise SerialException('write failed (select)')
5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                d = d[n:]
5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                tx_len -= n
5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            except OSError, v:
5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                if v.errno != errno.EAGAIN:
5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    raise SerialException('write failed: %s' % (v,))
5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return len(data)
5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def flush(self):
5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """Flush of file like objects. In this case, wait until all data
5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           is written."""
5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        self.drainOutput()
5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def flushInput(self):
5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """Clear input buffer, discarding all that is in the buffer."""
5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if not self._isOpen: raise portNotOpenError
5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        termios.tcflush(self.fd, TERMIOS.TCIFLUSH)
5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def flushOutput(self):
5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """Clear output buffer, aborting the current output and
5335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        discarding all that is in the buffer."""
5345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if not self._isOpen: raise portNotOpenError
5355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        termios.tcflush(self.fd, TERMIOS.TCOFLUSH)
5365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def sendBreak(self, duration=0.25):
5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """Send break condition. Timed, returns to idle state after given duration."""
5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if not self._isOpen: raise portNotOpenError
5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        termios.tcsendbreak(self.fd, int(duration/0.25))
5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def setBreak(self, level=1):
5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """Set break: Controls TXD. When active, no transmitting is possible."""
5445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if self.fd is None: raise portNotOpenError
5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if level:
5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            fcntl.ioctl(self.fd, TIOCSBRK)
5475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        else:
5485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            fcntl.ioctl(self.fd, TIOCCBRK)
5495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def setRTS(self, level=1):
5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """Set terminal status line: Request To Send"""
5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if not self._isOpen: raise portNotOpenError
5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if level:
5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_RTS_str)
5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        else:
5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_RTS_str)
5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def setDTR(self, level=1):
5595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """Set terminal status line: Data Terminal Ready"""
5605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if not self._isOpen: raise portNotOpenError
5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if level:
5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str)
5635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        else:
5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_DTR_str)
5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def getCTS(self):
5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """Read terminal status line: Clear To Send"""
5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if not self._isOpen: raise portNotOpenError
5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
5705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return struct.unpack('I',s)[0] & TIOCM_CTS != 0
5715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def getDSR(self):
5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """Read terminal status line: Data Set Ready"""
5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if not self._isOpen: raise portNotOpenError
5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
5765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return struct.unpack('I',s)[0] & TIOCM_DSR != 0
5775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def getRI(self):
5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """Read terminal status line: Ring Indicator"""
5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if not self._isOpen: raise portNotOpenError
5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
5825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return struct.unpack('I',s)[0] & TIOCM_RI != 0
5835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def getCD(self):
5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """Read terminal status line: Carrier Detect"""
5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if not self._isOpen: raise portNotOpenError
5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
5885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return struct.unpack('I',s)[0] & TIOCM_CD != 0
5895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    # - - platform specific - - - -
5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def outWaiting(self):
5935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """Return the number of characters currently in the output buffer."""
5945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        #~ s = fcntl.ioctl(self.fd, TERMIOS.FIONREAD, TIOCM_zero_str)
5955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        s = fcntl.ioctl(self.fd, TIOCOUTQ, TIOCM_zero_str)
5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return struct.unpack('I',s)[0]
5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def drainOutput(self):
5995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """internal - not portable!"""
6005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if not self._isOpen: raise portNotOpenError
6015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        termios.tcdrain(self.fd)
6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def nonblocking(self):
6045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """internal - not portable!"""
6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if not self._isOpen: raise portNotOpenError
6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        fcntl.fcntl(self.fd, FCNTL.F_SETFL, os.O_NONBLOCK)
6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def fileno(self):
6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """\
6105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        For easier use of the serial port instance with select.
6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        WARNING: this function is not portable to different platforms!
6125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """
6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if not self._isOpen: raise portNotOpenError
6145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return self.fd
6155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def setXON(self, level=True):
6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """\
6185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        Manually control flow - when software flow control is enabled.
6195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        This will send XON (true) and XOFF (false) to the other device.
6205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        WARNING: this function is not portable to different platforms!
6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """
6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if not self.hComPort: raise portNotOpenError
6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if enable:
6245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            termios.tcflow(self.fd, TERMIOS.TCION)
6255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        else:
6265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            termios.tcflow(self.fd, TERMIOS.TCIOFF)
6275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def flowControlOut(self, enable):
6295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """\
6305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        Manually control flow of outgoing data - when hardware or software flow
6315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        control is enabled.
6325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        WARNING: this function is not portable to different platforms!
6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """
6345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if not self._isOpen: raise portNotOpenError
6355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if enable:
6365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            termios.tcflow(self.fd, TERMIOS.TCOON)
6375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        else:
6385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            termios.tcflow(self.fd, TERMIOS.TCOOFF)
6395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# assemble Serial class with the platform specifc implementation and the base
6425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# for file-like behavior. for Python 2.6 and newer, that provide the new I/O
6435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# library, derrive from io.RawIOBase
6445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)try:
6455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    import io
6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)except ImportError:
6475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    # classic version with our own file-like emulation
6485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    class Serial(PosixSerial, FileLike):
6495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        pass
6505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)else:
6515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    # io library present
6525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    class Serial(PosixSerial, io.RawIOBase):
6535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        pass
6545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class PosixPollSerial(Serial):
6565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    """poll based read implementation. not all systems support poll properly.
6575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    however this one has better handling of errors, such as a device
6585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    disconnecting while it's in use (e.g. USB-serial unplugged)"""
6595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def read(self, size=1):
6615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """Read size bytes from the serial port. If a timeout is set it may
6625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           return less characters as requested. With no timeout it will block
6635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           until the requested number of bytes is read."""
6645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if self.fd is None: raise portNotOpenError
6655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        read = bytearray()
6665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        poll = select.poll()
6675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        poll.register(self.fd, select.POLLIN|select.POLLERR|select.POLLHUP|select.POLLNVAL)
6685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if size > 0:
6695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            while len(read) < size:
6705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                # print "\tread(): size",size, "have", len(read)    #debug
6715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                # wait until device becomes ready to read (or something fails)
6725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                for fd, event in poll.poll(self._timeout*1000):
6735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    if event & (select.POLLERR|select.POLLHUP|select.POLLNVAL):
6745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        raise SerialException('device reports error (poll)')
6755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    #  we don't care if it is select.POLLIN or timeout, that's
6765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    #  handled below
6775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                buf = os.read(self.fd, size - len(read))
6785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                read.extend(buf)
6795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                if ((self._timeout is not None and self._timeout >= 0) or
6805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    (self._interCharTimeout is not None and self._interCharTimeout > 0)) and not buf:
6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    break   # early abort on timeout
6825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return bytes(read)
6835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)if __name__ == '__main__':
6865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    s = Serial(0,
6875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 baudrate=19200,        # baud rate
6885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 bytesize=EIGHTBITS,    # number of data bits
6895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 parity=PARITY_EVEN,    # enable parity checking
6905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 stopbits=STOPBITS_ONE, # number of stop bits
6915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 timeout=3,             # set a timeout value, None for waiting forever
6925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 xonxoff=0,             # enable software flow control
6935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 rtscts=0,              # enable RTS/CTS flow control
6945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               )
6955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    s.setRTS(1)
6965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    s.setDTR(1)
6975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    s.flushInput()
6985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    s.flushOutput()
6995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    s.write('hello')
7005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    sys.stdout.write('%r\n' % s.read(5))
7015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    sys.stdout.write('%s\n' % s.inWaiting())
7025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    del s
7035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
704