From 4dac9b505a5383121f15e14c9244d920f328e6b4 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Sat, 2 Aug 2025 22:03:48 +0800 Subject: [PATCH 1/7] WIP: Customize LED config by registry settings Signed-off-by: Daniel Schaefer --- FrameworkArgb/Device.c | 124 +++++++++++++++++++++++++++++++++++++++++ FrameworkArgb/Device.h | 11 +++- README.md | 26 +++++++++ 3 files changed, 160 insertions(+), 1 deletion(-) diff --git a/FrameworkArgb/Device.c b/FrameworkArgb/Device.c index 356e992..420c012 100644 --- a/FrameworkArgb/Device.c +++ b/FrameworkArgb/Device.c @@ -261,6 +261,9 @@ Return Value: deviceContext->Device = device; deviceContext->CurrentLampId = 0; deviceContext->AutonomousMode = TRUE; + + // zoid + // 8 LEDs in a circle // z is 0 for all LEDs, they're all in the same plane // Bottom LED @@ -526,3 +529,124 @@ Return Value: status = RequestCopyFromBuffer(Request, string, stringSizeCb); return status; } + +NTSTATUS +CheckRegistryForDescriptor( + WDFDEVICE Device +) +/*++ + +Routine Description: + + Read "ReadFromRegistry" key value from device parameters in the registry. + +Arguments: + + device - pointer to a device object. + +Return Value: + + NT status code. + +--*/ + +{ + WDFKEY hKey = NULL; + NTSTATUS status; + UNICODE_STRING valueName; + ULONG value; + + status = WdfDeviceOpenRegistryKey(Device, + PLUGPLAY_REGKEY_DEVICE, + KEY_READ, + WDF_NO_OBJECT_ATTRIBUTES, + &hKey); + if (NT_SUCCESS(status)) { + + RtlInitUnicodeString(&valueName, L"ReadFromRegistry"); + + status = WdfRegistryQueryULong(hKey, + &valueName, + &value); + + if (NT_SUCCESS(status)) { + if (value == 0) { + status = STATUS_UNSUCCESSFUL; + } + } + + WdfRegistryClose(hKey); + } + + return status; +} + +NTSTATUS +ReadDescriptorFromRegistry( + WDFDEVICE Device +) +/*++ + +Routine Description: + + Read HID report descriptor from registry + +Arguments: + + device - pointer to a device object. + +Return Value: + + NT status code. + +--*/ +{ + WDFKEY hKey = NULL; + NTSTATUS status; + UNICODE_STRING valueName; + WDFMEMORY memory; + size_t bufferSize; + PVOID reportDescriptor; + PDEVICE_CONTEXT deviceContext; + WDF_OBJECT_ATTRIBUTES attributes; + + deviceContext = GetDeviceContext(Device); + + status = WdfDeviceOpenRegistryKey(Device, + PLUGPLAY_REGKEY_DEVICE, + KEY_READ, + WDF_NO_OBJECT_ATTRIBUTES, + &hKey); + + if (NT_SUCCESS(status)) { + + RtlInitUnicodeString(&valueName, L"MyReportDescriptor"); + + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = Device; + + status = WdfRegistryQueryMemory(hKey, + &valueName, + NonPagedPool, + &attributes, + &memory, + NULL); + + if (NT_SUCCESS(status)) { + + reportDescriptor = WdfMemoryGetBuffer(memory, &bufferSize); + + KdPrint(("No. of report descriptor bytes copied: %d\n", (INT)bufferSize)); + + // + // Store the registry report descriptor in the device extension + // + deviceContext->ReportDescriptor = reportDescriptor; + deviceContext->HidDescriptor.DescriptorList[0].wReportLength = (USHORT)bufferSize; + } + + WdfRegistryClose(hKey); + } + + return status; +} diff --git a/FrameworkArgb/Device.h b/FrameworkArgb/Device.h index 188ae69..663a4eb 100644 --- a/FrameworkArgb/Device.h +++ b/FrameworkArgb/Device.h @@ -51,7 +51,7 @@ typedef struct _DEVICE_CONTEXT Position LampPositions[LAMPARRAY_LAMP_COUNT]; HID_DESCRIPTOR HidDescriptor; PHID_REPORT_DESCRIPTOR ReportDescriptor; - BOOLEAN ReadReportDescFromRegistry; + BOOLEAN ReadLedConfigFromRegistry; } DEVICE_CONTEXT, * PDEVICE_CONTEXT; // @@ -168,6 +168,15 @@ RequestGetHidXferPacket_ToWriteToDevice( _Out_ HID_XFER_PACKET* Packet ); +NTSTATUS +CheckRegistryForLedConfig( + _In_ WDFDEVICE Device +); + +NTSTATUS +ReadLedConfigFromRegistry( + _In_ WDFDEVICE Device +); // // Misc definitions diff --git a/README.md b/README.md index fa02dd9..cd0fabe 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,32 @@ References: - [Windows.Devices.Enumeration](https://learn.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher?view=winrt-26100) - [Game Dev Documentation](https://learn.microsoft.com/en-us/gaming/gdk/docs/features/common/lighting/gc-lighting-toc) +## Configuration + +When the driver loads, the Windows Dynamic Lighting interface (or any HID +application) asks it about the LED configuration - how many and where in 3D +space. +This is so that they can know how to apply 2D or 3D animations to them. + +By default the driver loads with an 8 LED configuration arranged in a circle of +20mm diameter. This matches the ARGB fan that Framework offers for the +Framework Desktop. + +To customize the configuration, set/edit the following registry entries. +They are all under: `TBD` + +| Name | Type | Explanation | +| ReadFromRegistry | DWORD | If 1, the other values are read | +| LedCount | DWORD | How many LEDs in total | +| LedArrangement | DWORD | How the LEDs are arranged | + +LedArrangement can have the following values: + +- 0: Circular, layers of 8 (e.g. when 16 LEDs in total, two layers of 8 LEDs) +- 1: Circular, single layer +- 2: Linear (e.g. LED strip) +- 3: Square Matrix (works best with a square number of LEDs) + ## Development ### Build From 39d44e1c08201f37f25a6b85e2b3f085de9e2ea3 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Sat, 2 Aug 2025 23:20:04 +0800 Subject: [PATCH 2/7] fixup! WIP: Customize LED config by registry settings --- FrameworkArgb/Device.c | 134 ++++++++++++++++++++++++++++++++--------- FrameworkArgb/Device.h | 6 +- README.md | 1 + 3 files changed, 109 insertions(+), 32 deletions(-) diff --git a/FrameworkArgb/Device.c b/FrameworkArgb/Device.c index 420c012..51b8424 100644 --- a/FrameworkArgb/Device.c +++ b/FrameworkArgb/Device.c @@ -17,6 +17,7 @@ Module Name: #include "driver.h" #include "EcCommunication.h" #include "device.tmh" +#include // // This is the default report descriptor for the virtual Hid device returned @@ -200,6 +201,79 @@ HID_DESCRIPTOR G_DefaultHidDescriptor = { } }; +NTSTATUS +CalculateLampPositions( + Position *LampPositions, + UINT8 LedCount, + UINT8 LedArrangement +) +{ + UINT8 Layers = 0; + if (LedCount > MAX_LAMPARRAY_LAMP_COUNT) { + TraceError("LedCount %d over %d", LedCount, MAX_LAMPARRAY_LAMP_COUNT); + return STATUS_INVALID_PARAMETER; + } + + switch (LedArrangement) { + // Circular, layers of 8 + case 0: + for (UINT8 i = 0; i <= LedCount / 8; i++) { + // 8 LEDs in a circle + // z is 0 for all LEDs, they're all in the same plane + // Bottom LED + deviceContext->LampPositions[i+0].x = 40000; + deviceContext->LampPositions[i+0].y = 0; + deviceContext->LampPositions[i+1].x = 60000; + deviceContext->LampPositions[i+1].y = 20000; + // Right LED + deviceContext->LampPositions[i+2].x = 80000; + deviceContext->LampPositions[i+2].y = 40000; + deviceContext->LampPositions[i+3].x = 60000; + deviceContext->LampPositions[i+3].y = 60000; + // Top LED + deviceContext->LampPositions[i+4].x = 40000; + deviceContext->LampPositions[i+4].y = 80000; + deviceContext->LampPositions[i+5].x = 20000; + deviceContext->LampPositions[i+5].y = 60000; + // Left LED + deviceContext->LampPositions[i+6].x = 0; + deviceContext->LampPositions[i+6].y = 40000; + deviceContext->LampPositions[i+7].x = 20000; + deviceContext->LampPositions[i+7].y = 20000; + } + break; + // Circular, single layer, even distance from each other + case 1: + for (UINT8 i = 0; i <= LedCount; i++) { + // TODO + deviceContext->LampPositions[i].x = 0; + deviceContext->LampPositions[i].y = 0; + } + break; + // Linear, LED strip with 5mm distance + case 2: + for (UINT8 i = 0; i <= LedCount / 8; i++) { + deviceContext->LampPositions[i].x = i * 5000; + deviceContext->LampPositions[i].y = 0; + } + break; + } + // Square Matrix with 5mm distance + case 3: + Layers = (UINT8) sqrt((double) LedCount); + for (UINT8 i = 0; i <= LedCount; i++) { + deviceContext->LampPositions[i].x = (i % Layers) * 5000; + deviceContext->LampPositions[i].y = (i / Layers) * 5000; + } + break; + default: + TraceError("LedArrangement %d invalidt.", LedArrangement); + return STATUS_INVALID_PARAMETER; + } + + return STATUS_SUCCESS; +} + NTSTATUS FrameworkArgbCreateDevice( _Inout_ PWDFDEVICE_INIT DeviceInit @@ -227,6 +301,8 @@ Return Value: PHID_DEVICE_ATTRIBUTES hidAttributes; WDFDEVICE device; NTSTATUS status; + UINT8 LedCount; + UINT8 LedArrangement; TraceInformation("%!FUNC! Entry"); @@ -262,30 +338,28 @@ Return Value: deviceContext->CurrentLampId = 0; deviceContext->AutonomousMode = TRUE; - // zoid - - // 8 LEDs in a circle - // z is 0 for all LEDs, they're all in the same plane - // Bottom LED - deviceContext->LampPositions[0].x = 40000; - deviceContext->LampPositions[0].y = 0; - deviceContext->LampPositions[1].x = 60000; - deviceContext->LampPositions[1].y = 20000; - // Right LED - deviceContext->LampPositions[2].x = 80000; - deviceContext->LampPositions[2].y = 40000; - deviceContext->LampPositions[3].x = 60000; - deviceContext->LampPositions[3].y = 60000; - // Top LED - deviceContext->LampPositions[4].x = 40000; - deviceContext->LampPositions[4].y = 80000; - deviceContext->LampPositions[5].x = 20000; - deviceContext->LampPositions[5].y = 60000; - // Left LED - deviceContext->LampPositions[6].x = 0; - deviceContext->LampPositions[6].y = 40000; - deviceContext->LampPositions[7].x = 20000; - deviceContext->LampPositions[7].y = 20000; + status = CheckRegistryForLedConfig(device); + deviceContext->LedCount = 0; + if (NT_SUCCESS(status)) { + // + // We need to read read descriptor from registry + // + status = ReadLedConfigFromRegistry(device, &LedCount, &LedArrangement); + if (!NT_SUCCESS(status)) { + TraceError("Failed to read descriptor from registry\n"); + } + } + + status = CalculateLampPositions(&deviceContext->LampPositions, deviceContext->LedCount, LedArrangement); + if (!NT_SUCCESS(status)) { + deviceContext->LedCount = 0; + } + + // Default 8 LED fan + if (deviceContext->LedCount == 0) { + deviceContext->LedCount = 8; + LedArrangement = 0; + } hidAttributes = &deviceContext->HidDeviceAttributes; RtlZeroMemory(hidAttributes, sizeof(HID_DEVICE_ATTRIBUTES)); @@ -531,7 +605,7 @@ Return Value: } NTSTATUS -CheckRegistryForDescriptor( +CheckRegistryForLedConfig( WDFDEVICE Device ) /*++ @@ -582,14 +656,16 @@ Return Value: } NTSTATUS -ReadDescriptorFromRegistry( - WDFDEVICE Device +ReadLedConfigFromRegistry( + WDFDEVICE Device, + UINT8 *LedCount, + UINT8 *LedArrangement ) /*++ Routine Description: - Read HID report descriptor from registry + Read LED config report descriptor from registry Arguments: @@ -636,7 +712,7 @@ Return Value: reportDescriptor = WdfMemoryGetBuffer(memory, &bufferSize); - KdPrint(("No. of report descriptor bytes copied: %d\n", (INT)bufferSize)); + TraceInformation("No. of report descriptor bytes copied: %d\n", (INT)bufferSize); // // Store the registry report descriptor in the device extension diff --git a/FrameworkArgb/Device.h b/FrameworkArgb/Device.h index 663a4eb..8192942 100644 --- a/FrameworkArgb/Device.h +++ b/FrameworkArgb/Device.h @@ -28,7 +28,7 @@ DRIVER_INITIALIZE DriverEntry; EVT_WDF_DRIVER_DEVICE_ADD EvtDeviceAdd; EVT_WDF_TIMER EvtTimerFunc; -#define LAMPARRAY_LAMP_COUNT 8 +#define MAX_LAMPARRAY_LAMP_COUNT 256 #define LAMPARRAY_WIDTH 80000 // 80mm #define LAMPARRAY_HEIGHT 80000 // 80mm #define LAMPARRAY_DEPTH 20000 // 20mm @@ -48,10 +48,10 @@ typedef struct _DEVICE_CONTEXT HANDLE CrosEcHandle; UINT16 CurrentLampId; BOOLEAN AutonomousMode; - Position LampPositions[LAMPARRAY_LAMP_COUNT]; + UINT8 LampCount; + Position LampPositions[MAX_LAMPARRAY_LAMP_COUNT]; HID_DESCRIPTOR HidDescriptor; PHID_REPORT_DESCRIPTOR ReportDescriptor; - BOOLEAN ReadLedConfigFromRegistry; } DEVICE_CONTEXT, * PDEVICE_CONTEXT; // diff --git a/README.md b/README.md index cd0fabe..db27b9e 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ To customize the configuration, set/edit the following registry entries. They are all under: `TBD` | Name | Type | Explanation | +|------------------|-------|---------------------------------| | ReadFromRegistry | DWORD | If 1, the other values are read | | LedCount | DWORD | How many LEDs in total | | LedArrangement | DWORD | How the LEDs are arranged | From 000891e1a4d857d7c53436f00fdec616a951df4c Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Sat, 2 Aug 2025 23:22:14 +0800 Subject: [PATCH 3/7] fixup! WIP: Customize LED config by registry settings --- FrameworkArgb/Device.c | 45 +++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/FrameworkArgb/Device.c b/FrameworkArgb/Device.c index 51b8424..f7ecbd6 100644 --- a/FrameworkArgb/Device.c +++ b/FrameworkArgb/Device.c @@ -221,49 +221,48 @@ CalculateLampPositions( // 8 LEDs in a circle // z is 0 for all LEDs, they're all in the same plane // Bottom LED - deviceContext->LampPositions[i+0].x = 40000; - deviceContext->LampPositions[i+0].y = 0; - deviceContext->LampPositions[i+1].x = 60000; - deviceContext->LampPositions[i+1].y = 20000; + LampPositions[i+0].x = 40000; + LampPositions[i+0].y = 0; + LampPositions[i+1].x = 60000; + LampPositions[i+1].y = 20000; // Right LED - deviceContext->LampPositions[i+2].x = 80000; - deviceContext->LampPositions[i+2].y = 40000; - deviceContext->LampPositions[i+3].x = 60000; - deviceContext->LampPositions[i+3].y = 60000; + LampPositions[i+2].x = 80000; + LampPositions[i+2].y = 40000; + LampPositions[i+3].x = 60000; + LampPositions[i+3].y = 60000; // Top LED - deviceContext->LampPositions[i+4].x = 40000; - deviceContext->LampPositions[i+4].y = 80000; - deviceContext->LampPositions[i+5].x = 20000; - deviceContext->LampPositions[i+5].y = 60000; + LampPositions[i+4].x = 40000; + LampPositions[i+4].y = 80000; + LampPositions[i+5].x = 20000; + LampPositions[i+5].y = 60000; // Left LED - deviceContext->LampPositions[i+6].x = 0; - deviceContext->LampPositions[i+6].y = 40000; - deviceContext->LampPositions[i+7].x = 20000; - deviceContext->LampPositions[i+7].y = 20000; + LampPositions[i+6].x = 0; + LampPositions[i+6].y = 40000; + LampPositions[i+7].x = 20000; + LampPositions[i+7].y = 20000; } break; // Circular, single layer, even distance from each other case 1: for (UINT8 i = 0; i <= LedCount; i++) { // TODO - deviceContext->LampPositions[i].x = 0; - deviceContext->LampPositions[i].y = 0; + LampPositions[i].x = 0; + LampPositions[i].y = 0; } break; // Linear, LED strip with 5mm distance case 2: for (UINT8 i = 0; i <= LedCount / 8; i++) { - deviceContext->LampPositions[i].x = i * 5000; - deviceContext->LampPositions[i].y = 0; + LampPositions[i].x = i * 5000; + LampPositions[i].y = 0; } break; - } // Square Matrix with 5mm distance case 3: Layers = (UINT8) sqrt((double) LedCount); for (UINT8 i = 0; i <= LedCount; i++) { - deviceContext->LampPositions[i].x = (i % Layers) * 5000; - deviceContext->LampPositions[i].y = (i / Layers) * 5000; + LampPositions[i].x = (i % Layers) * 5000; + LampPositions[i].y = (i / Layers) * 5000; } break; default: From 63bbd6586c360eae33b61842949572d3995c7458 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Sat, 2 Aug 2025 23:33:12 +0800 Subject: [PATCH 4/7] fixup! WIP: Customize LED config by registry settings --- FrameworkArgb/Device.c | 77 +++++++++++++++++++----------------------- FrameworkArgb/Device.h | 4 ++- 2 files changed, 37 insertions(+), 44 deletions(-) diff --git a/FrameworkArgb/Device.c b/FrameworkArgb/Device.c index f7ecbd6..5c82d0f 100644 --- a/FrameworkArgb/Device.c +++ b/FrameworkArgb/Device.c @@ -204,20 +204,20 @@ HID_DESCRIPTOR G_DefaultHidDescriptor = { NTSTATUS CalculateLampPositions( Position *LampPositions, - UINT8 LedCount, + UINT8 LampCount, UINT8 LedArrangement ) { UINT8 Layers = 0; - if (LedCount > MAX_LAMPARRAY_LAMP_COUNT) { - TraceError("LedCount %d over %d", LedCount, MAX_LAMPARRAY_LAMP_COUNT); + if (LampCount > MAX_LAMPARRAY_LAMP_COUNT) { + TraceError("LampCount %d over %d", LampCount, MAX_LAMPARRAY_LAMP_COUNT); return STATUS_INVALID_PARAMETER; } switch (LedArrangement) { // Circular, layers of 8 case 0: - for (UINT8 i = 0; i <= LedCount / 8; i++) { + for (UINT8 i = 0; i <= LampCount / 8; i++) { // 8 LEDs in a circle // z is 0 for all LEDs, they're all in the same plane // Bottom LED @@ -244,7 +244,7 @@ CalculateLampPositions( break; // Circular, single layer, even distance from each other case 1: - for (UINT8 i = 0; i <= LedCount; i++) { + for (UINT8 i = 0; i <= LampCount; i++) { // TODO LampPositions[i].x = 0; LampPositions[i].y = 0; @@ -252,15 +252,15 @@ CalculateLampPositions( break; // Linear, LED strip with 5mm distance case 2: - for (UINT8 i = 0; i <= LedCount / 8; i++) { + for (UINT8 i = 0; i <= LampCount / 8; i++) { LampPositions[i].x = i * 5000; LampPositions[i].y = 0; } break; // Square Matrix with 5mm distance case 3: - Layers = (UINT8) sqrt((double) LedCount); - for (UINT8 i = 0; i <= LedCount; i++) { + Layers = (UINT8) sqrt((double) LampCount); + for (UINT8 i = 0; i <= LampCount; i++) { LampPositions[i].x = (i % Layers) * 5000; LampPositions[i].y = (i / Layers) * 5000; } @@ -300,7 +300,7 @@ Return Value: PHID_DEVICE_ATTRIBUTES hidAttributes; WDFDEVICE device; NTSTATUS status; - UINT8 LedCount; + UINT8 LampCount; UINT8 LedArrangement; TraceInformation("%!FUNC! Entry"); @@ -338,25 +338,25 @@ Return Value: deviceContext->AutonomousMode = TRUE; status = CheckRegistryForLedConfig(device); - deviceContext->LedCount = 0; + deviceContext->LampCount = 0; if (NT_SUCCESS(status)) { // // We need to read read descriptor from registry // - status = ReadLedConfigFromRegistry(device, &LedCount, &LedArrangement); + status = ReadLedConfigFromRegistry(device, &LampCount, &LedArrangement); if (!NT_SUCCESS(status)) { TraceError("Failed to read descriptor from registry\n"); } } - status = CalculateLampPositions(&deviceContext->LampPositions, deviceContext->LedCount, LedArrangement); + status = CalculateLampPositions(&deviceContext->LampPositions[0], deviceContext->LampCount, LedArrangement); if (!NT_SUCCESS(status)) { - deviceContext->LedCount = 0; + deviceContext->LampCount = 0; } // Default 8 LED fan - if (deviceContext->LedCount == 0) { - deviceContext->LedCount = 8; + if (deviceContext->LampCount == 0) { + deviceContext->LampCount = 8; LedArrangement = 0; } @@ -657,7 +657,7 @@ Return Value: NTSTATUS ReadLedConfigFromRegistry( WDFDEVICE Device, - UINT8 *LedCount, + UINT8 *LampCount, UINT8 *LedArrangement ) /*++ @@ -679,11 +679,10 @@ Return Value: WDFKEY hKey = NULL; NTSTATUS status; UNICODE_STRING valueName; - WDFMEMORY memory; size_t bufferSize; PVOID reportDescriptor; PDEVICE_CONTEXT deviceContext; - WDF_OBJECT_ATTRIBUTES attributes; + ULONG value; deviceContext = GetDeviceContext(Device); @@ -693,35 +692,27 @@ Return Value: WDF_NO_OBJECT_ATTRIBUTES, &hKey); - if (NT_SUCCESS(status)) { - - RtlInitUnicodeString(&valueName, L"MyReportDescriptor"); - - WDF_OBJECT_ATTRIBUTES_INIT(&attributes); - attributes.ParentObject = Device; - - status = WdfRegistryQueryMemory(hKey, - &valueName, - NonPagedPool, - &attributes, - &memory, - NULL); - - if (NT_SUCCESS(status)) { - - reportDescriptor = WdfMemoryGetBuffer(memory, &bufferSize); - - TraceInformation("No. of report descriptor bytes copied: %d\n", (INT)bufferSize); + if (!NT_SUCCESS(status)) { + return status; + } - // - // Store the registry report descriptor in the device extension - // - deviceContext->ReportDescriptor = reportDescriptor; - deviceContext->HidDescriptor.DescriptorList[0].wReportLength = (USHORT)bufferSize; - } + RtlInitUnicodeString(&valueName, L"LedCount"); + status = RtlInitUnicodeString(hKey, &valueName, value); + if (!NT_SUCCESS(status)) { + WdfRegistryClose(hKey); + return status; + } + *LampCount = (UINT8) value; + RtlInitUnicodeString(&valueName, L"LedArrangement"); + status = RtlInitUnicodeString(hKey, &valueName, value); + if (!NT_SUCCESS(status)) { WdfRegistryClose(hKey); + return status; } + *LedArrangement = (UINT8) value; + + WdfRegistryClose(hKey); return status; } diff --git a/FrameworkArgb/Device.h b/FrameworkArgb/Device.h index 8192942..79e6648 100644 --- a/FrameworkArgb/Device.h +++ b/FrameworkArgb/Device.h @@ -175,7 +175,9 @@ CheckRegistryForLedConfig( NTSTATUS ReadLedConfigFromRegistry( - _In_ WDFDEVICE Device + _In_ WDFDEVICE Device + _Out_ UINT8 *LampCount, + _Out_ UINT8 *LedArrangement ); // From 8cbc993cad43b96d63bc8ec0c0c380ce1c22d4f7 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Sun, 3 Aug 2025 00:30:21 +0800 Subject: [PATCH 5/7] fixup! WIP: Customize LED config by registry settings --- FrameworkArgb/Device.c | 105 +++++++++++++++++++++++------------- FrameworkArgb/Device.h | 6 ++- FrameworkArgb/LampArray.cpp | 8 +-- README.md | 12 ++++- 4 files changed, 87 insertions(+), 44 deletions(-) diff --git a/FrameworkArgb/Device.c b/FrameworkArgb/Device.c index 5c82d0f..b0302f3 100644 --- a/FrameworkArgb/Device.c +++ b/FrameworkArgb/Device.c @@ -17,6 +17,7 @@ Module Name: #include "driver.h" #include "EcCommunication.h" #include "device.tmh" +#define _USE_MATH_DEFINES #include // @@ -203,8 +204,8 @@ HID_DESCRIPTOR G_DefaultHidDescriptor = { NTSTATUS CalculateLampPositions( - Position *LampPositions, - UINT8 LampCount, + PDEVICE_CONTEXT DeviceContext, + UINT16 LampCount, UINT8 LedArrangement ) { @@ -217,56 +218,70 @@ CalculateLampPositions( switch (LedArrangement) { // Circular, layers of 8 case 0: + DeviceContext->Width = 80000; + DeviceContext->Height = 80000; for (UINT8 i = 0; i <= LampCount / 8; i++) { // 8 LEDs in a circle // z is 0 for all LEDs, they're all in the same plane // Bottom LED - LampPositions[i+0].x = 40000; - LampPositions[i+0].y = 0; - LampPositions[i+1].x = 60000; - LampPositions[i+1].y = 20000; + DeviceContext->LampPositions[i+0].x = 40000; + DeviceContext->LampPositions[i+0].y = 0; + DeviceContext->LampPositions[i+1].x = 60000; + DeviceContext->LampPositions[i+1].y = 20000; // Right LED - LampPositions[i+2].x = 80000; - LampPositions[i+2].y = 40000; - LampPositions[i+3].x = 60000; - LampPositions[i+3].y = 60000; + DeviceContext->LampPositions[i+2].x = 80000; + DeviceContext->LampPositions[i+2].y = 40000; + DeviceContext->LampPositions[i+3].x = 60000; + DeviceContext->LampPositions[i+3].y = 60000; // Top LED - LampPositions[i+4].x = 40000; - LampPositions[i+4].y = 80000; - LampPositions[i+5].x = 20000; - LampPositions[i+5].y = 60000; + DeviceContext->LampPositions[i+4].x = 40000; + DeviceContext->LampPositions[i+4].y = 80000; + DeviceContext->LampPositions[i+5].x = 20000; + DeviceContext->LampPositions[i+5].y = 60000; // Left LED - LampPositions[i+6].x = 0; - LampPositions[i+6].y = 40000; - LampPositions[i+7].x = 20000; - LampPositions[i+7].y = 20000; + DeviceContext->LampPositions[i+6].x = 0; + DeviceContext->LampPositions[i+6].y = 40000; + DeviceContext->LampPositions[i+7].x = 20000; + DeviceContext->LampPositions[i+7].y = 20000; } break; - // Circular, single layer, even distance from each other + // LEDs arranged in a circle single layer, even distance from each other case 1: - for (UINT8 i = 0; i <= LampCount; i++) { - // TODO - LampPositions[i].x = 0; - LampPositions[i].y = 0; + DeviceContext->Width = 80000; + DeviceContext->Height = 80000; + { + // Place LampCount LEDs evenly spaced around a circle of radius 40000 (centered at 40000,40000) + double centerX = 40000.0; + double centerY = 40000.0; + double radius = 40000.0; + for (UINT8 i = 0; i < LampCount; i++) { + double angle = (2.0 * M_PI * i) / LampCount; + DeviceContext->LampPositions[i].x = (UINT32)(centerX + radius * cos(angle)); + DeviceContext->LampPositions[i].y = (UINT32)(centerY + radius * sin(angle)); + } } break; // Linear, LED strip with 5mm distance case 2: + DeviceContext->Width = LampCount * 5000; + DeviceContext->Height = 0; for (UINT8 i = 0; i <= LampCount / 8; i++) { - LampPositions[i].x = i * 5000; - LampPositions[i].y = 0; + DeviceContext->LampPositions[i].x = i * 5000; + DeviceContext->LampPositions[i].y = 0; } break; // Square Matrix with 5mm distance case 3: Layers = (UINT8) sqrt((double) LampCount); + DeviceContext->Width = Layers * 5000; + DeviceContext->Height = Layers * 5000; for (UINT8 i = 0; i <= LampCount; i++) { - LampPositions[i].x = (i % Layers) * 5000; - LampPositions[i].y = (i / Layers) * 5000; + DeviceContext->LampPositions[i].x = (i % Layers) * 5000; + DeviceContext->LampPositions[i].y = (i / Layers) * 5000; } break; default: - TraceError("LedArrangement %d invalidt.", LedArrangement); + TraceError("LedArrangement %d invalid.", LedArrangement); return STATUS_INVALID_PARAMETER; } @@ -337,25 +352,34 @@ Return Value: deviceContext->CurrentLampId = 0; deviceContext->AutonomousMode = TRUE; - status = CheckRegistryForLedConfig(device); + LampCount = 0; deviceContext->LampCount = 0; + deviceContext->Width = 0; + deviceContext->Height = 0; + LedArrangement = 0; + status = CheckRegistryForLedConfig(device); if (NT_SUCCESS(status)) { // // We need to read read descriptor from registry // status = ReadLedConfigFromRegistry(device, &LampCount, &LedArrangement); if (!NT_SUCCESS(status)) { - TraceError("Failed to read descriptor from registry\n"); + TraceError("Failed to read LED config from registry\n"); } } - status = CalculateLampPositions(&deviceContext->LampPositions[0], deviceContext->LampCount, LedArrangement); + status = CalculateLampPositions(deviceContext, LampCount, LedArrangement); if (!NT_SUCCESS(status)) { + TraceError("Failed to calulcate lamp positions\n"); deviceContext->LampCount = 0; } + else { + deviceContext->LampCount = LampCount; + } // Default 8 LED fan if (deviceContext->LampCount == 0) { + TraceError("No lamps set, falling back to default"); deviceContext->LampCount = 8; LedArrangement = 0; } @@ -629,13 +653,14 @@ Return Value: UNICODE_STRING valueName; ULONG value; + TraceInformation("%!FUNC! Entry"); status = WdfDeviceOpenRegistryKey(Device, PLUGPLAY_REGKEY_DEVICE, KEY_READ, WDF_NO_OBJECT_ATTRIBUTES, &hKey); if (NT_SUCCESS(status)) { - + TraceInformation("%!FUNC! Found driver Registry key"); RtlInitUnicodeString(&valueName, L"ReadFromRegistry"); status = WdfRegistryQueryULong(hKey, @@ -643,6 +668,7 @@ Return Value: &value); if (NT_SUCCESS(status)) { + TraceInformation("%!FUNC! ReadFromRegistry has value: %d", value); if (value == 0) { status = STATUS_UNSUCCESSFUL; } @@ -651,6 +677,7 @@ Return Value: WdfRegistryClose(hKey); } + TraceInformation("%!FUNC! Exiting with %!STATUS!", status); return status; } @@ -679,11 +706,10 @@ Return Value: WDFKEY hKey = NULL; NTSTATUS status; UNICODE_STRING valueName; - size_t bufferSize; - PVOID reportDescriptor; PDEVICE_CONTEXT deviceContext; ULONG value; + TraceInformation("%!FUNC! Entry"); deviceContext = GetDeviceContext(Device); status = WdfDeviceOpenRegistryKey(Device, @@ -693,23 +719,28 @@ Return Value: &hKey); if (!NT_SUCCESS(status)) { - return status; + TraceError("%!FUNC! Failed to find driver registry key"); + return status; } RtlInitUnicodeString(&valueName, L"LedCount"); - status = RtlInitUnicodeString(hKey, &valueName, value); + status = WdfRegistryQueryULong(hKey, &valueName, &value); if (!NT_SUCCESS(status)) { + TraceError("%!FUNC! Failed to WdfRegistryQueryULong LedCount: %!STATUS!", status); WdfRegistryClose(hKey); return status; } + TraceInformation("%!FUNC! LedCount has value: %d", value); *LampCount = (UINT8) value; RtlInitUnicodeString(&valueName, L"LedArrangement"); - status = RtlInitUnicodeString(hKey, &valueName, value); + status = WdfRegistryQueryULong(hKey, &valueName, &value); if (!NT_SUCCESS(status)) { + TraceError("%!FUNC! Failed to WdfRegistryQueryULong LedArrangement: %!STATUS!", status); WdfRegistryClose(hKey); return status; } + TraceInformation("%!FUNC! LedArrangement has value: %d", value); *LedArrangement = (UINT8) value; WdfRegistryClose(hKey); diff --git a/FrameworkArgb/Device.h b/FrameworkArgb/Device.h index 79e6648..28d8aa2 100644 --- a/FrameworkArgb/Device.h +++ b/FrameworkArgb/Device.h @@ -48,7 +48,9 @@ typedef struct _DEVICE_CONTEXT HANDLE CrosEcHandle; UINT16 CurrentLampId; BOOLEAN AutonomousMode; - UINT8 LampCount; + UINT16 LampCount; + UINT32 Width; + UINT32 Height; Position LampPositions[MAX_LAMPARRAY_LAMP_COUNT]; HID_DESCRIPTOR HidDescriptor; PHID_REPORT_DESCRIPTOR ReportDescriptor; @@ -175,7 +177,7 @@ CheckRegistryForLedConfig( NTSTATUS ReadLedConfigFromRegistry( - _In_ WDFDEVICE Device + _In_ WDFDEVICE Device, _Out_ UINT8 *LampCount, _Out_ UINT8 *LedArrangement ); diff --git a/FrameworkArgb/LampArray.cpp b/FrameworkArgb/LampArray.cpp index 47e1330..2d92ce1 100644 --- a/FrameworkArgb/LampArray.cpp +++ b/FrameworkArgb/LampArray.cpp @@ -70,9 +70,9 @@ GetLampArrayAttributesReport( DeviceContext = DeviceContext; LampArrayAttributesReport report = { - LAMPARRAY_LAMP_COUNT, - LAMPARRAY_WIDTH, - LAMPARRAY_HEIGHT, + DeviceContext->LampCount, + DeviceContext->Width, + DeviceContext->Height, LAMPARRAY_DEPTH, LAMPARRAY_KIND, LAMPARRAY_UPDATE_INTERVAL @@ -112,7 +112,7 @@ GetLampAttributesResponseReport( }; RtlCopyMemory(ReportBuffer, &report, sizeof(LampAttributesResponseReport)); - DeviceContext->CurrentLampId = CurrentLampId + 1 >= LAMPARRAY_LAMP_COUNT ? CurrentLampId : CurrentLampId + 1; + DeviceContext->CurrentLampId = CurrentLampId + 1 >= DeviceContext->LampCount ? CurrentLampId : CurrentLampId + 1; return Size; diff --git a/README.md b/README.md index db27b9e..ff0889d 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,9 @@ By default the driver loads with an 8 LED configuration arranged in a circle of Framework Desktop. To customize the configuration, set/edit the following registry entries. -They are all under: `TBD` +They are all under: `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ROOT\HIDCLASS\0000\Device Parameters` + +This configuration must be done after the driver is installed, then you disable the device, set the registry entries and then re-enable the device. | Name | Type | Explanation | |------------------|-------|---------------------------------| @@ -56,6 +58,14 @@ LedArrangement can have the following values: - 2: Linear (e.g. LED strip) - 3: Square Matrix (works best with a square number of LEDs) +For example to control just 4 LEDs on the fan: + +``` +sudo reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ROOT\HIDCLASS\0000\Device Parameters" /v ReadFromRegistry /t REG_DWORD /d 1 +sudo reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ROOT\HIDCLASS\0000\Device Parameters" /v LedCount /t REG_DWORD /d 4 +sudo reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ROOT\HIDCLASS\0000\Device Parameters" /v LedArrangement /t REG_DWORD /d 0 +``` + ## Development ### Build From 4f903645ea46a7f80dea10926da93541fe970ab4 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Sun, 3 Aug 2025 00:47:47 +0800 Subject: [PATCH 6/7] add depth to multi circular Signed-off-by: Daniel Schaefer --- FrameworkArgb/Device.c | 12 +++++++++++- FrameworkArgb/Device.h | 7 ++++--- FrameworkArgb/LampArray.cpp | 2 +- README.md | 2 +- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/FrameworkArgb/Device.c b/FrameworkArgb/Device.c index b0302f3..0016adb 100644 --- a/FrameworkArgb/Device.c +++ b/FrameworkArgb/Device.c @@ -220,29 +220,38 @@ CalculateLampPositions( case 0: DeviceContext->Width = 80000; DeviceContext->Height = 80000; + DeviceContext->Depth = 2000 * (LampCount / 8); for (UINT8 i = 0; i <= LampCount / 8; i++) { // 8 LEDs in a circle // z is 0 for all LEDs, they're all in the same plane // Bottom LED DeviceContext->LampPositions[i+0].x = 40000; DeviceContext->LampPositions[i+0].y = 0; + DeviceContext->LampPositions[i+0].z = 2000 * i; DeviceContext->LampPositions[i+1].x = 60000; DeviceContext->LampPositions[i+1].y = 20000; + DeviceContext->LampPositions[i+1].z = 2000 * i; // Right LED DeviceContext->LampPositions[i+2].x = 80000; DeviceContext->LampPositions[i+2].y = 40000; + DeviceContext->LampPositions[i+2].z = 2000 * i; DeviceContext->LampPositions[i+3].x = 60000; DeviceContext->LampPositions[i+3].y = 60000; + DeviceContext->LampPositions[i+3].z = 2000 * i; // Top LED DeviceContext->LampPositions[i+4].x = 40000; DeviceContext->LampPositions[i+4].y = 80000; - DeviceContext->LampPositions[i+5].x = 20000; + DeviceContext->LampPositions[i+1].z = 2000 * i; + DeviceContext->LampPositions[i+4].x = 20000; DeviceContext->LampPositions[i+5].y = 60000; + DeviceContext->LampPositions[i+5].z = 2000 * i; // Left LED DeviceContext->LampPositions[i+6].x = 0; DeviceContext->LampPositions[i+6].y = 40000; + DeviceContext->LampPositions[i+6].z = 2000 * i; DeviceContext->LampPositions[i+7].x = 20000; DeviceContext->LampPositions[i+7].y = 20000; + DeviceContext->LampPositions[i+7].z = 2000 * i; } break; // LEDs arranged in a circle single layer, even distance from each other @@ -356,6 +365,7 @@ Return Value: deviceContext->LampCount = 0; deviceContext->Width = 0; deviceContext->Height = 0; + deviceContext->Depth = 2000; LedArrangement = 0; status = CheckRegistryForLedConfig(device); if (NT_SUCCESS(status)) { diff --git a/FrameworkArgb/Device.h b/FrameworkArgb/Device.h index 28d8aa2..346421c 100644 --- a/FrameworkArgb/Device.h +++ b/FrameworkArgb/Device.h @@ -29,9 +29,9 @@ EVT_WDF_DRIVER_DEVICE_ADD EvtDeviceAdd; EVT_WDF_TIMER EvtTimerFunc; #define MAX_LAMPARRAY_LAMP_COUNT 256 -#define LAMPARRAY_WIDTH 80000 // 80mm -#define LAMPARRAY_HEIGHT 80000 // 80mm -#define LAMPARRAY_DEPTH 20000 // 20mm +//#define LAMPARRAY_WIDTH 80000 // 80mm +//#define LAMPARRAY_HEIGHT 80000 // 80mm +//#define LAMPARRAY_DEPTH 20000 // 20mm #define LAMPARRAY_KIND 0x07 // LampArrayKindChassis #define LAMPARRAY_UPDATE_INTERVAL 100000 // 10ms @@ -51,6 +51,7 @@ typedef struct _DEVICE_CONTEXT UINT16 LampCount; UINT32 Width; UINT32 Height; + UINT32 Depth; Position LampPositions[MAX_LAMPARRAY_LAMP_COUNT]; HID_DESCRIPTOR HidDescriptor; PHID_REPORT_DESCRIPTOR ReportDescriptor; diff --git a/FrameworkArgb/LampArray.cpp b/FrameworkArgb/LampArray.cpp index 2d92ce1..f7295d0 100644 --- a/FrameworkArgb/LampArray.cpp +++ b/FrameworkArgb/LampArray.cpp @@ -73,7 +73,7 @@ GetLampArrayAttributesReport( DeviceContext->LampCount, DeviceContext->Width, DeviceContext->Height, - LAMPARRAY_DEPTH, + DeviceContext->Depth, LAMPARRAY_KIND, LAMPARRAY_UPDATE_INTERVAL }; diff --git a/README.md b/README.md index ff0889d..6d903c1 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ For example to control just 4 LEDs on the fan: ``` sudo reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ROOT\HIDCLASS\0000\Device Parameters" /v ReadFromRegistry /t REG_DWORD /d 1 -sudo reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ROOT\HIDCLASS\0000\Device Parameters" /v LedCount /t REG_DWORD /d 4 +sudo reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ROOT\HIDCLASS\0000\Device Parameters" /v LedCount /t REG_DWORD /d 8 sudo reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ROOT\HIDCLASS\0000\Device Parameters" /v LedArrangement /t REG_DWORD /d 0 ``` From 557cedc9da4e353b61eb517a27686b921420c6df Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Sun, 3 Aug 2025 11:48:38 +0800 Subject: [PATCH 7/7] Match on APCI/FRMW0006 Once included in the BIOS. Not included in BIOS 3.02 yet. Signed-off-by: Daniel Schaefer --- FrameworkArgb/FrameworkArgb.inf | 4 ++-- README.md | 6 +----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/FrameworkArgb/FrameworkArgb.inf b/FrameworkArgb/FrameworkArgb.inf index 5299b3c..9222faf 100644 --- a/FrameworkArgb/FrameworkArgb.inf +++ b/FrameworkArgb/FrameworkArgb.inf @@ -10,7 +10,7 @@ ; INF file for installing HID minidriver (UMDF 2 version) ; ; Installation Notes: -; Using Devcon: Type "devcon install FrameworkArgb.inf root\FrameworkArgb" to install +; Using pnputil: Type "sudo pnputil /add-driver FrameworkArgb.inf /install" to install ; ; Important: ; This INF depends on MsHidUmdf.inf, which was introduced in build 22000 @@ -40,7 +40,7 @@ FrameworkArgb.dll = 1 %ManufacturerName% = Standard,NT$ARCH$.10.0...22000 ; wudfrd.inf introduced in build 22000 [Standard.NT$ARCH$.10.0...22000] -%DeviceName% = FrameworkArgb, Root\FrameworkArgb ; TODO: edit hw-id +%DeviceName% = FrameworkArgb, ACPI\FRMW0006 ; =================== UMDF Device ================================== diff --git a/README.md b/README.md index 6d903c1..57830bf 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ By default the driver loads with an 8 LED configuration arranged in a circle of Framework Desktop. To customize the configuration, set/edit the following registry entries. -They are all under: `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ROOT\HIDCLASS\0000\Device Parameters` +They are all under: `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ACPI\FRMW0006\?\Device Parameters` This configuration must be done after the driver is installed, then you disable the device, set the registry entries and then re-enable the device. @@ -79,10 +79,6 @@ Use Visual Studio 2022 Community Edition and build the project. ### Install ``` -# Software device right now -cp "C:\Program Files (x86)\Windows Kits\10\Tools\10.0.26100.0\x64\devcon.exe" . -sudo .\devcon install .\FrameworkArgb\x64\Debug\FrameworkArgb\FrameworkArgb.inf root\FrameworkArgb - # Soon with ACPI device in updated BIOS sudo pnputil /add-driver .\FrameworkArgb\x64\Debug\FrameworkArgb\FrameworkArgb.inf /install ```