Support Joy-Con 2 clones that only speak the console protocol (NYXI Hyperion 3) - #26
Open
mygamecache wants to merge 1 commit into
Open
mygamecache wants to merge 1 commit into
mygamecache wants to merge 1 commit into
Conversation
NYXI Hyperion 3 Joy-Cons copy the Joy-Con 2 GATT table but ignore the common command and input characteristics, answering only on the side-specific channel a Switch 2 console uses. They are recognised by the SMP security request they send on connect, or by silence on the common channel after init, and are then driven by the console start-up sequence with Nintendo pairing and the console input report. Android's pairing with these controllers always fails, so the pairing dialog is suppressed and a pending L2CAP channel keeps the link from being dropped afterwards. A 7.5 ms connection interval is requested, with CONNECTION_PRIORITY_HIGH as the fallback, and every console session asks for its interval again when another controller joins the pool. Genuine Joy-Con 2 connections are unchanged.
mygamecache
force-pushed
the
nyxi-controller-support
branch
from
September 23, 2026 23:48
3ee6292 to
fe81675
Compare
Author
|
One design question, since 1.3.0 landed while I was writing this. The fast interval now rides on the high-priority toggle, which Options as I see them:
Happy to implement whichever you prefer — I have the hardware to measure any of them. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Support Joy-Con 2 clones that only speak the console protocol (NYXI Hyperion 3)
Follow-up to our Reddit chat. This adds support for third-party Joy-Con 2 clones that currently can't connect: pairing fails with an "incorrect PIN or passkey" error and the controller disconnects. Tested with a NYXI Hyperion 3 (left and right).
Why they fail today
649d4ac9…) and never notify on…FD2. They only answer on the side-specific channel a Switch 2 console uses (commands on65a724b3…/ce49a830…behind 17 zero bytes, input ond5a9e01e…/cc1bbbb5…).l2cu_start_post_bond_timer), so sessions end at ~33 s.What this changes
JoyconConnection): a controller that sends an SMP Security Request, or that neither replies to the SPI read nor streams on…FD2within 1.5 s of init, is handed toConsoleSession. The second check is needed because Android runs one pairing at a time, so a second clone connected while the first one's pairing is pending sends no request. Genuine Joy-Con 2 connections keep the existing flow.connection/console/: the console start-up sequence including Nintendo pairing (report0x15), the console input report translated into the existing button bitmask (so mapping, the gamepad and DSU are unchanged), player LEDs, and battery level.SecurityRequestReceiveraborts the ordered pairing broadcast so no dialog appears, andLinkHolderkeeps a pending LE L2CAP channel on the link so the post-pairing disconnect never fires.requestLeConnectionUpdate(via HiddenApiBypass) for 7.5 ms, the LE minimum, falling back toCONNECTION_PRIORITY_HIGH. That's ~200 reports/s instead of ~67. Each console session asks again when another controller joins, since Android can slow an existing one down when one does.settings get secure bluetooth_addressthrough the existing Shizuku access. If that isn't available, pairing is skipped.docs/protocol.mdsection (characteristics, pairing, report layout, the Android workarounds) and one README troubleshooting line. Unit tests cover the report parser and the pairing maths, using captured controller replies.Overlap with #19
@SWeav02's draft in #19 covers the same controller from a different angle, and I only spotted it after building this. Take whichever suits the project, or pieces of both — I'm happy either way, and glad to help test theirs. The main differences:
CONNECTION_PRIORITY_HIGH(~67).Their observation that Android slows an existing connection when a second controller joins is real, and it applies here too, so each console session re-asserts its interval when another joins. Credit to them for spotting it.
Tested
./gradlew buildpasses (compile, unit tests, lint).:konsist:testpasses too, though on Windows it needs the path fix from Add support for Nyxi Hyperion 3 and dual-controller latency fix #19 to run at all — unrelated to this change.Please check
Not included
One unrelated note worth a troubleshooting line (added to the README): on some OEM builds the game launcher clears background apps when a game starts and kills the foreground service, which drops every controller mid-game. Setting the app's battery usage to unrestricted and excluding it from that cleanup fixes it. Took me a while to realise it wasn't the app's fault.
Happy to test changes on the NYXI controllers and send logs.