Skip to content

Commit 2b6a87d

Browse files
committed
fix: defer steering wheel SDK init until game window exists
LogiSteeringInitialize fails during DLL_PROCESS_ATTACH because the game window doesn't exist yet. Now tries multiple approaches: 1. InitWithWindow + GetDesktopWindow 2. InitWithWindow + GetForegroundWindow 3. Simple init (no window) 4. Deferred init on first SetLEDs call (game window guaranteed)
1 parent 9617965 commit 2b6a87d

File tree

1 file changed

+115
-57
lines changed

1 file changed

+115
-57
lines changed

Common Files/LogitechLED.cpp

Lines changed: 115 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,19 @@ static bool IsKnownPID(USHORT pid)
4444
// --- Steering Wheel SDK function pointers ---
4545

4646
typedef bool (__cdecl *LogiSteeringInit_t)(bool);
47+
typedef bool (__cdecl *LogiSteeringInitWithWindow_t)(bool, HWND);
4748
typedef bool (__cdecl *LogiUpdate_t)();
4849
typedef bool (__cdecl *LogiIsConnected_t)(int);
4950
typedef bool (__cdecl *LogiPlayLeds_t)(int, float, float, float);
5051
typedef void (__cdecl *LogiSteeringShutdown_t)();
5152

52-
static LogiSteeringInit_t g_SteeringInit = NULL;
53-
static LogiUpdate_t g_SteeringUpdate = NULL;
54-
static LogiIsConnected_t g_IsConnected = NULL;
55-
static LogiPlayLeds_t g_PlayLeds = NULL;
56-
static LogiSteeringShutdown_t g_SteeringShutdown = NULL;
53+
static LogiSteeringInit_t g_SteeringInit = NULL;
54+
static LogiSteeringInitWithWindow_t g_SteeringInitWithWindow = NULL;
55+
static LogiUpdate_t g_SteeringUpdate = NULL;
56+
static LogiIsConnected_t g_IsConnected = NULL;
57+
static LogiPlayLeds_t g_PlayLeds = NULL;
58+
static LogiSteeringShutdown_t g_SteeringShutdown = NULL;
59+
static bool g_SteeringNeedsLateInit = false;
5760

5861
// --- G Hub LED SDK function pointers ---
5962

@@ -125,10 +128,12 @@ void LogitechLED::Close()
125128
m_available = false;
126129
m_method = METHOD_NONE;
127130
g_SteeringInit = NULL;
131+
g_SteeringInitWithWindow = NULL;
128132
g_SteeringUpdate = NULL;
129133
g_IsConnected = NULL;
130134
g_PlayLeds = NULL;
131135
g_SteeringShutdown = NULL;
136+
g_SteeringNeedsLateInit = false;
132137
g_LedInit = NULL;
133138
g_LedSetLighting = NULL;
134139
g_LedShutdown = NULL;
@@ -200,81 +205,103 @@ bool LogitechLED::TrySteeringSDK()
200205
for (int i = 0; shutNames[i] && !g_SteeringShutdown; i++)
201206
g_SteeringShutdown = (LogiSteeringShutdown_t)GetProcAddress(m_steeringDll, shutNames[i]);
202207

208+
// Also try InitWithWindow variant
209+
g_SteeringInitWithWindow = (LogiSteeringInitWithWindow_t)
210+
GetProcAddress(m_steeringDll, "LogiSteeringInitializeWithWindow");
211+
203212
Log(" LogiSteeringInitialize: %s", g_SteeringInit ? "FOUND" : "NOT FOUND");
213+
Log(" LogiSteeringInitializeWithWindow: %s", g_SteeringInitWithWindow ? "FOUND" : "NOT FOUND");
204214
Log(" LogiUpdate: %s", g_SteeringUpdate ? "FOUND" : "NOT FOUND");
205215
Log(" LogiIsConnected: %s", g_IsConnected ? "FOUND" : "NOT FOUND");
206216
Log(" LogiPlayLeds: %s", g_PlayLeds ? "FOUND" : "NOT FOUND");
207217
Log(" LogiSteeringShutdown: %s", g_SteeringShutdown ? "FOUND" : "NOT FOUND");
208218

209-
if (!g_SteeringInit || !g_SteeringUpdate || !g_IsConnected || !g_PlayLeds)
219+
if (!g_SteeringUpdate || !g_IsConnected || !g_PlayLeds)
210220
{
211221
Log(" Required functions missing");
212222
FreeLibrary(m_steeringDll);
213223
m_steeringDll = NULL;
214224
return false;
215225
}
216226

217-
// Initialize - ignoreXInputControllers=false so we see Xbox wheels
218-
bool ok = g_SteeringInit(false);
219-
Log(" LogiSteeringInitialize(false) -> %s", ok ? "OK" : "FAIL");
220-
221-
if (!ok)
227+
if (!g_SteeringInit && !g_SteeringInitWithWindow)
222228
{
223-
Log(" Init failed. Is G Hub running?");
229+
Log(" No init function found");
224230
FreeLibrary(m_steeringDll);
225231
m_steeringDll = NULL;
226232
return false;
227233
}
228234

229-
// CRITICAL: Must call LogiUpdate() multiple times for G Hub to enumerate
230-
// devices. Without this, LogiIsConnected() always returns false.
231-
for (int retry = 0; retry < 10; retry++)
235+
// Try immediate init with multiple approaches
236+
bool ok = false;
237+
238+
// Attempt 1: InitWithWindow + GetDesktopWindow (always available)
239+
if (!ok && g_SteeringInitWithWindow)
232240
{
233-
Sleep(200);
234-
g_SteeringUpdate();
241+
HWND desktop = GetDesktopWindow();
242+
ok = g_SteeringInitWithWindow(false, desktop);
243+
Log(" InitWithWindow(false, desktop=0x%p) -> %s", desktop, ok ? "OK" : "FAIL");
244+
}
235245

236-
if (g_IsConnected(0))
246+
// Attempt 2: InitWithWindow + GetForegroundWindow
247+
if (!ok && g_SteeringInitWithWindow)
248+
{
249+
HWND fg = GetForegroundWindow();
250+
if (fg)
237251
{
238-
Log(" Wheel connected at index 0 (after %d updates)", retry + 1);
239-
break;
252+
ok = g_SteeringInitWithWindow(false, fg);
253+
Log(" InitWithWindow(false, foreground=0x%p) -> %s", fg, ok ? "OK" : "FAIL");
240254
}
241255
}
242256

243-
bool connected = g_IsConnected(0);
244-
Log(" LogiIsConnected(0) -> %s", connected ? "YES" : "NO");
245-
246-
if (!connected)
257+
// Attempt 3: Simple init (no window)
258+
if (!ok && g_SteeringInit)
247259
{
248-
// Try index 1
249-
connected = g_IsConnected(1);
250-
Log(" LogiIsConnected(1) -> %s", connected ? "YES" : "NO");
260+
ok = g_SteeringInit(false);
261+
Log(" LogiSteeringInitialize(false) -> %s", ok ? "OK" : "FAIL");
251262
}
252263

253-
if (!connected)
264+
if (ok)
254265
{
255-
Log(" No wheel detected by SDK. Trying LogiPlayLeds anyway...");
256-
}
266+
// Init succeeded now - enumerate and test
267+
Log(" Init succeeded, enumerating...");
257268

258-
// Test LEDs - all on (redline)
259-
g_SteeringUpdate();
260-
bool led = g_PlayLeds(0, 100.0f, 0.0f, 100.0f);
261-
Log(" LogiPlayLeds(0, 100, 0, 100) -> %s *** ALL LEDs ON ***", led ? "OK" : "FAIL");
262-
Sleep(1000);
269+
for (int retry = 0; retry < 10; retry++)
270+
{
271+
Sleep(200);
272+
g_SteeringUpdate();
273+
if (g_IsConnected(0))
274+
{
275+
Log(" Wheel connected at index 0 (after %d updates)", retry + 1);
276+
break;
277+
}
278+
}
279+
280+
bool connected = g_IsConnected(0);
281+
Log(" LogiIsConnected(0) -> %s", connected ? "YES" : "NO");
282+
283+
// Test LEDs
284+
g_SteeringUpdate();
285+
bool led = g_PlayLeds(0, 100.0f, 0.0f, 100.0f);
286+
Log(" LogiPlayLeds(0, 100, 0, 100) -> %s *** ALL LEDs ***", led ? "OK" : "FAIL");
287+
Sleep(1000);
263288

264-
// Test LEDs - half
265-
g_SteeringUpdate();
266-
led = g_PlayLeds(0, 50.0f, 0.0f, 100.0f);
267-
Log(" LogiPlayLeds(0, 50, 0, 100) -> %s *** HALF LEDs ***", led ? "OK" : "FAIL");
268-
Sleep(1000);
289+
g_SteeringUpdate();
290+
g_PlayLeds(0, 0.0f, 0.0f, 100.0f);
269291

270-
// Test LEDs - off
271-
g_SteeringUpdate();
272-
led = g_PlayLeds(0, 0.0f, 0.0f, 100.0f);
273-
Log(" LogiPlayLeds(0, 0, 0, 100) -> %s *** LEDs OFF ***", led ? "OK" : "FAIL");
292+
m_method = METHOD_STEERING_SDK;
293+
m_available = true;
294+
Log("=== LED CONTROL ACTIVE (Steering Wheel SDK) ===");
295+
return true;
296+
}
274297

298+
// All immediate inits failed - defer to first SetLEDs call
299+
// (game window will exist by then)
300+
Log(" Immediate init failed - deferring to first SetLEDs call");
301+
g_SteeringNeedsLateInit = true;
275302
m_method = METHOD_STEERING_SDK;
276303
m_available = true;
277-
Log("=== LED CONTROL ACTIVE (Steering Wheel SDK) ===");
304+
Log("=== LED CONTROL PENDING (Steering Wheel SDK - deferred init) ===");
278305
return true;
279306
}
280307

@@ -695,21 +722,11 @@ bool LogitechLED::SetLEDs(BYTE ledMask)
695722

696723
if (m_method == METHOD_STEERING_SDK && g_PlayLeds && g_SteeringUpdate)
697724
{
698-
// Map 5-bit LED mask to RPM percentage for LogiPlayLeds
725+
// Delegate to SetLEDsFromPercent which handles deferred init
699726
int numLeds = 0;
700727
for (int i = 0; i < 5; i++)
701728
if (ledMask & (1 << i)) numLeds++;
702-
703-
float rpm = numLeds * 20.0f; // 0-100
704-
g_SteeringUpdate();
705-
bool ok = g_PlayLeds(0, rpm, 0.0f, 100.0f);
706-
707-
g_setLedsCallCount++;
708-
if (g_setLedsCallCount <= 20 || !ok)
709-
Log("SetLEDs(0x%02X) [SteeringSDK rpm=%.0f] -> %s (#%d)",
710-
ledMask, rpm, ok ? "OK" : "FAIL", g_setLedsCallCount);
711-
712-
return ok;
729+
return SetLEDsFromPercent(numLeds / 5.0);
713730
}
714731

715732
if (m_method == METHOD_SDK && g_LedSetLighting)
@@ -775,6 +792,47 @@ bool LogitechLED::SetLEDsFromPercent(double percent)
775792
// For steering SDK, pass percentage directly as RPM for smooth LED progression
776793
if (m_method == METHOD_STEERING_SDK && g_PlayLeds && g_SteeringUpdate)
777794
{
795+
// Deferred init: game window exists now
796+
if (g_SteeringNeedsLateInit)
797+
{
798+
g_SteeringNeedsLateInit = false;
799+
bool ok = false;
800+
801+
HWND fg = GetForegroundWindow();
802+
if (fg && g_SteeringInitWithWindow)
803+
{
804+
ok = g_SteeringInitWithWindow(false, fg);
805+
Log(" LATE InitWithWindow(false, hwnd=0x%p) -> %s", fg, ok ? "OK" : "FAIL");
806+
}
807+
if (!ok && g_SteeringInit)
808+
{
809+
ok = g_SteeringInit(false);
810+
Log(" LATE LogiSteeringInitialize(false) -> %s", ok ? "OK" : "FAIL");
811+
}
812+
813+
if (ok)
814+
{
815+
for (int retry = 0; retry < 10; retry++)
816+
{
817+
Sleep(200);
818+
g_SteeringUpdate();
819+
if (g_IsConnected(0))
820+
{
821+
Log(" LATE: Wheel connected (after %d updates)", retry + 1);
822+
break;
823+
}
824+
}
825+
Log(" LATE: LogiIsConnected(0) -> %s", g_IsConnected(0) ? "YES" : "NO");
826+
}
827+
else
828+
{
829+
Log(" LATE init also failed - steering SDK unavailable");
830+
m_method = METHOD_NONE;
831+
m_available = false;
832+
return false;
833+
}
834+
}
835+
778836
float rpm = (float)(percent * 100.0);
779837
g_SteeringUpdate();
780838
bool ok = g_PlayLeds(0, rpm, 0.0f, 100.0f);

0 commit comments

Comments
 (0)