blob: 9e300e1103e7e59435ed416a6d8b04065f78b133 [file] [log] [blame]
cliechti89b4af12002-02-12 23:24:41 +00001#! python
Chris Liechti3e02f702015-12-16 23:06:04 +01002#
3# backend for Windows ("win32" incl. 32/64 bit support)
cliechti89b4af12002-02-12 23:24:41 +00004#
Chris Liechti68340d72015-08-03 14:15:48 +02005# (C) 2001-2015 Chris Liechti <cliechti@gmx.net>
Chris Liechtifbdd8a02015-08-09 02:37:45 +02006#
Chris Liechti3e02f702015-12-16 23:06:04 +01007# This file is part of pySerial. https://github.com/pyserial/pyserial
Chris Liechtifbdd8a02015-08-09 02:37:45 +02008# 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
Chris Liechti033f17c2015-08-30 21:28:04 +020016import serial
17from serial.serialutil import SerialBase, SerialException, to_bytes, portNotOpenError, writeTimeoutError
cliechti89b4af12002-02-12 23:24:41 +000018
cliechti4a567a02009-07-27 22:09:31 +000019
Chris Liechtief6b7b42015-08-06 22:19:26 +020020class Serial(SerialBase):
cliechti1e2a6df2009-07-24 02:00:50 +000021 """Serial port implementation for Win32 based on ctypes."""
cliechti89b4af12002-02-12 23:24:41 +000022
cliechti4a567a02009-07-27 22:09:31 +000023 BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
24 9600, 19200, 38400, 57600, 115200)
cliechti80a0ed12003-10-03 23:53:42 +000025
cliechti5735a072009-10-26 23:57:48 +000026 def __init__(self, *args, **kwargs):
Chris Liechti76f83492015-08-10 01:22:01 +020027 super(SerialBase, self).__init__()
Chris Liechti3ad62fb2015-08-29 21:53:32 +020028 self._port_handle = None
29 self._overlapped_read = None
30 self._overlapped_write = None
cliechti5735a072009-10-26 23:57:48 +000031 SerialBase.__init__(self, *args, **kwargs)
32
cliechtid6bf52c2003-10-01 02:28:12 +000033 def open(self):
cliechti7d448562014-08-03 21:57:45 +000034 """\
35 Open port with current settings. This may throw a SerialException
36 if the port cannot be opened.
37 """
cliechtid6bf52c2003-10-01 02:28:12 +000038 if self._port is None:
39 raise SerialException("Port must be configured before it can be used.")
Chris Liechti3ad62fb2015-08-29 21:53:32 +020040 if self.is_open:
cliechti8f69e702011-03-19 00:22:32 +000041 raise SerialException("Port is already open.")
Chris Liechti4cf65392016-01-21 23:57:02 +010042 # if RTS and/or DTR are not set before open, they default to True
43 if self._rts_state is None:
44 self._rts_state = True
45 if self._dtr_state is None:
46 self._dtr_state = True
cliechti8b7cff02008-06-24 12:11:57 +000047 # the "\\.\COMx" format is required for devices other than COM1-COM8
48 # not all versions of windows seem to support this properly
49 # so that the first few ports are used with the DOS device name
Chris Liechtief1fe252015-08-27 23:25:21 +020050 port = self.name
cliechti4a567a02009-07-27 22:09:31 +000051 try:
52 if port.upper().startswith('COM') and int(port[3:]) > 8:
53 port = '\\\\.\\' + port
54 except ValueError:
55 # for like COMnotanumber
56 pass
Chris Liechti033f17c2015-08-30 21:28:04 +020057 self._port_handle = win32.CreateFile(
58 port,
59 win32.GENERIC_READ | win32.GENERIC_WRITE,
60 0, # exclusive access
61 None, # no security
62 win32.OPEN_EXISTING,
63 win32.FILE_ATTRIBUTE_NORMAL | win32.FILE_FLAG_OVERLAPPED,
64 0)
Chris Liechti3ad62fb2015-08-29 21:53:32 +020065 if self._port_handle == win32.INVALID_HANDLE_VALUE:
66 self._port_handle = None # 'cause __del__ is called anyway
cliechti1083be72011-12-28 20:45:30 +000067 raise SerialException("could not open port %r: %r" % (self.portstr, ctypes.WinError()))
cliechtie37b6a82009-07-24 12:19:50 +000068
cliechti1ae5ab02013-10-11 01:08:02 +000069 try:
Chris Liechti3ad62fb2015-08-29 21:53:32 +020070 self._overlapped_read = win32.OVERLAPPED()
71 self._overlapped_read.hEvent = win32.CreateEvent(None, 1, 0, None)
72 self._overlapped_write = win32.OVERLAPPED()
73 #~ self._overlapped_write.hEvent = win32.CreateEvent(None, 1, 0, None)
74 self._overlapped_write.hEvent = win32.CreateEvent(None, 0, 0, None)
cliechti89b4af12002-02-12 23:24:41 +000075
cliechti1ae5ab02013-10-11 01:08:02 +000076 # Setup a 4k buffer
Chris Liechti3ad62fb2015-08-29 21:53:32 +020077 win32.SetupComm(self._port_handle, 4096, 4096)
cliechti89b4af12002-02-12 23:24:41 +000078
cliechti1ae5ab02013-10-11 01:08:02 +000079 # Save original timeout values:
80 self._orgTimeouts = win32.COMMTIMEOUTS()
Chris Liechti3ad62fb2015-08-29 21:53:32 +020081 win32.GetCommTimeouts(self._port_handle, ctypes.byref(self._orgTimeouts))
cliechtiedfba4e2009-02-07 00:29:47 +000082
Chris Liechti3ad62fb2015-08-29 21:53:32 +020083 self._reconfigure_port()
cliechti89b4af12002-02-12 23:24:41 +000084
cliechti1ae5ab02013-10-11 01:08:02 +000085 # Clear buffers:
86 # Remove anything that was there
Chris Liechti033f17c2015-08-30 21:28:04 +020087 win32.PurgeComm(
88 self._port_handle,
cliechti1ae5ab02013-10-11 01:08:02 +000089 win32.PURGE_TXCLEAR | win32.PURGE_TXABORT |
90 win32.PURGE_RXCLEAR | win32.PURGE_RXABORT)
91 except:
92 try:
93 self._close()
94 except:
95 # ignore any exception when closing the port
96 # also to keep original exception that happened when setting up
97 pass
Chris Liechti3ad62fb2015-08-29 21:53:32 +020098 self._port_handle = None
cliechti1ae5ab02013-10-11 01:08:02 +000099 raise
100 else:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200101 self.is_open = True
cliechti1ae5ab02013-10-11 01:08:02 +0000102
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200103 def _reconfigure_port(self):
cliechticc8d9d22008-07-06 22:42:44 +0000104 """Set communication parameters on opened port."""
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200105 if not self._port_handle:
cliechtid6bf52c2003-10-01 02:28:12 +0000106 raise SerialException("Can only operate on a valid port handle")
cliechtiedfba4e2009-02-07 00:29:47 +0000107
108 # Set Windows timeout values
109 # timeouts is a tuple with the following items:
110 # (ReadIntervalTimeout,ReadTotalTimeoutMultiplier,
111 # ReadTotalTimeoutConstant,WriteTotalTimeoutMultiplier,
112 # WriteTotalTimeoutConstant)
Chris Liechticc128012015-11-06 02:34:16 +0100113 timeouts = win32.COMMTIMEOUTS()
cliechtid6bf52c2003-10-01 02:28:12 +0000114 if self._timeout is None:
Chris Liechtie1927242015-11-03 00:38:43 +0100115 pass # default of all zeros is OK
cliechtid6bf52c2003-10-01 02:28:12 +0000116 elif self._timeout == 0:
Chris Liechtie1927242015-11-03 00:38:43 +0100117 timeouts.ReadIntervalTimeout = win32.MAXDWORD
cliechtid6bf52c2003-10-01 02:28:12 +0000118 else:
Chris Liechtie1927242015-11-03 00:38:43 +0100119 timeouts.ReadTotalTimeoutConstant = max(int(self._timeout * 1000), 1)
Chris Liechti518b0d32015-08-30 02:20:39 +0200120 if self._timeout != 0 and self._inter_byte_timeout is not None:
Chris Liechtie1927242015-11-03 00:38:43 +0100121 timeouts.ReadIntervalTimeout = max(int(self._inter_byte_timeout * 1000), 1)
cliechtiedfba4e2009-02-07 00:29:47 +0000122
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200123 if self._write_timeout is None:
cliechti62611612004-04-20 01:55:43 +0000124 pass
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200125 elif self._write_timeout == 0:
Chris Liechtie1927242015-11-03 00:38:43 +0100126 timeouts.WriteTotalTimeoutConstant = win32.MAXDWORD
cliechti62611612004-04-20 01:55:43 +0000127 else:
Chris Liechtie1927242015-11-03 00:38:43 +0100128 timeouts.WriteTotalTimeoutConstant = max(int(self._write_timeout * 1000), 1)
129 win32.SetCommTimeouts(self._port_handle, ctypes.byref(timeouts))
cliechti89b4af12002-02-12 23:24:41 +0000130
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200131 win32.SetCommMask(self._port_handle, win32.EV_ERR)
cliechti89b4af12002-02-12 23:24:41 +0000132
cliechti95c62212002-03-04 22:17:53 +0000133 # Setup the connection info.
134 # Get state and modify it:
cliechti183d4ae2009-07-23 22:03:51 +0000135 comDCB = win32.DCB()
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200136 win32.GetCommState(self._port_handle, ctypes.byref(comDCB))
cliechtid6bf52c2003-10-01 02:28:12 +0000137 comDCB.BaudRate = self._baudrate
138
Chris Liechti033f17c2015-08-30 21:28:04 +0200139 if self._bytesize == serial.FIVEBITS:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200140 comDCB.ByteSize = 5
Chris Liechti033f17c2015-08-30 21:28:04 +0200141 elif self._bytesize == serial.SIXBITS:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200142 comDCB.ByteSize = 6
Chris Liechti033f17c2015-08-30 21:28:04 +0200143 elif self._bytesize == serial.SEVENBITS:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200144 comDCB.ByteSize = 7
Chris Liechti033f17c2015-08-30 21:28:04 +0200145 elif self._bytesize == serial.EIGHTBITS:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200146 comDCB.ByteSize = 8
cliechtid6bf52c2003-10-01 02:28:12 +0000147 else:
148 raise ValueError("Unsupported number of data bits: %r" % self._bytesize)
149
Chris Liechti033f17c2015-08-30 21:28:04 +0200150 if self._parity == serial.PARITY_NONE:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200151 comDCB.Parity = win32.NOPARITY
Chris Liechti033f17c2015-08-30 21:28:04 +0200152 comDCB.fParity = 0 # Disable Parity Check
153 elif self._parity == serial.PARITY_EVEN:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200154 comDCB.Parity = win32.EVENPARITY
Chris Liechti033f17c2015-08-30 21:28:04 +0200155 comDCB.fParity = 1 # Enable Parity Check
156 elif self._parity == serial.PARITY_ODD:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200157 comDCB.Parity = win32.ODDPARITY
Chris Liechti033f17c2015-08-30 21:28:04 +0200158 comDCB.fParity = 1 # Enable Parity Check
159 elif self._parity == serial.PARITY_MARK:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200160 comDCB.Parity = win32.MARKPARITY
Chris Liechti033f17c2015-08-30 21:28:04 +0200161 comDCB.fParity = 1 # Enable Parity Check
162 elif self._parity == serial.PARITY_SPACE:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200163 comDCB.Parity = win32.SPACEPARITY
Chris Liechti033f17c2015-08-30 21:28:04 +0200164 comDCB.fParity = 1 # Enable Parity Check
cliechtid6bf52c2003-10-01 02:28:12 +0000165 else:
166 raise ValueError("Unsupported parity mode: %r" % self._parity)
167
Chris Liechti033f17c2015-08-30 21:28:04 +0200168 if self._stopbits == serial.STOPBITS_ONE:
169 comDCB.StopBits = win32.ONESTOPBIT
170 elif self._stopbits == serial.STOPBITS_ONE_POINT_FIVE:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200171 comDCB.StopBits = win32.ONE5STOPBITS
Chris Liechti033f17c2015-08-30 21:28:04 +0200172 elif self._stopbits == serial.STOPBITS_TWO:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200173 comDCB.StopBits = win32.TWOSTOPBITS
cliechtid6bf52c2003-10-01 02:28:12 +0000174 else:
175 raise ValueError("Unsupported number of stop bits: %r" % self._stopbits)
cliechtiedfba4e2009-02-07 00:29:47 +0000176
Chris Liechti033f17c2015-08-30 21:28:04 +0200177 comDCB.fBinary = 1 # Enable Binary Transmission
cliechtid6bf52c2003-10-01 02:28:12 +0000178 # Char. w/ Parity-Err are replaced with 0xff (if fErrorChar is set to TRUE)
Chris Liechti33f0ec52015-08-06 16:37:21 +0200179 if self._rs485_mode is None:
180 if self._rtscts:
181 comDCB.fRtsControl = win32.RTS_CONTROL_HANDSHAKE
182 else:
Chris Liechtief1fe252015-08-27 23:25:21 +0200183 comDCB.fRtsControl = win32.RTS_CONTROL_ENABLE if self._rts_state else win32.RTS_CONTROL_DISABLE
Chris Liechti33f0ec52015-08-06 16:37:21 +0200184 comDCB.fOutxCtsFlow = self._rtscts
cliechtid6bf52c2003-10-01 02:28:12 +0000185 else:
Chris Liechti33f0ec52015-08-06 16:37:21 +0200186 # checks for unsupported settings
187 # XXX verify if platform really does not have a setting for those
188 if not self._rs485_mode.rts_level_for_tx:
189 raise ValueError(
190 'Unsupported value for RS485Settings.rts_level_for_tx: %r' % (
Chris Liechti033f17c2015-08-30 21:28:04 +0200191 self._rs485_mode.rts_level_for_tx,))
Chris Liechti33f0ec52015-08-06 16:37:21 +0200192 if self._rs485_mode.rts_level_for_rx:
193 raise ValueError(
194 'Unsupported value for RS485Settings.rts_level_for_rx: %r' % (
Chris Liechti033f17c2015-08-30 21:28:04 +0200195 self._rs485_mode.rts_level_for_rx,))
Chris Liechti33f0ec52015-08-06 16:37:21 +0200196 if self._rs485_mode.delay_before_tx is not None:
197 raise ValueError(
198 'Unsupported value for RS485Settings.delay_before_tx: %r' % (
Chris Liechti033f17c2015-08-30 21:28:04 +0200199 self._rs485_mode.delay_before_tx,))
Chris Liechti33f0ec52015-08-06 16:37:21 +0200200 if self._rs485_mode.delay_before_rx is not None:
201 raise ValueError(
202 'Unsupported value for RS485Settings.delay_before_rx: %r' % (
Chris Liechti033f17c2015-08-30 21:28:04 +0200203 self._rs485_mode.delay_before_rx,))
Chris Liechti33f0ec52015-08-06 16:37:21 +0200204 if self._rs485_mode.loopback:
205 raise ValueError(
206 'Unsupported value for RS485Settings.loopback: %r' % (
Chris Liechti033f17c2015-08-30 21:28:04 +0200207 self._rs485_mode.loopback,))
Chris Liechti33f0ec52015-08-06 16:37:21 +0200208 comDCB.fRtsControl = win32.RTS_CONTROL_TOGGLE
209 comDCB.fOutxCtsFlow = 0
210
cliechtif46e0a82005-05-19 15:24:57 +0000211 if self._dsrdtr:
Chris Liechti033f17c2015-08-30 21:28:04 +0200212 comDCB.fDtrControl = win32.DTR_CONTROL_HANDSHAKE
cliechtif46e0a82005-05-19 15:24:57 +0000213 else:
Chris Liechti033f17c2015-08-30 21:28:04 +0200214 comDCB.fDtrControl = win32.DTR_CONTROL_ENABLE if self._dtr_state else win32.DTR_CONTROL_DISABLE
215 comDCB.fOutxDsrFlow = self._dsrdtr
216 comDCB.fOutX = self._xonxoff
217 comDCB.fInX = self._xonxoff
218 comDCB.fNull = 0
219 comDCB.fErrorChar = 0
220 comDCB.fAbortOnError = 0
221 comDCB.XonChar = serial.XON
222 comDCB.XoffChar = serial.XOFF
cliechtid6bf52c2003-10-01 02:28:12 +0000223
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200224 if not win32.SetCommState(self._port_handle, ctypes.byref(comDCB)):
Chris Liechtia629c5d2015-12-12 23:19:14 +0100225 raise SerialException("Cannot configure port, something went wrong. Original message: %r" % ctypes.WinError())
cliechti95c62212002-03-04 22:17:53 +0000226
cliechtid6bf52c2003-10-01 02:28:12 +0000227 #~ def __del__(self):
228 #~ self.close()
229
cliechti1ae5ab02013-10-11 01:08:02 +0000230 def _close(self):
231 """internal close port helper"""
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200232 if self._port_handle:
cliechti1ae5ab02013-10-11 01:08:02 +0000233 # Restore original timeout values:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200234 win32.SetCommTimeouts(self._port_handle, self._orgTimeouts)
cliechti1ae5ab02013-10-11 01:08:02 +0000235 # Close COM-Port:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200236 win32.CloseHandle(self._port_handle)
237 if self._overlapped_read is not None:
238 win32.CloseHandle(self._overlapped_read.hEvent)
239 self._overlapped_read = None
240 if self._overlapped_write is not None:
241 win32.CloseHandle(self._overlapped_write.hEvent)
242 self._overlapped_write = None
243 self._port_handle = None
cliechti1ae5ab02013-10-11 01:08:02 +0000244
cliechtid6bf52c2003-10-01 02:28:12 +0000245 def close(self):
246 """Close port"""
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200247 if self.is_open:
cliechti1ae5ab02013-10-11 01:08:02 +0000248 self._close()
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200249 self.is_open = False
cliechtid6bf52c2003-10-01 02:28:12 +0000250
251 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechtiedfba4e2009-02-07 00:29:47 +0000252
Chris Liechtief1fe252015-08-27 23:25:21 +0200253 @property
254 def in_waiting(self):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200255 """Return the number of bytes currently in the input buffer."""
cliechti183d4ae2009-07-23 22:03:51 +0000256 flags = win32.DWORD()
257 comstat = win32.COMSTAT()
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200258 if not win32.ClearCommError(self._port_handle, ctypes.byref(flags), ctypes.byref(comstat)):
cliechti183d4ae2009-07-23 22:03:51 +0000259 raise SerialException('call to ClearCommError failed')
cliechti89b4af12002-02-12 23:24:41 +0000260 return comstat.cbInQue
261
cliechti4a567a02009-07-27 22:09:31 +0000262 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000263 """\
264 Read size bytes from the serial port. If a timeout is set it may
265 return less characters as requested. With no timeout it will block
266 until the requested number of bytes is read."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200267 if not self._port_handle:
268 raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000269 if size > 0:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200270 win32.ResetEvent(self._overlapped_read.hEvent)
cliechti183d4ae2009-07-23 22:03:51 +0000271 flags = win32.DWORD()
272 comstat = win32.COMSTAT()
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200273 if not win32.ClearCommError(self._port_handle, ctypes.byref(flags), ctypes.byref(comstat)):
cliechti183d4ae2009-07-23 22:03:51 +0000274 raise SerialException('call to ClearCommError failed')
cliechti5c39e702002-06-04 14:56:34 +0000275 if self.timeout == 0:
cliechti17f177f2002-06-07 22:33:37 +0000276 n = min(comstat.cbInQue, size)
277 if n > 0:
cliechti183d4ae2009-07-23 22:03:51 +0000278 buf = ctypes.create_string_buffer(n)
279 rc = win32.DWORD()
Chris Liechti7731e982015-11-02 23:46:07 +0100280 read_ok = win32.ReadFile(self._port_handle, buf, n, ctypes.byref(rc), ctypes.byref(self._overlapped_read))
281 if not read_ok and win32.GetLastError() not in (win32.ERROR_SUCCESS, win32.ERROR_IO_PENDING):
cliechti1083be72011-12-28 20:45:30 +0000282 raise SerialException("ReadFile failed (%r)" % ctypes.WinError())
David Howlett44a65c42015-12-14 14:51:17 +0000283 win32.GetOverlappedResult(self._port_handle, ctypes.byref(self._overlapped_read), ctypes.byref(rc), True)
cliechti183d4ae2009-07-23 22:03:51 +0000284 read = buf.raw[:rc.value]
cliechtif622faf2003-07-12 23:41:43 +0000285 else:
cliechti4a567a02009-07-27 22:09:31 +0000286 read = bytes()
cliechti5c39e702002-06-04 14:56:34 +0000287 else:
cliechti183d4ae2009-07-23 22:03:51 +0000288 buf = ctypes.create_string_buffer(size)
289 rc = win32.DWORD()
Chris Liechti7731e982015-11-02 23:46:07 +0100290 read_ok = win32.ReadFile(self._port_handle, buf, size, ctypes.byref(rc), ctypes.byref(self._overlapped_read))
291 if not read_ok and win32.GetLastError() not in (win32.ERROR_SUCCESS, win32.ERROR_IO_PENDING):
cliechti1083be72011-12-28 20:45:30 +0000292 raise SerialException("ReadFile failed (%r)" % ctypes.WinError())
Chris Liechti7731e982015-11-02 23:46:07 +0100293 win32.GetOverlappedResult(self._port_handle, ctypes.byref(self._overlapped_read), ctypes.byref(rc), True)
cliechti183d4ae2009-07-23 22:03:51 +0000294 read = buf.raw[:rc.value]
cliechtif622faf2003-07-12 23:41:43 +0000295 else:
cliechti4a567a02009-07-27 22:09:31 +0000296 read = bytes()
297 return bytes(read)
cliechti89b4af12002-02-12 23:24:41 +0000298
cliechti4a567a02009-07-27 22:09:31 +0000299 def write(self, data):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200300 """Output the given byte string over the serial port."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200301 if not self._port_handle:
302 raise portNotOpenError
cliechti23dc2a02009-07-30 17:25:09 +0000303 #~ if not isinstance(data, (bytes, bytearray)):
304 #~ raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data)))
305 # convert data (needed in case of memoryview instance: Py 3.1 io lib), ctypes doesn't like memoryview
cliechti38077122013-10-16 02:57:27 +0000306 data = to_bytes(data)
cliechtib2f5fc82006-10-20 00:09:07 +0000307 if data:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200308 #~ win32event.ResetEvent(self._overlapped_write.hEvent)
cliechti183d4ae2009-07-23 22:03:51 +0000309 n = win32.DWORD()
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200310 err = win32.WriteFile(self._port_handle, data, len(data), ctypes.byref(n), self._overlapped_write)
cliechti183d4ae2009-07-23 22:03:51 +0000311 if not err and win32.GetLastError() != win32.ERROR_IO_PENDING:
cliechti1083be72011-12-28 20:45:30 +0000312 raise SerialException("WriteFile failed (%r)" % ctypes.WinError())
Chris Liechti033f17c2015-08-30 21:28:04 +0200313 if self._write_timeout != 0: # if blocking (None) or w/ write timeout (>0)
cliechti31000fc2011-08-05 01:47:26 +0000314 # Wait for the write to complete.
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200315 #~ win32.WaitForSingleObject(self._overlapped_write.hEvent, win32.INFINITE)
316 err = win32.GetOverlappedResult(self._port_handle, self._overlapped_write, ctypes.byref(n), True)
cliechti31000fc2011-08-05 01:47:26 +0000317 if n.value != len(data):
318 raise writeTimeoutError
cliechti23dc2a02009-07-30 17:25:09 +0000319 return n.value
320 else:
321 return 0
cliechtiedfba4e2009-02-07 00:29:47 +0000322
cliechti26409782013-05-31 00:47:16 +0000323 def flush(self):
cliechti7d448562014-08-03 21:57:45 +0000324 """\
325 Flush of file like objects. In this case, wait until all data
326 is written.
327 """
Chris Liechtibc119fd2015-09-09 17:08:25 +0200328 while self.out_waiting:
cliechti26409782013-05-31 00:47:16 +0000329 time.sleep(0.05)
330 # XXX could also use WaitCommEvent with mask EV_TXEMPTY, but it would
331 # require overlapped IO and its also only possible to set a single mask
332 # on the port---
cliechti89b4af12002-02-12 23:24:41 +0000333
Chris Liechtief1fe252015-08-27 23:25:21 +0200334 def reset_input_buffer(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000335 """Clear input buffer, discarding all that is in the buffer."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200336 if not self._port_handle:
337 raise portNotOpenError
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200338 win32.PurgeComm(self._port_handle, win32.PURGE_RXCLEAR | win32.PURGE_RXABORT)
cliechti89b4af12002-02-12 23:24:41 +0000339
Chris Liechtief1fe252015-08-27 23:25:21 +0200340 def reset_output_buffer(self):
cliechti7d448562014-08-03 21:57:45 +0000341 """\
342 Clear output buffer, aborting the current output and discarding all
343 that is in the buffer.
344 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200345 if not self._port_handle:
346 raise portNotOpenError
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200347 win32.PurgeComm(self._port_handle, win32.PURGE_TXCLEAR | win32.PURGE_TXABORT)
cliechti89b4af12002-02-12 23:24:41 +0000348
Chris Liechtief1fe252015-08-27 23:25:21 +0200349 def _update_break_state(self):
cliechti997b63c2008-06-21 00:09:31 +0000350 """Set break: Controls TXD. When active, to transmitting is possible."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200351 if not self._port_handle:
352 raise portNotOpenError
Chris Liechtief1fe252015-08-27 23:25:21 +0200353 if self._break_state:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200354 win32.SetCommBreak(self._port_handle)
cliechti997b63c2008-06-21 00:09:31 +0000355 else:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200356 win32.ClearCommBreak(self._port_handle)
cliechti997b63c2008-06-21 00:09:31 +0000357
Chris Liechtief1fe252015-08-27 23:25:21 +0200358 def _update_rts_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000359 """Set terminal status line: Request To Send"""
Chris Liechtief1fe252015-08-27 23:25:21 +0200360 if self._rts_state:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200361 win32.EscapeCommFunction(self._port_handle, win32.SETRTS)
cliechti89b4af12002-02-12 23:24:41 +0000362 else:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200363 win32.EscapeCommFunction(self._port_handle, win32.CLRRTS)
cliechti89b4af12002-02-12 23:24:41 +0000364
Chris Liechtief1fe252015-08-27 23:25:21 +0200365 def _update_dtr_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000366 """Set terminal status line: Data Terminal Ready"""
Chris Liechtief1fe252015-08-27 23:25:21 +0200367 if self._dtr_state:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200368 win32.EscapeCommFunction(self._port_handle, win32.SETDTR)
cliechti89b4af12002-02-12 23:24:41 +0000369 else:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200370 win32.EscapeCommFunction(self._port_handle, win32.CLRDTR)
cliechti183d4ae2009-07-23 22:03:51 +0000371
372 def _GetCommModemStatus(self):
Chris Liechti033f17c2015-08-30 21:28:04 +0200373 if not self._port_handle:
374 raise portNotOpenError
cliechti183d4ae2009-07-23 22:03:51 +0000375 stat = win32.DWORD()
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200376 win32.GetCommModemStatus(self._port_handle, ctypes.byref(stat))
cliechti183d4ae2009-07-23 22:03:51 +0000377 return stat.value
cliechti89b4af12002-02-12 23:24:41 +0000378
Chris Liechtief1fe252015-08-27 23:25:21 +0200379 @property
380 def cts(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000381 """Read terminal status line: Clear To Send"""
cliechti183d4ae2009-07-23 22:03:51 +0000382 return win32.MS_CTS_ON & self._GetCommModemStatus() != 0
cliechti89b4af12002-02-12 23:24:41 +0000383
Chris Liechtief1fe252015-08-27 23:25:21 +0200384 @property
385 def dsr(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000386 """Read terminal status line: Data Set Ready"""
cliechti183d4ae2009-07-23 22:03:51 +0000387 return win32.MS_DSR_ON & self._GetCommModemStatus() != 0
cliechti89b4af12002-02-12 23:24:41 +0000388
Chris Liechtief1fe252015-08-27 23:25:21 +0200389 @property
390 def ri(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000391 """Read terminal status line: Ring Indicator"""
cliechti183d4ae2009-07-23 22:03:51 +0000392 return win32.MS_RING_ON & self._GetCommModemStatus() != 0
cliechti89b4af12002-02-12 23:24:41 +0000393
Chris Liechtief1fe252015-08-27 23:25:21 +0200394 @property
395 def cd(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000396 """Read terminal status line: Carrier Detect"""
cliechti183d4ae2009-07-23 22:03:51 +0000397 return win32.MS_RLSD_ON & self._GetCommModemStatus() != 0
cliechti89b4af12002-02-12 23:24:41 +0000398
cliechtia30a8a02003-10-05 12:28:13 +0000399 # - - platform specific - - - -
400
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200401 def set_buffer_size(self, rx_size=4096, tx_size=None):
cliechti59199642011-12-28 20:54:30 +0000402 """\
403 Recommend a buffer size to the driver (device driver can ignore this
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200404 value). Must be called before the port is opended.
cliechti59199642011-12-28 20:54:30 +0000405 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200406 if tx_size is None:
407 tx_size = rx_size
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200408 win32.SetupComm(self._port_handle, rx_size, tx_size)
cliechti59199642011-12-28 20:54:30 +0000409
Chris Liechti518b0d32015-08-30 02:20:39 +0200410 def set_output_flow_control(self, enable=True):
cliechti2f0f8a32011-12-28 22:10:00 +0000411 """\
412 Manually control flow - when software flow control is enabled.
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200413 This will do the same as if XON (true) or XOFF (false) are received
414 from the other device and control the transmission accordingly.
cliechti2f0f8a32011-12-28 22:10:00 +0000415 WARNING: this function is not portable to different platforms!
416 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200417 if not self._port_handle:
418 raise portNotOpenError
Chris Liechti518b0d32015-08-30 02:20:39 +0200419 if enable:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200420 win32.EscapeCommFunction(self._port_handle, win32.SETXON)
cliechtia30a8a02003-10-05 12:28:13 +0000421 else:
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200422 win32.EscapeCommFunction(self._port_handle, win32.SETXOFF)
cliechtia30a8a02003-10-05 12:28:13 +0000423
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200424 @property
425 def out_waiting(self):
426 """Return how many bytes the in the outgoing buffer"""
cliechti183d4ae2009-07-23 22:03:51 +0000427 flags = win32.DWORD()
428 comstat = win32.COMSTAT()
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200429 if not win32.ClearCommError(self._port_handle, ctypes.byref(flags), ctypes.byref(comstat)):
cliechti183d4ae2009-07-23 22:03:51 +0000430 raise SerialException('call to ClearCommError failed')
cliechtic8e83d82009-07-21 21:34:05 +0000431 return comstat.cbOutQue
432
cliechti1f89a0a2011-08-05 02:53:24 +0000433
cliechtiedfba4e2009-02-07 00:29:47 +0000434# Nur Testfunktion!!
cliechti89b4af12002-02-12 23:24:41 +0000435if __name__ == '__main__':
Chris Liechti033f17c2015-08-30 21:28:04 +0200436 import sys
cliechti93db61b2006-08-26 19:16:18 +0000437 s = Serial(0)
cliechti7aaead32009-07-23 14:02:41 +0000438 sys.stdout.write("%s\n" % s)
cliechtiedfba4e2009-02-07 00:29:47 +0000439
cliechtid6bf52c2003-10-01 02:28:12 +0000440 s = Serial()
cliechti7aaead32009-07-23 14:02:41 +0000441 sys.stdout.write("%s\n" % s)
cliechtiedfba4e2009-02-07 00:29:47 +0000442
cliechtid6bf52c2003-10-01 02:28:12 +0000443 s.baudrate = 19200
444 s.databits = 7
445 s.close()
cliechti93db61b2006-08-26 19:16:18 +0000446 s.port = 0
cliechtid6bf52c2003-10-01 02:28:12 +0000447 s.open()
cliechti7aaead32009-07-23 14:02:41 +0000448 sys.stdout.write("%s\n" % s)