diff --git a/src/HidApi.Net/Device.cs b/src/HidApi.Net/Device.cs index 97718c9..0538f1d 100644 --- a/src/HidApi.Net/Device.cs +++ b/src/HidApi.Net/Device.cs @@ -1,3 +1,5 @@ +using System.Runtime.CompilerServices; + namespace HidApi; /// @@ -15,7 +17,21 @@ public class Device : IDisposable /// product id of target device public Device(ushort vendorId, ushort productId) { - handle = NativeMethods.Open(vendorId, productId, string.Empty); + handle = NativeMethods.Open(vendorId, productId, ref Unsafe.NullRef()); + + if (handle.IsInvalid) + HidException.Throw(handle); + } + + /// + /// Connects to a given device. + /// + /// Vendor id of target device + /// Product id of target device + /// Serial number of target device + public Device(ushort vendorId, ushort productId, string serialNumber) + { + handle = NativeMethods.Open(vendorId, productId, ref WCharT.CreateNullTerminatedString(serialNumber)); if (handle.IsInvalid) HidException.Throw(handle); diff --git a/src/HidApi.Net/Internal/NativeMethods.cs b/src/HidApi.Net/Internal/NativeMethods.cs index 1018f98..edbb180 100644 --- a/src/HidApi.Net/Internal/NativeMethods.cs +++ b/src/HidApi.Net/Internal/NativeMethods.cs @@ -99,7 +99,7 @@ public static int GetInputReport(DeviceSafeHandle device, ReadOnlySpan 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); + public static extern DeviceSafeHandle Open(ushort vendorId, ushort productId, ref byte serialNumber); [DllImport(Library, EntryPoint = "hid_open_path")] public static extern DeviceSafeHandle OpenPath([MarshalAs(UnmanagedType.LPStr)] string path); diff --git a/src/HidApi.Net/Internal/Unicode.cs b/src/HidApi.Net/Internal/Unicode.cs index a2f0ba7..5024557 100644 --- a/src/HidApi.Net/Internal/Unicode.cs +++ b/src/HidApi.Net/Internal/Unicode.cs @@ -1,9 +1,19 @@ +using System.Runtime.InteropServices; using System.Text; namespace HidApi; internal static class Unicode { + public static ref byte CreateNullTerminatedString(string str) + { + var src = Encoding.Unicode.GetBytes(str); + var dest = new byte[src.Length + sizeof(uint)]; + Array.Copy(src, dest, src.Length); + + return ref MemoryMarshal.AsRef(dest); + } + public static ReadOnlySpan CreateBuffer(int size) { return new byte[size * sizeof(ushort)]; diff --git a/src/HidApi.Net/Internal/Utf32.cs b/src/HidApi.Net/Internal/Utf32.cs index 23b4846..0cb9293 100644 --- a/src/HidApi.Net/Internal/Utf32.cs +++ b/src/HidApi.Net/Internal/Utf32.cs @@ -1,9 +1,19 @@ +using System.Runtime.InteropServices; using System.Text; namespace HidApi; internal static class Utf32 { + public static ref byte CreateNullTerminatedString(string str) + { + var src = Encoding.UTF32.GetBytes(str); + var dest = new byte[src.Length + sizeof(uint)]; + Array.Copy(src, dest, src.Length); + + return ref MemoryMarshal.AsRef(dest); + } + public static ReadOnlySpan CreateBuffer(int size) { return new byte[size * sizeof(uint)]; diff --git a/src/HidApi.Net/Internal/WCharT.cs b/src/HidApi.Net/Internal/WCharT.cs index 55d4c76..a529f6f 100644 --- a/src/HidApi.Net/Internal/WCharT.cs +++ b/src/HidApi.Net/Internal/WCharT.cs @@ -46,4 +46,18 @@ public static ReadOnlySpan CreateBuffer(int size) throw new Exception("Unsupported platform to create a buffer"); } + + public static ref byte CreateNullTerminatedString(string str) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + return ref Utf32.CreateNullTerminatedString(str); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + return ref Unicode.CreateNullTerminatedString(str); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + return ref Utf32.CreateNullTerminatedString(str); + + throw new Exception("Unsupported platform to create a string"); + } }