diff options
Diffstat (limited to 'pyserial/serial/serialwin32.py')
-rw-r--r-- | pyserial/serial/serialwin32.py | 201 |
1 files changed, 103 insertions, 98 deletions
diff --git a/pyserial/serial/serialwin32.py b/pyserial/serial/serialwin32.py index e428bb5..0f33d00 100644 --- a/pyserial/serial/serialwin32.py +++ b/pyserial/serial/serialwin32.py @@ -1,23 +1,17 @@ #! python +#Python Serial Port Extension for Win32, Linux, BSD, Jython #serial driver for win32 #see __init__.py # -#(C) 2001-2002 Chris Liechti <cliechti@gmx.net> +#(C) 2001-2003 Chris Liechti <cliechti@gmx.net> # 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 +from serialutil import * -VERSION = string.split("$Revision: 1.24 $")[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') +VERSION = "$Revision: 1.25 $".split()[1] #extract CVS version #from winbase.h. these should realy be in win32con MS_CTS_ON = 16 @@ -26,6 +20,7 @@ MS_RING_ON = 64 MS_RLSD_ON = 128 def device(portnum): + """Turn a port number into a device name""" #the "//./COMx" format is required for devices >= 9 #not all versions of windows seem to support this propperly #so that the first few ports are used with the DOS device name @@ -34,29 +29,16 @@ def device(portnum): else: return r'\\.\COM%d' % (portnum+1) -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 to wait 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: - self.portstr = device(port) +class Serial(SerialBase): + """Serial port implemenation for Win32. This implemenatation requires a + win32all installation.""" + def open(self): + """Open port with current settings. This may throw a SerialException + if the port cannot be opened.""" + if self._port is None: + raise SerialException("Port must be configured before it can be used.") + self.hComPort = None try: self.hComPort = win32file.CreateFile(self.portstr, win32con.GENERIC_READ | win32con.GENERIC_WRITE, @@ -67,120 +49,128 @@ class Serial(serialutil.FileLike): None) except Exception, msg: self.hComPort = None #'cause __del__ is called anyway - raise serialutil.SerialException, "could not open port: %s" % msg + raise 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) + self._orgTimeouts = win32file.GetCommTimeouts(self.hComPort) + + self._reconfigurePort() + + # Clear buffers: + # Remove anything that was there + win32file.PurgeComm(self.hComPort, + win32file.PURGE_TXCLEAR | win32file.PURGE_TXABORT | + win32file.PURGE_RXCLEAR | win32file.PURGE_RXABORT) + self._overlappedRead = win32file.OVERLAPPED() + self._overlappedRead.hEvent = win32event.CreateEvent(None, 1, 0, None) + self._overlappedWrite = win32file.OVERLAPPED() + self._overlappedWrite.hEvent = win32event.CreateEvent(None, 0, 0, None) + self._isOpen = True + + def _reconfigurePort(self): + """Set commuication parameters on opened port.""" + if not self.hComPort: + raise SerialException("Can only operate on a valid port handle") + #Set Windows timeout values #timeouts is a tuple with the following items: #(ReadIntervalTimeout,ReadTotalTimeoutMultiplier, # ReadTotalTimeoutConstant,WriteTotalTimeoutMultiplier, # WriteTotalTimeoutConstant) - if timeout is None: + if self._timeout is None: timeouts = (0, 0, 0, 0, 0) - elif timeout == 0: + elif self._timeout == 0: timeouts = (win32con.MAXDWORD, 0, 0, 0, 0) else: - #timeouts = (0, 0, 0, 0, 0) #timeouts are done with WaitForSingleObject - timeouts = (0, 0, int(timeout*1000), 0, 0) + timeouts = (0, 0, int(self._timeout*1000), 0, 0) 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 + comDCB.BaudRate = self._baudrate - if bytesize == FIVEBITS: + if self._bytesize == FIVEBITS: comDCB.ByteSize = 5 - elif bytesize == SIXBITS: + elif self._bytesize == SIXBITS: comDCB.ByteSize = 6 - elif bytesize == SEVENBITS: + elif self._bytesize == SEVENBITS: comDCB.ByteSize = 7 - elif bytesize == EIGHTBITS: + elif self._bytesize == EIGHTBITS: comDCB.ByteSize = 8 + else: + raise ValueError("Unsupported number of data bits: %r" % self._bytesize) - if parity == PARITY_NONE: + if self._parity == PARITY_NONE: comDCB.Parity = win32file.NOPARITY comDCB.fParity = 0 # Dis/Enable Parity Check - elif parity == PARITY_EVEN: + elif self._parity == PARITY_EVEN: comDCB.Parity = win32file.EVENPARITY comDCB.fParity = 1 # Dis/Enable Parity Check - elif parity == PARITY_ODD: + elif self._parity == PARITY_ODD: comDCB.Parity = win32file.ODDPARITY comDCB.fParity = 1 # Dis/Enable Parity Check + else: + raise ValueError("Unsupported parity mode: %r" % self._parity) - if stopbits == STOPBITS_ONE: + if self._stopbits == STOPBITS_ONE: comDCB.StopBits = win32file.ONESTOPBIT - elif stopbits == STOPBITS_TWO: + elif self._stopbits == STOPBITS_TWO: comDCB.StopBits = win32file.TWOSTOPBITS + else: + raise ValueError("Unsupported number of stop bits: %r" % self._stopbits) + comDCB.fBinary = 1 # Enable Binary Transmission # Char. w/ Parity-Err are replaced with 0xff (if fErrorChar is set to TRUE) - if rtscts: + if self._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.fOutxCtsFlow = self._rtscts + comDCB.fOutxDsrFlow = self._rtscts + comDCB.fOutX = self._xonxoff + comDCB.fInX = self._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._overlappedRead = win32file.OVERLAPPED() - self._overlappedRead.hEvent = win32event.CreateEvent(None, 1, 0, None) - self._overlappedWrite = win32file.OVERLAPPED() - self._overlappedWrite.hEvent = win32event.CreateEvent(None, 0, 0, None) - - def __del__(self): - self.close() + #~ def __del__(self): + #~ self.close() def close(self): - """close port""" - if self.hComPort: - #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) - + """Close port""" + if self._isOpen: + if self.hComPort: + #Restore original timeout values: + win32file.SetCommTimeouts(self.hComPort, self._orgTimeouts) + #Close COM-Port: + win32file.CloseHandle(self.hComPort) + self.hComPort = None + self._isOpen = False + + def makeDeviceName(self, port): + return device(port) + + # - - - - - - - - - - - - - - - - - - - - - - - - + def inWaiting(self): - """returns the number of bytes waiting to be read""" + """Return the number of characters currently in the input buffer.""" flags, comstat = win32file.ClearCommError(self.hComPort) return comstat.cbInQue def read(self, size=1): - """read num bytes from serial port""" + """Read size bytes from the serial port. If a timeout is set it may + return less characters as requested. With no timeout it will block + until the requested number of bytes is read.""" if not self.hComPort: raise portNotOpenError if size > 0: win32event.ResetEvent(self._overlappedRead.hEvent) @@ -202,7 +192,7 @@ class Serial(serialutil.FileLike): return read def write(self, s): - """write string to serial port""" + """Output the given string over the serial port.""" if not self.hComPort: raise portNotOpenError #print repr(s), if s: @@ -212,14 +202,18 @@ class Serial(serialutil.FileLike): win32event.WaitForSingleObject(self._overlappedWrite.hEvent, win32event.INFINITE) def flushInput(self): + """Clear input buffer, discarding all that is in the buffer.""" if not self.hComPort: raise portNotOpenError win32file.PurgeComm(self.hComPort, win32file.PURGE_RXCLEAR | win32file.PURGE_RXABORT) def flushOutput(self): + """Clear output buffer, aborting the current output and + discarding all that is in the buffer.""" if not self.hComPort: raise portNotOpenError win32file.PurgeComm(self.hComPort, win32file.PURGE_TXCLEAR | win32file.PURGE_TXABORT) def sendBreak(self): + """Send break condition.""" if not self.hComPort: raise portNotOpenError import time win32file.SetCommBreak(self.hComPort) @@ -228,7 +222,7 @@ class Serial(serialutil.FileLike): win32file.ClearCommBreak(self.hComPort) def setRTS(self,level=1): - """set terminal status line""" + """Set terminal status line: Request To Send""" if not self.hComPort: raise portNotOpenError if level: win32file.EscapeCommFunction(self.hComPort, win32file.SETRTS) @@ -236,7 +230,7 @@ class Serial(serialutil.FileLike): win32file.EscapeCommFunction(self.hComPort, win32file.CLRRTS) def setDTR(self,level=1): - """set terminal status line""" + """Set terminal status line: Data Terminal Ready""" if not self.hComPort: raise portNotOpenError if level: win32file.EscapeCommFunction(self.hComPort, win32file.SETDTR) @@ -244,27 +238,38 @@ class Serial(serialutil.FileLike): win32file.EscapeCommFunction(self.hComPort, win32file.CLRDTR) def getCTS(self): - """read terminal status line""" + """Read terminal status line: Clear To Send""" if not self.hComPort: raise portNotOpenError return MS_CTS_ON & win32file.GetCommModemStatus(self.hComPort) != 0 def getDSR(self): - """read terminal status line""" + """Read terminal status line: Data Set Ready""" if not self.hComPort: raise portNotOpenError return MS_DSR_ON & win32file.GetCommModemStatus(self.hComPort) != 0 def getRI(self): - """read terminal status line""" + """Read terminal status line: Ring Indicator""" if not self.hComPort: raise portNotOpenError return MS_RING_ON & win32file.GetCommModemStatus(self.hComPort) != 0 def getCD(self): - """read terminal status line""" + """Read terminal status line: Carrier Detect""" if not self.hComPort: raise portNotOpenError return MS_RLSD_ON & win32file.GetCommModemStatus(self.hComPort) != 0 #Nur Testfunktion!! if __name__ == '__main__': print __name__ + s = Serial() + print s + s = Serial(0) + print s + + s.baudrate = 19200 + s.databits = 7 + s.close() + s.port = 3 + s.open() + print s |