Skip to content

Commit 5e8761c

Browse files
authored
v0.7.6-RC3 FIX: Xbox One reporting issues (#727)
* Clean-up and two fixes: sequence no longer goes to 0 and keep alive does not trigger a repeat input report. * Removing AlpacaOwO in this branch as this is a desired change * This one is an extern so we can't static it
1 parent 6f1af54 commit 5e8761c

8 files changed

Lines changed: 52 additions & 203 deletions

File tree

.github/workflows/cmake.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
runs-on: ubuntu-latest
2424
strategy:
2525
matrix:
26-
GP2040_BOARDCONFIG: [Pico, PicoW, AlpacaOwO, BentoBox, DURAL, FightboardV3, FightboardV3Mirrored, FlatboxRev4, FlatboxRev5, FlatboxRev5RGB, FlatboxRev5Southpaw, KB2040, KeyboardConverter, Haute42, Liatris, MavercadeKeebfighter, OpenCore0, OpenCore0WASD, PicoFightingBoard, RanaTadpole, ReflexCtrlSNES, ReflexEncodeV1.2, ReflexEncodeV2.0, RP2040AdvancedBreakoutBoard, RP2040AdvancedBreakoutBoardUSBPassthrough, RP2040MiniBreakoutBoard, SparkFunProMicro, WaveshareZero, Stress, SGFBridget, SGFFaust ]
26+
GP2040_BOARDCONFIG: [Pico, PicoW, BentoBox, DURAL, FightboardV3, FightboardV3Mirrored, FlatboxRev4, FlatboxRev5, FlatboxRev5RGB, FlatboxRev5Southpaw, KB2040, KeyboardConverter, Haute42, Liatris, MavercadeKeebfighter, OpenCore0, OpenCore0WASD, PicoFightingBoard, RanaTadpole, ReflexCtrlSNES, ReflexEncodeV1.2, ReflexEncodeV2.0, RP2040AdvancedBreakoutBoard, RP2040AdvancedBreakoutBoardUSBPassthrough, RP2040MiniBreakoutBoard, SparkFunProMicro, WaveshareZero, Stress, SGFBridget, SGFFaust ]
2727

2828
steps:
2929
#Global Setup

configs/AlpacaOwO/BoardConfig.h

Lines changed: 0 additions & 138 deletions
This file was deleted.

configs/AlpacaOwO/CMakeLists.txt

Lines changed: 0 additions & 3 deletions
This file was deleted.

configs/AlpacaOwO/README.md

Lines changed: 0 additions & 11 deletions
This file was deleted.
-72.1 KB
Binary file not shown.

headers/gamepad.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ class Gamepad {
9191
XboxOriginalReport *getXboxOriginalReport();
9292

9393
uint8_t last_report[CFG_TUD_ENDPOINT0_SIZE] = { };
94+
uint8_t last_report_counter = 0;
95+
uint16_t last_axis_counter = 0;
9496

9597
/**
9698
* @brief Check for a button press. Used by `pressed[Button]` helper methods.

lib/TinyUSB_Gamepad/src/xbone_driver.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,8 @@
3232
static bool waiting_ack=false;
3333
static uint32_t waiting_ack_timeout=0;
3434
uint8_t xbone_out_buffer[XBONE_OUT_SIZE] = {};
35-
uint32_t timer_wait_for_announce = 0;
36-
uint32_t xbox_one_powered_on = false;
37-
uint32_t keep_alive_timer = 0;
35+
static uint32_t timer_wait_for_announce = 0;
36+
static uint32_t xbox_one_powered_on = false;
3837

3938
// Sent report queue every 15 milliseconds
4039
static uint32_t lastReportQueueSent = 0;

src/gamepad.cpp

Lines changed: 47 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ static XboxOriginalReport xboxOriginalReport
175175
.rightStickY = 0,
176176
};
177177

178+
#define XBONE_KEEPALIVE_TIMER 15000
179+
178180
static XboxOneGamepad_Data_t xboneReport
179181
{
180182
.sync = 0,
@@ -206,8 +208,6 @@ static uint16_t xboneReportSize;
206208

207209
// Xbox One & PS4/PS5 Timing
208210
static TouchpadData touchpadData;
209-
static uint8_t last_report_counter = 0;
210-
static uint16_t last_axis_counter = 0;
211211

212212
static KeyboardReport keyboardReport
213213
{
@@ -281,10 +281,12 @@ void Gamepad::setup()
281281

282282
// setup PS5 compatibility
283283
PS4Data::getInstance().ps4ControllerType = gamepadOptions.ps4ControllerType;
284+
last_report_counter = 0;
285+
last_axis_counter = 0;
284286

285287
// Xbox One Keep-Alive
286-
keep_alive_timer = 0;
287-
keep_alive_sequence = 0;
288+
keep_alive_timer = to_ms_since_boot(get_absolute_time());
289+
keep_alive_sequence = 1;
288290
virtual_keycode_sequence = 0;
289291
xb1_guide_pressed = false;
290292
xboneReportSize = sizeof(XboxOneGamepad_Data_t);
@@ -800,9 +802,8 @@ void Gamepad::sendReportSuccess() {
800802
// Successfully sent report, actually increment last report counter!
801803
if ( memcmp(&last_report[4], &((uint8_t*)&xboneReport)[4], xboneReportSize-4) != 0) {
802804
last_report_counter++;
803-
if (last_report_counter == 0) {
805+
if (last_report_counter == 0)
804806
last_report_counter = 1;
805-
}
806807
memcpy(last_report, &xboneReport, xboneReportSize);
807808
}
808809
}
@@ -824,11 +825,9 @@ XboxOneGamepad_Data_t *Gamepad::getXBOneReport()
824825

825826
uint32_t now = to_ms_since_boot(get_absolute_time());
826827
// Send Keep-Alive every 15 seconds (keep_alive_timer updates if send is successful)
827-
if ( (now - keep_alive_timer) > 15000) {
828+
if ( (now - keep_alive_timer) > XBONE_KEEPALIVE_TIMER) {
828829
memset(&xboneReport.Header, 0, sizeof(GipHeader_t));
829-
xboneReport.Header.command = GIP_KEEPALIVE;
830-
xboneReport.Header.internal = 1;
831-
xboneReport.Header.sequence = keep_alive_sequence;
830+
GIP_HEADER((&xboneReport), GIP_KEEPALIVE, 1, keep_alive_sequence);
832831
xboneReport.Header.length = 4;
833832
static uint8_t keepAlive[] = { 0x80, 0x00, 0x00, 0x00 };
834833
memcpy(&((uint8_t*)&xboneReport)[4], &keepAlive, sizeof(keepAlive));
@@ -844,64 +843,65 @@ XboxOneGamepad_Data_t *Gamepad::getXBOneReport()
844843
virtual_keycode_sequence++; // will rollover
845844
if ( virtual_keycode_sequence == 0 )
846845
virtual_keycode_sequence = 1;
847-
memset(&xboneReport.Header, 0, sizeof(GipHeader_t));
848-
xboneReport.Header.command = GIP_VIRTUAL_KEYCODE;
849-
xboneReport.Header.internal = 1;
850-
xboneReport.Header.sequence = virtual_keycode_sequence;
846+
GIP_HEADER((&xboneReport), GIP_VIRTUAL_KEYCODE, 1, virtual_keycode_sequence);
847+
xboneReport.Header.length = sizeof(xb1_guide_on);
851848
if ( pressedA1() ) {
852849
xb1_guide_pressed = true;
853-
xboneReport.Header.length = sizeof(xb1_guide_on);
854850
memcpy(&((uint8_t*)&xboneReport)[4], &xb1_guide_on, sizeof(xb1_guide_on));
855851
} else {
856852
xb1_guide_pressed = false;
857-
xboneReport.Header.length = sizeof(xb1_guide_off);
858853
memcpy(&((uint8_t*)&xboneReport)[4], &xb1_guide_off, sizeof(xb1_guide_off));
859854
}
860855
}
861856
xboneReportSize = sizeof(GipHeader_t) + sizeof(xb1_guide_on);
862857
return &xboneReport;
863858
}
864859

865-
GIP_HEADER((&xboneReport), GIP_INPUT_REPORT, false, last_report_counter);
866-
867-
xboneReport.a = pressedB1();
868-
xboneReport.b = pressedB2();
869-
xboneReport.x = pressedB3();
870-
xboneReport.y = pressedB4();
871-
xboneReport.leftShoulder = pressedL1();
872-
xboneReport.rightShoulder = pressedR1();
873-
xboneReport.leftThumbClick = pressedL3();
874-
xboneReport.rightThumbClick = pressedR3();
875-
xboneReport.start = pressedS2();
876-
xboneReport.back = pressedS1();
877-
xboneReport.guide = 0; // always 0
878-
xboneReport.sync = 0;
879-
xboneReport.dpadUp = pressedUp();
880-
xboneReport.dpadDown = pressedDown();
881-
xboneReport.dpadLeft = pressedLeft();
882-
xboneReport.dpadRight = pressedRight();
883-
884-
xboneReport.leftStickX = static_cast<int16_t>(state.lx) + INT16_MIN;
885-
xboneReport.leftStickY = static_cast<int16_t>(~state.ly) + INT16_MIN;
886-
xboneReport.rightStickX = static_cast<int16_t>(state.rx) + INT16_MIN;
887-
xboneReport.rightStickY = static_cast<int16_t>(~state.ry) + INT16_MIN;
860+
// Only change xbox one input report if we have different inputs!
861+
XboxOneGamepad_Data_t newInputReport;
862+
863+
// This is due to our tusb_driver.cpp checking memcmp(last_report, report, size)
864+
memset(&newInputReport, 0, sizeof(XboxOneGamepad_Data_t));
865+
GIP_HEADER((&newInputReport), GIP_INPUT_REPORT, false, last_report_counter);
866+
867+
newInputReport.a = pressedB1();
868+
newInputReport.b = pressedB2();
869+
newInputReport.x = pressedB3();
870+
newInputReport.y = pressedB4();
871+
newInputReport.leftShoulder = pressedL1();
872+
newInputReport.rightShoulder = pressedR1();
873+
newInputReport.leftThumbClick = pressedL3();
874+
newInputReport.rightThumbClick = pressedR3();
875+
newInputReport.start = pressedS2();
876+
newInputReport.back = pressedS1();
877+
newInputReport.guide = 0; // always 0
878+
newInputReport.sync = 0;
879+
newInputReport.dpadUp = pressedUp();
880+
newInputReport.dpadDown = pressedDown();
881+
newInputReport.dpadLeft = pressedLeft();
882+
newInputReport.dpadRight = pressedRight();
883+
884+
newInputReport.leftStickX = static_cast<int16_t>(state.lx) + INT16_MIN;
885+
newInputReport.leftStickY = static_cast<int16_t>(~state.ly) + INT16_MIN;
886+
newInputReport.rightStickX = static_cast<int16_t>(state.rx) + INT16_MIN;
887+
newInputReport.rightStickY = static_cast<int16_t>(~state.ry) + INT16_MIN;
888888

889889
if (hasAnalogTriggers)
890890
{
891-
xboneReport.leftTrigger = pressedL2() ? 0x03FF : state.lt;
892-
xboneReport.rightTrigger = pressedR2() ? 0x03FF : state.rt;
891+
newInputReport.leftTrigger = pressedL2() ? 0x03FF : state.lt;
892+
newInputReport.rightTrigger = pressedR2() ? 0x03FF : state.rt;
893893
}
894894
else
895895
{
896-
xboneReport.leftTrigger = pressedL2() ? 0x03FF : 0;
897-
xboneReport.rightTrigger = pressedR2() ? 0x03FF : 0;
896+
newInputReport.leftTrigger = pressedL2() ? 0x03FF : 0;
897+
newInputReport.rightTrigger = pressedR2() ? 0x03FF : 0;
898898
}
899899

900-
xboneReportSize = sizeof(XboxOneGamepad_Data_t);
901-
902900
// We changed inputs since generating our last report, increment last report counter (but don't update until success)
903-
if ( memcmp(&last_report[4], &((uint8_t*)&xboneReport)[4], xboneReportSize-4) != 0 ) {
904-
xboneReport.Header.sequence = last_report_counter+1;
901+
if ( memcmp(&last_report[4], &((uint8_t*)&newInputReport)[4], sizeof(XboxOneGamepad_Data_t)-4) != 0 ) {
902+
xboneReportSize = sizeof(XboxOneGamepad_Data_t);
903+
memcpy(&xboneReport, &newInputReport, xboneReportSize);
904+
xboneReport.Header.sequence = (last_report_counter + 1 == 0) ? 1 : last_report_counter + 1;
905905
}
906906

907907
return &xboneReport;

0 commit comments

Comments
 (0)