[GH-ISSUE #248] Switch pro controller Gyro does not work on pre-release 0.9.49 #110

Closed
opened 2026-10-22 05:04:12 +00:00 by roman · 7 comments
Owner

Originally created by @jmt-gh on GitHub (Aug 23, 2026).
Original GitHub issue: https://github.com/safijari/openpuck/issues/248

Hi! Just recently set up my openpuck - amazing stuff, thank you!

I've bounced back and forth between pre release 0.9.49 and latest 0.9.31, and I'm not able to get gyro controls working on 0.9.49.

I'm able to get in to switch mode, connect, and use all of the other functions (including back buttons, etc). But gyro doesn't seem to work at all. When switching back to 0.9.31, it works immediately.

Not sure what all other sort of information would be helpful - let me know!

edit: Noting this is the board I'm using

Originally created by @jmt-gh on GitHub (Aug 23, 2026). Original GitHub issue: https://github.com/safijari/openpuck/issues/248 Hi! Just recently set up my openpuck - amazing stuff, thank you! I've bounced back and forth between pre release `0.9.49` and latest `0.9.31`, and I'm not able to get gyro controls working on `0.9.49`. I'm able to get in to switch mode, connect, and use all of the other functions (including back buttons, etc). But gyro doesn't seem to work at all. When switching back to `0.9.31`, it works immediately. Not sure what all other sort of information would be helpful - let me know! edit: [Noting this is the board I'm using ](https://www.amazon.com/dp/B0CYLNZ6V4)
roman closed this issue 2026-10-22 05:04:12 +00:00
Author
Owner

@jmt-gh commented on GitHub (Aug 23, 2026):

Using codex to help me work through this. Looks like it's got some options for a bisect i'll test out:

I found a strong candidate: the Switch Pro report-rate change introduced in 0.9.35.

  In 0.9.31, Switch mode could run at:

  - 66 Hz / 15 ms
  - 120 Hz / 8 ms
  - 250 Hz / 4 ms

  It also restored that choice from /swprocfg.bin. Starting with 0.9.35, the setting was removed and Switch reports were forced to 250 Hz. Version 0.9.49 inherits that behavior.

  The firmware puts three copies of the current IMU sample in every Switch input report. At 250 reports/sec, that presents 750 nominal IMU samples/sec to the host. That is substantially different from the genuine controller’s expected cadence and can make motion processing or calibration fail, even though buttons in the same reports continue to work.

  The current forced interval is visible in OpenPuck/mode_switch_pro.cpp:955 and OpenPuck/config.h:209.

  Why this fits your symptoms particularly well:

  - Button and gyro data use the same controller slot, so this isn’t likely a pairing/routing problem.
  - The actual gyro-axis decoding is essentially unchanged.
  - The later “corrected” gyro mapping only scales axes by 10–20%; it cannot turn functioning gyro data into zero.
  - 0.9.31 honors an old saved report-rate selection; 0.9.49 ignores that old configuration and always uses 250 Hz.
  - The project history contains earlier changes explicitly reducing Switch polling to address gyro problems, followed by the later return to fixed 250 Hz.
  - 0.9.49 itself barely changes Switch mode—the likely regression predates that release.

  The quickest definitive bisect is:

  1. Flash 0.9.34 and test gyro.
  2. Flash 0.9.35 and test again.

  If 0.9.34 works and 0.9.35 fails, the forced 250 Hz change is confirmed. If both work or both fail, the next boundary to test is 0.9.42 versus 0.9.43; 0.9.43 changed the USB device-version descriptor to USB 2.0, which is the next plausible compatibility regression.

  My confidence is high if you previously selected 66 or 120 Hz in the 0.9.31 configuration UI. Without a hardware/USB capture I wouldn’t call it conclusively proven, but it is the clearest code-level regression matching the exact behavior. The appropriate fix would be to restore a configurable Switch report interval—or default to the cadence known to work—while
  retaining the newer functionality.
<!-- gh-comment-id:5384235650 --> @jmt-gh commented on GitHub (Aug 23, 2026): Using codex to help me work through this. Looks like it's got some options for a bisect i'll test out: ``` I found a strong candidate: the Switch Pro report-rate change introduced in 0.9.35. In 0.9.31, Switch mode could run at: - 66 Hz / 15 ms - 120 Hz / 8 ms - 250 Hz / 4 ms It also restored that choice from /swprocfg.bin. Starting with 0.9.35, the setting was removed and Switch reports were forced to 250 Hz. Version 0.9.49 inherits that behavior. The firmware puts three copies of the current IMU sample in every Switch input report. At 250 reports/sec, that presents 750 nominal IMU samples/sec to the host. That is substantially different from the genuine controller’s expected cadence and can make motion processing or calibration fail, even though buttons in the same reports continue to work. The current forced interval is visible in OpenPuck/mode_switch_pro.cpp:955 and OpenPuck/config.h:209. Why this fits your symptoms particularly well: - Button and gyro data use the same controller slot, so this isn’t likely a pairing/routing problem. - The actual gyro-axis decoding is essentially unchanged. - The later “corrected” gyro mapping only scales axes by 10–20%; it cannot turn functioning gyro data into zero. - 0.9.31 honors an old saved report-rate selection; 0.9.49 ignores that old configuration and always uses 250 Hz. - The project history contains earlier changes explicitly reducing Switch polling to address gyro problems, followed by the later return to fixed 250 Hz. - 0.9.49 itself barely changes Switch mode—the likely regression predates that release. The quickest definitive bisect is: 1. Flash 0.9.34 and test gyro. 2. Flash 0.9.35 and test again. If 0.9.34 works and 0.9.35 fails, the forced 250 Hz change is confirmed. If both work or both fail, the next boundary to test is 0.9.42 versus 0.9.43; 0.9.43 changed the USB device-version descriptor to USB 2.0, which is the next plausible compatibility regression. My confidence is high if you previously selected 66 or 120 Hz in the 0.9.31 configuration UI. Without a hardware/USB capture I wouldn’t call it conclusively proven, but it is the clearest code-level regression matching the exact behavior. The appropriate fix would be to restore a configurable Switch report interval—or default to the cadence known to work—while retaining the newer functionality. ```
Author
Owner

@jmt-gh commented on GitHub (Aug 23, 2026):

actually seems like 0.9.34 appears to be busted too... continuing to look...

<!-- gh-comment-id:5384261898 --> @jmt-gh commented on GitHub (Aug 23, 2026): actually seems like `0.9.34` appears to be busted too... continuing to look...
Author
Owner

@jmt-gh commented on GitHub (Aug 23, 2026):

Hrmmm. reflashing 0.9.31 again, and now gyro doesn't work. It feels like there's an order of operations or something that I'm missing

<!-- gh-comment-id:5384287672 --> @jmt-gh commented on GitHub (Aug 23, 2026): Hrmmm. reflashing `0.9.31` again, and now gyro doesn't work. It feels like there's an order of operations or something that I'm missing
Author
Owner

@jmt-gh commented on GitHub (Aug 23, 2026):

OK factory reset 0.9.31 install seemed to get that version working again at least

<!-- gh-comment-id:5384315357 --> @jmt-gh commented on GitHub (Aug 23, 2026): OK factory reset `0.9.31` install seemed to get that version working again at least
Author
Owner

@jmt-gh commented on GitHub (Aug 23, 2026):

OK got a methodology down, and a working bisect...

0.9.42 has working gyro, but 0.9.43 does not.

<!-- gh-comment-id:5384359971 --> @jmt-gh commented on GitHub (Aug 23, 2026): OK got a methodology down, and a working bisect... `0.9.42` has working gyro, but `0.9.43` does not.
Author
Owner

@jmt-gh commented on GitHub (Aug 23, 2026):

We were able to isolate it down to a specific change from 0.9.43. Will look at getting a PR opened.

 Excellent—we’ve isolated it conclusively.

  The evidence:

  - Clean 0.9.42: gyro works
  - Clean 0.9.43: broken
  - 0.9.43 without USB-version change: still broken
  - 0.9.43 blocking setting 0x30: works

  Root cause: 0.9.43 began forwarding Steam’s complete 0x87 SET_SETTINGS blocks to the physical controller. Those blocks can contain setting 0x30, defined as SETTING_IMU_MODE.
  Delivering it disables/freezes the controller’s IMU.

  The bug remains in the current branch:

  - OpenPuck/puck_hid.cpp:382 forwards all settings blocks.
  - OpenPuck/steam_commands.h:82 identifies 0x30 as IMU mode.
  - OpenPuck/haptics.cpp:570 also constructs a maintenance settings block containing IMU_MODE = 0.

  The proper production fix should:

  1. Sanitize relayed 0x87 payloads and remove only the three-byte SETTING_IMU_MODE entry, preserving other settings in the same block.
  2. Remove the IMU entry from hapticReinit().
  3. Safely handle malformed/non-multiple-of-three payload lengths.
  4. Document why setting 0x30 must never be forwarded: OpenPuck still requires the controller to transmit IMU data over RF.
  5. Provide a recovery path for controllers already affected, likely factory reset/re-pairing until the correct explicit IMU-enable value is verified.

  Your Teyleten board is not responsible for this specific regression—the controlled A/B test on the same hardware proves that. It may have separate clock/stability quirks, but the
  missing gyro is a firmware command-forwarding bug.
<!-- gh-comment-id:5384396780 --> @jmt-gh commented on GitHub (Aug 23, 2026): We were able to isolate it down to a specific change from `0.9.43`. Will look at getting a PR opened. ``` Excellent—we’ve isolated it conclusively. The evidence: - Clean 0.9.42: gyro works - Clean 0.9.43: broken - 0.9.43 without USB-version change: still broken - 0.9.43 blocking setting 0x30: works Root cause: 0.9.43 began forwarding Steam’s complete 0x87 SET_SETTINGS blocks to the physical controller. Those blocks can contain setting 0x30, defined as SETTING_IMU_MODE. Delivering it disables/freezes the controller’s IMU. The bug remains in the current branch: - OpenPuck/puck_hid.cpp:382 forwards all settings blocks. - OpenPuck/steam_commands.h:82 identifies 0x30 as IMU mode. - OpenPuck/haptics.cpp:570 also constructs a maintenance settings block containing IMU_MODE = 0. The proper production fix should: 1. Sanitize relayed 0x87 payloads and remove only the three-byte SETTING_IMU_MODE entry, preserving other settings in the same block. 2. Remove the IMU entry from hapticReinit(). 3. Safely handle malformed/non-multiple-of-three payload lengths. 4. Document why setting 0x30 must never be forwarded: OpenPuck still requires the controller to transmit IMU data over RF. 5. Provide a recovery path for controllers already affected, likely factory reset/re-pairing until the correct explicit IMU-enable value is verified. Your Teyleten board is not responsible for this specific regression—the controlled A/B test on the same hardware proves that. It may have separate clock/stability quirks, but the missing gyro is a firmware command-forwarding bug. ```
Author
Owner

@jmt-gh commented on GitHub (Aug 23, 2026):

Opened a PR to fix in #249

<!-- gh-comment-id:5384441258 --> @jmt-gh commented on GitHub (Aug 23, 2026): Opened a PR to fix in #249
Sign in to join this conversation.
No labels
pull-request
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
safijari/openpuck#110
No description provided.