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);
}