Explorar o código

Fixed but with some issues

Jari hai 3 meses
pai
achega
85e21822dd
Modificáronse 2 ficheiros con 31 adicións e 4 borrados
  1. 17 2
      OpenPuck/puck_hid.cpp
  2. 14 2
      OpenPuck/rf_link.cpp

+ 17 - 2
OpenPuck/puck_hid.cpp

@@ -207,6 +207,9 @@ static inline void hostStampAlive()
 // as a real click/keypress into the just-woken desktop. Set when task() sees the suspended->active transition.
 static unsigned long g_resumeMs = 0;
 #define POST_RESUME_MUTE_MS 1500u
+// How long to keep re-asserting the 0x79 DISCONNECT edge to Steam after a controller drops, so a single
+// lost report can't strand Steam in "connected" (see task()). Bounded to avoid forever-spamming disc.
+#define DISC_RESEND_MS 6000u
 
 // ===================== puck feature command channel =====================
 // `slot` is the interface index (interface N == bond slot N).
@@ -919,7 +922,8 @@ void SteamPuckController::task()
 	// slot. The real puck's per-slot edge-triggered 0x79 prevents re-triggering Steam's connect-chime loop.
 	static bool usbConn[NSLOT] = { 0 };
 	static unsigned long last79[NSLOT] = { 0 }, last7B[NSLOT] = { 0 },
-			     connEdgeMs[NSLOT] = { 0 }, last43[NSLOT] = { 0 };
+			     connEdgeMs[NSLOT] = { 0 }, discEdgeMs[NSLOT] = { 0 },
+			     last43[NSLOT] = { 0 };
 	for (int s = 0; s < NSLOT; s++) {
 		if (!g_slot[s].used || !hid[s].ready())
 			continue;
@@ -932,10 +936,21 @@ void SteamPuckController::task()
 		bool steamAcked = g_steamAliveMs &&
 				  (int32_t)(g_steamAliveMs - connEdgeMs[s]) >=
 					  0;
+		// The DISCONNECT edge (0x79=01) also needs resending: it used to be sent exactly ONCE, so a single
+		// dropped report left Steam believing the controller was still connected indefinitely -- observed as
+		// "WebUSB panel shows the slot DOWN (g_connReplyMs stale) while Steam still lists it connected, and the
+		// controller light is solid (it re-adopted the beacon) but no input flows." Resend disc every 750ms but
+		// BOUNDED to DISC_RESEND_MS so a lost packet converges without the forever-spam the "real puck sends
+		// 0x79 once" note warns against.
+		bool discResend =
+			!conn && (millis() - discEdgeMs[s] < DISC_RESEND_MS);
 		if (conn != usbConn[s] ||
-		    (conn && !steamAcked && millis() - last79[s] >= 750)) {
+		    (conn && !steamAcked && millis() - last79[s] >= 750) ||
+		    (discResend && millis() - last79[s] >= 750)) {
 			if (conn && !usbConn[s])
 				connEdgeMs[s] = millis();
+			if (!conn && usbConn[s]) // connect->disc edge: anchor the resend window
+				discEdgeMs[s] = millis();
 			uint8_t st = conn ? 0x02 : 0x01;
 			hapLogAdd(0xFB, 0x79, &st, 1); // ->host push (capture)
 			usbTxHid(&hid[s], 0x79, &st, 1);

+ 14 - 2
OpenPuck/rf_link.cpp

@@ -895,6 +895,17 @@ static void rfConnStep()
 	//     every cycle was doubling/tripling Polls/s, flooding noRx, and stealing reply windows from the live
 	//     controller. A never-replied slot with nothing else connected still polls full-rate, so the FIRST
 	//     controller connects instantly; a phantom only backs off once a real link exists to protect.
+	//
+	// CRITICAL: every throttle (cold/quiet/phantom) is gated on linkUp -- i.e. it applies ONLY while another
+	// controller is currently connected and its reply windows must be protected (the issue-#72 radio-duty
+	// concern). With NOTHING linked we are in (re)acquire mode, so EVERY used slot polls at full rate, exactly
+	// like a first-boot connect. This fixes the solid-light reconnect wedge: after a controller is powered off
+	// for > SLOT_COLD_MS its slot went "cold" and dropped to a 2s poll cadence; on power-on the controller heard
+	// the E1 beacon and re-adopted the session (solid light) but then timed out waiting to be polled and dropped
+	// again before the next 2s cold poll ever landed -- a permanent livelock that only a puck replug (which
+	// resets the slot to never-replied => full rate) recovered. Full-rate acquire when !linkUp cannot regress
+	// issue #72: that hang was about starving a LIVE controller under comms load, and there is no live
+	// controller (and no comms load) here to starve.
 	bool linkUp = anySlotLinkUp();
 	for (int k = 0; k < NSLOT; k++) {
 		if (!g_slot[k].used)
@@ -902,8 +913,9 @@ static void rfConnStep()
 		bool everReplied = g_connReplyMs[k] != 0;
 		unsigned long silentMs =
 			everReplied ? (nowMs - g_connReplyMs[k]) : 0;
-		bool cold = everReplied && silentMs > SLOT_COLD_MS;
-		bool quiet = everReplied && !cold && silentMs > SLOT_QUIET_MS;
+		bool cold = linkUp && everReplied && silentMs > SLOT_COLD_MS;
+		bool quiet = linkUp && everReplied && !cold &&
+			     silentMs > SLOT_QUIET_MS;
 		bool phantom = !everReplied && linkUp;
 		unsigned long retry = (cold || phantom) ? SLOT_COLD_RETRY_MS :
 				      quiet		? SLOT_QUIET_RETRY_MS :