@@ -104,6 +104,12 @@ static LogiLedShutdown_t g_LedShutdown = NULL;
104104static LogiLedGetSdkVersion_t g_LedGetVersion = NULL ;
105105static LogiLedSetZone_t g_LedSetZone = NULL ;
106106
107+ // Discovered LED SDK configuration (set during TrySDK scan)
108+ static int g_sdkDevType = 0x8 ; // Device type for zone API
109+ static int g_sdkMaxZone = 1 ; // Highest zone that returned OK
110+ static bool g_sdkUseGlobal = false ; // Use SetLighting instead of zones
111+ static int g_sdkGlobalTarget = 0x1 ; // Target for global SetLighting
112+
107113// --- LogitechLED ---
108114
109115LogitechLED::LogitechLED ()
@@ -612,7 +618,7 @@ bool LogitechLED::TrySteeringSDK()
612618
613619bool LogitechLED::TrySDK ()
614620{
615- Log (" === Phase 1: G Hub LED SDK ===" );
621+ Log (" === Phase 1: G Hub LED SDK (v13 - exhaustive scan) ===" );
616622
617623#ifdef _WIN64
618624 const char * dllPath = " C:\\ Program Files\\ LGHUB\\ sdks\\ sdk_legacy_led_x64.dll" ;
@@ -628,13 +634,19 @@ bool LogitechLED::TrySDK()
628634 }
629635
630636 Log (" Loaded: %s" , dllPath);
631- DumpExports (m_sdkDll, " LED SDK" );
632637
633- g_LedInit = (LogiLedInit_t)GetProcAddress (m_sdkDll, " LogiLedInit" );
634- g_LedSetTarget = (LogiLedSetTargetDevice_t)GetProcAddress (m_sdkDll, " LogiLedSetTargetDevice" );
638+ g_LedInit = (LogiLedInit_t)GetProcAddress (m_sdkDll, " LogiLedInit" );
639+ g_LedInitWithName = (LogiLedInitWithName_t)GetProcAddress (m_sdkDll, " LogiLedInitWithName" );
640+ g_LedSetTarget = (LogiLedSetTargetDevice_t)GetProcAddress (m_sdkDll, " LogiLedSetTargetDevice" );
635641 g_LedSetLighting = (LogiLedSetLighting_t)GetProcAddress (m_sdkDll, " LogiLedSetLighting" );
636- g_LedShutdown = (LogiLedShutdown_t)GetProcAddress (m_sdkDll, " LogiLedShutdown" );
637- g_LedGetVersion = (LogiLedGetSdkVersion_t)GetProcAddress (m_sdkDll, " LogiLedGetSdkVersion" );
642+ g_LedShutdown = (LogiLedShutdown_t)GetProcAddress (m_sdkDll, " LogiLedShutdown" );
643+ g_LedGetVersion = (LogiLedGetSdkVersion_t)GetProcAddress (m_sdkDll, " LogiLedGetSdkVersion" );
644+ g_LedSetZone = (LogiLedSetZone_t)GetProcAddress (m_sdkDll, " LogiLedSetLightingForTargetZone" );
645+
646+ Log (" Init=%s InitName=%s Target=%s Lighting=%s Zone=%s Shut=%s" ,
647+ g_LedInit ? " OK" : " -" , g_LedInitWithName ? " OK" : " -" ,
648+ g_LedSetTarget ? " OK" : " -" , g_LedSetLighting ? " OK" : " -" ,
649+ g_LedSetZone ? " OK" : " -" , g_LedShutdown ? " OK" : " -" );
638650
639651 if (g_LedGetVersion)
640652 {
@@ -643,63 +655,155 @@ bool LogitechLED::TrySDK()
643655 Log (" SDK version: %d.%d.%d" , major, minor, build);
644656 }
645657
646- if (!g_LedInit)
658+ if (!g_LedInit && !g_LedInitWithName )
647659 {
648660 FreeLibrary (m_sdkDll);
649661 m_sdkDll = NULL ;
650662 return false ;
651663 }
652664
653- bool ok = g_LedInit ();
654- Log (" LogiLedInit() -> %s" , ok ? " OK" : " FAIL" );
655- if (!ok)
665+ bool initOk = false ;
666+ if (g_LedInit)
667+ {
668+ initOk = g_LedInit ();
669+ Log (" LogiLedInit() -> %s" , initOk ? " OK" : " FAIL" );
670+ }
671+ if (!initOk && g_LedInitWithName)
672+ {
673+ initOk = g_LedInitWithName (" FFBArcadePlugin" );
674+ Log (" LogiLedInitWithName('FFBArcadePlugin') -> %s" , initOk ? " OK" : " FAIL" );
675+ }
676+
677+ if (!initOk)
656678 {
657679 FreeLibrary (m_sdkDll);
658680 m_sdkDll = NULL ;
659681 return false ;
660682 }
661683
662- Sleep (500 );
684+ Log (" Init OK, waiting 1s for G Hub registration..." );
685+ Sleep (1000 );
663686
664- g_LedSetZone = (LogiLedSetZone_t)GetProcAddress (m_sdkDll, " LogiLedSetLightingForTargetZone" );
687+ // ================================================================
688+ // SCAN A: Global LogiLedSetLighting with various target devices
689+ // ================================================================
690+ Log (" --- SCAN A: SetTargetDevice + SetLighting (green) ---" );
691+ if (g_LedSetTarget && g_LedSetLighting)
692+ {
693+ // Known device types: 0x1=mono, 0x2=RGB, 0x4=perkey, 0x7=all
694+ // Also try: 0x8=headset, 0x10, 0x20, 0x40, 0x80, 0xFF
695+ int targets[] = { 0x1 , 0x2 , 0x3 , 0x4 , 0x7 , 0x8 , 0xE , 0x10 , 0x20 , 0x40 , 0x80 , 0xFF };
696+ int numTargets = sizeof (targets) / sizeof (targets[0 ]);
665697
666- if (g_LedSetZone && g_LedSetTarget)
698+ for (int t = 0 ; t < numTargets; t++)
699+ {
700+ g_LedSetTarget (targets[t]);
701+ bool ok = g_LedSetLighting (0 , 100 , 0 ); // Bright green
702+ Log (" target=0x%02X SetLighting(0,100,0) -> %s" , targets[t], ok ? " OK" : " FAIL" );
703+ if (ok)
704+ {
705+ Log (" >>> VISUAL A: target=0x%02X - CHECK WHEEL LEDs! (500ms)" , targets[t]);
706+ Sleep (500 );
707+ g_LedSetLighting (0 , 0 , 0 ); // Turn off
708+ Sleep (200 );
709+ }
710+ }
711+ }
712+
713+ // ================================================================
714+ // SCAN B: LogiLedSetLightingForTargetZone - exhaustive
715+ // ================================================================
716+ if (g_LedSetZone)
667717 {
668- // Target device type 0x8 (responded OK in previous tests)
669- g_LedSetTarget (0x8 );
718+ Log (" --- SCAN B: SetLightingForTargetZone (exhaustive) ---" );
719+ // Device types to test (covers known + potential undocumented)
720+ // 0x0=keyboard, 0x3=mouse, 0x4=mousemat, 0x8=headset, 0xE=speaker
721+ int zoneTypes[] = {
722+ 0x00 , 0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 ,
723+ 0x08 , 0x09 , 0x0A , 0x0B , 0x0C , 0x0D , 0x0E , 0x0F ,
724+ 0x10 , 0x11 , 0x12 , 0x13 , 0x14
725+ };
726+ int numZoneTypes = sizeof (zoneTypes) / sizeof (zoneTypes[0 ]);
670727
671- // Test: light up zone 0 and 1 with bright green (RPM LED color)
672- bool z0 = g_LedSetZone (0x8 , 0 , 0 , 100 , 0 );
673- bool z1 = g_LedSetZone (0x8 , 1 , 0 , 100 , 0 );
674- Log (" devType=0x8 zone0(green) -> %s, zone1(green) -> %s" , z0 ? " OK" : " FAIL" , z1 ? " OK" : " FAIL" );
728+ // Pass 1: silent scan to collect OK results
729+ Log (" Pass 1: collecting OK results..." );
730+ struct ZoneResult { int devType; int maxZone; int okCount; };
731+ ZoneResult okResults[21 ];
732+ int numOkResults = 0 ;
675733
676- if (z0 || z1 )
734+ for ( int dt = 0 ; dt < numZoneTypes; dt++ )
677735 {
678- Log (" *** Activating LED SDK with devType=0x8 ***" );
679- Log (" Waiting 2s to check if LEDs are visible..." );
680- Sleep (2000 );
736+ int okCount = 0 ;
737+ int maxZone = -1 ;
681738
682- // Clear
683- g_LedSetZone (0x8 , 0 , 0 , 0 , 0 );
684- g_LedSetZone (0x8 , 1 , 0 , 0 , 0 );
739+ for (int zone = 0 ; zone <= 5 ; zone++)
740+ {
741+ bool ok = g_LedSetZone (zoneTypes[dt], zone, 0 , 100 , 0 );
742+ if (ok)
743+ {
744+ okCount++;
745+ maxZone = zone;
746+ }
747+ // Immediately turn off
748+ g_LedSetZone (zoneTypes[dt], zone, 0 , 0 , 0 );
749+ }
685750
686- m_method = METHOD_SDK;
687- m_available = true ;
688- Log (" === LED CONTROL ACTIVE (LED SDK devType=0x8) ===" );
689- return true ;
751+ if (okCount > 0 )
752+ {
753+ Log (" devType=0x%02X: %d zones OK (max zone=%d)" , zoneTypes[dt], okCount, maxZone);
754+ if (numOkResults < 21 )
755+ {
756+ okResults[numOkResults].devType = zoneTypes[dt];
757+ okResults[numOkResults].maxZone = maxZone;
758+ okResults[numOkResults].okCount = okCount;
759+ numOkResults++;
760+ }
761+ }
762+ }
763+
764+ Log (" %d device types returned OK" , numOkResults);
765+
766+ // Pass 2: visual test on each OK device type (light ALL zones, 800ms per type)
767+ if (numOkResults > 0 )
768+ {
769+ Log (" Pass 2: visual test (%d types, ~%ds)..." , numOkResults, numOkResults);
770+
771+ for (int r = 0 ; r < numOkResults; r++)
772+ {
773+ int dt = okResults[r].devType ;
774+ int mz = okResults[r].maxZone ;
775+
776+ // Light all zones bright green
777+ for (int z = 0 ; z <= mz; z++)
778+ g_LedSetZone (dt, z, 0 , 100 , 0 );
779+
780+ Log (" >>> VISUAL B-%d: devType=0x%02X zones 0-%d GREEN - CHECK WHEEL! (800ms)" ,
781+ r + 1 , dt, mz);
782+ Sleep (800 );
783+
784+ // Turn off
785+ for (int z = 0 ; z <= mz; z++)
786+ g_LedSetZone (dt, z, 0 , 0 , 0 );
787+ Sleep (200 );
788+ }
789+ }
790+
791+ // Use first OK result as default
792+ if (numOkResults > 0 )
793+ {
794+ g_sdkDevType = okResults[0 ].devType ;
795+ g_sdkMaxZone = okResults[0 ].maxZone ;
796+ g_sdkUseGlobal = false ;
797+ Log (" Selected: devType=0x%02X maxZone=%d" , g_sdkDevType, g_sdkMaxZone);
690798 }
691799 }
692800
693- // devType=0x8 didn't work, clean up
694- Log (" LED SDK: no usable zones found" );
695- if (g_LedShutdown) g_LedShutdown ();
696- FreeLibrary (m_sdkDll);
697- m_sdkDll = NULL ;
698- g_LedInit = NULL ;
699- g_LedSetLighting = NULL ;
700- g_LedShutdown = NULL ;
701- g_LedSetZone = NULL ;
702- return false ;
801+ // Accept METHOD_SDK if init was OK (user will check visual tests and log)
802+ m_method = METHOD_SDK;
803+ m_available = true ;
804+ Log (" === LED CONTROL ACTIVE (LED SDK v13 scan) ===" );
805+ Log (" === Check log above for VISUAL tests that lit the wheel ===" );
806+ return true ;
703807}
704808
705809// --- I/O helpers ---
@@ -899,7 +1003,7 @@ bool LogitechLED::TryLegacy(HANDLE h, USHORT outLen)
8991003
9001004bool LogitechLED::Init ()
9011005{
902- Log (" === LogitechLED Init v12b (direct engine + diag ) ===" );
1006+ Log (" === LogitechLED Init v13 (exhaustive LED SDK scan ) ===" );
9031007 Log (" " );
9041008
9051009 if (m_available) return true ;
@@ -966,34 +1070,57 @@ bool LogitechLED::SetLEDs(BYTE ledMask)
9661070 return SetLEDsFromPercent (numLeds / 5.0 );
9671071 }
9681072
969- if (m_method == METHOD_SDK && g_LedSetZone )
1073+ if (m_method == METHOD_SDK)
9701074 {
971- // Map 5-bit LED mask to devType=0x8 zones 0-1
972- // Zone 0 = lower LEDs (green), Zone 1 = upper LEDs (red)
9731075 int numLeds = 0 ;
9741076 for (int i = 0 ; i < 5 ; i++)
9751077 if (ledMask & (1 << i)) numLeds++;
9761078
977- // Zone 0: green intensity based on LED count (first 3 LEDs)
978- // Zone 1: red intensity for high RPM (last 2 LEDs)
979- int greenPct = 0 , redPct = 0 ;
980- if (numLeds >= 1 ) greenPct = 33 ;
981- if (numLeds >= 2 ) greenPct = 66 ;
982- if (numLeds >= 3 ) greenPct = 100 ;
983- if (numLeds >= 4 ) redPct = 50 ;
984- if (numLeds >= 5 ) redPct = 100 ;
1079+ bool anyOk = false ;
9851080
986- g_LedSetTarget (0x8 );
987- bool z0 = g_LedSetZone (0x8 , 0 , 0 , greenPct, 0 );
988- bool z1 = g_LedSetZone (0x8 , 1 , redPct, 0 , 0 );
1081+ if (g_sdkUseGlobal && g_LedSetTarget && g_LedSetLighting)
1082+ {
1083+ // Global mode: single color for all LEDs
1084+ int pct = (numLeds * 100 ) / 5 ;
1085+ g_LedSetTarget (g_sdkGlobalTarget);
1086+ anyOk = g_LedSetLighting (0 , pct, 0 );
1087+ }
1088+ else if (g_LedSetZone)
1089+ {
1090+ // Zone mode: map LED mask to zones
1091+ if (g_sdkMaxZone >= 4 )
1092+ {
1093+ // 5+ zones: one zone per LED
1094+ for (int z = 0 ; z <= g_sdkMaxZone && z < 5 ; z++)
1095+ {
1096+ int green = (ledMask & (1 << z)) ? 100 : 0 ;
1097+ bool ok = g_LedSetZone (g_sdkDevType, z, 0 , green, 0 );
1098+ if (ok) anyOk = true ;
1099+ }
1100+ }
1101+ else
1102+ {
1103+ // 2 zones: zone 0 = green intensity, zone 1 = red intensity
1104+ int greenPct = 0 , redPct = 0 ;
1105+ if (numLeds >= 1 ) greenPct = 33 ;
1106+ if (numLeds >= 2 ) greenPct = 66 ;
1107+ if (numLeds >= 3 ) greenPct = 100 ;
1108+ if (numLeds >= 4 ) redPct = 50 ;
1109+ if (numLeds >= 5 ) redPct = 100 ;
1110+
1111+ bool z0 = g_LedSetZone (g_sdkDevType, 0 , 0 , greenPct, 0 );
1112+ bool z1 = g_LedSetZone (g_sdkDevType, 1 , redPct, 0 , 0 );
1113+ anyOk = z0 || z1;
1114+ }
1115+ }
9891116
9901117 g_setLedsCallCount++;
991- if (g_setLedsCallCount <= 20 || (!z0 && !z1) )
992- Log (" SetLEDs(0x%02X) [SDK 0x8 g=%d r =%d] -> z0=%s z1= %s (#%d)" ,
993- ledMask, greenPct, redPct ,
994- z0 ? " OK " : " FAIL " , z1 ? " OK" : " FAIL" , g_setLedsCallCount);
1118+ if (g_setLedsCallCount <= 20 || !anyOk )
1119+ Log (" SetLEDs(0x%02X) [SDK dt=0x%02X mz =%d] -> %s (#%d)" ,
1120+ ledMask, g_sdkDevType, g_sdkMaxZone ,
1121+ anyOk ? " OK" : " FAIL" , g_setLedsCallCount);
9951122
996- return z0 || z1 ;
1123+ return anyOk ;
9971124 }
9981125
9991126 if (m_handle == INVALID_HANDLE_VALUE) return false ;
0 commit comments