diff --git a/.gitignore b/.gitignore index a22ffe4c..f100f7a1 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ .patches/ tests/ dist/ -btdrv-mitm/build/ +bluetooth-mitm/build/ *.log *.elf *.nro diff --git a/.gitmodules b/.gitmodules index 4b88dc3c..5a56d773 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,6 +7,3 @@ [submodule "borealis"] path = borealis url = https://github.com/natinusala/borealis.git -[submodule "Atmosphere"] - path = Atmosphere - url = https://github.com/ndeadly/Atmosphere.git diff --git a/Atmosphere b/Atmosphere deleted file mode 160000 index 18d59e34..00000000 --- a/Atmosphere +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 18d59e341e1238a5182df81112074ca97f8628b5 diff --git a/Atmosphere-libs b/Atmosphere-libs index 2d522dc6..04ef9bf8 160000 --- a/Atmosphere-libs +++ b/Atmosphere-libs @@ -1 +1 @@ -Subproject commit 2d522dc6a12b2eb5eb3f103a8c5b5126ca301b1a +Subproject commit 04ef9bf8981044b0d7987cce01db4b77bd00b0cc diff --git a/Makefile b/Makefile index fcf905aa..a9eda1b3 100644 --- a/Makefile +++ b/Makefile @@ -1,33 +1,28 @@ PROJECT_NAME := MissionControl -BTDRVMITM_TID := 010000000000bd00 +BLUETOOTH_MITM_TID := 010000000000bd00 -TARGETS := boot2 btdrv-mitm +TARGETS := bluetooth-mitm all: $(TARGETS) -boot2: - $(MAKE) -C Atmosphere/libraries all - $(MAKE) -C Atmosphere/stratosphere/boot2 all - -btdrv-mitm: +bluetooth-mitm: $(MAKE) -C $@ clean: $(MAKE) -C Atmosphere/libraries clean - $(MAKE) -C Atmosphere/stratosphere/boot2 clean - $(MAKE) -C btdrv-mitm clean + $(MAKE) -C bluetooth-mitm clean rm -rf dist dist: all rm -rf dist - mkdir -p dist/atmosphere/contents/$(BTDRVMITM_TID) - cp btdrv-mitm/btdrv-mitm.nsp dist/atmosphere/contents/$(BTDRVMITM_TID)/exefs.nsp - mkdir -p dist/atmosphere/contents/0100000000000008/ - cp Atmosphere/stratosphere/boot2/boot2.nsp dist/atmosphere/contents/0100000000000008/exefs.nsp - #mkdir -p dist/atmosphere/contents/$(BTDRVMITM_TID)/flags - #touch dist/atmosphere/contents/$(BTDRVMITM_TID)/flags/boot2.flag - #echo "btdrv" > mitm.lst + mkdir -p dist/atmosphere/contents/$(BLUETOOTH_MITM_TID) + cp bluetooth-mitm/bluetooth-mitm.nsp dist/atmosphere/contents/$(BLUETOOTH_MITM_TID)/exefs.nsp + echo "btdrv" >> dist/atmosphere/contents/$(BLUETOOTH_MITM_TID)/mitm.lst + echo "btm" >> dist/atmosphere/contents/$(BLUETOOTH_MITM_TID)/mitm.lst + + mkdir -p dist/atmosphere/contents/$(BLUETOOTH_MITM_TID)/flags + touch dist/atmosphere/contents/$(BLUETOOTH_MITM_TID)/flags/boot2.flag cp -r exefs_patches dist/atmosphere/ diff --git a/btdrv-mitm/Makefile b/bluetooth-mitm/Makefile similarity index 100% rename from btdrv-mitm/Makefile rename to bluetooth-mitm/Makefile diff --git a/btdrv-mitm/btdrv-mitm.json b/bluetooth-mitm/bluetooth-mitm.json similarity index 98% rename from btdrv-mitm/btdrv-mitm.json rename to bluetooth-mitm/bluetooth-mitm.json index 27183721..f1f26d7d 100644 --- a/btdrv-mitm/btdrv-mitm.json +++ b/bluetooth-mitm/bluetooth-mitm.json @@ -1,10 +1,10 @@ { - "name": "btdrv.mitm", + "name": "bluetooth.mitm", "title_id": "0x010000000000bd00", "title_id_range_min": "0x010000000000bd00", "title_id_range_max": "0x010000000000bd00", - "main_thread_stack_size": "0x4000", - "main_thread_priority": 16, + "main_thread_stack_size": "0x1000", + "main_thread_priority": 42, "default_cpu_id": 3, "process_category": 1, "is_retail": true, @@ -25,7 +25,7 @@ "type": "kernel_flags", "value": { "highest_thread_priority": 63, - "lowest_thread_priority": 4, + "lowest_thread_priority": 12, "lowest_cpu_id": 3, "highest_cpu_id": 3 } diff --git a/btdrv-mitm/source/main.cpp b/bluetooth-mitm/source/bluetoothmitm_main.cpp similarity index 72% rename from btdrv-mitm/source/main.cpp rename to bluetooth-mitm/source/bluetoothmitm_main.cpp index 817db315..5649d4a2 100644 --- a/btdrv-mitm/source/main.cpp +++ b/bluetooth-mitm/source/bluetoothmitm_main.cpp @@ -15,9 +15,8 @@ */ #include #include -#include "btdrv_mitm_service.hpp" -#include "bluetooth/bluetooth_events.hpp" -#include +#include "btdrv_mitm/btdrvmitm_module.hpp" +#include "btm_mitm/btmmitm_module.hpp" extern "C" { @@ -72,7 +71,6 @@ void __appInit(void) { R_ABORT_UNLESS(fsInitialize()); R_ABORT_UNLESS(pmdmntInitialize()); R_ABORT_UNLESS(pminfoInitialize()); - R_ABORT_UNLESS(btdrvInitialize()); }); R_ABORT_UNLESS(fsdevMountSdmc()); @@ -93,26 +91,20 @@ void __libnx_exception_handler(ThreadExceptionDump* ctx) { ams::CrashHandler(ctx); } -namespace { - - constexpr sm::ServiceName BtdrvMitmServiceName = sm::ServiceName::Encode("btdrv"); - - struct ServerOptions { - static constexpr size_t PointerBufferSize = 0x1000; - static constexpr size_t MaxDomains = 0; - static constexpr size_t MaxDomainObjects = 0; - }; +ams::Result LaunchModules(void) { + R_TRY(ams::mitm::btdrv::Launch()); + R_TRY(ams::mitm::btm::Launch()); + return ams::ResultSuccess(); +} - constexpr size_t MaxServers = 1; - constexpr size_t MaxSessions = 6; - +void WaitModules(void) { + ams::mitm::btm::WaitFinished(); + ams::mitm::btdrv::WaitFinished(); } int main(int argc, char **argv) { - auto server_manager = std::make_unique>(); - R_ABORT_UNLESS((server_manager->RegisterMitmServer(BtdrvMitmServiceName))); - R_ABORT_UNLESS(bluetooth::events::Initialize()); - server_manager->LoopProcess(); - + R_ABORT_UNLESS(LaunchModules()); + WaitModules(); + return 0; } diff --git a/btdrv-mitm/source/bluetooth/bluetooth_ble.cpp b/bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_ble.cpp similarity index 100% rename from btdrv-mitm/source/bluetooth/bluetooth_ble.cpp rename to bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_ble.cpp diff --git a/btdrv-mitm/source/bluetooth/bluetooth_ble.hpp b/bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_ble.hpp similarity index 100% rename from btdrv-mitm/source/bluetooth/bluetooth_ble.hpp rename to bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_ble.hpp diff --git a/btdrv-mitm/source/bluetooth/bluetooth_circular_buffer.cpp b/bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_circular_buffer.cpp similarity index 100% rename from btdrv-mitm/source/bluetooth/bluetooth_circular_buffer.cpp rename to bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_circular_buffer.cpp diff --git a/btdrv-mitm/source/bluetooth/bluetooth_circular_buffer.hpp b/bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_circular_buffer.hpp similarity index 100% rename from btdrv-mitm/source/bluetooth/bluetooth_circular_buffer.hpp rename to bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_circular_buffer.hpp diff --git a/btdrv-mitm/source/bluetooth/bluetooth_core.cpp b/bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_core.cpp similarity index 96% rename from btdrv-mitm/source/bluetooth/bluetooth_core.cpp rename to bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_core.cpp index da94fd4f..03b3f2a6 100644 --- a/btdrv-mitm/source/bluetooth/bluetooth_core.cpp +++ b/bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_core.cpp @@ -15,7 +15,7 @@ */ #include "bluetooth_core.hpp" #include "../btdrv_mitm_flags.hpp" -#include "../controllers/controller_management.hpp" +#include "../../controllers/controller_management.hpp" #include #include #include @@ -83,17 +83,17 @@ namespace ams::bluetooth::core { if (program_id == ncm::SystemProgramId::Btm) { switch (g_current_event_type) { case BluetoothEvent_DeviceFound: - if (controller::IsGamepad(&event_data->deviceFound.cod) && !controller::IsOfficialSwitchControllerName(event_data->deviceFound.name)) { + if (controller::IsGamepad(&event_data->deviceFound.cod) && !controller::IsOfficialSwitchControllerName(event_data->deviceFound.name, sizeof(BluetoothName))) { std::strncpy(event_data->deviceFound.name, controller::pro_controller_name, sizeof(BluetoothName) - 1); } break; case BluetoothEvent_PinRequest: - if (!controller::IsOfficialSwitchControllerName(event_data->pinReply.name)) { + if (!controller::IsOfficialSwitchControllerName(event_data->pinReply.name, sizeof(BluetoothName))) { std::strncpy(event_data->pinReply.name, controller::pro_controller_name, sizeof(BluetoothName) - 1); } break; case BluetoothEvent_SspRequest: - if (!controller::IsOfficialSwitchControllerName(event_data->sspReply.name)) { + if (!controller::IsOfficialSwitchControllerName(event_data->sspReply.name, sizeof(BluetoothName))) { std::strncpy(event_data->sspReply.name, controller::pro_controller_name, sizeof(BluetoothName) - 1); } break; diff --git a/btdrv-mitm/source/bluetooth/bluetooth_core.hpp b/bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_core.hpp similarity index 100% rename from btdrv-mitm/source/bluetooth/bluetooth_core.hpp rename to bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_core.hpp diff --git a/btdrv-mitm/source/bluetooth/bluetooth_events.cpp b/bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_events.cpp similarity index 87% rename from btdrv-mitm/source/bluetooth/bluetooth_events.cpp rename to bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_events.cpp index 62c6a7b7..cbb46014 100644 --- a/btdrv-mitm/source/bluetooth/bluetooth_events.cpp +++ b/bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_events.cpp @@ -35,19 +35,24 @@ namespace ams::bluetooth::events { svc::SleepThread(1'000'000ul); } + // Initialise the btdrv service now that we can be sure the MITM is up and running + sm::DoWithSession([&]() { + R_ABORT_UNLESS(btdrvInitialize()); + }); + os::InitializeWaitableManager(&g_manager); os::InitializeWaitableHolder(&g_holder_bt_core, core::GetSystemEvent()); os::SetWaitableHolderUserData(&g_holder_bt_core, BtdrvEventType_BluetoothCore); os::LinkWaitableHolder(&g_manager, &g_holder_bt_core); - os::InitializeWaitableHolder(&g_holder_bt_hid, hid::GetSystemEvent()); - os::SetWaitableHolderUserData(&g_holder_bt_hid, BtdrvEventType_BluetoothHid); + os::InitializeWaitableHolder(&g_holder_bt_hid, hid::GetSystemEvent()); + os::SetWaitableHolderUserData(&g_holder_bt_hid, BtdrvEventType_BluetoothHid); os::LinkWaitableHolder(&g_manager, &g_holder_bt_hid); if (hos::GetVersion() >= hos::Version_5_0_0) { - os::InitializeWaitableHolder(&g_holder_bt_ble, ble::GetSystemEvent()); - os::SetWaitableHolderUserData(&g_holder_bt_ble, BtdrvEventType_BluetoothBle); + os::InitializeWaitableHolder(&g_holder_bt_ble, ble::GetSystemEvent()); + os::SetWaitableHolderUserData(&g_holder_bt_ble, BtdrvEventType_BluetoothBle); os::LinkWaitableHolder(&g_manager, &g_holder_bt_ble); } diff --git a/btdrv-mitm/source/bluetooth/bluetooth_events.hpp b/bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_events.hpp similarity index 100% rename from btdrv-mitm/source/bluetooth/bluetooth_events.hpp rename to bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_events.hpp diff --git a/btdrv-mitm/source/bluetooth/bluetooth_hid.cpp b/bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_hid.cpp similarity index 98% rename from btdrv-mitm/source/bluetooth/bluetooth_hid.cpp rename to bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_hid.cpp index 69adc34d..03f5fead 100644 --- a/btdrv-mitm/source/bluetooth/bluetooth_hid.cpp +++ b/bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_hid.cpp @@ -15,7 +15,7 @@ */ #include "bluetooth_hid.hpp" #include "../btdrv_mitm_flags.hpp" -#include "../controllers/controller_management.hpp" +#include "../../controllers/controller_management.hpp" #include #include #include diff --git a/btdrv-mitm/source/bluetooth/bluetooth_hid.hpp b/bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_hid.hpp similarity index 100% rename from btdrv-mitm/source/bluetooth/bluetooth_hid.hpp rename to bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_hid.hpp diff --git a/btdrv-mitm/source/bluetooth/bluetooth_hid_report.cpp b/bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_hid_report.cpp similarity index 99% rename from btdrv-mitm/source/bluetooth/bluetooth_hid_report.cpp rename to bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_hid_report.cpp index 5ad2e95a..354739e8 100644 --- a/btdrv-mitm/source/bluetooth/bluetooth_hid_report.cpp +++ b/bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_hid_report.cpp @@ -17,7 +17,7 @@ #include "bluetooth_circular_buffer.hpp" #include "../btdrv_shim.h" #include "../btdrv_mitm_flags.hpp" -#include "../controllers/controller_management.hpp" +#include "../../controllers/controller_management.hpp" #include #include #include diff --git a/btdrv-mitm/source/bluetooth/bluetooth_hid_report.hpp b/bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_hid_report.hpp similarity index 100% rename from btdrv-mitm/source/bluetooth/bluetooth_hid_report.hpp rename to bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_hid_report.hpp diff --git a/btdrv-mitm/source/bluetooth/bluetooth_types.hpp b/bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_types.hpp similarity index 54% rename from btdrv-mitm/source/bluetooth/bluetooth_types.hpp rename to bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_types.hpp index c72af568..45c40b8a 100644 --- a/btdrv-mitm/source/bluetooth/bluetooth_types.hpp +++ b/bluetooth-mitm/source/btdrv_mitm/bluetooth/bluetooth_types.hpp @@ -19,32 +19,6 @@ namespace ams::bluetooth { - enum SubCmdType : u8 { - SubCmd_GetControllerState = 0x00, - SubCmd_ManualPair = 0x01, - SubCmd_RequestDeviceInfo = 0x02, - SubCmd_SetInputReportMode = 0x03, - SubCmd_TriggersElapsedTime = 0x04, - SubCmd_SetHciState = 0x06, - SubCmd_ResetPairingInfo = 0x07, - SubCmd_SetShipPowerState = 0x08, - SubCmd_SpiFlashRead = 0x10, - SubCmd_SpiFlashWrite = 0x11, - SubCmd_SpiSectorErase = 0x12, - SubCmd_ResetMcu = 0x20, - SubCmd_SetMcuConfig = 0x21, - SubCmd_SetMcuState = 0x22, - SubCmd_SetPlayerLeds = 0x30, - SubCmd_GetPlayerLeds = 0x31, - SubCmd_SetHomeLed = 0x38, - SubCmd_EnableImu = 0x40, - SubCmd_SetImuSensitivity = 0x41, - SubCmd_WriteImuRegisters = 0x42, - SubCmd_ReadImuRegisters = 0x43, - SubCmd_EnableVibration = 0x48, - SubCmd_GetRegulatedVoltage = 0x50, - }; - typedef BluetoothEventType EventType; typedef BluetoothHidEventType HidEventType; typedef BluetoothBleEventType BleEventType; @@ -62,8 +36,4 @@ namespace ams::bluetooth { typedef BluetoothHhReportType HhReportType; - struct DeviceSettings : sf::LargeData { - BluetoothDevicesSettings device; - }; - } diff --git a/btdrv-mitm/source/btdrv_mitm_flags.cpp b/bluetooth-mitm/source/btdrv_mitm/btdrv_mitm_flags.cpp similarity index 100% rename from btdrv-mitm/source/btdrv_mitm_flags.cpp rename to bluetooth-mitm/source/btdrv_mitm/btdrv_mitm_flags.cpp diff --git a/btdrv-mitm/source/btdrv_mitm_flags.hpp b/bluetooth-mitm/source/btdrv_mitm/btdrv_mitm_flags.hpp similarity index 100% rename from btdrv-mitm/source/btdrv_mitm_flags.hpp rename to bluetooth-mitm/source/btdrv_mitm/btdrv_mitm_flags.hpp diff --git a/btdrv-mitm/source/btdrv_mitm_service.cpp b/bluetooth-mitm/source/btdrv_mitm/btdrv_mitm_service.cpp similarity index 92% rename from btdrv-mitm/source/btdrv_mitm_service.cpp rename to bluetooth-mitm/source/btdrv_mitm/btdrv_mitm_service.cpp index 76794e5e..2ea767fa 100644 --- a/btdrv-mitm/source/btdrv_mitm_service.cpp +++ b/bluetooth-mitm/source/btdrv_mitm/btdrv_mitm_service.cpp @@ -17,7 +17,7 @@ #include "btdrv_mitm_flags.hpp" #include "btdrv_shim.h" #include "bluetooth/bluetooth_events.hpp" -#include "controllers/controller_management.hpp" +#include "../controllers/controller_management.hpp" #include #include @@ -87,20 +87,6 @@ namespace ams::mitm::btdrv { return ams::ResultSuccess(); } - - Result BtdrvMitmService::GetPairedDeviceInfo(sf::Out out, bluetooth::Address address) { - auto device = reinterpret_cast(out.GetPointer()); - - R_TRY(btdrvGetPairedDeviceInfoFwd(this->forward_service.get(), &address, device)); - - if (this->client_info.program_id == ncm::SystemProgramId::Btm) { - if (!controller::IsOfficialSwitchControllerName(device->name)) { - std::strncpy(device->name, controller::pro_controller_name, sizeof(BluetoothLocalName) - 1); - } - } - - return ams::ResultSuccess(); - } Result BtdrvMitmService::FinalizeHid(void) { // Only btm should be able to make this call diff --git a/btdrv-mitm/source/btdrv_mitm_service.hpp b/bluetooth-mitm/source/btdrv_mitm/btdrv_mitm_service.hpp similarity index 96% rename from btdrv-mitm/source/btdrv_mitm_service.hpp rename to bluetooth-mitm/source/btdrv_mitm/btdrv_mitm_service.hpp index 9c20381b..000d826d 100644 --- a/btdrv-mitm/source/btdrv_mitm_service.hpp +++ b/bluetooth-mitm/source/btdrv_mitm/btdrv_mitm_service.hpp @@ -27,7 +27,6 @@ namespace ams::mitm::btdrv { AMS_SF_METHOD_INFO(C, H, 15, Result, GetEventInfo, (sf::Out out_type, const sf::OutPointerBuffer &out_buffer)) \ AMS_SF_METHOD_INFO(C, H, 16, Result, InitializeHid, (sf::OutCopyHandle out_handle, u16 version)) \ AMS_SF_METHOD_INFO(C, H, 19, Result, WriteHidData, (bluetooth::Address address, const sf::InPointerBuffer &buffer)) \ - AMS_SF_METHOD_INFO(C, H, 25, Result, GetPairedDeviceInfo, (sf::Out out, bluetooth::Address address)) \ AMS_SF_METHOD_INFO(C, H, 26, Result, FinalizeHid, (void)) \ AMS_SF_METHOD_INFO(C, H, 27, Result, GetHidEventInfo, (sf::Out out_type, const sf::OutPointerBuffer &out_buffer)) \ AMS_SF_METHOD_INFO(C, H, 36, Result, RegisterHidReportEventDeprecated, (sf::OutCopyHandle out_handle), hos::Version_1_0_0, hos::Version_3_0_2) \ @@ -66,7 +65,6 @@ namespace ams::mitm::btdrv { Result GetEventInfo(sf::Out out_type, const sf::OutPointerBuffer &out_buffer); Result InitializeHid(sf::OutCopyHandle out_handle, u16 version); Result WriteHidData(bluetooth::Address address, const sf::InPointerBuffer &buffer); - Result GetPairedDeviceInfo(sf::Out out, bluetooth::Address address); Result FinalizeHid(void); Result GetHidEventInfo(sf::Out out_type, const sf::OutPointerBuffer &out_buffer); Result RegisterHidReportEventDeprecated(sf::OutCopyHandle out_handle); diff --git a/btdrv-mitm/source/btdrv_shim.c b/bluetooth-mitm/source/btdrv_mitm/btdrv_shim.c similarity index 85% rename from btdrv-mitm/source/btdrv_shim.c rename to bluetooth-mitm/source/btdrv_mitm/btdrv_shim.c index f1799804..c5d01b3d 100644 --- a/btdrv-mitm/source/btdrv_shim.c +++ b/bluetooth-mitm/source/btdrv_mitm/btdrv_shim.c @@ -45,17 +45,6 @@ Result btdrvWriteHidDataFwd(Service* srv, const BluetoothAddress *address, const ); } -Result btdrvGetPairedDeviceInfoFwd(Service* srv, const BluetoothAddress *address, BluetoothDevicesSettings *device) { - const struct { - BluetoothAddress address; - } in = { *address }; - - return serviceMitmDispatchIn(srv, 25, in, - .buffer_attrs = { SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_Out }, - .buffers = { {device, sizeof(BluetoothDevicesSettings)} } - ); -} - Result btdrvFinalizeHidFwd(Service* srv) { return serviceMitmDispatch(srv, 26); } diff --git a/btdrv-mitm/source/btdrv_shim.h b/bluetooth-mitm/source/btdrv_mitm/btdrv_shim.h similarity index 91% rename from btdrv-mitm/source/btdrv_shim.h rename to bluetooth-mitm/source/btdrv_mitm/btdrv_shim.h index 2ddd702b..aad110df 100644 --- a/btdrv-mitm/source/btdrv_shim.h +++ b/bluetooth-mitm/source/btdrv_mitm/btdrv_shim.h @@ -24,7 +24,6 @@ Result btdrvInitializeBluetoothFwd(Service* srv, Handle *out_handle); Result btdrvFinalizeBluetoothFwd(Service* srv); Result btdrvInitializeHidFwd(Service* srv, Handle *out_handle, u16 version); Result btdrvWriteHidDataFwd(Service* srv, const BluetoothAddress *address, const BluetoothHidReport *data); -Result btdrvGetPairedDeviceInfoFwd(Service* srv, const BluetoothAddress *address, BluetoothDevicesSettings *device); Result btdrvFinalizeHidFwd(Service* srv); Result btdrvRegisterHidReportEventFwd(Service* srv, Handle *out_handle); Result btdrvGetHidReportEventInfoFwd(Service* srv, Handle *out_handle); diff --git a/bluetooth-mitm/source/btdrv_mitm/btdrvmitm_module.cpp b/bluetooth-mitm/source/btdrv_mitm/btdrvmitm_module.cpp new file mode 100644 index 00000000..55a1923e --- /dev/null +++ b/bluetooth-mitm/source/btdrv_mitm/btdrvmitm_module.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2020 ndeadly + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 "btdrvmitm_module.hpp" +#include "btdrv_mitm_service.hpp" +#include "bluetooth/bluetooth_events.hpp" +#include +#include + +namespace ams::mitm::btdrv { + + namespace { + + constexpr sm::ServiceName MitmServiceName = sm::ServiceName::Encode("btdrv"); + + struct ServerOptions { + static constexpr size_t PointerBufferSize = 0x1000; + static constexpr size_t MaxDomains = 0; + static constexpr size_t MaxDomainObjects = 0; + }; + + constexpr size_t MaxServers = 1; + constexpr size_t MaxSessions = 6; + + os::ThreadType g_btdrv_mitm_thread; + alignas(os::ThreadStackAlignment) u8 g_btdrv_mitm_thread_stack[0x2000]; + constexpr s32 g_btdrv_mitm_thread_priority = 16; + + void BtdrvMitmThreadFunction(void *arg) { + R_ABORT_UNLESS(bluetooth::events::Initialize()); + + auto server_manager = std::make_unique>(); + R_ABORT_UNLESS((server_manager->RegisterMitmServer(MitmServiceName))); + server_manager->LoopProcess(); + } + + } + + Result Launch(void) { + R_TRY(os::CreateThread(&g_btdrv_mitm_thread, + BtdrvMitmThreadFunction, + nullptr, + g_btdrv_mitm_thread_stack, + sizeof(g_btdrv_mitm_thread_stack), + g_btdrv_mitm_thread_priority + )); + + os::StartThread(&g_btdrv_mitm_thread); + + return ams::ResultSuccess(); + } + + void WaitFinished(void) { + os::WaitThread(&g_btdrv_mitm_thread); + } + +} diff --git a/bluetooth-mitm/source/btdrv_mitm/btdrvmitm_module.hpp b/bluetooth-mitm/source/btdrv_mitm/btdrvmitm_module.hpp new file mode 100644 index 00000000..ea5cf125 --- /dev/null +++ b/bluetooth-mitm/source/btdrv_mitm/btdrvmitm_module.hpp @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2020 ndeadly + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 + +namespace ams::mitm::btdrv { + + Result Launch(void); + void WaitFinished(void); + +} diff --git a/bluetooth-mitm/source/btm_mitm/btm/btm_types.hpp b/bluetooth-mitm/source/btm_mitm/btm/btm_types.hpp new file mode 100644 index 00000000..6fd951bd --- /dev/null +++ b/bluetooth-mitm/source/btm_mitm/btm/btm_types.hpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 ndeadly + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 +#include + +namespace ams::mitm::btm { + + struct DeviceConditionV100 : sf::LargeData { + BtmDeviceConditionV100 condition; + }; + + struct DeviceConditionV510 : sf::LargeData { + BtmDeviceConditionV510 condition; + }; + + struct DeviceConditionV800 : sf::LargeData { + BtmDeviceConditionV800 condition; + }; + + struct DeviceCondition : sf::LargeData { + BtmDeviceConditionV900 condition; + }; + + struct DeviceInfo : sf::LargeData { + BtmDeviceInfo info; + }; + +} diff --git a/bluetooth-mitm/source/btm_mitm/btm_mitm_service.cpp b/bluetooth-mitm/source/btm_mitm/btm_mitm_service.cpp new file mode 100644 index 00000000..760fe4bd --- /dev/null +++ b/bluetooth-mitm/source/btm_mitm/btm_mitm_service.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2020 ndeadly + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 "btm_mitm_service.hpp" +#include "btm_shim.h" +#include "../controllers/controller_management.hpp" +#include + +namespace ams::mitm::btm { + + namespace { + + void RenameConnectedDevices(BtmConnectedDevice devices[], size_t count) { + for (unsigned int i = 0; i < count; ++i) { + auto device = &devices[i]; + if (!controller::IsOfficialSwitchControllerName(device->name, sizeof(device->name))) { + std::strncpy(device->name, controller::pro_controller_name, sizeof(device->name) - 1); + } + } + } + + } + + Result BtmMitmService::GetDeviceConditionDeprecated1(sf::Out out) { + auto device_condition = reinterpret_cast(out.GetPointer()); + R_TRY(btmGetDeviceConditionDeprecated1Fwd(this->forward_service.get(), device_condition)); + RenameConnectedDevices(device_condition->devices, device_condition->connected_count); + return ams::ResultSuccess(); + } + + Result BtmMitmService::GetDeviceConditionDeprecated2(sf::Out out) { + auto device_condition = reinterpret_cast(out.GetPointer()); + R_TRY(btmGetDeviceConditionDeprecated2Fwd(this->forward_service.get(), device_condition)); + RenameConnectedDevices(device_condition->devices, device_condition->connected_count); + return ams::ResultSuccess(); + } + + Result BtmMitmService::GetDeviceConditionDeprecated3(sf::Out out) { + auto device_condition = reinterpret_cast(out.GetPointer()); + R_TRY(btmGetDeviceConditionDeprecated1Fwd(this->forward_service.get(), device_condition)); + RenameConnectedDevices(device_condition->devices, device_condition->connected_count); + return ams::ResultSuccess(); + } + + Result BtmMitmService::GetDeviceCondition(sf::Out out) { + auto device_condition = reinterpret_cast(out.GetPointer()); + R_TRY(btmGetDeviceConditionFwd(this->forward_service.get(), device_condition)); + RenameConnectedDevices(device_condition->devices, device_condition->connected_count); + return ams::ResultSuccess(); + } + + Result BtmMitmService::GetDeviceInfo(sf::Out out) { + auto device_info = reinterpret_cast(out.GetPointer()); + R_TRY(btmGetDeviceInfoFwd(this->forward_service.get(), device_info)); + + for (unsigned int i = 0; i < device_info->count; ++i) { + auto device = &device_info->devices[i]; + if (!controller::IsOfficialSwitchControllerName(device->name, sizeof(device->name))) { + std::strncpy(device->name, controller::pro_controller_name, sizeof(device->name) - 1); + } + } + + return ams::ResultSuccess(); + } + +} diff --git a/bluetooth-mitm/source/btm_mitm/btm_mitm_service.hpp b/bluetooth-mitm/source/btm_mitm/btm_mitm_service.hpp new file mode 100644 index 00000000..ba4ce276 --- /dev/null +++ b/bluetooth-mitm/source/btm_mitm/btm_mitm_service.hpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2020 ndeadly + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 +#include "btm/btm_types.hpp" + +namespace ams::mitm::btm { + + namespace { + + #define AMS_BTM_MITM_INTERFACE_INFO(C, H) \ + AMS_SF_METHOD_INFO(C, H, 3, Result, GetDeviceConditionDeprecated1, (sf::Out), hos::Version_1_0_0, hos::Version_5_0_2) \ + AMS_SF_METHOD_INFO(C, H, 3, Result, GetDeviceConditionDeprecated2, (sf::Out), hos::Version_5_1_0, hos::Version_7_0_1) \ + AMS_SF_METHOD_INFO(C, H, 3, Result, GetDeviceConditionDeprecated3, (sf::Out), hos::Version_8_0_0, hos::Version_8_1_1) \ + AMS_SF_METHOD_INFO(C, H, 3, Result, GetDeviceCondition, (sf::Out), hos::Version_9_0_0) \ + AMS_SF_METHOD_INFO(C, H, 9, Result, GetDeviceInfo, (sf::Out)) \ + + AMS_SF_DEFINE_MITM_INTERFACE(IBtmMitmInterface, AMS_BTM_MITM_INTERFACE_INFO) + + } + + class BtmMitmService : public sf::MitmServiceImplBase { + + public: + using MitmServiceImplBase::MitmServiceImplBase; + + public: + static bool ShouldMitm(const sm::MitmProcessInfo &client_info) { + return client_info.program_id == ncm::SystemProgramId::Hid; + } + + public: + Result GetDeviceConditionDeprecated1(sf::Out out); + Result GetDeviceConditionDeprecated2(sf::Out out); + Result GetDeviceConditionDeprecated3(sf::Out out); + Result GetDeviceCondition(sf::Out out); + Result GetDeviceInfo(sf::Out out); + }; + static_assert(IsIBtmMitmInterface); + +} diff --git a/bluetooth-mitm/source/btm_mitm/btm_shim.c b/bluetooth-mitm/source/btm_mitm/btm_shim.c new file mode 100644 index 00000000..5a8cb1e4 --- /dev/null +++ b/bluetooth-mitm/source/btm_mitm/btm_shim.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2020 ndeadly + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 "btm_shim.h" +#include + +Result btmGetDeviceConditionDeprecated1Fwd(Service* s, BtmDeviceConditionV100 *condition) { + return serviceMitmDispatch(s, 3, + .buffer_attrs = { SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_Out }, + .buffers = { {condition, sizeof(BtmDeviceConditionV100)} } + ); +} + +Result btmGetDeviceConditionDeprecated2Fwd(Service* s, BtmDeviceConditionV510 *condition) { + return serviceMitmDispatch(s, 3, + .buffer_attrs = { SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_Out }, + .buffers = { {condition, sizeof(BtmDeviceConditionV510)} } + ); +} + +Result btmGetDeviceConditionDeprecated3Fwd(Service* s, BtmDeviceConditionV800 *condition) { + return serviceMitmDispatch(s, 3, + .buffer_attrs = { SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_Out }, + .buffers = { {condition, sizeof(BtmDeviceConditionV800)} } + ); +} + +Result btmGetDeviceConditionFwd(Service* s, BtmDeviceConditionV900 *condition) { + return serviceMitmDispatch(s, 3, + .buffer_attrs = { SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_Out }, + .buffers = { {condition, sizeof(BtmDeviceConditionV900)} } + ); +} + +Result btmGetDeviceInfoFwd(Service* s, BtmDeviceInfo *devices) { + return serviceMitmDispatch(s, 9, + .buffer_attrs = { SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_Out }, + .buffers = { {devices, sizeof(BtmDeviceInfo)} } + ); +} diff --git a/bluetooth-mitm/source/btm_mitm/btm_shim.h b/bluetooth-mitm/source/btm_mitm/btm_shim.h new file mode 100644 index 00000000..f30785de --- /dev/null +++ b/bluetooth-mitm/source/btm_mitm/btm_shim.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020 ndeadly + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 + +Result btmGetDeviceConditionDeprecated1Fwd(Service* s, BtmDeviceConditionV100 *condition); +Result btmGetDeviceConditionDeprecated2Fwd(Service* s, BtmDeviceConditionV510 *condition); +Result btmGetDeviceConditionDeprecated3Fwd(Service* s, BtmDeviceConditionV800 *condition); +Result btmGetDeviceConditionFwd(Service* s, BtmDeviceConditionV900 *condition); +Result btmGetDeviceInfoFwd(Service* s, BtmDeviceInfo *devices); + +#ifdef __cplusplus +} +#endif diff --git a/bluetooth-mitm/source/btm_mitm/btmmitm_module.cpp b/bluetooth-mitm/source/btm_mitm/btmmitm_module.cpp new file mode 100644 index 00000000..2a0a8c49 --- /dev/null +++ b/bluetooth-mitm/source/btm_mitm/btmmitm_module.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2020 ndeadly + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 "btmmitm_module.hpp" +#include "btm_mitm_service.hpp" +#include +#include + +namespace ams::mitm::btm { + + namespace { + + constexpr sm::ServiceName MitmServiceName = sm::ServiceName::Encode("btm"); + + struct ServerOptions { + static constexpr size_t PointerBufferSize = 0x1000; + static constexpr size_t MaxDomains = 0; + static constexpr size_t MaxDomainObjects = 0; + }; + + constexpr size_t MaxServers = 1; + constexpr size_t MaxSessions = 6; + + os::ThreadType g_btm_mitm_thread; + alignas(os::ThreadStackAlignment) u8 g_btm_mitm_thread_stack[0x2000]; + constexpr s32 g_btm_mitm_thread_priority = 34; + + void BtmMitmThreadFunction(void *arg) { + auto server_manager = std::make_unique>(); + R_ABORT_UNLESS((server_manager->RegisterMitmServer(MitmServiceName))); + server_manager->LoopProcess(); + } + + } + + Result Launch(void) { + R_TRY(os::CreateThread(&g_btm_mitm_thread, + BtmMitmThreadFunction, + nullptr, + g_btm_mitm_thread_stack, + sizeof(g_btm_mitm_thread_stack), + g_btm_mitm_thread_priority + )); + + os::StartThread(&g_btm_mitm_thread); + + return ams::ResultSuccess(); + } + + void WaitFinished(void) { + os::WaitThread(&g_btm_mitm_thread); + } + +} diff --git a/bluetooth-mitm/source/btm_mitm/btmmitm_module.hpp b/bluetooth-mitm/source/btm_mitm/btmmitm_module.hpp new file mode 100644 index 00000000..fb93c535 --- /dev/null +++ b/bluetooth-mitm/source/btm_mitm/btmmitm_module.hpp @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2020 ndeadly + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 + +namespace ams::mitm::btm { + + Result Launch(void); + void WaitFinished(void); + +} diff --git a/btdrv-mitm/source/controllers/controller_management.cpp b/bluetooth-mitm/source/controllers/controller_management.cpp similarity index 61% rename from btdrv-mitm/source/controllers/controller_management.cpp rename to bluetooth-mitm/source/controllers/controller_management.cpp index c618c213..4eee0aee 100644 --- a/btdrv-mitm/source/controllers/controller_management.cpp +++ b/bluetooth-mitm/source/controllers/controller_management.cpp @@ -38,11 +38,9 @@ namespace ams::controller { } ControllerType Identify(const BluetoothDevicesSettings *device) { - for (auto hwId : SwitchController::hardware_ids) { - if ( (device->vid == hwId.vid) && (device->pid == hwId.pid) ) { - return ControllerType_Switch; - } - } + + if (IsOfficialSwitchControllerName(device->name, sizeof(device->name))) + return ControllerType_Switch; for (auto hwId : WiiController::hardware_ids) { if ( (device->vid == hwId.vid) && (device->pid == hwId.pid) ) { @@ -62,11 +60,36 @@ namespace ams::controller { } } - // Handle the case where joycons have been assigned random hardware ids when paired via rails - if (IsJoyCon(device->name)) { - return ControllerType_Switch;; + for (auto hwId : OuyaController::hardware_ids) { + if ( (device->vid == hwId.vid) && (device->pid == hwId.pid) ) { + return ControllerType_Ouya; + } + } + + for (auto hwId : GamestickController::hardware_ids) { + if ( (device->vid == hwId.vid) && (device->pid == hwId.pid) ) { + return ControllerType_Gamestick; + } + } + + for (auto hwId : GemboxController::hardware_ids) { + if ( (device->vid == hwId.vid) && (device->pid == hwId.pid) ) { + return ControllerType_Gembox; + } } + + for (auto hwId : IpegaController::hardware_ids) { + if ( (device->vid == hwId.vid) && (device->pid == hwId.pid) ) { + return ControllerType_Ipega; + } + } + for (auto hwId : XiaomiController::hardware_ids) { + if ( (device->vid == hwId.vid) && (device->pid == hwId.pid) ) { + return ControllerType_Xiaomi; + } + } + return ControllerType_Unknown; } @@ -75,20 +98,15 @@ namespace ams::controller { (((cod->cod[2] & 0x0f) == cod_minor_gamepad) || ((cod->cod[2] & 0x0f) == cod_minor_joystick)); } - bool IsJoyCon(const char *name) { - return std::strncmp(name, "Joy-Con (L)", sizeof(BluetoothName)) == 0 || - std::strncmp(name, "Joy-Con (R)", sizeof(BluetoothName)) == 0; - } - - bool IsOfficialSwitchControllerName(const char *name) { - return std::strncmp(name, "Joy-Con (L)", sizeof(BluetoothName)) == 0 || - std::strncmp(name, "Joy-Con (R)", sizeof(BluetoothName)) == 0 || - std::strncmp(name, "Pro Controller", sizeof(BluetoothName)) == 0 || - std::strncmp(name, "Lic Pro Controller", sizeof(BluetoothName)) == 0 || - std::strncmp(name, "NES Controller", sizeof(BluetoothName)) == 0 || - std::strncmp(name, "HVC Controller", sizeof(BluetoothName)) == 0 || - std::strncmp(name, "SNES Controller", sizeof(BluetoothName)) == 0 || - std::strncmp(name, "NintendoGamepad", sizeof(BluetoothName)) == 0 ; + bool IsOfficialSwitchControllerName(const char *name, size_t size) { + return std::strncmp(name, "Joy-Con (L)", size) == 0 || + std::strncmp(name, "Joy-Con (R)", size) == 0 || + std::strncmp(name, "Pro Controller", size) == 0 || + std::strncmp(name, "Lic Pro Controller", size) == 0 || + std::strncmp(name, "NES Controller", size) == 0 || + std::strncmp(name, "HVC Controller", size) == 0 || + std::strncmp(name, "SNES Controller", size) == 0 || + std::strncmp(name, "NintendoGamepad", size) == 0 ; } void AttachHandler(const bluetooth::Address *address) { @@ -110,8 +128,24 @@ namespace ams::controller { case ControllerType_XboxOne: g_controllers.push_back(std::make_unique(address)); break; + case ControllerType_Ouya: + g_controllers.push_back(std::make_unique(address)); + break; + case ControllerType_Gamestick: + g_controllers.push_back(std::make_unique(address)); + break; + case ControllerType_Gembox: + g_controllers.push_back(std::make_unique(address)); + break; + case ControllerType_Ipega: + g_controllers.push_back(std::make_unique(address)); + break; + case ControllerType_Xiaomi: + g_controllers.push_back(std::make_unique(address)); + break; default: - return; + g_controllers.push_back(std::make_unique(address)); + break; } g_controllers.back()->Initialize(); diff --git a/btdrv-mitm/source/controllers/controller_management.hpp b/bluetooth-mitm/source/controllers/controller_management.hpp similarity index 77% rename from btdrv-mitm/source/controllers/controller_management.hpp rename to bluetooth-mitm/source/controllers/controller_management.hpp index ddd6f538..7d5dc966 100644 --- a/btdrv-mitm/source/controllers/controller_management.hpp +++ b/bluetooth-mitm/source/controllers/controller_management.hpp @@ -15,10 +15,16 @@ */ #pragma once #include +#include "default_controller.hpp" #include "switch_controller.hpp" #include "wii_controller.hpp" #include "dualshock4_controller.hpp" #include "xbox_one_controller.hpp" +#include "ouya_controller.hpp" +#include "gamestick_controller.hpp" +#include "gembox_controller.hpp" +#include "ipega_controller.hpp" +#include "xiaomi_controller.hpp" namespace ams::controller { @@ -30,13 +36,17 @@ namespace ams::controller { ControllerType_Wii, ControllerType_Dualshock4, ControllerType_XboxOne, + ControllerType_Ouya, + ControllerType_Gamestick, + ControllerType_Gembox, + ControllerType_Ipega, + ControllerType_Xiaomi, ControllerType_Unknown, }; ControllerType Identify(const BluetoothDevicesSettings *device); bool IsGamepad(const bluetooth::DeviceClass *cod); - bool IsJoyCon(const char *name); - bool IsOfficialSwitchControllerName(const char *name); + bool IsOfficialSwitchControllerName(const char *name, size_t size); void AttachHandler(const bluetooth::Address *address); void RemoveHandler(const bluetooth::Address *address); diff --git a/bluetooth-mitm/source/controllers/default_controller.cpp b/bluetooth-mitm/source/controllers/default_controller.cpp new file mode 100644 index 00000000..f623ced5 --- /dev/null +++ b/bluetooth-mitm/source/controllers/default_controller.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 ndeadly + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 "default_controller.hpp" +#include + +namespace ams::controller { + + Result DefaultController::Initialize(void) { + // Write empty Switch report into buffer to kick off connection + R_TRY(EmulatedSwitchController::Initialize()); + s_output_report.size = sizeof(SwitchInputReport0x30) + 1; + auto switch_report = reinterpret_cast(s_output_report.data); + switch_report->id = 0x30; + switch_report->input0x30.conn_info = 0x0; + switch_report->input0x30.battery = BATTERY_MAX; + std::memset(switch_report->input0x30.motion, 0, sizeof(switch_report->input0x30.motion)); + switch_report->input0x30.timer = os::ConvertToTimeSpan(os::GetSystemTick()).GetMilliSeconds() & 0xff; + R_TRY(bluetooth::hid::report::WriteHidReportBuffer(&m_address, &s_output_report)); + return ams::ResultSuccess(); + } + + Result DefaultController::HandleIncomingReport(const bluetooth::HidReport *report) { + // Drop all incoming data for now + return ams::ResultSuccess(); + }; + +} diff --git a/bluetooth-mitm/source/controllers/default_controller.hpp b/bluetooth-mitm/source/controllers/default_controller.hpp new file mode 100644 index 00000000..a8cb7a2e --- /dev/null +++ b/bluetooth-mitm/source/controllers/default_controller.hpp @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2020 ndeadly + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 "emulated_switch_controller.hpp" + +namespace ams::controller { + + class DefaultController : public EmulatedSwitchController { + + public: + DefaultController(const bluetooth::Address *address) + : EmulatedSwitchController(address) { }; + + Result Initialize(void); + Result HandleIncomingReport(const bluetooth::HidReport *report) override; + + }; + +} diff --git a/btdrv-mitm/source/controllers/dualshock4_controller.cpp b/bluetooth-mitm/source/controllers/dualshock4_controller.cpp similarity index 94% rename from btdrv-mitm/source/controllers/dualshock4_controller.cpp rename to bluetooth-mitm/source/controllers/dualshock4_controller.cpp index 8287f101..6560422b 100644 --- a/btdrv-mitm/source/controllers/dualshock4_controller.cpp +++ b/bluetooth-mitm/source/controllers/dualshock4_controller.cpp @@ -71,6 +71,7 @@ namespace ams::controller { switch_report->id = 0x30; switch_report->input0x30.conn_info = 0x0; switch_report->input0x30.battery = m_battery | m_charging; + std::memset(switch_report->input0x30.motion, 0, sizeof(switch_report->input0x30.motion)); switch_report->input0x30.timer = os::ConvertToTimeSpan(os::GetSystemTick()).GetMilliSeconds() & 0xff; } @@ -93,7 +94,13 @@ namespace ams::controller { else m_charging = true; - m_battery = src->input0x11.battery_level & 0xe; + uint8_t battery_level = src->input0x11.battery_level; + if (!src->input0x11.usb) + battery_level++; + if (battery_level > 10) + battery_level = 10; + + m_battery = static_cast(8 * (battery_level + 1) / 10) & 0x0e; this->PackStickData(&dst->input0x30.left_stick, static_cast(stick_scale_factor * src->input0x11.left_stick.x) & 0xfff, diff --git a/btdrv-mitm/source/controllers/dualshock4_controller.hpp b/bluetooth-mitm/source/controllers/dualshock4_controller.hpp similarity index 100% rename from btdrv-mitm/source/controllers/dualshock4_controller.hpp rename to bluetooth-mitm/source/controllers/dualshock4_controller.hpp diff --git a/btdrv-mitm/source/controllers/emulated_switch_controller.cpp b/bluetooth-mitm/source/controllers/emulated_switch_controller.cpp similarity index 81% rename from btdrv-mitm/source/controllers/emulated_switch_controller.cpp rename to bluetooth-mitm/source/controllers/emulated_switch_controller.cpp index af20619f..66a3640e 100644 --- a/btdrv-mitm/source/controllers/emulated_switch_controller.cpp +++ b/bluetooth-mitm/source/controllers/emulated_switch_controller.cpp @@ -53,43 +53,46 @@ namespace ams::controller { Result EmulatedSwitchController::HandleSubCmdReport(const bluetooth::HidReport *report) { const uint8_t *subcmd = &report->data[10]; - auto subcmd_id = static_cast(subcmd[0]); + auto subcmd_id = static_cast(subcmd[0]); switch (subcmd_id) { - case bluetooth::SubCmd_RequestDeviceInfo: + case SubCmd_RequestDeviceInfo: R_TRY(this->SubCmdRequestDeviceInfo(report)); break; - case bluetooth::SubCmd_SpiFlashRead: + case SubCmd_SpiFlashRead: R_TRY(this->SubCmdSpiFlashRead(report)); break; - case bluetooth::SubCmd_SpiFlashWrite: + case SubCmd_SpiFlashWrite: R_TRY(this->SubCmdSpiFlashWrite(report)); break; - case bluetooth::SubCmd_SpiSectorErase: + case SubCmd_SpiSectorErase: R_TRY(this->SubCmdSpiSectorErase(report)); break; - case bluetooth::SubCmd_SetInputReportMode: + case SubCmd_SetInputReportMode: R_TRY(this->SubCmdSetInputReportMode(report)); break; - case bluetooth::SubCmd_TriggersElapsedTime: + case SubCmd_TriggersElapsedTime: R_TRY(this->SubCmdTriggersElapsedTime(report)); break; - case bluetooth::SubCmd_SetShipPowerState: + case SubCmd_SetShipPowerState: R_TRY(this->SubCmdSetShipPowerState(report)); break; - case bluetooth::SubCmd_SetMcuConfig: + case SubCmd_SetMcuConfig: R_TRY(this->SubCmdSetMcuConfig(report)); break; - case bluetooth::SubCmd_SetMcuState: + case SubCmd_SetMcuState: R_TRY(this->SubCmdSetMcuState(report)); break; - case bluetooth::SubCmd_SetPlayerLeds: + case SubCmd_SetPlayerLeds: R_TRY(this->SubCmdSetPlayerLeds(report)); break; - case bluetooth::SubCmd_EnableImu: + case SubCmd_SetHomeLed: + R_TRY(this->SubCmdSetHomeLed(report)); + break; + case SubCmd_EnableImu: R_TRY(this->SubCmdEnableImu(report)); break; - case bluetooth::SubCmd_EnableVibration: + case SubCmd_EnableVibration: R_TRY(this->SubCmdEnableVibration(report)); break; default: @@ -117,7 +120,7 @@ namespace ams::controller { uint32_t read_addr = *(uint32_t *)(&report->data[11]); uint8_t read_size = report->data[15]; - const uint8_t prefix[] = {0x90, bluetooth::SubCmd_SpiFlashRead, report->data[11], report->data[12], report->data[13], report->data[14], report->data[15]}; + const uint8_t prefix[] = {0x90, SubCmd_SpiFlashRead, report->data[11], report->data[12], report->data[13], report->data[14], report->data[15]}; int response_size = read_size + sizeof(prefix); auto response = std::make_unique(response_size); @@ -133,37 +136,37 @@ namespace ams::controller { } Result EmulatedSwitchController::SubCmdSpiFlashWrite(const bluetooth::HidReport *report) { - const uint8_t response[] = {0x80, bluetooth::SubCmd_SpiFlashWrite, 0x01}; + const uint8_t response[] = {0x80, SubCmd_SpiFlashWrite, 0x01}; return this->FakeSubCmdResponse(response, sizeof(response)); } Result EmulatedSwitchController::SubCmdSpiSectorErase(const bluetooth::HidReport *report) { - const uint8_t response[] = {0x80, bluetooth::SubCmd_SpiSectorErase, 0x01}; + const uint8_t response[] = {0x80, SubCmd_SpiSectorErase, 0x01}; return this->FakeSubCmdResponse(response, sizeof(response)); } Result EmulatedSwitchController::SubCmdSetInputReportMode(const bluetooth::HidReport *report) { - const uint8_t response[] = {0x80, bluetooth::SubCmd_SetInputReportMode}; + const uint8_t response[] = {0x80, SubCmd_SetInputReportMode}; return this->FakeSubCmdResponse(response, sizeof(response)); } Result EmulatedSwitchController::SubCmdTriggersElapsedTime(const bluetooth::HidReport *report) { - const uint8_t response[] = {0x83, bluetooth::SubCmd_TriggersElapsedTime}; + const uint8_t response[] = {0x83, SubCmd_TriggersElapsedTime}; return this->FakeSubCmdResponse(response, sizeof(response)); } Result EmulatedSwitchController::SubCmdSetShipPowerState(const bluetooth::HidReport *report) { - const uint8_t response[] = {0x80, bluetooth::SubCmd_SetShipPowerState, 0x00}; + const uint8_t response[] = {0x80, SubCmd_SetShipPowerState, 0x00}; return this->FakeSubCmdResponse(response, sizeof(response)); } Result EmulatedSwitchController::SubCmdSetMcuConfig(const bluetooth::HidReport *report) { - const uint8_t response[] = {0xa0, bluetooth::SubCmd_SetMcuConfig, 0x01, 0x00, 0xff, 0x00, 0x03, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c}; + const uint8_t response[] = {0xa0, SubCmd_SetMcuConfig, 0x01, 0x00, 0xff, 0x00, 0x03, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c}; return this->FakeSubCmdResponse(response, sizeof(response)); } Result EmulatedSwitchController::SubCmdSetMcuState(const bluetooth::HidReport *report) { - const uint8_t response[] = {0x80, bluetooth::SubCmd_SetMcuState}; + const uint8_t response[] = {0x80, SubCmd_SetMcuState}; return this->FakeSubCmdResponse(response, sizeof(response)); } @@ -172,17 +175,22 @@ namespace ams::controller { uint8_t led_mask = subCmd[1]; R_TRY(this->SetPlayerLed(led_mask)); - const uint8_t response[] = {0x80, bluetooth::SubCmd_SetPlayerLeds}; + const uint8_t response[] = {0x80, SubCmd_SetPlayerLeds}; + return this->FakeSubCmdResponse(response, sizeof(response)); + } + + Result EmulatedSwitchController::SubCmdSetHomeLed(const bluetooth::HidReport *report) { + const uint8_t response[] = {0x80, SubCmd_SetHomeLed}; return this->FakeSubCmdResponse(response, sizeof(response)); } Result EmulatedSwitchController::SubCmdEnableImu(const bluetooth::HidReport *report) { - const uint8_t response[] = {0x80, bluetooth::SubCmd_EnableImu}; + const uint8_t response[] = {0x80, SubCmd_EnableImu}; return this->FakeSubCmdResponse(response, sizeof(response)); } Result EmulatedSwitchController::SubCmdEnableVibration(const bluetooth::HidReport *report) { - const uint8_t response[] = {0x80, bluetooth::SubCmd_EnableVibration}; + const uint8_t response[] = {0x80, SubCmd_EnableVibration}; return this->FakeSubCmdResponse(response, sizeof(response)); } diff --git a/btdrv-mitm/source/controllers/emulated_switch_controller.hpp b/bluetooth-mitm/source/controllers/emulated_switch_controller.hpp similarity index 97% rename from btdrv-mitm/source/controllers/emulated_switch_controller.hpp rename to bluetooth-mitm/source/controllers/emulated_switch_controller.hpp index 90ef02d6..8bd7e905 100644 --- a/btdrv-mitm/source/controllers/emulated_switch_controller.hpp +++ b/bluetooth-mitm/source/controllers/emulated_switch_controller.hpp @@ -48,6 +48,7 @@ namespace ams::controller { Result SubCmdSetMcuConfig(const bluetooth::HidReport *report); Result SubCmdSetMcuState(const bluetooth::HidReport *report); Result SubCmdSetPlayerLeds(const bluetooth::HidReport *report); + Result SubCmdSetHomeLed(const bluetooth::HidReport *report); Result SubCmdEnableImu(const bluetooth::HidReport *report); Result SubCmdEnableVibration(const bluetooth::HidReport *report); diff --git a/bluetooth-mitm/source/controllers/gamestick_controller.cpp b/bluetooth-mitm/source/controllers/gamestick_controller.cpp new file mode 100644 index 00000000..ada10e66 --- /dev/null +++ b/bluetooth-mitm/source/controllers/gamestick_controller.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2020 ndeadly + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 "gamestick_controller.hpp" +#include +#include + +namespace ams::controller { + + namespace { + + const constexpr float stick_scale_factor = float(UINT12_MAX) / UINT8_MAX; + + } + + void GamestickController::ConvertReportFormat(const bluetooth::HidReport *in_report, bluetooth::HidReport *out_report) { + auto gamestick_report = reinterpret_cast(&in_report->data); + auto switch_report = reinterpret_cast(&out_report->data); + + switch(gamestick_report->id) { + case 0x01: + this->HandleInputReport0x01(gamestick_report, switch_report); + break; + case 0x03: + this->HandleInputReport0x03(gamestick_report, switch_report); + break; + default: + break; + } + + out_report->size = sizeof(SwitchInputReport0x30) + 1; + switch_report->id = 0x30; + switch_report->input0x30.conn_info = 0x0; + switch_report->input0x30.battery = m_battery | m_charging; + std::memset(switch_report->input0x30.motion, 0, sizeof(switch_report->input0x30.motion)); + switch_report->input0x30.timer = os::ConvertToTimeSpan(os::GetSystemTick()).GetMilliSeconds() & 0xff; + } + + void GamestickController::HandleInputReport0x01(const GamestickReportData *src, SwitchReportData *dst) { + dst->input0x30.buttons.minus = src->input0x01.buttons.back; + dst->input0x30.buttons.home = src->input0x01.buttons.home; + } + + void GamestickController::HandleInputReport0x03(const GamestickReportData *src, SwitchReportData *dst) { + this->PackStickData(&dst->input0x30.left_stick, + static_cast(stick_scale_factor * src->input0x03.left_stick.x) & 0xfff, + static_cast(stick_scale_factor * (UINT8_MAX - src->input0x03.left_stick.y)) & 0xfff + ); + this->PackStickData(&dst->input0x30.right_stick, + static_cast(stick_scale_factor * src->input0x03.right_stick.x) & 0xfff, + static_cast(stick_scale_factor * (UINT8_MAX - src->input0x03.right_stick.y)) & 0xfff + ); + + dst->input0x30.buttons.dpad_down = (src->input0x03.dpad == GamestickDPad_S) || + (src->input0x03.dpad == GamestickDPad_SE) || + (src->input0x03.dpad == GamestickDPad_SW); + dst->input0x30.buttons.dpad_up = (src->input0x03.dpad == GamestickDPad_N) || + (src->input0x03.dpad == GamestickDPad_NE) || + (src->input0x03.dpad == GamestickDPad_NW); + dst->input0x30.buttons.dpad_right = (src->input0x03.dpad == GamestickDPad_E) || + (src->input0x03.dpad == GamestickDPad_NE) || + (src->input0x03.dpad == GamestickDPad_SE); + dst->input0x30.buttons.dpad_left = (src->input0x03.dpad == GamestickDPad_W) || + (src->input0x03.dpad == GamestickDPad_NW) || + (src->input0x03.dpad == GamestickDPad_SW); + + dst->input0x30.buttons.A = src->input0x03.buttons.B; + dst->input0x30.buttons.B = src->input0x03.buttons.A; + dst->input0x30.buttons.X = src->input0x03.buttons.Y; + dst->input0x30.buttons.Y = src->input0x03.buttons.X; + + /* + dst->input0x30.buttons.ZR = src->input0x03.buttons.start && src->input0x03.buttons.R; + dst->input0x30.buttons.ZL = src->input0x03.buttons.start && src->input0x03.buttons.L; + + if (!dst->input0x30.buttons.ZR) + dst->input0x30.buttons.R = src->input0x03.buttons.R; + + if (!dst->input0x30.buttons.ZL) + dst->input0x30.buttons.L = src->input0x03.buttons.L; + + if (!(dst->input0x30.buttons.ZR || dst->input0x30.buttons.ZL)) + dst->input0x30.buttons.plus = src->input0x03.buttons.start; + */ + dst->input0x30.buttons.L = src->input0x03.buttons.L; + dst->input0x30.buttons.R = src->input0x03.buttons.R; + + // Combos for ZL/ZR + if (dst->input0x30.buttons.dpad_down) { + dst->input0x30.buttons.ZL = src->input0x03.buttons.L; + dst->input0x30.buttons.ZR = src->input0x03.buttons.R; + dst->input0x30.buttons.dpad_down = !(dst->input0x30.buttons.ZL || dst->input0x30.buttons.ZR); + dst->input0x30.buttons.L = !dst->input0x30.buttons.ZL; + dst->input0x30.buttons.R = !dst->input0x30.buttons.ZR; + } + + dst->input0x30.buttons.plus = src->input0x03.buttons.start; + + dst->input0x30.buttons.lstick_press = src->input0x03.buttons.lstick_press; + dst->input0x30.buttons.rstick_press = src->input0x03.buttons.rstick_press; + + dst->input0x30.buttons.capture = 0; + } + +} diff --git a/bluetooth-mitm/source/controllers/gamestick_controller.hpp b/bluetooth-mitm/source/controllers/gamestick_controller.hpp new file mode 100644 index 00000000..5ef3d4f7 --- /dev/null +++ b/bluetooth-mitm/source/controllers/gamestick_controller.hpp @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2020 ndeadly + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 "emulated_switch_controller.hpp" + +namespace ams::controller { + + enum GamestickDPadDirection { + GamestickDPad_N, + GamestickDPad_NE, + GamestickDPad_E, + GamestickDPad_SE, + GamestickDPad_S, + GamestickDPad_SW, + GamestickDPad_W, + GamestickDPad_NW, + GamestickDPad_Released = 0x0f + }; + + struct GamestickStickData { + uint8_t x; + uint8_t y; + } __attribute__((packed)); + + struct GamestickInputReport0x01 { + uint8_t _unk0; + + struct { + uint8_t : 4; + uint8_t home : 1; + uint8_t back : 1; + uint8_t : 0; + } buttons; + + uint8_t _unk1[6]; + } __attribute__((packed)); + + struct GamestickInputReport0x03 { + uint8_t dpad; + GamestickStickData left_stick; + GamestickStickData right_stick; + uint8_t _unk0[2]; + + struct { + uint8_t A : 1; + uint8_t B : 1; + uint8_t : 1; + uint8_t X : 1; + uint8_t Y : 1; + uint8_t : 1; + uint8_t L : 1; + uint8_t R : 1; + + uint8_t : 3; + uint8_t start : 1; + uint8_t : 1; + uint8_t lstick_press : 1; + uint8_t rstick_press : 1; + uint8_t : 1; + } buttons; + + } __attribute__((packed)); + + struct GamestickReportData { + uint8_t id; + union { + GamestickInputReport0x01 input0x01; + GamestickInputReport0x03 input0x03; + }; + } __attribute__((packed)); + + class GamestickController : public EmulatedSwitchController { + + public: + static constexpr const HardwareID hardware_ids[] = { + {0x0f0d, 0x1011} + }; + + GamestickController(const bluetooth::Address *address) + : EmulatedSwitchController(address) { }; + + void ConvertReportFormat(const bluetooth::HidReport *in_report, bluetooth::HidReport *out_report); + + private: + void HandleInputReport0x01(const GamestickReportData *src, SwitchReportData *dst); + void HandleInputReport0x03(const GamestickReportData *src, SwitchReportData *dst); + + + }; + +} diff --git a/bluetooth-mitm/source/controllers/gembox_controller.cpp b/bluetooth-mitm/source/controllers/gembox_controller.cpp new file mode 100644 index 00000000..a67c8fc9 --- /dev/null +++ b/bluetooth-mitm/source/controllers/gembox_controller.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2020 ndeadly + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 "gembox_controller.hpp" +#include + +namespace ams::controller { + + namespace { + + const constexpr float stick_scale_factor = float(UINT12_MAX) / UINT8_MAX; + + } + + void GemboxController::ConvertReportFormat(const bluetooth::HidReport *in_report, bluetooth::HidReport *out_report) { + auto gembox_report = reinterpret_cast(&in_report->data); + auto switch_report = reinterpret_cast(&out_report->data); + + switch(gembox_report->id) { + case 0x02: + this->HandleInputReport0x02(gembox_report, switch_report); + break; + case 0x07: + this->HandleInputReport0x07(gembox_report, switch_report); + break; + default: + break; + } + + out_report->size = sizeof(SwitchInputReport0x30) + 1; + switch_report->id = 0x30; + switch_report->input0x30.conn_info = 0x0; + switch_report->input0x30.battery = m_battery | m_charging; + std::memset(switch_report->input0x30.motion, 0, sizeof(switch_report->input0x30.motion)); + switch_report->input0x30.timer = os::ConvertToTimeSpan(os::GetSystemTick()).GetMilliSeconds() & 0xff; + } + + void GemboxController::HandleInputReport0x02(const GemboxReportData *src, SwitchReportData *dst) { + dst->input0x30.buttons.minus = src->input0x02.back; + + dst->input0x30.buttons.home = src->input0x02.buttons == 0; + + + this->PackStickData(&dst->input0x30.left_stick, STICK_ZERO, STICK_ZERO); + this->PackStickData(&dst->input0x30.right_stick, STICK_ZERO, STICK_ZERO); + } + + void GemboxController::HandleInputReport0x07(const GemboxReportData *src, SwitchReportData *dst) { + this->PackStickData(&dst->input0x30.left_stick, + static_cast(stick_scale_factor * -static_cast(~src->input0x07.left_stick.x + 1) + 0x7ff) & 0xfff, + static_cast(stick_scale_factor * (UINT8_MAX + static_cast(~src->input0x07.left_stick.y + 1)) + 0x7ff) & 0xfff + ); + this->PackStickData(&dst->input0x30.right_stick, + static_cast(stick_scale_factor * -static_cast(~src->input0x07.right_stick.x + 1) + 0x7ff) & 0xfff, + static_cast(stick_scale_factor * (UINT8_MAX + static_cast(~src->input0x07.right_stick.y + 1)) + 0x7ff) & 0xfff + ); + + dst->input0x30.buttons.dpad_down = (src->input0x07.dpad == GemboxDPad_S) || + (src->input0x07.dpad == GemboxDPad_SE) || + (src->input0x07.dpad == GemboxDPad_SW); + dst->input0x30.buttons.dpad_up = (src->input0x07.dpad == GemboxDPad_N) || + (src->input0x07.dpad == GemboxDPad_NE) || + (src->input0x07.dpad == GemboxDPad_NW); + dst->input0x30.buttons.dpad_right = (src->input0x07.dpad == GemboxDPad_E) || + (src->input0x07.dpad == GemboxDPad_NE) || + (src->input0x07.dpad == GemboxDPad_SE); + dst->input0x30.buttons.dpad_left = (src->input0x07.dpad == GemboxDPad_W) || + (src->input0x07.dpad == GemboxDPad_NW) || + (src->input0x07.dpad == GemboxDPad_SW); + + dst->input0x30.buttons.A = src->input0x07.buttons.B; + dst->input0x30.buttons.B = src->input0x07.buttons.A; + dst->input0x30.buttons.X = src->input0x07.buttons.Y; + dst->input0x30.buttons.Y = src->input0x07.buttons.X; + + dst->input0x30.buttons.R = src->input0x07.buttons.RB; + dst->input0x30.buttons.ZR = src->input0x07.right_trigger > 0; + dst->input0x30.buttons.L = src->input0x07.buttons.LB; + dst->input0x30.buttons.ZL = src->input0x07.left_trigger > 0; + + dst->input0x30.buttons.plus = src->input0x07.buttons.start; + + dst->input0x30.buttons.lstick_press = src->input0x07.buttons.L3; + dst->input0x30.buttons.rstick_press = src->input0x07.buttons.R3; + + dst->input0x30.buttons.capture = 0; + dst->input0x30.buttons.home = 0; + } + +} diff --git a/bluetooth-mitm/source/controllers/gembox_controller.hpp b/bluetooth-mitm/source/controllers/gembox_controller.hpp new file mode 100644 index 00000000..42574213 --- /dev/null +++ b/bluetooth-mitm/source/controllers/gembox_controller.hpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2020 ndeadly + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 "emulated_switch_controller.hpp" + +namespace ams::controller { + + enum GemboxDPadDirection { + GemboxDPad_N, + GemboxDPad_NE, + GemboxDPad_E, + GemboxDPad_SE, + GemboxDPad_S, + GemboxDPad_SW, + GemboxDPad_W, + GemboxDPad_NW, + GemboxDPad_Released = 0x0f + }; + + struct GemboxStickData { + uint8_t x; + uint8_t y; + } __attribute__ ((__packed__)); + + struct GemboxButtonData { + uint8_t A : 1; + uint8_t B : 1; + uint8_t : 1; + uint8_t X : 1; + uint8_t Y : 1; + uint8_t : 1; + uint8_t LB : 1; + uint8_t RB : 1; + + uint8_t : 3; + uint8_t start : 1; + uint8_t : 1; + uint8_t L3 : 1; + uint8_t R3 : 1; + uint8_t : 0; + } __attribute__ ((__packed__)); + + struct GemboxInputReport0x02 { + union { + struct { + uint8_t : 6; + uint8_t back : 1; + uint8_t : 0; + }; + + uint8_t buttons; + }; + } __attribute__((packed)); + + struct GemboxInputReport0x07 { + uint8_t dpad; + GemboxStickData left_stick; + GemboxStickData right_stick; + uint8_t left_trigger; + uint8_t right_trigger; + GemboxButtonData buttons; + } __attribute__((packed)); + + struct GemboxReportData { + uint8_t id; + union { + GemboxInputReport0x02 input0x02; + GemboxInputReport0x07 input0x07; + }; + } __attribute__((packed)); + + class GemboxController : public EmulatedSwitchController { + + public: + static constexpr const HardwareID hardware_ids[] = { + {0x1d79, 0x0009} + }; + + GemboxController(const bluetooth::Address *address) + : EmulatedSwitchController(address) { }; + + void ConvertReportFormat(const bluetooth::HidReport *in_report, bluetooth::HidReport *out_report); + + private: + void HandleInputReport0x02(const GemboxReportData *src, SwitchReportData *dst); + void HandleInputReport0x07(const GemboxReportData *src, SwitchReportData *dst); + + }; + +} diff --git a/bluetooth-mitm/source/controllers/ipega_controller.cpp b/bluetooth-mitm/source/controllers/ipega_controller.cpp new file mode 100644 index 00000000..3087c508 --- /dev/null +++ b/bluetooth-mitm/source/controllers/ipega_controller.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2020 ndeadly + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 "ipega_controller.hpp" +#include + +namespace ams::controller { + + namespace { + + const constexpr float stick_scale_factor = float(UINT12_MAX) / UINT8_MAX; + + } + + void IpegaController::ConvertReportFormat(const bluetooth::HidReport *in_report, bluetooth::HidReport *out_report) { + auto ipega_report = reinterpret_cast(&in_report->data); + auto switch_report = reinterpret_cast(&out_report->data); + + switch(ipega_report->id) { + case 0x02: + this->HandleInputReport0x02(ipega_report, switch_report); + break; + case 0x07: + this->HandleInputReport0x07(ipega_report, switch_report); + break; + default: + break; + } + + out_report->size = sizeof(SwitchInputReport0x30) + 1; + switch_report->id = 0x30; + switch_report->input0x30.conn_info = 0x0; + switch_report->input0x30.battery = m_battery | m_charging; + std::memset(switch_report->input0x30.motion, 0, sizeof(switch_report->input0x30.motion)); + switch_report->input0x30.timer = os::ConvertToTimeSpan(os::GetSystemTick()).GetMilliSeconds() & 0xff; + } + + void IpegaController::HandleInputReport0x02(const IpegaReportData *src, SwitchReportData *dst) { + dst->input0x30.buttons.home = src->input0x02.home; + + this->PackStickData(&dst->input0x30.left_stick, STICK_ZERO, STICK_ZERO); + this->PackStickData(&dst->input0x30.right_stick, STICK_ZERO, STICK_ZERO); + } + + void IpegaController::HandleInputReport0x07(const IpegaReportData *src, SwitchReportData *dst) { + this->PackStickData(&dst->input0x30.left_stick, + static_cast(stick_scale_factor * src->input0x07.left_stick.x) & 0xfff, + static_cast(stick_scale_factor * (UINT8_MAX - src->input0x07.left_stick.y)) & 0xfff + ); + this->PackStickData(&dst->input0x30.right_stick, + static_cast(stick_scale_factor * src->input0x07.right_stick.x) & 0xfff, + static_cast(stick_scale_factor * (UINT8_MAX - src->input0x07.right_stick.y)) & 0xfff + ); + + dst->input0x30.buttons.dpad_down = (src->input0x07.buttons.dpad == IpegaDPad_S) || + (src->input0x07.buttons.dpad == IpegaDPad_SE) || + (src->input0x07.buttons.dpad == IpegaDPad_SW); + dst->input0x30.buttons.dpad_up = (src->input0x07.buttons.dpad == IpegaDPad_N) || + (src->input0x07.buttons.dpad == IpegaDPad_NE) || + (src->input0x07.buttons.dpad == IpegaDPad_NW); + dst->input0x30.buttons.dpad_right = (src->input0x07.buttons.dpad == IpegaDPad_E) || + (src->input0x07.buttons.dpad == IpegaDPad_NE) || + (src->input0x07.buttons.dpad == IpegaDPad_SE); + dst->input0x30.buttons.dpad_left = (src->input0x07.buttons.dpad == IpegaDPad_W) || + (src->input0x07.buttons.dpad == IpegaDPad_NW) || + (src->input0x07.buttons.dpad == IpegaDPad_SW); + + dst->input0x30.buttons.A = src->input0x07.buttons.B; + dst->input0x30.buttons.B = src->input0x07.buttons.A; + dst->input0x30.buttons.X = src->input0x07.buttons.Y; + dst->input0x30.buttons.Y = src->input0x07.buttons.X; + + dst->input0x30.buttons.R = src->input0x07.buttons.RB; + dst->input0x30.buttons.ZR = src->input0x07.buttons.RT; + dst->input0x30.buttons.L = src->input0x07.buttons.LB; + dst->input0x30.buttons.ZL = src->input0x07.buttons.LT; + + dst->input0x30.buttons.minus = src->input0x07.buttons.view; + dst->input0x30.buttons.plus = src->input0x07.buttons.menu; + + dst->input0x30.buttons.lstick_press = src->input0x07.buttons.lstick_press; + dst->input0x30.buttons.rstick_press = src->input0x07.buttons.rstick_press; + + dst->input0x30.buttons.capture = 0; + dst->input0x30.buttons.home = 0; + } + +} diff --git a/bluetooth-mitm/source/controllers/ipega_controller.hpp b/bluetooth-mitm/source/controllers/ipega_controller.hpp new file mode 100644 index 00000000..e2f0a9e3 --- /dev/null +++ b/bluetooth-mitm/source/controllers/ipega_controller.hpp @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2020 ndeadly + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 "emulated_switch_controller.hpp" + +namespace ams::controller { + + enum IpegaDPadDirection { + IpegaDPad_N, + IpegaDPad_NE, + IpegaDPad_E, + IpegaDPad_SE, + IpegaDPad_S, + IpegaDPad_SW, + IpegaDPad_W, + IpegaDPad_NW, + IpegaDPad_Released = 0x88 + }; + + struct IpegaStickData { + uint8_t x; + uint8_t y; + } __attribute__((packed)); + + struct IpegaButtonData { + uint8_t dpad; + + uint8_t A : 1; + uint8_t B : 1; + uint8_t : 1; + uint8_t X : 1; + uint8_t Y : 1; + uint8_t : 1; + uint8_t LB : 1; + uint8_t RB : 1; + + uint8_t LT : 1; + uint8_t RT : 1; + uint8_t view : 1; + uint8_t menu : 1; + uint8_t : 1; + uint8_t lstick_press : 1; + uint8_t rstick_press : 1; + uint8_t : 0; + } __attribute__((packed)); + + struct IpegaInputReport0x02 { + uint8_t : 7; + uint8_t home : 1; + } __attribute__((packed)); + + struct IpegaInputReport0x07 { + IpegaStickData left_stick; + IpegaStickData right_stick; + IpegaButtonData buttons; + uint8_t right_trigger; + uint8_t left_trigger; + } __attribute__((packed)); + + struct IpegaReportData { + uint8_t id; + union { + IpegaInputReport0x02 input0x02; + IpegaInputReport0x07 input0x07; + }; + } __attribute__ ((__packed__)); + + class IpegaController : public EmulatedSwitchController { + + public: + static constexpr const HardwareID hardware_ids[] = { + {0x1949, 0x0402} + }; + + IpegaController(const bluetooth::Address *address) + : EmulatedSwitchController(address) { }; + + void ConvertReportFormat(const bluetooth::HidReport *in_report, bluetooth::HidReport *out_report); + + private: + void HandleInputReport0x02(const IpegaReportData *src, SwitchReportData *dst); + void HandleInputReport0x07(const IpegaReportData *src, SwitchReportData *dst); + + }; + +} diff --git a/bluetooth-mitm/source/controllers/ouya_controller.cpp b/bluetooth-mitm/source/controllers/ouya_controller.cpp new file mode 100644 index 00000000..74d5f9ff --- /dev/null +++ b/bluetooth-mitm/source/controllers/ouya_controller.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2020 ndeadly + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 "ouya_controller.hpp" +#include + +namespace ams::controller { + + namespace { + + constexpr float stick_scale_factor = float(UINT12_MAX) / UINT16_MAX; + + } + + void OuyaController::ConvertReportFormat(const bluetooth::HidReport *in_report, bluetooth::HidReport *out_report) { + auto ouya_report = reinterpret_cast(&in_report->data); + auto switch_report = reinterpret_cast(&out_report->data); + + switch(ouya_report->id) { + case 0x03: + this->HandleInputReport0x03(ouya_report, switch_report); + break; + case 0x07: + this->HandleInputReport0x07(ouya_report, switch_report); + break; + default: + break; + } + + out_report->size = sizeof(SwitchInputReport0x30) + 1; + switch_report->id = 0x30; + switch_report->input0x30.conn_info = 0x0; + switch_report->input0x30.battery = m_battery | m_charging; + std::memset(switch_report->input0x30.motion, 0, sizeof(switch_report->input0x30.motion)); + switch_report->input0x30.timer = os::ConvertToTimeSpan(os::GetSystemTick()).GetMilliSeconds() & 0xff; + } + + void OuyaController::HandleInputReport0x03(const OuyaReportData *src, SwitchReportData *dst) { + m_battery = src->input0x03.battery / 52 << 1; + + this->PackStickData(&dst->input0x30.left_stick, STICK_ZERO, STICK_ZERO); + this->PackStickData(&dst->input0x30.right_stick, STICK_ZERO, STICK_ZERO); + } + + void OuyaController::HandleInputReport0x07(const OuyaReportData *src, SwitchReportData *dst) { + this->PackStickData(&dst->input0x30.left_stick, + static_cast(stick_scale_factor * src->input0x07.left_stick.x) & 0xfff, + static_cast(stick_scale_factor * (UINT16_MAX - src->input0x07.left_stick.y)) & 0xfff + ); + this->PackStickData(&dst->input0x30.right_stick, + static_cast(stick_scale_factor * src->input0x07.right_stick.x) & 0xfff, + static_cast(stick_scale_factor * (UINT16_MAX - src->input0x07.right_stick.y)) & 0xfff + ); + + dst->input0x30.buttons.dpad_down = src->input0x07.buttons.dpad_down; + dst->input0x30.buttons.dpad_up = src->input0x07.buttons.dpad_up; + dst->input0x30.buttons.dpad_right = src->input0x07.buttons.dpad_right; + dst->input0x30.buttons.dpad_left = src->input0x07.buttons.dpad_left; + + dst->input0x30.buttons.A = src->input0x07.buttons.A; + dst->input0x30.buttons.B = src->input0x07.buttons.O; + dst->input0x30.buttons.X = src->input0x07.buttons.Y; + dst->input0x30.buttons.Y = src->input0x07.buttons.U; + + dst->input0x30.buttons.R = src->input0x07.buttons.RB; + dst->input0x30.buttons.ZR = src->input0x07.buttons.RT; + dst->input0x30.buttons.L = src->input0x07.buttons.LB; + dst->input0x30.buttons.ZL = src->input0x07.buttons.LT; + + dst->input0x30.buttons.minus = 0; + dst->input0x30.buttons.plus = 0; + + dst->input0x30.buttons.lstick_press = src->input0x07.buttons.LS; + dst->input0x30.buttons.rstick_press = src->input0x07.buttons.RS; + + dst->input0x30.buttons.capture = 0; + dst->input0x30.buttons.home = src->input0x07.buttons.center_hold; + } + +} diff --git a/bluetooth-mitm/source/controllers/ouya_controller.hpp b/bluetooth-mitm/source/controllers/ouya_controller.hpp new file mode 100644 index 00000000..707fb6d9 --- /dev/null +++ b/bluetooth-mitm/source/controllers/ouya_controller.hpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2020 ndeadly + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 "emulated_switch_controller.hpp" + +namespace ams::controller { + + struct OuyaStickData { + uint16_t x; + uint16_t y; + } __attribute__ ((__packed__)); + + struct OuyaButtonData { + uint8_t O : 1; + uint8_t U : 1; + uint8_t Y : 1; + uint8_t A : 1; + uint8_t LB : 1; + uint8_t RB : 1; + uint8_t LS : 1; + uint8_t RS : 1; + + uint8_t dpad_up : 1; + uint8_t dpad_down : 1; + uint8_t dpad_left : 1; + uint8_t dpad_right : 1; + uint8_t LT : 1; + uint8_t RT : 1; + uint8_t center_press : 1; + uint8_t center_hold : 1; + } __attribute__ ((__packed__));; + + struct OuyaInputReport0x03 { + uint8_t battery; + uint8_t _unk[6]; + } __attribute__((packed)); + + struct OuyaInputReport0x07 { + OuyaStickData left_stick; + OuyaStickData right_stick; + uint16_t left_trigger; + uint16_t right_trigger; + OuyaButtonData buttons; + } __attribute__((packed)); + + struct OuyaReportData { + uint8_t id; + union { + OuyaInputReport0x03 input0x03; + OuyaInputReport0x07 input0x07; + }; + } __attribute__((packed)); + + class OuyaController : public EmulatedSwitchController { + + public: + static constexpr const HardwareID hardware_ids[] = { + {0x2836, 0x0001} + }; + + OuyaController(const bluetooth::Address *address) + : EmulatedSwitchController(address) { }; + + void ConvertReportFormat(const bluetooth::HidReport *in_report, bluetooth::HidReport *out_report); + + private: + void HandleInputReport0x03(const OuyaReportData *src, SwitchReportData *dst); + void HandleInputReport0x07(const OuyaReportData *src, SwitchReportData *dst); + + }; + +} diff --git a/btdrv-mitm/source/controllers/switch_controller.cpp b/bluetooth-mitm/source/controllers/switch_controller.cpp similarity index 100% rename from btdrv-mitm/source/controllers/switch_controller.cpp rename to bluetooth-mitm/source/controllers/switch_controller.cpp diff --git a/btdrv-mitm/source/controllers/switch_controller.hpp b/bluetooth-mitm/source/controllers/switch_controller.hpp similarity index 80% rename from btdrv-mitm/source/controllers/switch_controller.hpp rename to bluetooth-mitm/source/controllers/switch_controller.hpp index 62b40090..9cf20cd0 100644 --- a/btdrv-mitm/source/controllers/switch_controller.hpp +++ b/bluetooth-mitm/source/controllers/switch_controller.hpp @@ -14,8 +14,8 @@ * along with this program. If not, see . */ #pragma once -#include "../bluetooth/bluetooth_types.hpp" -#include "../bluetooth/bluetooth_hid_report.hpp" +#include "../btdrv_mitm/bluetooth/bluetooth_types.hpp" +#include "../btdrv_mitm/bluetooth/bluetooth_hid_report.hpp" namespace ams::controller { @@ -67,6 +67,32 @@ namespace ams::controller { uint16_t gyro_3; } __attribute__ ((__packed__)); + enum SubCmdType : u8 { + SubCmd_GetControllerState = 0x00, + SubCmd_ManualPair = 0x01, + SubCmd_RequestDeviceInfo = 0x02, + SubCmd_SetInputReportMode = 0x03, + SubCmd_TriggersElapsedTime = 0x04, + SubCmd_SetHciState = 0x06, + SubCmd_ResetPairingInfo = 0x07, + SubCmd_SetShipPowerState = 0x08, + SubCmd_SpiFlashRead = 0x10, + SubCmd_SpiFlashWrite = 0x11, + SubCmd_SpiSectorErase = 0x12, + SubCmd_ResetMcu = 0x20, + SubCmd_SetMcuConfig = 0x21, + SubCmd_SetMcuState = 0x22, + SubCmd_SetPlayerLeds = 0x30, + SubCmd_GetPlayerLeds = 0x31, + SubCmd_SetHomeLed = 0x38, + SubCmd_EnableImu = 0x40, + SubCmd_SetImuSensitivity = 0x41, + SubCmd_WriteImuRegisters = 0x42, + SubCmd_ReadImuRegisters = 0x43, + SubCmd_EnableVibration = 0x48, + SubCmd_GetRegulatedVoltage = 0x50, + }; + struct SwitchOutputReport0x01; struct SwitchOutputReport0x03; struct SwitchOutputReport0x10; @@ -101,9 +127,8 @@ namespace ams::controller { SwitchStickData right_stick; uint8_t vibrator; - Switch6AxisData imu_0ms; - Switch6AxisData imu_5ms; - Switch6AxisData imu_10ms; + // IMU samples at 0, 5 and 10ms + Switch6AxisData motion[3]; } __attribute__ ((__packed__)); struct SwitchInputReport0x31; diff --git a/btdrv-mitm/source/controllers/wii_controller.cpp b/bluetooth-mitm/source/controllers/wii_controller.cpp similarity index 97% rename from btdrv-mitm/source/controllers/wii_controller.cpp rename to bluetooth-mitm/source/controllers/wii_controller.cpp index 7052e356..e26a2989 100644 --- a/btdrv-mitm/source/controllers/wii_controller.cpp +++ b/bluetooth-mitm/source/controllers/wii_controller.cpp @@ -72,6 +72,7 @@ namespace ams::controller { switch_report->id = 0x30; switch_report->input0x30.conn_info = 0x0; switch_report->input0x30.battery = m_battery | m_charging; + std::memset(switch_report->input0x30.motion, 0, sizeof(switch_report->input0x30.motion)); switch_report->input0x30.timer = os::ConvertToTimeSpan(os::GetSystemTick()).GetMilliSeconds() & 0xff; } @@ -332,15 +333,6 @@ namespace ams::controller { return bluetooth::hid::report::SendHidReport(&m_address, &s_output_report); } - Result WiiController::SetPlayerLeds(uint8_t mask) { - s_output_report.size = sizeof(WiiOutputReport0x15) + 1; - auto report_data = reinterpret_cast(s_output_report.data); - report_data->id = 0x11; - report_data->output0x11.leds = mask; - - return bluetooth::hid::report::SendHidReport(&m_address, &s_output_report); - } - Result WiiController::QueryStatus(void) { s_output_report.size = sizeof(WiiOutputReport0x15) + 1; auto report_data = reinterpret_cast(s_output_report.data); diff --git a/btdrv-mitm/source/controllers/wii_controller.hpp b/bluetooth-mitm/source/controllers/wii_controller.hpp similarity index 99% rename from btdrv-mitm/source/controllers/wii_controller.hpp rename to bluetooth-mitm/source/controllers/wii_controller.hpp index 1cabbbae..b10888a1 100644 --- a/btdrv-mitm/source/controllers/wii_controller.hpp +++ b/bluetooth-mitm/source/controllers/wii_controller.hpp @@ -304,7 +304,6 @@ namespace ams::controller { Result ReadMemory(uint32_t read_addr, uint16_t size); Result SetReportMode(uint8_t mode); - Result SetPlayerLeds(uint8_t mask); Result QueryStatus(void); Result SetPlayerLed(uint8_t led_mask); diff --git a/btdrv-mitm/source/controllers/xbox_one_controller.cpp b/bluetooth-mitm/source/controllers/xbox_one_controller.cpp similarity index 98% rename from btdrv-mitm/source/controllers/xbox_one_controller.cpp rename to bluetooth-mitm/source/controllers/xbox_one_controller.cpp index 04fa2c5a..af7581a4 100644 --- a/btdrv-mitm/source/controllers/xbox_one_controller.cpp +++ b/bluetooth-mitm/source/controllers/xbox_one_controller.cpp @@ -54,6 +54,7 @@ namespace ams::controller { switch_report->id = 0x30; switch_report->input0x30.conn_info = 0x0; switch_report->input0x30.battery = m_battery | m_charging; + std::memset(switch_report->input0x30.motion, 0, sizeof(switch_report->input0x30.motion)); switch_report->input0x30.timer = os::ConvertToTimeSpan(os::GetSystemTick()).GetMilliSeconds() & 0xff; } diff --git a/btdrv-mitm/source/controllers/xbox_one_controller.hpp b/bluetooth-mitm/source/controllers/xbox_one_controller.hpp similarity index 94% rename from btdrv-mitm/source/controllers/xbox_one_controller.hpp rename to bluetooth-mitm/source/controllers/xbox_one_controller.hpp index cb6d716f..0e2b8abb 100644 --- a/btdrv-mitm/source/controllers/xbox_one_controller.hpp +++ b/bluetooth-mitm/source/controllers/xbox_one_controller.hpp @@ -112,9 +112,10 @@ namespace ams::controller { public: static constexpr const HardwareID hardware_ids[] = { - {0x045e, 0x02e0}, // Official Xbox One S Controller - {0x045e, 0x02fd} // Official Xbox One S Controller - }; + {0x045e, 0x02e0}, // Official Xbox One S Controller + {0x045e, 0x02fd}, // Official Xbox One S Controller + {0x045e, 0x0b00} // Official Xbox One Elite 2 Controller + }; XboxOneController(const bluetooth::Address *address) : EmulatedSwitchController(address) { }; diff --git a/bluetooth-mitm/source/controllers/xiaomi_controller.cpp b/bluetooth-mitm/source/controllers/xiaomi_controller.cpp new file mode 100644 index 00000000..62ac2e28 --- /dev/null +++ b/bluetooth-mitm/source/controllers/xiaomi_controller.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2020 ndeadly + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 "xiaomi_controller.hpp" +#include + +namespace ams::controller { + + namespace { + + constexpr uint8_t init_packet[] = {0x20, 0x00, 0x00}; // packet to init vibration apparently + + const constexpr float stick_scale_factor = float(UINT12_MAX) / UINT8_MAX; + + } + + Result XiaomiController::Initialize(void) { + R_TRY(EmulatedSwitchController::Initialize()); + s_output_report.size = sizeof(init_packet); + std::memcpy(s_output_report.data, init_packet, sizeof(init_packet)); + R_TRY(bluetooth::hid::report::SendHidReport(&m_address, &s_output_report)); + return ams::ResultSuccess(); + } + + void XiaomiController::ConvertReportFormat(const bluetooth::HidReport *in_report, bluetooth::HidReport *out_report) { + auto xiaomi_report = reinterpret_cast(&in_report->data); + auto switch_report = reinterpret_cast(&out_report->data); + + switch(xiaomi_report->id) { + case 0x04: + this->HandleInputReport0x04(xiaomi_report, switch_report); + break; + default: + break; + } + + out_report->size = sizeof(SwitchInputReport0x30) + 1; + switch_report->id = 0x30; + switch_report->input0x30.conn_info = 0x0; + switch_report->input0x30.battery = m_battery | m_charging; + std::memset(switch_report->input0x30.motion, 0, sizeof(switch_report->input0x30.motion)); + switch_report->input0x30.timer = os::ConvertToTimeSpan(os::GetSystemTick()).GetMilliSeconds() & 0xff; + } + + void XiaomiController::HandleInputReport0x04(const XiaomiReportData *src, SwitchReportData *dst) { + m_battery = src->input0x04.battery / 52 << 1; + + this->PackStickData(&dst->input0x30.left_stick, + static_cast(stick_scale_factor * src->input0x04.left_stick.x) & 0xfff, + static_cast(stick_scale_factor * (UINT8_MAX - src->input0x04.left_stick.y)) & 0xfff + ); + this->PackStickData(&dst->input0x30.right_stick, + static_cast(stick_scale_factor * src->input0x04.right_stick.x) & 0xfff, + static_cast(stick_scale_factor * (UINT8_MAX - src->input0x04.right_stick.y)) & 0xfff + ); + + dst->input0x30.buttons.dpad_down = (src->input0x04.buttons.dpad == XiaomiDPad_S) || + (src->input0x04.buttons.dpad == XiaomiDPad_SE) || + (src->input0x04.buttons.dpad == XiaomiDPad_SW); + dst->input0x30.buttons.dpad_up = (src->input0x04.buttons.dpad == XiaomiDPad_N) || + (src->input0x04.buttons.dpad == XiaomiDPad_NE) || + (src->input0x04.buttons.dpad == XiaomiDPad_NW); + dst->input0x30.buttons.dpad_right = (src->input0x04.buttons.dpad == XiaomiDPad_E) || + (src->input0x04.buttons.dpad == XiaomiDPad_NE) || + (src->input0x04.buttons.dpad == XiaomiDPad_SE); + dst->input0x30.buttons.dpad_left = (src->input0x04.buttons.dpad == XiaomiDPad_W) || + (src->input0x04.buttons.dpad == XiaomiDPad_NW) || + (src->input0x04.buttons.dpad == XiaomiDPad_SW); + + dst->input0x30.buttons.A = src->input0x04.buttons.B; + dst->input0x30.buttons.B = src->input0x04.buttons.A; + dst->input0x30.buttons.X = src->input0x04.buttons.Y; + dst->input0x30.buttons.Y = src->input0x04.buttons.X; + + dst->input0x30.buttons.R = src->input0x04.buttons.R1; + dst->input0x30.buttons.ZR = src->input0x04.buttons.R2; + dst->input0x30.buttons.L = src->input0x04.buttons.L1; + dst->input0x30.buttons.ZL = src->input0x04.buttons.L2; + + dst->input0x30.buttons.minus = src->input0x04.buttons.back; + dst->input0x30.buttons.plus = src->input0x04.buttons.menu; + + dst->input0x30.buttons.lstick_press = src->input0x04.buttons.lstick_press; + dst->input0x30.buttons.rstick_press = src->input0x04.buttons.rstick_press; + + dst->input0x30.buttons.capture = 0; + dst->input0x30.buttons.home = src->input0x04.home; + } + +} diff --git a/bluetooth-mitm/source/controllers/xiaomi_controller.hpp b/bluetooth-mitm/source/controllers/xiaomi_controller.hpp new file mode 100644 index 00000000..4e8b18b1 --- /dev/null +++ b/bluetooth-mitm/source/controllers/xiaomi_controller.hpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2020 ndeadly + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 "emulated_switch_controller.hpp" + +namespace ams::controller { + + enum XiaomiDPadDirection { + XiaomiDPad_N, + XiaomiDPad_NE, + XiaomiDPad_E, + XiaomiDPad_SE, + XiaomiDPad_S, + XiaomiDPad_SW, + XiaomiDPad_W, + XiaomiDPad_NW, + XiaomiDPad_Released = 0x0f + }; + + struct XiaomiStickData { + uint8_t x; + uint8_t y; + } __attribute__((packed)); + + struct XiaomiButtonData { + uint8_t A : 1; + uint8_t B : 1; + uint8_t : 1; + uint8_t X : 1; + uint8_t Y : 1; + uint8_t : 1; + uint8_t L1 : 1; + uint8_t R1 : 1; + + uint8_t L2 : 1; + uint8_t R2 : 1; + uint8_t back : 1; + uint8_t menu : 1; + uint8_t : 1; + uint8_t lstick_press : 1; + uint8_t rstick_press : 1; + uint8_t : 0; + + uint8_t _unk; + + uint8_t dpad; + } __attribute__((packed)); + + struct XiaomiInputReport0x04 { + XiaomiButtonData buttons; + XiaomiStickData left_stick; + XiaomiStickData right_stick; + uint8_t _unk0[2]; + uint8_t left_trigger; + uint8_t right_trigger; + uint16_t accel_x; + uint16_t accel_y; + uint16_t accel_z; + uint8_t battery; + uint8_t home : 1; + uint8_t : 0; + } __attribute__((packed)); + + struct XiaomiReportData{ + uint8_t id; + union { + XiaomiInputReport0x04 input0x04; + }; + } __attribute__((packed)); + + class XiaomiController : public EmulatedSwitchController { + + public: + static constexpr const HardwareID hardware_ids[] = { + {0x2717, 0x3144} // Xiaomi Mi Controller + }; + + XiaomiController(const bluetooth::Address *address) + : EmulatedSwitchController(address) { }; + + Result Initialize(void); + + void ConvertReportFormat(const bluetooth::HidReport *in_report, bluetooth::HidReport *out_report); + + private: + void HandleInputReport0x04(const XiaomiReportData *src, SwitchReportData *dst); + + }; + +} diff --git a/libnx b/libnx index 050a95dc..ffde37ae 160000 --- a/libnx +++ b/libnx @@ -1 +1 @@ -Subproject commit 050a95dcc2223fe534eb97d07a76f899d45ba8e6 +Subproject commit ffde37ae3d0be30269f5aa5d0c1986e6d7dcdb10