@@ -44,16 +44,19 @@ static bool IsKnownPID(USHORT pid)
4444// --- Steering Wheel SDK function pointers ---
4545
4646typedef bool (__cdecl *LogiSteeringInit_t)(bool );
47+ typedef bool (__cdecl *LogiSteeringInitWithWindow_t)(bool , HWND);
4748typedef bool (__cdecl *LogiUpdate_t)();
4849typedef bool (__cdecl *LogiIsConnected_t)(int );
4950typedef bool (__cdecl *LogiPlayLeds_t)(int , float , float , float );
5051typedef 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