Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions dm/host/hle_hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,21 @@ HLE_FORCE("_ZN2nn3hid13GetJcmsStatesEPNS0_9JcmsStateEiRKNS0_10JcmsHandleE", "Joy
// hid::detail::GetJcmsState): with no sensor, a cleared state (sampling number 0, no movement, attributes 0: not connected)
HLE_FORCE("_ZN2nn3hid12GetJcmsStateEPNS0_9JcmsStateERKNS0_10JcmsHandleE", "Joy-Con mouse sensor state: the newest (cleared until a front end reports the sensor)",
void, h_hid_JcmsState, void *out, const uint32_t *h) { if (out) { memset(out, 0, 32); if (h) jcms_copy(out, 1, *h); } }
// A Switch 2 SDK's guard against a Home press made by accident on a controller (Drag x Drive turns it on for player 1's Joy-Con 2 as they connect, main+0x2c80c4). The SDK's own
// opens the hid service, which the host does not serve, and calls through the null session (sdk+0x63ce10). It sets a flag in hid and returns nothing; the host handles Home itself
// (home_quit.h), so the setting is logged
static _Atomic uint16_t g_home_protect; // the setting per npad (No 1-8, then Other, then Handheld), as the game left it; off until it turns it on
static int home_protect_bit(const uint32_t *id) { return !id ? -1 : *id < 8 ? (int)*id : *id == 0x10 ? 8 : *id == 0x20 ? 9 : -1; }
HLE_FORCE("_ZN2nn3hid41EnableUnintendedHomeButtonInputProtectionERKjb", "Home button protection: recorded and logged, the host handles Home itself", void, h_hid_HomeProtect,
const uint32_t *id, bool on) {
int b = home_protect_bit(id);
if (b >= 0) { if (on) atomic_fetch_or(&g_home_protect, (uint16_t)(1u << b)); else atomic_fetch_and(&g_home_protect, (uint16_t)~(1u << b)); }
LOG("hid: EnableUnintendedHomeButtonInputProtection npad %#x %s", id ? *id : 0xffffffffu, on ? "on" : "off");
}
// The question (Nintendo Switch Sports Resort asks it at boot): the SDK's own asks the hid service, which the host does not serve, and aborted on its error (Result 0x58cca at
// sdk+0x6ca40c). The answer is what the game set, off by default
HLE_FORCE("_ZN2nn3hid44IsUnintendedHomeButtonInputProtectionEnabledERKj", "Home button protection: what the game set (off by default)", bool, h_hid_HomeProtectOn,
const uint32_t *id) { int b = home_protect_bit(id); return b >= 0 && (atomic_load(&g_home_protect) >> b) & 1; }
// The system setting for the mouse pointer's speed (System Settings, Mouse): the default, 1
HLE_FORCE("_ZN2nn3hid25GetMousePointerSpeedScaleEv", "mouse pointer speed setting: the default, 1.0", float, h_hid_MouseSpeed, void) { return 1.0f; }
// The Switch 2's pointer on top of those sensors (Nmouse; Fire Emblem Fortune's Weave initializes it at boot with the 1920x1080 screen it maps the pointer to, main+0x650a24). InitializeNmouse opens the
Expand Down
10 changes: 10 additions & 0 deletions dm/host/tests/t_hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,16 @@ static void t_npads(void) {
CHECK(buttons_of(0, STYLE_FULLKEY) == DM_BTN_Y && lx_of(0) == 0, "player 1 does not see player 2");
CHECK(buttons_of(1, STYLE_HANDHELD) == 0, "player 2 is not a handheld controller");
CHECK(h_hid_Led(&(uint32_t){0}) == 0x1 && h_hid_Led(&(uint32_t){1}) == 0x3 && h_hid_Led(&(uint32_t){7}) == 0x6, "player LED patterns");
{ // Home button protection: what the game set, per npad, off by default (Nintendo Switch Sports Resort asks at boot)
uint32_t no1 = 0, no8 = 7, other = 0x10, handheld = 0x20, bad = 9;
CHECK(!h_hid_HomeProtectOn(&no1) && !h_hid_HomeProtectOn(&handheld), "Home protection starts off");
h_hid_HomeProtect(&no1, true); h_hid_HomeProtect(&handheld, true);
CHECK(h_hid_HomeProtectOn(&no1) && h_hid_HomeProtectOn(&handheld) && !h_hid_HomeProtectOn(&no8) && !h_hid_HomeProtectOn(&other), "on for the npads the game turned it on for");
h_hid_HomeProtect(&no1, false);
CHECK(!h_hid_HomeProtectOn(&no1) && h_hid_HomeProtectOn(&handheld), "off again for No1, Handheld kept");
h_hid_HomeProtect(&bad, true); CHECK(!h_hid_HomeProtectOn(&bad) && !h_hid_HomeProtectOn(NULL), "an id that is no npad: off");
h_hid_HomeProtect(&handheld, false);
}
int32_t info[2]; int8_t arg[8] = {1, 4};
CHECK(h_hid_ShowCtrl(info, arg) == RES_OK && info[0] == 2 && info[1] == 0, "the controller applet reports two players, player 1 selected");
CHECK(applet_opens == 1 && applet_depth == 0 && applet_closes_at_depth0 == 1, "the controller applet opens and closes once around its answer (focus 2, then 1)");
Expand Down
1 change: 1 addition & 0 deletions docs/agents/symptoms.md
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ One line per symptom in the [subsystem references](../reference/): what you see
- an abort connecting to `pl:u` at boot; a failed `nn::audio` call at boot. → [Built-in fonts and the audio device notification of SDK 21](../reference/services.md#built-in-fonts-and-the-audio-device-notification-of-sdk-21)
- an abort in `nn::hid` at boot, in a Switch 2 game that sets up the Joy-Con's mouse mode. → [The Joy-Con mouse pointer](../reference/services.md#the-joy-con-mouse-pointer)
- a Switch 2 game's mouse mode does nothing with Joy-Con 2s: its pointer stays still, or a game that offers its mouse modes only to Joy-Con 2 controllers finds none. → [The Joy-Con 2 mouse sensor and pointer](../reference/services.md#the-joy-con-2-mouse-sensor-and-pointer)
- a Switch 2 game crashes as a Joy-Con 2 joins: `[RED] sf: the game connects to service hid itself, which the host does not serve`, then `CRASH sig=11 addr=0` at `sdk+0x63ce10`, called from `nn::hid::EnableUnintendedHomeButtonInputProtection`. → [Home button protection on a Switch 2 controller](../reference/services.md#home-button-protection-on-a-switch-2-controller)
- a crash at boot in `nn::vi` under `nn::streamplay::CreateIndividualDisplays`. → [GameShare guest displays](../reference/services.md#gameshare-guest-displays)
- `[RED] sf: the game connects to service chat:u itself, which the host does not serve`, then `game called nn::diag abort: Result 0xe15` under `nn::chat::Initialize`. → [GameChat at boot](../reference/services.md#gamechat-at-boot)
- `CRASH sig=11 addr=0 pc=sdk+0x6be4d4` in `nn::chat::GetChattingUid()`, from the game's title screen code. → [GameChat queries from the title screen (SDK 21)](../reference/services.md#gamechat-queries-from-the-title-screen-sdk-21)
Expand Down
8 changes: 8 additions & 0 deletions docs/reference/services.md
Original file line number Diff line number Diff line change
Expand Up @@ -1100,6 +1100,14 @@ Most service calls can be found before they crash, before the first boot or the
- `DM_JCMS_LOG=1` logs the game's sensor and pointer calls, at most once a second each kind.
- **Found on:** Nintendo Switch 2 Welcome Tour (040057C02159A000; its note and profile are their own pull request): its cursor and its mouse exhibits, with a left and a right Joy-Con 2. `t_hid` checks the states, the handles and their order, and the styles.

### Home button protection on a Switch 2 controller

- **Symptom:** a Switch 2 game crashes as a Joy-Con 2 joins: `[RED] sf: the game connects to service hid itself, which the host does not serve`, then `CRASH sig=11 addr=0` at `sdk+0x63ce10`, called from `nn::hid::EnableUnintendedHomeButtonInputProtection`.
- **Cause:** `nn::hid::EnableUnintendedHomeButtonInputProtection(const NpadIdType&, bool)` turns on a guard against a Home press made by accident on that controller. It returns nothing; the SDK's own sets the flag through the hid service, which the host does not serve, and calls through the null session.
- **Fix:** the host answers it (`hle_hid.c`), records the setting per npad (No 1-8, Other, Handheld) and logs it (`hid: EnableUnintendedHomeButtonInputProtection npad 0 on`). The question, `IsUnintendedHomeButtonInputProtectionEnabled(const NpadIdType&)`, whose SDK function asks the service too, answers what the game set, off by default. The host handles the Home button itself ([home_quit.h](../../dm/host/home_quit.h)), so nothing else changes.
- **Found on:** Drag x Drive (040041601D83A000, v196608, SDK 20; no profile in the repository yet): 43 s in, as player 1's Joy-Con 2 pair joined (`main+0x2c80c4`). Nintendo Switch Sports Resort (`04008E001F098000`, v65536; no profile yet) asks the question at boot: the SDK's own aborted on its error (`Result 0x58cca` at `sdk+0x6ca40c`).
- **Check:** `make -C dm/host/tests GAME=<id> run` (`t_hid`).

### GameShare guest displays

- **Symptom:** a crash at boot in `nn::vi` under `nn::streamplay::CreateIndividualDisplays`.
Expand Down
Loading