未验证 提交 942c3e12 编写于 作者: R Rich Lander 提交者: GitHub

Update GPIO library and samples to NRTs (#1215)

* Update GPIO library and samples to NRTs

* Simplify if checks

* Simplify if checks

* Update per feedback

* Fix code style with pragma

* Update NRT annotations

* Update Windows-specific NRT errors

* Remove null check

* Remove type constraint

* Remove null check

* Simplify NRT annotations

* Enable nullable for _pinModes

* Adding a comment to the pragma
Co-authored-by: NJose Perez Rodriguez <joperezr@microsoft.com>
上级 5eeac6ce
......@@ -10,6 +10,7 @@
<NoWarn>$(NoWarn);CS8321;CS1591</NoWarn>
<DeterministicSourcePaths>false</DeterministicSourcePaths>
<IsPackable>false</IsPackable>
<Nullable>enable</Nullable>
<MainLibraryPath>$(MSBuildThisFileDirectory)../src/System.Device.Gpio/</MainLibraryPath>
<IotBindingsLibraryPath>$(MSBuildThisFileDirectory)../src/Iot.Device.Bindings/</IotBindingsLibraryPath>
</PropertyGroup>
......
......@@ -20,11 +20,11 @@ namespace LedMatrixWeather
{
internal partial class Program
{
private static Action<RGBLedMatrix> s_scenario = WeatherDemo;
private static Stopwatch s_showLocalIp = null;
private static string[] s_ips;
private static Action<RGBLedMatrix>? s_scenario = WeatherDemo;
private static Stopwatch? s_showLocalIp = null;
private static string[]? s_ips;
private static bool s_networkAvailable = false;
private static Weather s_client;
private static Weather? s_client;
private static OpenWeatherResponse s_weatherResponse;
private static readonly TimeZoneInfo s_timeZonePst = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
......@@ -55,17 +55,14 @@ namespace LedMatrixWeather
{
matrix.StartRendering();
while (true)
while (s_scenario is object)
{
Action<RGBLedMatrix> scenario = s_scenario;
if (scenario == null)
break;
Stopwatch sw = Stopwatch.StartNew();
scenario(matrix);
if (s_scenario != null && sw.ElapsedMilliseconds < 100)
if (sw.ElapsedMilliseconds < 100)
{
Debug.WriteLine("Scenario execution finished in less than 100ms. This is likely due to bug.");
}
......@@ -76,7 +73,7 @@ namespace LedMatrixWeather
{
if (!Console.IsOutputRedirected)
{
while (s_scenario != null)
while (s_scenario is object)
{
switch (Console.ReadKey(intercept: true).Key)
{
......@@ -127,7 +124,7 @@ namespace LedMatrixWeather
{
try
{
s_weatherResponse = s_client.GetWeatherFromOpenWeather();
s_weatherResponse = s_client!.GetWeatherFromOpenWeather();
s_networkAvailable = true;
}
catch (Exception e)
......@@ -212,7 +209,7 @@ namespace LedMatrixWeather
return (byte)Math.Clamp(x * 255, 0, 255);
}
string text = null;
string text = string.Empty;
int fullTextWidth = 0;
Stopwatch sw = Stopwatch.StartNew();
......
......@@ -25,7 +25,7 @@ namespace led_more_blinking_lights
// volume support
var initialSleep = 100;
var sleep = initialSleep;
Volume volume = null;
Volume? volume = null;
// this line should only be enabled if a trimpot is connected
volume = Volume.EnableVolume();
......@@ -87,7 +87,7 @@ namespace led_more_blinking_lights
}
// behavior for buttonOne
if (volume != null)
if (volume is object)
{
var update = true;
var value = 0;
......

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
MinimumVisualStudioVersion = 15.0.26124.0
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "force-sensitive-resistor", "force-sensitive-resistor\force-sensitive-resistor.csproj", "{61530E24-4BF0-4FE0-9523-F283AD529E7B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "led-blink", "led-blink\led-blink.csproj", "{3151F9FD-175A-4CFE-B8B7-51A4B02EB4E9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "led-matrix-weather", "led-matrix-weather\led-matrix-weather.csproj", "{C36FF5D4-0159-4588-8384-B23F07DD1827}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "led-more-blinking-lights", "led-more-blinking-lights\led-more-blinking-lights.csproj", "{6B3DB7E2-FDFA-4429-936F-1C0854388C9E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "serialport_arduino", "serialport-arduino\serialport_arduino.csproj", "{5B81A152-AA24-4CFE-B774-CA034F09F749}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{61530E24-4BF0-4FE0-9523-F283AD529E7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{61530E24-4BF0-4FE0-9523-F283AD529E7B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{61530E24-4BF0-4FE0-9523-F283AD529E7B}.Debug|x64.ActiveCfg = Debug|Any CPU
{61530E24-4BF0-4FE0-9523-F283AD529E7B}.Debug|x64.Build.0 = Debug|Any CPU
{61530E24-4BF0-4FE0-9523-F283AD529E7B}.Debug|x86.ActiveCfg = Debug|Any CPU
{61530E24-4BF0-4FE0-9523-F283AD529E7B}.Debug|x86.Build.0 = Debug|Any CPU
{61530E24-4BF0-4FE0-9523-F283AD529E7B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{61530E24-4BF0-4FE0-9523-F283AD529E7B}.Release|Any CPU.Build.0 = Release|Any CPU
{61530E24-4BF0-4FE0-9523-F283AD529E7B}.Release|x64.ActiveCfg = Release|Any CPU
{61530E24-4BF0-4FE0-9523-F283AD529E7B}.Release|x64.Build.0 = Release|Any CPU
{61530E24-4BF0-4FE0-9523-F283AD529E7B}.Release|x86.ActiveCfg = Release|Any CPU
{61530E24-4BF0-4FE0-9523-F283AD529E7B}.Release|x86.Build.0 = Release|Any CPU
{3151F9FD-175A-4CFE-B8B7-51A4B02EB4E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3151F9FD-175A-4CFE-B8B7-51A4B02EB4E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3151F9FD-175A-4CFE-B8B7-51A4B02EB4E9}.Debug|x64.ActiveCfg = Debug|Any CPU
{3151F9FD-175A-4CFE-B8B7-51A4B02EB4E9}.Debug|x64.Build.0 = Debug|Any CPU
{3151F9FD-175A-4CFE-B8B7-51A4B02EB4E9}.Debug|x86.ActiveCfg = Debug|Any CPU
{3151F9FD-175A-4CFE-B8B7-51A4B02EB4E9}.Debug|x86.Build.0 = Debug|Any CPU
{3151F9FD-175A-4CFE-B8B7-51A4B02EB4E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3151F9FD-175A-4CFE-B8B7-51A4B02EB4E9}.Release|Any CPU.Build.0 = Release|Any CPU
{3151F9FD-175A-4CFE-B8B7-51A4B02EB4E9}.Release|x64.ActiveCfg = Release|Any CPU
{3151F9FD-175A-4CFE-B8B7-51A4B02EB4E9}.Release|x64.Build.0 = Release|Any CPU
{3151F9FD-175A-4CFE-B8B7-51A4B02EB4E9}.Release|x86.ActiveCfg = Release|Any CPU
{3151F9FD-175A-4CFE-B8B7-51A4B02EB4E9}.Release|x86.Build.0 = Release|Any CPU
{C36FF5D4-0159-4588-8384-B23F07DD1827}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C36FF5D4-0159-4588-8384-B23F07DD1827}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C36FF5D4-0159-4588-8384-B23F07DD1827}.Debug|x64.ActiveCfg = Debug|Any CPU
{C36FF5D4-0159-4588-8384-B23F07DD1827}.Debug|x64.Build.0 = Debug|Any CPU
{C36FF5D4-0159-4588-8384-B23F07DD1827}.Debug|x86.ActiveCfg = Debug|Any CPU
{C36FF5D4-0159-4588-8384-B23F07DD1827}.Debug|x86.Build.0 = Debug|Any CPU
{C36FF5D4-0159-4588-8384-B23F07DD1827}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C36FF5D4-0159-4588-8384-B23F07DD1827}.Release|Any CPU.Build.0 = Release|Any CPU
{C36FF5D4-0159-4588-8384-B23F07DD1827}.Release|x64.ActiveCfg = Release|Any CPU
{C36FF5D4-0159-4588-8384-B23F07DD1827}.Release|x64.Build.0 = Release|Any CPU
{C36FF5D4-0159-4588-8384-B23F07DD1827}.Release|x86.ActiveCfg = Release|Any CPU
{C36FF5D4-0159-4588-8384-B23F07DD1827}.Release|x86.Build.0 = Release|Any CPU
{6B3DB7E2-FDFA-4429-936F-1C0854388C9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6B3DB7E2-FDFA-4429-936F-1C0854388C9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6B3DB7E2-FDFA-4429-936F-1C0854388C9E}.Debug|x64.ActiveCfg = Debug|Any CPU
{6B3DB7E2-FDFA-4429-936F-1C0854388C9E}.Debug|x64.Build.0 = Debug|Any CPU
{6B3DB7E2-FDFA-4429-936F-1C0854388C9E}.Debug|x86.ActiveCfg = Debug|Any CPU
{6B3DB7E2-FDFA-4429-936F-1C0854388C9E}.Debug|x86.Build.0 = Debug|Any CPU
{6B3DB7E2-FDFA-4429-936F-1C0854388C9E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6B3DB7E2-FDFA-4429-936F-1C0854388C9E}.Release|Any CPU.Build.0 = Release|Any CPU
{6B3DB7E2-FDFA-4429-936F-1C0854388C9E}.Release|x64.ActiveCfg = Release|Any CPU
{6B3DB7E2-FDFA-4429-936F-1C0854388C9E}.Release|x64.Build.0 = Release|Any CPU
{6B3DB7E2-FDFA-4429-936F-1C0854388C9E}.Release|x86.ActiveCfg = Release|Any CPU
{6B3DB7E2-FDFA-4429-936F-1C0854388C9E}.Release|x86.Build.0 = Release|Any CPU
{9B019F9E-0645-43F5-9AE1-F468B02E6061}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9B019F9E-0645-43F5-9AE1-F468B02E6061}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9B019F9E-0645-43F5-9AE1-F468B02E6061}.Debug|x64.ActiveCfg = Debug|Any CPU
{9B019F9E-0645-43F5-9AE1-F468B02E6061}.Debug|x64.Build.0 = Debug|Any CPU
{9B019F9E-0645-43F5-9AE1-F468B02E6061}.Debug|x86.ActiveCfg = Debug|Any CPU
{9B019F9E-0645-43F5-9AE1-F468B02E6061}.Debug|x86.Build.0 = Debug|Any CPU
{9B019F9E-0645-43F5-9AE1-F468B02E6061}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9B019F9E-0645-43F5-9AE1-F468B02E6061}.Release|Any CPU.Build.0 = Release|Any CPU
{9B019F9E-0645-43F5-9AE1-F468B02E6061}.Release|x64.ActiveCfg = Release|Any CPU
{9B019F9E-0645-43F5-9AE1-F468B02E6061}.Release|x64.Build.0 = Release|Any CPU
{9B019F9E-0645-43F5-9AE1-F468B02E6061}.Release|x86.ActiveCfg = Release|Any CPU
{9B019F9E-0645-43F5-9AE1-F468B02E6061}.Release|x86.Build.0 = Release|Any CPU
{5B81A152-AA24-4CFE-B774-CA034F09F749}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5B81A152-AA24-4CFE-B774-CA034F09F749}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B81A152-AA24-4CFE-B774-CA034F09F749}.Debug|x64.ActiveCfg = Debug|Any CPU
{5B81A152-AA24-4CFE-B774-CA034F09F749}.Debug|x64.Build.0 = Debug|Any CPU
{5B81A152-AA24-4CFE-B774-CA034F09F749}.Debug|x86.ActiveCfg = Debug|Any CPU
{5B81A152-AA24-4CFE-B774-CA034F09F749}.Debug|x86.Build.0 = Debug|Any CPU
{5B81A152-AA24-4CFE-B774-CA034F09F749}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5B81A152-AA24-4CFE-B774-CA034F09F749}.Release|Any CPU.Build.0 = Release|Any CPU
{5B81A152-AA24-4CFE-B774-CA034F09F749}.Release|x64.ActiveCfg = Release|Any CPU
{5B81A152-AA24-4CFE-B774-CA034F09F749}.Release|x64.Build.0 = Release|Any CPU
{5B81A152-AA24-4CFE-B774-CA034F09F749}.Release|x86.ActiveCfg = Release|Any CPU
{5B81A152-AA24-4CFE-B774-CA034F09F749}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>arduino_demo</RootNamespace>
<RuntimeIdentifier>linux-arm</RuntimeIdentifier>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Device.Gpio" Version="1.1.0-prerelease.20153.1" />
<PackageReference Include="Iot.Device.Bindings" Version="1.1.0-prerelease.20153.1" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>arduino_demo</RootNamespace>
<RuntimeIdentifier>linux-arm</RuntimeIdentifier>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Device.Gpio" Version="1.1.0-prerelease.20153.1" />
<PackageReference Include="Iot.Device.Bindings" Version="1.1.0-prerelease.20153.1" />
</ItemGroup>
</Project>
......@@ -6,6 +6,7 @@
<Description>The System.Device.Gpio package supports general-purpose I/O (GPIO) pins, PWM, I2C, SPI and related interfaces for interacting with low level hardware pins to control hardware sensors, displays and input devices on single-board-computers; Raspberry Pi, BeagleBoard, HummingBoard, ODROID, and other single-board-computers that are supported by Linux and Windows 10 IoT Core OS can be used with .NET Core and System.Device.Gpio. On Windows 10 IoT Core OS, the library wraps the Windows.Devices.Gpio.dll assembly. On Linux, the library supports three driver modes: libgpiod for fast full-featured GPIO access on all Linux distros since version 4.8 of the Linux kernel; slower and limited-functionality GPIO access via the deprecated Sysfs interface (/sys/class/gpio) when running on older Linux distro versions with a Linux kernel older than version 4.8; and lastly board-specific Linux drivers that access GPIO addresses in /dev/mem for fasted performance at the trade-off of being able to run on very specific versions of single-board-computers. In the future, the board-specific Linux drivers may be removed in favor of only supporting libgpiod and sysfs Linux interfaces. In addition to System.Device.Gpio, the optional IoT.Device.Bindings NuGet package contains device bindings for many sensors, displays, and input devices that can be used with System.Device.Gpio.
</Description>
<PackageTags>.NET Core GPIO Pins SPI I2C PWM BCM2835 RPi IoT</PackageTags>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="..\..\Directory.Build.props" />
......
......@@ -8,7 +8,7 @@ using Windows.Foundation;
internal static partial class Interop
{
public static TResult WaitForCompletion<TResult>(this IAsyncOperation<TResult> operation)
public static TResult? WaitForCompletion<TResult>(this IAsyncOperation<TResult> operation)
{
using (var waitEvent = new ManualResetEvent(false))
{
......
......@@ -102,7 +102,7 @@ namespace System.Device.Gpio.Drivers
protected override void Dispose(bool disposing)
{
_internalDriver?.Dispose();
_internalDriver = null;
_internalDriver = null!;
base.Dispose(disposing);
}
}
......
......@@ -45,7 +45,7 @@ namespace System.Device.Gpio.Drivers
if (disposing)
{
// not our instance
_gpioDriver = null;
_gpioDriver = null!;
}
base.Dispose(disposing);
......
......@@ -31,10 +31,15 @@ namespace System.Device.Gpio.Drivers
private static bool IsLibgpiodVersion1_5orHigher()
{
IntPtr libgpiodVersionPtr = Interop.libgpiod.gpiod_version_string();
string libgpiodVersionMatch = Marshal.PtrToStringAnsi(libgpiodVersionPtr);
Version libgpiodVersion = new Version(libgpiodVersionMatch);
string? libgpiodVersionMatch = Marshal.PtrToStringAnsi(libgpiodVersionPtr);
return (libgpiodVersion.Major >= 1 && libgpiodVersion.Minor >= 5);
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();
......@@ -106,17 +111,16 @@ namespace System.Device.Gpio.Drivers
{
lock (_pinNumberLock)
{
if (_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 (!Interop.libgpiod.gpiod_line_is_free(pinHandle))
{
pinHandle.Dispose();
pinHandle = Interop.libgpiod.gpiod_chip_get_line(_chip, pinNumber);
_pinNumberToSafeLineHandle[pinNumber] = pinHandle;
}
pinHandle?.Dispose();
pinHandle = Interop.libgpiod.gpiod_chip_get_line(_chip, pinNumber);
_pinNumberToSafeLineHandle[pinNumber] = pinHandle;
}
return new LibGpiodDriverEventHandler(pinNumber, pinHandle);
return new LibGpiodDriverEventHandler(pinNumber, pinHandle!);
}
}
......@@ -125,7 +129,7 @@ namespace System.Device.Gpio.Drivers
{
lock (_pinNumberLock)
{
if (_pinNumberToSafeLineHandle.TryGetValue(pinNumber, out SafeLineHandle pinHandle) &&
if (_pinNumberToSafeLineHandle.TryGetValue(pinNumber, out SafeLineHandle? pinHandle) &&
!IsListeningEvent(pinNumber))
{
pinHandle?.Dispose();
......@@ -149,7 +153,7 @@ namespace System.Device.Gpio.Drivers
{
lock (_pinNumberLock)
{
if (!_pinNumberToSafeLineHandle.TryGetValue(pinNumber, out SafeLineHandle pinHandle))
if (!_pinNumberToSafeLineHandle.TryGetValue(pinNumber, out SafeLineHandle? pinHandle))
{
throw ExceptionHelper.GetInvalidOperationException(ExceptionResource.PinNotOpenedError,
pin: pinNumber);
......@@ -199,7 +203,7 @@ namespace System.Device.Gpio.Drivers
/// <inheritdoc/>
protected internal override PinValue Read(int pinNumber)
{
if (_pinNumberToSafeLineHandle.TryGetValue(pinNumber, out SafeLineHandle pinHandle))
if (_pinNumberToSafeLineHandle.TryGetValue(pinNumber, out SafeLineHandle? pinHandle))
{
int result = Interop.libgpiod.gpiod_line_get_value(pinHandle);
if (result == -1)
......@@ -216,14 +220,14 @@ namespace System.Device.Gpio.Drivers
/// <inheritdoc/>
protected internal override void RemoveCallbackForPinValueChangedEvent(int pinNumber, PinChangeEventHandler callback)
{
if (_pinNumberToEventHandler.TryGetValue(pinNumber, out LibGpiodDriverEventHandler eventHandler))
if (_pinNumberToEventHandler.TryGetValue(pinNumber, out LibGpiodDriverEventHandler? eventHandler))
{
eventHandler.ValueFalling -= callback;
eventHandler.ValueRising -= callback;
if (eventHandler.IsCallbackListEmpty())
{
_pinNumberToEventHandler.TryRemove(pinNumber, out eventHandler);
eventHandler.Dispose();
eventHandler?.Dispose();
}
}
else
......@@ -236,7 +240,7 @@ namespace System.Device.Gpio.Drivers
protected internal override void SetPinMode(int pinNumber, PinMode mode)
{
int requestResult = -1;
if (_pinNumberToSafeLineHandle.TryGetValue(pinNumber, out SafeLineHandle pinHandle))
if (_pinNumberToSafeLineHandle.TryGetValue(pinNumber, out SafeLineHandle? pinHandle))
{
switch (mode)
{
......@@ -317,7 +321,7 @@ namespace System.Device.Gpio.Drivers
/// <inheritdoc/>
protected internal override void Write(int pinNumber, PinValue value)
{
if (!_pinNumberToSafeLineHandle.TryGetValue(pinNumber, out SafeLineHandle pinHandle))
if (!_pinNumberToSafeLineHandle.TryGetValue(pinNumber, out SafeLineHandle? pinHandle))
{
throw ExceptionHelper.GetInvalidOperationException(ExceptionResource.PinNotOpenedError,
pin: pinNumber);
......@@ -344,7 +348,7 @@ namespace System.Device.Gpio.Drivers
{
foreach (int pin in _pinNumberToSafeLineHandle.Keys)
{
if (_pinNumberToSafeLineHandle.TryGetValue(pin, out SafeLineHandle pinHandle))
if (_pinNumberToSafeLineHandle.TryGetValue(pin, out SafeLineHandle? pinHandle))
{
pinHandle?.Dispose();
}
......@@ -354,7 +358,7 @@ namespace System.Device.Gpio.Drivers
}
_chip?.Dispose();
_chip = null;
_chip = null!;
base.Dispose(disposing);
}
......
......@@ -32,7 +32,7 @@ namespace System.Device.Gpio.Drivers
{
if (Environment.OSVersion.Platform == PlatformID.Unix)
{
RaspberryPi3LinuxDriver linuxDriver = CreateInternalRaspberryPi3LinuxDriver(out RaspberryBoardInfo boardInfo);
RaspberryPi3LinuxDriver? linuxDriver = CreateInternalRaspberryPi3LinuxDriver(out RaspberryBoardInfo boardInfo);
if (linuxDriver == null)
{
......@@ -71,10 +71,10 @@ namespace System.Device.Gpio.Drivers
}
}
internal static RaspberryPi3LinuxDriver CreateInternalRaspberryPi3LinuxDriver(out RaspberryBoardInfo boardInfo)
internal static RaspberryPi3LinuxDriver? CreateInternalRaspberryPi3LinuxDriver(out RaspberryBoardInfo boardInfo)
{
RaspberryBoardInfo identification = RaspberryBoardInfo.LoadBoardInfo();
RaspberryPi3LinuxDriver linuxDriver;
RaspberryPi3LinuxDriver? linuxDriver;
boardInfo = identification;
switch (identification.BoardModel)
{
......@@ -172,7 +172,7 @@ namespace System.Device.Gpio.Drivers
protected override void Dispose(bool disposing)
{
_internalDriver?.Dispose();
_internalDriver = null;
_internalDriver = null!;
base.Dispose(disposing);
}
}
......
......@@ -10,6 +10,8 @@ using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
#pragma warning disable SA1011 // Closing square brackets should be spaced correctly https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2927
namespace System.Device.Gpio.Drivers
{
/// <summary>
......@@ -29,11 +31,11 @@ namespace System.Device.Gpio.Drivers
private const string DeviceTreeRanges = "/proc/device-tree/soc/ranges";
private const string ModelFilePath = "/proc/device-tree/model";
private readonly PinState[] _pinModes;
private readonly PinState?[] _pinModes;
private RegisterView* _registerViewPointer = null;
private static readonly object s_initializationLock = new object();
private UnixDriver _interruptDriver = null;
private UnixDriver? _interruptDriver = null;
/// <summary>
/// Returns true if this is a Raspberry Pi4
......@@ -113,9 +115,8 @@ namespace System.Device.Gpio.Drivers
{
ValidatePinNumber(pinNumber);
_interruptDriver.OpenPin(pinNumber);
_pinModes[pinNumber].InUseByInterruptDriver = true;
_interruptDriver!.OpenPin(pinNumber);
_pinModes[pinNumber]!.InUseByInterruptDriver = true;
_interruptDriver.AddCallbackForPinValueChangedEvent(pinNumber, eventTypes, callback);
}
......@@ -127,10 +128,9 @@ namespace System.Device.Gpio.Drivers
{
ValidatePinNumber(pinNumber);
bool isOpen = _pinModes[pinNumber] != null && _pinModes[pinNumber].InUseByInterruptDriver;
if (isOpen)
if (_pinModes[pinNumber]?.InUseByInterruptDriver ?? false)
{
_interruptDriver.ClosePin(pinNumber);
_interruptDriver!.ClosePin(pinNumber);
}
// Set pin low and mode to input upon closing a pin
......@@ -197,8 +197,8 @@ namespace System.Device.Gpio.Drivers
{
ValidatePinNumber(pinNumber);
_interruptDriver.OpenPin(pinNumber);
_pinModes[pinNumber].InUseByInterruptDriver = true;
_interruptDriver!.OpenPin(pinNumber);
_pinModes[pinNumber]!.InUseByInterruptDriver = true;
_interruptDriver.RemoveCallbackForPinValueChangedEvent(pinNumber, callback);
}
......@@ -234,9 +234,9 @@ namespace System.Device.Gpio.Drivers
register |= (mode == PinMode.Output ? 1u : 0u) << shift;
*registerPointer = register;
if (_pinModes[pinNumber] != null)
if (_pinModes[pinNumber] is object)
{
_pinModes[pinNumber].CurrentPinMode = mode;
_pinModes[pinNumber]!.CurrentPinMode = mode;
}
else
{
......@@ -378,8 +378,8 @@ namespace System.Device.Gpio.Drivers
{
ValidatePinNumber(pinNumber);
_interruptDriver.OpenPin(pinNumber);
_pinModes[pinNumber].InUseByInterruptDriver = true;
_interruptDriver!.OpenPin(pinNumber);
_pinModes[pinNumber]!.InUseByInterruptDriver = true;
return _interruptDriver.WaitForEvent(pinNumber, eventTypes, cancellationToken);
}
......@@ -395,8 +395,8 @@ namespace System.Device.Gpio.Drivers
{
ValidatePinNumber(pinNumber);
_interruptDriver.OpenPin(pinNumber);
_pinModes[pinNumber].InUseByInterruptDriver = true;
_interruptDriver!.OpenPin(pinNumber);
_pinModes[pinNumber]!.InUseByInterruptDriver = true;
return _interruptDriver.WaitForEventAsync(pinNumber, eventTypes, cancellationToken);
}
......@@ -623,11 +623,8 @@ namespace System.Device.Gpio.Drivers
_registerViewPointer = null;
}
if (_interruptDriver != null)
{
_interruptDriver.Dispose();
_interruptDriver = null;
}
_interruptDriver?.Dispose();
_interruptDriver = null;
}
private class PinState
......
......@@ -28,7 +28,7 @@ namespace System.Device.Gpio.Drivers
private static readonly int s_pinOffset = ReadOffset();
private TimeSpan _statusUpdateSleepTime = TimeSpan.FromMilliseconds(1);
private int _pollFileDescriptor = -1;
private Thread _eventDetectionThread;
private Thread? _eventDetectionThread;
private int _pinsToDetectEventsCount;
private static int ReadOffset()
......
......@@ -32,7 +32,7 @@ namespace System.Device.Gpio.Drivers
throw new PlatformNotSupportedException(nameof(UnixDriver) + " is only supported on Linux/Unix");
}
UnixDriver driver = null;
UnixDriver? driver = null;
try
{
driver = new LibGpiodDriver();
......
......@@ -13,8 +13,8 @@ namespace System.Device.Gpio.Drivers
ActiveEdges = PinEventTypes.None;
}
public event PinChangeEventHandler ValueRising;
public event PinChangeEventHandler ValueFalling;
public event PinChangeEventHandler? ValueRising;
public event PinChangeEventHandler? ValueFalling;
public int FileDescriptor;
......
......@@ -67,7 +67,7 @@ namespace System.Device.Gpio.Drivers
/// <param name="pinNumber">The pin number in the driver's logical numbering scheme.</param>
protected internal override void ClosePin(int pinNumber)
{
if (_openPins.TryGetValue(pinNumber, out Windows10DriverPin pin))
if (_openPins.TryGetValue(pinNumber, out Windows10DriverPin? pin))
{
pin.ClosePin();
_openPins.Remove(pinNumber);
......
......@@ -16,8 +16,8 @@ namespace System.Device.Gpio.Drivers
private readonly int _pinNumber;
private WeakReference<Windows10Driver> _driver;
private WinGpio.GpioPin _pin;
private PinChangeEventHandler _risingCallbacks;
private PinChangeEventHandler _fallingCallbacks;
private PinChangeEventHandler? _risingCallbacks;
private PinChangeEventHandler? _fallingCallbacks;
public Windows10DriverPin(Windows10Driver driver, WinGpio.GpioPin pin)
{
......@@ -40,10 +40,10 @@ namespace System.Device.Gpio.Drivers
{
_pin.ValueChanged -= Pin_ValueChanged;
_pin.Dispose();
_pin = null;
_pin = null!;
}
_driver = null;
_driver = null!;
_fallingCallbacks = null;
_risingCallbacks = null;
GC.SuppressFinalize(this);
......@@ -76,7 +76,7 @@ namespace System.Device.Gpio.Drivers
private void Pin_ValueChanged(WinGpio.GpioPin sender, WinGpio.GpioPinValueChangedEventArgs args)
{
if (!_driver.TryGetTarget(out Windows10Driver driver))
if (!_driver.TryGetTarget(out Windows10Driver? driver))
{
return;
}
......
......@@ -381,9 +381,9 @@ namespace System.Device.Gpio
/// <returns>A driver that works with the board the program is executing on.</returns>
private static GpioDriver GetBestDriverForBoardOnLinux()
{
RaspberryPi3LinuxDriver internalDriver = RaspberryPi3Driver.CreateInternalRaspberryPi3LinuxDriver(out _);
RaspberryPi3LinuxDriver? internalDriver = RaspberryPi3Driver.CreateInternalRaspberryPi3LinuxDriver(out _);
if (internalDriver != null)
if (internalDriver is object)
{
return new RaspberryPi3Driver(internalDriver);
}
......@@ -403,7 +403,12 @@ namespace System.Device.Gpio
/// </remarks>
private static GpioDriver GetBestDriverForBoardOnWindows()
{
string baseBoardProduct = Registry.LocalMachine.GetValue(BaseBoardProductRegistryValue, string.Empty).ToString();
string? baseBoardProduct = Registry.LocalMachine.GetValue(BaseBoardProductRegistryValue, string.Empty).ToString();
if (baseBoardProduct is null)
{
throw new Exception("Single board computer type cannot be detected.");
}
if (baseBoardProduct == RaspberryPi3Product || baseBoardProduct.StartsWith($"{RaspberryPi3Product} ") ||
baseBoardProduct == RaspberryPi2Product || baseBoardProduct.StartsWith($"{RaspberryPi2Product} "))
......
......@@ -11,9 +11,9 @@ namespace System.Device.Gpio.Drivers
{
internal sealed class LibGpiodDriverEventHandler : IDisposable
{
public event PinChangeEventHandler ValueRising;
public event PinChangeEventHandler? ValueRising;
public event PinChangeEventHandler ValueFalling;
public event PinChangeEventHandler? ValueFalling;
private int _pinNumber;
......
......@@ -62,7 +62,7 @@ namespace System.Device.Gpio
public bool Equals(PinValue other) => other._value == _value;
/// <inheritdoc cref="ValueType.Equals(object)"/>
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
if (obj is PinValue)
{
......
......@@ -96,23 +96,17 @@ namespace System.Device.Gpio
private RaspberryBoardInfo(Dictionary<string, string> settings)
{
_settings = settings;
Firmware = 0;
ProcessorName = string.Empty;
if (_settings.TryGetValue("Hardware", out string hardware))
{
ProcessorName = hardware;
}
ProcessorName = _settings.TryGetValue("Hardware", out string? hardware) && hardware is object ? hardware : string.Empty;
if (_settings.TryGetValue("Revision", out string revision)
if (_settings.TryGetValue("Revision", out string? revision)
&& !string.IsNullOrEmpty(revision)
&& int.TryParse(revision, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out int firmware))
{
Firmware = firmware;
}
if (_settings.TryGetValue("Serial", out string serial)
&& !string.IsNullOrEmpty(serial))
if (_settings.TryGetValue("Serial", out string? serial))
{
SerialNumber = serial;
}
......@@ -215,7 +209,7 @@ namespace System.Device.Gpio
/// <summary>
/// Gets the serial number.
/// </summary>
public string SerialNumber
public string? SerialNumber
{
get;
}
......@@ -230,8 +224,7 @@ namespace System.Device.Gpio
{
get
{
var firmware = Firmware;
return (firmware & 0xFFFF0000) != 0;
return (Firmware & 0xFFFF0000) != 0;
}
}
......
......@@ -27,17 +27,19 @@ namespace System.Device.I2c
string busFriendlyName = $"I2C{settings.BusId}";
string deviceSelector = WinI2c.I2cDevice.GetDeviceSelector(busFriendlyName);
DeviceInformationCollection deviceInformationCollection = DeviceInformation.FindAllAsync(deviceSelector).WaitForCompletion();
if (deviceInformationCollection.Count == 0)
DeviceInformationCollection? deviceInformationCollection = DeviceInformation.FindAllAsync(deviceSelector).WaitForCompletion();
if (deviceInformationCollection is null || deviceInformationCollection.Count == 0)
{
throw new ArgumentException($"No I2C device exists for bus ID {settings.BusId}.", $"{nameof(settings)}.{nameof(settings.BusId)}");
}
_winI2cDevice = WinI2c.I2cDevice.FromIdAsync(deviceInformationCollection[0].Id, winSettings).WaitForCompletion();
if (_winI2cDevice == null)
WinI2c.I2cDevice? winI2cDevice = WinI2c.I2cDevice.FromIdAsync(deviceInformationCollection[0].Id, winSettings).WaitForCompletion();
if (winI2cDevice == null)
{
throw new PlatformNotSupportedException($"I2C devices are not supported.");
throw new PlatformNotSupportedException("An I2C device could not be found.");
}
_winI2cDevice = winI2cDevice;
}
/// <summary>
......@@ -123,7 +125,7 @@ namespace System.Device.I2c
protected override void Dispose(bool disposing)
{
_winI2cDevice?.Dispose();
_winI2cDevice = null;
_winI2cDevice = null!;
base.Dispose(disposing);
}
......
......@@ -235,9 +235,9 @@ namespace System.Device.Pwm.Channels
protected override void Dispose(bool disposing)
{
_dutyCycleWriter?.Dispose();
_dutyCycleWriter = null;
_dutyCycleWriter = null!;
_frequencyWriter?.Dispose();
_frequencyWriter = null;
_frequencyWriter = null!;
Close();
base.Dispose(disposing);
}
......
......@@ -42,21 +42,28 @@ namespace System.Device.Pwm.Channels
// Open the Windows PWM controller for the specified PWM chip.
string deviceSelector = useDefaultChip ? WinPwm.PwmController.GetDeviceSelector() : WinPwm.PwmController.GetDeviceSelector($"PWM{chip}");
DeviceInformationCollection deviceInformationCollection = DeviceInformation.FindAllAsync(deviceSelector).WaitForCompletion();
if (deviceInformationCollection.Count == 0)
DeviceInformationCollection? deviceInformationCollection = DeviceInformation.FindAllAsync(deviceSelector).WaitForCompletion();
if (deviceInformationCollection is null || deviceInformationCollection.Count == 0)
{
throw new ArgumentException($"No PWM device exists for PWM chip at index {chip}.", nameof(chip));
}
string deviceId = deviceInformationCollection[0].Id;
_winController = WinPwm.PwmController.FromIdAsync(deviceId).WaitForCompletion();
WinPwm.PwmController? winController = WinPwm.PwmController.FromIdAsync(deviceId).WaitForCompletion();
_winPin = _winController.OpenPin(channel);
if (_winPin == null)
if (winController is null)
{
throw new Exception("A PWM device could not be found.");
}
WinPwm.PwmPin? winPin = winController.OpenPin(channel);
if (winPin is null)
{
throw new ArgumentOutOfRangeException($"The PWM chip is unable to open a channel at index {channel}.", nameof(channel));
}
_winController = winController;
_winPin = winPin;
Frequency = frequency;
DutyCycle = dutyCycle;
}
......@@ -111,8 +118,8 @@ namespace System.Device.Pwm.Channels
{
Stop();
_winPin?.Dispose();
_winPin = null;
_winController = null;
_winPin = null!;
_winController = null!;
base.Dispose(disposing);
}
}
......
......@@ -44,13 +44,20 @@ namespace System.Device.Spi
string busFriendlyName = $"SPI{settings.BusId}";
string deviceSelector = WinSpi.SpiDevice.GetDeviceSelector(busFriendlyName);
DeviceInformationCollection deviceInformationCollection = DeviceInformation.FindAllAsync(deviceSelector).WaitForCompletion();
if (deviceInformationCollection.Count == 0)
DeviceInformationCollection? deviceInformationCollection = DeviceInformation.FindAllAsync(deviceSelector).WaitForCompletion();
if (deviceInformationCollection is null || deviceInformationCollection.Count == 0)
{
throw new ArgumentException($"No SPI device exists for bus ID {settings.BusId}.", $"{nameof(settings)}.{nameof(settings.BusId)}");
}
_winDevice = WinSpi.SpiDevice.FromIdAsync(deviceInformationCollection[0].Id, winSettings).WaitForCompletion();
WinSpi.SpiDevice? winDevice = WinSpi.SpiDevice.FromIdAsync(deviceInformationCollection[0].Id, winSettings).WaitForCompletion();
if (winDevice is null)
{
throw new Exception("A SPI device could not be found.");
}
_winDevice = winDevice;
}
/// <summary>
......@@ -129,7 +136,7 @@ namespace System.Device.Spi
protected override void Dispose(bool disposing)
{
_winDevice?.Dispose();
_winDevice = null;
_winDevice = null!;
base.Dispose(disposing);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册