|
|
@@ -191,10 +191,43 @@ void SteamPuckController::onReport45(const uint8_t* rep, bool fresh, uint8_t bod
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// ---- wake nudge: real HID input delivered right after the bus resumes. A bare USB resume signal is NOT
|
|
|
+// enough to wake some hosts (Windows in particular) -- they only wake when actual keyboard/mouse input
|
|
|
+// follows. So on a deliberate wake gesture we play a HARMLESS nudge on the puck's own kb/mouse reports:
|
|
|
+// a mouse JIGGLE (move a few px and back, NO button) + a lone Left-Ctrl tap. Earlier this sent a left CLICK
|
|
|
+// and SPACE, which woke the host but also clicked/activated whatever was focused (it kept launching the
|
|
|
+// browser). Move + modifier wake just as well with no actionable side effect. Queued by wakeEvent() (called
|
|
|
+// from rf_link on a Steam-button short press / controller connect while suspended); stepped ~15ms per phase.
|
|
|
+// Reports can't cross a suspended bus, so it's delivered once the bus has resumed.
|
|
|
+static uint8_t g_nudgeStep = 0; // 0=idle; 1=jiggle+, 2=jiggle-, 3=Ctrl down, 4=Ctrl up
|
|
|
+static unsigned long g_nudgeMs = 0;
|
|
|
+#define NUDGE_JIGGLE_PX 10
|
|
|
+void SteamPuckController::wakeEvent(){
|
|
|
+ g_nudgeStep = 1; g_nudgeMs = millis();
|
|
|
+}
|
|
|
+static void wakeNudgeTask(){
|
|
|
+ if(!g_nudgeStep) return;
|
|
|
+ if(millis()-g_nudgeMs > 5000){ g_nudgeStep=0; return; } // bus never resumed -> drop the nudge
|
|
|
+ if(USBDevice.suspended()) return; // wait for resume; reports can't cross a suspended bus
|
|
|
+ if(g_connSlot<0 || g_connSlot>=NSLOT || !hid[g_connSlot].ready()) return;
|
|
|
+ static unsigned long stepMs=0;
|
|
|
+ if(millis()-stepMs < 15) return; // pace the edges
|
|
|
+ stepMs=millis();
|
|
|
+ switch(g_nudgeStep){
|
|
|
+ case 1: case 2: { // mouse jiggle: move +N then -N (net zero cursor), no buttons -> wakes, clicks nothing
|
|
|
+ hid_mouse_report_t m; m.buttons=0; m.x=(g_nudgeStep==1)?NUDGE_JIGGLE_PX:-NUDGE_JIGGLE_PX; m.y=0; m.wheel=0; m.pan=0;
|
|
|
+ hid[g_connSlot].sendReport(0x40,&m,sizeof m); break; }
|
|
|
+ case 3: { uint8_t k[8]={KEYBOARD_MODIFIER_LEFTCTRL,0,0,0,0,0,0,0}; hid[g_connSlot].sendReport(0x41,k,8); break; } // lone modifier: inert
|
|
|
+ case 4: { uint8_t k[8]={0,0,0,0,0,0,0,0}; hid[g_connSlot].sendReport(0x41,k,8); break; } // release
|
|
|
+ }
|
|
|
+ g_nudgeStep = (g_nudgeStep>=4) ? 0 : (uint8_t)(g_nudgeStep+1);
|
|
|
+}
|
|
|
+
|
|
|
// USB connection presentation (like the real dongle): report 0x79 = connection state (01=disc, 02=conn),
|
|
|
// edge-triggered, + periodic 0x7B status. Live-captured: this is what Steam reads to mark the controller
|
|
|
// connected. Without it Steam shows disconnected even though 0x45 input is streaming.
|
|
|
void SteamPuckController::task(){
|
|
|
+ wakeNudgeTask();
|
|
|
if (USBDevice.suspended()) return; // no periodic 0x79/0x7B while the host sleeps -- those sends can wake it too
|
|
|
static bool usbConn=false; static unsigned long last79=0, last7B=0;
|
|
|
bool conn = (g_connSlot>=0 && millis()-g_connReplyMs < 300);
|