diff --git a/src/System.Device.Gpio.Tests/LibGpiodDriverTests.cs b/src/System.Device.Gpio.Tests/LibGpiodDriverTests.cs
deleted file mode 100644
index f4c4eafe89..0000000000
--- a/src/System.Device.Gpio.Tests/LibGpiodDriverTests.cs
+++ /dev/null
@@ -1,107 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Device.Gpio.Drivers;
-using System.Threading;
-using Xunit;
-using Xunit.Abstractions;
-
-namespace System.Device.Gpio.Tests
-{
- [Trait("feature", "gpio")]
- [Trait("feature", "gpio-libgpiod")]
- [Trait("SkipOnTestRun", "Windows_NT")]
- public class LibGpiodDriverTests : GpioControllerTestBase
- {
- public LibGpiodDriverTests(ITestOutputHelper testOutputHelper)
- : base(testOutputHelper)
- {
- }
-
- protected override GpioDriver GetTestDriver() => new LibGpiodDriver();
-
- protected override PinNumberingScheme GetTestNumberingScheme() => PinNumberingScheme.Logical;
-
- [Fact]
- public void SetPinModeSetsDefaultValue()
- {
- using (GpioController controller = new GpioController(GetTestNumberingScheme(), GetTestDriver()))
- {
- int testPin = OutputPin;
- // Set value to low prior to test, so that we have a defined start situation
- controller.OpenPin(testPin, PinMode.Output);
- controller.Write(testPin, PinValue.Low);
- controller.ClosePin(testPin);
- // For this test, we use the input pin as an external pull-up
- controller.OpenPin(InputPin, PinMode.Output);
- controller.Write(InputPin, PinValue.High);
- Thread.Sleep(2);
-
- controller.OpenPin(testPin, PinMode.Input);
- Thread.Sleep(50);
- // It's not possible to change the direction while listening to events (causes an error). Therefore the real behavior of the driver
- // can only be tested with a scope (or if we had a third pin connected in the lab hardware)
-
- // We do another test here and make sure the
- // pin is really high now
- controller.Write(testPin, PinValue.High);
- controller.SetPinMode(testPin, PinMode.Output);
- controller.SetPinMode(InputPin, PinMode.Input);
-
- Assert.True(controller.Read(InputPin) == PinValue.High);
-
- controller.ClosePin(OutputPin);
- controller.ClosePin(InputPin);
- }
- }
-
- [Fact]
- public void UnregisterPinValueChangedShallNotThrow()
- {
- using var gc = new GpioController(GetTestNumberingScheme(), GetTestDriver());
- gc.OpenPin(InputPin, PinMode.Input);
-
- static void PinChanged(object sender, PinValueChangedEventArgs args)
- {
- }
-
- for (var i = 0; i < 1000; i++)
- {
- gc.RegisterCallbackForPinValueChangedEvent(InputPin, PinEventTypes.Rising | PinEventTypes.Falling, PinChanged);
- gc.UnregisterCallbackForPinValueChangedEvent(InputPin, PinChanged);
- }
- }
- }
-
- ///
- /// Ensure leaking instances of the driver doesn't cause a segfault
- /// Regression test for https://github.com/dotnet/iot/issues/1849
- ///
- [Fact]
- public void LeakingDriverDoesNotCrash()
- {
- GpioController controller1 = new GpioController(PinNumberingScheme.Logical, new LibGpiodDriver());
- controller1.OpenPin(10, PinMode.Output);
- GpioController controller2 = new GpioController(PinNumberingScheme.Logical, new LibGpiodDriver());
- controller2.OpenPin(11, PinMode.Output);
- GpioController controller3 = new GpioController(PinNumberingScheme.Logical, new LibGpiodDriver());
- controller3.OpenPin(12, PinMode.Output);
- GpioController controller4 = new GpioController(PinNumberingScheme.Logical, new LibGpiodDriver());
- controller4.OpenPin(13, PinMode.Output);
- GpioController controller5 = new GpioController(PinNumberingScheme.Logical, new LibGpiodDriver());
- controller5.OpenPin(14, PinMode.Output);
-
- for (int i = 0; i < 10; i++)
- {
- GC.Collect();
- GpioController controller6 = new GpioController(PinNumberingScheme.Logical, new LibGpiodDriver());
- controller6.OpenPin(15, PinMode.Output);
- controller6.ClosePin(15);
- controller6.Dispose();
- GC.Collect();
- Thread.Sleep(20);
- }
-
- GC.WaitForPendingFinalizers();
- }
-}
diff --git a/src/System.Device.Gpio.Tests/LibGpiodV1DriverTests.cs b/src/System.Device.Gpio.Tests/LibGpiodV1DriverTests.cs
index 0cd8f4332f..a0d69c0076 100644
--- a/src/System.Device.Gpio.Tests/LibGpiodV1DriverTests.cs
+++ b/src/System.Device.Gpio.Tests/LibGpiodV1DriverTests.cs
@@ -72,4 +72,36 @@ static void PinChanged(object sender, PinValueChangedEventArgs args)
gc.UnregisterCallbackForPinValueChangedEvent(InputPin, PinChanged);
}
}
-}
+
+ ///
+ /// Ensure leaking instances of the driver doesn't cause a segfault
+ /// Regression test for https://github.com/dotnet/iot/issues/1849
+ ///
+ [Fact]
+ public void LeakingDriverDoesNotCrash()
+ {
+ GpioController controller1 = new GpioController(PinNumberingScheme.Logical, new LibGpiodDriver());
+ controller1.OpenPin(10, PinMode.Output);
+ GpioController controller2 = new GpioController(PinNumberingScheme.Logical, new LibGpiodDriver());
+ controller2.OpenPin(11, PinMode.Output);
+ GpioController controller3 = new GpioController(PinNumberingScheme.Logical, new LibGpiodDriver());
+ controller3.OpenPin(12, PinMode.Output);
+ GpioController controller4 = new GpioController(PinNumberingScheme.Logical, new LibGpiodDriver());
+ controller4.OpenPin(13, PinMode.Output);
+ GpioController controller5 = new GpioController(PinNumberingScheme.Logical, new LibGpiodDriver());
+ controller5.OpenPin(14, PinMode.Output);
+
+ for (int i = 0; i < 10; i++)
+ {
+ GC.Collect();
+ GpioController controller6 = new GpioController(PinNumberingScheme.Logical, new LibGpiodDriver());
+ controller6.OpenPin(15, PinMode.Output);
+ controller6.ClosePin(15);
+ controller6.Dispose();
+ GC.Collect();
+ Thread.Sleep(20);
+ }
+
+ GC.WaitForPendingFinalizers();
+ }
+}
\ No newline at end of file
diff --git a/src/System.Device.Gpio/Interop/Unix/SafeLineHandle.cs b/src/System.Device.Gpio/Interop/Unix/SafeLineHandle.cs
deleted file mode 100644
index ef5333338d..0000000000
--- a/src/System.Device.Gpio/Interop/Unix/SafeLineHandle.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Runtime.InteropServices;
-
-namespace System.Device.Gpio;
-
-///
-/// Pointer to a pin (Not a real SafeLineHandle, because we need to align its finalization with the owning object)
-///
-internal sealed class SafeLineHandle : IDisposable
-{
- private IntPtr _handle;
- public SafeLineHandle()
- {
- _handle = IntPtr.Zero;
- }
-
- public SafeLineHandle(IntPtr handle)
- {
- _handle = handle;
- PinMode = PinMode.Input;
- }
-
- public PinMode PinMode { get; set; }
-
- public IntPtr Handle
- {
- get
- {
- return _handle;
- }
- set
- {
- _handle = value;
- }
- }
-
- ///
- /// Release the lock on the line handle.
- ///
- public void ReleaseLock()
- {
- // Contrary to intuition, this does not invalidate the handle (see comment on declaration)
- Interop.libgpiod.gpiod_line_release(_handle);
- }
-
- public bool IsInvalid => _handle == IntPtr.Zero || _handle == Interop.libgpiod.InvalidHandleValue;
-
- public void Dispose()
- {
- if (_handle != IntPtr.Zero)
- {
- Interop.libgpiod.gpiod_line_release(_handle);
- _handle = IntPtr.Zero;
- }
- }
-
- public static implicit operator IntPtr(SafeLineHandle self)
- {
- return self.Handle;
- }
-}
diff --git a/src/System.Device.Gpio/Interop/Unix/libgpiod/V1/SafeLineHandle.cs b/src/System.Device.Gpio/Interop/Unix/libgpiod/V1/SafeLineHandle.cs
index be7172fa31..5e71c2eeec 100644
--- a/src/System.Device.Gpio/Interop/Unix/libgpiod/V1/SafeLineHandle.cs
+++ b/src/System.Device.Gpio/Interop/Unix/libgpiod/V1/SafeLineHandle.cs
@@ -7,31 +7,53 @@
namespace System.Device.Gpio.Libgpiod.V1;
///
-/// Pointer to a pin.
+/// Pointer to a pin (Not a real SafeLineHandle, because we need to align its finalization with the owning object)
///
-internal class SafeLineHandle : SafeHandle
+internal sealed class SafeLineHandle : IDisposable
{
- public PinMode PinMode { get; set; }
-
+ private IntPtr _handle;
public SafeLineHandle()
- : base(IntPtr.Zero, true)
{
+ _handle = IntPtr.Zero;
}
- protected override bool ReleaseHandle()
+ public SafeLineHandle(IntPtr handle)
{
- // Contrary to intuition, this does not invalidate the handle (see comment on declaration)
- LibgpiodV1.gpiod_line_release(handle);
- return true;
+ _handle = handle;
+ PinMode = PinMode.Input;
+ }
+
+ public PinMode PinMode { get; set; }
+
+ public IntPtr Handle
+ {
+ get
+ {
+ return _handle;
+ }
+ set
+ {
+ _handle = value;
+ }
}
///
- /// Release the lock on the line handle.
+ /// Release the lock on the line handle.
///
public void ReleaseLock()
{
- ReleaseHandle();
+ // Contrary to intuition, this does not invalidate the handle (see comment on declaration)
+ Interop.libgpiod.gpiod_line_release(_handle);
}
- public override bool IsInvalid => handle == IntPtr.Zero || handle == LibgpiodV1.InvalidHandleValue;
+ public bool IsInvalid => _handle == IntPtr.Zero || _handle == Interop.libgpiod.InvalidHandleValue;
+
+ public void Dispose()
+ {
+ if (_handle != IntPtr.Zero)
+ {
+ Interop.libgpiod.gpiod_line_release(_handle);
+ _handle = IntPtr.Zero;
+ }
+ }
}
diff --git a/src/System.Device.Gpio/System/Device/Gpio/Drivers/LibGpiodDriver.cs b/src/System.Device.Gpio/System/Device/Gpio/Drivers/LibGpiodDriver.cs
deleted file mode 100644
index 003f21a6d4..0000000000
--- a/src/System.Device.Gpio/System/Device/Gpio/Drivers/LibGpiodDriver.cs
+++ /dev/null
@@ -1,410 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Collections.Generic;
-using System.Threading;
-using System.Runtime.InteropServices;
-using System.Collections.Concurrent;
-using System.Diagnostics;
-
-namespace System.Device.Gpio.Drivers
-{
- ///
- /// This driver uses the Libgpiod library to get user-level access to the gpio ports.
- /// It superseeds the SysFsDriver, but requires that libgpiod is installed. To do so, run
- /// "sudo apt install -y libgpiod-dev".
- ///
- public class LibGpiodDriver : UnixDriver
- {
- private static string s_consumerName = Process.GetCurrentProcess().ProcessName;
- private readonly object _pinNumberLock;
- private readonly ConcurrentDictionary _pinNumberToSafeLineHandle;
- private readonly ConcurrentDictionary _pinNumberToEventHandler;
- private readonly int _pinCount;
- private SafeChipHandle _chip;
-
- ///
- protected internal override int PinCount => _pinCount;
-
- // for use the bias flags we need libgpiod version 1.5 or later
- private static bool IsLibgpiodVersion1_5orHigher()
- {
- IntPtr libgpiodVersionPtr = Interop.libgpiod.gpiod_version_string();
- string? libgpiodVersionMatch = Marshal.PtrToStringAnsi(libgpiodVersionPtr);
-
- if (libgpiodVersionMatch is object)
- {
- Version libgpiodVersion = new Version(libgpiodVersionMatch);
- return (libgpiodVersion.Major >= 1 && libgpiodVersion.Minor >= 5);
- }
-
- return false;
- }
-
- private static bool s_isLibgpiodVersion1_5orHigher = IsLibgpiodVersion1_5orHigher();
-
- private enum RequestFlag : ulong
- {
- GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN = (1UL << 0),
- GPIOD_LINE_REQUEST_FLAG_OPEN_SOURCE = (1UL << 1),
- GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW = (1UL << 2),
- GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE = (1UL << 3),
- GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN = (1UL << 4),
- GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP = (1UL << 5)
- }
-
- ///
- /// Construct an instance
- ///
- /// Number of the gpio Chip. Default 0
- public LibGpiodDriver(int gpioChip = 0)
- {
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- {
- throw new PlatformNotSupportedException($"{GetType().Name} is only supported on Linux/Unix.");
- }
-
- try
- {
- _pinNumberLock = new object();
- _chip = Interop.libgpiod.gpiod_chip_open_by_number(gpioChip);
- if (_chip == null)
- {
- throw ExceptionHelper.GetIOException(ExceptionResource.NoChipFound, Marshal.GetLastWin32Error());
- }
-
- _pinCount = Interop.libgpiod.gpiod_chip_num_lines(_chip);
- _pinNumberToEventHandler = new ConcurrentDictionary();
- _pinNumberToSafeLineHandle = new ConcurrentDictionary();
- }
- catch (DllNotFoundException)
- {
- throw ExceptionHelper.GetPlatformNotSupportedException(ExceptionResource.LibGpiodNotInstalled);
- }
- }
-
- ///
- protected internal override void AddCallbackForPinValueChangedEvent(int pinNumber, PinEventTypes eventTypes, PinChangeEventHandler callback)
- {
- if ((eventTypes & PinEventTypes.Rising) != 0 || (eventTypes & PinEventTypes.Falling) != 0)
- {
- LibGpiodDriverEventHandler eventHandler = _pinNumberToEventHandler.GetOrAdd(pinNumber, PopulateEventHandler);
-
- if ((eventTypes & PinEventTypes.Rising) != 0)
- {
- eventHandler.ValueRising += callback;
- }
-
- if ((eventTypes & PinEventTypes.Falling) != 0)
- {
- eventHandler.ValueFalling += callback;
- }
- }
- else
- {
- throw ExceptionHelper.GetArgumentException(ExceptionResource.InvalidEventType);
- }
- }
-
- private LibGpiodDriverEventHandler PopulateEventHandler(int pinNumber)
- {
- lock (_pinNumberLock)
- {
- _pinNumberToSafeLineHandle.TryGetValue(pinNumber, out SafeLineHandle? pinHandle);
-
- if (pinHandle is null || (pinHandle is object && !Interop.libgpiod.gpiod_line_is_free(pinHandle)))
- {
- pinHandle?.Dispose();
- pinHandle = new SafeLineHandle(Interop.libgpiod.gpiod_chip_get_line(_chip, pinNumber));
- _pinNumberToSafeLineHandle[pinNumber] = pinHandle;
- }
-
- return new LibGpiodDriverEventHandler(pinNumber, pinHandle!);
- }
- }
-
- ///
- protected internal override void ClosePin(int pinNumber)
- {
- lock (_pinNumberLock)
- {
- if (_pinNumberToSafeLineHandle.TryGetValue(pinNumber, out SafeLineHandle? pinHandle) &&
- !IsListeningEvent(pinNumber))
- {
- pinHandle?.Dispose();
- // We know this works
- _pinNumberToSafeLineHandle.TryRemove(pinNumber, out _);
- }
- }
- }
-
- private bool IsListeningEvent(int pinNumber)
- {
- return _pinNumberToEventHandler.ContainsKey(pinNumber);
- }
-
- ///
- protected internal override int ConvertPinNumberToLogicalNumberingScheme(int pinNumber) =>
- throw ExceptionHelper.GetPlatformNotSupportedException(ExceptionResource.ConvertPinNumberingSchemaError);
-
- ///
- protected internal override PinMode GetPinMode(int pinNumber)
- {
- lock (_pinNumberLock)
- {
- if (!_pinNumberToSafeLineHandle.TryGetValue(pinNumber, out SafeLineHandle? pinHandle))
- {
- throw ExceptionHelper.GetInvalidOperationException(ExceptionResource.PinNotOpenedError,
- pin: pinNumber);
- }
-
- return pinHandle.PinMode;
- }
- }
-
- ///
- protected internal override bool IsPinModeSupported(int pinNumber, PinMode mode) => mode switch
- {
- PinMode.Input or PinMode.Output => true,
- PinMode.InputPullDown or PinMode.InputPullUp => s_isLibgpiodVersion1_5orHigher,
- _ => false,
- };
-
- ///
- protected internal override void OpenPin(int pinNumber)
- {
- lock (_pinNumberLock)
- {
- if (_pinNumberToSafeLineHandle.TryGetValue(pinNumber, out _))
- {
- return;
- }
-
- SafeLineHandle pinHandle = new SafeLineHandle(Interop.libgpiod.gpiod_chip_get_line(_chip, pinNumber));
- if (pinHandle == null)
- {
- throw ExceptionHelper.GetIOException(ExceptionResource.OpenPinError, Marshal.GetLastWin32Error());
- }
-
- int mode = Interop.libgpiod.gpiod_line_direction(pinHandle);
- if (mode == 1)
- {
- pinHandle.PinMode = PinMode.Input;
- }
- else if (mode == 2)
- {
- pinHandle.PinMode = PinMode.Output;
- }
-
- if (s_isLibgpiodVersion1_5orHigher && pinHandle.PinMode == PinMode.Input)
- {
- int bias = Interop.libgpiod.gpiod_line_bias(pinHandle);
- if (bias == (int)RequestFlag.GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN)
- {
- pinHandle.PinMode = PinMode.InputPullDown;
- }
-
- if (bias == (int)RequestFlag.GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP)
- {
- pinHandle.PinMode = PinMode.InputPullUp;
- }
- }
-
- _pinNumberToSafeLineHandle.TryAdd(pinNumber, pinHandle);
- }
- }
-
- ///
- protected internal override PinValue Read(int pinNumber)
- {
- if (_pinNumberToSafeLineHandle.TryGetValue(pinNumber, out SafeLineHandle? pinHandle))
- {
- int result = Interop.libgpiod.gpiod_line_get_value(pinHandle);
- if (result == -1)
- {
- throw ExceptionHelper.GetIOException(ExceptionResource.ReadPinError, Marshal.GetLastWin32Error(), pinNumber);
- }
-
- return result;
- }
-
- throw ExceptionHelper.GetInvalidOperationException(ExceptionResource.PinNotOpenedError, pin: pinNumber);
- }
-
- ///
- protected internal override void RemoveCallbackForPinValueChangedEvent(int pinNumber, PinChangeEventHandler callback)
- {
- if (_pinNumberToEventHandler.TryGetValue(pinNumber, out LibGpiodDriverEventHandler? eventHandler))
- {
- eventHandler.ValueFalling -= callback;
- eventHandler.ValueRising -= callback;
- if (eventHandler.IsCallbackListEmpty())
- {
- _pinNumberToEventHandler.TryRemove(pinNumber, out eventHandler);
- eventHandler?.Dispose();
- }
- }
- else
- {
- throw ExceptionHelper.GetInvalidOperationException(ExceptionResource.NotListeningForEventError);
- }
- }
-
- ///
- protected internal override void SetPinMode(int pinNumber, PinMode mode)
- {
- if (_pinNumberToSafeLineHandle.TryGetValue(pinNumber, out SafeLineHandle? pinHandle))
- {
- // This call does not release the handle. It only releases the lock on the handle. Without this, changing the direction of a line is not possible.
- // Line handles cannot be freed and are cached until the chip is closed.
- pinHandle.ReleaseLock();
- int requestResult = mode switch
- {
- PinMode.Input => Interop.libgpiod.gpiod_line_request_input(pinHandle, s_consumerName),
- PinMode.InputPullDown => Interop.libgpiod.gpiod_line_request_input_flags(pinHandle, s_consumerName,
- (int)RequestFlag.GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN),
- PinMode.InputPullUp => Interop.libgpiod.gpiod_line_request_input_flags(pinHandle, s_consumerName,
- (int)RequestFlag.GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP),
- PinMode.Output => Interop.libgpiod.gpiod_line_request_output(pinHandle, s_consumerName, 0),
- _ => -1,
- };
-
- if (requestResult == -1)
- {
- throw ExceptionHelper.GetIOException(ExceptionResource.SetPinModeError, Marshal.GetLastWin32Error(),
- pinNumber);
- }
-
- pinHandle.PinMode = mode;
- return;
- }
-
- throw new InvalidOperationException($"Pin {pinNumber} is not open");
- }
-
- ///
- protected internal override void SetPinMode(int pinNumber, PinMode mode, PinValue initialValue)
- {
- if (_pinNumberToSafeLineHandle.TryGetValue(pinNumber, out SafeLineHandle? pinHandle))
- {
- // This call does not release the handle. It only releases the lock on the handle. Without this, changing the direction of a line is not possible.
- // Line handles cannot be freed and are cached until the chip is closed.
- pinHandle.ReleaseLock();
- int requestResult = mode switch
- {
- PinMode.Input => Interop.libgpiod.gpiod_line_request_input(pinHandle, s_consumerName),
- PinMode.InputPullDown => Interop.libgpiod.gpiod_line_request_input_flags(pinHandle, s_consumerName,
- (int)RequestFlag.GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN),
- PinMode.InputPullUp => Interop.libgpiod.gpiod_line_request_input_flags(pinHandle, s_consumerName,
- (int)RequestFlag.GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP),
- PinMode.Output => Interop.libgpiod.gpiod_line_request_output(pinHandle, s_consumerName, initialValue == PinValue.High ? 1 : 0),
- _ => -1,
- };
-
- if (requestResult == -1)
- {
- throw ExceptionHelper.GetIOException(ExceptionResource.SetPinModeError, Marshal.GetLastWin32Error(),
- pinNumber);
- }
-
- pinHandle.PinMode = mode;
- return;
- }
-
- throw new InvalidOperationException($"Pin {pinNumber} is not open");
- }
-
- ///
- protected internal override WaitForEventResult WaitForEvent(int pinNumber, PinEventTypes eventTypes, CancellationToken cancellationToken)
- {
- if ((eventTypes & PinEventTypes.Rising) != 0 || (eventTypes & PinEventTypes.Falling) != 0)
- {
- LibGpiodDriverEventHandler eventHandler = _pinNumberToEventHandler.GetOrAdd(pinNumber, PopulateEventHandler);
-
- if ((eventTypes & PinEventTypes.Rising) != 0)
- {
- eventHandler.ValueRising += Callback;
- }
-
- if ((eventTypes & PinEventTypes.Falling) != 0)
- {
- eventHandler.ValueFalling += Callback;
- }
-
- bool eventOccurred = false;
- PinEventTypes typeOfEventOccured = PinEventTypes.None;
- void Callback(object o, PinValueChangedEventArgs e)
- {
- eventOccurred = true;
- typeOfEventOccured = e.ChangeType;
- }
-
- WaitForEventResult(cancellationToken, eventHandler.CancellationToken, ref eventOccurred);
- RemoveCallbackForPinValueChangedEvent(pinNumber, Callback);
-
- return new WaitForEventResult
- {
- TimedOut = !eventOccurred,
- EventTypes = eventOccurred ? typeOfEventOccured : PinEventTypes.None,
- };
- }
- else
- {
- throw ExceptionHelper.GetArgumentException(ExceptionResource.InvalidEventType);
- }
- }
-
- private void WaitForEventResult(CancellationToken sourceToken, CancellationToken parentToken, ref bool eventOccurred)
- {
- while (!(sourceToken.IsCancellationRequested || parentToken.IsCancellationRequested || eventOccurred))
- {
- Thread.Sleep(1);
- }
- }
-
- ///
- protected internal override void Write(int pinNumber, PinValue value)
- {
- if (!_pinNumberToSafeLineHandle.TryGetValue(pinNumber, out SafeLineHandle? pinHandle))
- {
- throw ExceptionHelper.GetInvalidOperationException(ExceptionResource.PinNotOpenedError,
- pin: pinNumber);
- }
-
- Interop.libgpiod.gpiod_line_set_value(pinHandle, (value == PinValue.High) ? 1 : 0);
- }
-
- ///
- protected override void Dispose(bool disposing)
- {
- if (_pinNumberToEventHandler != null)
- {
- foreach (KeyValuePair kv in _pinNumberToEventHandler)
- {
- LibGpiodDriverEventHandler eventHandler = kv.Value;
- eventHandler.Dispose();
- }
-
- _pinNumberToEventHandler.Clear();
- }
-
- if (_pinNumberToSafeLineHandle != null)
- {
- foreach (int pin in _pinNumberToSafeLineHandle.Keys)
- {
- if (_pinNumberToSafeLineHandle.TryGetValue(pin, out SafeLineHandle? pinHandle))
- {
- pinHandle?.Dispose();
- }
- }
-
- _pinNumberToSafeLineHandle.Clear();
- }
-
- _chip?.Dispose();
- _chip = null!;
-
- base.Dispose(disposing);
- }
- }
-}