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