### Install HidLibrary via NuGet Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Use this command in the Package Manager Console to install the HidLibrary NuGet package. ```powershell PM> Install-Package hidlibrary ``` -------------------------------- ### Get HID Device Capabilities Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Retrieves device capabilities including report sizes and usage metadata. This reflects the parsed HIDP_CAPS structure and is useful for sizing buffers. ```csharp using HidLibrary; var device = HidDevices.Enumerate(0x046D, 0xC216).FirstOrDefault(); if (device == null) return; var c = device.Capabilities; Console.WriteLine($"Usage : {c.Usage}"); Console.WriteLine($"UsagePage : {c.UsagePage}"); Console.WriteLine($"InputLen : {c.InputReportByteLength}"); Console.WriteLine($"OutputLen : {c.OutputReportByteLength}"); Console.WriteLine($"FeatureLen : {c.FeatureReportByteLength}"); Console.WriteLine($"InputValues : {c.NumberInputValueCaps}"); Console.WriteLine($"OutputButtons: {c.NumberOutputButtonCaps}"); ``` -------------------------------- ### HidDevice.MonitorDeviceEvents Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Starts a background poller to monitor device insertion and removal events. The Inserted and Removed events fire when the device is plugged in or unplugged while the program is running. ```APIDOC ## MonitorDeviceEvents, Inserted, Removed ### Description Setting `MonitorDeviceEvents = true` starts a background poller. The `Inserted` and `Removed` events fire when the device is plugged in or unplugged while the program is running. ### Properties - **MonitorDeviceEvents** (bool) - Set to `true` to start monitoring for device hot-plug events. - **Inserted** (event) - Event that fires when a device is plugged in. - **Removed** (event) - Event that fires when a device is unplugged. ### Event Handlers #### Inserted Event This event is invoked when a device is inserted. #### Removed Event This event is invoked when a device is removed. ### Example Usage ```csharp using System; using HidLibrary; var device = HidDevices.Enumerate(0x046D, 0xC216).FirstOrDefault(); if (device == null) { Console.WriteLine("Not found"); return; } device.Inserted += () => { Console.WriteLine("Device inserted — re-opening."); device.OpenDevice(); device.ReadReport(OnReport); }; device.Removed += () => { Console.WriteLine("Device removed."); }; device.OpenDevice(); device.MonitorDeviceEvents = true; // starts the event monitor device.ReadReport(OnReport); Console.WriteLine("Monitoring. Press any key to quit."); Console.ReadKey(); device.Dispose(); void OnReport(HidReport r) { if (r.Exists) Console.WriteLine($"Report id={{r.ReportId}} data={{BitConverter.ToString(r.Data)}}"); device.ReadReport(OnReport); } ``` ``` -------------------------------- ### Check Device Connection and Get Device Instance Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Use IsConnected for a quick check of device presence or GetDevice to retrieve a HidDevice instance by its full path. Both methods are part of the HidDevices static class. ```csharp using HidLibrary; string path = @"\\?\hid#vid_0536&pid_0207#..."; bool connected = HidDevices.IsConnected(path); Console.WriteLine($"Connected: {connected}"); HidDevice device = HidDevices.GetDevice(path); if (device != null) Console.WriteLine($"Retrieved: {device.Description}"); ``` -------------------------------- ### Get HID Device Attributes Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Retrieves device identification properties such as Vendor ID, Product ID, and firmware version. This information is parsed from HidD_GetAttributes and exposed via the HidDevice.Attributes property. ```csharp using HidLibrary; foreach (var dev in HidDevices.Enumerate()) { var a = dev.Attributes; Console.WriteLine($"VID={a.VendorHexId} PID={a.ProductHexId} Ver={a.Version} (int VID={a.VendorId})"); // Output example: VID=0x046D PID=0xC52B Ver=18 (int VID=1133) } ``` -------------------------------- ### Monitor HID Device Hot-plug Events Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Monitors for device insertion and removal events. Setting MonitorDeviceEvents to true starts a background poller. The Inserted and Removed events fire when the device is plugged in or unplugged while the program is running. Ensure the device is opened and ReadReport is called to begin monitoring. ```csharp using System; using HidLibrary; var device = HidDevices.Enumerate(0x046D, 0xC216).FirstOrDefault(); if (device == null) { Console.WriteLine("Not found"); return; } device.Inserted += () => { Console.WriteLine("Device inserted — re-opening."); device.OpenDevice(); device.ReadReport(OnReport); }; device.Removed += () => { Console.WriteLine("Device removed."); }; device.OpenDevice(); device.MonitorDeviceEvents = true; // starts the event monitor device.ReadReport(OnReport); Console.WriteLine("Monitoring. Press any key to quit."); Console.ReadKey(); device.Dispose(); void OnReport(HidReport r) { if (r.Exists) Console.WriteLine($"Report id={r.ReportId} data={BitConverter.ToString(r.Data)}"); device.ReadReport(OnReport); } ``` -------------------------------- ### Running NUnit FIT Tests Source: https://github.com/mikeobrien/hidlibrary/blob/master/experimental/packages/NUnit.2.5.9.10348/Tools/NUnitFitTests.html Commands to execute NUnit FIT tests from the console. ```bash runFile NUnitFitTests.html TestResults.html . ``` ```bash mono runFile.exe NUnitFitTests.html TestResults.html . ``` -------------------------------- ### Run NUnit FIT Tests (Mono) Source: https://github.com/mikeobrien/hidlibrary/blob/master/experimental/packages/NUnit.2.5.9.10348/NUnitFitTests.html Command to execute NUnit FIT tests using the runFile executable on Mono. Results are saved to TestResults.html. ```bash mono runFile.exe NUnitFitTests.html TestResults.html . ``` -------------------------------- ### Run NUnit FIT Tests (Microsoft .Net) Source: https://github.com/mikeobrien/hidlibrary/blob/master/experimental/packages/NUnit.2.5.9.10348/NUnitFitTests.html Command to execute NUnit FIT tests using the runFile executable on Microsoft .Net. Results are saved to TestResults.html. ```bash runFile NUnitFitTests.html TestResults.html . ``` -------------------------------- ### HidDevice.Capabilities Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Reflects the parsed HIDP_CAPS structure, providing report byte lengths and usage page/usage values needed when sizing buffers. ```APIDOC ## HidDeviceCapabilities ### Description `HidDeviceCapabilities` is exposed via `HidDevice.Capabilities` and reflects the parsed `HIDP_CAPS` structure, providing report byte lengths and usage page/usage values needed when sizing buffers. ### Properties - **Usage** (int) - The usage code of the device. - **UsagePage** (int) - The usage page of the device. - **InputReportByteLength** (int) - The byte length of input reports. - **OutputReportByteLength** (int) - The byte length of output reports. - **FeatureReportByteLength** (int) - The byte length of feature reports. - **NumberInputValueCaps** (int) - The number of input value capabilities. - **NumberOutputButtonCaps** (int) - The number of output button capabilities. ### Example Usage ```csharp using HidLibrary; var device = HidDevices.Enumerate(0x046D, 0xC216).FirstOrDefault(); if (device == null) return; var c = device.Capabilities; Console.WriteLine($"Usage : {{c.Usage}}"); Console.WriteLine($"UsagePage : {{c.UsagePage}}"); Console.WriteLine($"InputLen : {{c.InputReportByteLength}}"); Console.WriteLine($"OutputLen : {{c.OutputReportByteLength}}"); Console.WriteLine($"FeatureLen : {{c.FeatureReportByteLength}}"); Console.WriteLine($"InputValues : {{c.NumberInputValueCaps}}"); Console.WriteLine($"OutputButtons: {{c.NumberOutputButtonCaps}}"); ``` ``` -------------------------------- ### HidDevices.Enumerate Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Discovers connected HID devices on the system. Overloads allow filtering by Vendor ID, Product ID, Usage Page, or exact device path. Results are returned as a lazy IEnumerable. ```APIDOC ## HidDevices.Enumerate — Discover connected HID devices `HidDevices` is a static factory class. Its `Enumerate` overloads query the Windows SetupAPI to return all currently connected HID devices that match the supplied filter criteria. Results are lazy `IEnumerable` sequences. ### Method Signature Examples ```csharp // Enumerate ALL HID devices on the system public static IEnumerable Enumerate(); // Enumerate by Vendor ID only public static IEnumerable Enumerate(int vendorId); // Enumerate by Vendor ID + one or more Product IDs public static IEnumerable Enumerate(int vendorId, params int[] productIds); // Enumerate by Vendor ID, Product ID, and USB Usage Page public static IEnumerable Enumerate(int vendorId, int productId, int UsagePage); // Enumerate by Usage Page alone public static IEnumerable Enumerate(int UsagePage); // Enumerate by exact device path public static IEnumerable Enumerate(string devicePath); ``` ### Usage Examples ```csharp using System; using System.Linq; using HidLibrary; // 1. Enumerate ALL HID devices on the system foreach (var dev in HidDevices.Enumerate()) { Console.WriteLine(dev); // "VendorID=0x046D, ProductID=0xC52B, Version=..., DevicePath=\\?\hid#..." } // 2. Enumerate by Vendor ID only var logitech = HidDevices.Enumerate(vendorId: 0x046D); // 3. Enumerate by Vendor ID + one or more Product IDs var gamepad = HidDevices.Enumerate(vendorId: 0x046D, productIds: new[] { 0xC216, 0xC218 }).FirstOrDefault(); // 4. Enumerate by Vendor ID, Product ID, and USB Usage Page var keyboard = HidDevices.Enumerate(vendorId: 0x046D, productId: 0xC31C, UsagePage: 0x0001).FirstOrDefault(); // 5. Enumerate by Usage Page alone var pointerDevices = HidDevices.Enumerate(UsagePage: 0x0001); // 6. Enumerate by exact device path var specific = HidDevices.Enumerate(@"\\?\hid#vid_046d&pid_c52b#...").FirstOrDefault(); if (gamepad != null) Console.WriteLine($"Found gamepad: VID={gamepad.Attributes.VendorHexId} PID={gamepad.Attributes.ProductHexId}"); ``` ``` -------------------------------- ### Enumerate HID Devices with HidDevices.Enumerate Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Discover connected HID devices using various filter criteria such as Vendor ID, Product ID, and Usage Page. Results are returned as a lazy IEnumerable. ```csharp using System; using System.Linq; using HidLibrary; // 1. Enumerate ALL HID devices on the system foreach (var dev in HidDevices.Enumerate()) { Console.WriteLine(dev); // "VendorID=0x046D, ProductID=0xC52B, Version=..., DevicePath=\\?\hid#..." } // 2. Enumerate by Vendor ID only var logitech = HidDevices.Enumerate(vendorId: 0x046D); // 3. Enumerate by Vendor ID + one or more Product IDs var gamepad = HidDevices.Enumerate(vendorId: 0x046D, productIds: new[] { 0xC216, 0xC218 }).FirstOrDefault(); // 4. Enumerate by Vendor ID, Product ID, and USB Usage Page var keyboard = HidDevices.Enumerate(vendorId: 0x046D, productId: 0xC31C, UsagePage: 0x0001).FirstOrDefault(); // 5. Enumerate by Usage Page alone var pointerDevices = HidDevices.Enumerate(UsagePage: 0x0001); // 6. Enumerate by exact device path var specific = HidDevices.Enumerate(@"\\?\hid#vid_046d&pid_c52b#").FirstOrDefault(); if (gamepad != null) Console.WriteLine($"Found gamepad: VID={gamepad.Attributes.VendorHexId} PID={gamepad.Attributes.ProductHexId}"); ``` -------------------------------- ### JavaScript Event Handling for Page Load Source: https://github.com/mikeobrien/hidlibrary/blob/master/experimental/UpgradeLog.htm Hooks up the 'onload' event for the document/window to execute a startup function, ensuring code runs after the page is fully loaded. Supports multiple browser event models. ```javascript var startupFunction = function() { linkifyElement("messages"); }; if(window.attachEvent) { window.attachEvent('onload', startupFunction); } else if (window.addEventListener) { window.addEventListener('load', startupFunction, false); } else { document.addEventListener('load', startupFunction, false); } ``` -------------------------------- ### Manage HidDevice Handles with OpenDevice and CloseDevice Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Open a device for I/O operations using OpenDevice, optionally specifying overlapped mode and share mode for exclusive or shared access. CloseDevice or Dispose releases the handles. ```csharp using HidLibrary; var device = HidDevices.Enumerate(0x046D, 0xC216).FirstOrDefault(); if (device == null) return; // Default: NonOverlapped, ShareRead | ShareWrite device.OpenDevice(); Console.WriteLine($"IsOpen: {device.IsOpen}"); // Overlapped mode + exclusive access device.CloseDevice(); device.OpenDevice(DeviceMode.Overlapped, DeviceMode.Overlapped, ShareMode.Exclusive); Console.WriteLine($"ReadHandle valid: {device.ReadHandle != IntPtr.Zero}"); Console.WriteLine($"WriteHandle valid: {device.WriteHandle != IntPtr.Zero}"); device.Dispose(); // also closes if open ``` -------------------------------- ### HidDevice.Write (callback) / WriteAsync Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Performs asynchronous raw byte writes using either a callback or Task-based approach. ```APIDOC ## Write (callback) / WriteAsync ### Description Provides non-blocking write operations for raw output reports. Supports both APM-style callbacks and `Task`-based asynchronous patterns. ### Methods - `Write(byte[] data, Action successCallback, int timeout = -1)` - `WriteAsync(byte[] data, int timeout = -1)` ### Parameters #### Path Parameters - **data** (byte[]) - Required - The payload of the output report. The Report ID prefix byte is added automatically. - **successCallback** (Action) - Optional (for `Write` method) - A callback action that is invoked with the success status of the write operation. - **timeout** (int) - Optional - The timeout in milliseconds for the write operation. Defaults to -1 (no timeout). ### Response - **Write**: The `successCallback` is invoked with the result. - **WriteAsync**: Returns a `Task` that completes with the success status of the write operation. ### Request Example ```csharp using System; using System.Threading.Tasks; using HidLibrary; static async Task Main() { var device = HidDevices.Enumerate(0x046D, 0xC216).FirstOrDefault(); device?.OpenDevice(); byte[] payload = new byte[device.Capabilities.OutputReportByteLength - 1]; payload[0] = 0x01; // example command // Callback style device.Write(payload, success => Console.WriteLine($"Callback write: {success}"), timeout: 500); // Task/await style bool result = await device.WriteAsync(payload, timeout: 500); Console.WriteLine($"Async write: {result}"); device?.Dispose(); } ``` ``` -------------------------------- ### HidDevice.Write Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Sends a raw output report as a byte array. The array should contain the payload only (Report ID is prepended automatically). ```APIDOC ## Write ### Description Sends a raw output report as a byte array. The array should contain the payload only (Report ID is prepended automatically to fill `OutputReportByteLength`). An optional timeout in milliseconds can be specified. ### Method `Write(byte[] data, int timeout = -1)` ### Parameters #### Path Parameters - **data** (byte[]) - Required - The payload of the output report. The Report ID prefix byte is added automatically. - **timeout** (int) - Optional - The timeout in milliseconds for the write operation. Defaults to -1 (no timeout). ### Response - **bool** - Returns `true` if the write operation was successful, `false` otherwise. ### Request Example ```csharp using HidLibrary; var device = HidDevices.Enumerate(0x0536, 0x0207).FirstOrDefault(); // Build payload (excluding the Report ID prefix byte) byte[] data = new byte[device.Capabilities.OutputReportByteLength - 1]; data[0] = 0x04; // command byte data[1] = 0x40; // sub-command: success beep bool sent = device.Write(data); Console.WriteLine($"Write success: {sent}"); // With timeout bool sentTimed = device.Write(data, timeout: 1000); Console.WriteLine($"Write (timed) success: {sentTimed}"); ``` ``` -------------------------------- ### HidDevice.ReadAsync — Task-based asynchronous raw read Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Wraps the read operation in a Task, enabling await usage in modern async code paths. ```APIDOC ## HidDevice.ReadAsync — Task-based asynchronous raw read `ReadAsync` wraps the read operation in a `Task`, enabling `await` usage in modern async code paths. ### Method `ReadAsync(int timeout)` ### Parameters #### Optional Parameters - **timeout** (int) - Description: Timeout in milliseconds. ### Response - **Task** - A task that, when completed, contains the read data and status. - **Status** (HidDeviceData.ReadStatus) - Indicates the outcome of the read operation. - **Data** (byte[]) - The raw bytes read from the device. ### Request Example ```csharp HidDeviceData data = await device.ReadAsync(timeout: 1000); ``` ### Response Example ```csharp // On Success { "Status": "Success", "Data": [ ... bytes ... ] } // On Failure { "Status": "WaitTimedOut", "Data": null } ``` ``` -------------------------------- ### Read and Write HID Reports Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Demonstrates reading a HID report and constructing/writing an outbound report. HidReport separates the Report ID from the payload and can be serialized back to the raw wire format using GetBytes(). ```csharp using System; using HidLibrary; var device = HidDevices.Enumerate(0x046D, 0xC216).FirstOrDefault(); device?.OpenDevice(); // Reading a report HidReport inReport = device.ReadReport(); Console.WriteLine($"Exists : {inReport.Exists}"); Console.WriteLine($"ReportId: {inReport.ReportId}"); Console.WriteLine($"Payload : {BitConverter.ToString(inReport.Data)}"); Console.WriteLine($"Status : {inReport.ReadStatus}"); // Building an outbound report manually HidReport outReport = new HidReport(device.Capabilities.OutputReportByteLength); outReport.ReportId = 0x00; outReport.Data[0] = 0x01; outReport.Data[1] = 0x02; byte[] raw = outReport.GetBytes(); // [ReportId, Data[0], Data[1], ...] Console.WriteLine($"Raw bytes: {BitConverter.ToString(raw)}"); device.WriteReport(outReport); device?.Dispose(); ``` -------------------------------- ### Read Device String Descriptors Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Retrieves product, manufacturer, or serial number strings from device string descriptors. The returned byte arrays contain UTF-16LE encoded text. ```csharp using System; using System.Text; using HidLibrary; var device = HidDevices.Enumerate(0x046D, 0xC52B).FirstOrDefault(); device?.OpenDevice(); if (device.ReadProduct(out byte[] productBytes)) Console.WriteLine($"Product : {Encoding.Unicode.GetString(productBytes).TrimEnd('\0')}"); if (device.ReadManufacturer(out byte[] mfrBytes)) Console.WriteLine($"Manufacturer: {Encoding.Unicode.GetString(mfrBytes).TrimEnd('\0')}"); if (device.ReadSerialNumber(out byte[] snBytes)) Console.WriteLine($"Serial : {Encoding.Unicode.GetString(snBytes).TrimEnd('\0')}"); device?.Dispose(); ``` -------------------------------- ### Task-based Asynchronous Raw Byte Read Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Wraps the read operation in a Task, enabling await usage in modern async code paths. Ensure the device is opened before calling ReadAsync. ```csharp using System; using System.Threading.Tasks; using HidLibrary; static async Task Main() { var device = HidDevices.Enumerate(0x046D, 0xC216).FirstOrDefault(); if (device == null) return; device.OpenDevice(); HidDeviceData data = await device.ReadAsync(timeout: 1000); if (data.Status == HidDeviceData.ReadStatus.Success) Console.WriteLine(BitConverter.ToString(data.Data)); else Console.WriteLine($"Failed: {data.Status}"); device.Dispose(); } ``` -------------------------------- ### HidDevice.OpenDevice / HidDevice.CloseDevice Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Manages the device handle for reading and writing. Supports default modes, overlapped I/O, and different sharing modes. Handles are released via CloseDevice or Dispose. ```APIDOC ## HidDevice.OpenDevice / HidDevice.CloseDevice — Manage the device handle `OpenDevice` creates read and write handles for the device. The overload accepting `DeviceMode` and `ShareMode` allows overlapped (async-capable) I/O and exclusive vs. shared access. `CloseDevice` and `Dispose` release handles. ### Method Signatures ```csharp // Opens the device with default settings (NonOverlapped, ShareRead | ShareWrite) public void OpenDevice(); // Opens the device with specified modes and share settings public void OpenDevice(DeviceMode readMode, DeviceMode writeMode, ShareMode shareMode); // Closes the device handles public void CloseDevice(); // Disposes the device, also closing handles if open public void Dispose(); ``` ### Usage Examples ```csharp using HidLibrary; var device = HidDevices.Enumerate(0x046D, 0xC216).FirstOrDefault(); if (device == null) return; // Default: NonOverlapped, ShareRead | ShareWrite device.OpenDevice(); Console.WriteLine($"IsOpen: {device.IsOpen}"); // Overlapped mode + exclusive access device.CloseDevice(); device.OpenDevice(DeviceMode.Overlapped, DeviceMode.Overlapped, ShareMode.Exclusive); Console.WriteLine($"ReadHandle valid: {device.ReadHandle != IntPtr.Zero}"); Console.WriteLine($"WriteHandle valid: {device.WriteHandle != IntPtr.Zero}"); device.Dispose(); // also closes if open ``` ``` -------------------------------- ### HidDevice.WriteReport / WriteReportAsync Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Writes a structured HID report, which includes a Report ID and a typed payload. ```APIDOC ## WriteReport / WriteReportAsync ### Description Writes a structured HID report to the device. This method accepts a `HidReport` object, which contains both a Report ID and a data payload. `CreateReport` can be used to allocate a correctly-sized `HidReport`. ### Methods - `WriteReport(HidReport report, int timeout = -1)` - `WriteReportAsync(HidReport report, int timeout = -1)` - `WriteReport(HidReport report, Action successCallback, int timeout = -1)` ### Parameters #### Path Parameters - **report** (HidReport) - Required - The `HidReport` object to write, containing Report ID and data. - **timeout** (int) - Optional - The timeout in milliseconds for the write operation. Defaults to -1 (no timeout). - **successCallback** (Action) - Optional (for callback overload) - A callback action invoked with the success status. ### Response - **WriteReport**: Returns `true` if the write was successful, `false` otherwise. - **WriteReportAsync**: Returns a `Task` that completes with the success status. - **WriteReport (callback)**: The `successCallback` is invoked with the result. ### Request Example ```csharp using System; using System.Threading.Tasks; using HidLibrary; static async Task Main() { var device = HidDevices.Enumerate(0x077D, 0x0410).FirstOrDefault(); device?.OpenDevice(); // Create and populate a report HidReport report = device.CreateReport(); report.ReportId = 0x00; report.Data[0] = 0x00; // LED brightness = off report.Data[1] = 0xFF; // example value // Synchronous bool ok = device.WriteReport(report); Console.WriteLine($"WriteReport: {ok}"); // Async bool asyncOk = await device.WriteReportAsync(report, timeout: 500); Console.WriteLine($"WriteReportAsync: {asyncOk}"); // Callback device.WriteReport(report, success => Console.WriteLine($"Callback: {success}")); device?.Dispose(); } ``` ``` -------------------------------- ### Basic Test Fixture Source: https://github.com/mikeobrien/hidlibrary/blob/master/experimental/packages/NUnit.2.5.9.10348/NUnitFitTests.html A C# test fixture with a single test method, used to verify snippet runner functionality. ```csharp using NUnit.Framework; [TestFixture] public class TestClass { } ``` -------------------------------- ### Asynchronous Raw Byte Read with Callback Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Dispatches the read onto a thread-pool thread and invokes a callback delegate when data arrives, allowing the calling thread to remain unblocked. Use ManualResetEventSlim to wait for completion. ```csharp using System; using System.Threading; using HidLibrary; var device = HidDevices.Enumerate(0x046D, 0xC216).FirstOrDefault(); device?.OpenDevice(); var done = new ManualResetEventSlim(false); device.Read(data => { Console.WriteLine($"Status : {data.Status}"); Console.WriteLine($"Payload: {BitConverter.ToString(data.Data)}"); done.Set(); }, timeout: 2000); done.Wait(); device?.Dispose(); ``` -------------------------------- ### HidDevice.Read (callback) — APM-style asynchronous raw read Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Dispatches the read onto a thread-pool thread and invokes the ReadCallback delegate when data (or a timeout/error) arrives, allowing the calling thread to remain unblocked. ```APIDOC ## HidDevice.Read (callback) — APM-style asynchronous raw read The callback overload dispatches the read onto a thread-pool thread and invokes the `ReadCallback` delegate when data (or a timeout/error) arrives, allowing the calling thread to remain unblocked. ### Method `Read(ReadCallback callback, int timeout)` ### Parameters #### Required Parameters - **callback** (ReadCallback) - Description: A delegate that will be invoked with the read result. - **timeout** (int) - Description: Timeout in milliseconds. ### Callback Signature `void ReadCallback(HidDeviceData data)` ### Request Example ```csharp device.Read(data => { Console.WriteLine($"Status : {data.Status}"); Console.WriteLine($"Payload: {BitConverter.ToString(data.Data)}"); done.Set(); }, timeout: 2000); ``` ### Response Example (The callback receives a `HidDeviceData` object) ```csharp { "Status": "Success", "Data": [ ... bytes ... ] } ``` ``` -------------------------------- ### HidDevice.Attributes Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Provides device identification properties including Vendor ID, Product ID, and firmware version. ```APIDOC ## HidDeviceAttributes ### Description `HidDeviceAttributes` is exposed via `HidDevice.Attributes` and provides the Vendor ID, Product ID, firmware version, and hex-string equivalents parsed from `HidD_GetAttributes`. ### Properties - **VendorId** (int) - The Vendor ID of the device. - **ProductId** (int) - The Product ID of the device. - **Version** (int) - The firmware version of the device. - **VendorHexId** (string) - The Vendor ID of the device as a hexadecimal string. - **ProductHexId** (string) - The Product ID of the device as a hexadecimal string. ### Example Usage ```csharp using HidLibrary; foreach (var dev in HidDevices.Enumerate()) { var a = dev.Attributes; Console.WriteLine($"VID={{a.VendorHexId}} PID={{a.ProductHexId}} Ver={{a.Version}} (int VID={{a.VendorId}})"); // Output example: VID=0x046D PID=0xC52B Ver=18 (int VID=1133) } ``` ``` -------------------------------- ### Asynchronous Raw Byte Write Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Provides APM-callback and Task-based overloads for non-blocking writes. Both methods accept an optional timeout. ```csharp using System; using System.Threading.Tasks; using HidLibrary; static async Task Main() { var device = HidDevices.Enumerate(0x046D, 0xC216).FirstOrDefault(); device?.OpenDevice(); byte[] payload = new byte[device.Capabilities.OutputReportByteLength - 1]; payload[0] = 0x01; // example command // Callback style device.Write(payload, success => Console.WriteLine($"Callback write: {success}"), timeout: 500); // Task/await style bool result = await device.WriteAsync(payload, timeout: 500); Console.WriteLine($"Async write: {result}"); device?.Dispose(); } ``` -------------------------------- ### HidDevices.IsConnected / HidDevices.GetDevice Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Checks if a device is currently connected using its path or retrieves a specific HidDevice instance by its full device path. ```APIDOC ## HidDevices.IsConnected / HidDevices.GetDevice — Check presence and retrieve a device `IsConnected` performs a fast path check against the live device list. `GetDevice` returns the first `HidDevice` matching a full device path string. ### Method Signatures ```csharp // Checks if a device with the given path is connected public static bool IsConnected(string devicePath); // Retrieves the HidDevice instance for the given device path public static HidDevice GetDevice(string devicePath); ``` ### Usage Examples ```csharp using HidLibrary; string path = @"\\?\hid#vid_0536&pid_0207#..."; bool connected = HidDevices.IsConnected(path); Console.WriteLine($"Connected: {connected}"); HidDevice device = HidDevices.GetDevice(path); if (device != null) Console.WriteLine($"Retrieved: {device.Description}"); ``` ``` -------------------------------- ### Structured Report Writes Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Accepts a HidReport object, which carries a Report ID and a typed payload. CreateReport allocates a correctly-sized HidReport for the device's output report length. Supports synchronous, asynchronous, and callback styles. ```csharp using System; using System.Threading.Tasks; using HidLibrary; static async Task Main() { var device = HidDevices.Enumerate(0x077D, 0x0410).FirstOrDefault(); device?.OpenDevice(); // Create and populate a report HidReport report = device.CreateReport(); report.ReportId = 0x00; report.Data[0] = 0x00; // LED brightness = off report.Data[1] = 0xFF; // example value // Synchronous bool ok = device.WriteReport(report); Console.WriteLine($"WriteReport: {ok}"); // Async bool asyncOk = await device.WriteReportAsync(report, timeout: 500); Console.WriteLine($"WriteReportAsync: {asyncOk}"); // Callback device.WriteReport(report, success => Console.WriteLine($"Callback: {success}")); device?.Dispose(); } ``` -------------------------------- ### HidDevice.WriteReportSync Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Performs a control-channel write using `HidD_SetOutputReport` for devices that do not support interrupt-out transfers. ```APIDOC ## WriteReportSync ### Description Uses `HidD_SetOutputReport` to deliver a report over the control channel. This is suitable for devices that do not support interrupt-out transfers. ### Method `WriteReportSync(HidReport report)` ### Parameters #### Path Parameters - **report** (HidReport) - Required - The `HidReport` object to write, containing Report ID and data. ### Response - **bool** - Returns `true` if the write operation was successful, `false` otherwise. ### Request Example ```csharp using HidLibrary; var device = HidDevices.Enumerate(0x1234, 0x5678).FirstOrDefault(); device?.OpenDevice(); HidReport report = device.CreateReport(); report.ReportId = 0x02; report.Data[0] = 0xAB; bool sent = device.WriteReportSync(report); Console.WriteLine($"Control write: {sent}"); device?.Dispose(); ``` ``` -------------------------------- ### Synchronous Raw Byte Write Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Sends a raw output report as a byte array. The array should contain the payload only (Report ID is prepended automatically). An optional timeout can be specified. ```csharp using HidLibrary; var device = HidDevices.Enumerate(0x0536, 0x0207).FirstOrDefault(); // Build payload (excluding the Report ID prefix byte) byte[] data = new byte[device.Capabilities.OutputReportByteLength - 1]; data[0] = 0x04; // command byte data[1] = 0x40; // sub-command: success beep bool sent = device.Write(data); Console.WriteLine($"Write success: {sent}"); // With timeout bool sentTimed = device.Write(data, timeout: 1000); Console.WriteLine($"Write (timed) success: {sentTimed}"); ``` -------------------------------- ### Empty Test Fixture Source: https://github.com/mikeobrien/hidlibrary/blob/master/experimental/packages/NUnit.2.5.9.10348/NUnitFitTests.html A basic C# test fixture with no methods, used to verify snippet runner functionality. ```csharp public class TestClass { } ``` -------------------------------- ### HidDevice.ReadProduct / ReadManufacturer / ReadSerialNumber Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Retrieves string descriptor information (product, manufacturer, or serial number) from the device. ```APIDOC ## ReadProduct / ReadManufacturer / ReadSerialNumber ### Description These methods retrieve the product string, manufacturer string, or serial number from the device's string descriptors. The returned byte arrays contain UTF-16LE encoded text. ### Methods - `ReadProduct(out byte[] productBytes)` - `ReadManufacturer(out byte[] mfrBytes)` - `ReadSerialNumber(out byte[] snBytes)` ### Parameters #### Output Parameters - **productBytes** (byte[]) - Output - Buffer to store the product string bytes. - **mfrBytes** (byte[]) - Output - Buffer to store the manufacturer string bytes. - **snBytes** (byte[]) - Output - Buffer to store the serial number string bytes. ### Response - **bool** - Returns `true` if the string descriptor was successfully read, `false` otherwise. ### Request Example ```csharp using System; using System.Text; using HidLibrary; var device = HidDevices.Enumerate(0x046D, 0xC52B).FirstOrDefault(); device?.OpenDevice(); if (device.ReadProduct(out byte[] productBytes)) Console.WriteLine($"Product : {Encoding.Unicode.GetString(productBytes).TrimEnd('\0')}"); if (device.ReadManufacturer(out byte[] mfrBytes)) Console.WriteLine($"Manufacturer: {Encoding.Unicode.GetString(mfrBytes).TrimEnd('\0')}"); if (device.ReadSerialNumber(out byte[] snBytes)) Console.WriteLine($"Serial : {Encoding.Unicode.GetString(snBytes).TrimEnd('\0')}"); device?.Dispose(); ``` ``` -------------------------------- ### Instance-based HID Enumeration with HidEnumerator for Dependency Injection Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Utilize HidEnumerator as a non-static wrapper around HidDevices for dependency injection and mocking in tests. It implements IHidEnumerator, allowing the enumeration logic to be easily replaced. ```csharp using System.Linq; using HidLibrary; // Inject via IHidEnumerator; swap for a mock in tests IHidEnumerator enumerator = new HidEnumerator(); bool connected = enumerator.IsConnected(@"\\?\hid#vid_046d&pid_c216#..."); IHidDevice device = enumerator.Enumerate(0x046D, new[] { 0xC216 }).FirstOrDefault(); device?.OpenDevice(); // GetDevice by path IHidDevice byPath = enumerator.GetDevice(@"\\?\hid#vid_046d&pid_c216#..."); device?.Dispose(); ``` -------------------------------- ### Multiple Test Fixtures Source: https://github.com/mikeobrien/hidlibrary/blob/master/experimental/packages/NUnit.2.5.9.10348/NUnitFitTests.html A C# code snippet containing multiple test fixtures with test methods, used to verify snippet runner functionality. ```csharp using NUnit.Framework; [TestFixture] public class TestClass1 { [Test] public void T1() { } } [TestFixture] public class TestClass2 { [Test] public void T2() { } [Test] public void T3() { } } ``` -------------------------------- ### HidEnumerator Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Provides a non-static wrapper around HidDevices implementing IHidEnumerator, allowing for dependency injection and mocking in tests. It supports device enumeration and connection checks. ```APIDOC ## HidEnumerator — Instance-based enumeration wrapper (for dependency injection / testing) `HidEnumerator` is a non-static wrapper around `HidDevices` that implements `IHidEnumerator`, enabling the enumeration logic to be injected, mocked, or replaced in tests. `HidFastReadEnumerator` provides the same interface backed by `HidFastReadDevice`. ```csharp using System.Linq; using HidLibrary; // Inject via IHidEnumerator; swap for a mock in tests IHidEnumerator enumerator = new HidEnumerator(); bool connected = enumerator.IsConnected(@"\\?\hid#vid_046d&pid_c216#..."); IHidDevice device = enumerator.Enumerate(0x046D, new[] { 0xC216 }).FirstOrDefault(); device?.OpenDevice(); // GetDevice by path IHidDevice byPath = enumerator.GetDevice(@"\\?\hid#vid_046d&pid_c216#..."); device?.Dispose(); ``` ``` -------------------------------- ### Test with Explicit Method Source: https://github.com/mikeobrien/hidlibrary/blob/master/experimental/packages/NUnit.2.5.9.10348/NUnitFitTests.html A C# test fixture demonstrating an explicit test method, used to verify snippet runner functionality. ```csharp using NUnit.Framework; [TestFixture] public class TestClass { [Test] public void T1() { } [Test, Explicit] public void T2() { } [Test] public void T3() { } } ``` -------------------------------- ### Synchronous Raw Byte Read Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Performs a blocking read of a single HID input report. A timeout can be specified; 0 means wait indefinitely. Check HidDeviceData.Status for the outcome. ```csharp using System; using System.Text; using HidLibrary; var device = HidDevices.Enumerate(0x0536, 0x0207).FirstOrDefault(); if (device == null) { Console.WriteLine("Device not found"); return; } // Blocking read, infinite wait HidDeviceData result = device.Read(); if (result.Status == HidDeviceData.ReadStatus.Success) { Console.WriteLine($"Bytes: {result.Data.Length}"); Console.WriteLine($"ASCII: {Encoding.ASCII.GetString(result.Data)}"); } else { // Possible statuses: WaitTimedOut, WaitFail, NoDataRead, ReadError, NotConnected Console.WriteLine($"Read failed: {result.Status}"); } // Read with 500 ms timeout HidDeviceData timedResult = device.Read(timeout: 500); Console.WriteLine($"Timed read status: {timedResult.Status}"); ``` -------------------------------- ### Write HID Feature Report Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Writes a HID feature report to the device. The byte array must include the Report ID as its first byte. Ensure the device is opened before calling this method. ```csharp using HidLibrary; var device = HidDevices.Enumerate(0x077D, 0x0410).FirstOrDefault(); device?.OpenDevice(); // Enable LED pulsing on a Griffin PowerMate (VID 0x077D / PID 0x0410) byte[] featureData = new byte[9]; featureData[0] = 0x00; // Report ID featureData[1] = 0x41; featureData[2] = 0x01; featureData[3] = 0x03; // pulse enable command featureData[5] = 0x01; // enable = true bool written = device.WriteFeatureData(featureData); Console.WriteLine($"Feature write: {written}"); device?.Dispose(); ``` -------------------------------- ### Multiple Test Methods Source: https://github.com/mikeobrien/hidlibrary/blob/master/experimental/packages/NUnit.2.5.9.10348/NUnitFitTests.html A C# test fixture containing multiple test methods, used to verify snippet runner functionality. ```csharp using NUnit.Framework; [TestFixture] public class TestClass { [Test] public void T1() { } [Test] public void T2() { } [Test] public void T3() { } } ``` -------------------------------- ### Control-Channel Report Write Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Uses HidD_SetOutputReport to deliver a report over the control channel, for devices that do not support interrupt-out transfers. A HidReport object is used to specify the Report ID and data. ```csharp using HidLibrary; var device = HidDevices.Enumerate(0x1234, 0x5678).FirstOrDefault(); device?.OpenDevice(); HidReport report = device.CreateReport(); report.ReportId = 0x02; report.Data[0] = 0xAB; bool sent = device.WriteReportSync(report); Console.WriteLine($"Control write: {sent}"); device?.Dispose(); ``` -------------------------------- ### HidDevice.ReadReport / ReadReportAsync — Structured report reads Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Wraps the raw bytes in a HidReport object that separates the Report ID byte from the payload bytes. Callback and async overloads mirror the raw Read API. ```APIDOC ## HidDevice.ReadReport / ReadReportAsync — Structured report reads `ReadReport` wraps the raw bytes in a `HidReport` object that separates the Report ID byte from the payload bytes. The callback and async overloads mirror the raw `Read` API. ### Methods - `ReadReport()` - `ReadReport(int timeout)` - `ReadReport(ReadReportCallback callback, int timeout)` - `ReadReportAsync(int timeout)` ### Parameters #### Optional Parameters - **timeout** (int) - Description: Timeout in milliseconds for asynchronous operations. - **callback** (ReadReportCallback) - Description: A delegate that will be invoked with the read report for callback-based reads. ### Response - **HidReport** - An object containing the report ID, data, and status. - **Exists** (bool) - True if a report was successfully read. - **ReportId** (byte) - The ID of the report. - **Data** (byte[]) - The payload bytes of the report. - **ReadStatus** (HidDeviceData.ReadStatus) - The status of the read operation. ### Request Example ```csharp // Synchronous HidReport report = device.ReadReport(); // Async HidReport asyncReport = await device.ReadReportAsync(timeout: 500); // Callback void OnReport(HidReport r) { /* handle report */ } device.ReadReport(OnReport); ``` ### Response Example ```csharp { "Exists": true, "ReportId": 1, "Data": [ ... bytes ... ], "ReadStatus": "Success" } ``` ``` -------------------------------- ### HidDevice.Read — Synchronous raw byte read Source: https://context7.com/mikeobrien/hidlibrary/llms.txt Performs a blocking read of a single HID input report. A timeout can be supplied, where 0 means wait indefinitely. The returned HidDeviceData.Status enum indicates the outcome. ```APIDOC ## HidDevice.Read — Synchronous raw byte read Performs a blocking read of a single HID input report into `HidDeviceData`. A timeout (milliseconds) can be supplied; `0` means wait indefinitely. The returned `HidDeviceData.Status` enum indicates the outcome. ### Method `Read()` ### Parameters #### Optional Parameters - **timeout** (int) - Description: Timeout in milliseconds. `0` means wait indefinitely. ### Response - **HidDeviceData** - An object containing the read data and status. - **Status** (HidDeviceData.ReadStatus) - Indicates the outcome of the read operation (e.g., Success, WaitTimedOut, ReadError). - **Data** (byte[]) - The raw bytes read from the device. ### Request Example ```csharp // Blocking read, infinite wait HidDeviceData result = device.Read(); // Read with 500 ms timeout HidDeviceData timedResult = device.Read(timeout: 500); ``` ### Response Example ```csharp // On Success { "Status": "Success", "Data": [ ... bytes ... ] } // On Failure { "Status": "WaitTimedOut", "Data": null } ``` ``` -------------------------------- ### HidReport Source: https://context7.com/mikeobrien/hidlibrary/llms.txt A structured container for HID reports, separating the Report ID from the payload and allowing serialization back to the raw wire format. ```APIDOC ## HidReport ### Description `HidReport` separates the Report ID from the payload and exposes `GetBytes()` to re-serialize back to the raw wire format. It is both read from `ReadReport` and written with `WriteReport`. ### Properties - **Exists** (bool) - Indicates if the report is valid. - **ReportId** (byte) - The Report ID of the report. - **Data** (byte[]) - The payload data of the report. - **ReadStatus** (int) - The status of the last read operation. ### Methods - **GetBytes()**: Serializes the report back to the raw wire format (Report ID + Data). ### Example Usage ```csharp using System; using HidLibrary; var device = HidDevices.Enumerate(0x046D, 0xC216).FirstOrDefault(); device?.OpenDevice(); // Reading a report HidReport inReport = device.ReadReport(); Console.WriteLine($"Exists : {inReport.Exists}"); Console.WriteLine($"ReportId: {inReport.ReportId}"); Console.WriteLine($"Payload : {BitConverter.ToString(inReport.Data)}"); Console.WriteLine($"Status : {inReport.ReadStatus}"); // Building an outbound report manually HidReport outReport = new HidReport(device.Capabilities.OutputReportByteLength); outReport.ReportId = 0x00; outReport.Data[0] = 0x01; outReport.Data[1] = 0x02; byte[] raw = outReport.GetBytes(); // [ReportId, Data[0], Data[1], ...] Console.WriteLine($"Raw bytes: {BitConverter.ToString(raw)}"); device.WriteReport(outReport); device?.Dispose(); ``` ``` -------------------------------- ### Test with Ignored Method Source: https://github.com/mikeobrien/hidlibrary/blob/master/experimental/packages/NUnit.2.5.9.10348/NUnitFitTests.html A C# test fixture demonstrating an ignored test method, used to verify snippet runner functionality. ```csharp using NUnit.Framework; [TestFixture] public class TestClass { [Test] public void T1() { } [Test, Ignore] public void T2() { } [Test] public void T3() { } } ```