diff --git a/src/Iot.Device.Bindings/CompatibilitySuppressions.xml b/src/Iot.Device.Bindings/CompatibilitySuppressions.xml
index 626bebcfa6..c6dfb5a928 100644
--- a/src/Iot.Device.Bindings/CompatibilitySuppressions.xml
+++ b/src/Iot.Device.Bindings/CompatibilitySuppressions.xml
@@ -14,6 +14,13 @@
lib/net6.0/Iot.Device.Bindings.dll
true
+
+ CP0001
+ T:Iot.Device.Ft232H.Ft232HI2c
+ lib/net6.0/Iot.Device.Bindings.dll
+ lib/net6.0/Iot.Device.Bindings.dll
+ true
+
CP0001
T:IoT.Device.Pn532.ErrorCode
@@ -147,6 +154,13 @@
lib/netstandard2.0/Iot.Device.Bindings.dll
true
+
+ CP0001
+ T:Iot.Device.Ft232H.Ft232HI2c
+ lib/netcoreapp3.1/Iot.Device.Bindings.dll
+ lib/netstandard2.0/Iot.Device.Bindings.dll
+ true
+
CP0001
T:Iot.Device.Common.ValueArray`1
@@ -161,6 +175,13 @@
lib/netstandard2.0/Iot.Device.Bindings.dll
true
+
+ CP0001
+ T:Iot.Device.Ft232H.Ft232HI2c
+ lib/netstandard2.0/Iot.Device.Bindings.dll
+ lib/netstandard2.0/Iot.Device.Bindings.dll
+ true
+
CP0001
T:IoT.Device.Pn532.ErrorCode
diff --git a/src/System.Device.Gpio.Tests/ProtocolTests.cs b/src/System.Device.Gpio.Tests/ProtocolTests.cs
index 935c7b38bb..f138d925ef 100644
--- a/src/System.Device.Gpio.Tests/ProtocolTests.cs
+++ b/src/System.Device.Gpio.Tests/ProtocolTests.cs
@@ -1,13 +1,15 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System.Threading;
+using System.Collections.Generic;
using System.Device.I2c;
using System.Device.Pwm;
+using System.Threading;
using Iot.Device.Adc;
using Iot.Device.Bmxx80;
-using Xunit;
+using Iot.Device.Board;
using UnitsNet;
+using Xunit;
using static System.Device.Gpio.Tests.SetupHelpers;
namespace System.Device.Gpio.Tests;
@@ -100,6 +102,67 @@ public void I2C_I2cBus_MultipleDispose()
bme280.Dispose();
}
+ [Fact]
+ [Trait("feature", "i2c")]
+ public void I2C_I2cBus_MultipleCreate()
+ {
+ I2cBus i2cBus = CreateI2cBusForBme280();
+
+ I2cDevice device1 = i2cBus.CreateDevice(Bmp280.DefaultI2cAddress);
+ device1.ReadByte();
+ i2cBus.RemoveDevice(Bmp280.DefaultI2cAddress);
+
+ I2cDevice device2 = i2cBus.CreateDevice(Bmp280.DefaultI2cAddress);
+ device2.ReadByte();
+ }
+
+ [Fact]
+ [Trait("feature", "i2c")]
+ public void I2C_I2cBus_MultipleCreateAndDispose()
+ {
+ I2cBus i2cBus = CreateI2cBusForBme280();
+
+ I2cDevice device1 = i2cBus.CreateDevice(Bmp280.DefaultI2cAddress);
+ device1.ReadByte();
+ device1.Dispose();
+
+ I2cDevice device2 = i2cBus.CreateDevice(Bmp280.DefaultI2cAddress);
+ device2.ReadByte();
+ device2.Dispose();
+ }
+
+ [Fact]
+ [Trait("feature", "i2c")]
+ public void I2C_I2cBus_Scan()
+ {
+ I2cBus i2cBus = CreateI2cBusForBme280();
+ List addresses = i2cBus.PerformBusScan();
+ Assert.NotNull(addresses);
+ }
+
+ [Fact]
+ [Trait("feature", "i2c")]
+ public void I2C_I2cBus_ScanMultipleTimes()
+ {
+ I2cBus i2cBus = CreateI2cBusForBme280();
+
+ List addresses1 = i2cBus.PerformBusScan();
+ Assert.NotNull(addresses1);
+
+ List addresses2 = i2cBus.PerformBusScan();
+ Assert.NotNull(addresses2);
+ }
+
+ [Fact]
+ [Trait("feature", "i2c")]
+ public void I2C_I2cBus_HasBmp280Present()
+ {
+ I2cBus i2cBus = CreateI2cBusForBme280();
+ List addresses = i2cBus.PerformBusScan();
+ Assert.NotEmpty(addresses);
+ Assert.Contains(Bmp280.DefaultI2cAddress, addresses);
+ }
+
[Fact]
[Trait("feature", "pwm")]
[Trait("feature", "spi")]
diff --git a/src/devices/Board/I2cBusManager.cs b/src/devices/Board/I2cBusManager.cs
index 049e7e8fe6..1a23186ba8 100644
--- a/src/devices/Board/I2cBusManager.cs
+++ b/src/devices/Board/I2cBusManager.cs
@@ -68,13 +68,8 @@ public I2cBusManager(Board board, int bus, int[]? pins, I2cBus busInstance)
/// No test is performed whether the given device exists and is usable
public override I2cDevice CreateDevice(int deviceAddress)
{
- if (_devices.TryGetValue(deviceAddress, out I2cDevice? device))
- {
- return device;
- }
-
I2cDevice newDevice = _busInstance.CreateDevice(deviceAddress);
- _devices.Add(deviceAddress, newDevice);
+ _devices[deviceAddress] = newDevice;
return newDevice;
}
diff --git a/src/devices/Board/tests/BoardTests.cs b/src/devices/Board/tests/BoardTests.cs
index 68e8471f15..b9c15fb29f 100644
--- a/src/devices/Board/tests/BoardTests.cs
+++ b/src/devices/Board/tests/BoardTests.cs
@@ -185,6 +185,34 @@ public void TwoI2cDevicesCanSharePins()
ctrl.OpenPin(0);
}
+ [Fact]
+ public void CreateAndRemoveI2cDevice()
+ {
+ using Board board = CreateBoard();
+ I2cBus bus = board.CreateOrGetI2cBus(0);
+
+ I2cDevice device1 = bus.CreateDevice(0x55);
+ device1.ReadByte();
+ bus.RemoveDevice(0x55);
+
+ I2cDevice device2 = bus.CreateDevice(0x55);
+ device2.ReadByte();
+ }
+
+ [Fact]
+ public void CreateAndDisposeI2cDevice()
+ {
+ using Board board = CreateBoard();
+ I2cBus bus = board.CreateOrGetI2cBus(0);
+
+ I2cDevice device1 = bus.CreateDevice(0x55);
+ device1.ReadByte();
+ device1.Dispose();
+
+ I2cDevice device2 = bus.CreateDevice(0x55);
+ device2.ReadByte();
+ }
+
[Fact]
public void CreateSpiDeviceDefault()
{
diff --git a/src/devices/Ft232H/Ft232H.csproj b/src/devices/Ft232H/Ft232H.csproj
index 0cfcbde535..86d985b7d6 100644
--- a/src/devices/Ft232H/Ft232H.csproj
+++ b/src/devices/Ft232H/Ft232H.csproj
@@ -9,8 +9,8 @@
-
+
diff --git a/src/devices/Ft232H/Ft232HI2cBus.cs b/src/devices/Ft232H/Ft232HI2cBus.cs
index 49a110a77b..0347881058 100644
--- a/src/devices/Ft232H/Ft232HI2cBus.cs
+++ b/src/devices/Ft232H/Ft232HI2cBus.cs
@@ -15,7 +15,7 @@ namespace Iot.Device.Ft232H
///
internal class Ft232HI2cBus : I2cBus
{
- private HashSet _usedAddresses = new HashSet();
+ private HashSet? _usedAddresses = null;
///
/// Store the FTDI Device Information
@@ -35,23 +35,34 @@ public Ft232HI2cBus(Ftx232HDevice deviceInformation)
///
public override I2cDevice CreateDevice(int deviceAddress)
{
+ _usedAddresses ??= new HashSet();
if (!_usedAddresses.Add(deviceAddress))
{
throw new ArgumentException($"Device with address 0x{deviceAddress,0X2} is already open.", nameof(deviceAddress));
}
- return new Ft232HI2c(this, deviceAddress);
+ return CreateDeviceNoCheck(deviceAddress);
+ }
+
+ internal I2cDevice CreateDeviceNoCheck(int deviceAddress)
+ {
+ return new Ft232HI2cDevice(this, deviceAddress);
}
///
public override void RemoveDevice(int deviceAddress)
{
- if (!_usedAddresses.Remove(deviceAddress))
+ if (!RemoveDeviceNoCheck(deviceAddress))
{
throw new ArgumentException($"Device with address 0x{deviceAddress,0X2} was not open.", nameof(deviceAddress));
}
}
+ internal bool RemoveDeviceNoCheck(int deviceAddress)
+ {
+ return _usedAddresses?.Remove(deviceAddress) ?? false;
+ }
+
internal void Read(int deviceAddress, Span buffer)
{
DeviceInformation.I2cStart();
diff --git a/src/devices/Ft232H/Ft232HI2c.cs b/src/devices/Ft232H/Ft232HI2cDevice.cs
similarity index 71%
rename from src/devices/Ft232H/Ft232HI2c.cs
rename to src/devices/Ft232H/Ft232HI2cDevice.cs
index b925792866..0c9a417d2e 100644
--- a/src/devices/Ft232H/Ft232HI2c.cs
+++ b/src/devices/Ft232H/Ft232HI2cDevice.cs
@@ -9,17 +9,19 @@ namespace Iot.Device.Ft232H
///
/// I2C Device for FT232H
///
- public class Ft232HI2c : I2cDevice
+ public class Ft232HI2cDevice : I2cDevice
{
private Ft232HI2cBus _i2cBus;
private int _deviceAddress;
private I2cConnectionSettings _settings;
+ private bool _shouldDisposeBus;
- internal Ft232HI2c(Ft232HI2cBus i2cBus, int deviceAddress)
+ internal Ft232HI2cDevice(Ft232HI2cBus i2cBus, int deviceAddress, bool shouldDisposeBus = false)
{
_i2cBus = i2cBus;
_deviceAddress = deviceAddress;
_settings = new I2cConnectionSettings((int)i2cBus.DeviceInformation.LocId, deviceAddress);
+ _shouldDisposeBus = shouldDisposeBus;
}
///
@@ -47,9 +49,22 @@ public override void WriteRead(ReadOnlySpan writeBuffer, Span readBu
///
protected override void Dispose(bool disposing)
{
- _i2cBus?.RemoveDevice(_deviceAddress);
- _i2cBus = null!;
+ if (_i2cBus != null)
+ {
+ if (_shouldDisposeBus)
+ {
+ _i2cBus.Dispose();
+ }
+ else
+ {
+ _i2cBus.RemoveDeviceNoCheck(_deviceAddress);
+ }
+
+ _i2cBus = null!;
+ }
+
_settings = null!;
+
base.Dispose(disposing);
}