blob: b0f92a2e1b9d915b0b30573a6ebfbeeb362ecc09 [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#
Chris Liechti68340d72015-08-03 14:15:48 +02006# (C) 2001-2015 Chris Liechti <cliechti@gmx.net>
Chris Liechtifbdd8a02015-08-09 02:37:45 +02007#
8# SPDX-License-Identifier: BSD-3-Clause
cliechti183d4ae2009-07-23 22:03:51 +00009#
10# Initial patch to use ctypes by Giovanni Bajo <rasky@develer.com>
cliechti89b4af12002-02-12 23:24:41 +000011
cliechti183d4ae2009-07-23 22:03:51 +000012import ctypes
Chris Liechtid240cf52015-08-05 02:57:03 +020013import time
cliechti39cfb7b2011-08-22 00:30:07 +000014from serial import win32
cliechti183d4ae2009-07-23 22:03:51 +000015
cliechti39cfb7b2011-08-22 00:30:07 +000016from serial.serialutil import *
cliechti89b4af12002-02-12 23:24:41 +000017
cliechti4a567a02009-07-27 22:09:31 +000018
Chris Liechtief6b7b42015-08-06 22:19:26 +020019class Serial(SerialBase):
cliechti1e2a6df2009-07-24 02:00:50 +000020 """Serial port implementation for Win32 based on ctypes."""
cliechti89b4af12002-02-12 23:24:41 +000021
cliechti4a567a02009-07-27 22:09:31 +000022 BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
23 9600, 19200, 38400, 57600, 115200)
cliechti80a0ed12003-10-03 23:53:42 +000024
cliechti5735a072009-10-26 23:57:48 +000025 def __init__(self, *args, **kwargs):
Chris Liechti76f83492015-08-10 01:22:01 +020026 super(SerialBase, self).__init__()
Chris Liechti3ad62fb2015-08-29 21:53:32 +020027 self._port_handle = None
28 self._overlapped_read = None
29 self._overlapped_write = None
cliechti5735a072009-10-26 23:57:48 +000030 SerialBase.__init__(self, *args, **kwargs)
31
cliechtid6bf52c2003-10-01 02:28:12 +000032 def open(self):
cliechti7d448562014-08-03 21:57:45 +000033 """\
34 Open port with current settings. This may throw a SerialException
35 if the port cannot be opened.
36 """
cliechtid6bf52c2003-10-01 02:28:12 +000037 if self._port is None:
38 raise SerialException("Port must be configured before it can be used.")
Chris Liechti3ad62fb2015-08-29 21:53:32 +020039 if self.is_open:
cliechti8f69e702011-03-19 00:22:32 +000040 raise SerialException("Port is already open.")
cliechti8b7cff02008-06-24 12:11:57 +000041 # the "\\.\COMx" format is required for devices other than COM1-COM8
42 # not all versions of windows seem to support this properly
43 # so that the first few ports are used with the DOS device name
Chris Liechtief1fe252015-08-27 23:25:21 +020044 port = self.name
cliechti4a567a02009-07-27 22:09:31 +000045 try:
46 if port.upper().startswith('COM') and int(port[3:]) > 8:
47 port = '\\\\.\\' + port
48 except ValueError:
49 # for like COMnotanumber
50 pass
Chris Liechti3ad62fb2015-08-29 21:53:32 +020051 self._port_handle = win32.CreateFile(port,
cliechtie37b6a82009-07-24 12:19:50 +000052 win32.GENERIC_READ | win32.GENERIC_WRITE,
53 0, # exclusive access
54 None, # no security
55 win32.OPEN_EXISTING,
56 win32.FILE_ATTRIBUTE_NORMAL | win32.FILE_FLAG_OVERLAPPED,
57 0)
Chris Liechti3ad62fb2015-08-29 21:53:32 +020058 if self._port_handle == win32.INVALID_HANDLE_VALUE:
59 self._port_handle = None # 'cause __del__ is called anyway
cliechti1083be72011-12-28 20:45:30 +000060 raise SerialException("could not open port %r: %r" % (self.portstr, ctypes.WinError()))
cliechtie37b6a82009-07-24 12:19:50 +000061
cliechti1ae5ab02013-10-11 01:08:02 +000062 try:
Chris Liechti3ad62fb2015-08-29 21:53:32 +020063 self._overlapped_read = win32.OVERLAPPED()
64 self._overlapped_read.hEvent = win32.CreateEvent(None, 1, 0, None)
65 self._overlapped_write = win32.OVERLAPPED()
66 #~ self._overlapped_write.hEvent = win32.CreateEvent(None, 1, 0, None)
67 self._overlapped_write.hEvent = win32.CreateEvent(None, 0, 0, None)
cliechti89b4af12002-02-12 23:24:41 +000068
cliechti1ae5ab02013-10-11 01:08:02 +000069 # Setup a 4k buffer
Chris Liechti3ad62fb2015-08-29 21:53:32 +020070 win32.SetupComm(self._port_handle, 4096, 4096)
cliechti89b4af12002-02-12 23:24:41 +000071
cliechti1ae5ab02013-10-11 01:08:02 +000072 # Save original timeout values:
73 self._orgTimeouts = win32.COMMTIMEOUTS()
Chris Liechti3ad62fb2015-08-29 21:53:32 +020074 win32.GetCommTimeouts(self._port_handle, ctypes.byref(self._orgTimeouts))
cliechtiedfba4e2009-02-07 00:29:47 +000075
Chris Liechti3ad62fb2015-08-29 21:53:32 +020076 self._reconfigure_port()
cliechti89b4af12002-02-12 23:24:41 +000077
cliechti1ae5ab02013-10-11 01:08:02 +000078 # Clear buffers:
79 # Remove anything that was there
Chris Liechti3ad62fb2015-08-29 21:53:32 +020080 win32.PurgeComm(self._port_handle,
cliechti1ae5ab02013-10-11 01:08:02 +000081 win32.PURGE_TXCLEAR | win32.PURGE_TXABORT |
82 win32.PURGE_RXCLEAR | win32.PURGE_RXABORT)
83 except:
84 try:
85 self._close()
86 except:
87 # ignore any exception when closing the port
88 # also to keep original exception that happened when setting up
89 pass
Chris Liechti3ad62fb2015-08-29 21:53:32 +020090 self._port_handle = None
cliechti1ae5ab02013-10-11 01:08:02 +000091 raise
92 else:
Chris Liechti3ad62fb2015-08-29 21:53:32 +020093 self.is_open = True
cliechti1ae5ab02013-10-11 01:08:02 +000094
cliechti89b4af12002-02-12 23:24:41 +000095
Chris Liechti3ad62fb2015-08-29 21:53:32 +020096 def _reconfigure_port(self):
cliechticc8d9d22008-07-06 22:42:44 +000097 """Set communication parameters on opened port."""
Chris Liechti3ad62fb2015-08-29 21:53:32 +020098 if not self._port_handle:
cliechtid6bf52c2003-10-01 02:28:12 +000099 raise SerialException("Can only operate on a valid port handle")
cliechtiedfba4e2009-02-07 00:29:47 +0000100
101 # Set Windows timeout values
102 # timeouts is a tuple with the following items:
103 # (ReadIntervalTimeout,ReadTotalTimeoutMultiplier,
104 # ReadTotalTimeoutConstant,WriteTotalTimeoutMultiplier,
105 # WriteTotalTimeoutConstant)
cliechtid6bf52c2003-10-01 02:28:12 +0000106 if self._timeout is None:
107 timeouts = (0, 0, 0, 0, 0)
108 elif self._timeout == 0:
cliechti183d4ae2009-07-23 22:03:51 +0000109 timeouts = (win32.MAXDWORD, 0, 0, 0, 0)
cliechtid6bf52c2003-10-01 02:28:12 +0000110 else:
111 timeouts = (0, 0, int(self._timeout*1000), 0, 0)
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200112 if self._timeout != 0 and self._inter_character_timeout is not None:
113 timeouts = (int(self._inter_character_timeout * 1000),) + timeouts[1:]
cliechtiedfba4e2009-02-07 00:29:47 +0000114
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200115 if self._write_timeout is None:
cliechti62611612004-04-20 01:55:43 +0000116 pass
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200117 elif self._write_timeout == 0:
cliechti183d4ae2009-07-23 22:03:51 +0000118 timeouts = timeouts[:-2] + (0, win32.MAXDWORD)
cliechti62611612004-04-20 01:55:43 +0000119 else:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200120 timeouts = timeouts[:-2] + (0, int(self._write_timeout*1000))
121 win32.SetCommTimeouts(self._port_handle, ctypes.byref(win32.COMMTIMEOUTS(*timeouts)))
cliechti89b4af12002-02-12 23:24:41 +0000122
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200123 win32.SetCommMask(self._port_handle, win32.EV_ERR)
cliechti89b4af12002-02-12 23:24:41 +0000124
cliechti95c62212002-03-04 22:17:53 +0000125 # Setup the connection info.
126 # Get state and modify it:
cliechti183d4ae2009-07-23 22:03:51 +0000127 comDCB = win32.DCB()
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200128 win32.GetCommState(self._port_handle, ctypes.byref(comDCB))
cliechtid6bf52c2003-10-01 02:28:12 +0000129 comDCB.BaudRate = self._baudrate
130
131 if self._bytesize == FIVEBITS:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200132 comDCB.ByteSize = 5
cliechtid6bf52c2003-10-01 02:28:12 +0000133 elif self._bytesize == SIXBITS:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200134 comDCB.ByteSize = 6
cliechtid6bf52c2003-10-01 02:28:12 +0000135 elif self._bytesize == SEVENBITS:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200136 comDCB.ByteSize = 7
cliechtid6bf52c2003-10-01 02:28:12 +0000137 elif self._bytesize == EIGHTBITS:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200138 comDCB.ByteSize = 8
cliechtid6bf52c2003-10-01 02:28:12 +0000139 else:
140 raise ValueError("Unsupported number of data bits: %r" % self._bytesize)
141
142 if self._parity == PARITY_NONE:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200143 comDCB.Parity = win32.NOPARITY
144 comDCB.fParity = 0 # Disable Parity Check
cliechtid6bf52c2003-10-01 02:28:12 +0000145 elif self._parity == PARITY_EVEN:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200146 comDCB.Parity = win32.EVENPARITY
147 comDCB.fParity = 1 # Enable Parity Check
cliechtid6bf52c2003-10-01 02:28:12 +0000148 elif self._parity == PARITY_ODD:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200149 comDCB.Parity = win32.ODDPARITY
150 comDCB.fParity = 1 # Enable Parity Check
cliechtic54b2c82008-06-21 01:59:08 +0000151 elif self._parity == PARITY_MARK:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200152 comDCB.Parity = win32.MARKPARITY
153 comDCB.fParity = 1 # Enable Parity Check
cliechtic54b2c82008-06-21 01:59:08 +0000154 elif self._parity == PARITY_SPACE:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200155 comDCB.Parity = win32.SPACEPARITY
156 comDCB.fParity = 1 # Enable Parity Check
cliechtid6bf52c2003-10-01 02:28:12 +0000157 else:
158 raise ValueError("Unsupported parity mode: %r" % self._parity)
159
160 if self._stopbits == STOPBITS_ONE:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200161 comDCB.StopBits win32.ONESTOPBIT
cliechti58b481c2009-02-16 20:42:32 +0000162 elif self._stopbits == STOPBITS_ONE_POINT_FIVE:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200163 comDCB.StopBits = win32.ONE5STOPBITS
cliechtid6bf52c2003-10-01 02:28:12 +0000164 elif self._stopbits == STOPBITS_TWO:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200165 comDCB.StopBits = win32.TWOSTOPBITS
cliechtid6bf52c2003-10-01 02:28:12 +0000166 else:
167 raise ValueError("Unsupported number of stop bits: %r" % self._stopbits)
cliechtiedfba4e2009-02-07 00:29:47 +0000168
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200169 comDCB.fBinary = 1 # Enable Binary Transmission
cliechtid6bf52c2003-10-01 02:28:12 +0000170 # Char. w/ Parity-Err are replaced with 0xff (if fErrorChar is set to TRUE)
Chris Liechti33f0ec52015-08-06 16:37:21 +0200171 if self._rs485_mode is None:
172 if self._rtscts:
173 comDCB.fRtsControl = win32.RTS_CONTROL_HANDSHAKE
174 else:
Chris Liechtief1fe252015-08-27 23:25:21 +0200175 comDCB.fRtsControl = win32.RTS_CONTROL_ENABLE if self._rts_state else win32.RTS_CONTROL_DISABLE
Chris Liechti33f0ec52015-08-06 16:37:21 +0200176 comDCB.fOutxCtsFlow = self._rtscts
cliechtid6bf52c2003-10-01 02:28:12 +0000177 else:
Chris Liechti33f0ec52015-08-06 16:37:21 +0200178 # checks for unsupported settings
179 # XXX verify if platform really does not have a setting for those
180 if not self._rs485_mode.rts_level_for_tx:
181 raise ValueError(
182 'Unsupported value for RS485Settings.rts_level_for_tx: %r' % (
183 self._rs485_mode.rts_level_for_tx,))
184 if self._rs485_mode.rts_level_for_rx:
185 raise ValueError(
186 'Unsupported value for RS485Settings.rts_level_for_rx: %r' % (
187 self._rs485_mode.rts_level_for_rx,))
188 if self._rs485_mode.delay_before_tx is not None:
189 raise ValueError(
190 'Unsupported value for RS485Settings.delay_before_tx: %r' % (
191 self._rs485_mode.delay_before_tx,))
192 if self._rs485_mode.delay_before_rx is not None:
193 raise ValueError(
194 'Unsupported value for RS485Settings.delay_before_rx: %r' % (
195 self._rs485_mode.delay_before_rx,))
196 if self._rs485_mode.loopback:
197 raise ValueError(
198 'Unsupported value for RS485Settings.loopback: %r' % (
199 self._rs485_mode.loopback,))
200 comDCB.fRtsControl = win32.RTS_CONTROL_TOGGLE
201 comDCB.fOutxCtsFlow = 0
202
cliechtif46e0a82005-05-19 15:24:57 +0000203 if self._dsrdtr:
cliechti183d4ae2009-07-23 22:03:51 +0000204 comDCB.fDtrControl = win32.DTR_CONTROL_HANDSHAKE
cliechtif46e0a82005-05-19 15:24:57 +0000205 else:
Chris Liechtief1fe252015-08-27 23:25:21 +0200206 comDCB.fDtrControl = win32.DTR_CONTROL_ENABLE if self._dtr_state else win32.DTR_CONTROL_DISABLE
cliechtif46e0a82005-05-19 15:24:57 +0000207 comDCB.fOutxDsrFlow = self._dsrdtr
cliechtid6bf52c2003-10-01 02:28:12 +0000208 comDCB.fOutX = self._xonxoff
209 comDCB.fInX = self._xonxoff
210 comDCB.fNull = 0
211 comDCB.fErrorChar = 0
212 comDCB.fAbortOnError = 0
cliechti62611612004-04-20 01:55:43 +0000213 comDCB.XonChar = XON
214 comDCB.XoffChar = XOFF
cliechtid6bf52c2003-10-01 02:28:12 +0000215
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200216 if not win32.SetCommState(self._port_handle, ctypes.byref(comDCB)):
cliechti1083be72011-12-28 20:45:30 +0000217 raise ValueError("Cannot configure port, some setting was wrong. Original message: %r" % ctypes.WinError())
cliechti95c62212002-03-04 22:17:53 +0000218
cliechtid6bf52c2003-10-01 02:28:12 +0000219 #~ def __del__(self):
220 #~ self.close()
221
cliechti1ae5ab02013-10-11 01:08:02 +0000222
223 def _close(self):
224 """internal close port helper"""
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200225 if self._port_handle:
cliechti1ae5ab02013-10-11 01:08:02 +0000226 # Restore original timeout values:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200227 win32.SetCommTimeouts(self._port_handle, self._orgTimeouts)
cliechti1ae5ab02013-10-11 01:08:02 +0000228 # Close COM-Port:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200229 win32.CloseHandle(self._port_handle)
230 if self._overlapped_read is not None:
231 win32.CloseHandle(self._overlapped_read.hEvent)
232 self._overlapped_read = None
233 if self._overlapped_write is not None:
234 win32.CloseHandle(self._overlapped_write.hEvent)
235 self._overlapped_write = None
236 self._port_handle = None
cliechti1ae5ab02013-10-11 01:08:02 +0000237
cliechtid6bf52c2003-10-01 02:28:12 +0000238 def close(self):
239 """Close port"""
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200240 if self.is_open:
cliechti1ae5ab02013-10-11 01:08:02 +0000241 self._close()
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200242 self.is_open = False
cliechtid6bf52c2003-10-01 02:28:12 +0000243
244 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechtiedfba4e2009-02-07 00:29:47 +0000245
Chris Liechtief1fe252015-08-27 23:25:21 +0200246 @property
247 def in_waiting(self):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200248 """Return the number of bytes currently in the input buffer."""
cliechti183d4ae2009-07-23 22:03:51 +0000249 flags = win32.DWORD()
250 comstat = win32.COMSTAT()
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200251 if not win32.ClearCommError(self._port_handle, ctypes.byref(flags), ctypes.byref(comstat)):
cliechti183d4ae2009-07-23 22:03:51 +0000252 raise SerialException('call to ClearCommError failed')
cliechti89b4af12002-02-12 23:24:41 +0000253 return comstat.cbInQue
254
cliechti4a567a02009-07-27 22:09:31 +0000255 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000256 """\
257 Read size bytes from the serial port. If a timeout is set it may
258 return less characters as requested. With no timeout it will block
259 until the requested number of bytes is read."""
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200260 if not self._port_handle: raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000261 if size > 0:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200262 win32.ResetEvent(self._overlapped_read.hEvent)
cliechti183d4ae2009-07-23 22:03:51 +0000263 flags = win32.DWORD()
264 comstat = win32.COMSTAT()
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200265 if not win32.ClearCommError(self._port_handle, ctypes.byref(flags), ctypes.byref(comstat)):
cliechti183d4ae2009-07-23 22:03:51 +0000266 raise SerialException('call to ClearCommError failed')
cliechti5c39e702002-06-04 14:56:34 +0000267 if self.timeout == 0:
cliechti17f177f2002-06-07 22:33:37 +0000268 n = min(comstat.cbInQue, size)
269 if n > 0:
cliechti183d4ae2009-07-23 22:03:51 +0000270 buf = ctypes.create_string_buffer(n)
271 rc = win32.DWORD()
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200272 err = win32.ReadFile(self._port_handle, buf, n, ctypes.byref(rc), ctypes.byref(self._overlapped_read))
cliechti183d4ae2009-07-23 22:03:51 +0000273 if not err and win32.GetLastError() != win32.ERROR_IO_PENDING:
cliechti1083be72011-12-28 20:45:30 +0000274 raise SerialException("ReadFile failed (%r)" % ctypes.WinError())
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200275 err = win32.WaitForSingleObject(self._overlapped_read.hEvent, win32.INFINITE)
cliechti183d4ae2009-07-23 22:03:51 +0000276 read = buf.raw[:rc.value]
cliechtif622faf2003-07-12 23:41:43 +0000277 else:
cliechti4a567a02009-07-27 22:09:31 +0000278 read = bytes()
cliechti5c39e702002-06-04 14:56:34 +0000279 else:
cliechti183d4ae2009-07-23 22:03:51 +0000280 buf = ctypes.create_string_buffer(size)
281 rc = win32.DWORD()
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200282 err = win32.ReadFile(self._port_handle, buf, size, ctypes.byref(rc), ctypes.byref(self._overlapped_read))
cliechti183d4ae2009-07-23 22:03:51 +0000283 if not err and win32.GetLastError() != win32.ERROR_IO_PENDING:
cliechti1083be72011-12-28 20:45:30 +0000284 raise SerialException("ReadFile failed (%r)" % ctypes.WinError())
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200285 err = win32.GetOverlappedResult(self._port_handle, ctypes.byref(self._overlapped_read), ctypes.byref(rc), True)
cliechti183d4ae2009-07-23 22:03:51 +0000286 read = buf.raw[:rc.value]
cliechtif622faf2003-07-12 23:41:43 +0000287 else:
cliechti4a567a02009-07-27 22:09:31 +0000288 read = bytes()
289 return bytes(read)
cliechti89b4af12002-02-12 23:24:41 +0000290
cliechti4a567a02009-07-27 22:09:31 +0000291 def write(self, data):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200292 """Output the given byte string over the serial port."""
293 if not self._port_handle: raise portNotOpenError
cliechti23dc2a02009-07-30 17:25:09 +0000294 #~ if not isinstance(data, (bytes, bytearray)):
295 #~ raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data)))
296 # convert data (needed in case of memoryview instance: Py 3.1 io lib), ctypes doesn't like memoryview
cliechti38077122013-10-16 02:57:27 +0000297 data = to_bytes(data)
cliechtib2f5fc82006-10-20 00:09:07 +0000298 if data:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200299 #~ win32event.ResetEvent(self._overlapped_write.hEvent)
cliechti183d4ae2009-07-23 22:03:51 +0000300 n = win32.DWORD()
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200301 err = win32.WriteFile(self._port_handle, data, len(data), ctypes.byref(n), self._overlapped_write)
cliechti183d4ae2009-07-23 22:03:51 +0000302 if not err and win32.GetLastError() != win32.ERROR_IO_PENDING:
cliechti1083be72011-12-28 20:45:30 +0000303 raise SerialException("WriteFile failed (%r)" % ctypes.WinError())
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200304 if self._write_timeout != 0: # if blocking (None) or w/ write timeout (>0)
cliechti31000fc2011-08-05 01:47:26 +0000305 # Wait for the write to complete.
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200306 #~ win32.WaitForSingleObject(self._overlapped_write.hEvent, win32.INFINITE)
307 err = win32.GetOverlappedResult(self._port_handle, self._overlapped_write, ctypes.byref(n), True)
cliechti31000fc2011-08-05 01:47:26 +0000308 if n.value != len(data):
309 raise writeTimeoutError
cliechti23dc2a02009-07-30 17:25:09 +0000310 return n.value
311 else:
312 return 0
cliechtiedfba4e2009-02-07 00:29:47 +0000313
cliechti26409782013-05-31 00:47:16 +0000314 def flush(self):
cliechti7d448562014-08-03 21:57:45 +0000315 """\
316 Flush of file like objects. In this case, wait until all data
317 is written.
318 """
cliechti26409782013-05-31 00:47:16 +0000319 while self.outWaiting():
320 time.sleep(0.05)
321 # XXX could also use WaitCommEvent with mask EV_TXEMPTY, but it would
322 # require overlapped IO and its also only possible to set a single mask
323 # on the port---
cliechti89b4af12002-02-12 23:24:41 +0000324
Chris Liechtief1fe252015-08-27 23:25:21 +0200325 def reset_input_buffer(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000326 """Clear input buffer, discarding all that is in the buffer."""
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200327 if not self._port_handle: raise portNotOpenError
328 win32.PurgeComm(self._port_handle, win32.PURGE_RXCLEAR | win32.PURGE_RXABORT)
cliechti89b4af12002-02-12 23:24:41 +0000329
Chris Liechtief1fe252015-08-27 23:25:21 +0200330 def reset_output_buffer(self):
cliechti7d448562014-08-03 21:57:45 +0000331 """\
332 Clear output buffer, aborting the current output and discarding all
333 that is in the buffer.
334 """
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200335 if not self._port_handle: raise portNotOpenError
336 win32.PurgeComm(self._port_handle, win32.PURGE_TXCLEAR | win32.PURGE_TXABORT)
cliechti89b4af12002-02-12 23:24:41 +0000337
Chris Liechtief1fe252015-08-27 23:25:21 +0200338 def _update_break_state(self):
cliechti997b63c2008-06-21 00:09:31 +0000339 """Set break: Controls TXD. When active, to transmitting is possible."""
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200340 if not self._port_handle: raise portNotOpenError
Chris Liechtief1fe252015-08-27 23:25:21 +0200341 if self._break_state:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200342 win32.SetCommBreak(self._port_handle)
cliechti997b63c2008-06-21 00:09:31 +0000343 else:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200344 win32.ClearCommBreak(self._port_handle)
cliechti997b63c2008-06-21 00:09:31 +0000345
Chris Liechtief1fe252015-08-27 23:25:21 +0200346 def _update_rts_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000347 """Set terminal status line: Request To Send"""
Chris Liechtief1fe252015-08-27 23:25:21 +0200348 if self._rts_state:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200349 win32.EscapeCommFunction(self._port_handle, win32.SETRTS)
cliechti89b4af12002-02-12 23:24:41 +0000350 else:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200351 win32.EscapeCommFunction(self._port_handle, win32.CLRRTS)
cliechti89b4af12002-02-12 23:24:41 +0000352
Chris Liechtief1fe252015-08-27 23:25:21 +0200353 def _update_dtr_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000354 """Set terminal status line: Data Terminal Ready"""
Chris Liechtief1fe252015-08-27 23:25:21 +0200355 if self._dtr_state:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200356 win32.EscapeCommFunction(self._port_handle, win32.SETDTR)
cliechti89b4af12002-02-12 23:24:41 +0000357 else:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200358 win32.EscapeCommFunction(self._port_handle, win32.CLRDTR)
cliechti183d4ae2009-07-23 22:03:51 +0000359
360 def _GetCommModemStatus(self):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200361 if not self._port_handle: raise portNotOpenError
cliechti183d4ae2009-07-23 22:03:51 +0000362 stat = win32.DWORD()
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200363 win32.GetCommModemStatus(self._port_handle, ctypes.byref(stat))
cliechti183d4ae2009-07-23 22:03:51 +0000364 return stat.value
cliechti89b4af12002-02-12 23:24:41 +0000365
Chris Liechtief1fe252015-08-27 23:25:21 +0200366 @property
367 def cts(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000368 """Read terminal status line: Clear To Send"""
cliechti183d4ae2009-07-23 22:03:51 +0000369 return win32.MS_CTS_ON & self._GetCommModemStatus() != 0
cliechti89b4af12002-02-12 23:24:41 +0000370
Chris Liechtief1fe252015-08-27 23:25:21 +0200371 @property
372 def dsr(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000373 """Read terminal status line: Data Set Ready"""
cliechti183d4ae2009-07-23 22:03:51 +0000374 return win32.MS_DSR_ON & self._GetCommModemStatus() != 0
cliechti89b4af12002-02-12 23:24:41 +0000375
Chris Liechtief1fe252015-08-27 23:25:21 +0200376 @property
377 def ri(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000378 """Read terminal status line: Ring Indicator"""
cliechti183d4ae2009-07-23 22:03:51 +0000379 return win32.MS_RING_ON & self._GetCommModemStatus() != 0
cliechti89b4af12002-02-12 23:24:41 +0000380
Chris Liechtief1fe252015-08-27 23:25:21 +0200381 @property
382 def cd(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000383 """Read terminal status line: Carrier Detect"""
cliechti183d4ae2009-07-23 22:03:51 +0000384 return win32.MS_RLSD_ON & self._GetCommModemStatus() != 0
cliechti89b4af12002-02-12 23:24:41 +0000385
cliechtia30a8a02003-10-05 12:28:13 +0000386 # - - platform specific - - - -
387
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200388 def set_buffer_size(self, rx_size=4096, tx_size=None):
cliechti59199642011-12-28 20:54:30 +0000389 """\
390 Recommend a buffer size to the driver (device driver can ignore this
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200391 value). Must be called before the port is opended.
cliechti59199642011-12-28 20:54:30 +0000392 """
393 if tx_size is None: tx_size = rx_size
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200394 win32.SetupComm(self._port_handle, rx_size, tx_size)
cliechti59199642011-12-28 20:54:30 +0000395
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200396 def set_output_flow_control(self, level=True):
cliechti2f0f8a32011-12-28 22:10:00 +0000397 """\
398 Manually control flow - when software flow control is enabled.
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200399 This will do the same as if XON (true) or XOFF (false) are received
400 from the other device and control the transmission accordingly.
cliechti2f0f8a32011-12-28 22:10:00 +0000401 WARNING: this function is not portable to different platforms!
402 """
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200403 if not self._port_handle: raise portNotOpenError
cliechtia30a8a02003-10-05 12:28:13 +0000404 if level:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200405 win32.EscapeCommFunction(self._port_handle, win32.SETXON)
cliechtia30a8a02003-10-05 12:28:13 +0000406 else:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200407 win32.EscapeCommFunction(self._port_handle, win32.SETXOFF)
cliechtia30a8a02003-10-05 12:28:13 +0000408
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200409 @property
410 def out_waiting(self):
411 """Return how many bytes the in the outgoing buffer"""
cliechti183d4ae2009-07-23 22:03:51 +0000412 flags = win32.DWORD()
413 comstat = win32.COMSTAT()
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200414 if not win32.ClearCommError(self._port_handle, ctypes.byref(flags), ctypes.byref(comstat)):
cliechti183d4ae2009-07-23 22:03:51 +0000415 raise SerialException('call to ClearCommError failed')
cliechtic8e83d82009-07-21 21:34:05 +0000416 return comstat.cbOutQue
417
cliechti1f89a0a2011-08-05 02:53:24 +0000418
cliechtif81362e2009-07-25 03:44:33 +0000419
cliechtiedfba4e2009-02-07 00:29:47 +0000420# Nur Testfunktion!!
cliechti89b4af12002-02-12 23:24:41 +0000421if __name__ == '__main__':
cliechti93db61b2006-08-26 19:16:18 +0000422 s = Serial(0)
cliechti7aaead32009-07-23 14:02:41 +0000423 sys.stdout.write("%s\n" % s)
cliechtiedfba4e2009-02-07 00:29:47 +0000424
cliechtid6bf52c2003-10-01 02:28:12 +0000425 s = Serial()
cliechti7aaead32009-07-23 14:02:41 +0000426 sys.stdout.write("%s\n" % s)
cliechtiedfba4e2009-02-07 00:29:47 +0000427
cliechtid6bf52c2003-10-01 02:28:12 +0000428 s.baudrate = 19200
429 s.databits = 7
430 s.close()
cliechti93db61b2006-08-26 19:16:18 +0000431 s.port = 0
cliechtid6bf52c2003-10-01 02:28:12 +0000432 s.open()
cliechti7aaead32009-07-23 14:02:41 +0000433 sys.stdout.write("%s\n" % s)
cliechti89b4af12002-02-12 23:24:41 +0000434