From d8717c264af4caa8d368d602038123260b97a3da Mon Sep 17 00:00:00 2001 From: adamdunkels Date: Tue, 13 Nov 2007 13:23:02 +0000 Subject: [PATCH] Serial library for Python needed for some of the Tmote Sky tools --- tools/sky/serial/Makefile.am | 10 + tools/sky/serial/__init__.py | 21 ++ tools/sky/serial/__init__.pyc | Bin 0 -> 535 bytes tools/sky/serial/serialjava.py | 197 ++++++++++++++++ tools/sky/serial/serialposix.py | 392 +++++++++++++++++++++++++++++++ tools/sky/serial/serialposix.pyc | Bin 0 -> 16103 bytes tools/sky/serial/serialutil.py | 65 +++++ tools/sky/serial/serialutil.pyc | Bin 0 -> 3216 bytes tools/sky/serial/serialwin32.py | 280 ++++++++++++++++++++++ 9 files changed, 965 insertions(+) create mode 100644 tools/sky/serial/Makefile.am create mode 100644 tools/sky/serial/__init__.py create mode 100644 tools/sky/serial/__init__.pyc create mode 100644 tools/sky/serial/serialjava.py create mode 100644 tools/sky/serial/serialposix.py create mode 100644 tools/sky/serial/serialposix.pyc create mode 100644 tools/sky/serial/serialutil.py create mode 100644 tools/sky/serial/serialutil.pyc create mode 100644 tools/sky/serial/serialwin32.py diff --git a/tools/sky/serial/Makefile.am b/tools/sky/serial/Makefile.am new file mode 100644 index 000000000..c3ccf3fb7 --- /dev/null +++ b/tools/sky/serial/Makefile.am @@ -0,0 +1,10 @@ +AUTOMAKE_OPTIONS = foreign + +tinyoslibdir=$(libdir)/tinyos +serialdir=$(tinyoslibdir)/serial + +serial_DATA = __init__.py \ + serialjava.py \ + serialposix.py \ + serialutil.py \ + serialwin32.py diff --git a/tools/sky/serial/__init__.py b/tools/sky/serial/__init__.py new file mode 100644 index 000000000..88af1da9e --- /dev/null +++ b/tools/sky/serial/__init__.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +#portable serial port access with python +#this is a wrapper module for different platform implementations +# +# (C)2001-2002 Chris Liechti +# this is distributed under a free software license, see license.txt + +import sys, os, string +VERSION = string.split("$Revision: 1.1 $")[1] #extract CVS version + +#chose an implementation, depending on os +if os.name == 'nt': #sys.platform == 'win32': + from serialwin32 import * +elif os.name == 'posix': + from serialposix import * +elif os.name == 'java': + from serialjava import * +else: + raise "Sorry no implementation for your platform available." + +#no "mac" implementation. someone want's to write it? i have no access to a mac. diff --git a/tools/sky/serial/__init__.pyc b/tools/sky/serial/__init__.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e81d9f74e94bff26b55a87c81180950338447f00 GIT binary patch literal 535 zcmdOW%gc3nf1Fz~0|NsC69WT7@p1+RhI$5udJcvZ28L_~hA0LwgOMSM5zJs>h+<-> z=VVA_V#s7>NMU4XW@JcVVvvktVW{U}NM&TmWMxQUX2@b<$me5VtmkD&VPVK-V+hIf zVPLH1gDGHzE8qt!U}p%)(`I0-7l0{XgDVgOE8t)V$>U;RtQTfTVP|LpJ0)0ygMop; zuULSAfk7oGwJftZGe6Ht!BEdoK_!zB^4oSy9Zwz`&4| zSe969!oa`~oL^K_sgReikeOSMlbV~FSCUwgnV+YSmS3b$nO|C@P>_>Yl9peTtB_ch zn3^ zOUz9z<_4)uEy_&HDbLI^HbUY<+{Xo%2f0!M +# this is distributed under a free software license, see license.txt + +import sys, os, string, javax.comm +import serialutil + +VERSION = string.split("$Revision: 1.1 $")[1] #extract CVS version + +PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE = (0,1,2,3,4) +STOPBITS_ONE, STOPBITS_TWO, STOPBITS_ONE_HALVE = (1, 2, 3) +FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS = (5,6,7,8) + + +portNotOpenError = ValueError('port not open') + +def device(portnumber): + enum = javax.comm.CommPortIdentifier.getPortIdentifiers() + ports = [] + while enum.hasMoreElements(): + el = enum.nextElement() + if el.getPortType() == javax.comm.CommPortIdentifier.PORT_SERIAL: + ports.append(el) + return ports[portnumber] + +class Serial(serialutil.FileLike): + def __init__(self, + port, #number of device, numbering starts at + #zero. if everything fails, the user + #can specify a device string, note + #that this isn't portable anymore + baudrate=9600, #baudrate + bytesize=EIGHTBITS, #number of databits + parity=PARITY_NONE, #enable parity checking + stopbits=STOPBITS_ONE, #number of stopbits + timeout=None, #set a timeout value, None for waiting forever + xonxoff=0, #enable software flow control + rtscts=0, #enable RTS/CTS flow control + ): + + if type(port) == type(''): #strings are taken directly + portId = javax.comm.CommPortIdentifier.getPortIdentifier(port) + else: + portId = device(port) #numbers are transformed to a comportid obj + self.portstr = portId.getName() + try: + self.sPort = portId.open("python serial module", 10) + except Exception, msg: + self.sPort = None + raise serialutil.SerialException, "could not open port: %s" % msg + self.instream = self.sPort.getInputStream() + self.outstream = self.sPort.getOutputStream() + self.sPort.enableReceiveTimeout(30) + if bytesize == FIVEBITS: + self.databits = javax.comm.SerialPort.DATABITS_5 + elif bytesize == SIXBITS: + self.databits = javax.comm.SerialPort.DATABITS_6 + elif bytesize == SEVENBITS: + self.databits = javax.comm.SerialPort.DATABITS_7 + elif bytesize == EIGHTBITS: + self.databits = javax.comm.SerialPort.DATABITS_8 + else: + raise ValueError, "unsupported bytesize" + + if stopbits == STOPBITS_ONE: + self.jstopbits = javax.comm.SerialPort.STOPBITS_1 + elif stopbits == STOPBITS_ONE_HALVE: + self.jstopbits = javax.comm.SerialPort.STOPBITS_1_5 + elif stopbits == STOPBITS_TWO: + self.jstopbits = javax.comm.SerialPort.STOPBITS_2 + else: + raise ValueError, "unsupported number of stopbits" + + if parity == PARITY_NONE: + self.jparity = javax.comm.SerialPort.PARITY_NONE + elif parity == PARITY_EVEN: + self.jparity = javax.comm.SerialPort.PARITY_EVEN + elif parity == PARITY_ODD: + self.jparity = javax.comm.SerialPort.PARITY_ODD + elif parity == PARITY_MARK: + self.jparity = javax.comm.SerialPort.PARITY_MARK + elif parity == PARITY_SPACE: + self.jparity = javax.comm.SerialPort.PARITY_SPACE + else: + raise ValueError, "unsupported parity type" + + jflowin = jflowout = 0 + if rtscts: + jflowin = jflowin | javax.comm.SerialPort.FLOWCONTROL_RTSCTS_IN + jflowout = jflowout | javax.comm.SerialPort.FLOWCONTROL_RTSCTS_OUT + if xonxoff: + jflowin = jflowin | javax.comm.SerialPort.FLOWCONTROL_XONXOFF_IN + jflowout = jflowout | javax.comm.SerialPort.FLOWCONTROL_XONXOFF_OUT + + self.sPort.setSerialPortParams(baudrate, self.databits, self.jstopbits, self.jparity) + self.sPort.setFlowControlMode(jflowin | jflowout) + + self.timeout = timeout + if timeout >= 0: + self.sPort.enableReceiveTimeout(timeout*1000) + else: + self.sPort.disableReceiveTimeout() + + def close(self): + if self.sPort: + self.instream.close() + self.outstream.close() + self.sPort.close() + self.sPort = None + + def setBaudrate(self, baudrate): + """change baudrate after port is open""" + if not self.sPort: raise portNotOpenError + self.sPort.setSerialPortParams(baudrate, self.databits, self.jstopbits, self.jparity) + + + def inWaiting(self): + if not self.sPort: raise portNotOpenError + return self.instream.available() + + def write(self, data): + if not self.sPort: raise portNotOpenError + self.outstream.write(data) + + def read(self, size=1): + if not self.sPort: raise portNotOpenError + read = '' + if size > 0: + while len(read) < size: + x = self.instream.read() + if x == -1: + if self.timeout >= 0: + break + else: + read = read + chr(x) + return read + + def flushInput(self): + if not self.sPort: raise portNotOpenError + self.instream.skip(self.instream.available()) + + def flushOutput(self): + if not self.sPort: raise portNotOpenError + self.outstream.flush() + + def sendBreak(self): + if not self.sPort: raise portNotOpenError + self.sPort.sendBreak() + + def getDSR(self): + if not self.sPort: raise portNotOpenError + self.sPort.isDSR() + + def getCD(self): + if not self.sPort: raise portNotOpenError + self.sPort.isCD() + + def getRI(self): + if not self.sPort: raise portNotOpenError + self.sPort.isRI() + + def getCTS(self): + if not self.sPort: raise portNotOpenError + self.sPort.isCTS() + + def setDTR(self,on=1): + if not self.sPort: raise portNotOpenError + self.sPort.setDTR(on) + + def setRTS(self,on=1): + if not self.sPort: raise portNotOpenError + self.sPort.setRTS(on) + +if __name__ == '__main__': + s = Serial(0, + baudrate=19200, #baudrate + bytesize=EIGHTBITS, #number of databits + parity=PARITY_EVEN, #enable parity checking + stopbits=STOPBITS_ONE, #number of stopbits + timeout=3, #set a timeout value, None for waiting forever + xonxoff=0, #enable software flow control + rtscts=0, #enable RTS/CTS flow control + ) + s.setRTS(1) + s.setDTR(1) + s.flushInput() + s.flushOutput() + s.write('hello') + print repr(s.read(5)) + print s.inWaiting() + del s + + + diff --git a/tools/sky/serial/serialposix.py b/tools/sky/serial/serialposix.py new file mode 100644 index 000000000..240a58741 --- /dev/null +++ b/tools/sky/serial/serialposix.py @@ -0,0 +1,392 @@ +#!/usr/bin/env python +#module for serial IO for POSIX compatible systems, like Linux +#see __init__.py +# +#(C) 2001-2002 Chris Liechti +# this is distributed under a free software license, see license.txt +# +#parts based on code from Grant B. Edwards : +# ftp://ftp.visi.com/users/grante/python/PosixSerial.py +# references: http://www.easysw.com/~mike/serial/serial.html + +import sys, os, fcntl, termios, struct, string, select +import serialutil + +VERSION = string.split("$Revision: 1.1 $")[1] #extract CVS version + +PARITY_NONE, PARITY_EVEN, PARITY_ODD = range(3) +STOPBITS_ONE, STOPBITS_TWO = (1, 2) +FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS = (5,6,7,8) + +#Do check the Python version as some constants have moved. +if (sys.hexversion < 0x020100f0): + import TERMIOS +else: + TERMIOS = termios + +if (sys.hexversion < 0x020200f0): + import FCNTL +else: + FCNTL = fcntl + +#try to detect the os so that a device can be selected... +plat = string.lower(sys.platform) + +if plat[:5] == 'linux': #Linux (confirmed) + def device(port): + return '/dev/ttyS%d' % port + +elif plat == 'cygwin': #cywin/win32 (confirmed) + def device(port): + return '/dev/com%d' % (port + 1) + +elif plat == 'openbsd3': #BSD (confirmed) + def device(port): + return '/dev/ttyp%d' % port + +elif plat[:3] == 'bsd' or \ + plat[:6] == 'netbsd' or \ + plat[:7] == 'freebsd' or \ + plat[:7] == 'openbsd' or \ + plat[:6] == 'darwin': #BSD (confirmed for freebsd4: cuaa%d) + def device(port): + return '/dev/cuaa%d' % port + +elif plat[:4] == 'irix': #IRIX (not tested) + def device(port): + return '/dev/ttyf%d' % port + +elif plat[:2] == 'hp': #HP-UX (not tested) + def device(port): + return '/dev/tty%dp0' % (port+1) + +elif plat[:5] == 'sunos': #Solaris/SunOS (confirmed) + def device(port): + return '/dev/tty%c' % (ord('a')+port) + +elif plat[:3] == 'dgux': #Digital UNIX (not tested) + def device(port): + return '/dev/tty0%d' % (port+1) + +else: + #platform detection has failed... + info = "sys.platform = %r\nos.name = %r\nserialposix.py version = %s" % (sys.platform, os.name, VERSION) + print """send this information to the author of this module: + +%s + +also add the device name of the serial port and where the +counting starts for the first serial port. +e.g. 'first serial port: /dev/ttyS0' +and with a bit luck you can get this module running... +""" + raise Exception, "this module does not run on this platform, sorry." + +#whats up with "aix", "beos", "sco", .... +#they should work, just need to know the device names. + + +# construct dictionaries for baud rate lookups +baudEnumToInt = {} +baudIntToEnum = {} +for rate in (0,50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600, + 19200,38400,57600,115200,230400,460800,500000,576000,921600, + 1000000,1152000,1500000,2000000,2500000,3000000,3500000,4000000 + ): + try: + i = eval('TERMIOS.B'+str(rate)) + baudEnumToInt[i]=rate + baudIntToEnum[rate] = i + except: + pass + + +#load some constants for later use. +#try to use values from TERMIOS, use defaults from linux otherwise +TIOCMGET = hasattr(TERMIOS, 'TIOCMGET') and TERMIOS.TIOCMGET or 0x5415 +TIOCMBIS = hasattr(TERMIOS, 'TIOCMBIS') and TERMIOS.TIOCMBIS or 0x5416 +TIOCMBIC = hasattr(TERMIOS, 'TIOCMBIC') and TERMIOS.TIOCMBIC or 0x5417 +TIOCMSET = hasattr(TERMIOS, 'TIOCMSET') and TERMIOS.TIOCMSET or 0x5418 + +#TIOCM_LE = hasattr(TERMIOS, 'TIOCM_LE') and TERMIOS.TIOCM_LE or 0x001 +TIOCM_DTR = hasattr(TERMIOS, 'TIOCM_DTR') and TERMIOS.TIOCM_DTR or 0x002 +TIOCM_RTS = hasattr(TERMIOS, 'TIOCM_RTS') and TERMIOS.TIOCM_RTS or 0x004 +#TIOCM_ST = hasattr(TERMIOS, 'TIOCM_ST') and TERMIOS.TIOCM_ST or 0x008 +#TIOCM_SR = hasattr(TERMIOS, 'TIOCM_SR') and TERMIOS.TIOCM_SR or 0x010 + +TIOCM_CTS = hasattr(TERMIOS, 'TIOCM_CTS') and TERMIOS.TIOCM_CTS or 0x020 +TIOCM_CAR = hasattr(TERMIOS, 'TIOCM_CAR') and TERMIOS.TIOCM_CAR or 0x040 +TIOCM_RNG = hasattr(TERMIOS, 'TIOCM_RNG') and TERMIOS.TIOCM_RNG or 0x080 +TIOCM_DSR = hasattr(TERMIOS, 'TIOCM_DSR') and TERMIOS.TIOCM_DSR or 0x100 +TIOCM_CD = hasattr(TERMIOS, 'TIOCM_CD') and TERMIOS.TIOCM_CD or TIOCM_CAR +TIOCM_RI = hasattr(TERMIOS, 'TIOCM_RI') and TERMIOS.TIOCM_RI or TIOCM_RNG +#TIOCM_OUT1 = hasattr(TERMIOS, 'TIOCM_OUT1') and TERMIOS.TIOCM_OUT1 or 0x2000 +#TIOCM_OUT2 = hasattr(TERMIOS, 'TIOCM_OUT2') and TERMIOS.TIOCM_OUT2 or 0x4000 +TIOCINQ = hasattr(TERMIOS, 'FIONREAD') and TERMIOS.FIONREAD or 0x541B + +TIOCM_zero_str = struct.pack('I', 0) +TIOCM_RTS_str = struct.pack('I', TIOCM_RTS) +TIOCM_DTR_str = struct.pack('I', TIOCM_DTR) + +portNotOpenError = ValueError('port not open') + +class Serial(serialutil.FileLike): + def __init__(self, + port, #number of device, numbering starts at + #zero. if everything fails, the user + #can specify a device string, note + #that this isn't portable anymore + baudrate=9600, #baudrate + bytesize=EIGHTBITS, #number of databits + parity=PARITY_NONE, #enable parity checking + stopbits=STOPBITS_ONE, #number of stopbits + timeout=None, #set a timeout value, None for waiting forever + xonxoff=0, #enable software flow control + rtscts=0, #enable RTS/CTS flow control + ): + """init comm port""" + self.fd = None + self.timeout = timeout + vmin = vtime = 0 #timeout is done via select + #open + if type(port) == type(''): #strings are taken directly + self.portstr = port + else: + self.portstr = device(port) #numbers are transformed to a os dependant string + try: + self.fd = os.open(self.portstr, os.O_RDWR|os.O_NOCTTY|os.O_NONBLOCK) + except Exception, msg: + self.fd = None + raise serialutil.SerialException, "could not open port: %s" % msg + fcntl.fcntl(self.fd, FCNTL.F_SETFL, 0) #set blocking + try: + self.__tcgetattr() #read current settings + except termios.error, msg: #if a port is nonexistent but has a /dev file, it'll fail here + raise serialutil.SerialException, "could not open port: %s" % msg + #set up raw mode / no echo / binary + self.cflag = self.cflag | (TERMIOS.CLOCAL|TERMIOS.CREAD) + self.lflag = self.lflag & ~(TERMIOS.ICANON|TERMIOS.ECHO|TERMIOS.ECHOE|TERMIOS.ECHOK|TERMIOS.ECHONL| + TERMIOS.ECHOCTL|TERMIOS.ECHOKE|TERMIOS.ISIG|TERMIOS.IEXTEN) #|TERMIOS.ECHOPRT + self.oflag = self.oflag & ~(TERMIOS.OPOST) + if hasattr(TERMIOS, 'IUCLC'): + self.iflag = self.iflag & ~(TERMIOS.INLCR|TERMIOS.IGNCR|TERMIOS.ICRNL|TERMIOS.IUCLC|TERMIOS.IGNBRK) + else: + self.iflag = self.iflag & ~(TERMIOS.INLCR|TERMIOS.IGNCR|TERMIOS.ICRNL|TERMIOS.IGNBRK) + #setup baudrate + try: + self.ispeed = self.ospeed = baudIntToEnum[baudrate] + except: + raise ValueError,'invalid baud rate: %s' % baudrate + #setup char len + self.cflag = self.cflag & ~TERMIOS.CSIZE + if bytesize == 8: + self.cflag = self.cflag | TERMIOS.CS8 + elif bytesize == 7: + self.cflag = self.cflag | TERMIOS.CS7 + elif bytesize == 6: + self.cflag = self.cflag | TERMIOS.CS6 + elif bytesize == 5: + self.cflag = self.cflag | TERMIOS.CS5 + else: + raise ValueError,'invalid char len: '+str(clen) + #setup stopbits + if stopbits == STOPBITS_ONE: + self.cflag = self.cflag & ~(TERMIOS.CSTOPB) + elif stopbits == STOPBITS_TWO: + self.cflag = self.cflag | (TERMIOS.CSTOPB) + else: + raise ValueError,'invalid stopit specification:'+str(stopbits) + #setup parity + self.iflag = self.iflag & ~(TERMIOS.INPCK|TERMIOS.ISTRIP) + if parity == PARITY_NONE: + self.cflag = self.cflag & ~(TERMIOS.PARENB|TERMIOS.PARODD) + elif parity == PARITY_EVEN: + self.cflag = self.cflag & ~(TERMIOS.PARODD) + self.cflag = self.cflag | (TERMIOS.PARENB) + elif parity == PARITY_ODD: + self.cflag = self.cflag | (TERMIOS.PARENB|TERMIOS.PARODD) + else: + raise ValueError,'invalid parity: '+str(par) + #setup flow control + #xonxoff + if hasattr(TERMIOS, 'IXANY'): + if xonxoff: + self.iflag = self.iflag | (TERMIOS.IXON|TERMIOS.IXOFF|TERMIOS.IXANY) + else: + self.iflag = self.iflag & ~(TERMIOS.IXON|TERMIOS.IXOFF|TERMIOS.IXANY) + else: + if xonxoff: + self.iflag = self.iflag | (TERMIOS.IXON|TERMIOS.IXOFF) + else: + self.iflag = self.iflag & ~(TERMIOS.IXON|TERMIOS.IXOFF) + #rtscts + if hasattr(TERMIOS, 'CRTSCTS'): + if rtscts: + self.cflag = self.cflag | (TERMIOS.CRTSCTS) + else: + self.cflag = self.cflag & ~(TERMIOS.CRTSCTS) + elif hasattr(TERMIOS, 'CNEW_RTSCTS'): #try it with alternate constant name + if rtscts: + self.cflag = self.cflag | (TERMIOS.CNEW_RTSCTS) + else: + self.cflag = self.cflag & ~(TERMIOS.CNEW_RTSCTS) + #XXX should there be a warning if setting up rtscts (and xonxoff etc) fails?? + + #buffer + #vmin "minimal number of characters to be read. = for non blocking" + if vmin<0 or vmin>255: + raise ValueError,'invalid vmin: '+str(vmin) + self.cc[TERMIOS.VMIN] = vmin + #vtime + if vtime<0 or vtime>255: + raise ValueError,'invalid vtime: '+str(vtime) + self.cc[TERMIOS.VTIME] = vtime + #activate settings + self.__tcsetattr() + + def __tcsetattr(self): + """internal function to set port attributes""" + termios.tcsetattr(self.fd, TERMIOS.TCSANOW, [self.iflag,self.oflag,self.cflag,self.lflag,self.ispeed,self.ospeed,self.cc]) + + def __tcgetattr(self): + """internal function to get port attributes""" + self.iflag,self.oflag,self.cflag,self.lflag,self.ispeed,self.ospeed,self.cc = termios.tcgetattr(self.fd) + + def close(self): + """close port""" + if self.fd: + os.close(self.fd) + self.fd = None + + def setBaudrate(self, baudrate): + """change baudrate after port is open""" + if not self.fd: raise portNotOpenError + self.__tcgetattr() #read current settings + #setup baudrate + try: + self.ispeed = self.ospeed = baudIntToEnum[baudrate] + except: + raise ValueError,'invalid baud rate: %s' % baudrate + self.__tcsetattr() + + def inWaiting(self): + """how many character are in the input queue""" + #~ s = fcntl.ioctl(self.fd, TERMIOS.FIONREAD, TIOCM_zero_str) + s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str) + return struct.unpack('I',s)[0] + + def write(self, data): + """write a string to the port""" + if not self.fd: raise portNotOpenError + t = len(data) + d = data + while t>0: + n = os.write(self.fd, d) + d = d[n:] + t = t - n + + def read(self, size=1): + """read a number of bytes from the port. + the default is one (unlike files)""" + if not self.fd: raise portNotOpenError + read = '' + inp = None + if size > 0: + while len(read) < size: + #print "\tread(): size",size, "have", len(read) #debug + ready,_,_ = select.select([self.fd],[],[], self.timeout) + if not ready: + break #timeout + buf = os.read(self.fd, size-len(read)) + read = read + buf + if self.timeout >= 0 and not buf: + break #early abort on timeout + return read + + def flushInput(self): + """clear input queue""" + if not self.fd: + raise portNotOpenError + termios.tcflush(self.fd, TERMIOS.TCIFLUSH) + + def flushOutput(self): + """flush output""" + if not self.fd: + raise portNotOpenError + termios.tcflush(self.fd, TERMIOS.TCOFLUSH) + + def sendBreak(self): + """send break signal""" + if not self.fd: + raise portNotOpenError + termios.tcsendbreak(self.fd, 0) + + def drainOutput(self): + """internal - not portable!""" + if not self.fd: raise portNotOpenError + termios.tcdrain(self.fd) + + def nonblocking(self): + """internal - not portable!""" + if not self.fd: + raise portNotOpenError + fcntl.fcntl(self.fd, FCNTL.F_SETFL, FCNTL.O_NONBLOCK) + + def getDSR(self): + """read terminal status line""" + if not self.fd: raise portNotOpenError + s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str) + return struct.unpack('I',s)[0] & TIOCM_DSR + + def getCD(self): + """read terminal status line""" + if not self.fd: raise portNotOpenError + s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str) + return struct.unpack('I',s)[0] & TIOCM_CD + + def getRI(self): + """read terminal status line""" + if not self.fd: raise portNotOpenError + s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str) + return struct.unpack('I',s)[0] & TIOCM_RI + + def getCTS(self): + """read terminal status line""" + if not self.fd: raise portNotOpenError + s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str) + return struct.unpack('I',s)[0] & TIOCM_CTS + + def setDTR(self,on=1): + """set terminal status line""" + if not self.fd: raise portNotOpenError + if on: + fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str) + else: + fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_DTR_str) + + def setRTS(self,on=1): + """set terminal status line""" + if not self.fd: raise portNotOpenError + if on: + fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_RTS_str) + else: + fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_RTS_str) + +if __name__ == '__main__': + s = Serial(0, + baudrate=19200, #baudrate + bytesize=EIGHTBITS, #number of databits + parity=PARITY_EVEN, #enable parity checking + stopbits=STOPBITS_ONE, #number of stopbits + timeout=3, #set a timeout value, None for waiting forever + xonxoff=0, #enable software flow control + rtscts=0, #enable RTS/CTS flow control + ) + s.setRTS(1) + s.setDTR(1) + s.flushInput() + s.flushOutput() + s.write('hello') + print repr(s.read(5)) + print s.inWaiting() + del s diff --git a/tools/sky/serial/serialposix.pyc b/tools/sky/serial/serialposix.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ba8d505b04c722a7ecd119987a4218afaa870754 GIT binary patch literal 16103 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 literal 0 HcmV?d00001 diff --git a/tools/sky/serial/serialutil.py b/tools/sky/serial/serialutil.py new file mode 100644 index 000000000..e3a4bdb3c --- /dev/null +++ b/tools/sky/serial/serialutil.py @@ -0,0 +1,65 @@ + +class SerialException(Exception): + pass + +class FileLike: + """An abstract file like class. + + This class implements readline and readlines based on read and + writelines based on write. + This class is used to provide the above functions for to Serial + port objects. + + Note that when the serial port was opened with _NO_ timeout that + readline blocks until it sees a newline (or the specified size is + reached) and that readlines would never return and therefore + refuses to work (it raises an exception in this case)! + """ + + def read(self, size): raise NotImplementedError + def write(self, s): raise NotImplementedError + + def readline(self, size=None, eol='\n'): + """read a line which is terminated with end-of-line (eol) character + ('\n' by default) or until timeout""" + line = '' + while 1: + c = self.read(1) + if c: + line += c #not very efficient but lines are usually not that long + if c == eol: + break + if size is not None and len(line) >= size: + break + else: + break + return line + + def readlines(self, sizehint=None, eol='\n'): + """read a list of lines, until timeout + sizehint is ignored""" + if self.timeout is None: + raise ValueError, "Serial port MUST have enabled timeout for this function!" + lines = [] + while 1: + line = self.readline(eol=eol) + if line: + lines.append(line) + if line[-1] != eol: #was the line received with a timeout? + break + else: + break + return lines + + def xreadlines(self, sizehint=None): + """just call readlines - here for compatibility""" + return self.readlines() + + def writelines(self, sequence): + for line in sequence: + self.write(line) + + def flush(self): + """flush of file like objects""" + pass + diff --git a/tools/sky/serial/serialutil.pyc b/tools/sky/serial/serialutil.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1ded9ffd89a12ffbcb6d62057bdd2ef3f31e6aea GIT binary patch literal 3216 zcmdOW%gc3nf1Fz~0|NsCGXn!du^9scLp=jSJrhF;14AkULmDGP3L`@c14Aq zLp>`)3KK&b149ZkT$G6+g@qwlgB7HopMilPIJGD3=Hw{d5O8H@$to6U`}p+N@-4Ne7pw8eF&mh zih+SaPd_O$Prn#!7nCY3$;{C!s4T|f2quPNkR_aq#UN|kGILUWGP6^`PGbf+tsLYu zR;bfb7#O0M80rNX>V=`ck78!17XkUag@GZ8g`r-IA(a&r1Su>GEldniYz*~kFcDU; z2s=Z)8CZmkp@oqlii4rviXnv^6l77H4E1&lDI8!n7bpxkLB4;*$iU#3r;wObTvC*n zT%wScnUkuJlbM~WkeriPT&%~XprD`tCPFeYiy?vvnYjfysky0nCB+Iwsfj5$nR%%S ziFqk-PO(B#VsUDULVg}t2qXtKqP!@xBo(9@NdZ_4Vhyql#R{b$6H4+G3X1Z}GE-6& zN-|Ov5|i@FQWerl^O8X^T&$3mU!+iyuKX{E)f#UPKD z=NDxwXk?Zs6eVVYgc9=d5jE<^$H9%j0`1g3|X8E`2q}#CF~$g&5R(?ELMn8MTpWo zRtCm;Wrl!4Q3l5FdKHkm;1p(tU=2{n7H2UqFo1$rAyEO8q7=$AGLthDGK&>TQj2mk z^Aby7DLgeVMK?c97pzDlH9tpFAvq%vR05QC6?xtXe#6v zLDM`mYZQaZ$4pRo`DuX4H*k6Y83|?-!%_&yLEunLE(R6$srfk&`OKNObZHNkPr$WX$>ki`LxrFt!f5@t}6Xkuaj$D%ev zIs-WNbr>p=80vLE=^;Oyfw5i}tQTB#*Dx_OGcbbEf*vUD@(mam>-9mYB9jBeZw93X z0}v~Pg+UUOQkWspZ-^BA#tZ?47NF=i0ci|QVPy!`U<2hzd*tXZE>Xx&11E!G9n^S( z$1o^pGcxl^Kq(|MJukl~HKo{s0alel%0}PN;1Gq3#IjU{)V#!`oYWL}!3ZvWLA3&` zKvo2&1z22V{{R2~zn=!Unt?|sI|Bm)EcJi{!Eq0&b;A;KN>jmQOfe`=g5s$dTxr5$ z4Q4Dj$$+InUQR41NX<(@OEsX#hItKB8{Bx}QxC`waCfL7l8-Q>05l1SGIB8rFp5Bu z54@BW2PGdfhI(^`dJAw8U<5U2f>Rh7f*~cT4g&*2R%vmGLULkG4pK#+tB{delnSoj zlJj#55=%0ZGIKIZDxqx_P{@I^7mC9mM#ANgLxFg&g5shA?pHGgaBwp-GBYNFN<(m_ z&;$9(ilN?`p+XT0uDPz*{u%#2(NoQ%ng3?RtN zP|OSRm>omCJwv?%C|^S(3DoRM%PB3+0Ocn{0}0y7@Pjx4R35=y3lRd9j^L68Pn!|s zU9j19h>+Ic2IXathjFw^i$S?4K0YNsIX)h2Cn&za*#_)Iun;(7fy@BOfjy0qR=_P? zL_CAJV9j8qV6(u^LihyCBIF&Ag|JpGE2Ndd&%?~b!^p!VBp@Wf&%(pv2Z>maYv65l hY)xly=7*UDN!nN%*r=*NAx@M#L9t~IZJf(60{|A#`SSn( literal 0 HcmV?d00001 diff --git a/tools/sky/serial/serialwin32.py b/tools/sky/serial/serialwin32.py new file mode 100644 index 000000000..1e2045b16 --- /dev/null +++ b/tools/sky/serial/serialwin32.py @@ -0,0 +1,280 @@ +#! python +#serial driver for win32 +#see __init__.py +# +#(C) 2001-2002 Chris Liechti +# this is distributed under a free software license, see license.txt + +import win32file # The base COM port and file IO functions. +import win32event # We use events and the WaitFor[Single|Multiple]Objects functions. +import win32con # constants. +import sys, string +import serialutil + +VERSION = string.split("$Revision: 1.1 $")[1] #extract CVS version + +PARITY_NONE, PARITY_EVEN, PARITY_ODD = range(3) +STOPBITS_ONE, STOPBITS_TWO = (1, 2) +FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS = (5,6,7,8) + +portNotOpenError = ValueError('port not open') + +#from winbase.h. these should realy be in win32con +MS_CTS_ON = 16 +MS_DSR_ON = 32 +MS_RING_ON = 64 +MS_RLSD_ON = 128 + +class Serial(serialutil.FileLike): + def __init__(self, + port, #number of device, numbering starts at + #zero. if everything fails, the user + #can specify a device string, note + #that this isn't portable anymore + baudrate=9600, #baudrate + bytesize=EIGHTBITS, #number of databits + parity=PARITY_NONE, #enable parity checking + stopbits=STOPBITS_ONE, #number of stopbits + timeout=None, #set a timeout value, None for waiting forever + xonxoff=0, #enable software flow control + rtscts=0, #enable RTS/CTS flow control + ): + """initialize comm port""" + + self.timeout = timeout + + if type(port) == type(''): #strings are taken directly + self.portstr = port + else: + # CSS 20040528 - open wasn't working for COM10 and greater, but by + # chance the '\\.\COM10' format seems to work, yay! But, only use + # if for COM10 and greater in case it introduces some other + # incompatibility. + if port < 9: + self.portstr = 'COM%d' % (port+1) #numbers are transformed to a string + else: + self.portstr = '\\\\.\\COM%d' % (port+1) #WIN NT format?? + + try: + self.hComPort = win32file.CreateFile(self.portstr, + win32con.GENERIC_READ | win32con.GENERIC_WRITE, + 0, # exclusive access + None, # no security + win32con.OPEN_EXISTING, + win32con.FILE_ATTRIBUTE_NORMAL | win32con.FILE_FLAG_OVERLAPPED, + None) + except Exception, msg: + self.hComPort = None #'cause __del__ is called anyway + raise serialutil.SerialException, "could not open port: %s" % msg + # Setup a 4k buffer + win32file.SetupComm(self.hComPort, 4096, 4096) + + #Save original timeout values: + self.orgTimeouts = win32file.GetCommTimeouts(self.hComPort) + + #Set Windows timeout values + #timeouts is a tuple with the following items: + #(ReadIntervalTimeout,ReadTotalTimeoutMultiplier, + # ReadTotalTimeoutConstant,WriteTotalTimeoutMultiplier, + # WriteTotalTimeoutConstant) + if timeout is None: + timeouts = (0, 0, 0, 0, 0) + elif timeout == 0: + timeouts = (win32con.MAXDWORD, 0, 0, 0, 0) + else: + #timeouts = (0, 0, 0, 0, 0) #timeouts are done with WaitForSingleObject + #timeouts = (win32con.MAXDWORD, 0, 0, 0, 1000) #doesn't works + #timeouts = (timeout*1000, 0, timeout*1000, 0, 0) + timeouts = (0, 0, timeout*1000, 0, timeout*1000) + win32file.SetCommTimeouts(self.hComPort, timeouts) + + #win32file.SetCommMask(self.hComPort, win32file.EV_RXCHAR | win32file.EV_TXEMPTY | + # win32file.EV_RXFLAG | win32file.EV_ERR) + win32file.SetCommMask(self.hComPort, + win32file.EV_RXCHAR | win32file.EV_RXFLAG | win32file.EV_ERR) + #win32file.SetCommMask(self.hComPort, win32file.EV_ERR) + + # Setup the connection info. + # Get state and modify it: + comDCB = win32file.GetCommState(self.hComPort) + comDCB.BaudRate = baudrate + + if bytesize == FIVEBITS: + comDCB.ByteSize = 5 + elif bytesize == SIXBITS: + comDCB.ByteSize = 6 + elif bytesize == SEVENBITS: + comDCB.ByteSize = 7 + elif bytesize == EIGHTBITS: + comDCB.ByteSize = 8 + + if parity == PARITY_NONE: + comDCB.Parity = win32file.NOPARITY + comDCB.fParity = 0 # Dis/Enable Parity Check + elif parity == PARITY_EVEN: + comDCB.Parity = win32file.EVENPARITY + comDCB.fParity = 1 # Dis/Enable Parity Check + elif parity == PARITY_ODD: + comDCB.Parity = win32file.ODDPARITY + comDCB.fParity = 1 # Dis/Enable Parity Check + + if stopbits == STOPBITS_ONE: + comDCB.StopBits = win32file.ONESTOPBIT + elif stopbits == STOPBITS_TWO: + comDCB.StopBits = win32file.TWOSTOPBITS + comDCB.fBinary = 1 # Enable Binary Transmission + # Char. w/ Parity-Err are replaced with 0xff (if fErrorChar is set to TRUE) + if rtscts: + comDCB.fRtsControl = win32file.RTS_CONTROL_HANDSHAKE + comDCB.fDtrControl = win32file.DTR_CONTROL_HANDSHAKE + else: + comDCB.fRtsControl = win32file.RTS_CONTROL_ENABLE + comDCB.fDtrControl = win32file.DTR_CONTROL_ENABLE + comDCB.fOutxCtsFlow = rtscts + comDCB.fOutxDsrFlow = rtscts + comDCB.fOutX = xonxoff + comDCB.fInX = xonxoff + comDCB.fNull = 0 + comDCB.fErrorChar = 0 + comDCB.fAbortOnError = 0 + + win32file.SetCommState(self.hComPort, comDCB) + + # Clear buffers: + # Remove anything that was there + win32file.PurgeComm(self.hComPort, + win32file.PURGE_TXCLEAR | win32file.PURGE_TXABORT | + win32file.PURGE_RXCLEAR | win32file.PURGE_RXABORT) + + #print win32file.ClearCommError(self.hComPort) #flags, comState = + + #self.overlapped = win32file.OVERLAPPED() + #self.overlapped.hEvent = win32event.CreateEvent(None, 0, 0, None) + + def __del__(self): + self.close() + + def close(self): + """close port""" + if self.hComPort: + #Wait until data is transmitted, but not too long... (Timeout-Time) + #while 1: + # flags, comState = win32file.ClearCommError(hComPort) + # if comState.cbOutQue <= 0 or calcTimeout(startTime) > timeout: + # break + + self.setRTS(0) + self.setDTR(0) + #Clear buffers: + win32file.PurgeComm(self.hComPort, + win32file.PURGE_TXCLEAR | win32file.PURGE_TXABORT | + win32file.PURGE_RXCLEAR | win32file.PURGE_RXABORT) + #Restore original timeout values: + win32file.SetCommTimeouts(self.hComPort, self.orgTimeouts) + #Close COM-Port: + win32file.CloseHandle(self.hComPort) + self.hComPort = None + + def setBaudrate(self, baudrate): + """change baudrate after port is open""" + if not self.hComPort: raise portNotOpenError + # Setup the connection info. + # Get state and modify it: + comDCB = win32file.GetCommState(self.hComPort) + comDCB.BaudRate = baudrate + win32file.SetCommState(self.hComPort, comDCB) + + def inWaiting(self): + """returns the number of bytes waiting to be read""" + flags, comstat = win32file.ClearCommError(self.hComPort) + return comstat.cbInQue + + def read(self, size=1): + "read num bytes from serial port" + if not self.hComPort: raise portNotOpenError + read = '' + if size > 0: + overlapped = win32file.OVERLAPPED() + overlapped.hEvent = win32event.CreateEvent(None, 1, 0, None) + if self.timeout == 0: + flags, comstat = win32file.ClearCommError(self.hComPort) + n = min(comstat.cbInQue, size) + if n > 0: + rc, buf = win32file.ReadFile(self.hComPort, win32file.AllocateReadBuffer(n), overlapped) + win32event.WaitForSingleObject(overlapped.hEvent, win32event.INFINITE) + read = str(buf) + else: + flags, comstat = win32file.ClearCommError(self.hComPort) + rc, buf = win32file.ReadFile(self.hComPort, win32file.AllocateReadBuffer(size), overlapped) + n = win32file.GetOverlappedResult(self.hComPort, overlapped, 1) + read = str(buf[:n]) + return read + + def write(self, s): + "write string to serial port" + if not self.hComPort: raise portNotOpenError + #print repr(s), + overlapped = win32file.OVERLAPPED() + overlapped.hEvent = win32event.CreateEvent(None, 1, 0, None) + err, n = win32file.WriteFile(self.hComPort, s, overlapped) + if err: #will be ERROR_IO_PENDING: + # Wait for the write to complete. + win32event.WaitForSingleObject(overlapped.hEvent, win32event.INFINITE) + + def flushInput(self): + if not self.hComPort: raise portNotOpenError + win32file.PurgeComm(self.hComPort, win32file.PURGE_RXCLEAR | win32file.PURGE_RXABORT) + + def flushOutput(self): + if not self.hComPort: raise portNotOpenError + win32file.PurgeComm(self.hComPort, win32file.PURGE_TXCLEAR | win32file.PURGE_TXABORT) + + def sendBreak(self): + if not self.hComPort: raise portNotOpenError + import time + win32file.SetCommBreak(self.hComPort) + #TODO: how to set the correct duration?? + time.sleep(0.020) + win32file.ClearCommBreak(self.hComPort) + + def setRTS(self,level=1): + """set terminal status line""" + if not self.hComPort: raise portNotOpenError + if level: + win32file.EscapeCommFunction(self.hComPort, win32file.SETRTS) + else: + win32file.EscapeCommFunction(self.hComPort, win32file.CLRRTS) + + def setDTR(self,level=1): + """set terminal status line""" + if not self.hComPort: raise portNotOpenError + if level: + win32file.EscapeCommFunction(self.hComPort, win32file.SETDTR) + else: + win32file.EscapeCommFunction(self.hComPort, win32file.CLRDTR) + + def getCTS(self): + """read terminal status line""" + if not self.hComPort: raise portNotOpenError + return MS_CTS_ON & win32file.GetCommModemStatus(self.hComPort) != 0 + + def getDSR(self): + """read terminal status line""" + if not self.hComPort: raise portNotOpenError + return MS_DSR_ON & win32file.GetCommModemStatus(self.hComPort) != 0 + + def getRI(self): + """read terminal status line""" + if not self.hComPort: raise portNotOpenError + return MS_RING_ON & win32file.GetCommModemStatus(self.hComPort) != 0 + + def getCD(self): + """read terminal status line""" + if not self.hComPort: raise portNotOpenError + return MS_RLSD_ON & win32file.GetCommModemStatus(self.hComPort) != 0 + +#Nur Testfunktion!! +if __name__ == '__main__': + print __name__ + s = Serial(0) +