Repository navigation
Mac: identical pads that GameController lists as one are each a player of their own (issue #1218) - #1595
Closed
elieteyssedou wants to merge 4 commits into
Closed
Mac: identical pads that GameController lists as one are each a player of their own (issue #1218)#1595elieteyssedou wants to merge 4 commits into
elieteyssedou wants to merge 4 commits into
Conversation
…says YES a5281d0 skipped every HID pad for which +[GCController supportsHIDDevice:] answers YES. It answers YES for the 8BitDo Ultimate 2C Wireless (2dc8:301b), which GameController then never lists, so the pad got no input from either path (seedds#637 again). The call is now made only for Microsoft, Sony and Nintendo pads, the vendors GameController does list; other vendors are read as HID.
… and is read as HID if it never comes +[GCController supportsHIDDevice:] is only a hint: it answers YES for the 8BitDo Ultimate 2C (2dc8:301b), which GameController then never lists (GitHub issue seedds#965). A device it says YES for now waits HIDPAD_GC_WAIT seconds for a GCController of its name; without one it is read as HID, and dropped again if that GCController connects later. A device it says NO for is read at once, as before. This replaces the Microsoft, Sony and Nintendo vendor list, so a pad of another vendor that GameController does list is not read twice.
# Conflicts: # dm/host/front_mac.m
… are each a player of their own (issue seedds#1218) Two Pro Controllers over USB are listed as one by GameController. When IOKit has at least two pads of a model and more than GameController lists, after a 3 s wait, every pad of that model is read here, by USB location, each a player of its own: - a Switch Pro Controller from its report 0x30 (pad_pro.h), with its gyro, and its sticks from its own calibration in SPI flash (the user's, else the factory's), asked with subcommand 0x10; until it answers, or if it never does, each axis measures its rest and reach itself; - any other model from its HID elements as pad_hid.h reads them: no gyro, 8BitDo's button numbering unless DM_HID_MAP says otherwise. Built on seedds#859: the devices GameController lists are now kept, unread, to count them. GameController gives a controller no HID identity, so its controllers of such a model are left unread rather than read twice. DM_PAD_IDENTICAL=0 turns it off. No rumble or player lights on such pads, and Home does not quit from them. Tests: t_pad_pro (report 0x30, the SPI read, both calibrations), t_pad_hid (when a model is read here). Run: Mario Kart World 1.8.0 on an M4 Pro (macOS 27), 33 min of split-screen races, two Pro Controllers over USB, which GameController lists as one: each was a player of its own, each with its own calibration (one the factory's, one the user's), read over USB and over Bluetooth; two Xbox controllers over Bluetooth, which GameController lists both, joined as players 3 and 4 while the game ran. A duplicate player found in that run (GameController's own Pro Controller also joining) is fixed here; the fix builds and the unit tests pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 tasks done
seedds
added a commit
that referenced
this pull request
Nov 7, 2026
… are each a player of their own, two Pro Controllers over USB among them (PR #1595) GameController lists two Switch Pro Controllers over USB as one, so a two-player game refused them. pad_hid_mac.h now keeps the devices GameController reads, unread, to count IOKit's pads of each model (vendor and product ID) against GameController's controllers of it: a Pro Controller's by product category, another model's by name. When IOKit has at least two of a model and more than GameController lists, after a 3 s wait (pad_dupes_want), every pad of that model is read there, a player each, by USB location: a Pro Controller from its report 0x30 (pad_pro.h) with its gyro and its own stick calibration from SPI flash, another model from its HID elements. front_mac.m leaves GameController's controllers of that model unread. When GameController lists them all again they go back to it. Reworked from the PR: one mechanism on pad_hid_mac.h's own HID manager instead of a Pro Controller path on motion_pro_mac.h's manager beside a path for other models, so DM_MOTION=0 / DM_MOTION_HID=0 turn off only the gyro and no longer bring the bug back, and motion_pro_mac.h is unchanged. Microsoft's, Sony's and Nintendo's other pads are never read this way: their names do not match GameController's (a DualShock 4 is "Wireless Controller"), so two of them would have been read twice. DM_PAD_IDENTICAL=0 or DM_HID_PADS=0 turn it off. No rumble, player lights or Home quit on such pads. Tests: t_pad_pro (report 0x30, the SPI read, both calibrations), t_pad_hid (pad_dupes_want); host tests pass. The PR's version ran 33 minutes of Mario Kart World 1.8.0 split-screen with two Pro Controllers over USB; the reworked version awaits a run with real pads. Fixes #1218 Co-authored-by: Elie <8143621+elieteyssedou@users.noreply.github.com>
Owner
|
Landed in 1ed28ed, reworked, with you credited as co-author. Thanks, the diagnosis and the decoder made this easy. What changed from the PR:
The reworked version builds and the host tests pass, but it hasn't run on real pads; I have no Pro Controllers here. Could you run two Pro Controllers over USB on current main, and check that each is a player of its own with its calibration? The log lines are now #1596 is next: I'll check it on top of this. |
seedds
added a commit
that referenced
this pull request
Nov 8, 2026
…once per matching dictionary it meets, so the HID reader knows a pad by its I/O Registry entry, not by its IOHIDDeviceRef (PR #1722) A Pro Controller meets both the GamePad usage dictionary and the vendor / product one added for identical pads (PR #1595), and each match came as a new IOHIDDeviceRef for the same registry entry. hidpad_found compared references only, so one pad counted as two of its model against GameController's one controller: both were read as twins, players 1 and 2. A one-player game then opened the controller applet every few frames, and The Legend of Zelda: Ocarina of Time, which suspends its music while an applet has focus, played no area or cutscene music. Co-authored-by: Ludovic LEMARINEL - Adesin.fr <10656218+LudovicLemarinel@users.noreply.github.com>
dandelion711
pushed a commit
to dandelion711/nxnative
that referenced
this pull request
Nov 8, 2026
…once per matching dictionary it meets, so the HID reader knows a pad by its I/O Registry entry, not by its IOHIDDeviceRef (PR seedds#1722) A Pro Controller meets both the GamePad usage dictionary and the vendor / product one added for identical pads (PR seedds#1595), and each match came as a new IOHIDDeviceRef for the same registry entry. hidpad_found compared references only, so one pad counted as two of its model against GameController's one controller: both were read as twins, players 1 and 2. A one-player game then opened the controller applet every few frames, and The Legend of Zelda: Ocarina of Time, which suspends its music while an applet has focus, played no area or cutscene music. Co-authored-by: Ludovic LEMARINEL - Adesin.fr <10656218+LudovicLemarinel@users.noreply.github.com>
Know-It-All-Brother
pushed a commit
to Know-It-All-Brother/nxnative
that referenced
this pull request
Nov 9, 2026
… are each a player of their own, two Pro Controllers over USB among them (PR seedds#1595) GameController lists two Switch Pro Controllers over USB as one, so a two-player game refused them. pad_hid_mac.h now keeps the devices GameController reads, unread, to count IOKit's pads of each model (vendor and product ID) against GameController's controllers of it: a Pro Controller's by product category, another model's by name. When IOKit has at least two of a model and more than GameController lists, after a 3 s wait (pad_dupes_want), every pad of that model is read there, a player each, by USB location: a Pro Controller from its report 0x30 (pad_pro.h) with its gyro and its own stick calibration from SPI flash, another model from its HID elements. front_mac.m leaves GameController's controllers of that model unread. When GameController lists them all again they go back to it. Reworked from the PR: one mechanism on pad_hid_mac.h's own HID manager instead of a Pro Controller path on motion_pro_mac.h's manager beside a path for other models, so DM_MOTION=0 / DM_MOTION_HID=0 turn off only the gyro and no longer bring the bug back, and motion_pro_mac.h is unchanged. Microsoft's, Sony's and Nintendo's other pads are never read this way: their names do not match GameController's (a DualShock 4 is "Wireless Controller"), so two of them would have been read twice. DM_PAD_IDENTICAL=0 or DM_HID_PADS=0 turn it off. No rumble, player lights or Home quit on such pads. Tests: t_pad_pro (report 0x30, the SPI read, both calibrations), t_pad_hid (pad_dupes_want); host tests pass. The PR's version ran 33 minutes of Mario Kart World 1.8.0 split-screen with two Pro Controllers over USB; the reworked version awaits a run with real pads. Fixes seedds#1218 Co-authored-by: Elie <8143621+elieteyssedou@users.noreply.github.com>
Know-It-All-Brother
pushed a commit
to Know-It-All-Brother/nxnative
that referenced
this pull request
Nov 9, 2026
…once per matching dictionary it meets, so the HID reader knows a pad by its I/O Registry entry, not by its IOHIDDeviceRef (PR seedds#1722) A Pro Controller meets both the GamePad usage dictionary and the vendor / product one added for identical pads (PR seedds#1595), and each match came as a new IOHIDDeviceRef for the same registry entry. hidpad_found compared references only, so one pad counted as two of its model against GameController's one controller: both were read as twins, players 1 and 2. A one-player game then opened the controller applet every few frames, and The Legend of Zelda: Ocarina of Time, which suspends its music while an applet has focus, played no area or cutscene music. Co-authored-by: Ludovic LEMARINEL - Adesin.fr <10656218+LudovicLemarinel@users.noreply.github.com>
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.
What and why
Fixes #1218. Builds on #859: its commits come first in this branch until it lands. #1534 does the same as #859; if that one lands instead, this moves onto it.
Two Switch Pro Controllers over USB play as one player on the Mac: GameController lists one controller, IOKit has both devices, and their USB serial numbers match (over Bluetooth both are listed). GameController gives a controller no HID identity, so its one controller cannot be tied to one of the two devices.
In
dm/host:pad_hid_mac.hkeeps the devices GameController lists (g_hidpads_gc), unread, instead of dropping them, so that the pads of each model can be counted, by name (vendorNameis the HID product string, as Mac: a HID pad GameController says it lists waits two seconds for it, and is read as HID if it never comes #859 matches them).front_mac.m: when IOKit has at least two pads of a model and more than GameController lists, after a 3 s wait for a pad not listed yet (pad_dupes_want,pad_hid.h), every pad of that model is read here, a player each, by USB location. GameController's controllers of that model are left unread. When GameController lists them all again, they go back to it.0x30(pad_pro.h), with its motion throughmotion_pro_mac.h; any other model from its HID elements, aspad_hid.hreads them.0x10: the user's at0x8010when its magic is there, else the factory's at0x603D). Without an answer, each axis measures its own rest and reach.DM_PAD_IDENTICAL=0turns it off.Limits: such pads have no rumble or player lights, and Home does not quit from them. Another model's buttons follow 8BitDo's numbering unless
DM_HID_MAPsays otherwise; only Pro Controllers were run this way.Checked
make -C dm/host/tests GAME=0400C3F00006E000 runpasses:t_pad_pro55 checks (report0x30, the SPI read, both calibrations),t_pad_hid27 (when a model is read here).dm/tools/tests/test_docs.pypasses.front_mac.mcompiles with-Wall -Wextrawith no new warning.0400C3F00006E000) 1.8.0 as a Mac app, 33 minutes of two-player split-screen races, from a local build that also carried Indirect-count multi-draws are copied when their pass opens: Mario Kart World's scene passes are no longer split for them #1179, Mario Kart World 1.8.0: image slots in the dimension the shader declares, and Ampere's fragment depth register #1292 and host/vi: HDR output for Switch 2 games on screens that can show EDR #1176:Pro Controllers: GameController lists 1 of 2: reading them all from their HID reports; two players; one pad took its factory calibration, the other the user'sscripts/regress.py: not run; the change is in the host's controller input only, with no shader, rendering or tool change.Docs
docs/reference/services.md: Identical controllers that GameController lists as one;python3 dm/tools/docs_symptoms.pyrundocs/playing.md,docs/env_switches.tsv🤖 Generated with Claude Code