Przeglądaj źródła

remove all re-inits

Jariullah Safi 4 miesięcy temu
rodzic
commit
1c29ea1584
3 zmienionych plików z 30 dodań i 44 usunięć
  1. 11 33
      OpenPuck/haptics.cpp
  2. 0 8
      OpenPuck/haptics.h
  3. 19 3
      OpenPuck/puck_hid.cpp

+ 11 - 33
OpenPuck/haptics.cpp

@@ -41,14 +41,7 @@ static unsigned long g_rumble80Ms = 0;
 // Steam/Triton rumble is latched on until an explicit zero report
 static bool g_rumble80On = false;
 
-// when to fire the next post-reconnect haptic re-init (0 = none scheduled)
-static unsigned long g_reinitAt = 0;
-
-// how many re-init shots remain in this connect window
-static uint8_t g_reinitLeft = 0;
-
-// haptic activity happened -> arm a clear once it goes idle (catches a
-// latch that engaged during/after use, even seconds after connect)
+// haptic activity happened (tracked for the 0x82 quiet timeout; the idle-clear that read it is gone)
 static bool g_hapClearArmed = false;
 
 // ---- relay ring: multi-producer (USB ISR + loop-context console/xinput), single consumer (poll flush) ----
@@ -435,16 +428,13 @@ void hapticOnReconnect()
 
 	// drop any haptic ON queued before the link came up
 	hapticCancelPendingOn();
-	// Re-init the haptic engine repeatedly across the settle window rather than waiting for the block to end: the
-	// brief connect buzz engages early (during the block, controller-internal), so a single late shot misses it.
-	// The re-init is settings only (no haptic play) and Steam haptics are blocked throughout, so it can't buzz.
-	g_reinitAt = millis() + 200u; // first reset ~200ms after (re)connect
-
-	// then every HAPTIC_REINIT_GAP_MS across the window
-	g_reinitLeft = HAPTIC_REINIT_SHOTS;
+	// NO re-init injection. The buzz is fixed at its root by bursting the haptic STOP (relayHaptic) so a lost
+	// NO-ACK stop can't latch the actuator -- so the old connect-time 0x81/0x87 re-init flood is redundant. It
+	// also injected in EVERY mode and could freeze the controller IMU in the emulated modes, so it's removed
+	// outright (all modes). We still hold haptics off for the 3s connect settle (block above). Be a pure relay.
 	uint8_t mk = 2;
 
-	// capture marker: RECONNECT detected (block+reinit armed)
+	// capture marker: RECONNECT detected (block armed, no reinit)
 	hapLogAdd(0xFD, 0xEE, &mk, 1);
 }
 void hapticTask()
@@ -463,14 +453,7 @@ void hapticTask()
 		hapLogAdd(0xFD, 0xEE, &mk, 1);
 	}
 	wasHapticLinkUp = up;
-	if (g_reinitAt && up &&
-	    (int32_t)(millis() - g_reinitAt) >=
-		    0) { // proactive haptic re-init across the connect window
-		hapticReinit();
-		g_reinitAt = (g_reinitLeft && --g_reinitLeft) ?
-				     (millis() + HAPTIC_REINIT_GAP_MS) :
-				     0;
-	}
+	// (Connect-time re-init flood removed -- the stop-burst is the real fix; see hapticOnReconnect.)
 	// Controller power-off on host SLEEP: send the power-off command (0x9F "off!") the instant the USB bus
 	// suspends, like the real puck. BUT only when USB power (VBUS) is still present -- i.e. a genuine host sleep,
 	// NOT a cable unplug. Pulling the dongle ALSO trips the suspend edge (in the brief window it runs on residual
@@ -492,13 +475,8 @@ void hapticTask()
 		g_haptic82On = false;
 	if (g_rumble80On && millis() - g_rumble80Ms > 2500u)
 		hapticSteamRumble(0, 0);
-	// Haptic activity has gone idle for a while -> fire one re-init to clear any latch it left behind (the buzz
-	// that engages during/after use and won't self-clear, incl. after a mode switch). Fires only after a quiet
-	// gap, so it never interrupts active haptics; the brightness-less re-init is silent (settings, no play, no
-	// LED). Runs in ALL modes (the controller-side latch is mode-independent).
-	if (g_hapClearArmed &&
-	    (millis() - g_haptic82Ms) > HAPTIC_CLEAR_IDLE_MS) {
-		g_hapClearArmed = false;
-		hapticReinit();
-	}
+	// Idle-clear re-init removed: with the stop-burst (relayHaptic) a lost stop can't latch the actuator, so
+	// there's no during-use latch to clear -- and the old idle-clear injected 0x81/0x87 ~1.2s after every haptic
+	// burst in ALL modes (a likelier latch CAUSE than cure, and an IMU-freeze risk in emulated modes).
+	(void)g_hapClearArmed;
 }

+ 0 - 8
OpenPuck/haptics.h

@@ -29,14 +29,6 @@
 #define HAPTIC_STOP_BURST 4u
 // max relayed payload bytes per entry: RF frame = [E3][len][05][rid][payload] and MAXLEN=64 -> 60
 #define RELAY_MAXP 60u
-// Proactive post-(re)connect haptic re-init: this many shots, this far apart, starting ~200ms after the link
-// comes up -- covers ~0.2s..3s so the brief controller-side connect buzz gets reset before it can sustain.
-#define HAPTIC_REINIT_SHOTS 8u
-#define HAPTIC_REINIT_GAP_MS 350u
-// After haptic activity, if it's been idle this long, fire one clear-re-init -- kills a latch that engaged
-// during use (a buzz that starts seconds after connect and won't self-clear). Long enough not to fire between
-// rapid in-game haptics; short enough to clear a stuck buzz soon after the user pauses.
-#define HAPTIC_CLEAR_IDLE_MS 1200u
 // Controller power-off: hapticSendShutdown() relays Steam's confirmed "turn off controller" command (feature-0x01
 // cmd 0x9F, payload "off!" -- captured from the real puck). Sent as a small burst because the RF relay is NO-ACK.
 #define HAPTIC_SHUTDOWN_SHOTS 3u

+ 19 - 3
OpenPuck/puck_hid.cpp

@@ -307,7 +307,6 @@ static void handleSet(int slot, uint8_t rid, hid_report_type_t type,
 static uint16_t handleGet(int slot, uint8_t rid, hid_report_type_t type,
 			  uint8_t *buf, uint16_t reqlen)
 {
-	(void)rid;
 	if (type != HID_REPORT_TYPE_FEATURE)
 		return 0;
 
@@ -319,6 +318,11 @@ static uint16_t handleGet(int slot, uint8_t rid, hid_report_type_t type,
 	if (n > reqlen)
 		n = reqlen;
 	memcpy(buf, S.resp, n);
+	// Log feature READS (we already log writes as "# SET"). Battery-hunt: shows whether Steam polls a specific
+	// report / the last-answered cmd when the gamepad is active (resp[0]=the cmd we're echoing back).
+	if (Serial.availableForWrite() > 60)
+		Serial.printf("# GET if%d rid=%02X resp0=%02X len=%u\n", slot,
+			      rid, S.resp[0], (unsigned)n);
 	return n;
 }
 
@@ -421,8 +425,20 @@ void SteamPuckController::onAuxReport(uint8_t rid, const uint8_t *data,
 		return;
 	if (g_connSlot < 0 || g_connSlot >= NSLOT)
 		return;
-	if (g_slot[g_connSlot].used && hid[g_connSlot].ready())
-		hid[g_connSlot].sendReport(rid, data, n);
+	if (!(g_slot[g_connSlot].used && hid[g_connSlot].ready()))
+		return;
+	// Send EXACTLY the descriptor-declared length, zero-padded. Hosts (macOS especially -- see the HID
+	// report-length note) DROP an input report whose length doesn't match its declared size, so a short/odd 0x43
+	// never reaches Steam and its battery indicator stays at the default (100%) even though the value is correct
+	// in our own readout. 0x43 (power/battery) is declared 14 bytes, 0x44 (status event) 5 bytes. Battery % sits
+	// in the early bytes, so trailing zero-pad doesn't move it; we only normalize the frame length.
+	uint8_t declared = (rid == 0x43) ? 14u : (rid == 0x44) ? 5u : n;
+	uint8_t buf[14] = { 0 };
+	uint8_t cn = (n < declared) ? n : declared;
+	if (declared > sizeof buf)
+		declared = sizeof buf; // safety; both known aux reports fit
+	memcpy(buf, data, cn);
+	hid[g_connSlot].sendReport(rid, buf, declared);
 }
 
 // wake nudge: a bare USB resume signal is NOT enough to wake some hosts (Windows in particular) -- they only