From 475bc7e68c8d79ea2d9d9c56a6767e52c5ff08ae Mon Sep 17 00:00:00 2001 From: Brett Smith Date: Thu, 7 Nov 2024 18:32:44 +0000 Subject: [PATCH] Fixes https://github.com/Threetwosevensixseven/CSpectPlugins/issues/3. Mono on Linux does not fire `DataReceived` events. Instead a thread must be used to constantly read from the serial port. Fortunately, only `SerialPort.cs` needed changing, as it appears entirely safe to pass a null event. --- UARTReplacement/SerialPort.cs | 41 +++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/UARTReplacement/SerialPort.cs b/UARTReplacement/SerialPort.cs index 8bf6b17..b2802a4 100644 --- a/UARTReplacement/SerialPort.cs +++ b/UARTReplacement/SerialPort.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; namespace Plugins.UARTReplacement @@ -21,6 +22,8 @@ public class SerialPort : IDisposable private bool enablePiGpio5Output = false; private UARTTargets target; private string logPrefix; + private System.IO.Ports.SerialDataReceivedEventHandler handler; + private Thread readThread; /// /// Creates an instance of the SerialPort class. @@ -31,6 +34,7 @@ public SerialPort(string PortName, UARTTargets Target, System.IO.Ports.SerialDat try { target = Target; + handler = dataReceivedHandler; logPrefix = target.ToString().Substring(0, 1) + "." + (PortName ?? "").Trim() + "."; if (string.IsNullOrWhiteSpace(PortName)) { @@ -51,8 +55,19 @@ public SerialPort(string PortName, UARTTargets Target, System.IO.Ports.SerialDat LogClock(oldBaud, baud, false); LogPrescaler(oldBaud, baud, ""); if (dataReceivedHandler != null) - port.DataReceived += dataReceivedHandler; - port.Open(); + { + if (IsRunningOnMono()) + { + port.Open(); + readThread = new Thread(new ThreadStart(this.ReadThread)); + readThread.Start(); + } + else + { + port.DataReceived += dataReceivedHandler; + port.Open(); + } + } } catch (System.IO.IOException ex) { @@ -98,6 +113,21 @@ public void Write(byte[] buffer, int offset, int count) } } + public void ReadThread() + { + try + { + while(true) + { + Thread.Sleep(10); + handler.Invoke(port, null); + } + } + catch(ThreadInterruptedException) { + // normal at dispose + } + } + /// /// If there is a byte available in the UART buffer return it, otherwise a value representing no data. /// @@ -404,6 +434,11 @@ public bool IsEnabled return port != null; } } + + public static bool IsRunningOnMono () + { + return Type.GetType ("Mono.Runtime") != null; + } /// /// Convenience method to log the clock and calculated baud to the debug console, every time the video timing clock changes. @@ -462,6 +497,8 @@ protected virtual void Dispose(bool disposing) if (disposing) { // Dispose managed state (managed objects). + readThread?.Interrupt(); + if (port != null) { if (port.IsOpen)