未验证 提交 b135f814 编写于 作者: J Jose Perez Rodriguez 提交者: GitHub

Bind to explicit major version of libgpiod (#2120)

上级 79a8bcdd
...@@ -17,9 +17,9 @@ internal class SafeChipHandle : SafeHandle ...@@ -17,9 +17,9 @@ internal class SafeChipHandle : SafeHandle
protected override bool ReleaseHandle() protected override bool ReleaseHandle()
{ {
Interop.libgpiod.gpiod_chip_close(handle); Interop.Libgpiod.gpiod_chip_close(handle);
return true; return true;
} }
public override bool IsInvalid => handle == IntPtr.Zero || handle == Interop.libgpiod.InvalidHandleValue; public override bool IsInvalid => handle == IntPtr.Zero || handle == Interop.Libgpiod.InvalidHandleValue;
} }
...@@ -17,9 +17,9 @@ internal class SafeChipIteratorHandle : SafeHandle ...@@ -17,9 +17,9 @@ internal class SafeChipIteratorHandle : SafeHandle
protected override bool ReleaseHandle() protected override bool ReleaseHandle()
{ {
Interop.libgpiod.gpiod_chip_iter_free(handle); Interop.Libgpiod.gpiod_chip_iter_free(handle);
return true; return true;
} }
public override bool IsInvalid => handle == IntPtr.Zero || handle == Interop.libgpiod.InvalidHandleValue; public override bool IsInvalid => handle == IntPtr.Zero || handle == Interop.Libgpiod.InvalidHandleValue;
} }
...@@ -20,17 +20,17 @@ internal class SafeLineHandle : SafeHandle ...@@ -20,17 +20,17 @@ internal class SafeLineHandle : SafeHandle
protected override bool ReleaseHandle() protected override bool ReleaseHandle()
{ {
// Contrary to intuition, this does not invalidate the handle (see comment on declaration) // Contrary to intuition, this does not invalidate the handle (see comment on declaration)
Interop.libgpiod.gpiod_line_release(handle); Interop.Libgpiod.gpiod_line_release(handle);
return true; return true;
} }
/// <summary> /// <summary>
/// Release the lock on the line handle. <see cref="Interop.libgpiod.gpiod_line_release"/> /// Release the lock on the line handle. <see cref="Interop.Libgpiod.gpiod_line_release"/>
/// </summary> /// </summary>
public void ReleaseLock() public void ReleaseLock()
{ {
ReleaseHandle(); ReleaseHandle();
} }
public override bool IsInvalid => handle == IntPtr.Zero || handle == Interop.libgpiod.InvalidHandleValue; public override bool IsInvalid => handle == IntPtr.Zero || handle == Interop.Libgpiod.InvalidHandleValue;
} }
...@@ -8,15 +8,48 @@ ...@@ -8,15 +8,48 @@
using System; using System;
using System.Device.Gpio; using System.Device.Gpio;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
#if NET6_0_OR_GREATER
using System.Runtime.Loader;
using System.Reflection;
#endif
// Since this is only used on Linux, and in C on Linux sizeof(long) == sizeof(void*) this is a valid alias. // Since this is only used on Linux, and in C on Linux sizeof(long) == sizeof(void*) this is a valid alias.
using NativeLong = System.IntPtr; using NativeLong = System.IntPtr;
internal partial class Interop internal partial class Interop
{ {
internal partial class libgpiod internal static partial class Libgpiod
{ {
#if NET6_0_OR_GREATER
private const string LibgpiodLibrary = "libgpiod.so.2";
#else
private const string LibgpiodLibrary = "libgpiod"; private const string LibgpiodLibrary = "libgpiod";
internal static IntPtr InvalidHandleValue = new IntPtr(-1); #endif
internal static IntPtr InvalidHandleValue;
static Libgpiod()
{
InvalidHandleValue = new IntPtr(-1);
#if NET6_0_OR_GREATER
Assembly currentAssembly = typeof(Libgpiod).Assembly;
AssemblyLoadContext.GetLoadContext(currentAssembly)!.ResolvingUnmanagedDll += (assembly, libgpiodName) =>
{
if (assembly != currentAssembly || libgpiodName != LibgpiodLibrary)
{
return IntPtr.Zero;
}
// If loading the 2.x libgpiod failed, we may be running in a Linux distribution that has the 1.x
// version installed, so we try to load that instead.
if (NativeLibrary.TryLoad("libgpiod.so.1", out IntPtr handle))
{
return handle;
}
return IntPtr.Zero;
};
#endif
}
/// <summary> /// <summary>
/// Release all resources allocated for the gpiochip iterator and close the most recently opened gpiochip(if any). /// Release all resources allocated for the gpiochip iterator and close the most recently opened gpiochip(if any).
......
...@@ -31,7 +31,7 @@ public class LibGpiodDriver : UnixDriver ...@@ -31,7 +31,7 @@ public class LibGpiodDriver : UnixDriver
// for use the bias flags we need libgpiod version 1.5 or later // for use the bias flags we need libgpiod version 1.5 or later
private static bool IsLibgpiodVersion1_5orHigher() private static bool IsLibgpiodVersion1_5orHigher()
{ {
IntPtr libgpiodVersionPtr = Interop.libgpiod.gpiod_version_string(); IntPtr libgpiodVersionPtr = Interop.Libgpiod.gpiod_version_string();
string? libgpiodVersionMatch = Marshal.PtrToStringAnsi(libgpiodVersionPtr); string? libgpiodVersionMatch = Marshal.PtrToStringAnsi(libgpiodVersionPtr);
if (libgpiodVersionMatch is object) if (libgpiodVersionMatch is object)
...@@ -69,13 +69,13 @@ public class LibGpiodDriver : UnixDriver ...@@ -69,13 +69,13 @@ public class LibGpiodDriver : UnixDriver
try try
{ {
_pinNumberLock = new object(); _pinNumberLock = new object();
_chip = Interop.libgpiod.gpiod_chip_open_by_number(gpioChip); _chip = Interop.Libgpiod.gpiod_chip_open_by_number(gpioChip);
if (_chip == null) if (_chip == null)
{ {
throw ExceptionHelper.GetIOException(ExceptionResource.NoChipFound, Marshal.GetLastWin32Error()); throw ExceptionHelper.GetIOException(ExceptionResource.NoChipFound, Marshal.GetLastWin32Error());
} }
_pinCount = Interop.libgpiod.gpiod_chip_num_lines(_chip); _pinCount = Interop.Libgpiod.gpiod_chip_num_lines(_chip);
_pinNumberToEventHandler = new ConcurrentDictionary<int, LibGpiodDriverEventHandler>(); _pinNumberToEventHandler = new ConcurrentDictionary<int, LibGpiodDriverEventHandler>();
_pinNumberToSafeLineHandle = new ConcurrentDictionary<int, SafeLineHandle>(); _pinNumberToSafeLineHandle = new ConcurrentDictionary<int, SafeLineHandle>();
_pinValue = new ConcurrentDictionary<int, PinValue>(); _pinValue = new ConcurrentDictionary<int, PinValue>();
...@@ -115,10 +115,10 @@ public class LibGpiodDriver : UnixDriver ...@@ -115,10 +115,10 @@ public class LibGpiodDriver : UnixDriver
{ {
_pinNumberToSafeLineHandle.TryGetValue(pinNumber, out SafeLineHandle? pinHandle); _pinNumberToSafeLineHandle.TryGetValue(pinNumber, out SafeLineHandle? pinHandle);
if (pinHandle is null || (pinHandle is object && !Interop.libgpiod.gpiod_line_is_free(pinHandle))) if (pinHandle is null || (pinHandle is object && !Interop.Libgpiod.gpiod_line_is_free(pinHandle)))
{ {
pinHandle?.Dispose(); pinHandle?.Dispose();
pinHandle = Interop.libgpiod.gpiod_chip_get_line(_chip, pinNumber); pinHandle = Interop.Libgpiod.gpiod_chip_get_line(_chip, pinNumber);
_pinNumberToSafeLineHandle[pinNumber] = pinHandle; _pinNumberToSafeLineHandle[pinNumber] = pinHandle;
} }
...@@ -184,13 +184,13 @@ public class LibGpiodDriver : UnixDriver ...@@ -184,13 +184,13 @@ public class LibGpiodDriver : UnixDriver
return; return;
} }
SafeLineHandle pinHandle = Interop.libgpiod.gpiod_chip_get_line(_chip, pinNumber); SafeLineHandle pinHandle = Interop.Libgpiod.gpiod_chip_get_line(_chip, pinNumber);
if (pinHandle == null) if (pinHandle == null)
{ {
throw ExceptionHelper.GetIOException(ExceptionResource.OpenPinError, Marshal.GetLastWin32Error()); throw ExceptionHelper.GetIOException(ExceptionResource.OpenPinError, Marshal.GetLastWin32Error());
} }
int mode = Interop.libgpiod.gpiod_line_direction(pinHandle); int mode = Interop.Libgpiod.gpiod_line_direction(pinHandle);
if (mode == 1) if (mode == 1)
{ {
pinHandle.PinMode = PinMode.Input; pinHandle.PinMode = PinMode.Input;
...@@ -202,7 +202,7 @@ public class LibGpiodDriver : UnixDriver ...@@ -202,7 +202,7 @@ public class LibGpiodDriver : UnixDriver
if (s_isLibgpiodVersion1_5orHigher && pinHandle.PinMode == PinMode.Input) if (s_isLibgpiodVersion1_5orHigher && pinHandle.PinMode == PinMode.Input)
{ {
int bias = Interop.libgpiod.gpiod_line_bias(pinHandle); int bias = Interop.Libgpiod.gpiod_line_bias(pinHandle);
if (bias == (int)RequestFlag.GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN) if (bias == (int)RequestFlag.GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN)
{ {
pinHandle.PinMode = PinMode.InputPullDown; pinHandle.PinMode = PinMode.InputPullDown;
...@@ -226,7 +226,7 @@ public class LibGpiodDriver : UnixDriver ...@@ -226,7 +226,7 @@ public class LibGpiodDriver : UnixDriver
{ {
if (_pinNumberToSafeLineHandle.TryGetValue(pinNumber, out SafeLineHandle? pinHandle)) if (_pinNumberToSafeLineHandle.TryGetValue(pinNumber, out SafeLineHandle? pinHandle))
{ {
int result = Interop.libgpiod.gpiod_line_get_value(pinHandle); int result = Interop.Libgpiod.gpiod_line_get_value(pinHandle);
if (result == -1) if (result == -1)
{ {
throw ExceptionHelper.GetIOException(ExceptionResource.ReadPinError, Marshal.GetLastWin32Error(), pinNumber); throw ExceptionHelper.GetIOException(ExceptionResource.ReadPinError, Marshal.GetLastWin32Error(), pinNumber);
...@@ -271,12 +271,12 @@ public class LibGpiodDriver : UnixDriver ...@@ -271,12 +271,12 @@ public class LibGpiodDriver : UnixDriver
pinHandle.ReleaseLock(); pinHandle.ReleaseLock();
int requestResult = mode switch int requestResult = mode switch
{ {
PinMode.Input => Interop.libgpiod.gpiod_line_request_input(pinHandle, s_consumerName), PinMode.Input => Interop.Libgpiod.gpiod_line_request_input(pinHandle, s_consumerName),
PinMode.InputPullDown => Interop.libgpiod.gpiod_line_request_input_flags(pinHandle, s_consumerName, PinMode.InputPullDown => Interop.Libgpiod.gpiod_line_request_input_flags(pinHandle, s_consumerName,
(int)RequestFlag.GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN), (int)RequestFlag.GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN),
PinMode.InputPullUp => Interop.libgpiod.gpiod_line_request_input_flags(pinHandle, s_consumerName, PinMode.InputPullUp => Interop.Libgpiod.gpiod_line_request_input_flags(pinHandle, s_consumerName,
(int)RequestFlag.GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP), (int)RequestFlag.GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP),
PinMode.Output => Interop.libgpiod.gpiod_line_request_output(pinHandle, s_consumerName, 0), PinMode.Output => Interop.Libgpiod.gpiod_line_request_output(pinHandle, s_consumerName, 0),
_ => -1, _ => -1,
}; };
...@@ -303,12 +303,12 @@ public class LibGpiodDriver : UnixDriver ...@@ -303,12 +303,12 @@ public class LibGpiodDriver : UnixDriver
pinHandle.ReleaseLock(); pinHandle.ReleaseLock();
int requestResult = mode switch int requestResult = mode switch
{ {
PinMode.Input => Interop.libgpiod.gpiod_line_request_input(pinHandle, s_consumerName), PinMode.Input => Interop.Libgpiod.gpiod_line_request_input(pinHandle, s_consumerName),
PinMode.InputPullDown => Interop.libgpiod.gpiod_line_request_input_flags(pinHandle, s_consumerName, PinMode.InputPullDown => Interop.Libgpiod.gpiod_line_request_input_flags(pinHandle, s_consumerName,
(int)RequestFlag.GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN), (int)RequestFlag.GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN),
PinMode.InputPullUp => Interop.libgpiod.gpiod_line_request_input_flags(pinHandle, s_consumerName, PinMode.InputPullUp => Interop.Libgpiod.gpiod_line_request_input_flags(pinHandle, s_consumerName,
(int)RequestFlag.GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP), (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), PinMode.Output => Interop.Libgpiod.gpiod_line_request_output(pinHandle, s_consumerName, initialValue == PinValue.High ? 1 : 0),
_ => -1, _ => -1,
}; };
...@@ -383,7 +383,7 @@ public class LibGpiodDriver : UnixDriver ...@@ -383,7 +383,7 @@ public class LibGpiodDriver : UnixDriver
pin: pinNumber); pin: pinNumber);
} }
Interop.libgpiod.gpiod_line_set_value(pinHandle, (value == PinValue.High) ? 1 : 0); Interop.Libgpiod.gpiod_line_set_value(pinHandle, (value == PinValue.High) ? 1 : 0);
_pinValue[pinNumber] = value; _pinValue[pinNumber] = value;
} }
...@@ -391,7 +391,7 @@ public class LibGpiodDriver : UnixDriver ...@@ -391,7 +391,7 @@ public class LibGpiodDriver : UnixDriver
public override ComponentInformation QueryComponentInformation() public override ComponentInformation QueryComponentInformation()
{ {
var self = new ComponentInformation(this, "LibGpiodDriver"); var self = new ComponentInformation(this, "LibGpiodDriver");
IntPtr libgpiodVersionPtr = Interop.libgpiod.gpiod_version_string(); IntPtr libgpiodVersionPtr = Interop.Libgpiod.gpiod_version_string();
string libgpiodVersion = Marshal.PtrToStringAnsi(libgpiodVersionPtr) ?? string.Empty; string libgpiodVersion = Marshal.PtrToStringAnsi(libgpiodVersionPtr) ?? string.Empty;
self.Properties["LibGpiodVersion"] = libgpiodVersion; self.Properties["LibGpiodVersion"] = libgpiodVersion;
return self; return self;
......
...@@ -34,7 +34,7 @@ internal sealed class LibGpiodDriverEventHandler : IDisposable ...@@ -34,7 +34,7 @@ internal sealed class LibGpiodDriverEventHandler : IDisposable
private void SubscribeForEvent(SafeLineHandle pinHandle) private void SubscribeForEvent(SafeLineHandle pinHandle)
{ {
int eventSuccess = Interop.libgpiod.gpiod_line_request_both_edges_events(pinHandle, s_consumerName); int eventSuccess = Interop.Libgpiod.gpiod_line_request_both_edges_events(pinHandle, s_consumerName);
if (eventSuccess < 0) if (eventSuccess < 0)
{ {
...@@ -55,7 +55,7 @@ internal sealed class LibGpiodDriverEventHandler : IDisposable ...@@ -55,7 +55,7 @@ internal sealed class LibGpiodDriverEventHandler : IDisposable
TvNsec = new IntPtr(50_000_000) TvNsec = new IntPtr(50_000_000)
}; };
WaitEventResult waitResult = Interop.libgpiod.gpiod_line_event_wait(pinHandle, ref timeout); WaitEventResult waitResult = Interop.Libgpiod.gpiod_line_event_wait(pinHandle, ref timeout);
if (waitResult == WaitEventResult.Error) if (waitResult == WaitEventResult.Error)
{ {
var errorCode = Marshal.GetLastWin32Error(); var errorCode = Marshal.GetLastWin32Error();
...@@ -71,7 +71,7 @@ internal sealed class LibGpiodDriverEventHandler : IDisposable ...@@ -71,7 +71,7 @@ internal sealed class LibGpiodDriverEventHandler : IDisposable
if (waitResult == WaitEventResult.EventOccured) if (waitResult == WaitEventResult.EventOccured)
{ {
GpioLineEvent eventResult = new GpioLineEvent(); GpioLineEvent eventResult = new GpioLineEvent();
int checkForEvent = Interop.libgpiod.gpiod_line_event_read(pinHandle, ref eventResult); int checkForEvent = Interop.Libgpiod.gpiod_line_event_read(pinHandle, ref eventResult);
if (checkForEvent == -1) if (checkForEvent == -1)
{ {
throw ExceptionHelper.GetIOException(ExceptionResource.EventReadError, Marshal.GetLastWin32Error()); throw ExceptionHelper.GetIOException(ExceptionResource.EventReadError, Marshal.GetLastWin32Error());
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册