Skip to main content

framework-dotnet

framework-dotnet (FrameworkDotnet) is a .NET library for talking to Framework laptop and desktop embedded controller APIs through the native framework-system Rust FFI layer. Developed by community member TekuSP, it provides a managed API for detecting EC drivers, reading platform/product information, opening EC connections, reading firmware/power/fan/thermal snapshots, and controlling fan RPM and duty — all without exposing unsafe code to callers1.

The library wraps Framework's official framework-system Rust crate through an FFI extensions layer, using csbindgen to generate low-level C# interop bindings and UnitsNet for unit-bearing values. A hand-written API surface sits on top so normal .NET callers never need to work with pointers or unsafe code1.

Architecture

The project uses the following layered architecture1:

LayerTechnologyPurpose
Native hardware accessframework-system (Rust, nested submodule)Chromium EC interface
FFI extensionsframework-system-ffi-extensions (Rust submodule)Native .NET FFI layer
Interop bindingscsbindgenGenerates C# bindings from Rust
Managed APIFrameworkDotnet (C#)Hand-written, safe public API
Unit typesUnitsNetTemperature, RotationalSpeed, Ratio, ElectricPotential, etc.

Public API

The public API is centered around two main entry points1:

FrameworkSystem

  • Detects platform and product information
  • Checks driver support (IsDriverSupported(...))
  • Opens EC connections (OpenDefaultEc())

IFrameworkEcConnection

  • Reads firmware, power, fan capability, and thermal snapshots
  • Sends fan control commands (set RPM, set duty, restore automatic control)

Snapshot Types

TypeData
FrameworkEcFlashSnapshotCurrent image, RO/RW firmware versions
FrameworkPowerSnapshotPower state, battery info
FrameworkBatterySnapshotBattery voltage, rate, capacity, state
FrameworkFanCapabilitiesSnapshotFan count and capabilities
FrameworkThermalSnapshotTemperature sensors (0–7), fans (0–3), sensor count, sensor names
FrameworkFanSnapshotFan speed, fan state
FrameworkTemperatureSnapshotTemperature, state
FrameworkInputModulePositionSnapshotFramework Laptop 16 input module physical position

The public snapshot API intentionally stays aligned with the native Rust fixed-slot structs (e.g., FrameworkThermalSnapshot.Temperature_0 through Temperature_7, Fan_0 through Fan_3). Count-aware enumerable properties (ReportedBatteries, ReportedTemperatures, ReportedFans) return only entries reported by the corresponding count field1.

Units

Public unit-bearing values use UnitsNet1:

QuantityUnitsNet Type
TemperaturesUnitsNet.Temperature
Fan speedsUnitsNet.RotationalSpeed
Fan dutyUnitsNet.Ratio
Battery voltageUnitsNet.ElectricPotential
Battery rateUnitsNet.ElectricCurrent
Battery capacitiesUnitsNet.ElectricCharge

Exception Types

Public API methods throw specific managed exception types rather than requiring callers to inspect status codes1:

  • FrameworkEcResponseException and derived EC response exceptions
  • FrameworkInvalidFanIndexException
  • FrameworkBatteryStateException and derived battery state exceptions
  • FrameworkTemperatureStateException and derived temperature state exceptions
  • FrameworkFanStateException and derived fan state exceptions

When native context is available, exceptions attempt to include native descriptions and device error messages from the Rust layer (best-effort).

Installation

NuGet

<PackageReference Include="FrameworkDotnet" Version="0.8.213" />

UnitsNet is already a dependency of the library, so callers do not need to add separate unit types manually1.

Building from Source

git clone https://github.com/TekuSP/framework-dotnet.git
cd framework-dotnet
dotnet build framework-dotnet/framework-dotnet.csproj

If generated bindings and native assets are already supplied externally, the Rust build step can be skipped:

dotnet build framework-dotnet/framework-dotnet.csproj /p:SkipRustBuild=true

Example

using FrameworkDotnet;
using FrameworkDotnet.Exceptions;

var frameworkSystem = new FrameworkSystem();

try
{
using var ec = frameworkSystem.OpenDefaultEc();

var thermal = ec.GetThermalSnapshot();

foreach (var temperature in thermal.ReportedTemperatures)
{
Console.WriteLine($"Temperature: {temperature.Temperature.DegreesCelsius}C ({temperature.State})");
}

foreach (var fan in thermal.ReportedFans)
{
Console.WriteLine($"Fan: {fan.Speed.RevolutionsPerMinute} RPM ({fan.FanState})");
}
}
catch (FrameworkEcResponseException ex)
{
Console.WriteLine($"EC response failure: {ex.Detail}");
Console.WriteLine($"Description: {ex.Description}");
}

Native Loading

PlatformNative LibraryNotes
Windows x64/arm64framework_lib_ffi.dllExpected beside the application or in the packaged runtime-specific native layout
Linux x64/arm64libframework_lib_ffi.soExpected beside the application or in the packaged runtime-specific native layout

On both platforms, successful native loading alone does not guarantee that EC operations will succeed — permissions, kernel support, driver availability, and installed BIOS/firmware versions still matter. IsDriverSupported(...) should be treated as a runtime check1.

Technical Details

DetailValue
LanguageC# (.NET 10.0)
LicenseMIT
Stars4
Commits130+
NuGet packageFrameworkDotnet v0.8.213 (source v0.9.0)
FFI layerframework-system-ffi-extensions (Rust) with csbindgen
Unit libraryUnitsNet
PlatformsWindows x64/arm64 (DLL), Linux x64/arm64 (.so)
AffiliationNot affiliated with Framework Computer Inc.
ProjectDescription
Framework Tool TUITerminal dashboard using framework_lib (Rust)
Framework ControlGUI tool using framework_tool CLI
fw-fanctrlFan control daemon using ectool for EC access
FanFramePer-fan control GUI for Framework Desktop using framework_tool

Footnotes

  1. TekuSP/framework-dotnet — GitHub 2 3 4 5 6 7 8 9