diff --git a/README.md b/README.md index b998b0da..78aab911 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ Use controllers from other consoles natively on your Nintendo Switch via Bluetoo * __Sony Dualsense Controller__ * __Microsoft Xbox One S/X Controller (not to be confused with Series S/X controllers - these use Bluetooth LE, which isn't currently supported)__* * __Microsoft Xbox Elite Wireless Controller Series 2__ -* __NVidia Shield Controller(2017 Model)__ +* __NVidia Shield Controller (2017 Model)__ * __Ouya Controller__ * __Gamestick Controller__ * __Gembox Controller__ @@ -78,7 +78,7 @@ Use controllers from other consoles natively on your Nintendo Switch via Bluetoo Download the [latest release](https://github.com/ndeadly/MissionControl/releases) .zip and extract to the root of your SD card, allowing the folders to merge and overwriting any existing files. A console reboot is required in order for Mission Control to become active. ***IMPORTANT: -Atmosphère >= 1.1.0 is required to run the latest release of Mission Control. Using an older Atmosphère version will cause Mission Control to crash the system on boot. +Atmosphère >= 1.2.0 is required to run the latest release of Mission Control. Using an older Atmosphère version will cause Mission Control to crash or freeze the system on boot. Users upgrading from version 0.1.0 of Mission Control are also advised to wipe their pairing database and re-pair controllers running the latest version. Failure to wipe the old entries may result in non-switch controllers being detected incorrectly.*** ### Usage diff --git a/exefs_patches/bluetooth_patches/E9A6DBF13FE4A6833606A834C7BA1B44F4DDD60F.ips b/exefs_patches/bluetooth_patches/E9A6DBF13FE4A6833606A834C7BA1B44F4DDD60F.ips new file mode 100644 index 00000000..5d00d6a7 Binary files /dev/null and b/exefs_patches/bluetooth_patches/E9A6DBF13FE4A6833606A834C7BA1B44F4DDD60F.ips differ diff --git a/lib/Atmosphere-libs b/lib/Atmosphere-libs index cf765c09..13c6987c 160000 --- a/lib/Atmosphere-libs +++ b/lib/Atmosphere-libs @@ -1 +1 @@ -Subproject commit cf765c0946cc5c828364ae6bfccddc4041304f28 +Subproject commit 13c6987cc43d0b9a874e87e3ce8eaffd1c72fa69 diff --git a/lib/libnx b/lib/libnx index b5714296..93db7abb 160000 --- a/lib/libnx +++ b/lib/libnx @@ -1 +1 @@ -Subproject commit b5714296d6bc2b5a014942ac88e2f72ca7658a8c +Subproject commit 93db7abb032823747d9760426401dc05693afd21 diff --git a/mc_mitm/source/bluetooth_mitm/bluetooth/bluetooth_hid_report.cpp b/mc_mitm/source/bluetooth_mitm/bluetooth/bluetooth_hid_report.cpp index a164f4ac..0cdf8caf 100644 --- a/mc_mitm/source/bluetooth_mitm/bluetooth/bluetooth_hid_report.cpp +++ b/mc_mitm/source/bluetooth_mitm/bluetooth/bluetooth_hid_report.cpp @@ -43,8 +43,8 @@ namespace ams::bluetooth::hid::report { os::Event g_init_event(os::EventClearMode_ManualClear); os::Event g_report_read_event(os::EventClearMode_AutoClear); - SharedMemory g_real_bt_shmem; - SharedMemory g_fake_bt_shmem; + os::SharedMemory g_real_bt_shmem; + os::SharedMemory g_fake_bt_shmem(bluetooth_sharedmem_size, os::MemoryPermission_ReadWrite, os::MemoryPermission_ReadWrite); bluetooth::CircularBuffer *g_real_buffer; bluetooth::CircularBuffer *g_fake_buffer; @@ -75,14 +75,14 @@ namespace ams::bluetooth::hid::report { g_report_read_event.Signal(); } - SharedMemory *GetRealSharedMemory(void) { + os::SharedMemory *GetRealSharedMemory(void) { if (hos::GetVersion() < hos::Version_7_0_0) return nullptr; return &g_real_bt_shmem; } - SharedMemory *GetFakeSharedMemory(void) { + os::SharedMemory *GetFakeSharedMemory(void) { return &g_fake_bt_shmem; } @@ -98,7 +98,7 @@ namespace ams::bluetooth::hid::report { return &g_system_event_user_fwd; } - Result Initialize(Handle event_handle, Service *forward_service, os::ThreadId main_thread_id) { + Result Initialize(os::NativeHandle event_handle, Service *forward_service, os::ThreadId main_thread_id) { g_system_event.AttachReadableHandle(event_handle, false, os::EventClearMode_AutoClear); R_TRY(os::CreateThread(&g_event_handler_thread, @@ -123,19 +123,17 @@ namespace ams::bluetooth::hid::report { os::DestroyThread(&g_event_handler_thread); } - Result MapRemoteSharedMemory(Handle handle) { - shmemLoadRemote(&g_real_bt_shmem, handle, bluetooth_sharedmem_size, Perm_Rw); - R_TRY(shmemMap(&g_real_bt_shmem)); - g_real_buffer = reinterpret_cast(shmemGetAddr(&g_real_bt_shmem)); + Result MapRemoteSharedMemory(os::NativeHandle handle) { + g_real_bt_shmem.Attach(bluetooth_sharedmem_size, handle, true); + g_real_bt_shmem.Map(os::MemoryPermission_ReadWrite); + g_real_buffer = reinterpret_cast(g_real_bt_shmem.GetMappedAddress()); return ams::ResultSuccess(); } Result InitializeReportBuffer(void) { - R_TRY(shmemCreate(&g_fake_bt_shmem, bluetooth_sharedmem_size, Perm_Rw, Perm_Rw)); - R_TRY(shmemMap(&g_fake_bt_shmem)); - g_fake_buffer = reinterpret_cast(shmemGetAddr(&g_fake_bt_shmem)); - + g_fake_bt_shmem.Map(os::MemoryPermission_ReadWrite); + g_fake_buffer = reinterpret_cast(g_fake_bt_shmem.GetMappedAddress()); g_fake_buffer->Initialize("HID Report"); g_fake_buffer->type = bluetooth::CircularBufferType_HidReport; g_fake_buffer->_unk3 = 1; diff --git a/mc_mitm/source/bluetooth_mitm/bluetooth/bluetooth_hid_report.hpp b/mc_mitm/source/bluetooth_mitm/bluetooth/bluetooth_hid_report.hpp index 192164fd..a898366f 100644 --- a/mc_mitm/source/bluetooth_mitm/bluetooth/bluetooth_hid_report.hpp +++ b/mc_mitm/source/bluetooth_mitm/bluetooth/bluetooth_hid_report.hpp @@ -24,17 +24,17 @@ namespace ams::bluetooth::hid::report { void WaitInitialized(void); void SignalReportRead(void); - SharedMemory *GetRealSharedMemory(void); - SharedMemory *GetFakeSharedMemory(void); + os::SharedMemory *GetRealSharedMemory(void); + os::SharedMemory *GetFakeSharedMemory(void); os::SystemEvent *GetSystemEvent(void); os::SystemEvent *GetForwardEvent(void); os::SystemEvent *GetUserForwardEvent(void); - Result Initialize(Handle event_handle, Service *forward_service, os::ThreadId main_thread_id); + Result Initialize(os::NativeHandle event_handle, Service *forward_service, os::ThreadId main_thread_id); void Finalize(void); - Result MapRemoteSharedMemory(Handle handle); + Result MapRemoteSharedMemory(os::NativeHandle handle); Result InitializeReportBuffer(void); Result WriteHidReportBuffer(const bluetooth::Address *address, const bluetooth::HidReport *report); diff --git a/mc_mitm/source/bluetooth_mitm/btdrv_mitm_service.cpp b/mc_mitm/source/bluetooth_mitm/btdrv_mitm_service.cpp index d0914c61..84ed6443 100644 --- a/mc_mitm/source/bluetooth_mitm/btdrv_mitm_service.cpp +++ b/mc_mitm/source/bluetooth_mitm/btdrv_mitm_service.cpp @@ -202,7 +202,7 @@ namespace ams::mitm::bluetooth { os::NativeHandle handle = os::InvalidNativeHandle; R_TRY(btdrvGetHidReportEventInfoFwd(m_forward_service.get(), &handle)); R_TRY(ams::bluetooth::hid::report::MapRemoteSharedMemory(handle)); - out_handle.SetValue(ams::bluetooth::hid::report::GetFakeSharedMemory()->handle, false); + out_handle.SetValue(ams::bluetooth::hid::report::GetFakeSharedMemory()->GetHandle(), false); return ams::ResultSuccess(); } @@ -243,12 +243,12 @@ namespace ams::mitm::bluetooth { } Result BtdrvMitmService::GetRealSharedMemory(sf::OutCopyHandle out_handle) { - out_handle.SetValue(ams::bluetooth::hid::report::GetRealSharedMemory()->handle, false); + out_handle.SetValue(ams::bluetooth::hid::report::GetRealSharedMemory()->GetHandle(), false); return ams::ResultSuccess(); } Result BtdrvMitmService::GetFakeSharedMemory(sf::OutCopyHandle out_handle) { - out_handle.SetValue(ams::bluetooth::hid::report::GetFakeSharedMemory()->handle, false); + out_handle.SetValue(ams::bluetooth::hid::report::GetFakeSharedMemory()->GetHandle(), false); return ams::ResultSuccess(); } diff --git a/mc_mitm/source/controllers/emulated_switch_controller.cpp b/mc_mitm/source/controllers/emulated_switch_controller.cpp index c7788f5e..e795d1e1 100644 --- a/mc_mitm/source/controllers/emulated_switch_controller.cpp +++ b/mc_mitm/source/controllers/emulated_switch_controller.cpp @@ -28,6 +28,9 @@ namespace ams::controller { SwitchAnalogStickFactoryCalibration lstick_factory_calib = {0xff, 0xf7, 0x7f, 0x00, 0x08, 0x80, 0x00, 0x08, 0x80}; SwitchAnalogStickFactoryCalibration rstick_factory_calib = {0x00, 0x08, 0x80, 0x00, 0x08, 0x80, 0xff, 0xf7, 0x7f}; + // Stick parameters data that produce a 12.5% inner deadzone and a 5% outer deadzone (in relation to the full 12 bit range above) + SwitchAnalogStickParameters default_stick_params = {0x0f, 0x30, 0x61, 0x00, 0x31, 0xf3, 0xd4, 0x14, 0x54, 0x41, 0x15, 0x54, 0xc7, 0x79, 0x9c, 0x33, 0x36, 0x63}; + // Frequency in Hz rounded to nearest int // https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/rumble_data_table.md#frequency-table const uint16_t rumble_freq_lut[] = { @@ -118,6 +121,12 @@ namespace ams::controller { } data2 = { {0x32, 0x32, 0x32}, {0xe6, 0xe6, 0xe6}, {0x46, 0x46, 0x46}, {0x46, 0x46, 0x46} }; R_TRY(fs::WriteFile(file, 0x6050, &data2, sizeof(data2), fs::WriteOption::None)); + const struct { + SwitchAnalogStickParameters lstick_default_parameters; + SwitchAnalogStickParameters rstick_default_parameters; + } data3 = { default_stick_params, default_stick_params }; + R_TRY(fs::WriteFile(file, 0x6086, &data3, sizeof(data3), fs::WriteOption::None)); + R_TRY(fs::FlushFile(file)); return ams::ResultSuccess(); @@ -147,6 +156,8 @@ namespace ams::controller { } Result EmulatedSwitchController::Initialize(void) { + SwitchController::Initialize(); + char path[0x100] = {}; // Ensure config directory for this controller exists diff --git a/mc_mitm/source/controllers/lanshen_controller.hpp b/mc_mitm/source/controllers/lanshen_controller.hpp index 0cfb3be0..9c90e9e9 100644 --- a/mc_mitm/source/controllers/lanshen_controller.hpp +++ b/mc_mitm/source/controllers/lanshen_controller.hpp @@ -82,6 +82,8 @@ namespace ams::controller { LanShenController(const bluetooth::Address *address, HardwareID id) : EmulatedSwitchController(address, id) { } + bool SupportsSetTsiCommand(void) { return false; } + void UpdateControllerState(const bluetooth::HidReport *report); private: diff --git a/mc_mitm/source/controllers/switch_analog_stick.hpp b/mc_mitm/source/controllers/switch_analog_stick.hpp index 27d797f0..9aff881c 100644 --- a/mc_mitm/source/controllers/switch_analog_stick.hpp +++ b/mc_mitm/source/controllers/switch_analog_stick.hpp @@ -29,7 +29,7 @@ namespace ams::controller { uint16_t GetY(void); void InvertX(void); void InvertY(void); - + uint8_t m_xy[3]; }; @@ -37,4 +37,8 @@ namespace ams::controller { uint8_t calib[9]; }; + struct SwitchAnalogStickParameters { + uint8_t stickvalues[18]; + }; + } diff --git a/mc_mitm/source/controllers/switch_controller.cpp b/mc_mitm/source/controllers/switch_controller.cpp index f187ccea..7b9813d6 100644 --- a/mc_mitm/source/controllers/switch_controller.cpp +++ b/mc_mitm/source/controllers/switch_controller.cpp @@ -14,6 +14,8 @@ * along with this program. If not, see . */ #include "switch_controller.hpp" +#include "../utils.hpp" +#include namespace ams::controller { @@ -48,9 +50,40 @@ namespace ams::controller { return ams::ResultSuccess(); } + std::string GetControllerDirectory(const bluetooth::Address *address) { + char path[0x100]; + util::SNPrintf(path, sizeof(path), "sdmc:/config/MissionControl/controllers/%02x%02x%02x%02x%02x%02x", + address->address[0], + address->address[1], + address->address[2], + address->address[3], + address->address[4], + address->address[5] + ); + return path; + } + bluetooth::HidReport SwitchController::s_input_report; bluetooth::HidReport SwitchController::s_output_report; + Result SwitchController::Initialize(void) { + if (this->HasSetTsiDisableFlag()) + m_settsi_supported = false; + + return ams::ResultSuccess(); + } + + bool SwitchController::HasSetTsiDisableFlag(void) { + std::string flag_file = GetControllerDirectory(&m_address) + "/settsi_disable.flag"; + + bool file_exists; + if (R_SUCCEEDED(fs::HasFile(&file_exists, flag_file.c_str()))) { + return file_exists; + } + + return false; + } + Result SwitchController::HandleIncomingReport(const bluetooth::HidReport *report) { s_input_report.size = report->size; std::memcpy(s_input_report.data, report->data, report->size); diff --git a/mc_mitm/source/controllers/switch_controller.hpp b/mc_mitm/source/controllers/switch_controller.hpp index de5e9e35..7ca60447 100644 --- a/mc_mitm/source/controllers/switch_controller.hpp +++ b/mc_mitm/source/controllers/switch_controller.hpp @@ -267,25 +267,31 @@ namespace ams::controller { SwitchController(const bluetooth::Address *address, HardwareID id) : m_address(*address) - , m_id(id) { } + , m_id(id) + , m_settsi_supported(true) { } virtual ~SwitchController() { }; const bluetooth::Address& Address(void) const { return m_address; } virtual bool IsOfficialController(void) { return true; } - virtual bool SupportsSetTsiCommand(void) { return true; } + virtual bool SupportsSetTsiCommand(void) { return m_settsi_supported; } - virtual Result Initialize(void) { return ams::ResultSuccess(); } + virtual Result Initialize(void); virtual Result HandleIncomingReport(const bluetooth::HidReport *report); virtual Result HandleOutgoingReport(const bluetooth::HidReport *report); + private: + bool HasSetTsiDisableFlag(void); + protected: virtual void ApplyButtonCombos(SwitchButtonData *buttons); bluetooth::Address m_address; HardwareID m_id; + bool m_settsi_supported; + static bluetooth::HidReport s_input_report; static bluetooth::HidReport s_output_report; };