From a91883eba4a52b1a8cedf30ea920c41acc10eb97 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 1 Jul 2026 14:14:12 +0000
Subject: [PATCH 1/2] Initial plan
From 3345d4bd9eb7e07dce8caf47171f3401ba88413a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 1 Jul 2026 14:18:05 +0000
Subject: [PATCH 2/2] Allow zero-length I2C Write to emit a Start/Stop bus
transaction
---
src/System.Device.Gpio/System/Device/I2c/I2cDevice.cs | 2 ++
.../System/Device/I2c/UnixI2cBus.cs | 11 +++++++++++
2 files changed, 13 insertions(+)
diff --git a/src/System.Device.Gpio/System/Device/I2c/I2cDevice.cs b/src/System.Device.Gpio/System/Device/I2c/I2cDevice.cs
index d43e745ba5..1c7dce159b 100644
--- a/src/System.Device.Gpio/System/Device/I2c/I2cDevice.cs
+++ b/src/System.Device.Gpio/System/Device/I2c/I2cDevice.cs
@@ -70,6 +70,8 @@ public virtual unsafe void WriteByte(byte value)
///
/// The buffer that contains the data to be written to the I2C device.
/// The data should not include the I2C device address.
+ /// An empty buffer generates a transaction on the bus (Start condition, device address and Stop
+ /// condition) without transferring any data byte, which some devices require to be woken up.
///
public abstract void Write(ReadOnlySpan buffer);
diff --git a/src/System.Device.Gpio/System/Device/I2c/UnixI2cBus.cs b/src/System.Device.Gpio/System/Device/I2c/UnixI2cBus.cs
index bd5ee325b5..2e8ee50701 100644
--- a/src/System.Device.Gpio/System/Device/I2c/UnixI2cBus.cs
+++ b/src/System.Device.Gpio/System/Device/I2c/UnixI2cBus.cs
@@ -121,6 +121,17 @@ internal unsafe void Write(int deviceAddress, ReadOnlySpan buffer)
throw new ArgumentException($"{nameof(buffer)} length is too long.", nameof(buffer));
}
+ if (buffer.Length == 0)
+ {
+ // An empty write still generates a transaction on the bus (Start condition, device
+ // address, Stop condition) without transferring any data byte. Some devices (e.g. the
+ // PN532 NFC reader) rely on this to be woken up. A non-null pointer is required so that
+ // WriteReadCore emits a zero-length write message instead of skipping it.
+ byte placeholder = 0;
+ WriteReadCore((ushort)deviceAddress, &placeholder, null, 0, 0);
+ return;
+ }
+
fixed (byte* writeBufferPointer = buffer)
{
WriteReadCore((ushort)deviceAddress, writeBufferPointer, null, (ushort)buffer.Length, 0);