DotNetHid 0.2.0

dotnet add package DotNetHid --version 0.2.0
                    
NuGet\Install-Package DotNetHid -Version 0.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="DotNetHid" Version="0.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DotNetHid" Version="0.2.0" />
                    
Directory.Packages.props
<PackageReference Include="DotNetHid" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add DotNetHid --version 0.2.0
                    
#r "nuget: DotNetHid, 0.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#addin nuget:?package=DotNetHid&version=0.2.0
                    
Install as a Cake Addin
#tool nuget:?package=DotNetHid&version=0.2.0
                    
Install as a Cake Tool

DotNetHid

GitHub Actions Workflow Status NuGet Version GitHub License

.Net library for communicating with HID (Human Interface Devices). This library allows you to discover connected HID devices (such as keyboards, mice, etc.) and establish bidirectional communication with them.

A great use of this tool is communication with programmable devices that use vendor-defined Usage Page ranges (0xFF00-0xFFFF), enabling raw data exchange without interference from the operating system. One example is devices powered by QMK Firmware using the Raw HID feature. Such functionality can be used, for instance, to send system metrics (e.g., CPU/GPU/RAM usage) to the keyboard for display on its screen, or to remap input reports received from the keyboard to custom actions on the host system.

Usage:

using DotNetHid;

ushort vendorId  = 0x00; // device Vendor ID
ushort productId = 0x00; // device Product ID
ushort usagePage = 0x00; // HID Usage Page
ushort usageId   = 0x00; // HID Usage ID

var deviceInfo = Hid.Enumerate(vendorId, productId, usagePage, usageId).First();

Console.WriteLine($"Device name: {deviceInfo.ManufacturerString} - {deviceInfo.ProductString}");

var device = Hid.Create(deviceInfo);

if (!device.TryOpen(out var error))
{
  Console.WriteLine($"Failed to open: {error}");
  return;
}

using (device)
{
  if (!device.TryWrite([ 1, 2, 3, 4, 5 ], out error)) // sends data to the device
  {
    Console.WriteLine($"Failed to write: {error}");
    return;
  }

  var timeout = 1000; // ms

  var result = device.Read(timeout); // reads data from the device
  if (!result.IsOk(out var input, out error))
  {
    Console.WriteLine($"Failed to read: {error}");
    return;
  }

  Console.WriteLine($"[ {string.Join(", ", input)} ]");
}

Caveats

  • Both reading and writing methods open the device and close it afterward, if it wasn't initially open. Therefore, it's not necessary to manually open the device for a single read or write operation.
  • The HidDevice object is not thread-safe and should not be shared across threads. Create a new instance (e.g., var device = Hid.Create(...);) for each thread.
  • Calling Dispose() on an HidDevice instance (either explicitly or via a using block) does not make the object unusable. Disposing is simply a shortcut for calling Close(), making it convenient to use with the using keyword for automatic cleanup. The following two examples are functionally equivalent:
    // device.Open...
    
    using (device)
    {
      // read/write operations...
    }
    
    // device can still be re-used here
    
    // device.Open...
    
    try
    {
      // read/write operations...
    }
    finally
    {
      device.Close();
    }
    
  • If the device gets disconnected during read or write operations (i.e., error.Kind == ErrorKind.DeviceNotConnected), the device is automatically disposed. To re-establish communication, simply call .Open (or .TryOpen) on the same device instance:
    while (true) // assume we've opened the device earlier and are reading input reports in a loop
    {
      if (!device.Read().IsOk(out var input, out var error))
      {
        switch (error.Kind)
        {
        case ErrorKind.DeviceNotConnected: // device got disconnected
          if (device.TryOpen(out error)) // try to reconnect and continue
          {
            continue;
          }
          Console.WriteLine($"Failed to reconnect: {error}");
          return;
    
        // handle other error cases...
        }
      }
    }
    

ToDo

  • support older Target Frameworks
  • support Linux
  • support macOS
Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net9.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.2.0 108 6/25/2025
0.1.1 180 5/16/2025