Skip to content

Commit bcd2890

Browse files
committed
fix: exhaustive LED SDK export scan + simplified init flow
- Enumerate ALL DLL exports (PE export table walk) to find undocumented steering wheel functions in the newer G Hub LED SDK v75.71.76 - Scan device types 0x01-0x200 + ordinals 0-5 with zones 0-9 for SetLightingForTargetZone (120+ combinations) - LED SDK no longer activates (confirmed keyboard/mouse only) - Legacy HID tried on ALL collections (not just UP=0xFF43) - Log suggests taskkill lghub_agent.exe as workaround
1 parent 2b6a87d commit bcd2890

File tree

1 file changed

+62
-102
lines changed

1 file changed

+62
-102
lines changed

Common Files/LogitechLED.cpp

Lines changed: 62 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -326,128 +326,104 @@ bool LogitechLED::TrySDK()
326326

327327
Log(" Loaded: %s", dllPath);
328328

329-
// Enumerate exported functions
330-
const char* probeNames[] = {
331-
"LogiLedInit", "LogiLedInitWithName",
332-
"LogiLedSetTargetDevice", "LogiLedSetLighting",
333-
"LogiLedSaveCurrentLighting", "LogiLedRestoreLighting",
334-
"LogiLedShutdown", "LogiLedGetSdkVersion",
335-
"LogiLedSetLightingForKeyWithKeyName",
336-
"LogiLedSetLightingForKeyWithScanCode",
337-
"LogiLedSetLightingForKeyWithHidCode",
338-
"LogiLedSetLightingForTargetZone",
339-
"LogiLedGetConfigOptionNumber",
340-
// Steering wheel SDK functions (maybe bundled?)
341-
"LogiSteeringInitialize", "LogiPlayLeds",
342-
"LogiIsConnected", "LogiUpdate",
343-
NULL
344-
};
345-
346-
Log(" Exported functions:");
347-
for (int i = 0; probeNames[i]; i++)
329+
// Enumerate ALL exports from the DLL using PE export table
330+
Log(" --- ALL DLL EXPORTS ---");
331+
BYTE* base = (BYTE*)m_sdkDll;
332+
IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)base;
333+
if (dos->e_magic == IMAGE_DOS_SIGNATURE)
348334
{
349-
FARPROC p = GetProcAddress(m_sdkDll, probeNames[i]);
350-
if (p) Log(" %s: FOUND", probeNames[i]);
335+
IMAGE_NT_HEADERS* nt = (IMAGE_NT_HEADERS*)(base + dos->e_lfanew);
336+
if (nt->Signature == IMAGE_NT_SIGNATURE)
337+
{
338+
DWORD expRVA = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
339+
if (expRVA)
340+
{
341+
IMAGE_EXPORT_DIRECTORY* exp = (IMAGE_EXPORT_DIRECTORY*)(base + expRVA);
342+
DWORD* names = (DWORD*)(base + exp->AddressOfNames);
343+
for (DWORD i = 0; i < exp->NumberOfNames; i++)
344+
Log(" [%02lu] %s", i, (char*)(base + names[i]));
345+
}
346+
}
351347
}
348+
Log(" --- END EXPORTS ---");
352349

353-
// Get function pointers
354350
g_LedInit = (LogiLedInit_t)GetProcAddress(m_sdkDll, "LogiLedInit");
355-
g_LedInitWithName = (LogiLedInitWithName_t)GetProcAddress(m_sdkDll, "LogiLedInitWithName");
356351
g_LedSetTarget = (LogiLedSetTargetDevice_t)GetProcAddress(m_sdkDll, "LogiLedSetTargetDevice");
357352
g_LedSetLighting = (LogiLedSetLighting_t)GetProcAddress(m_sdkDll, "LogiLedSetLighting");
358353
g_LedShutdown = (LogiLedShutdown_t)GetProcAddress(m_sdkDll, "LogiLedShutdown");
359354
g_LedGetVersion = (LogiLedGetSdkVersion_t)GetProcAddress(m_sdkDll, "LogiLedGetSdkVersion");
360355

361-
// SDK version
362356
if (g_LedGetVersion)
363357
{
364358
int major = 0, minor = 0, build = 0;
365359
if (g_LedGetVersion(&major, &minor, &build))
366360
Log(" SDK version: %d.%d.%d", major, minor, build);
367361
}
368362

369-
// Init
370363
if (!g_LedInit)
371364
{
372-
Log(" LogiLedInit not found");
373365
FreeLibrary(m_sdkDll);
374366
m_sdkDll = NULL;
375367
return false;
376368
}
377369

378370
bool ok = g_LedInit();
379371
Log(" LogiLedInit() -> %s", ok ? "OK" : "FAIL");
380-
381372
if (!ok)
382373
{
383-
Log(" Is G Hub running?");
384374
FreeLibrary(m_sdkDll);
385375
m_sdkDll = NULL;
386376
return false;
387377
}
388378

389-
// Give G Hub a moment to enumerate devices
390379
Sleep(500);
391380

392-
// Try setting lighting on all device types
393-
if (g_LedSetTarget)
394-
{
395-
// LOGI_DEVICETYPE_MONOCHROME=1, RGB=2, PERKEY_RGB=4, ALL=7
396-
g_LedSetTarget(0x07); // target ALL devices
397-
Log(" SetTargetDevice(ALL)");
398-
}
399-
400-
if (g_LedSetLighting)
381+
// Exhaustive scan: try many device type + zone combinations
382+
FARPROC pZone = GetProcAddress(m_sdkDll, "LogiLedSetLightingForTargetZone");
383+
if (pZone && g_LedSetTarget)
401384
{
402-
// Try full brightness
403-
bool led = g_LedSetLighting(100, 100, 100);
404-
Log(" SetLighting(100,100,100) -> %s *** LOOK AT WHEEL ***", led ? "OK" : "FAIL");
385+
typedef bool (*SetZone_t)(int, int, int, int, int);
386+
SetZone_t setZone = (SetZone_t)pZone;
405387

406-
Sleep(1000);
407-
408-
// Try just green (RPM LEDs are green at low RPM)
409-
led = g_LedSetLighting(0, 100, 0);
410-
Log(" SetLighting(0,100,0) -> %s", led ? "OK" : "FAIL");
411-
412-
Sleep(1000);
413-
414-
// Try red (RPM LEDs are red at high RPM)
415-
led = g_LedSetLighting(100, 0, 0);
416-
Log(" SetLighting(100,0,0) -> %s", led ? "OK" : "FAIL");
388+
// Try device types: known bitmasks + higher values + 0xFF
389+
int deviceTypes[] = { 0x01, 0x02, 0x04, 0x07, 0x08, 0x10, 0x20,
390+
0x40, 0x80, 0xFF, 0x0100, 0x0200, -1 };
417391

418-
Sleep(1000);
419-
420-
// Try monochrome target specifically
421-
if (g_LedSetTarget)
392+
for (int di = 0; deviceTypes[di] != -1; di++)
422393
{
423-
g_LedSetTarget(0x01); // MONOCHROME only
424-
led = g_LedSetLighting(100, 100, 100);
425-
Log(" SetTargetDevice(MONO) + SetLighting(100,100,100) -> %s", led ? "OK" : "FAIL");
426-
Sleep(1000);
394+
g_LedSetTarget(deviceTypes[di]);
395+
for (int zone = 0; zone < 10; zone++)
396+
{
397+
bool zok = setZone(deviceTypes[di], zone, 100, 100, 100);
398+
if (zok)
399+
{
400+
Log(" *** HIT *** SetZone(devType=0x%X, zone=%d) -> OK", deviceTypes[di], zone);
401+
Sleep(500);
402+
}
403+
}
427404
}
428405

429-
// Check if there's a zone-based function
430-
FARPROC pZone = GetProcAddress(m_sdkDll, "LogiLedSetLightingForTargetZone");
431-
if (pZone)
406+
// Also try SetZone with ordinal device types (0, 1, 2, 3, 4, 5)
407+
for (int dt = 0; dt <= 5; dt++)
432408
{
433-
typedef bool (*SetZone_t)(int, int, int, int, int);
434-
SetZone_t setZone = (SetZone_t)pZone;
435-
436-
// deviceType=ALL, zone=0..4, R=100, G=100, B=100
437-
for (int zone = 0; zone < 6; zone++)
409+
for (int zone = 0; zone < 10; zone++)
438410
{
439-
bool zled = setZone(0x07, zone, 100, 100, 100);
440-
Log(" SetLightingForTargetZone(ALL,%d,100,100,100) -> %s", zone, zled ? "OK" : "FAIL");
441-
Sleep(500);
411+
bool zok = setZone(dt, zone, 100, 100, 100);
412+
if (zok)
413+
Log(" *** HIT *** SetZone(ordinal=%d, zone=%d) -> OK", dt, zone);
442414
}
443415
}
444416
}
445417

446-
Log(" SDK init complete - check if any LEDs responded");
447-
448-
m_method = METHOD_SDK;
449-
m_available = true;
450-
return true;
418+
// Don't activate LED SDK - it doesn't control wheel LEDs
419+
Log(" LED SDK scan complete (keyboard/mouse only)");
420+
if (g_LedShutdown) g_LedShutdown();
421+
FreeLibrary(m_sdkDll);
422+
m_sdkDll = NULL;
423+
g_LedInit = NULL;
424+
g_LedSetLighting = NULL;
425+
g_LedShutdown = NULL;
426+
return false;
451427
}
452428

453429
// --- I/O helpers ---
@@ -647,55 +623,37 @@ bool LogitechLED::TryLegacy(HANDLE h, USHORT outLen)
647623

648624
bool LogitechLED::Init()
649625
{
650-
Log("=== LogitechLED Init v5 ===");
626+
Log("=== LogitechLED Init v6 ===");
651627
Log("");
652628

653629
if (m_available) return true;
654630

655-
// Phase 0: Steering Wheel SDK (LogiPlayLeds - standard for racing games)
631+
// Phase 0: Steering Wheel SDK (LogiPlayLeds)
656632
if (TrySteeringSDK())
657633
return true;
658634

659-
// Phase 1: G Hub LED SDK (keyboard/mouse - fallback)
635+
// Phase 1: G Hub LED SDK (diagnostic - enumerate exports, scan zones)
660636
Log("");
661-
if (TrySDK())
662-
return true;
637+
TrySDK(); // always returns false now, just diagnostic
663638

664-
// Phase 2: HID++ enumeration (diagnostic only - kernel drivers block)
639+
// Phase 2: HID enumeration + Legacy attempt
665640
Log("");
666-
Log("=== Phase 2: HID++ enumeration ===");
641+
Log("=== Phase 2: HID collections ===");
667642

668643
HIDCandidate candidates[MAX_CANDIDATES];
669644
int numCandidates = 0;
670645
EnumerateCandidates(candidates, &numCandidates);
671646
Log(" %d writable collections", numCandidates);
672647

673-
for (int ci = 0; ci < numCandidates; ci++)
674-
{
675-
if (candidates[ci].usagePage != 0xFF43) continue;
676-
if (candidates[ci].inputReportLen == 0) continue;
677-
if (candidates[ci].outputReportLen < 64) continue;
678-
679-
HANDLE h = CreateFileA(candidates[ci].path,
680-
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
681-
NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
682-
if (h == INVALID_HANDLE_VALUE) continue;
683-
684-
TryHIDPPDiscovery(h, candidates[ci].outputReportLen, candidates[ci].inputReportLen);
685-
CloseHandle(h);
686-
}
687-
688-
// Phase 3: Legacy fallback
689-
Log("");
690-
Log("=== Phase 3: Legacy ===");
691-
648+
// Try legacy on ALL writable collections (not just UP=0xFF43)
692649
for (int ci = 0; ci < numCandidates; ci++)
693650
{
694651
HANDLE h = CreateFileA(candidates[ci].path,
695652
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
696653
NULL, OPEN_EXISTING, 0, NULL);
697654
if (h == INVALID_HANDLE_VALUE) continue;
698655

656+
// Try legacy [F8 12] on every collection
699657
if (TryLegacy(h, candidates[ci].outputReportLen))
700658
{
701659
m_handle = h;
@@ -709,6 +667,8 @@ bool LogitechLED::Init()
709667

710668
Log("");
711669
Log("=== NO WORKING METHOD ===");
670+
Log("G Hub kernel drivers block HID LED commands.");
671+
Log("Try: taskkill /f /im lghub_agent.exe (then relaunch game)");
712672
return false;
713673
}
714674

0 commit comments

Comments
 (0)