From 5228768841a5256add9bd936d80464e36b4ceb3d Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 21 Nov 2019 12:01:14 -0800 Subject: [PATCH] ams_mitm: implement hid mitm --- .../source/hid_mitm/hid_mitm_service.cpp | 27 +++++ .../source/hid_mitm/hid_mitm_service.hpp | 14 ++- .../ams_mitm/source/hid_mitm/hid_shim.c | 27 +++++ .../ams_mitm/source/hid_mitm/hid_shim.h | 19 ++++ .../include/stratosphere/sf.hpp | 2 + .../stratosphere/sf/sf_mitm_dispatch.h | 100 ++++++++++++++++++ .../libstratosphere/source/sm/sm_ams.c | 15 ++- 7 files changed, 196 insertions(+), 8 deletions(-) create mode 100644 stratosphere/ams_mitm/source/hid_mitm/hid_mitm_service.cpp create mode 100644 stratosphere/ams_mitm/source/hid_mitm/hid_shim.c create mode 100644 stratosphere/ams_mitm/source/hid_mitm/hid_shim.h create mode 100644 stratosphere/libstratosphere/include/stratosphere/sf/sf_mitm_dispatch.h diff --git a/stratosphere/ams_mitm/source/hid_mitm/hid_mitm_service.cpp b/stratosphere/ams_mitm/source/hid_mitm/hid_mitm_service.cpp new file mode 100644 index 000000000..5d21f4a2e --- /dev/null +++ b/stratosphere/ams_mitm/source/hid_mitm/hid_mitm_service.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "hid_mitm_service.hpp" +#include "hid_shim.h" + +namespace ams::mitm::hid { + + Result HidMitmService::SetSupportedNpadStyleSet(const sf::ClientAppletResourceUserId &client_aruid, u32 style_set) { + /* This code applies only to hbl, guaranteed by the check in ShouldMitm. */ + style_set |= TYPE_SYSTEM | TYPE_SYSTEM_EXT; + return hidSetSupportedNpadStyleSetFwd(this->forward_service.get(), static_cast(this->client_info.process_id), static_cast(client_aruid.GetValue()), static_cast(style_set)); + } + +} diff --git a/stratosphere/ams_mitm/source/hid_mitm/hid_mitm_service.hpp b/stratosphere/ams_mitm/source/hid_mitm/hid_mitm_service.hpp index 9e2a684e2..3ca28a5b4 100644 --- a/stratosphere/ams_mitm/source/hid_mitm/hid_mitm_service.hpp +++ b/stratosphere/ams_mitm/source/hid_mitm/hid_mitm_service.hpp @@ -22,20 +22,24 @@ namespace ams::mitm::hid { class HidMitmService : public sf::IMitmServiceObject { private: enum class CommandId { - /* TODO */ + SetSupportedNpadStyleSet = 100, }; public: static bool ShouldMitm(const sm::MitmProcessInfo &client_info) { - /* TODO */ - return false; + /* TODO: Remove in Atmosphere 0.10.1. */ + /* We will mitm: + * - hbl, to help homebrew not need to be recompiled. + */ + return client_info.override_status.IsHbl(); } public: SF_MITM_SERVICE_OBJECT_CTOR(HidMitmService) { /* ... */ } protected: - /* TODO */ + /* Overridden commands. */ + Result SetSupportedNpadStyleSet(const sf::ClientAppletResourceUserId &client_aruid, u32 style_set); public: DEFINE_SERVICE_DISPATCH_TABLE { - /* TODO */ + MAKE_SERVICE_COMMAND_META(SetSupportedNpadStyleSet), }; }; diff --git a/stratosphere/ams_mitm/source/hid_mitm/hid_shim.c b/stratosphere/ams_mitm/source/hid_mitm/hid_shim.c new file mode 100644 index 000000000..576b21d0b --- /dev/null +++ b/stratosphere/ams_mitm/source/hid_mitm/hid_shim.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "hid_shim.h" +#include + +/* Command forwarders. */ +Result hidSetSupportedNpadStyleSetFwd(Service* s, u64 process_id, u64 aruid, HidControllerType type) { + const struct { + u32 type; + u32 pad; + u64 aruid; + } in = { type, 0, aruid }; + return serviceMitmDispatchIn(s, 100, in, .in_send_pid = true, .override_pid = process_id); +} diff --git a/stratosphere/ams_mitm/source/hid_mitm/hid_shim.h b/stratosphere/ams_mitm/source/hid_mitm/hid_shim.h new file mode 100644 index 000000000..6a16f8fc5 --- /dev/null +++ b/stratosphere/ams_mitm/source/hid_mitm/hid_shim.h @@ -0,0 +1,19 @@ +/** + * @file hid_shim.h + * @brief Human Interface Devices Services (hid) IPC wrapper. + * @author SciresM + * @copyright libnx Authors + */ +#pragma once +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Command forwarders. */ +Result hidSetSupportedNpadStyleSetFwd(Service* s, u64 process_id, u64 aruid, HidControllerType type); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/sf.hpp b/stratosphere/libstratosphere/include/stratosphere/sf.hpp index 7c7a52811..c37ef3aad 100644 --- a/stratosphere/libstratosphere/include/stratosphere/sf.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/sf.hpp @@ -25,3 +25,5 @@ #include "sf/impl/sf_impl_command_serialization.hpp" #include "sf/hipc/sf_hipc_server_manager.hpp" + +#include "sf/sf_mitm_dispatch.h" diff --git a/stratosphere/libstratosphere/include/stratosphere/sf/sf_mitm_dispatch.h b/stratosphere/libstratosphere/include/stratosphere/sf/sf_mitm_dispatch.h new file mode 100644 index 000000000..17e567db5 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/sf/sf_mitm_dispatch.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + Handle target_session; + u32 context; + + SfBufferAttrs buffer_attrs; + SfBuffer buffers[8]; + + bool in_send_pid; + + u32 in_num_objects; + const Service* in_objects[8]; + + u32 in_num_handles; + Handle in_handles[8]; + + u32 out_num_objects; + Service* out_objects; + + SfOutHandleAttrs out_handle_attrs; + Handle* out_handles; + + u64 override_pid; +} SfMitmDispatchParams; + +NX_INLINE Result serviceMitmDispatchImpl( + Service* s, u32 request_id, + const void* in_data, u32 in_data_size, + void* out_data, u32 out_data_size, + SfMitmDispatchParams disp +) +{ + // Make a copy of the service struct, so that the compiler can assume that it won't be modified by function calls. + Service srv = *s; + + void* in = serviceMakeRequest(&srv, request_id, disp.context, + in_data_size, disp.in_send_pid, + disp.buffer_attrs, disp.buffers, + disp.in_num_objects, disp.in_objects, + disp.in_num_handles, disp.in_handles); + + if (in_data_size) + __builtin_memcpy(in, in_data, in_data_size); + + if (disp.in_send_pid && disp.override_pid) { + const u64 pid = (disp.override_pid & 0x0000FFFFFFFFFFFFul) | 0xFFFE000000000000ul; + __builtin_memcpy((u8 *)armGetTls() + 0xC, &pid, sizeof(pid)); + } + + Result rc = svcSendSyncRequest(disp.target_session == INVALID_HANDLE ? s->session : disp.target_session); + if (R_SUCCEEDED(rc)) { + void* out = NULL; + rc = serviceParseResponse(&srv, + out_data_size, &out, + disp.out_num_objects, disp.out_objects, + disp.out_handle_attrs, disp.out_handles); + + if (R_SUCCEEDED(rc) && out_data && out_data_size) + __builtin_memcpy(out_data, out, out_data_size); + } + + return rc; +} + +#define serviceMitmDispatch(_s,_rid,...) \ + serviceMitmDispatchImpl((_s),(_rid),NULL,0,NULL,0,(SfMitmDispatchParams){ __VA_ARGS__ }) + +#define serviceMitmDispatchIn(_s,_rid,_in,...) \ + serviceMitmDispatchImpl((_s),(_rid),&(_in),sizeof(_in),NULL,0,(SfMitmDispatchParams){ __VA_ARGS__ }) + +#define serviceMitmDispatchOut(_s,_rid,_out,...) \ + serviceMitmDispatchImpl((_s),(_rid),NULL,0,&(_out),sizeof(_out),(SfMitmDispatchParams){ __VA_ARGS__ }) + +#define serviceMitmDispatchInOut(_s,_rid,_in,_out,...) \ + serviceMitmDispatchImpl((_s),(_rid),&(_in),sizeof(_in),&(_out),sizeof(_out),(SfMitmDispatchParams){ __VA_ARGS__ }) + +#ifdef __cplusplus +} +#endif diff --git a/stratosphere/libstratosphere/source/sm/sm_ams.c b/stratosphere/libstratosphere/source/sm/sm_ams.c index ac606e672..ababf1e07 100644 --- a/stratosphere/libstratosphere/source/sm/sm_ams.c +++ b/stratosphere/libstratosphere/source/sm/sm_ams.c @@ -114,9 +114,18 @@ Result smAtmosphereMitmAcknowledgeSession(Service *srv_out, void *_out, SmServic u64 keys_held; u64 flags; } *out = _out; + _Static_assert(sizeof(*out) == 0x20, "sizeof(*out) == 0x20"); - return serviceDispatchInOut(&g_smAtmosphereMitmSrv, 65003, name, *out, - .out_num_objects = 1, - .out_objects = srv_out, + Handle tmp_handle; + + Result rc = serviceDispatchInOut(&g_smAtmosphereMitmSrv, 65003, name, *out, + .out_handle_attrs = { SfOutHandleAttr_HipcMove }, + .out_handles = &tmp_handle, ); + + if (R_SUCCEEDED(rc)) { + serviceCreate(srv_out, tmp_handle); + } + + return rc; }