diff --git a/System.IO.Ports/Properties/AssemblyInfo.cs b/System.IO.Ports/Properties/AssemblyInfo.cs index 3c9fe3f..54660a0 100644 --- a/System.IO.Ports/Properties/AssemblyInfo.cs +++ b/System.IO.Ports/Properties/AssemblyInfo.cs @@ -12,7 +12,7 @@ //////////////////////////////////////////////////////////////// // update this whenever the native assembly signature changes // -[assembly: AssemblyNativeVersion("100.1.1.2")] +[assembly: AssemblyNativeVersion("100.1.1.3")] //////////////////////////////////////////////////////////////// // Setting ComVisible to false makes the types in this assembly not visible diff --git a/System.IO.Ports/SerialData.cs b/System.IO.Ports/SerialData.cs index fc1a74a..6e79782 100644 --- a/System.IO.Ports/SerialData.cs +++ b/System.IO.Ports/SerialData.cs @@ -20,4 +20,4 @@ public enum SerialData /// WatchChar = 2 } -} \ No newline at end of file +} diff --git a/System.IO.Ports/SerialDataReceivedEventArgs.cs b/System.IO.Ports/SerialDataReceivedEventArgs.cs index b8ed8d6..a97b13e 100644 --- a/System.IO.Ports/SerialDataReceivedEventArgs.cs +++ b/System.IO.Ports/SerialDataReceivedEventArgs.cs @@ -22,4 +22,4 @@ internal SerialDataReceivedEventArgs(SerialData eventCode) /// public SerialData EventType { get => _data; } } -} \ No newline at end of file +} diff --git a/System.IO.Ports/SerialDataReceivedEventHandler.cs b/System.IO.Ports/SerialDataReceivedEventHandler.cs index 689cb46..731f80c 100644 --- a/System.IO.Ports/SerialDataReceivedEventHandler.cs +++ b/System.IO.Ports/SerialDataReceivedEventHandler.cs @@ -11,5 +11,7 @@ namespace System.IO.Ports /// /// The sender of the event, which is the object. /// A object that contains the event data. - public delegate void SerialDataReceivedEventHandler(object sender, SerialDataReceivedEventArgs e); + public delegate void SerialDataReceivedEventHandler( + object sender, + SerialDataReceivedEventArgs e); } \ No newline at end of file diff --git a/System.IO.Ports/SerialDeviceController.cs b/System.IO.Ports/SerialDeviceController.cs index e9462ae..d0b49f6 100644 --- a/System.IO.Ports/SerialDeviceController.cs +++ b/System.IO.Ports/SerialDeviceController.cs @@ -10,16 +10,13 @@ namespace System.IO.Ports /// /// This class is used to keep tabs on what serial ports are open. /// - internal sealed class SerialDeviceController + internal static class SerialDeviceController { // this is used as the lock object // a lock is required because multiple threads can access the SerialDevice controller + [System.Diagnostics.DebuggerBrowsable(Diagnostics.DebuggerBrowsableState.Never)] private static object _syncLock; - // we can have only one instance of the SerialDeviceController - // need to do a lazy initialization of this field to make sure it exists when called elsewhere. - private static SerialDeviceController s_instance; - // backing field for DeviceCollection private static ArrayList s_deviceCollection; @@ -57,30 +54,5 @@ internal static ArrayList DeviceCollection s_deviceCollection = value; } } - - /// - /// Gets the default serial device controller for the system. - /// - /// The default GPIO controller for the system, or null if the system has no GPIO controller. - internal static SerialDeviceController GetDefault() - { - if (s_instance == null) - { - if (_syncLock == null) - { - _syncLock = new object(); - } - - lock (_syncLock) - { - if (s_instance == null) - { - s_instance = new SerialDeviceController(); - } - } - } - - return s_instance; - } } } diff --git a/System.IO.Ports/SerialPort.cs b/System.IO.Ports/SerialPort.cs index e6f29e9..ffc012e 100644 --- a/System.IO.Ports/SerialPort.cs +++ b/System.IO.Ports/SerialPort.cs @@ -12,7 +12,7 @@ namespace System.IO.Ports /// /// Represents a serial port resource. /// - public class SerialPort : IDisposable + public sealed class SerialPort : IDisposable { /// /// Indicates that no time-out should occur. @@ -24,32 +24,40 @@ public class SerialPort : IDisposable /// public const string DefaultNewLine = "\r\n"; + [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] private static readonly SerialDeviceEventListener s_eventListener = new(); + private bool _disposed; + + // this is used as the lock object + // a lock is required because multiple threads can access the SerialPort + [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] + private readonly object _syncLock = new(); + + // flag to signal an open serial port + private bool _opened; + private int _writeTimeout = InfiniteTimeout; private int _readTimeout = InfiniteTimeout; private int _receivedBytesThreshold; - private int _baudRate = 9600; - private bool _opened = false; - private bool _disposed = true; + private int _baudRate; private Handshake _handshake = Handshake.None; - private StopBits _stopBits = StopBits.One; - private int _dataBits = 8; - private Parity _parity = Parity.None; + private StopBits _stopBits; + private int _dataBits; + private Parity _parity; private SerialMode _mode = SerialMode.Normal; - private string _deviceId; + private readonly string _deviceId; internal int _portIndex; -#pragma warning disable IDE0052 // need this to be used in native code +#pragma warning disable S4487 // need this to be used in native code private char _watchChar; -#pragma warning restore IDE0052 // Remove unread private members +#pragma warning restore S4487 // Unread "private" fields should be removed private SerialDataReceivedEventHandler _callbacksDataReceivedEvent = null; private SerialStream _stream; - private readonly object _syncLock; - private string _newLine; - private bool _hasBeenOpened = false; + private string _newLine = DefaultNewLine; + private Encoding _encoding = Encoding.UTF8; /// /// Initializes a new instance of the class using the /// specified port name, baud rate, parity bit, data bits, and stop bit. @@ -60,15 +68,20 @@ public class SerialPort : IDisposable /// The data bits value. /// One of the values. /// The specified port could not be found or opened. - public SerialPort(string portName, int baudRate = 9600, Parity parity = Parity.None, int dataBits = 8, StopBits stopBits = StopBits.One) + /// The specified port could as aleready been opened. + public SerialPort( + string portName, + int baudRate = 9600, + Parity parity = Parity.None, + int dataBits = 8, + StopBits stopBits = StopBits.One) { - _syncLock = new object(); - // the UART name is an ASCII string with the COM port name in format 'COMn' // need to grab 'n' from the string and convert that to the integer value from the ASCII code (do this by subtracting 48 from the char value) - _portIndex = (portName[3] - 48); + _portIndex = portName[3] - 48; var device = FindDevice(_portIndex); + if (device == null) { _deviceId = portName; @@ -76,14 +89,16 @@ public SerialPort(string portName, int baudRate = 9600, Parity parity = Parity.N _parity = parity; _dataBits = dataBits; _stopBits = stopBits; + _newLine = DefaultNewLine; + + // add serial device to collection + SerialDeviceController.DeviceCollection.Add(this); } else { // this device already exists throw an exception throw new ArgumentException(); } - - _newLine = DefaultNewLine; } /// @@ -97,20 +112,11 @@ public void Open() { _disposed = false; - // Initi should happen only once - if (!_hasBeenOpened) - { - NativeInit(); - } - - _hasBeenOpened = true; + NativeInit(); // add the serial device to the event listener in order to receive the callbacks from the native interrupts s_eventListener.AddSerialDevice(this); - // add serial device to collection - SerialDeviceController.DeviceCollection.Add(this); - _stream = new SerialStream(this); _opened = true; @@ -137,15 +143,6 @@ public void Close() // remove the pin from the event listener s_eventListener.RemoveSerialDevice(_portIndex); - // find device - var device = FindDevice(_portIndex); - - if (device != null) - { - // remove device from collection - SerialDeviceController.DeviceCollection.Remove(device); - } - _stream.Dispose(); } @@ -184,7 +181,11 @@ public int BaudRate _baudRate = value; - NativeConfig(); + // reconfig needed, if opened + if (_opened) + { + NativeConfig(); + } } } @@ -207,7 +208,11 @@ public Handshake Handshake { _handshake = value; - NativeConfig(); + // reconfig needed, if opened + if (_opened) + { + NativeConfig(); + } } } @@ -235,7 +240,11 @@ public int DataBits _dataBits = value; - NativeConfig(); + // reconfig needed, if opened + if (_opened) + { + NativeConfig(); + } } } @@ -252,7 +261,12 @@ public Parity Parity set { _parity = value; - NativeConfig(); + + // reconfig needed, if opened + if (_opened) + { + NativeConfig(); + } } } @@ -268,8 +282,11 @@ public SerialMode Mode { _mode = value; - // need to reconfigure device - NativeConfig(); + // reconfig needed, if opened + if (_opened) + { + NativeConfig(); + } } } @@ -287,54 +304,25 @@ public StopBits StopBits { _stopBits = value; - NativeConfig(); + // reconfig needed, if opened + if (_opened) + { + NativeConfig(); + } } } /// - /// Gets or sets the port for communications, including but not limited to all available - /// COM ports. + /// Gets the port for communications. /// - /// The property was set to a value with a length - /// of zero. -or- The property was set to a value - /// that starts with "\\". -or- The port name was not valid. - /// The property was set to null. - /// The specified port is open. + /// + /// .NET nanoFramework doesn't support changing the port. + /// public string PortName { get { - if (!_disposed) - { - return _deviceId; - } - - throw new ObjectDisposedException(); - } - - set - { - if (string.IsNullOrEmpty(value)) - { - throw new ArgumentException(); - } - - if (_deviceId != value) - { - // First dispose the old one - if (_hasBeenOpened) - { - NativeDispose(); - } - - _deviceId = value; - _portIndex = (value[3] - 48); - - NativeInit(); - - _hasBeenOpened = true; - _disposed = false; - } + return _deviceId; } } @@ -352,7 +340,16 @@ public char WatchChar { _watchChar = value; - NativeSetWatchChar(); + // update native, if opened + if (_opened) + { + NativeSetWatchChar(); + } + } + + get + { + throw new NotSupportedException(); } } @@ -367,7 +364,17 @@ public char WatchChar /// /// .NET nanoFrameowrk implementation of serial port only supports . /// - public Encoding Encoding { get; set; } = Encoding.UTF8; +#pragma warning disable S2292 // can't have this adding a automated backing field + public Encoding Encoding +#pragma warning restore S2292 // Trivial properties should be auto-implemented + { + get => _encoding; + + set + { + _encoding = value; + } + } /// /// Gets a value indicating the open or closed status of the @@ -479,7 +486,7 @@ public int ReceivedBytesThreshold /// /// The number of bytes of data in the receive buffer. /// The port is not open. - public int BytesToRead + public extern int BytesToRead { [MethodImpl(MethodImplOptions.InternalCall)] get; @@ -874,6 +881,15 @@ protected void Dispose(bool disposing) Close(); } + // find device + var device = FindDevice(_portIndex); + + if (device != null) + { + // remove device from collection + SerialDeviceController.DeviceCollection.Remove(device); + } + NativeDispose(); } diff --git a/System.IO.Ports/StopBits.cs b/System.IO.Ports/StopBits.cs index 5e82dfa..2c28207 100644 --- a/System.IO.Ports/StopBits.cs +++ b/System.IO.Ports/StopBits.cs @@ -25,4 +25,4 @@ public enum StopBits /// OnePointFive = 3 }; -} \ No newline at end of file +}