Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
253 changes: 231 additions & 22 deletions FrameworkArgb/Device.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ Module Name:
#include "driver.h"
#include "EcCommunication.h"
#include "device.tmh"
#define _USE_MATH_DEFINES
#include <math.h>

//
// This is the default report descriptor for the virtual Hid device returned
Expand Down Expand Up @@ -200,6 +202,81 @@ HID_DESCRIPTOR G_DefaultHidDescriptor = {
}
};

NTSTATUS
CalculateLampPositions(
PDEVICE_CONTEXT DeviceContext,
UINT16 LampCount,
UINT8 LedArrangement
)
{
UINT8 Layers = 0;
double centerX = 40000.0;
double centerY = 40000.0;
double radius = 40000.0;

TraceInformation("%!FUNC! LampCount: %d, LedArrangement: %d", LampCount, LedArrangement);

if (LampCount == 0) {
TraceError("LampCount is 0");
return STATUS_INVALID_PARAMETER;
}
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:
DeviceContext->Width = 80000;
DeviceContext->Height = 80000;
DeviceContext->Depth = 2000 * (LampCount / 8);
// Place LampCount LEDs evenly spaced around a circle of radius 40000 (centered at 40000,40000) in layers of 8
for (UINT8 i = 0; i < LampCount; i++) {
double angle = (2.0 * M_PI * (i % 8)) / 8;
DeviceContext->LampPositions[i].x = (UINT32)(centerX + radius * cos(angle));
DeviceContext->LampPositions[i].y = (UINT32)(centerY + radius * sin(angle));
DeviceContext->LampPositions[i].z = 2000 * i;
}
break;
// LEDs arranged in a circle single layer, even distance from each other
case 1:
DeviceContext->Width = 80000;
DeviceContext->Height = 80000;
// Place LampCount LEDs evenly spaced around a circle of radius 40000 (centered at 40000,40000)
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; i++) {
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++) {
DeviceContext->LampPositions[i].x = (i % Layers) * 5000;
DeviceContext->LampPositions[i].y = (i / Layers) * 5000;
}
break;
default:
TraceError("LedArrangement %d invalid.", LedArrangement);
return STATUS_INVALID_PARAMETER;
}

return STATUS_SUCCESS;
}

NTSTATUS
FrameworkArgbCreateDevice(
_Inout_ PWDFDEVICE_INIT DeviceInit
Expand Down Expand Up @@ -227,6 +304,7 @@ Return Value:
PHID_DEVICE_ATTRIBUTES hidAttributes;
WDFDEVICE device;
NTSTATUS status;
UINT8 LedArrangement;

TraceInformation("%!FUNC! Entry");

Expand Down Expand Up @@ -261,28 +339,35 @@ Return Value:
deviceContext->Device = device;
deviceContext->CurrentLampId = 0;
deviceContext->AutonomousMode = TRUE;
// 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;

deviceContext->LampCount = 0;
deviceContext->Width = 0;
deviceContext->Height = 0;
deviceContext->Depth = 2000;
LedArrangement = 0;
status = CheckRegistryForLedConfig(device);
if (NT_SUCCESS(status)) {
//
// We need to read read descriptor from registry
//
status = ReadLedConfigFromRegistry(device, &deviceContext->LampCount, &LedArrangement);
if (!NT_SUCCESS(status)) {
TraceError("Failed to read LED config from registry\n");
}
}

// Default 8 LED fan
if (deviceContext->LampCount == 0) {
TraceError("No lamps set, falling back to default");
deviceContext->LampCount = 8;
LedArrangement = 0;
}

status = CalculateLampPositions(deviceContext, deviceContext->LampCount, LedArrangement);
if (!NT_SUCCESS(status)) {
TraceError("Failed to calulcate lamp positions\n");
deviceContext->LampCount = 0;
}

hidAttributes = &deviceContext->HidDeviceAttributes;
RtlZeroMemory(hidAttributes, sizeof(HID_DEVICE_ATTRIBUTES));
Expand Down Expand Up @@ -526,3 +611,127 @@ Return Value:
status = RequestCopyFromBuffer(Request, string, stringSizeCb);
return status;
}

NTSTATUS
CheckRegistryForLedConfig(
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;

TraceInformation("%!FUNC! Entry");
//
// If this fails, AppVerifier shows an error
// RegOpenKeyExW: Key (\REGISTRY\MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WUDF\Services\WUDFx02000) is denied &apos;READ_CONTROL KEY_QUERY_VALUE KEY_ENUMERATE_SUB_KEYS KEY_NOTIFY&apos; access with error 0x2
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,
&valueName,
&value);

if (NT_SUCCESS(status)) {
TraceInformation("%!FUNC! ReadFromRegistry has value: %d", value);
if (value == 0) {
status = STATUS_UNSUCCESSFUL;
}
}

WdfRegistryClose(hKey);
}

TraceInformation("%!FUNC! Exiting with %!STATUS!", status);
return status;
}

NTSTATUS
ReadLedConfigFromRegistry(
WDFDEVICE Device,
UINT16 *LampCount,
UINT8 *LedArrangement
)
/*++

Routine Description:

Read LED config report descriptor from registry

Arguments:

device - pointer to a device object.

Return Value:

NT status code.

--*/
{
WDFKEY hKey = NULL;
NTSTATUS status;
UNICODE_STRING valueName;
PDEVICE_CONTEXT deviceContext;
ULONG value;

TraceInformation("%!FUNC! Entry");
deviceContext = GetDeviceContext(Device);

status = WdfDeviceOpenRegistryKey(Device,
PLUGPLAY_REGKEY_DEVICE,
KEY_READ,
WDF_NO_OBJECT_ATTRIBUTES,
&hKey);

if (!NT_SUCCESS(status)) {
TraceError("%!FUNC! Failed to find driver registry key");
return status;
}

RtlInitUnicodeString(&valueName, L"LedCount");
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 = 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);

return status;
}
36 changes: 20 additions & 16 deletions FrameworkArgb/Device.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ DRIVER_INITIALIZE DriverEntry;
EVT_WDF_DRIVER_DEVICE_ADD EvtDeviceAdd;
EVT_WDF_TIMER EvtTimerFunc;

#define LAMPARRAY_LAMP_COUNT 8
#define LAMPARRAY_WIDTH 80000 // 80mm
#define LAMPARRAY_HEIGHT 80000 // 80mm
#define LAMPARRAY_DEPTH 20000 // 20mm
#define MAX_LAMPARRAY_LAMP_COUNT 256
//#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

Expand All @@ -48,10 +48,13 @@ typedef struct _DEVICE_CONTEXT
HANDLE CrosEcHandle;
UINT16 CurrentLampId;
BOOLEAN AutonomousMode;
Position LampPositions[LAMPARRAY_LAMP_COUNT];
UINT16 LampCount;
UINT32 Width;
UINT32 Height;
UINT32 Depth;
Position LampPositions[MAX_LAMPARRAY_LAMP_COUNT];
HID_DESCRIPTOR HidDescriptor;
PHID_REPORT_DESCRIPTOR ReportDescriptor;
BOOLEAN ReadReportDescFromRegistry;
} DEVICE_CONTEXT, * PDEVICE_CONTEXT;

//
Expand Down Expand Up @@ -168,6 +171,17 @@ RequestGetHidXferPacket_ToWriteToDevice(
_Out_ HID_XFER_PACKET* Packet
);

NTSTATUS
CheckRegistryForLedConfig(
_In_ WDFDEVICE Device
);

NTSTATUS
ReadLedConfigFromRegistry(
_In_ WDFDEVICE Device,
_Out_ UINT16 *LampCount,
_Out_ UINT8 *LedArrangement
);

//
// Misc definitions
Expand All @@ -182,16 +196,6 @@ RequestGetHidXferPacket_ToWriteToDevice(
#define FWK_ARGB_HID_PID 0x0033
#define FWK_ARGB_HID_VERSION 0x0100

//
// Custom control codes are defined here. They are to be used for sideband
// communication with the hid minidriver. These control codes are sent to
// the hid minidriver using Hid_SetFeature() API to a custom collection
// defined especially to handle such requests.
//
#define FWK_ARGB_CONTROL_CODE_SET_ATTRIBUTES 0x00
#define FWK_ARGB_CONTROL_CODE_DUMMY1 0x01
#define FWK_ARGB_CONTROL_CODE_DUMMY2 0x02

#define LAMP_ARRAY_ATTRIBUTES_REPORT_ID 0x01
#define LAMP_ATTRIBUTES_REQUEST_REPORT_ID 0x02
#define LAMP_ATTRIBUTES_RESPONSE_REPORT_ID 0x03
Expand Down
4 changes: 4 additions & 0 deletions FrameworkArgb/Driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ Return Value:
#endif

TraceInformation("%!FUNC! Entry");
// TODO: Print Registry path

//
// Register a cleanup callback so that we can call WPP_CLEANUP when
Expand All @@ -74,6 +75,9 @@ Return Value:
FrameworkArgbEvtDeviceAdd
);

// AppVerifier shows the following errors
// Could not convert Key security descriptor &apos;\REGISTRY\MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WUDF\Services\FrameworkArgb&apos; to text due to error 0x8
// RegOpenKeyExW: Key (\REGISTRY\MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WUDF\Services\FrameworkArgb\Parameters\Wdf) is denied &apos;READ_CONTROL KEY_QUERY_VALUE KEY_ENUMERATE_SUB_KEYS KEY_NOTIFY&apos; access with error 0x2
status = WdfDriverCreate(DriverObject,
RegistryPath,
&attributes,
Expand Down
2 changes: 1 addition & 1 deletion FrameworkArgb/FrameworkArgb.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
</DriverSign>
<Inf>
<TimeStamp>0.0.0.1</TimeStamp>
<TimeStamp>0.0.0.2</TimeStamp>
</Inf>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
Expand Down
Loading