From bc3cba1cf84abc4d0db940be57b97e095443434f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 9 Apr 2026 15:48:59 +0000
Subject: [PATCH 1/2] Initial plan
From 88b37cdf599d83b4b40c2b3079a82377e1cc2fa2 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 9 Apr 2026 15:55:11 +0000
Subject: [PATCH 2/2] Fix SpiAdapter.Read to use equal-length buffers for
TransferFullDuplex
TransferFullDuplex requires writeBuffer and readBuffer to have the same
length. The Read method was creating a 2-byte writeBuffer and a
(buffer.Length + 2)-byte readBuffer, causing ArgumentException on real
SPI devices.
Fix: allocate writeBuffer with the same size as readBuffer, placing
OpCode and register address in the first two bytes (remaining bytes are
don't-care for the SPI read operation).
Also fix the test mock's TransferFullDuplex to only pass command bytes
to Write, preventing don't-care padding from corrupting register data.
Agent-Logs-Url: https://github.com/dotnet/iot/sessions/7c410060-a096-49b1-8cfa-348f86e1f77b
Co-authored-by: krwq <660048+krwq@users.noreply.github.com>
---
src/devices/Mcp23xxx/SpiAdapter.cs | 17 +++++++----------
src/devices/Mcp23xxx/tests/Mcp23xxxTest.cs | 5 ++++-
2 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/src/devices/Mcp23xxx/SpiAdapter.cs b/src/devices/Mcp23xxx/SpiAdapter.cs
index f2b077b54e..ce58cd38bf 100644
--- a/src/devices/Mcp23xxx/SpiAdapter.cs
+++ b/src/devices/Mcp23xxx/SpiAdapter.cs
@@ -37,18 +37,15 @@ public SpiAdapter(SpiDevice device, int deviceAddress)
///
public override void Read(byte registerAddress, Span buffer)
{
- // Include OpCode and Register Address.
- Span writeBuffer = stackalloc byte[]
- {
- GetOpCode(_deviceAddress, isReadCommand: true),
- registerAddress
- };
+ int fullLength = buffer.Length + 2;
- Span readBuffer = stackalloc byte[buffer.Length + 2];
+ // Include OpCode and Register Address.
+ // writeBuffer must be the same length as readBuffer for TransferFullDuplex.
+ Span writeBuffer = stackalloc byte[fullLength];
+ writeBuffer[0] = GetOpCode(_deviceAddress, isReadCommand: true);
+ writeBuffer[1] = registerAddress;
- // Should this also contain the op code and register?
- // Why are we transferring full duplex if we only really
- // need to read?
+ Span readBuffer = stackalloc byte[fullLength];
_device.TransferFullDuplex(writeBuffer, readBuffer);
// First 2 bytes are from sending OpCode and Register Address.
diff --git a/src/devices/Mcp23xxx/tests/Mcp23xxxTest.cs b/src/devices/Mcp23xxx/tests/Mcp23xxxTest.cs
index d787000d44..6ef22fb71e 100644
--- a/src/devices/Mcp23xxx/tests/Mcp23xxxTest.cs
+++ b/src/devices/Mcp23xxx/tests/Mcp23xxxTest.cs
@@ -71,7 +71,10 @@ public SpiDeviceMock(int ports)
public override void TransferFullDuplex(ReadOnlySpan writeBuffer, Span readBuffer)
{
- Write(writeBuffer);
+ // Only pass the command bytes (OpCode + RegisterAddress) to Write.
+ // Remaining bytes in writeBuffer are don't-care padding for full-duplex reads
+ // and should not be written as register data.
+ Write(writeBuffer.Slice(0, Math.Min(writeBuffer.Length, 2)));
Read(readBuffer);
}