From c05eb1f683034cf5d73d8c4ce8954c1be697347c Mon Sep 17 00:00:00 2001 From: cedric Date: Tue, 27 Oct 2020 22:17:25 +0100 Subject: [PATCH] Update serial module to work on windowz --- parameters.py | 2 +- serial/__init__.py | 6 +- serial/rfc2217.py | 41 +++--- serial/rs485.py | 2 - serial/serialcli.py | 28 ++-- serial/serialjava.py | 28 ++-- serial/serialposix.py | 155 ++++++--------------- serial/serialutil.py | 22 ++- serial/serialwin32.py | 34 +++-- serial/threaded/__init__.py | 6 +- serial/tools/hexlify_codec.py | 2 - serial/tools/list_ports.py | 2 - serial/tools/list_ports_common.py | 21 +-- serial/tools/list_ports_linux.py | 10 +- serial/tools/list_ports_osx.py | 86 ++++-------- serial/tools/list_ports_posix.py | 2 - serial/tools/list_ports_windows.py | 142 ++----------------- serial/tools/miniterm.py | 192 +++++++++----------------- serial/urlhandler/protocol_alt.py | 2 - serial/urlhandler/protocol_hwgrep.py | 2 - serial/urlhandler/protocol_loop.py | 35 ++--- serial/urlhandler/protocol_rfc2217.py | 4 +- serial/urlhandler/protocol_socket.py | 33 ++--- serial/urlhandler/protocol_spy.py | 2 - serial/win32.py | 12 -- 25 files changed, 252 insertions(+), 619 deletions(-) diff --git a/parameters.py b/parameters.py index 5dc522c0..07800b7f 100644 --- a/parameters.py +++ b/parameters.py @@ -1280,7 +1280,7 @@ def updateDisplay(self, request_name, update_inputs=False): if self.updatelog and self.logfile is not None: self.logfile.write("\t@ " + datetime.datetime.now().strftime("%H:%M:%S.%f")[:-3] + "\n") - self.logfile.write("\tScreen : " + self.pagename.encode('utf-8') + "\tRequest : " + request_name.encode('utf-8') + "\n") + self.logfile.write("\tScreen : " + self.pagename + "\tRequest : " + request_name + "\n") string = json.dumps(logdict) self.logfile.write(u"\t\t" + string) self.logfile.write("\n") diff --git a/serial/__init__.py b/serial/__init__.py index e6b64cd9..c24ced88 100644 --- a/serial/__init__.py +++ b/serial/__init__.py @@ -3,19 +3,17 @@ # This is a wrapper module for different platform implementations # # This file is part of pySerial. https://github.com/pyserial/pyserial -# (C) 2001-2020 Chris Liechti +# (C) 2001-2017 Chris Liechti # # SPDX-License-Identifier: BSD-3-Clause -from __future__ import absolute_import - import sys import importlib from serial.serialutil import * #~ SerialBase, SerialException, to_bytes, iterbytes -__version__ = '3.5b0' +__version__ = '3.4' VERSION = __version__ diff --git a/serial/rfc2217.py b/serial/rfc2217.py index 2ae188ed..419947d3 100644 --- a/serial/rfc2217.py +++ b/serial/rfc2217.py @@ -58,8 +58,6 @@ # RFC). # the order of the options is not relevant -from __future__ import absolute_import - import logging import socket import struct @@ -76,7 +74,7 @@ import serial from serial.serialutil import SerialBase, SerialException, to_bytes, \ - iterbytes, PortNotOpenError, Timeout + iterbytes, portNotOpenError, Timeout # port string is expected to be something like this: # rfc2217://host:port @@ -483,7 +481,7 @@ def open(self): if self.logger: self.logger.info("Negotiated options: {}".format(self._telnet_options)) - # fine, go on, set RFC 2217 specific things + # fine, go on, set RFC 2271 specific things self._reconfigure_port() # all things set up get, now a clean start if not self._dsrdtr: @@ -598,7 +596,7 @@ def from_url(self, url): def in_waiting(self): """Return the number of bytes currently in the input buffer.""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError return self._read_buffer.qsize() def read(self, size=1): @@ -608,17 +606,14 @@ def read(self, size=1): until the requested number of bytes is read. """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError data = bytearray() try: timeout = Timeout(self._timeout) while len(data) < size: - if self._thread is None or not self._thread.is_alive(): + if self._thread is None: raise SerialException('connection failed (reader thread died)') - buf = self._read_buffer.get(True, timeout.time_left()) - if buf is None: - return bytes(data) - data += buf + data += self._read_buffer.get(True, timeout.time_left()) if timeout.expired(): break except Queue.Empty: # -> timeout @@ -632,7 +627,8 @@ def write(self, data): closed. """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError + # XXX use protocol_socket's write with self._write_lock: try: self._socket.sendall(to_bytes(data).replace(IAC, IAC_DOUBLED)) @@ -643,7 +639,7 @@ def write(self, data): def reset_input_buffer(self): """Clear input buffer, discarding all that is in the buffer.""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError self.rfc2217_send_purge(PURGE_RECEIVE_BUFFER) # empty read buffer while self._read_buffer.qsize(): @@ -655,7 +651,7 @@ def reset_output_buffer(self): discarding all that is in the buffer. """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError self.rfc2217_send_purge(PURGE_TRANSMIT_BUFFER) def _update_break_state(self): @@ -664,7 +660,7 @@ def _update_break_state(self): possible. """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError if self.logger: self.logger.info('set BREAK to {}'.format('active' if self._break_state else 'inactive')) if self._break_state: @@ -675,7 +671,7 @@ def _update_break_state(self): def _update_rts_state(self): """Set terminal status line: Request To Send.""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError if self.logger: self.logger.info('set RTS to {}'.format('active' if self._rts_state else 'inactive')) if self._rts_state: @@ -686,7 +682,7 @@ def _update_rts_state(self): def _update_dtr_state(self): """Set terminal status line: Data Terminal Ready.""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError if self.logger: self.logger.info('set DTR to {}'.format('active' if self._dtr_state else 'inactive')) if self._dtr_state: @@ -698,28 +694,28 @@ def _update_dtr_state(self): def cts(self): """Read terminal status line: Clear To Send.""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError return bool(self.get_modem_state() & MODEMSTATE_MASK_CTS) @property def dsr(self): """Read terminal status line: Data Set Ready.""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError return bool(self.get_modem_state() & MODEMSTATE_MASK_DSR) @property def ri(self): """Read terminal status line: Ring Indicator.""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError return bool(self.get_modem_state() & MODEMSTATE_MASK_RI) @property def cd(self): """Read terminal status line: Carrier Detect.""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError return bool(self.get_modem_state() & MODEMSTATE_MASK_CD) # - - - platform specific - - - @@ -743,10 +739,8 @@ def _telnet_read_loop(self): # connection fails -> terminate loop if self.logger: self.logger.debug("socket error in reader thread: {}".format(e)) - self._read_buffer.put(None) break if not data: - self._read_buffer.put(None) break # lost connection for byte in iterbytes(data): if mode == M_NORMAL: @@ -790,6 +784,7 @@ def _telnet_read_loop(self): self._telnet_negotiate_option(telnet_command, byte) mode = M_NORMAL finally: + self._thread = None if self.logger: self.logger.debug("read thread terminated") diff --git a/serial/rs485.py b/serial/rs485.py index d7aff6f6..29393507 100644 --- a/serial/rs485.py +++ b/serial/rs485.py @@ -13,8 +13,6 @@ NOTE: Some implementations may only support a subset of the settings. """ -from __future__ import absolute_import - import time import serial diff --git a/serial/serialcli.py b/serial/serialcli.py index 4614736e..0727a525 100644 --- a/serial/serialcli.py +++ b/serial/serialcli.py @@ -7,8 +7,6 @@ # # SPDX-License-Identifier: BSD-3-Clause -from __future__ import absolute_import - import System import System.IO.Ports from serial.serialutil import * @@ -148,7 +146,7 @@ def close(self): def in_waiting(self): """Return the number of characters currently in the input buffer.""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError return self._port_handle.BytesToRead def read(self, size=1): @@ -158,7 +156,7 @@ def read(self, size=1): until the requested number of bytes is read. """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError # must use single byte reads as this is the only way to read # without applying encodings data = bytearray() @@ -174,7 +172,7 @@ def read(self, size=1): def write(self, data): """Output the given string over the serial port.""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError #~ if not isinstance(data, (bytes, bytearray)): #~ raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data))) try: @@ -182,13 +180,13 @@ def write(self, data): # as this is the only one not applying encodings self._port_handle.Write(as_byte_array(data), 0, len(data)) except System.TimeoutException: - raise SerialTimeoutException('Write timeout') + raise writeTimeoutError return len(data) def reset_input_buffer(self): """Clear input buffer, discarding all that is in the buffer.""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError self._port_handle.DiscardInBuffer() def reset_output_buffer(self): @@ -197,7 +195,7 @@ def reset_output_buffer(self): discarding all that is in the buffer. """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError self._port_handle.DiscardOutBuffer() def _update_break_state(self): @@ -205,40 +203,40 @@ def _update_break_state(self): Set break: Controls TXD. When active, to transmitting is possible. """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError self._port_handle.BreakState = bool(self._break_state) def _update_rts_state(self): """Set terminal status line: Request To Send""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError self._port_handle.RtsEnable = bool(self._rts_state) def _update_dtr_state(self): """Set terminal status line: Data Terminal Ready""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError self._port_handle.DtrEnable = bool(self._dtr_state) @property def cts(self): """Read terminal status line: Clear To Send""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError return self._port_handle.CtsHolding @property def dsr(self): """Read terminal status line: Data Set Ready""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError return self._port_handle.DsrHolding @property def ri(self): """Read terminal status line: Ring Indicator""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError #~ return self._port_handle.XXX return False # XXX an error would be better @@ -246,7 +244,7 @@ def ri(self): def cd(self): """Read terminal status line: Carrier Detect""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError return self._port_handle.CDHolding # - - platform specific - - - - diff --git a/serial/serialjava.py b/serial/serialjava.py index 0789a780..7bd5b3e0 100644 --- a/serial/serialjava.py +++ b/serial/serialjava.py @@ -7,8 +7,6 @@ # # SPDX-License-Identifier: BSD-3-Clause -from __future__ import absolute_import - from serial.serialutil import * @@ -152,7 +150,7 @@ def close(self): def in_waiting(self): """Return the number of characters currently in the input buffer.""" if not self.sPort: - raise PortNotOpenError() + raise portNotOpenError return self._instream.available() def read(self, size=1): @@ -162,7 +160,7 @@ def read(self, size=1): until the requested number of bytes is read. """ if not self.sPort: - raise PortNotOpenError() + raise portNotOpenError read = bytearray() if size > 0: while len(read) < size: @@ -177,7 +175,7 @@ def read(self, size=1): def write(self, data): """Output the given string over the serial port.""" if not self.sPort: - raise PortNotOpenError() + raise portNotOpenError if not isinstance(data, (bytes, bytearray)): raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data))) self._outstream.write(data) @@ -186,7 +184,7 @@ def write(self, data): def reset_input_buffer(self): """Clear input buffer, discarding all that is in the buffer.""" if not self.sPort: - raise PortNotOpenError() + raise portNotOpenError self._instream.skip(self._instream.available()) def reset_output_buffer(self): @@ -195,57 +193,57 @@ def reset_output_buffer(self): discarding all that is in the buffer. """ if not self.sPort: - raise PortNotOpenError() + raise portNotOpenError self._outstream.flush() def send_break(self, duration=0.25): """Send break condition. Timed, returns to idle state after given duration.""" if not self.sPort: - raise PortNotOpenError() + raise portNotOpenError self.sPort.sendBreak(duration*1000.0) def _update_break_state(self): """Set break: Controls TXD. When active, to transmitting is possible.""" if self.fd is None: - raise PortNotOpenError() + raise portNotOpenError raise SerialException("The _update_break_state function is not implemented in java.") def _update_rts_state(self): """Set terminal status line: Request To Send""" if not self.sPort: - raise PortNotOpenError() + raise portNotOpenError self.sPort.setRTS(self._rts_state) def _update_dtr_state(self): """Set terminal status line: Data Terminal Ready""" if not self.sPort: - raise PortNotOpenError() + raise portNotOpenError self.sPort.setDTR(self._dtr_state) @property def cts(self): """Read terminal status line: Clear To Send""" if not self.sPort: - raise PortNotOpenError() + raise portNotOpenError self.sPort.isCTS() @property def dsr(self): """Read terminal status line: Data Set Ready""" if not self.sPort: - raise PortNotOpenError() + raise portNotOpenError self.sPort.isDSR() @property def ri(self): """Read terminal status line: Ring Indicator""" if not self.sPort: - raise PortNotOpenError() + raise portNotOpenError self.sPort.isRI() @property def cd(self): """Read terminal status line: Carrier Detect""" if not self.sPort: - raise PortNotOpenError() + raise portNotOpenError self.sPort.isCD() diff --git a/serial/serialposix.py b/serial/serialposix.py index 51e6a108..afe50622 100644 --- a/serial/serialposix.py +++ b/serial/serialposix.py @@ -3,7 +3,7 @@ # backend for serial IO for POSIX compatible systems, like Linux, OSX # # This file is part of pySerial. https://github.com/pyserial/pyserial -# (C) 2001-2020 Chris Liechti +# (C) 2001-2016 Chris Liechti # # SPDX-License-Identifier: BSD-3-Clause # @@ -26,8 +26,6 @@ # - aix (AIX) /dev/tty%d -from __future__ import absolute_import - # pylint: disable=abstract-method import errno import fcntl @@ -39,7 +37,7 @@ import serial from serial.serialutil import SerialBase, SerialException, to_bytes, \ - PortNotOpenError, SerialTimeoutException, Timeout + portNotOpenError, writeTimeoutError, Timeout class PlatformSpecificBase(object): @@ -51,18 +49,6 @@ def _set_special_baudrate(self, baudrate): def _set_rs485_mode(self, rs485_settings): raise NotImplementedError('RS485 not supported on this platform') - def set_low_latency_mode(self, low_latency_settings): - raise NotImplementedError('Low latency not supported on this platform') - - def _update_break_state(self): - """\ - Set break: Controls TXD. When active, no transmitting is possible. - """ - if self._break_state: - fcntl.ioctl(self.fd, TIOCSBRK) - else: - fcntl.ioctl(self.fd, TIOCCBRK) - # some systems support an extra flag to enable the two in POSIX unsupported # paritiy settings for MARK and SPACE @@ -127,24 +113,6 @@ class PlatformSpecific(PlatformSpecificBase): 4000000: 0o010017 } - def set_low_latency_mode(self, low_latency_settings): - buf = array.array('i', [0] * 32) - - try: - # get serial_struct - fcntl.ioctl(self.fd, termios.TIOCGSERIAL, buf) - - # set or unset ASYNC_LOW_LATENCY flag - if low_latency_settings: - buf[4] |= 0x2000 - else: - buf[4] &= ~0x2000 - - # set serial_struct - fcntl.ioctl(self.fd, termios.TIOCSSERIAL, buf) - except IOError as e: - raise ValueError('Failed to update ASYNC_LOW_LATENCY flag to {}: {}'.format(low_latency_settings, e)) - def _set_special_baudrate(self, baudrate): # right size is 44 on x86_64, allow for some growth buf = array.array('i', [0] * 64) @@ -214,9 +182,6 @@ class PlatformSpecific(PlatformSpecificBase): class PlatformSpecific(PlatformSpecificBase): osx_version = os.uname()[2].split('.') - TIOCSBRK = 0x2000747B # _IO('t', 123) - TIOCCBRK = 0x2000747A # _IO('t', 122) - # Tiger or above can support arbitrary serial speeds if int(osx_version[0]) >= 8: def _set_special_baudrate(self, baudrate): @@ -224,15 +189,6 @@ def _set_special_baudrate(self, baudrate): buf = array.array('i', [baudrate]) fcntl.ioctl(self.fd, IOSSIOSPEED, buf, 1) - def _update_break_state(self): - """\ - Set break: Controls TXD. When active, no transmitting is possible. - """ - if self._break_state: - fcntl.ioctl(self.fd, PlatformSpecific.TIOCSBRK) - else: - fcntl.ioctl(self.fd, PlatformSpecific.TIOCCBRK) - elif plat[:3] == 'bsd' or \ plat[:7] == 'freebsd' or \ plat[:6] == 'netbsd' or \ @@ -248,19 +204,6 @@ class PlatformSpecific(PlatformSpecificBase): # a literal value. BAUDRATE_CONSTANTS = ReturnBaudrate() - TIOCSBRK = 0x2000747B # _IO('t', 123) - TIOCCBRK = 0x2000747A # _IO('t', 122) - - - def _update_break_state(self): - """\ - Set break: Controls TXD. When active, no transmitting is possible. - """ - if self._break_state: - fcntl.ioctl(self.fd, PlatformSpecific.TIOCSBRK) - else: - fcntl.ioctl(self.fd, PlatformSpecific.TIOCCBRK) - else: class PlatformSpecific(PlatformSpecificBase): pass @@ -405,15 +348,8 @@ def _reconfigure_port(self, force_update=False): ispeed = ospeed = self.BAUDRATE_CONSTANTS[self._baudrate] except KeyError: #~ raise ValueError('Invalid baud rate: %r' % self._baudrate) - - # See if BOTHER is defined for this platform; if it is, use - # this for a speed not defined in the baudrate constants list. - try: - ispeed = ospeed = BOTHER - except NameError: - # may need custom baud rate, it isn't in our list. - ispeed = ospeed = getattr(termios, 'B38400') - + # may need custom baud rate, it isn't in our list. + ispeed = ospeed = getattr(termios, 'B38400') try: custom_baud = int(self._baudrate) # store for later except ValueError: @@ -539,7 +475,7 @@ def read(self, size=1): until the requested number of bytes is read. """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError read = bytearray() timeout = Timeout(self._timeout) while len(read) < size: @@ -555,6 +491,16 @@ def read(self, size=1): if not ready: break # timeout buf = os.read(self.fd, size - len(read)) + # read should always return some data as select reported it was + # ready to read when we get to this point. + if not buf: + # Disconnected devices, at least on Linux, show the + # behavior that they are always ready to read immediately + # but reading returns nothing. + raise SerialException( + 'device reports readiness to read but returned no data ' + '(device disconnected or multiple access on port?)') + read.extend(buf) except OSError as e: # this is for Python 3.x where select.error is a subclass of # OSError ignore BlockingIOErrors and EINTR. other errors are shown @@ -567,18 +513,6 @@ def read(self, size=1): # see also http://www.python.org/dev/peps/pep-3151/#select if e[0] not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR): raise SerialException('read failed: {}'.format(e)) - else: - # read should always return some data as select reported it was - # ready to read when we get to this point. - if not buf: - # Disconnected devices, at least on Linux, show the - # behavior that they are always ready to read immediately - # but reading returns nothing. - raise SerialException( - 'device reports readiness to read but returned no data ' - '(device disconnected or multiple access on port?)') - read.extend(buf) - if timeout.expired(): break return bytes(read) @@ -594,7 +528,7 @@ def cancel_write(self): def write(self, data): """Output the given byte string over the serial port.""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError d = to_bytes(data) tx_len = length = len(d) timeout = Timeout(self._write_timeout) @@ -609,13 +543,13 @@ def write(self, data): # when timeout is set, use select to wait for being ready # with the time left as timeout if timeout.expired(): - raise SerialTimeoutException('Write timeout') + raise writeTimeoutError abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], timeout.time_left()) if abort: os.read(self.pipe_abort_write_r, 1000) break if not ready: - raise SerialTimeoutException('Write timeout') + raise writeTimeoutError else: assert timeout.time_left() is None # wait for write operation @@ -642,7 +576,7 @@ def write(self, data): if e[0] not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR): raise SerialException('write failed: {}'.format(e)) if not timeout.is_non_blocking and timeout.expired(): - raise SerialTimeoutException('Write timeout') + raise writeTimeoutError return length - len(d) def flush(self): @@ -651,13 +585,13 @@ def flush(self): is written. """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError termios.tcdrain(self.fd) def reset_input_buffer(self): """Clear input buffer, discarding all that is in the buffer.""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError termios.tcflush(self.fd, termios.TCIFLUSH) def reset_output_buffer(self): @@ -666,7 +600,7 @@ def reset_output_buffer(self): that is in the buffer. """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError termios.tcflush(self.fd, termios.TCOFLUSH) def send_break(self, duration=0.25): @@ -675,9 +609,18 @@ def send_break(self, duration=0.25): duration. """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError termios.tcsendbreak(self.fd, int(duration / 0.25)) + def _update_break_state(self): + """\ + Set break: Controls TXD. When active, no transmitting is possible. + """ + if self._break_state: + fcntl.ioctl(self.fd, TIOCSBRK) + else: + fcntl.ioctl(self.fd, TIOCCBRK) + def _update_rts_state(self): """Set terminal status line: Request To Send""" if self._rts_state: @@ -696,7 +639,7 @@ def _update_dtr_state(self): def cts(self): """Read terminal status line: Clear To Send""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str) return struct.unpack('I', s)[0] & TIOCM_CTS != 0 @@ -704,7 +647,7 @@ def cts(self): def dsr(self): """Read terminal status line: Data Set Ready""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str) return struct.unpack('I', s)[0] & TIOCM_DSR != 0 @@ -712,7 +655,7 @@ def dsr(self): def ri(self): """Read terminal status line: Ring Indicator""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str) return struct.unpack('I', s)[0] & TIOCM_RI != 0 @@ -720,7 +663,7 @@ def ri(self): def cd(self): """Read terminal status line: Carrier Detect""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str) return struct.unpack('I', s)[0] & TIOCM_CD != 0 @@ -739,7 +682,7 @@ def fileno(self): WARNING: this function is not portable to different platforms! """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError return self.fd def set_input_flow_control(self, enable=True): @@ -749,7 +692,7 @@ def set_input_flow_control(self, enable=True): WARNING: this function is not portable to different platforms! """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError if enable: termios.tcflow(self.fd, termios.TCION) else: @@ -762,7 +705,7 @@ def set_output_flow_control(self, enable=True): WARNING: this function is not portable to different platforms! """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError if enable: termios.tcflow(self.fd, termios.TCOON) else: @@ -788,30 +731,23 @@ def read(self, size=1): until the requested number of bytes is read. """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError read = bytearray() - timeout = Timeout(self._timeout) poll = select.poll() poll.register(self.fd, select.POLLIN | select.POLLERR | select.POLLHUP | select.POLLNVAL) - poll.register(self.pipe_abort_read_r, select.POLLIN | select.POLLERR | select.POLLHUP | select.POLLNVAL) if size > 0: while len(read) < size: # print "\tread(): size",size, "have", len(read) #debug # wait until device becomes ready to read (or something fails) - for fd, event in poll.poll(None if timeout.is_infinite else (timeout.time_left() * 1000)): - if fd == self.pipe_abort_read_r: - break + for fd, event in poll.poll(self._timeout * 1000): if event & (select.POLLERR | select.POLLHUP | select.POLLNVAL): raise SerialException('device reports error (poll)') # we don't care if it is select.POLLIN or timeout, that's # handled below - if fd == self.pipe_abort_read_r: - os.read(self.pipe_abort_read_r, 1000) - break buf = os.read(self.fd, size - len(read)) read.extend(buf) - if timeout.expired() \ - or (self._inter_byte_timeout is not None and self._inter_byte_timeout > 0) and not buf: + if ((self._timeout is not None and self._timeout >= 0) or + (self._inter_byte_timeout is not None and self._inter_byte_timeout > 0)) and not buf: break # early abort on timeout return bytes(read) @@ -823,9 +759,6 @@ class VTIMESerial(Serial): the error handling is degraded. Overall timeout is disabled when inter-character timeout is used. - - Note that this implementation does NOT support cancel_read(), it will - just ignore that. """ def _reconfigure_port(self, force_update=True): @@ -865,7 +798,7 @@ def read(self, size=1): until the requested number of bytes is read. """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError read = bytearray() while len(read) < size: buf = os.read(self.fd, size - len(read)) diff --git a/serial/serialutil.py b/serial/serialutil.py index 789219e9..7d51752f 100644 --- a/serial/serialutil.py +++ b/serial/serialutil.py @@ -3,12 +3,10 @@ # Base class and support functions used by various backends. # # This file is part of pySerial. https://github.com/pyserial/pyserial -# (C) 2001-2020 Chris Liechti +# (C) 2001-2016 Chris Liechti # # SPDX-License-Identifier: BSD-3-Clause -from __future__ import absolute_import - import io import time @@ -97,10 +95,8 @@ class SerialTimeoutException(SerialException): """Write timeouts give an exception""" -class PortNotOpenError(SerialException): - """Port is not open""" - def __init__(self): - super(PortNotOpenError, self).__init__('Attempting to use a port that is not open') +writeTimeoutError = SerialTimeoutException('Write timeout') +portNotOpenError = SerialException('Attempting to use a port that is not open') class Timeout(object): @@ -561,7 +557,7 @@ def readinto(self, b): # context manager def __enter__(self): - if self._port is not None and not self.is_open: + if not self.is_open: self.open() return self @@ -576,7 +572,7 @@ def send_break(self, duration=0.25): duration. """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError self.break_condition = True time.sleep(duration) self.break_condition = False @@ -651,19 +647,19 @@ def read_all(self): """ return self.read(self.in_waiting) - def read_until(self, expected=LF, size=None): + def read_until(self, terminator=LF, size=None): """\ - Read until an expected sequence is found ('\n' by default), the size + Read until a termination sequence is found ('\n' by default), the size is exceeded or until timeout occurs. """ - lenterm = len(expected) + lenterm = len(terminator) line = bytearray() timeout = Timeout(self._timeout) while True: c = self.read(1) if c: line += c - if line[-lenterm:] == expected: + if line[-lenterm:] == terminator: break if size is not None and len(line) >= size: break diff --git a/serial/serialwin32.py b/serial/serialwin32.py index e7da929a..7b889993 100644 --- a/serial/serialwin32.py +++ b/serial/serialwin32.py @@ -2,22 +2,20 @@ # # backend for Windows ("win32" incl. 32/64 bit support) # -# (C) 2001-2020 Chris Liechti +# (C) 2001-2015 Chris Liechti # # This file is part of pySerial. https://github.com/pyserial/pyserial # SPDX-License-Identifier: BSD-3-Clause # # Initial patch to use ctypes by Giovanni Bajo -from __future__ import absolute_import - # pylint: disable=invalid-name,too-few-public-methods import ctypes import time from serial import win32 import serial -from serial.serialutil import SerialBase, SerialException, to_bytes, PortNotOpenError, SerialTimeoutException +from serial.serialutil import SerialBase, SerialException, to_bytes, portNotOpenError, writeTimeoutError class Serial(SerialBase): @@ -184,23 +182,23 @@ def _reconfigure_port(self): # XXX verify if platform really does not have a setting for those if not self._rs485_mode.rts_level_for_tx: raise ValueError( - 'Unsupported value for RS485Settings.rts_level_for_tx: {!r} (only True is allowed)'.format( + 'Unsupported value for RS485Settings.rts_level_for_tx: {!r}'.format( self._rs485_mode.rts_level_for_tx,)) if self._rs485_mode.rts_level_for_rx: raise ValueError( - 'Unsupported value for RS485Settings.rts_level_for_rx: {!r} (only False is allowed)'.format( + 'Unsupported value for RS485Settings.rts_level_for_rx: {!r}'.format( self._rs485_mode.rts_level_for_rx,)) if self._rs485_mode.delay_before_tx is not None: raise ValueError( - 'Unsupported value for RS485Settings.delay_before_tx: {!r} (only None is allowed)'.format( + 'Unsupported value for RS485Settings.delay_before_tx: {!r}'.format( self._rs485_mode.delay_before_tx,)) if self._rs485_mode.delay_before_rx is not None: raise ValueError( - 'Unsupported value for RS485Settings.delay_before_rx: {!r} (only None is allowed)'.format( + 'Unsupported value for RS485Settings.delay_before_rx: {!r}'.format( self._rs485_mode.delay_before_rx,)) if self._rs485_mode.loopback: raise ValueError( - 'Unsupported value for RS485Settings.loopback: {!r} (only False is allowed)'.format( + 'Unsupported value for RS485Settings.loopback: {!r}'.format( self._rs485_mode.loopback,)) comDCB.fRtsControl = win32.RTS_CONTROL_TOGGLE comDCB.fOutxCtsFlow = 0 @@ -266,7 +264,7 @@ def read(self, size=1): until the requested number of bytes is read. """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError if size > 0: win32.ResetEvent(self._overlapped_read.hEvent) flags = win32.DWORD() @@ -303,7 +301,7 @@ def read(self, size=1): def write(self, data): """Output the given byte string over the serial port.""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError #~ if not isinstance(data, (bytes, bytearray)): #~ raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data))) # convert data (needed in case of memoryview instance: Py 3.1 io lib), ctypes doesn't like memoryview @@ -322,7 +320,7 @@ def write(self, data): if win32.GetLastError() == win32.ERROR_OPERATION_ABORTED: return n.value # canceled IO is no error if n.value != len(data): - raise SerialTimeoutException('Write timeout') + raise writeTimeoutError return n.value else: errorcode = win32.ERROR_SUCCESS if success else win32.GetLastError() @@ -351,7 +349,7 @@ def flush(self): def reset_input_buffer(self): """Clear input buffer, discarding all that is in the buffer.""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError win32.PurgeComm(self._port_handle, win32.PURGE_RXCLEAR | win32.PURGE_RXABORT) def reset_output_buffer(self): @@ -360,13 +358,13 @@ def reset_output_buffer(self): that is in the buffer. """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError win32.PurgeComm(self._port_handle, win32.PURGE_TXCLEAR | win32.PURGE_TXABORT) def _update_break_state(self): """Set break: Controls TXD. When active, to transmitting is possible.""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError if self._break_state: win32.SetCommBreak(self._port_handle) else: @@ -388,7 +386,7 @@ def _update_dtr_state(self): def _GetCommModemStatus(self): if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError stat = win32.DWORD() win32.GetCommModemStatus(self._port_handle, ctypes.byref(stat)) return stat.value @@ -418,7 +416,7 @@ def cd(self): def set_buffer_size(self, rx_size=4096, tx_size=None): """\ Recommend a buffer size to the driver (device driver can ignore this - value). Must be called after the port is opened. + value). Must be called before the port is opened. """ if tx_size is None: tx_size = rx_size @@ -432,7 +430,7 @@ def set_output_flow_control(self, enable=True): WARNING: this function is not portable to different platforms! """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError if enable: win32.EscapeCommFunction(self._port_handle, win32.SETXON) else: diff --git a/serial/threaded/__init__.py b/serial/threaded/__init__.py index b8940b6d..74b69249 100644 --- a/serial/threaded/__init__.py +++ b/serial/threaded/__init__.py @@ -9,8 +9,6 @@ """\ Support threading with serial ports. """ -from __future__ import absolute_import - import serial import threading @@ -203,7 +201,7 @@ def run(self): break else: if data: - # make a separated try-except for called user code + # make a separated try-except for called used code try: self.protocol.data_received(data) except Exception as e: @@ -216,7 +214,7 @@ def run(self): def write(self, data): """Thread safe writing (uses lock)""" with self._lock: - return self.serial.write(data) + self.serial.write(data) def close(self): """Close the serial port and exit reader thread (uses lock)""" diff --git a/serial/tools/hexlify_codec.py b/serial/tools/hexlify_codec.py index bd8f6b0d..1371da2c 100644 --- a/serial/tools/hexlify_codec.py +++ b/serial/tools/hexlify_codec.py @@ -18,8 +18,6 @@ """ -from __future__ import absolute_import - import codecs import serial diff --git a/serial/tools/list_ports.py b/serial/tools/list_ports.py index 0d7e3d41..827e81f9 100644 --- a/serial/tools/list_ports.py +++ b/serial/tools/list_ports.py @@ -16,8 +16,6 @@ based on their descriptions or hardware ID. """ -from __future__ import absolute_import - import sys import os import re diff --git a/serial/tools/list_ports_common.py b/serial/tools/list_ports_common.py index 617f3dc1..145e63ee 100644 --- a/serial/tools/list_ports_common.py +++ b/serial/tools/list_ports_common.py @@ -7,13 +7,9 @@ # (C) 2015 Chris Liechti # # SPDX-License-Identifier: BSD-3-Clause - -from __future__ import absolute_import - import re import glob import os -import os.path def numsplit(text): @@ -35,9 +31,9 @@ def numsplit(text): class ListPortInfo(object): """Info collection base class for serial ports""" - def __init__(self, device, skip_link_detection=False): + def __init__(self, device=None): self.device = device - self.name = os.path.basename(device) + self.name = None self.description = 'n/a' self.hwid = 'n/a' # USB specific data @@ -49,7 +45,7 @@ def __init__(self, device, skip_link_detection=False): self.product = None self.interface = None # special handling for links - if not skip_link_detection and device is not None and os.path.islink(device): + if device is not None and os.path.islink(device): self.hwid = 'LINK={}'.format(os.path.realpath(device)) def usb_description(self): @@ -75,16 +71,9 @@ def apply_usb_info(self): self.hwid = self.usb_info() def __eq__(self, other): - return isinstance(other, ListPortInfo) and self.device == other.device - - def __hash__(self): - return hash(self.device) + return self.device == other.device def __lt__(self, other): - if not isinstance(other, ListPortInfo): - raise TypeError('unorderable types: {}() and {}()'.format( - type(self).__name__, - type(other).__name__)) return numsplit(self.device) < numsplit(other.device) def __str__(self): @@ -101,7 +90,6 @@ def __getitem__(self, index): else: raise IndexError('{} > 2'.format(index)) - # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def list_links(devices): """\ @@ -114,7 +102,6 @@ def list_links(devices): links.append(device) return links - # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # test if __name__ == '__main__': diff --git a/serial/tools/list_ports_linux.py b/serial/tools/list_ports_linux.py index c8c1cfc0..4be27cdf 100644 --- a/serial/tools/list_ports_linux.py +++ b/serial/tools/list_ports_linux.py @@ -8,8 +8,6 @@ # # SPDX-License-Identifier: BSD-3-Clause -from __future__ import absolute_import - import glob import os from serial.tools import list_ports_common @@ -26,6 +24,7 @@ def __init__(self, device): is_link = True else: is_link = False + self.name = os.path.basename(device) self.usb_device_path = None if os.path.exists('/sys/class/tty/{}/device'.format(self.name)): self.device_path = os.path.realpath('/sys/class/tty/{}/device'.format(self.name)) @@ -59,7 +58,7 @@ def __init__(self, device): self.manufacturer = self.read_line(self.usb_device_path, 'manufacturer') self.product = self.read_line(self.usb_device_path, 'product') - self.interface = self.read_line(self.usb_interface_path, 'interface') + self.interface = self.read_line(self.device_path, 'interface') if self.subsystem in ('usb', 'usb-serial'): self.apply_usb_info() @@ -91,7 +90,6 @@ def read_line(self, *args): def comports(include_links=False): devices = glob.glob('/dev/ttyS*') # built-in serial ports devices.extend(glob.glob('/dev/ttyUSB*')) # usb-serial with own driver - devices.extend(glob.glob('/dev/ttyXRUSB*')) # xr-usb-serial port exar (DELL Edge 3001) devices.extend(glob.glob('/dev/ttyACM*')) # usb-serial with CDC-ACM profile devices.extend(glob.glob('/dev/ttyAMA*')) # ARM internal port (raspi) devices.extend(glob.glob('/dev/rfcomm*')) # BT serial devices @@ -105,5 +103,5 @@ def comports(include_links=False): # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # test if __name__ == '__main__': - for info in sorted(comports()): - print("{0}: {0.subsystem}".format(info)) + for port, desc, hwid in sorted(comports()): + print("{}: {} [{}]".format(port, desc, hwid)) diff --git a/serial/tools/list_ports_osx.py b/serial/tools/list_ports_osx.py index 0b73fa23..79ce4f1d 100644 --- a/serial/tools/list_ports_osx.py +++ b/serial/tools/list_ports_osx.py @@ -7,7 +7,7 @@ # and modifications by cliechti, hoihu, hardkrash # # This file is part of pySerial. https://github.com/pyserial/pyserial -# (C) 2013-2020 +# (C) 2013-2015 # # SPDX-License-Identifier: BSD-3-Clause @@ -21,53 +21,37 @@ # Also see the 'IORegistryExplorer' for an idea of what we are actually searching -from __future__ import absolute_import - import ctypes +import ctypes.util from serial.tools import list_ports_common -iokit = ctypes.cdll.LoadLibrary('/System/Library/Frameworks/IOKit.framework/IOKit') -cf = ctypes.cdll.LoadLibrary('/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation') +iokit = ctypes.cdll.LoadLibrary(ctypes.util.find_library('IOKit')) +cf = ctypes.cdll.LoadLibrary(ctypes.util.find_library('CoreFoundation')) kIOMasterPortDefault = ctypes.c_void_p.in_dll(iokit, "kIOMasterPortDefault") kCFAllocatorDefault = ctypes.c_void_p.in_dll(cf, "kCFAllocatorDefault") kCFStringEncodingMacRoman = 0 -kCFStringEncodingUTF8 = 0x08000100 - -# defined in `IOKit/usb/USBSpec.h` -kUSBVendorString = 'USB Vendor Name' -kUSBSerialNumberString = 'USB Serial Number' - -# `io_name_t` defined as `typedef char io_name_t[128];` -# in `device/device_types.h` -io_name_size = 128 - -# defined in `mach/kern_return.h` -KERN_SUCCESS = 0 -# kern_return_t defined as `typedef int kern_return_t;` in `mach/i386/kern_return.h` -kern_return_t = ctypes.c_int iokit.IOServiceMatching.restype = ctypes.c_void_p iokit.IOServiceGetMatchingServices.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p] -iokit.IOServiceGetMatchingServices.restype = kern_return_t +iokit.IOServiceGetMatchingServices.restype = ctypes.c_void_p iokit.IORegistryEntryGetParentEntry.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p] -iokit.IOServiceGetMatchingServices.restype = kern_return_t iokit.IORegistryEntryCreateCFProperty.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint32] iokit.IORegistryEntryCreateCFProperty.restype = ctypes.c_void_p iokit.IORegistryEntryGetPath.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p] -iokit.IORegistryEntryGetPath.restype = kern_return_t +iokit.IORegistryEntryGetPath.restype = ctypes.c_void_p iokit.IORegistryEntryGetName.argtypes = [ctypes.c_void_p, ctypes.c_void_p] -iokit.IORegistryEntryGetName.restype = kern_return_t +iokit.IORegistryEntryGetName.restype = ctypes.c_void_p iokit.IOObjectGetClass.argtypes = [ctypes.c_void_p, ctypes.c_void_p] -iokit.IOObjectGetClass.restype = kern_return_t +iokit.IOObjectGetClass.restype = ctypes.c_void_p iokit.IOObjectRelease.argtypes = [ctypes.c_void_p] @@ -78,9 +62,6 @@ cf.CFStringGetCStringPtr.argtypes = [ctypes.c_void_p, ctypes.c_uint32] cf.CFStringGetCStringPtr.restype = ctypes.c_char_p -cf.CFStringGetCString.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_long, ctypes.c_uint32] -cf.CFStringGetCString.restype = ctypes.c_bool - cf.CFNumberGetValue.argtypes = [ctypes.c_void_p, ctypes.c_uint32, ctypes.c_void_p] cf.CFNumberGetValue.restype = ctypes.c_void_p @@ -105,8 +86,8 @@ def get_string_property(device_type, property): """ key = cf.CFStringCreateWithCString( kCFAllocatorDefault, - property.encode("utf-8"), - kCFStringEncodingUTF8) + property.encode("mac_roman"), + kCFStringEncodingMacRoman) CFContainer = iokit.IORegistryEntryCreateCFProperty( device_type, @@ -118,12 +99,7 @@ def get_string_property(device_type, property): if CFContainer: output = cf.CFStringGetCStringPtr(CFContainer, 0) if output is not None: - output = output.decode('utf-8') - else: - buffer = ctypes.create_string_buffer(io_name_size); - success = cf.CFStringGetCString(CFContainer, ctypes.byref(buffer), io_name_size, kCFStringEncodingUTF8) - if success: - output = buffer.value.decode('utf-8') + output = output.decode('mac_roman') cf.CFRelease(CFContainer) return output @@ -140,8 +116,8 @@ def get_int_property(device_type, property, cf_number_type): """ key = cf.CFStringCreateWithCString( kCFAllocatorDefault, - property.encode("utf-8"), - kCFStringEncodingUTF8) + property.encode("mac_roman"), + kCFStringEncodingMacRoman) CFContainer = iokit.IORegistryEntryCreateCFProperty( device_type, @@ -159,19 +135,12 @@ def get_int_property(device_type, property, cf_number_type): return number.value return None + def IORegistryEntryGetName(device): - devicename = ctypes.create_string_buffer(io_name_size); - res = iokit.IORegistryEntryGetName(device, ctypes.byref(devicename)) - if res != KERN_SUCCESS: - return None - # this works in python2 but may not be valid. Also I don't know if - # this encoding is guaranteed. It may be dependent on system locale. - return devicename.value.decode('utf-8') - -def IOObjectGetClass(device): - classname = ctypes.create_string_buffer(io_name_size) - iokit.IOObjectGetClass(device, ctypes.byref(classname)) - return classname.value + pathname = ctypes.create_string_buffer(100) # TODO: Is this ok? + iokit.IOObjectGetClass(device, ctypes.byref(pathname)) + return pathname.value + def GetParentDeviceByType(device, parent_type): """ Find the first parent of a device that implements the parent_type @@ -179,15 +148,15 @@ def GetParentDeviceByType(device, parent_type): @return Pointer to the parent type, or None if it was not found. """ # First, try to walk up the IOService tree to find a parent of this device that is a IOUSBDevice. - parent_type = parent_type.encode('utf-8') - while IOObjectGetClass(device) != parent_type: + parent_type = parent_type.encode('mac_roman') + while IORegistryEntryGetName(device) != parent_type: parent = ctypes.c_void_p() response = iokit.IORegistryEntryGetParentEntry( device, - "IOService".encode("utf-8"), + "IOService".encode("mac_roman"), ctypes.byref(parent)) # If we weren't able to find a parent for the device, we're done. - if response != KERN_SUCCESS: + if response != 0: return None device = parent return device @@ -201,7 +170,7 @@ def GetIOServicesByType(service_type): iokit.IOServiceGetMatchingServices( kIOMasterPortDefault, - iokit.IOServiceMatching(service_type.encode('utf-8')), + iokit.IOServiceMatching(service_type.encode('mac_roman')), ctypes.byref(serial_port_iterator)) services = [] @@ -275,12 +244,9 @@ def comports(include_links=False): # fetch some useful informations from properties info.vid = get_int_property(usb_device, "idVendor", kCFNumberSInt16Type) info.pid = get_int_property(usb_device, "idProduct", kCFNumberSInt16Type) - info.serial_number = get_string_property(usb_device, kUSBSerialNumberString) - # We know this is a usb device, so the - # IORegistryEntryName should always be aliased to the - # usb product name string descriptor. - info.product = IORegistryEntryGetName(usb_device) or 'n/a' - info.manufacturer = get_string_property(usb_device, kUSBVendorString) + info.serial_number = get_string_property(usb_device, "USB Serial Number") + info.product = get_string_property(usb_device, "USB Product Name") or 'n/a' + info.manufacturer = get_string_property(usb_device, "USB Vendor Name") locationID = get_int_property(usb_device, "locationID", kCFNumberSInt32Type) info.location = location_to_string(locationID) info.interface = search_for_locationID_in_interfaces(serial_interfaces, locationID) diff --git a/serial/tools/list_ports_posix.py b/serial/tools/list_ports_posix.py index 79bc8ed1..0d580b02 100644 --- a/serial/tools/list_ports_posix.py +++ b/serial/tools/list_ports_posix.py @@ -16,8 +16,6 @@ currently just identical to the port name. """ -from __future__ import absolute_import - import glob import sys import os diff --git a/serial/tools/list_ports_windows.py b/serial/tools/list_ports_windows.py index 0b4a5b1e..f28047be 100644 --- a/serial/tools/list_ports_windows.py +++ b/serial/tools/list_ports_windows.py @@ -8,8 +8,6 @@ # # SPDX-License-Identifier: BSD-3-Clause -from __future__ import absolute_import - # pylint: disable=invalid-name,too-few-public-methods import re import ctypes @@ -115,28 +113,14 @@ def __str__(self): RegCloseKey.restype = LONG RegQueryValueEx = advapi32.RegQueryValueExW -RegQueryValueEx.argtypes = [HKEY, LPCTSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD] +RegQueryValueEx.argtypes = [HKEY, LPCTSTR , LPDWORD, LPDWORD, LPBYTE, LPDWORD] RegQueryValueEx.restype = LONG -cfgmgr32 = ctypes.windll.LoadLibrary("Cfgmgr32") -CM_Get_Parent = cfgmgr32.CM_Get_Parent -CM_Get_Parent.argtypes = [PDWORD, DWORD, ULONG] -CM_Get_Parent.restype = LONG - -CM_Get_Device_IDW = cfgmgr32.CM_Get_Device_IDW -CM_Get_Device_IDW.argtypes = [DWORD, PTSTR, ULONG, ULONG] -CM_Get_Device_IDW.restype = LONG - -CM_MapCrToWin32Err = cfgmgr32.CM_MapCrToWin32Err -CM_MapCrToWin32Err.argtypes = [DWORD, DWORD] -CM_MapCrToWin32Err.restype = DWORD - DIGCF_PRESENT = 2 DIGCF_DEVICEINTERFACE = 16 INVALID_HANDLE_VALUE = 0 ERROR_INSUFFICIENT_BUFFER = 122 -ERROR_NOT_FOUND = 1168 SPDRP_HARDWAREID = 1 SPDRP_FRIENDLYNAME = 12 SPDRP_LOCATION_PATHS = 35 @@ -146,119 +130,19 @@ def __str__(self): KEY_READ = 0x20019 -MAX_USB_DEVICE_TREE_TRAVERSAL_DEPTH = 5 - - -def get_parent_serial_number(child_devinst, child_vid, child_pid, depth=0, last_serial_number=None): - """ Get the serial number of the parent of a device. - - Args: - child_devinst: The device instance handle to get the parent serial number of. - child_vid: The vendor ID of the child device. - child_pid: The product ID of the child device. - depth: The current iteration depth of the USB device tree. - """ - - # If the traversal depth is beyond the max, abandon attempting to find the serial number. - if depth > MAX_USB_DEVICE_TREE_TRAVERSAL_DEPTH: - return '' if not last_serial_number else last_serial_number - - # Get the parent device instance. - devinst = DWORD() - ret = CM_Get_Parent(ctypes.byref(devinst), child_devinst, 0) - - if ret: - win_error = CM_MapCrToWin32Err(DWORD(ret), DWORD(0)) - - # If there is no parent available, the child was the root device. We cannot traverse - # further. - if win_error == ERROR_NOT_FOUND: - return '' if not last_serial_number else last_serial_number - - raise ctypes.WinError(win_error) - - # Get the ID of the parent device and parse it for vendor ID, product ID, and serial number. - parentHardwareID = ctypes.create_unicode_buffer(250) - - ret = CM_Get_Device_IDW( - devinst, - parentHardwareID, - ctypes.sizeof(parentHardwareID) - 1, - 0) - - if ret: - raise ctypes.WinError(CM_MapCrToWin32Err(DWORD(ret), DWORD(0))) - - parentHardwareID_str = parentHardwareID.value - m = re.search(r'VID_([0-9a-f]{4})(&PID_([0-9a-f]{4}))?(&MI_(\d{2}))?(\\(.*))?', - parentHardwareID_str, - re.I) - - # return early if we have no matches (likely malformed serial, traversed too far) - if not m: - return '' if not last_serial_number else last_serial_number - - vid = None - pid = None - serial_number = None - if m.group(1): - vid = int(m.group(1), 16) - if m.group(3): - pid = int(m.group(3), 16) - if m.group(7): - serial_number = m.group(7) - - # store what we found as a fallback for malformed serial values up the chain - found_serial_number = serial_number - - # Check that the USB serial number only contains alpha-numeric characters. It may be a windows - # device ID (ephemeral ID). - if serial_number and not re.match(r'^\w+$', serial_number): - serial_number = None - - if not vid or not pid: - # If pid and vid are not available at this device level, continue to the parent. - return get_parent_serial_number(devinst, child_vid, child_pid, depth + 1, found_serial_number) - - if pid != child_pid or vid != child_vid: - # If the VID or PID has changed, we are no longer looking at the same physical device. The - # serial number is unknown. - return '' if not last_serial_number else last_serial_number - - # In this case, the vid and pid of the parent device are identical to the child. However, if - # there still isn't a serial number available, continue to the next parent. - if not serial_number: - return get_parent_serial_number(devinst, child_vid, child_pid, depth + 1, found_serial_number) - - # Finally, the VID and PID are identical to the child and a serial number is present, so return - # it. - return serial_number - - def iterate_comports(): """Return a generator that yields descriptions for serial ports""" - PortsGUIDs = (GUID * 8)() # so far only seen one used, so hope 8 are enough... - ports_guids_size = DWORD() + GUIDs = (GUID * 8)() # so far only seen one used, so hope 8 are enough... + guids_size = DWORD() if not SetupDiClassGuidsFromName( "Ports", - PortsGUIDs, - ctypes.sizeof(PortsGUIDs), - ctypes.byref(ports_guids_size)): - raise ctypes.WinError() - - ModemsGUIDs = (GUID * 8)() # so far only seen one used, so hope 8 are enough... - modems_guids_size = DWORD() - if not SetupDiClassGuidsFromName( - "Modem", - ModemsGUIDs, - ctypes.sizeof(ModemsGUIDs), - ctypes.byref(modems_guids_size)): + GUIDs, + ctypes.sizeof(GUIDs), + ctypes.byref(guids_size)): raise ctypes.WinError() - GUIDs = PortsGUIDs[:ports_guids_size.value] + ModemsGUIDs[:modems_guids_size.value] - # repeat for all possible GUIDs - for index in range(len(GUIDs)): + for index in range(guids_size.value): bInterfaceNumber = None g_hdi = SetupDiGetClassDevs( ctypes.byref(GUIDs[index]), @@ -322,26 +206,20 @@ def iterate_comports(): # stringify szHardwareID_str = szHardwareID.value - info = list_ports_common.ListPortInfo(port_name_buffer.value, skip_link_detection=True) + info = list_ports_common.ListPortInfo(port_name_buffer.value) # in case of USB, make a more readable string, similar to that form # that we also generate on other platforms if szHardwareID_str.startswith('USB'): - m = re.search(r'VID_([0-9a-f]{4})(&PID_([0-9a-f]{4}))?(&MI_(\d{2}))?(\\(.*))?', szHardwareID_str, re.I) + m = re.search(r'VID_([0-9a-f]{4})(&PID_([0-9a-f]{4}))?(&MI_(\d{2}))?(\\(\w+))?', szHardwareID_str, re.I) if m: info.vid = int(m.group(1), 16) if m.group(3): info.pid = int(m.group(3), 16) if m.group(5): bInterfaceNumber = int(m.group(5)) - - # Check that the USB serial number only contains alpha-numeric characters. It - # may be a windows device ID (ephemeral ID) for composite devices. - if m.group(7) and re.match(r'^\w+$', m.group(7)): + if m.group(7): info.serial_number = m.group(7) - else: - info.serial_number = get_parent_serial_number(devinfo.DevInst, info.vid, info.pid) - # calculate a location string loc_path_str = ctypes.create_unicode_buffer(250) if SetupDiGetDeviceRegistryProperty( diff --git a/serial/tools/miniterm.py b/serial/tools/miniterm.py index 2cceff63..88307c6e 100644 --- a/serial/tools/miniterm.py +++ b/serial/tools/miniterm.py @@ -3,12 +3,10 @@ # Very simple serial terminal # # This file is part of pySerial. https://github.com/pyserial/pyserial -# (C)2002-2020 Chris Liechti +# (C)2002-2015 Chris Liechti # # SPDX-License-Identifier: BSD-3-Clause -from __future__ import absolute_import - import codecs import os import sys @@ -88,7 +86,6 @@ def __exit__(self, *args, **kwargs): if os.name == 'nt': # noqa import msvcrt import ctypes - import platform class Out(object): """file-like wrapper that uses os.write""" @@ -103,52 +100,12 @@ def write(self, s): os.write(self.fd, s) class Console(ConsoleBase): - fncodes = { - ';': '\1bOP', # F1 - '<': '\1bOQ', # F2 - '=': '\1bOR', # F3 - '>': '\1bOS', # F4 - '?': '\1b[15~', # F5 - '@': '\1b[17~', # F6 - 'A': '\1b[18~', # F7 - 'B': '\1b[19~', # F8 - 'C': '\1b[20~', # F9 - 'D': '\1b[21~', # F10 - } - navcodes = { - 'H': '\x1b[A', # UP - 'P': '\x1b[B', # DOWN - 'K': '\x1b[D', # LEFT - 'M': '\x1b[C', # RIGHT - 'G': '\x1b[H', # HOME - 'O': '\x1b[F', # END - 'R': '\x1b[2~', # INSERT - 'S': '\x1b[3~', # DELETE - 'I': '\x1b[5~', # PGUP - 'Q': '\x1b[6~', # PGDN - } - def __init__(self): super(Console, self).__init__() self._saved_ocp = ctypes.windll.kernel32.GetConsoleOutputCP() self._saved_icp = ctypes.windll.kernel32.GetConsoleCP() ctypes.windll.kernel32.SetConsoleOutputCP(65001) ctypes.windll.kernel32.SetConsoleCP(65001) - # ANSI handling available through SetConsoleMode since Windows 10 v1511 - # https://en.wikipedia.org/wiki/ANSI_escape_code#cite_note-win10th2-1 - if platform.release() == '10' and int(platform.version().split('.')[2]) > 10586: - ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004 - import ctypes.wintypes as wintypes - if not hasattr(wintypes, 'LPDWORD'): # PY2 - wintypes.LPDWORD = ctypes.POINTER(wintypes.DWORD) - SetConsoleMode = ctypes.windll.kernel32.SetConsoleMode - GetConsoleMode = ctypes.windll.kernel32.GetConsoleMode - GetStdHandle = ctypes.windll.kernel32.GetStdHandle - mode = wintypes.DWORD() - GetConsoleMode(GetStdHandle(-11), ctypes.byref(mode)) - if (mode.value & ENABLE_VIRTUAL_TERMINAL_PROCESSING) == 0: - SetConsoleMode(GetStdHandle(-11), mode.value | ENABLE_VIRTUAL_TERMINAL_PROCESSING) - self._saved_cm = mode self.output = codecs.getwriter('UTF-8')(Out(sys.stdout.fileno()), 'replace') # the change of the code page is not propagated to Python, manually fix it sys.stderr = codecs.getwriter('UTF-8')(Out(sys.stderr.fileno()), 'replace') @@ -158,25 +115,14 @@ def __init__(self): def __del__(self): ctypes.windll.kernel32.SetConsoleOutputCP(self._saved_ocp) ctypes.windll.kernel32.SetConsoleCP(self._saved_icp) - try: - ctypes.windll.kernel32.SetConsoleMode(ctypes.windll.kernel32.GetStdHandle(-11), self._saved_cm) - except AttributeError: # in case no _saved_cm - pass def getkey(self): while True: z = msvcrt.getwch() if z == unichr(13): return unichr(10) - elif z is unichr(0) or z is unichr(0xe0): - try: - code = msvcrt.getwch() - if z is unichr(0): - return self.fncodes[code] - else: - return self.navcodes[code] - except KeyError: - pass + elif z in (unichr(0), unichr(0x0e)): # functions keys, ignore + msvcrt.getwch() else: return z @@ -329,12 +275,12 @@ class DebugIO(Transform): """Print what is sent and received""" def rx(self, text): - sys.stderr.write(' [RX:{!r}] '.format(text)) + sys.stderr.write(' [RX:{}] '.format(repr(text))) sys.stderr.flush() return text def tx(self, text): - sys.stderr.write(' [TX:{!r}] '.format(text)) + sys.stderr.write(' [TX:{}] '.format(repr(text))) sys.stderr.flush() return text @@ -401,8 +347,8 @@ def __init__(self, serial_instance, echo=False, eol='crlf', filters=()): self.eol = eol self.filters = filters self.update_transformations() - self.exit_character = unichr(0x1d) # GS/CTRL+] - self.menu_character = unichr(0x14) # Menu: CTRL+T + self.exit_character = 0x1d # GS/CTRL+] + self.menu_character = 0x14 # Menu: CTRL+T self.alive = None self._reader_alive = None self.receiver_thread = None @@ -574,7 +520,7 @@ def handle_menu_key(self, c): elif c == '\x06': # CTRL+F -> edit filters self.change_filter() elif c == '\x0c': # CTRL+L -> EOL mode - modes = list(EOL_TRANSFORMATIONS) # keys + modes = list(EOL_TRANSFORMATIONS) # keys eol = modes.index(self.eol) + 1 if eol >= len(modes): eol = 0 @@ -589,7 +535,7 @@ def handle_menu_key(self, c): #~ elif c == '\x0c': # CTRL+L -> cycle linefeed mode elif c in 'pP': # P -> change port self.change_port() - elif c in 'zZ': # S -> suspend / open port temporarily + elif c in 'sS': # S -> suspend / open port temporarily self.suspend_port() elif c in 'bB': # B -> change baudrate self.change_baudrate() @@ -629,8 +575,6 @@ def handle_menu_key(self, c): elif c in 'rR': # R -> change hardware flow control self.serial.rtscts = (c == 'R') self.dump_port_settings() - elif c in 'qQ': - self.stop() # Q -> exit app else: sys.stderr.write('--- unknown menu character {} --\n'.format(key_description(c))) @@ -668,7 +612,7 @@ def change_filter(self): if new_filters: for f in new_filters: if f not in TRANSFORMATIONS: - sys.stderr.write('--- unknown filter: {!r}\n'.format(f)) + sys.stderr.write('--- unknown filter: {}\n'.format(repr(f))) break else: self.filters = new_filters @@ -772,7 +716,7 @@ def get_help_text(self): return """ --- pySerial ({version}) - miniterm - help --- ---- {exit:8} Exit program (alias {menu} Q) +--- {exit:8} Exit program --- {menu:8} Menu escape key, followed by: --- Menu keys: --- {menu:7} Send the menu character itself to remote @@ -816,130 +760,123 @@ def main(default_port=None, default_baudrate=9600, default_rts=None, default_dtr import argparse parser = argparse.ArgumentParser( - description='Miniterm - A simple terminal program for the serial port.') + description="Miniterm - A simple terminal program for the serial port.") parser.add_argument( - 'port', + "port", nargs='?', - help='serial port name ("-" to show port list)', + help="serial port name ('-' to show port list)", default=default_port) parser.add_argument( - 'baudrate', + "baudrate", nargs='?', type=int, - help='set baud rate, default: %(default)s', + help="set baud rate, default: %(default)s", default=default_baudrate) - group = parser.add_argument_group('port settings') + group = parser.add_argument_group("port settings") group.add_argument( - '--parity', + "--parity", choices=['N', 'E', 'O', 'S', 'M'], type=lambda c: c.upper(), - help='set parity, one of {N E O S M}, default: N', + help="set parity, one of {N E O S M}, default: N", default='N') group.add_argument( - '--rtscts', - action='store_true', - help='enable RTS/CTS flow control (default off)', + "--rtscts", + action="store_true", + help="enable RTS/CTS flow control (default off)", default=False) group.add_argument( - '--xonxoff', - action='store_true', - help='enable software flow control (default off)', + "--xonxoff", + action="store_true", + help="enable software flow control (default off)", default=False) group.add_argument( - '--rts', + "--rts", type=int, - help='set initial RTS line state (possible values: 0, 1)', + help="set initial RTS line state (possible values: 0, 1)", default=default_rts) group.add_argument( - '--dtr', + "--dtr", type=int, - help='set initial DTR line state (possible values: 0, 1)', + help="set initial DTR line state (possible values: 0, 1)", default=default_dtr) group.add_argument( - '--non-exclusive', - dest='exclusive', - action='store_false', - help='disable locking for native ports', - default=True) - - group.add_argument( - '--ask', - action='store_true', - help='ask again for port when open fails', + "--ask", + action="store_true", + help="ask again for port when open fails", default=False) - group = parser.add_argument_group('data handling') + group = parser.add_argument_group("data handling") group.add_argument( - '-e', '--echo', - action='store_true', - help='enable local echo (default off)', + "-e", "--echo", + action="store_true", + help="enable local echo (default off)", default=False) group.add_argument( - '--encoding', - dest='serial_port_encoding', - metavar='CODEC', - help='set the encoding for the serial port (e.g. hexlify, Latin1, UTF-8), default: %(default)s', + "--encoding", + dest="serial_port_encoding", + metavar="CODEC", + help="set the encoding for the serial port (e.g. hexlify, Latin1, UTF-8), default: %(default)s", default='UTF-8') group.add_argument( - '-f', '--filter', - action='append', - metavar='NAME', - help='add text transformation', + "-f", "--filter", + action="append", + metavar="NAME", + help="add text transformation", default=[]) group.add_argument( - '--eol', + "--eol", choices=['CR', 'LF', 'CRLF'], type=lambda c: c.upper(), - help='end of line mode', + help="end of line mode", default='CRLF') group.add_argument( - '--raw', - action='store_true', - help='Do no apply any encodings/transformations', + "--raw", + action="store_true", + help="Do no apply any encodings/transformations", default=False) - group = parser.add_argument_group('hotkeys') + group = parser.add_argument_group("hotkeys") group.add_argument( - '--exit-char', + "--exit-char", type=int, metavar='NUM', - help='Unicode of special character that is used to exit the application, default: %(default)s', + help="Unicode of special character that is used to exit the application, default: %(default)s", default=0x1d) # GS/CTRL+] group.add_argument( - '--menu-char', + "--menu-char", type=int, metavar='NUM', - help='Unicode code of special character that is used to control miniterm (menu), default: %(default)s', + help="Unicode code of special character that is used to control miniterm (menu), default: %(default)s", default=0x14) # Menu: CTRL+T - group = parser.add_argument_group('diagnostics') + group = parser.add_argument_group("diagnostics") group.add_argument( - '-q', '--quiet', - action='store_true', - help='suppress non-error messages', + "-q", "--quiet", + action="store_true", + help="suppress non-error messages", default=False) group.add_argument( - '--develop', - action='store_true', - help='show Python traceback on error', + "--develop", + action="store_true", + help="show Python traceback on error", default=False) args = parser.parse_args() @@ -992,12 +929,9 @@ def main(default_port=None, default_baudrate=9600, default_rts=None, default_dtr sys.stderr.write('--- forcing RTS {}\n'.format('active' if args.rts else 'inactive')) serial_instance.rts = args.rts - if isinstance(serial_instance, serial.Serial): - serial_instance.exclusive = args.exclusive - serial_instance.open() except serial.SerialException as e: - sys.stderr.write('could not open port {!r}: {}\n'.format(args.port, e)) + sys.stderr.write('could not open port {}: {}\n'.format(repr(args.port), e)) if args.develop: raise if not args.ask: @@ -1033,7 +967,7 @@ def main(default_port=None, default_baudrate=9600, default_rts=None, default_dtr except KeyboardInterrupt: pass if not args.quiet: - sys.stderr.write('\n--- exit ---\n') + sys.stderr.write("\n--- exit ---\n") miniterm.join() miniterm.close() diff --git a/serial/urlhandler/protocol_alt.py b/serial/urlhandler/protocol_alt.py index 2e666ca7..c14a87e4 100644 --- a/serial/urlhandler/protocol_alt.py +++ b/serial/urlhandler/protocol_alt.py @@ -16,8 +16,6 @@ # use poll based implementation on Posix (Linux): # python -m serial.tools.miniterm alt:///dev/ttyUSB0?class=PosixPollSerial -from __future__ import absolute_import - try: import urlparse except ImportError: diff --git a/serial/urlhandler/protocol_hwgrep.py b/serial/urlhandler/protocol_hwgrep.py index 1a288c94..49bbebe3 100644 --- a/serial/urlhandler/protocol_hwgrep.py +++ b/serial/urlhandler/protocol_hwgrep.py @@ -20,8 +20,6 @@ # n= pick the N'th entry instead of the first one (numbering starts at 1) # skip_busy tries to open port to check if it is busy, fails on posix as ports are not locked! -from __future__ import absolute_import - import serial import serial.tools.list_ports diff --git a/serial/urlhandler/protocol_loop.py b/serial/urlhandler/protocol_loop.py index 2aeebfc7..7bf6cf90 100644 --- a/serial/urlhandler/protocol_loop.py +++ b/serial/urlhandler/protocol_loop.py @@ -6,15 +6,13 @@ # and it was so easy to implement ;-) # # This file is part of pySerial. https://github.com/pyserial/pyserial -# (C) 2001-2020 Chris Liechti +# (C) 2001-2015 Chris Liechti # # SPDX-License-Identifier: BSD-3-Clause # # URL format: loop://[option[/option...]] # options: # - "debug" print diagnostic messages -from __future__ import absolute_import - import logging import numbers import time @@ -27,7 +25,7 @@ except ImportError: import Queue as queue -from serial.serialutil import SerialBase, SerialException, to_bytes, iterbytes, SerialTimeoutException, PortNotOpenError +from serial.serialutil import SerialBase, SerialException, to_bytes, iterbytes, writeTimeoutError, portNotOpenError # map log level names to constants. used in from_url() LOGGER_LEVELS = { @@ -127,7 +125,7 @@ def from_url(self, url): def in_waiting(self): """Return the number of bytes currently in the input buffer.""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError if self.logger: # attention the logged value can differ from return value in # threaded environments... @@ -141,7 +139,7 @@ def read(self, size=1): until the requested number of bytes is read. """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError if self._timeout is not None and self._timeout != 0: timeout = time.time() + self._timeout else: @@ -181,7 +179,7 @@ def write(self, data): """ self._cancel_write = False if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError data = to_bytes(data) # calculate aprox time that would be used to send the data time_used_to_send = 10.0 * len(data) / self._baudrate @@ -195,7 +193,7 @@ def write(self, data): time_left -= 0.5 if self._cancel_write: return 0 # XXX - raise SerialTimeoutException('Write timeout') + raise writeTimeoutError for byte in iterbytes(data): self.queue.put(byte, timeout=self._write_timeout) return len(data) @@ -203,7 +201,7 @@ def write(self, data): def reset_input_buffer(self): """Clear input buffer, discarding all that is in the buffer.""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError if self.logger: self.logger.info('reset_input_buffer()') try: @@ -218,7 +216,7 @@ def reset_output_buffer(self): discarding all that is in the buffer. """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError if self.logger: self.logger.info('reset_output_buffer()') try: @@ -227,17 +225,6 @@ def reset_output_buffer(self): except queue.Empty: pass - @property - def out_waiting(self): - """Return how many bytes the in the outgoing buffer""" - if not self.is_open: - raise PortNotOpenError() - if self.logger: - # attention the logged value can differ from return value in - # threaded environments... - self.logger.debug('out_waiting -> {:d}'.format(self.queue.qsize())) - return self.queue.qsize() - def _update_break_state(self): """\ Set break: Controls TXD. When active, to transmitting is @@ -260,7 +247,7 @@ def _update_dtr_state(self): def cts(self): """Read terminal status line: Clear To Send""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError if self.logger: self.logger.info('CTS -> state of RTS ({!r})'.format(self._rts_state)) return self._rts_state @@ -276,7 +263,7 @@ def dsr(self): def ri(self): """Read terminal status line: Ring Indicator""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError if self.logger: self.logger.info('returning dummy for RI') return False @@ -285,7 +272,7 @@ def ri(self): def cd(self): """Read terminal status line: Carrier Detect""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError if self.logger: self.logger.info('returning dummy for CD') return True diff --git a/serial/urlhandler/protocol_rfc2217.py b/serial/urlhandler/protocol_rfc2217.py index ebeec3a5..1898803e 100644 --- a/serial/urlhandler/protocol_rfc2217.py +++ b/serial/urlhandler/protocol_rfc2217.py @@ -1,12 +1,10 @@ #! python # -# This is a thin wrapper to load the rfc2217 implementation. +# This is a thin wrapper to load the rfc2271 implementation. # # This file is part of pySerial. https://github.com/pyserial/pyserial # (C) 2011 Chris Liechti # # SPDX-License-Identifier: BSD-3-Clause -from __future__ import absolute_import - from serial.rfc2217 import Serial # noqa diff --git a/serial/urlhandler/protocol_socket.py b/serial/urlhandler/protocol_socket.py index 28884679..5c774155 100644 --- a/serial/urlhandler/protocol_socket.py +++ b/serial/urlhandler/protocol_socket.py @@ -16,8 +16,6 @@ # options: # - "debug" print diagnostic messages -from __future__ import absolute_import - import errno import logging import select @@ -29,7 +27,7 @@ import urllib.parse as urlparse from serial.serialutil import SerialBase, SerialException, to_bytes, \ - PortNotOpenError, SerialTimeoutException, Timeout + portNotOpenError, writeTimeoutError, Timeout # map log level names to constants. used in from_url() LOGGER_LEVELS = { @@ -136,7 +134,7 @@ def from_url(self, url): def in_waiting(self): """Return the number of bytes currently in the input buffer.""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError # Poll the socket to see if it is ready for reading. # If ready, at least one byte will be to read. lr, lw, lx = select.select([self._socket], [], [], 0) @@ -152,7 +150,7 @@ def read(self, size=1): until the requested number of bytes is read. """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError read = bytearray() timeout = Timeout(self._timeout) while len(read) < size: @@ -193,7 +191,7 @@ def write(self, data): closed. """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError d = to_bytes(data) tx_len = length = len(d) @@ -209,10 +207,10 @@ def write(self, data): # when timeout is set, use select to wait for being ready # with the time left as timeout if timeout.expired(): - raise SerialTimeoutException('Write timeout') + raise writeTimeoutError _, ready, _ = select.select([], [self._socket], [], timeout.time_left()) if not ready: - raise SerialTimeoutException('Write timeout') + raise writeTimeoutError else: assert timeout.time_left() is None # wait for write operation @@ -236,21 +234,20 @@ def write(self, data): if e[0] not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR): raise SerialException('write failed: {}'.format(e)) if not timeout.is_non_blocking and timeout.expired(): - raise SerialTimeoutException('Write timeout') + raise writeTimeoutError return length - len(d) def reset_input_buffer(self): """Clear input buffer, discarding all that is in the buffer.""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError # just use recv to remove input, while there is some ready = True while ready: ready, _, _ = select.select([self._socket], [], [], 0) try: - if ready: - ready = self._socket.recv(4096) + self._socket.recv(4096) except OSError as e: # this is for Python 3.x where select.error is a subclass of # OSError ignore BlockingIOErrors and EINTR. other errors are shown @@ -270,7 +267,7 @@ def reset_output_buffer(self): discarding all that is in the buffer. """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError if self.logger: self.logger.info('ignored reset_output_buffer') @@ -280,7 +277,7 @@ def send_break(self, duration=0.25): duration. """ if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError if self.logger: self.logger.info('ignored send_break({!r})'.format(duration)) @@ -304,7 +301,7 @@ def _update_dtr_state(self): def cts(self): """Read terminal status line: Clear To Send""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError if self.logger: self.logger.info('returning dummy for cts') return True @@ -313,7 +310,7 @@ def cts(self): def dsr(self): """Read terminal status line: Data Set Ready""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError if self.logger: self.logger.info('returning dummy for dsr') return True @@ -322,7 +319,7 @@ def dsr(self): def ri(self): """Read terminal status line: Ring Indicator""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError if self.logger: self.logger.info('returning dummy for ri') return False @@ -331,7 +328,7 @@ def ri(self): def cd(self): """Read terminal status line: Carrier Detect""" if not self.is_open: - raise PortNotOpenError() + raise portNotOpenError if self.logger: self.logger.info('returning dummy for cd)') return True diff --git a/serial/urlhandler/protocol_spy.py b/serial/urlhandler/protocol_spy.py index 92aaa2eb..34790100 100644 --- a/serial/urlhandler/protocol_spy.py +++ b/serial/urlhandler/protocol_spy.py @@ -20,8 +20,6 @@ # redirect output to an other terminal window on Posix (Linux): # python -m serial.tools.miniterm spy:///dev/ttyUSB0?dev=/dev/pts/14\&color -from __future__ import absolute_import - import sys import time diff --git a/serial/win32.py b/serial/win32.py index 157f4702..905ce0fd 100644 --- a/serial/win32.py +++ b/serial/win32.py @@ -9,8 +9,6 @@ # pylint: disable=invalid-name,too-few-public-methods,protected-access,too-many-instance-attributes -from __future__ import absolute_import - from ctypes import c_ulong, c_void_p, c_int64, c_char, \ WinDLL, sizeof, Structure, Union, POINTER from ctypes.wintypes import HANDLE @@ -181,10 +179,6 @@ class _COMMTIMEOUTS(Structure): WaitForSingleObject.restype = DWORD WaitForSingleObject.argtypes = [HANDLE, DWORD] -WaitCommEvent = _stdcall_libraries['kernel32'].WaitCommEvent -WaitCommEvent.restype = BOOL -WaitCommEvent.argtypes = [HANDLE, LPDWORD, LPOVERLAPPED] - CancelIoEx = _stdcall_libraries['kernel32'].CancelIoEx CancelIoEx.restype = BOOL CancelIoEx.argtypes = [HANDLE, LPOVERLAPPED] @@ -251,12 +245,6 @@ class _COMMTIMEOUTS(Structure): PURGE_RXCLEAR = 8 # Variable c_int INFINITE = 0xFFFFFFFF -CE_RXOVER = 0x0001 -CE_OVERRUN = 0x0002 -CE_RXPARITY = 0x0004 -CE_FRAME = 0x0008 -CE_BREAK = 0x0010 - class N11_OVERLAPPED4DOLLAR_48E(Union): pass