Port the iRIO decode and Press_V2/Release_V2 routing into testable C#: - Mapping/: RioMapEntry decodes the 16-bit map word (lamp/mouse/hat/joy/extended/ alt/ctrl/shift flags + value) and resolves the routing Kind by the legacy precedence (joy+hat+mouse => RIO command; none => keyboard; else joy>hat>mouse). RioAddress translates button/keypad events to table addresses (+0x50/+0x60 keypad offsets); RioInputMap is the 112-entry per-profile table replacing the hard-coded iRIO[]. - InputRouter ports Press_V2/Release_V2: modifier press/release ordering, scancode keys, joystick buttons, POV hat, mouse move/click (deltas corrected per PROTOCOL.md), RIO-command dispatch, and lamp feedback (bright on press, dim on release; RIO commands carry none). InitializeLamps() dims all lamp entries. - Output is split behind sink interfaces (IInputSink/IJoystickSink/ILampSink/ IRioCommandSink) so routing is pure + unit-tested; Output/SendInputSink is the real SendInput keyboard/mouse adapter (scancode injection). - tests: 30 new xUnit tests (84 total) for entry decode, address translation, and router routing/precedence/lamp/modifier ordering via a recording sink. The joystick sink's real adapter (HID feeder -> RioGamepad via DeviceIoControl) is blocked on the Phase 1 driver; routing already targets IJoystickSink. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
29 lines
1.1 KiB
C#
29 lines
1.1 KiB
C#
using RioJoy.Core.Mapping;
|
|
|
|
namespace RioJoy.Core.Tests.Mapping;
|
|
|
|
/// <summary>
|
|
/// Records every routed output as an ordered, human-readable log so tests can
|
|
/// assert both <i>what</i> happened and <i>in what order</i>.
|
|
/// </summary>
|
|
internal sealed class RecordingSink : IInputSink, IJoystickSink, ILampSink, IRioCommandSink
|
|
{
|
|
public List<string> Log { get; } = new();
|
|
|
|
public void KeyDown(byte virtualKey, bool extended) => Log.Add($"KeyDown(0x{virtualKey:X2},ext={extended})");
|
|
|
|
public void KeyUp(byte virtualKey, bool extended) => Log.Add($"KeyUp(0x{virtualKey:X2},ext={extended})");
|
|
|
|
public void MouseMove(int dx, int dy) => Log.Add($"MouseMove({dx},{dy})");
|
|
|
|
public void MouseButton(MouseButton button, bool down) => Log.Add($"MouseButton({button},{down})");
|
|
|
|
public void SetButton(int button, bool pressed) => Log.Add($"Joy({button},{pressed})");
|
|
|
|
public void SetHat(RioHat position) => Log.Add($"Hat({position})");
|
|
|
|
public void SetLamp(int address, byte lampState) => Log.Add($"Lamp(0x{address:X2},0x{lampState:X2})");
|
|
|
|
public void Execute(RioCommandCode command) => Log.Add($"Cmd({command})");
|
|
}
|