From 88254ff0c1596ea6cde739fae5afb270de0c94f5 Mon Sep 17 00:00:00 2001 From: jdstroy Date: Mon, 24 May 2021 23:40:46 -0700 Subject: [PATCH] Add detection for WSL1 in SerialInterface WSL1 shares the same (buggy) driver behavior as the underlying Windows/NT platform; thus, the RTS/RTR workaround applied to Windows and OS X applies to WSL1, too. --- meshtastic/__init__.py | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/meshtastic/__init__.py b/meshtastic/__init__.py index 505fdd6..b54a324 100644 --- a/meshtastic/__init__.py +++ b/meshtastic/__init__.py @@ -68,6 +68,8 @@ import base64 import platform import socket import timeago +import os +import stat from . import mesh_pb2, portnums_pb2, apponly_pb2, admin_pb2, environmental_measurement_pb2, remote_hardware_pb2, channel_pb2, radioconfig_pb2, util from .util import fixme, catchAndIgnore, stripnl, DeferredExecution, Timeout from .node import Node @@ -923,18 +925,40 @@ class SerialInterface(StreamInterface): # rts=False Needed to prevent TBEAMs resetting on OSX, because rts is connected to reset self.stream.port = devPath - # OS-X/Windows seems to have a bug in its serial driver. It ignores that we asked for no RTSCTS - # control and will always drive RTS either high or low (rather than letting the CP102 leave - # it as an open-collector floating pin). Since it is going to drive it anyways we want to make - # sure it is driven low, so that the TBEAM won't reset - # Linux does this properly, so don't apply this hack (because it makes the reset button not work) - if platform.system() != 'Linux': + + # HACK: If the platform driving the serial port is unable to leave the RTS pin in high-impedance + # mode, set RTS to false so that the device platform won't be reset spuriously. + # Linux does this properly, so don't apply this hack on Linux (because it makes the reset button not work). + if self._hostPlatformAlwaysDrivesUartRts(): self.stream.rts = False self.stream.open() StreamInterface.__init__( self, debugOut=debugOut, noProto=noProto, connectNow=connectNow) - + + """true if platform driving the serial port is Windows Subsystem for Linux 1.""" + def _isWsl1(self): + # WSL1 identifies itself as Linux, but has a special char device at /dev/lxss for use with session control, + # e.g. /init. We should treat WSL1 as Windows for the RTS-driving hack because the underlying platfrom + # serial driver for the CP21xx still exhibits the buggy behavior. + # WSL2 is not covered here, as it does not (as of 2021-May-25) support the appropriate functionality to + # share or pass-through serial ports. + try: + # Claims to be Linux, but has /dev/lxss; must be WSL 1 + return platform.system() == 'Linux' and stat.S_ISCHR(os.stat('/dev/lxss').st_mode); + except: + # Couldn't stat /dev/lxss special device; not WSL1 + return False; + + def _hostPlatformAlwaysDrivesUartRts(self): + # OS-X/Windows seems to have a bug in its CP21xx serial drivers. It ignores that we asked for no RTSCTS + # control and will always drive RTS either high or low (rather than letting the CP102 leave + # it as an open-collector floating pin). + # TODO: When WSL2 supports USB passthrough, this will get messier. If/when WSL2 gets virtual serial + # ports that "share" the Windows serial port (and thus the Windows drivers), this code will need to be + # updated to reflect that as well -- or if T-Beams get made with an alternate USB to UART bridge that has + # a less buggy driver. + return platform.system() != 'Linux' or self._isWsl1(); class TCPInterface(StreamInterface): """Interface class for meshtastic devices over a TCP link"""