Skip to content

Commit

Permalink
Merge pull request #4 from badcel/support-connection-via-serial-number
Browse files Browse the repository at this point in the history
Support connection via serial number
  • Loading branch information
badcel authored Oct 27, 2022
2 parents cca7514 + 0620ae4 commit 6447035
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 4 deletions.
13 changes: 13 additions & 0 deletions src/HidApi.Net.Tests/StringTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,17 @@ public void TestUtf32()
}
}
}


[TestMethod]
public unsafe void CanCreateNullTerminatedString()
{
var result = "MyString";
var nullTerminatedString = WCharT.CreateNullTerminatedString(result);
fixed (byte* ptr = nullTerminatedString)
{
var r = WCharT.GetString(ptr);
r.Should().Be(result);
}
}
}
16 changes: 15 additions & 1 deletion src/HidApi.Net/Device.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,21 @@ public class Device : IDisposable
/// <param name="productId">product id of target device</param>
public Device(ushort vendorId, ushort productId)
{
handle = NativeMethods.Open(vendorId, productId, string.Empty);
handle = NativeMethods.Open(vendorId, productId, NullTerminatedString.Empty);

if (handle.IsInvalid)
HidException.Throw(handle);
}

/// <summary>
/// Connects to a given device.
/// </summary>
/// <param name="vendorId">Vendor id of target device</param>
/// <param name="productId">Product id of target device</param>
/// <param name="serialNumber">Serial number of target device</param>
public Device(ushort vendorId, ushort productId, string serialNumber)
{
handle = NativeMethods.Open(vendorId, productId, WCharT.CreateNullTerminatedString(serialNumber));

if (handle.IsInvalid)
HidException.Throw(handle);
Expand Down
4 changes: 2 additions & 2 deletions src/HidApi.Net/HidApi.Net.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<VersionPrefix>0.1.2</VersionPrefix>
<VersionPrefix>0.2.0</VersionPrefix>

<RootNamespace>HidApi</RootNamespace>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
Expand All @@ -26,7 +26,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All"/>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
<InternalsVisibleTo Include="$(AssemblyName).Tester" />
<InternalsVisibleTo Include="$(AssemblyName).Tests" />
<None Include="../../readme.md" Pack="true" PackagePath="/" />
Expand Down
13 changes: 12 additions & 1 deletion src/HidApi.Net/Internal/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@ private static IntPtr Resolve(string libraryName, Assembly assembly, DllImportSe
throw new Exception($"Could not find hidapi library tried: {string.Join(", ", libraries)}");
}

public static DeviceSafeHandle Open(ushort vendorId, ushort productId, NullTerminatedString serialNumber)
{
unsafe
{
fixed (byte* ptr = serialNumber)
{
return Open(vendorId, productId, ptr);
}
}
}

public static int Write(DeviceSafeHandle device, ReadOnlySpan<byte> data)
{
return Write(device, ref MemoryMarshal.GetReference(data), (nuint) data.Length);
Expand Down Expand Up @@ -99,7 +110,7 @@ public static int GetInputReport(DeviceSafeHandle device, ReadOnlySpan<byte> dat
public static extern unsafe void FreeEnumeration(NativeDeviceInfo* devices);

[DllImport(Library, EntryPoint = "hid_open")]
public static extern DeviceSafeHandle Open(ushort vendorId, ushort productId, [MarshalAs(UnmanagedType.LPWStr)] string serialNumber);
private static extern unsafe DeviceSafeHandle Open(ushort vendorId, ushort productId, byte* serialNumber);

[DllImport(Library, EntryPoint = "hid_open_path")]
public static extern DeviceSafeHandle OpenPath([MarshalAs(UnmanagedType.LPStr)] string path);
Expand Down
20 changes: 20 additions & 0 deletions src/HidApi.Net/Internal/NullTerminatedString.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace HidApi;

internal readonly ref struct NullTerminatedString
{
public static NullTerminatedString Empty => new();

private readonly ReadOnlySpan<byte> data;

public NullTerminatedString()
{
data = ReadOnlySpan<byte>.Empty;
}

internal NullTerminatedString(ref byte[] str)
{
data = str;
}

public ref readonly byte GetPinnableReference() => ref data.GetPinnableReference();
}
9 changes: 9 additions & 0 deletions src/HidApi.Net/Internal/Unicode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ namespace HidApi;

internal static class Unicode
{
public static NullTerminatedString CreateNullTerminatedString(string str)
{
var src = Encoding.Unicode.GetBytes(str);
var dest = new byte[src.Length + sizeof(ushort)];
Array.Copy(src, dest, src.Length);

return new NullTerminatedString(ref dest);
}

public static ReadOnlySpan<byte> CreateBuffer(int size)
{
return new byte[size * sizeof(ushort)];
Expand Down
9 changes: 9 additions & 0 deletions src/HidApi.Net/Internal/Utf32.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ namespace HidApi;

internal static class Utf32
{
public static NullTerminatedString CreateNullTerminatedString(string str)
{
var src = Encoding.UTF32.GetBytes(str);
var dest = new byte[src.Length + sizeof(uint)];
Array.Copy(src, dest, src.Length);

return new NullTerminatedString(ref dest);
}

public static ReadOnlySpan<byte> CreateBuffer(int size)
{
return new byte[size * sizeof(uint)];
Expand Down
14 changes: 14 additions & 0 deletions src/HidApi.Net/Internal/WCharT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,18 @@ public static ReadOnlySpan<byte> CreateBuffer(int size)

throw new Exception("Unsupported platform to create a buffer");
}

public static NullTerminatedString CreateNullTerminatedString(string str)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return Utf32.CreateNullTerminatedString(str);

if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return Unicode.CreateNullTerminatedString(str);

if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
return Utf32.CreateNullTerminatedString(str);

throw new Exception("Unsupported platform to create a null terminated string");
}
}

0 comments on commit 6447035

Please sign in to comment.