blob: 260096fabadb8d4a2d3659c759928298524f040a [file] [log] [blame]
cliechti89b4af12002-02-12 23:24:41 +00001#! python
cliechtic54b2c82008-06-21 01:59:08 +00002# Python Serial Port Extension for Win32, Linux, BSD, Jython
3# serial driver for win32
4# see __init__.py
cliechti89b4af12002-02-12 23:24:41 +00005#
cliechti1f89a0a2011-08-05 02:53:24 +00006# (C) 2001-2011 Chris Liechti <cliechti@gmx.net>
cliechti89b4af12002-02-12 23:24:41 +00007# this is distributed under a free software license, see license.txt
cliechti183d4ae2009-07-23 22:03:51 +00008#
9# Initial patch to use ctypes by Giovanni Bajo <rasky@develer.com>
cliechti89b4af12002-02-12 23:24:41 +000010
cliechti183d4ae2009-07-23 22:03:51 +000011import ctypes
cliechti39cfb7b2011-08-22 00:30:07 +000012from serial import win32
cliechti183d4ae2009-07-23 22:03:51 +000013
cliechti39cfb7b2011-08-22 00:30:07 +000014from serial.serialutil import *
cliechti89b4af12002-02-12 23:24:41 +000015
cliechti4a567a02009-07-27 22:09:31 +000016
cliechti4e838702003-08-28 22:18:02 +000017def device(portnum):
cliechtid6bf52c2003-10-01 02:28:12 +000018 """Turn a port number into a device name"""
cliechti4a567a02009-07-27 22:09:31 +000019 return 'COM%d' % (portnum+1) # numbers are transformed to a string
20
cliechti4e838702003-08-28 22:18:02 +000021
cliechtif81362e2009-07-25 03:44:33 +000022class Win32Serial(SerialBase):
cliechti1e2a6df2009-07-24 02:00:50 +000023 """Serial port implementation for Win32 based on ctypes."""
cliechti89b4af12002-02-12 23:24:41 +000024
cliechti4a567a02009-07-27 22:09:31 +000025 BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
26 9600, 19200, 38400, 57600, 115200)
cliechti80a0ed12003-10-03 23:53:42 +000027
cliechti5735a072009-10-26 23:57:48 +000028 def __init__(self, *args, **kwargs):
29 self.hComPort = None
cliechti1f89a0a2011-08-05 02:53:24 +000030 self._rtsToggle = False
cliechti5735a072009-10-26 23:57:48 +000031 SerialBase.__init__(self, *args, **kwargs)
32
cliechtid6bf52c2003-10-01 02:28:12 +000033 def open(self):
34 """Open port with current settings. This may throw a SerialException
35 if the port cannot be opened."""
36 if self._port is None:
37 raise SerialException("Port must be configured before it can be used.")
cliechti8f69e702011-03-19 00:22:32 +000038 if self._isOpen:
39 raise SerialException("Port is already open.")
cliechti8b7cff02008-06-24 12:11:57 +000040 # the "\\.\COMx" format is required for devices other than COM1-COM8
41 # not all versions of windows seem to support this properly
42 # so that the first few ports are used with the DOS device name
43 port = self.portstr
cliechti4a567a02009-07-27 22:09:31 +000044 try:
45 if port.upper().startswith('COM') and int(port[3:]) > 8:
46 port = '\\\\.\\' + port
47 except ValueError:
48 # for like COMnotanumber
49 pass
cliechtie37b6a82009-07-24 12:19:50 +000050 self.hComPort = win32.CreateFile(port,
51 win32.GENERIC_READ | win32.GENERIC_WRITE,
52 0, # exclusive access
53 None, # no security
54 win32.OPEN_EXISTING,
55 win32.FILE_ATTRIBUTE_NORMAL | win32.FILE_FLAG_OVERLAPPED,
56 0)
57 if self.hComPort == win32.INVALID_HANDLE_VALUE:
cliechti4a567a02009-07-27 22:09:31 +000058 self.hComPort = None # 'cause __del__ is called anyway
cliechti1083be72011-12-28 20:45:30 +000059 raise SerialException("could not open port %r: %r" % (self.portstr, ctypes.WinError()))
cliechtie37b6a82009-07-24 12:19:50 +000060
cliechti89b4af12002-02-12 23:24:41 +000061 # Setup a 4k buffer
cliechti183d4ae2009-07-23 22:03:51 +000062 win32.SetupComm(self.hComPort, 4096, 4096)
cliechti89b4af12002-02-12 23:24:41 +000063
cliechtiedfba4e2009-02-07 00:29:47 +000064 # Save original timeout values:
cliechti183d4ae2009-07-23 22:03:51 +000065 self._orgTimeouts = win32.COMMTIMEOUTS()
66 win32.GetCommTimeouts(self.hComPort, ctypes.byref(self._orgTimeouts))
cliechti89b4af12002-02-12 23:24:41 +000067
cliechti183d4ae2009-07-23 22:03:51 +000068 self._rtsState = win32.RTS_CONTROL_ENABLE
69 self._dtrState = win32.DTR_CONTROL_ENABLE
cliechti7ffcfef2004-07-28 01:08:25 +000070
cliechtid6bf52c2003-10-01 02:28:12 +000071 self._reconfigurePort()
cliechtiedfba4e2009-02-07 00:29:47 +000072
cliechti89b4af12002-02-12 23:24:41 +000073 # Clear buffers:
74 # Remove anything that was there
cliechti183d4ae2009-07-23 22:03:51 +000075 win32.PurgeComm(self.hComPort,
76 win32.PURGE_TXCLEAR | win32.PURGE_TXABORT |
77 win32.PURGE_RXCLEAR | win32.PURGE_RXABORT)
cliechti89b4af12002-02-12 23:24:41 +000078
cliechti183d4ae2009-07-23 22:03:51 +000079 self._overlappedRead = win32.OVERLAPPED()
80 self._overlappedRead.hEvent = win32.CreateEvent(None, 1, 0, None)
81 self._overlappedWrite = win32.OVERLAPPED()
82 #~ self._overlappedWrite.hEvent = win32.CreateEvent(None, 1, 0, None)
83 self._overlappedWrite.hEvent = win32.CreateEvent(None, 0, 0, None)
cliechtid6bf52c2003-10-01 02:28:12 +000084 self._isOpen = True
cliechti89b4af12002-02-12 23:24:41 +000085
cliechtid6bf52c2003-10-01 02:28:12 +000086 def _reconfigurePort(self):
cliechticc8d9d22008-07-06 22:42:44 +000087 """Set communication parameters on opened port."""
cliechtid6bf52c2003-10-01 02:28:12 +000088 if not self.hComPort:
89 raise SerialException("Can only operate on a valid port handle")
cliechtiedfba4e2009-02-07 00:29:47 +000090
91 # Set Windows timeout values
92 # timeouts is a tuple with the following items:
93 # (ReadIntervalTimeout,ReadTotalTimeoutMultiplier,
94 # ReadTotalTimeoutConstant,WriteTotalTimeoutMultiplier,
95 # WriteTotalTimeoutConstant)
cliechtid6bf52c2003-10-01 02:28:12 +000096 if self._timeout is None:
97 timeouts = (0, 0, 0, 0, 0)
98 elif self._timeout == 0:
cliechti183d4ae2009-07-23 22:03:51 +000099 timeouts = (win32.MAXDWORD, 0, 0, 0, 0)
cliechtid6bf52c2003-10-01 02:28:12 +0000100 else:
101 timeouts = (0, 0, int(self._timeout*1000), 0, 0)
cliechti679bfa62008-06-20 23:58:15 +0000102 if self._timeout != 0 and self._interCharTimeout is not None:
103 timeouts = (int(self._interCharTimeout * 1000),) + timeouts[1:]
cliechtiedfba4e2009-02-07 00:29:47 +0000104
cliechti62611612004-04-20 01:55:43 +0000105 if self._writeTimeout is None:
106 pass
107 elif self._writeTimeout == 0:
cliechti183d4ae2009-07-23 22:03:51 +0000108 timeouts = timeouts[:-2] + (0, win32.MAXDWORD)
cliechti62611612004-04-20 01:55:43 +0000109 else:
110 timeouts = timeouts[:-2] + (0, int(self._writeTimeout*1000))
cliechti183d4ae2009-07-23 22:03:51 +0000111 win32.SetCommTimeouts(self.hComPort, ctypes.byref(win32.COMMTIMEOUTS(*timeouts)))
cliechti89b4af12002-02-12 23:24:41 +0000112
cliechti183d4ae2009-07-23 22:03:51 +0000113 win32.SetCommMask(self.hComPort, win32.EV_ERR)
cliechti89b4af12002-02-12 23:24:41 +0000114
cliechti95c62212002-03-04 22:17:53 +0000115 # Setup the connection info.
116 # Get state and modify it:
cliechti183d4ae2009-07-23 22:03:51 +0000117 comDCB = win32.DCB()
118 win32.GetCommState(self.hComPort, ctypes.byref(comDCB))
cliechtid6bf52c2003-10-01 02:28:12 +0000119 comDCB.BaudRate = self._baudrate
120
121 if self._bytesize == FIVEBITS:
122 comDCB.ByteSize = 5
123 elif self._bytesize == SIXBITS:
124 comDCB.ByteSize = 6
125 elif self._bytesize == SEVENBITS:
126 comDCB.ByteSize = 7
127 elif self._bytesize == EIGHTBITS:
128 comDCB.ByteSize = 8
129 else:
130 raise ValueError("Unsupported number of data bits: %r" % self._bytesize)
131
132 if self._parity == PARITY_NONE:
cliechti183d4ae2009-07-23 22:03:51 +0000133 comDCB.Parity = win32.NOPARITY
134 comDCB.fParity = 0 # Disable Parity Check
cliechtid6bf52c2003-10-01 02:28:12 +0000135 elif self._parity == PARITY_EVEN:
cliechti183d4ae2009-07-23 22:03:51 +0000136 comDCB.Parity = win32.EVENPARITY
137 comDCB.fParity = 1 # Enable Parity Check
cliechtid6bf52c2003-10-01 02:28:12 +0000138 elif self._parity == PARITY_ODD:
cliechti183d4ae2009-07-23 22:03:51 +0000139 comDCB.Parity = win32.ODDPARITY
140 comDCB.fParity = 1 # Enable Parity Check
cliechtic54b2c82008-06-21 01:59:08 +0000141 elif self._parity == PARITY_MARK:
cliechti183d4ae2009-07-23 22:03:51 +0000142 comDCB.Parity = win32.MARKPARITY
143 comDCB.fParity = 1 # Enable Parity Check
cliechtic54b2c82008-06-21 01:59:08 +0000144 elif self._parity == PARITY_SPACE:
cliechti183d4ae2009-07-23 22:03:51 +0000145 comDCB.Parity = win32.SPACEPARITY
146 comDCB.fParity = 1 # Enable Parity Check
cliechtid6bf52c2003-10-01 02:28:12 +0000147 else:
148 raise ValueError("Unsupported parity mode: %r" % self._parity)
149
150 if self._stopbits == STOPBITS_ONE:
cliechti183d4ae2009-07-23 22:03:51 +0000151 comDCB.StopBits = win32.ONESTOPBIT
cliechti58b481c2009-02-16 20:42:32 +0000152 elif self._stopbits == STOPBITS_ONE_POINT_FIVE:
cliechti183d4ae2009-07-23 22:03:51 +0000153 comDCB.StopBits = win32.ONE5STOPBITS
cliechtid6bf52c2003-10-01 02:28:12 +0000154 elif self._stopbits == STOPBITS_TWO:
cliechti183d4ae2009-07-23 22:03:51 +0000155 comDCB.StopBits = win32.TWOSTOPBITS
cliechtid6bf52c2003-10-01 02:28:12 +0000156 else:
157 raise ValueError("Unsupported number of stop bits: %r" % self._stopbits)
cliechtiedfba4e2009-02-07 00:29:47 +0000158
cliechtid6bf52c2003-10-01 02:28:12 +0000159 comDCB.fBinary = 1 # Enable Binary Transmission
160 # Char. w/ Parity-Err are replaced with 0xff (if fErrorChar is set to TRUE)
161 if self._rtscts:
cliechti183d4ae2009-07-23 22:03:51 +0000162 comDCB.fRtsControl = win32.RTS_CONTROL_HANDSHAKE
cliechti1f89a0a2011-08-05 02:53:24 +0000163 elif self._rtsToggle:
164 comDCB.fRtsControl = win32.RTS_CONTROL_TOGGLE
cliechtid6bf52c2003-10-01 02:28:12 +0000165 else:
cliechti7ffcfef2004-07-28 01:08:25 +0000166 comDCB.fRtsControl = self._rtsState
cliechtif46e0a82005-05-19 15:24:57 +0000167 if self._dsrdtr:
cliechti183d4ae2009-07-23 22:03:51 +0000168 comDCB.fDtrControl = win32.DTR_CONTROL_HANDSHAKE
cliechtif46e0a82005-05-19 15:24:57 +0000169 else:
cliechti7ffcfef2004-07-28 01:08:25 +0000170 comDCB.fDtrControl = self._dtrState
cliechti1f89a0a2011-08-05 02:53:24 +0000171
172 if self._rtsToggle:
173 comDCB.fOutxCtsFlow = 0
174 else:
175 comDCB.fOutxCtsFlow = self._rtscts
cliechtif46e0a82005-05-19 15:24:57 +0000176 comDCB.fOutxDsrFlow = self._dsrdtr
cliechtid6bf52c2003-10-01 02:28:12 +0000177 comDCB.fOutX = self._xonxoff
178 comDCB.fInX = self._xonxoff
179 comDCB.fNull = 0
180 comDCB.fErrorChar = 0
181 comDCB.fAbortOnError = 0
cliechti62611612004-04-20 01:55:43 +0000182 comDCB.XonChar = XON
183 comDCB.XoffChar = XOFF
cliechtid6bf52c2003-10-01 02:28:12 +0000184
cliechti183d4ae2009-07-23 22:03:51 +0000185 if not win32.SetCommState(self.hComPort, ctypes.byref(comDCB)):
cliechti1083be72011-12-28 20:45:30 +0000186 raise ValueError("Cannot configure port, some setting was wrong. Original message: %r" % ctypes.WinError())
cliechti95c62212002-03-04 22:17:53 +0000187
cliechtid6bf52c2003-10-01 02:28:12 +0000188 #~ def __del__(self):
189 #~ self.close()
190
191 def close(self):
192 """Close port"""
193 if self._isOpen:
194 if self.hComPort:
cliechti183d4ae2009-07-23 22:03:51 +0000195 # Restore original timeout values:
196 win32.SetCommTimeouts(self.hComPort, self._orgTimeouts)
cliechtib6132082008-06-19 00:29:52 +0000197 # Close COM-Port:
cliechti183d4ae2009-07-23 22:03:51 +0000198 win32.CloseHandle(self.hComPort)
199 win32.CloseHandle(self._overlappedRead.hEvent)
200 win32.CloseHandle(self._overlappedWrite.hEvent)
cliechtid6bf52c2003-10-01 02:28:12 +0000201 self.hComPort = None
202 self._isOpen = False
203
204 def makeDeviceName(self, port):
cliechti8b7cff02008-06-24 12:11:57 +0000205 return device(port)
cliechtid6bf52c2003-10-01 02:28:12 +0000206
207 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechtiedfba4e2009-02-07 00:29:47 +0000208
cliechti89b4af12002-02-12 23:24:41 +0000209 def inWaiting(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000210 """Return the number of characters currently in the input buffer."""
cliechti183d4ae2009-07-23 22:03:51 +0000211 flags = win32.DWORD()
212 comstat = win32.COMSTAT()
213 if not win32.ClearCommError(self.hComPort, ctypes.byref(flags), ctypes.byref(comstat)):
214 raise SerialException('call to ClearCommError failed')
cliechti89b4af12002-02-12 23:24:41 +0000215 return comstat.cbInQue
216
cliechti4a567a02009-07-27 22:09:31 +0000217 def read(self, size=1):
cliechtid6bf52c2003-10-01 02:28:12 +0000218 """Read size bytes from the serial port. If a timeout is set it may
219 return less characters as requested. With no timeout it will block
220 until the requested number of bytes is read."""
cliechti89b4af12002-02-12 23:24:41 +0000221 if not self.hComPort: raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000222 if size > 0:
cliechti183d4ae2009-07-23 22:03:51 +0000223 win32.ResetEvent(self._overlappedRead.hEvent)
224 flags = win32.DWORD()
225 comstat = win32.COMSTAT()
226 if not win32.ClearCommError(self.hComPort, ctypes.byref(flags), ctypes.byref(comstat)):
227 raise SerialException('call to ClearCommError failed')
cliechti5c39e702002-06-04 14:56:34 +0000228 if self.timeout == 0:
cliechti17f177f2002-06-07 22:33:37 +0000229 n = min(comstat.cbInQue, size)
230 if n > 0:
cliechti183d4ae2009-07-23 22:03:51 +0000231 buf = ctypes.create_string_buffer(n)
232 rc = win32.DWORD()
cliechti14213e12010-05-20 22:31:18 +0000233 err = win32.ReadFile(self.hComPort, buf, n, ctypes.byref(rc), ctypes.byref(self._overlappedRead))
cliechti183d4ae2009-07-23 22:03:51 +0000234 if not err and win32.GetLastError() != win32.ERROR_IO_PENDING:
cliechti1083be72011-12-28 20:45:30 +0000235 raise SerialException("ReadFile failed (%r)" % ctypes.WinError())
cliechti183d4ae2009-07-23 22:03:51 +0000236 err = win32.WaitForSingleObject(self._overlappedRead.hEvent, win32.INFINITE)
237 read = buf.raw[:rc.value]
cliechtif622faf2003-07-12 23:41:43 +0000238 else:
cliechti4a567a02009-07-27 22:09:31 +0000239 read = bytes()
cliechti5c39e702002-06-04 14:56:34 +0000240 else:
cliechti183d4ae2009-07-23 22:03:51 +0000241 buf = ctypes.create_string_buffer(size)
242 rc = win32.DWORD()
243 err = win32.ReadFile(self.hComPort, buf, size, ctypes.byref(rc), ctypes.byref(self._overlappedRead))
244 if not err and win32.GetLastError() != win32.ERROR_IO_PENDING:
cliechti1083be72011-12-28 20:45:30 +0000245 raise SerialException("ReadFile failed (%r)" % ctypes.WinError())
cliechti183d4ae2009-07-23 22:03:51 +0000246 err = win32.GetOverlappedResult(self.hComPort, ctypes.byref(self._overlappedRead), ctypes.byref(rc), True)
247 read = buf.raw[:rc.value]
cliechtif622faf2003-07-12 23:41:43 +0000248 else:
cliechti4a567a02009-07-27 22:09:31 +0000249 read = bytes()
250 return bytes(read)
cliechti89b4af12002-02-12 23:24:41 +0000251
cliechti4a567a02009-07-27 22:09:31 +0000252 def write(self, data):
cliechtid6bf52c2003-10-01 02:28:12 +0000253 """Output the given string over the serial port."""
cliechti89b4af12002-02-12 23:24:41 +0000254 if not self.hComPort: raise portNotOpenError
cliechti23dc2a02009-07-30 17:25:09 +0000255 #~ if not isinstance(data, (bytes, bytearray)):
256 #~ raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data)))
257 # convert data (needed in case of memoryview instance: Py 3.1 io lib), ctypes doesn't like memoryview
258 data = bytes(data)
cliechtib2f5fc82006-10-20 00:09:07 +0000259 if data:
cliechti107db8d2004-01-15 01:20:23 +0000260 #~ win32event.ResetEvent(self._overlappedWrite.hEvent)
cliechti183d4ae2009-07-23 22:03:51 +0000261 n = win32.DWORD()
cliechtie37b6a82009-07-24 12:19:50 +0000262 err = win32.WriteFile(self.hComPort, data, len(data), ctypes.byref(n), self._overlappedWrite)
cliechti183d4ae2009-07-23 22:03:51 +0000263 if not err and win32.GetLastError() != win32.ERROR_IO_PENDING:
cliechti1083be72011-12-28 20:45:30 +0000264 raise SerialException("WriteFile failed (%r)" % ctypes.WinError())
cliechti31000fc2011-08-05 01:47:26 +0000265 if self._writeTimeout != 0: # if blocking (None) or w/ write timeout (>0)
266 # Wait for the write to complete.
267 #~ win32.WaitForSingleObject(self._overlappedWrite.hEvent, win32.INFINITE)
268 err = win32.GetOverlappedResult(self.hComPort, self._overlappedWrite, ctypes.byref(n), True)
269 if n.value != len(data):
270 raise writeTimeoutError
cliechti23dc2a02009-07-30 17:25:09 +0000271 return n.value
272 else:
273 return 0
cliechtiedfba4e2009-02-07 00:29:47 +0000274
cliechti89b4af12002-02-12 23:24:41 +0000275
276 def flushInput(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000277 """Clear input buffer, discarding all that is in the buffer."""
cliechti89b4af12002-02-12 23:24:41 +0000278 if not self.hComPort: raise portNotOpenError
cliechti183d4ae2009-07-23 22:03:51 +0000279 win32.PurgeComm(self.hComPort, win32.PURGE_RXCLEAR | win32.PURGE_RXABORT)
cliechti89b4af12002-02-12 23:24:41 +0000280
281 def flushOutput(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000282 """Clear output buffer, aborting the current output and
283 discarding all that is in the buffer."""
cliechti89b4af12002-02-12 23:24:41 +0000284 if not self.hComPort: raise portNotOpenError
cliechti183d4ae2009-07-23 22:03:51 +0000285 win32.PurgeComm(self.hComPort, win32.PURGE_TXCLEAR | win32.PURGE_TXABORT)
cliechti89b4af12002-02-12 23:24:41 +0000286
cliechtiaaa04602006-02-05 23:02:46 +0000287 def sendBreak(self, duration=0.25):
cliechti997b63c2008-06-21 00:09:31 +0000288 """Send break condition. Timed, returns to idle state after given duration."""
cliechti89b4af12002-02-12 23:24:41 +0000289 if not self.hComPort: raise portNotOpenError
cliechti1b327022002-02-13 22:26:06 +0000290 import time
cliechti183d4ae2009-07-23 22:03:51 +0000291 win32.SetCommBreak(self.hComPort)
cliechtiaaa04602006-02-05 23:02:46 +0000292 time.sleep(duration)
cliechti183d4ae2009-07-23 22:03:51 +0000293 win32.ClearCommBreak(self.hComPort)
cliechti89b4af12002-02-12 23:24:41 +0000294
cliechti997b63c2008-06-21 00:09:31 +0000295 def setBreak(self, level=1):
296 """Set break: Controls TXD. When active, to transmitting is possible."""
297 if not self.hComPort: raise portNotOpenError
298 if level:
cliechti183d4ae2009-07-23 22:03:51 +0000299 win32.SetCommBreak(self.hComPort)
cliechti997b63c2008-06-21 00:09:31 +0000300 else:
cliechti183d4ae2009-07-23 22:03:51 +0000301 win32.ClearCommBreak(self.hComPort)
cliechti997b63c2008-06-21 00:09:31 +0000302
cliechti93db61b2006-08-26 19:16:18 +0000303 def setRTS(self, level=1):
cliechtid6bf52c2003-10-01 02:28:12 +0000304 """Set terminal status line: Request To Send"""
cliechti89b4af12002-02-12 23:24:41 +0000305 if not self.hComPort: raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000306 if level:
cliechtie37b6a82009-07-24 12:19:50 +0000307 self._rtsState = win32.RTS_CONTROL_ENABLE
cliechti183d4ae2009-07-23 22:03:51 +0000308 win32.EscapeCommFunction(self.hComPort, win32.SETRTS)
cliechti89b4af12002-02-12 23:24:41 +0000309 else:
cliechtie37b6a82009-07-24 12:19:50 +0000310 self._rtsState = win32.RTS_CONTROL_DISABLE
cliechti183d4ae2009-07-23 22:03:51 +0000311 win32.EscapeCommFunction(self.hComPort, win32.CLRRTS)
cliechti89b4af12002-02-12 23:24:41 +0000312
cliechti93db61b2006-08-26 19:16:18 +0000313 def setDTR(self, level=1):
cliechtid6bf52c2003-10-01 02:28:12 +0000314 """Set terminal status line: Data Terminal Ready"""
cliechti89b4af12002-02-12 23:24:41 +0000315 if not self.hComPort: raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000316 if level:
cliechtie37b6a82009-07-24 12:19:50 +0000317 self._dtrState = win32.DTR_CONTROL_ENABLE
cliechti183d4ae2009-07-23 22:03:51 +0000318 win32.EscapeCommFunction(self.hComPort, win32.SETDTR)
cliechti89b4af12002-02-12 23:24:41 +0000319 else:
cliechtie37b6a82009-07-24 12:19:50 +0000320 self._dtrState = win32.DTR_CONTROL_DISABLE
cliechti183d4ae2009-07-23 22:03:51 +0000321 win32.EscapeCommFunction(self.hComPort, win32.CLRDTR)
322
323 def _GetCommModemStatus(self):
324 stat = win32.DWORD()
325 win32.GetCommModemStatus(self.hComPort, ctypes.byref(stat))
326 return stat.value
cliechti89b4af12002-02-12 23:24:41 +0000327
328 def getCTS(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000329 """Read terminal status line: Clear To Send"""
cliechti89b4af12002-02-12 23:24:41 +0000330 if not self.hComPort: raise portNotOpenError
cliechti183d4ae2009-07-23 22:03:51 +0000331 return win32.MS_CTS_ON & self._GetCommModemStatus() != 0
cliechti89b4af12002-02-12 23:24:41 +0000332
333 def getDSR(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000334 """Read terminal status line: Data Set Ready"""
cliechti89b4af12002-02-12 23:24:41 +0000335 if not self.hComPort: raise portNotOpenError
cliechti183d4ae2009-07-23 22:03:51 +0000336 return win32.MS_DSR_ON & self._GetCommModemStatus() != 0
cliechti89b4af12002-02-12 23:24:41 +0000337
cliechtid0b8b272002-02-14 01:33:08 +0000338 def getRI(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000339 """Read terminal status line: Ring Indicator"""
cliechtid0b8b272002-02-14 01:33:08 +0000340 if not self.hComPort: raise portNotOpenError
cliechti183d4ae2009-07-23 22:03:51 +0000341 return win32.MS_RING_ON & self._GetCommModemStatus() != 0
cliechti89b4af12002-02-12 23:24:41 +0000342
cliechtid0b8b272002-02-14 01:33:08 +0000343 def getCD(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000344 """Read terminal status line: Carrier Detect"""
cliechtid0b8b272002-02-14 01:33:08 +0000345 if not self.hComPort: raise portNotOpenError
cliechti183d4ae2009-07-23 22:03:51 +0000346 return win32.MS_RLSD_ON & self._GetCommModemStatus() != 0
cliechti89b4af12002-02-12 23:24:41 +0000347
cliechtia30a8a02003-10-05 12:28:13 +0000348 # - - platform specific - - - -
349
350 def setXON(self, level=True):
351 """Platform specific - set flow state."""
352 if not self.hComPort: raise portNotOpenError
353 if level:
cliechti183d4ae2009-07-23 22:03:51 +0000354 win32.EscapeCommFunction(self.hComPort, win32.SETXON)
cliechtia30a8a02003-10-05 12:28:13 +0000355 else:
cliechti183d4ae2009-07-23 22:03:51 +0000356 win32.EscapeCommFunction(self.hComPort, win32.SETXOFF)
cliechtia30a8a02003-10-05 12:28:13 +0000357
cliechtic8e83d82009-07-21 21:34:05 +0000358 def outWaiting(self):
359 """return how many characters the in the outgoing buffer"""
cliechti183d4ae2009-07-23 22:03:51 +0000360 flags = win32.DWORD()
361 comstat = win32.COMSTAT()
362 if not win32.ClearCommError(self.hComPort, ctypes.byref(flags), ctypes.byref(comstat)):
363 raise SerialException('call to ClearCommError failed')
cliechtic8e83d82009-07-21 21:34:05 +0000364 return comstat.cbOutQue
365
cliechti1f89a0a2011-08-05 02:53:24 +0000366 # functions useful for RS-485 adapters
367 def setRtsToggle(self, rtsToggle):
368 """Change RTS toggle control setting."""
369 self._rtsToggle = rtsToggle
370 if self._isOpen: self._reconfigurePort()
371
372 def getRtsToggle(self):
373 """Get the current RTS toggle control setting."""
374 return self._rtsToggle
375
376 rtsToggle = property(getRtsToggle, setRtsToggle, doc="RTS toggle control setting")
377
cliechtif81362e2009-07-25 03:44:33 +0000378
cliechti4a567a02009-07-27 22:09:31 +0000379# assemble Serial class with the platform specific implementation and the base
380# for file-like behavior. for Python 2.6 and newer, that provide the new I/O
381# library, derive from io.RawIOBase
382try:
383 import io
384except ImportError:
385 # classic version with our own file-like emulation
386 class Serial(Win32Serial, FileLike):
cliechtif81362e2009-07-25 03:44:33 +0000387 pass
cliechti4a567a02009-07-27 22:09:31 +0000388else:
389 # io library present
390 class Serial(Win32Serial, io.RawIOBase):
391 pass
cliechtif81362e2009-07-25 03:44:33 +0000392
cliechtic8e83d82009-07-21 21:34:05 +0000393
cliechtiedfba4e2009-02-07 00:29:47 +0000394# Nur Testfunktion!!
cliechti89b4af12002-02-12 23:24:41 +0000395if __name__ == '__main__':
cliechti93db61b2006-08-26 19:16:18 +0000396 s = Serial(0)
cliechti7aaead32009-07-23 14:02:41 +0000397 sys.stdout.write("%s\n" % s)
cliechtiedfba4e2009-02-07 00:29:47 +0000398
cliechtid6bf52c2003-10-01 02:28:12 +0000399 s = Serial()
cliechti7aaead32009-07-23 14:02:41 +0000400 sys.stdout.write("%s\n" % s)
cliechtiedfba4e2009-02-07 00:29:47 +0000401
cliechtid6bf52c2003-10-01 02:28:12 +0000402 s.baudrate = 19200
403 s.databits = 7
404 s.close()
cliechti93db61b2006-08-26 19:16:18 +0000405 s.port = 0
cliechtid6bf52c2003-10-01 02:28:12 +0000406 s.open()
cliechti7aaead32009-07-23 14:02:41 +0000407 sys.stdout.write("%s\n" % s)
cliechti89b4af12002-02-12 23:24:41 +0000408