serial: pipe:vrio named-pipe transport, no com0com needed
NamedPipeTransport connects as a client to vRIO's \\.\pipe\vrio (the DOSBox-X fork's role) and speaks the shared typed-frame contract (PipeFraming: 0x00 data / 0x01 modem lines, null-modem crossed). The COM path's DTR reset pulse is replayed in-band on connect. Peer disconnects and framing violations surface as the 0-byte transport-closed read the link already understands. RioTransportFactory routes endpoint strings — pipe:name (vRIO's own picker syntax) to the pipe transport, everything else to SerialPortTransport — and is wired into RioCoordinator and all three RioSerialMonitor modes, so profiles (RioComPort/DefaultRioComPort) and the bench tools take pipe endpoints anywhere a COM name went. Gotcha baked into the design: named pipes here have 0-byte buffers, so a write blocks until the peer reads it, and vRIO also writes its lines frame before reading — the on-connect pulse frames are therefore queued as overlapped writes (pipe writes drain in issue order, preserving the edge positions) instead of blocking the constructor into a mutual write-first deadlock. Verified end-to-end against the real VRioDevice + VRioPipeService over \\.\pipe\vrio: version 4.2 + check replies, 137 analog polls, lamp commands ACKed, zero framing errors. 322 tests green, both flavors. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -70,7 +70,7 @@ internal static class E0Test
|
||||
int frameCountdown = 0; // >0: inside a reply frame, bytes remaining
|
||||
bool ackSent = false;
|
||||
|
||||
SerialPortTransport? transport = null;
|
||||
IRioTransport? transport = null;
|
||||
Task? reader = null;
|
||||
|
||||
void PhaseReset(AckMode mode, int expectReply, int expectLen)
|
||||
@@ -93,7 +93,7 @@ internal static class E0Test
|
||||
foreach (int tryBaud in bauds)
|
||||
{
|
||||
Console.WriteLine($"[{sw.Elapsed.TotalSeconds,6:F2}s] probing {port} @ {tryBaud} (DTR reset, ~2s boot wait)...");
|
||||
try { transport = new SerialPortTransport(port, tryBaud); }
|
||||
try { transport = RioTransportFactory.Open(port, tryBaud); }
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($" FAILED to open {port}: {ex.GetType().Name}: {ex.Message}");
|
||||
@@ -101,7 +101,7 @@ internal static class E0Test
|
||||
}
|
||||
|
||||
lock (gate) { buffer.Clear(); cursor = 0; }
|
||||
SerialPortTransport t = transport;
|
||||
IRioTransport t = transport;
|
||||
reader = Task.Run(async () =>
|
||||
{
|
||||
var tmp = new byte[256];
|
||||
|
||||
@@ -110,7 +110,7 @@ internal static class MashTest
|
||||
IRioTransport transport;
|
||||
try
|
||||
{
|
||||
transport = selftest ? new SelftestTransport() : new SerialPortTransport(port, baud);
|
||||
transport = selftest ? new SelftestTransport() : RioTransportFactory.Open(port, baud);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -9,6 +9,8 @@ using RioJoy.Core.Serial;
|
||||
// It flashes all lamps once to prove the PC -> RIO output path, then echoes a lamp
|
||||
// on each button press so a physical press lights up.
|
||||
// dotnet run --project tools/RioSerialMonitor -- [port] [seconds] [--baud rate]
|
||||
// [port] is a COM name or a pipe endpoint: pipe:vrio connects to the vRIO
|
||||
// emulator's \\.\pipe\vrio (no com0com pair; vRIO must have its pipe open).
|
||||
// Firmware wedge-patch validation (RIO_TAP mash test, see MashTest.cs):
|
||||
// dotnet run --project tools/RioSerialMonitor -- --mash [port] [seconds]
|
||||
// [--label baseline|patched] [--no-lamps] [--wedge seconds] [--baud rate]
|
||||
@@ -45,10 +47,10 @@ void Log(string msg)
|
||||
|
||||
Console.WriteLine($"== RIO serial monitor :: {port} @ {baud} 8N1 for {seconds}s ==");
|
||||
|
||||
SerialPortTransport transport;
|
||||
IRioTransport transport;
|
||||
try
|
||||
{
|
||||
transport = new SerialPortTransport(port, baud);
|
||||
transport = RioTransportFactory.Open(port, baud);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user