From ec61c3e3c7ab477c4c2708951743604ab7d50fa2 Mon Sep 17 00:00:00 2001 From: capitalistspz Date: Mon, 7 Aug 2023 18:42:39 +0100 Subject: [PATCH 01/12] Add hidapi wiimote --- CMakeLists.txt | 11 ++++- src/input/CMakeLists.txt | 38 ++++++++++------ src/input/InputManager.h | 3 ++ .../api/Wiimote/WiimoteControllerProvider.cpp | 4 +- .../api/Wiimote/hidapi/HidapiWiimote.cpp | 43 +++++++++++++++++++ src/input/api/Wiimote/hidapi/HidapiWiimote.h | 23 ++++++++++ vcpkg.json | 1 + 7 files changed, 109 insertions(+), 14 deletions(-) create mode 100644 src/input/api/Wiimote/hidapi/HidapiWiimote.cpp create mode 100644 src/input/api/Wiimote/hidapi/HidapiWiimote.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 57615e867..6c73ebae0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,7 +88,10 @@ option(ENABLE_DISCORD_RPC "Enables the Discord Rich Presence feature" ON) if (WIN32) option(ENABLE_XINPUT "Enables the usage of XInput" ON) option(ENABLE_DIRECTINPUT "Enables the usage of DirectInput" ON) - add_compile_definitions(HAS_DIRECTINPUT) + option(ENABLE_HIDAPI "Build with HIDAPI" OFF) + set(ENABLE_WIIMOTE ON) +elseif (UNIX) + option(ENABLE_HIDAPI "Build with HIDAPI" ON) endif() option(ENABLE_SDL "Enables the SDLController backend" ON) @@ -155,6 +158,12 @@ if (ENABLE_DISCORD_RPC) target_include_directories(discord-rpc INTERFACE ./dependencies/discord-rpc/include) endif() +if (ENABLE_HIDAPI) + find_package(hidapi REQUIRED) + set(ENABLE_WIIMOTE ON) + add_compile_definitions(HAS_HIDAPI) +endif () + if(UNIX AND NOT APPLE) if(ENABLE_FERAL_GAMEMODE) add_compile_definitions(ENABLE_FERAL_GAMEMODE) diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt index ecb88cd28..9f5423718 100644 --- a/src/input/CMakeLists.txt +++ b/src/input/CMakeLists.txt @@ -44,18 +44,6 @@ add_library(CemuInput set_property(TARGET CemuInput PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") if(WIN32) - # Native wiimote (Win32 only for now) - target_sources(CemuInput PRIVATE - api/Wiimote/WiimoteControllerProvider.h - api/Wiimote/windows/WinWiimoteDevice.cpp - api/Wiimote/windows/WinWiimoteDevice.h - api/Wiimote/WiimoteControllerProvider.cpp - api/Wiimote/WiimoteMessages.h - api/Wiimote/NativeWiimoteController.h - api/Wiimote/NativeWiimoteController.cpp - api/Wiimote/WiimoteDevice.h - ) - # XInput target_sources(CemuInput PRIVATE api/XInput/XInputControllerProvider.cpp @@ -73,6 +61,29 @@ if(WIN32) ) endif() +if (ENABLE_WIIMOTE) + target_sources(CemuInput PRIVATE + api/Wiimote/WiimoteControllerProvider.h + api/Wiimote/WiimoteControllerProvider.cpp + api/Wiimote/WiimoteMessages.h + api/Wiimote/NativeWiimoteController.h + api/Wiimote/NativeWiimoteController.cpp + api/Wiimote/WiimoteDevice.h + ) + if (ENABLE_HIDAPI) + target_sources(CemuInput PRIVATE + api/Wiimote/hidapi/HidapiWiimote.cpp + api/Wiimote/hidapi/HidapiWiimote.h + ) + elseif (WIN32) + target_sources(CemuInput PRIVATE + api/Wiimote/windows/WinWiimoteDevice.cpp + api/Wiimote/windows/WinWiimoteDevice.h + ) + endif() +endif () + + target_include_directories(CemuInput PUBLIC "../") target_link_libraries(CemuInput PRIVATE @@ -87,6 +98,9 @@ target_link_libraries(CemuInput PRIVATE pugixml::pugixml SDL2::SDL2 ) +if (ENABLE_HIDAPI) + target_link_libraries(CemuInput PRIVATE hidapi::hidapi) +endif() if (ENABLE_WXWIDGETS) target_link_libraries(CemuInput PRIVATE wx::base wx::core) diff --git a/src/input/InputManager.h b/src/input/InputManager.h index 848c4810b..345f7ba00 100644 --- a/src/input/InputManager.h +++ b/src/input/InputManager.h @@ -3,6 +3,9 @@ #if BOOST_OS_WINDOWS #include "input/api/DirectInput/DirectInputControllerProvider.h" #include "input/api/XInput/XInputControllerProvider.h" +#endif + +#if defined(HAS_HIDAPI) || BOOST_OS_WINDOWS #include "input/api/Wiimote/WiimoteControllerProvider.h" #endif diff --git a/src/input/api/Wiimote/WiimoteControllerProvider.cpp b/src/input/api/Wiimote/WiimoteControllerProvider.cpp index a742a9d3a..63f53a5d6 100644 --- a/src/input/api/Wiimote/WiimoteControllerProvider.cpp +++ b/src/input/api/Wiimote/WiimoteControllerProvider.cpp @@ -2,7 +2,9 @@ #include "input/api/Wiimote/NativeWiimoteController.h" #include "input/api/Wiimote/WiimoteMessages.h" -#if BOOST_OS_WINDOWS +#ifdef HAS_HIDAPI +#include "input/api/Wiimote/hidapi/HidapiWiimote.h" +#elif BOOST_OS_WINDOWS #include "input/api/Wiimote/windows/WinWiimoteDevice.h" #endif diff --git a/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp b/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp new file mode 100644 index 000000000..180ca2857 --- /dev/null +++ b/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp @@ -0,0 +1,43 @@ +#include "HidapiWiimote.h" + +HidapiWiimote::HidapiWiimote(fs::path const& device_path, uint64_t identifier) + : m_handle(hid_open_path(_pathToUtf8(device_path).c_str())), m_identifier(identifier) { + +} + +bool HidapiWiimote::write_data(const std::vector &data) { + return hid_write(m_handle, data.data(), data.size()) >= 0; +} + +std::optional> HidapiWiimote::read_data() { + std::array read_data{}; + const auto result = hid_read(m_handle, read_data.data(), 20); + if (result < 0) + return {}; + return {{read_data.cbegin(), read_data.cend()}}; +} + +std::vector HidapiWiimote::get_devices() { + std::vector wiimote_devices; + hid_init(); + const auto device_enumeration = hid_enumerate(0x057e, 0x0306); + auto it = device_enumeration; + while (it){ + // Enough to have a unique id for each device within a session + uint64_t id = (static_cast(it->interface_number) << 32) | + (static_cast(it->usage_page) << 16) | + (it->usage); + wiimote_devices.push_back(std::make_shared(it->path, id)); + it = it->next; + } + hid_free_enumeration(device_enumeration); + return wiimote_devices; +} + +bool HidapiWiimote::operator==(WiimoteDevice& o) const { + return m_identifier == dynamic_cast(o).m_identifier; +} + +HidapiWiimote::~HidapiWiimote() { + hid_close(m_handle); +} diff --git a/src/input/api/Wiimote/hidapi/HidapiWiimote.h b/src/input/api/Wiimote/hidapi/HidapiWiimote.h new file mode 100644 index 000000000..298556d65 --- /dev/null +++ b/src/input/api/Wiimote/hidapi/HidapiWiimote.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +class HidapiWiimote : public WiimoteDevice { +public: + HidapiWiimote(fs::path const& device_path, uint64_t identifier); + ~HidapiWiimote() override; + + bool write_data(const std::vector &data) override; + std::optional> read_data() override; + bool operator==(WiimoteDevice& o) const override; + + static std::vector get_devices(); + +private: + hid_device* m_handle; + uint64_t m_identifier; + +}; + +using WiimoteDevice_t = HidapiWiimote; \ No newline at end of file diff --git a/vcpkg.json b/vcpkg.json index d0facf8b6..642e94d9b 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -26,6 +26,7 @@ "boost-static-string", "boost-random", "fmt", + "hidapi", "libpng", "glm", { From 74b5a100204fee4653da6a846ceb43323b8aceb5 Mon Sep 17 00:00:00 2001 From: capitalistspz Date: Mon, 7 Aug 2023 19:23:55 +0100 Subject: [PATCH 02/12] message size correction, no magic numbers --- src/input/api/Wiimote/hidapi/HidapiWiimote.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp b/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp index 180ca2857..5e5d500b1 100644 --- a/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp +++ b/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp @@ -1,5 +1,9 @@ #include "HidapiWiimote.h" +static constexpr uint16 WIIMOTE_VENDOR_ID = 0x057e; +static constexpr uint16 WIIMOTE_PRODUCT_ID = 0x0306; +static constexpr uint16 WIIMOTE_MAX_MESSAGE_LENGTH = 21; + HidapiWiimote::HidapiWiimote(fs::path const& device_path, uint64_t identifier) : m_handle(hid_open_path(_pathToUtf8(device_path).c_str())), m_identifier(identifier) { @@ -10,8 +14,8 @@ bool HidapiWiimote::write_data(const std::vector &data) { } std::optional> HidapiWiimote::read_data() { - std::array read_data{}; - const auto result = hid_read(m_handle, read_data.data(), 20); + std::array read_data{}; + const auto result = hid_read(m_handle, read_data.data(), WIIMOTE_MAX_MESSAGE_LENGTH); if (result < 0) return {}; return {{read_data.cbegin(), read_data.cend()}}; @@ -20,7 +24,7 @@ std::optional> HidapiWiimote::read_data() { std::vector HidapiWiimote::get_devices() { std::vector wiimote_devices; hid_init(); - const auto device_enumeration = hid_enumerate(0x057e, 0x0306); + const auto device_enumeration = hid_enumerate(WIIMOTE_VENDOR_ID, WIIMOTE_PRODUCT_ID); auto it = device_enumeration; while (it){ // Enough to have a unique id for each device within a session From 10a1b33bd56cd3400035e506891ea95f2e7978d7 Mon Sep 17 00:00:00 2001 From: capitalistspz Date: Mon, 7 Aug 2023 21:00:40 +0100 Subject: [PATCH 03/12] whoops --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c73ebae0..ced142c19 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,6 +89,7 @@ if (WIN32) option(ENABLE_XINPUT "Enables the usage of XInput" ON) option(ENABLE_DIRECTINPUT "Enables the usage of DirectInput" ON) option(ENABLE_HIDAPI "Build with HIDAPI" OFF) + add_compile_definitions(HAS_DIRECTINPUT) set(ENABLE_WIIMOTE ON) elseif (UNIX) option(ENABLE_HIDAPI "Build with HIDAPI" ON) From 1639e4f2cf7380f003baf13a35e9baa31828b87d Mon Sep 17 00:00:00 2001 From: capitalistspz Date: Mon, 7 Aug 2023 22:55:24 +0100 Subject: [PATCH 04/12] logging changes, variable rename --- .../api/Wiimote/WiimoteControllerProvider.cpp | 114 +++++++----------- .../api/Wiimote/hidapi/HidapiWiimote.cpp | 6 +- 2 files changed, 46 insertions(+), 74 deletions(-) diff --git a/src/input/api/Wiimote/WiimoteControllerProvider.cpp b/src/input/api/Wiimote/WiimoteControllerProvider.cpp index 63f53a5d6..b16ff7d27 100644 --- a/src/input/api/Wiimote/WiimoteControllerProvider.cpp +++ b/src/input/api/Wiimote/WiimoteControllerProvider.cpp @@ -8,6 +8,11 @@ #include "input/api/Wiimote/windows/WinWiimoteDevice.h" #endif +#ifdef WIIMOTE_DEBUG +#define WIIMOTE_DEBUG_LOG(FMT, ARGS...) cemuLog_logDebug(LogType::Force, FMT, ##ARGS); +#else +#define WIIMOTE_DEBUG_LOG(FMT, ARGS...) +#endif #include WiimoteControllerProvider::WiimoteControllerProvider() @@ -165,9 +170,7 @@ void WiimoteControllerProvider::reader_thread() { case kStatus: { -#ifdef WIIMOTE_DEBUG - printf("WiimoteControllerProvider::read_thread: kStatus\n"); -#endif + WIIMOTE_DEBUG_LOG("WiimoteControllerProvider::read_thread: kStatus") new_state.buttons = (*(uint16*)data) & (~0x60E0); data += 2; new_state.flags = *data; @@ -185,9 +188,7 @@ void WiimoteControllerProvider::reader_thread() if (HAS_FLAG(new_state.flags, kExtensionConnected)) { -#ifdef WIIMOTE_DEBUG - printf("\tExtension flag is set\n"); -#endif + WIIMOTE_DEBUG_LOG("Extension flag is set") if(new_state.m_extension.index() == 0) request_extension(index); } @@ -201,9 +202,7 @@ void WiimoteControllerProvider::reader_thread() break; case kRead: { -#ifdef WIIMOTE_DEBUG - printf("WiimoteControllerProvider::read_thread: kRead\n"); -#endif + WIIMOTE_DEBUG_LOG("WiimoteControllerProvider::read_thread: kRead") new_state.buttons = (*(uint16*)data) & (~0x60E0); data += 2; const uint8 error_flag = *data & 0xF, size = (*data >> 4) + 1; @@ -211,10 +210,9 @@ void WiimoteControllerProvider::reader_thread() if (error_flag) { + // 7 means that wiimote is already enabled or not available -#ifdef WIIMOTE_DEBUG - printf("Received error on data read 0x%x\n", error_flag); -#endif + WIIMOTE_DEBUG_LOG("Received error on data read {:#x}", error_flag) continue; } @@ -222,9 +220,7 @@ void WiimoteControllerProvider::reader_thread() data += 2; if (address == (kRegisterCalibration & 0xFFFF)) { -#ifdef WIIMOTE_DEBUG - printf("Calibration received\n"); -#endif + WIIMOTE_DEBUG_LOG("Calibration received"); cemu_assert(size == 8); @@ -257,17 +253,10 @@ void WiimoteControllerProvider::reader_thread() { if (size == 0xf) { -#ifdef WIIMOTE_DEBUG - printf("Extension type received but no extension connected\n"); -#endif + WIIMOTE_DEBUG_LOG("Extension type received but no extension connected") continue; } - -#ifdef WIIMOTE_DEBUG - printf("Extension type received\n"); -#endif - cemu_assert(size == 6); auto be_type = *(betype*)data; data += 6; // 48 @@ -276,37 +265,32 @@ void WiimoteControllerProvider::reader_thread() switch (be_type.value()) { case kExtensionNunchuck: -#ifdef WIIMOTE_DEBUG - printf("\tNunchuck\n"); -#endif + WIIMOTE_DEBUG_LOG("Extension Type Received: Nunchuck") new_state.m_extension = NunchuckData{}; break; case kExtensionClassic: -#ifdef WIIMOTE_DEBUG - printf("\tClassic\n"); -#endif + WIIMOTE_DEBUG_LOG("Extension Type Received: Classic") new_state.m_extension = ClassicData{}; break; case kExtensionClassicPro: - break; + WIIMOTE_DEBUG_LOG("Extension Type Received: Classic Pro") + break; case kExtensionGuitar: - break; + WIIMOTE_DEBUG_LOG("Extension Type Received: Guitar") + break; case kExtensionDrums: - break; + WIIMOTE_DEBUG_LOG("Extension Type Received: Drums") + break; case kExtensionBalanceBoard: - break; + WIIMOTE_DEBUG_LOG("Extension Type Received: Balance Board") + break; case kExtensionMotionPlus: - //m_motion_plus = true; -#ifdef WIIMOTE_DEBUG - printf("\tMotion plus detected\n"); -#endif + WIIMOTE_DEBUG_LOG("Extension Type Received: MotionPlus") set_motion_plus(index, true); new_state.m_motion_plus = MotionPlusData{}; break; case kExtensionPartialyInserted: -#ifdef WIIMOTE_DEBUG - printf("\tExtension only partially inserted!\n"); -#endif + WIIMOTE_DEBUG_LOG("Extension only partially inserted") new_state.m_extension = {}; request_status(index); break; @@ -321,9 +305,7 @@ void WiimoteControllerProvider::reader_thread() else if (address == (kRegisterExtensionCalibration & 0xFFFF)) { cemu_assert(size == 0x10); -#ifdef WIIMOTE_DEBUG - printf("Extension calibration received\n"); -#endif + WIIMOTE_DEBUG_LOG("Extension calibration received") std::visit( overloaded { @@ -339,9 +321,7 @@ void WiimoteControllerProvider::reader_thread() std::array zero{}; if (memcmp(zero.data(), data, zero.size()) == 0) { -#ifdef WIIMOTE_DEBUG - printf("\tExtension calibration data is zero!\n"); -#endif + WIIMOTE_DEBUG_LOG("\tExtension calibration data is zero") return; } @@ -374,10 +354,8 @@ void WiimoteControllerProvider::reader_thread() } else { -#ifdef WIIMOTE_DEBUG - printf("Unhandled read data received\n"); -#endif - continue; + WIIMOTE_DEBUG_LOG("Unhandled read data received") + continue; } update_report = true; @@ -478,10 +456,7 @@ void WiimoteControllerProvider::reader_thread() orientation /= tmp;*/ mp.orientation = orientation; -#ifdef WIIMOTE_DEBUG - printf("\tmp: %.2lf %.2lf %.2lf\n", mp.orientation.x, mp.orientation.y, - mp.orientation.z); -#endif + WIIMOTE_DEBUG_LOG("MotionPlus: {:.2f}, {:.2f} {:.2f}", mp.orientation.x, mp.orientation.y, mp.orientation.z) }, [data](NunchuckData& nunchuck) mutable { @@ -555,12 +530,11 @@ void WiimoteControllerProvider::reader_thread() zero3, zero4 ); -#ifdef WIIMOTE_DEBUG - printf("\tn: %d,%d | %lf - %lf | %.2lf %.2lf %.2lf\n", nunchuck.z, nunchuck.c, - nunchuck.axis.x, nunchuck.axis.y, - RadToDeg(nunchuck.acceleration.x), RadToDeg(nunchuck.acceleration.y), - RadToDeg(nunchuck.acceleration.z)); -#endif + WIIMOTE_DEBUG_LOG("Nunchuck: Z={}, C={} | {}, {} | {:.2f}, {:.2f}, {:.2f}", + nunchuck.z, nunchuck.c, + nunchuck.axis.x, nunchuck.axis.y, + RadToDeg(nunchuck.acceleration.x), RadToDeg(nunchuck.acceleration.y), + RadToDeg(nunchuck.acceleration.z)) }, [data](ClassicData& classic) mutable { @@ -594,11 +568,11 @@ void WiimoteControllerProvider::reader_thread() classic.trigger = classic.raw_trigger; classic.trigger /= 31.0f; -#ifdef WIIMOTE_DEBUG - printf("\tc: %d | %lf - %lf | %lf - %lf | %lf - %lf\n", classic.buttons, - classic.left_axis.x, classic.left_axis.y, classic.right_axis.x, - classic.right_axis.y, classic.trigger.x, classic.trigger.y); -#endif + WIIMOTE_DEBUG_LOG("\tClassic Controller: Buttons={:b} | {}, {} | {}, {} | {}, {}", + classic.buttons, classic.left_axis.x, classic.left_axis.y, + classic.right_axis.x, classic.right_axis.y, classic.trigger.x, + classic.trigger.y); + } }, new_state.m_extension); @@ -611,9 +585,7 @@ void WiimoteControllerProvider::reader_thread() break; } default: -#ifdef WIIMOTE_DEBUG - printf("unhandled input packet id %d for wiimote\n", data[0]); -#endif + WIIMOTE_DEBUG_LOG("unhandled input packet id {} for wiimote", data[0]) } // update motion data @@ -975,9 +947,7 @@ void WiimoteControllerProvider::update_report_type(size_t index) else report_type = kDataCore; -#ifdef WIIMOTE_DEBUG - printf("Setting report type to %d\n", report_type); -#endif + WIIMOTE_DEBUG_LOG("Setting report type to {}", report_type) send_packet(index, {kType, 0x04, report_type}); state.ir_camera.mode = set_ir_camera(index, true); @@ -1056,3 +1026,5 @@ void WiimoteControllerProvider::send_write_packet(size_t index, MemoryType type, std::copy(data.begin(), data.end(), packet.data() + 2 + 3 + 1); send_packet(index, std::move(packet)); } + +#undef WIIMOTE_DEBUG_LOG \ No newline at end of file diff --git a/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp b/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp index 5e5d500b1..148f8ce33 100644 --- a/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp +++ b/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp @@ -2,7 +2,7 @@ static constexpr uint16 WIIMOTE_VENDOR_ID = 0x057e; static constexpr uint16 WIIMOTE_PRODUCT_ID = 0x0306; -static constexpr uint16 WIIMOTE_MAX_MESSAGE_LENGTH = 21; +static constexpr uint16 WIIMOTE_MAX_INPUT_REPROT_LENGTH = 21; HidapiWiimote::HidapiWiimote(fs::path const& device_path, uint64_t identifier) : m_handle(hid_open_path(_pathToUtf8(device_path).c_str())), m_identifier(identifier) { @@ -14,8 +14,8 @@ bool HidapiWiimote::write_data(const std::vector &data) { } std::optional> HidapiWiimote::read_data() { - std::array read_data{}; - const auto result = hid_read(m_handle, read_data.data(), WIIMOTE_MAX_MESSAGE_LENGTH); + std::array read_data{}; + const auto result = hid_read(m_handle, read_data.data(), WIIMOTE_MAX_INPUT_REPROT_LENGTH); if (result < 0) return {}; return {{read_data.cbegin(), read_data.cend()}}; From 12b02d174af465028d705e03d7c41c2a9abe8793 Mon Sep 17 00:00:00 2001 From: capitalistspz Date: Wed, 9 Aug 2023 18:42:19 +0100 Subject: [PATCH 05/12] No hidapi on Windows --- CMakeLists.txt | 1 - vcpkg.json | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ced142c19..34a28a06a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,7 +88,6 @@ option(ENABLE_DISCORD_RPC "Enables the Discord Rich Presence feature" ON) if (WIN32) option(ENABLE_XINPUT "Enables the usage of XInput" ON) option(ENABLE_DIRECTINPUT "Enables the usage of DirectInput" ON) - option(ENABLE_HIDAPI "Build with HIDAPI" OFF) add_compile_definitions(HAS_DIRECTINPUT) set(ENABLE_WIIMOTE ON) elseif (UNIX) diff --git a/vcpkg.json b/vcpkg.json index 642e94d9b..940ed7484 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -26,7 +26,10 @@ "boost-static-string", "boost-random", "fmt", - "hidapi", + { + "name": "hidapi", + "platform": "!windows" + }, "libpng", "glm", { From 250401e540d5368dd625e9170f18169b81286a88 Mon Sep 17 00:00:00 2001 From: capitalistspz Date: Wed, 9 Aug 2023 22:23:25 +0100 Subject: [PATCH 06/12] don't use compiler extensions, slight log message changes --- src/input/api/Wiimote/WiimoteControllerProvider.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/input/api/Wiimote/WiimoteControllerProvider.cpp b/src/input/api/Wiimote/WiimoteControllerProvider.cpp index b16ff7d27..d8a677506 100644 --- a/src/input/api/Wiimote/WiimoteControllerProvider.cpp +++ b/src/input/api/Wiimote/WiimoteControllerProvider.cpp @@ -9,9 +9,9 @@ #endif #ifdef WIIMOTE_DEBUG -#define WIIMOTE_DEBUG_LOG(FMT, ARGS...) cemuLog_logDebug(LogType::Force, FMT, ##ARGS); +#define WIIMOTE_DEBUG_LOG(FMT, ...) cemuLog_logDebug(LogType::Force, FMT __VA_OPT__(,) __VA_ARGS__); #else -#define WIIMOTE_DEBUG_LOG(FMT, ARGS...) +#define WIIMOTE_DEBUG_LOG(FMT, ...) #endif #include @@ -321,7 +321,7 @@ void WiimoteControllerProvider::reader_thread() std::array zero{}; if (memcmp(zero.data(), data, zero.size()) == 0) { - WIIMOTE_DEBUG_LOG("\tExtension calibration data is zero") + WIIMOTE_DEBUG_LOG("Extension calibration data is zero") return; } @@ -568,7 +568,7 @@ void WiimoteControllerProvider::reader_thread() classic.trigger = classic.raw_trigger; classic.trigger /= 31.0f; - WIIMOTE_DEBUG_LOG("\tClassic Controller: Buttons={:b} | {}, {} | {}, {} | {}, {}", + WIIMOTE_DEBUG_LOG("Classic Controller: Buttons={:b} | {}, {} | {}, {} | {}, {}", classic.buttons, classic.left_axis.x, classic.left_axis.y, classic.right_axis.x, classic.right_axis.y, classic.trigger.x, classic.trigger.y); @@ -668,7 +668,6 @@ void WiimoteControllerProvider::parse_acceleration(WiimoteState& wiimote_state, tmp -= calib.zero; acceleration = (wiimote_state.m_acceleration / tmp); - //printf("%d, %d, %d\n", (int)m_acceleration.x, (int)m_acceleration.y, (int)m_acceleration.z); const float pi_2 = (float)std::numbers::pi / 2.0f; wiimote_state.m_roll = std::atan2(acceleration.z, acceleration.x) - pi_2; } @@ -687,7 +686,6 @@ void WiimoteControllerProvider::rotate_ir(WiimoteState& wiimote_state) i++; if (!dot.visible) continue; - //printf("%d:\t%.02lf | %.02lf\n", i, dot.pos.x, dot.pos.y); // move to center, rotate and move back dot.pos -= 0.5f; dot.pos.x = (dot.pos.x * cos) + (dot.pos.y * (-sin)); From 7e330fb83d43117278616aa60e17f65e1cc9f0d7 Mon Sep 17 00:00:00 2001 From: capitalistspz Date: Thu, 10 Aug 2023 00:35:55 +0100 Subject: [PATCH 07/12] MSVC's non-compliance makes me cry --- .../api/Wiimote/WiimoteControllerProvider.cpp | 51 +++++++++---------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/src/input/api/Wiimote/WiimoteControllerProvider.cpp b/src/input/api/Wiimote/WiimoteControllerProvider.cpp index d8a677506..4b08089f9 100644 --- a/src/input/api/Wiimote/WiimoteControllerProvider.cpp +++ b/src/input/api/Wiimote/WiimoteControllerProvider.cpp @@ -8,11 +8,6 @@ #include "input/api/Wiimote/windows/WinWiimoteDevice.h" #endif -#ifdef WIIMOTE_DEBUG -#define WIIMOTE_DEBUG_LOG(FMT, ...) cemuLog_logDebug(LogType::Force, FMT __VA_OPT__(,) __VA_ARGS__); -#else -#define WIIMOTE_DEBUG_LOG(FMT, ...) -#endif #include WiimoteControllerProvider::WiimoteControllerProvider() @@ -170,7 +165,7 @@ void WiimoteControllerProvider::reader_thread() { case kStatus: { - WIIMOTE_DEBUG_LOG("WiimoteControllerProvider::read_thread: kStatus") + cemuLog_logDebug(LogType::Force,"WiimoteControllerProvider::read_thread: kStatus"); new_state.buttons = (*(uint16*)data) & (~0x60E0); data += 2; new_state.flags = *data; @@ -188,7 +183,7 @@ void WiimoteControllerProvider::reader_thread() if (HAS_FLAG(new_state.flags, kExtensionConnected)) { - WIIMOTE_DEBUG_LOG("Extension flag is set") + cemuLog_logDebug(LogType::Force,"Extension flag is set"); if(new_state.m_extension.index() == 0) request_extension(index); } @@ -202,7 +197,7 @@ void WiimoteControllerProvider::reader_thread() break; case kRead: { - WIIMOTE_DEBUG_LOG("WiimoteControllerProvider::read_thread: kRead") + cemuLog_logDebug(LogType::Force,"WiimoteControllerProvider::read_thread: kRead"); new_state.buttons = (*(uint16*)data) & (~0x60E0); data += 2; const uint8 error_flag = *data & 0xF, size = (*data >> 4) + 1; @@ -212,7 +207,7 @@ void WiimoteControllerProvider::reader_thread() { // 7 means that wiimote is already enabled or not available - WIIMOTE_DEBUG_LOG("Received error on data read {:#x}", error_flag) + cemuLog_logDebug(LogType::Force,"Received error on data read {:#x}", error_flag); continue; } @@ -220,7 +215,7 @@ void WiimoteControllerProvider::reader_thread() data += 2; if (address == (kRegisterCalibration & 0xFFFF)) { - WIIMOTE_DEBUG_LOG("Calibration received"); + cemuLog_logDebug(LogType::Force,"Calibration received"); cemu_assert(size == 8); @@ -253,7 +248,7 @@ void WiimoteControllerProvider::reader_thread() { if (size == 0xf) { - WIIMOTE_DEBUG_LOG("Extension type received but no extension connected") + cemuLog_logDebug(LogType::Force,"Extension type received but no extension connected"); continue; } @@ -265,32 +260,32 @@ void WiimoteControllerProvider::reader_thread() switch (be_type.value()) { case kExtensionNunchuck: - WIIMOTE_DEBUG_LOG("Extension Type Received: Nunchuck") + cemuLog_logDebug(LogType::Force,"Extension Type Received: Nunchuck"); new_state.m_extension = NunchuckData{}; break; case kExtensionClassic: - WIIMOTE_DEBUG_LOG("Extension Type Received: Classic") + cemuLog_logDebug(LogType::Force,"Extension Type Received: Classic"); new_state.m_extension = ClassicData{}; break; case kExtensionClassicPro: - WIIMOTE_DEBUG_LOG("Extension Type Received: Classic Pro") + cemuLog_logDebug(LogType::Force,"Extension Type Received: Classic Pro"); break; case kExtensionGuitar: - WIIMOTE_DEBUG_LOG("Extension Type Received: Guitar") + cemuLog_logDebug(LogType::Force,"Extension Type Received: Guitar"); break; case kExtensionDrums: - WIIMOTE_DEBUG_LOG("Extension Type Received: Drums") + cemuLog_logDebug(LogType::Force,"Extension Type Received: Drums"); break; case kExtensionBalanceBoard: - WIIMOTE_DEBUG_LOG("Extension Type Received: Balance Board") + cemuLog_logDebug(LogType::Force,"Extension Type Received: Balance Board"); break; case kExtensionMotionPlus: - WIIMOTE_DEBUG_LOG("Extension Type Received: MotionPlus") + cemuLog_logDebug(LogType::Force,"Extension Type Received: MotionPlus"); set_motion_plus(index, true); new_state.m_motion_plus = MotionPlusData{}; break; case kExtensionPartialyInserted: - WIIMOTE_DEBUG_LOG("Extension only partially inserted") + cemuLog_logDebug(LogType::Force,"Extension only partially inserted"); new_state.m_extension = {}; request_status(index); break; @@ -305,7 +300,7 @@ void WiimoteControllerProvider::reader_thread() else if (address == (kRegisterExtensionCalibration & 0xFFFF)) { cemu_assert(size == 0x10); - WIIMOTE_DEBUG_LOG("Extension calibration received") + cemuLog_logDebug(LogType::Force,"Extension calibration received"); std::visit( overloaded { @@ -321,7 +316,7 @@ void WiimoteControllerProvider::reader_thread() std::array zero{}; if (memcmp(zero.data(), data, zero.size()) == 0) { - WIIMOTE_DEBUG_LOG("Extension calibration data is zero") + cemuLog_logDebug(LogType::Force,"Extension calibration data is zero"); return; } @@ -354,7 +349,7 @@ void WiimoteControllerProvider::reader_thread() } else { - WIIMOTE_DEBUG_LOG("Unhandled read data received") + cemuLog_logDebug(LogType::Force,"Unhandled read data received"); continue; } @@ -456,7 +451,7 @@ void WiimoteControllerProvider::reader_thread() orientation /= tmp;*/ mp.orientation = orientation; - WIIMOTE_DEBUG_LOG("MotionPlus: {:.2f}, {:.2f} {:.2f}", mp.orientation.x, mp.orientation.y, mp.orientation.z) + cemuLog_logDebug(LogType::Force,"MotionPlus: {:.2f}, {:.2f} {:.2f}", mp.orientation.x, mp.orientation.y, mp.orientation.z); }, [data](NunchuckData& nunchuck) mutable { @@ -530,11 +525,11 @@ void WiimoteControllerProvider::reader_thread() zero3, zero4 ); - WIIMOTE_DEBUG_LOG("Nunchuck: Z={}, C={} | {}, {} | {:.2f}, {:.2f}, {:.2f}", + cemuLog_logDebug(LogType::Force,"Nunchuck: Z={}, C={} | {}, {} | {:.2f}, {:.2f}, {:.2f}", nunchuck.z, nunchuck.c, nunchuck.axis.x, nunchuck.axis.y, RadToDeg(nunchuck.acceleration.x), RadToDeg(nunchuck.acceleration.y), - RadToDeg(nunchuck.acceleration.z)) + RadToDeg(nunchuck.acceleration.z)); }, [data](ClassicData& classic) mutable { @@ -568,7 +563,7 @@ void WiimoteControllerProvider::reader_thread() classic.trigger = classic.raw_trigger; classic.trigger /= 31.0f; - WIIMOTE_DEBUG_LOG("Classic Controller: Buttons={:b} | {}, {} | {}, {} | {}, {}", + cemuLog_logDebug(LogType::Force,"Classic Controller: Buttons={:b} | {}, {} | {}, {} | {}, {}", classic.buttons, classic.left_axis.x, classic.left_axis.y, classic.right_axis.x, classic.right_axis.y, classic.trigger.x, classic.trigger.y); @@ -585,7 +580,7 @@ void WiimoteControllerProvider::reader_thread() break; } default: - WIIMOTE_DEBUG_LOG("unhandled input packet id {} for wiimote", data[0]) + cemuLog_logDebug(LogType::Force,"unhandled input packet id {} for wiimote", data[0]); } // update motion data @@ -945,7 +940,7 @@ void WiimoteControllerProvider::update_report_type(size_t index) else report_type = kDataCore; - WIIMOTE_DEBUG_LOG("Setting report type to {}", report_type) + cemuLog_logDebug(LogType::Force,"Setting report type to {}", report_type); send_packet(index, {kType, 0x04, report_type}); state.ir_camera.mode = set_ir_camera(index, true); From 024c7ffa620342c52e28b1aefa421c32c16ce2ad Mon Sep 17 00:00:00 2001 From: capitalistspz Date: Thu, 10 Aug 2023 21:17:50 +0100 Subject: [PATCH 08/12] check if device is opened prior to constructing HidapiWiimote --- .../api/Wiimote/hidapi/HidapiWiimote.cpp | 20 ++++++++++++------- src/input/api/Wiimote/hidapi/HidapiWiimote.h | 2 +- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp b/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp index 148f8ce33..26949e86b 100644 --- a/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp +++ b/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp @@ -4,8 +4,8 @@ static constexpr uint16 WIIMOTE_VENDOR_ID = 0x057e; static constexpr uint16 WIIMOTE_PRODUCT_ID = 0x0306; static constexpr uint16 WIIMOTE_MAX_INPUT_REPROT_LENGTH = 21; -HidapiWiimote::HidapiWiimote(fs::path const& device_path, uint64_t identifier) - : m_handle(hid_open_path(_pathToUtf8(device_path).c_str())), m_identifier(identifier) { +HidapiWiimote::HidapiWiimote(hid_device* dev, uint64_t identifier) + : m_handle(dev), m_identifier(identifier) { } @@ -27,11 +27,17 @@ std::vector HidapiWiimote::get_devices() { const auto device_enumeration = hid_enumerate(WIIMOTE_VENDOR_ID, WIIMOTE_PRODUCT_ID); auto it = device_enumeration; while (it){ - // Enough to have a unique id for each device within a session - uint64_t id = (static_cast(it->interface_number) << 32) | - (static_cast(it->usage_page) << 16) | - (it->usage); - wiimote_devices.push_back(std::make_shared(it->path, id)); + auto dev = hid_open_path(it->path); + if (!dev){ + cemuLog_logDebug(LogType::Force, "Unable to open Wiimote device at {}: {}", it->path, boost::nowide::narrow(hid_error(nullptr))); + } + else { + // Enough to have a unique id for each device within a session + uint64_t id = (static_cast(it->interface_number) << 32) | + (static_cast(it->usage_page) << 16) | + (it->usage); + wiimote_devices.push_back(std::make_shared(dev, id)); + } it = it->next; } hid_free_enumeration(device_enumeration); diff --git a/src/input/api/Wiimote/hidapi/HidapiWiimote.h b/src/input/api/Wiimote/hidapi/HidapiWiimote.h index 298556d65..6bd90dac7 100644 --- a/src/input/api/Wiimote/hidapi/HidapiWiimote.h +++ b/src/input/api/Wiimote/hidapi/HidapiWiimote.h @@ -5,7 +5,7 @@ class HidapiWiimote : public WiimoteDevice { public: - HidapiWiimote(fs::path const& device_path, uint64_t identifier); + HidapiWiimote(hid_device* dev, uint64_t identifier); ~HidapiWiimote() override; bool write_data(const std::vector &data) override; From bfd59c1cda901957944f6b4ba18f540131cc2e2e Mon Sep 17 00:00:00 2001 From: capitalistspz Date: Thu, 10 Aug 2023 22:48:13 +0100 Subject: [PATCH 09/12] correct read size --- src/input/api/Wiimote/hidapi/HidapiWiimote.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp b/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp index 26949e86b..a9d63d711 100644 --- a/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp +++ b/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp @@ -2,7 +2,7 @@ static constexpr uint16 WIIMOTE_VENDOR_ID = 0x057e; static constexpr uint16 WIIMOTE_PRODUCT_ID = 0x0306; -static constexpr uint16 WIIMOTE_MAX_INPUT_REPROT_LENGTH = 21; +static constexpr uint16 WIIMOTE_MAX_INPUT_REPORT_LENGTH = 21; HidapiWiimote::HidapiWiimote(hid_device* dev, uint64_t identifier) : m_handle(dev), m_identifier(identifier) { @@ -14,11 +14,11 @@ bool HidapiWiimote::write_data(const std::vector &data) { } std::optional> HidapiWiimote::read_data() { - std::array read_data{}; - const auto result = hid_read(m_handle, read_data.data(), WIIMOTE_MAX_INPUT_REPROT_LENGTH); + std::array read_data{}; + const auto result = hid_read(m_handle, read_data.data(), WIIMOTE_MAX_INPUT_REPORT_LENGTH); if (result < 0) return {}; - return {{read_data.cbegin(), read_data.cend()}}; + return {{read_data.cbegin(), read_data.cbegin() + result}}; } std::vector HidapiWiimote::get_devices() { From b52a073c3cfe016208c92e47d77b4e36dc30ffc4 Mon Sep 17 00:00:00 2001 From: capitalistspz Date: Fri, 11 Aug 2023 10:26:51 +0100 Subject: [PATCH 10/12] cleanup: static cast is safe enough here; remove purposeless undef --- src/input/api/Wiimote/WiimoteControllerProvider.cpp | 2 -- src/input/api/Wiimote/hidapi/HidapiWiimote.cpp | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/input/api/Wiimote/WiimoteControllerProvider.cpp b/src/input/api/Wiimote/WiimoteControllerProvider.cpp index 4b08089f9..685bc9f57 100644 --- a/src/input/api/Wiimote/WiimoteControllerProvider.cpp +++ b/src/input/api/Wiimote/WiimoteControllerProvider.cpp @@ -1019,5 +1019,3 @@ void WiimoteControllerProvider::send_write_packet(size_t index, MemoryType type, std::copy(data.begin(), data.end(), packet.data() + 2 + 3 + 1); send_packet(index, std::move(packet)); } - -#undef WIIMOTE_DEBUG_LOG \ No newline at end of file diff --git a/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp b/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp index a9d63d711..a7a447011 100644 --- a/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp +++ b/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp @@ -45,7 +45,7 @@ std::vector HidapiWiimote::get_devices() { } bool HidapiWiimote::operator==(WiimoteDevice& o) const { - return m_identifier == dynamic_cast(o).m_identifier; + return m_identifier == static_cast(o).m_identifier; } HidapiWiimote::~HidapiWiimote() { From e6c8c31419a1ecbf3f32332fb99a89b0e1d4ae28 Mon Sep 17 00:00:00 2001 From: capitalistspz Date: Sat, 12 Aug 2023 16:02:41 +0100 Subject: [PATCH 11/12] correct read size again, don't forget new motionplus wiimotes --- src/input/api/Wiimote/hidapi/HidapiWiimote.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp b/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp index a7a447011..7baad55d4 100644 --- a/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp +++ b/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp @@ -2,7 +2,8 @@ static constexpr uint16 WIIMOTE_VENDOR_ID = 0x057e; static constexpr uint16 WIIMOTE_PRODUCT_ID = 0x0306; -static constexpr uint16 WIIMOTE_MAX_INPUT_REPORT_LENGTH = 21; +static constexpr uint16 WIIMOTE_MP_PRODUCT_ID = 0x0330; +static constexpr uint16 WIIMOTE_MAX_INPUT_REPORT_LENGTH = 22; HidapiWiimote::HidapiWiimote(hid_device* dev, uint64_t identifier) : m_handle(dev), m_identifier(identifier) { @@ -24,9 +25,11 @@ std::optional> HidapiWiimote::read_data() { std::vector HidapiWiimote::get_devices() { std::vector wiimote_devices; hid_init(); - const auto device_enumeration = hid_enumerate(WIIMOTE_VENDOR_ID, WIIMOTE_PRODUCT_ID); - auto it = device_enumeration; - while (it){ + const auto device_enumeration = hid_enumerate(WIIMOTE_VENDOR_ID, 0x0); + + for (auto it = device_enumeration; it != nullptr; it = it->next){ + if (it->product_id != WIIMOTE_PRODUCT_ID && it->product_id != WIIMOTE_MP_PRODUCT_ID) + continue; auto dev = hid_open_path(it->path); if (!dev){ cemuLog_logDebug(LogType::Force, "Unable to open Wiimote device at {}: {}", it->path, boost::nowide::narrow(hid_error(nullptr))); @@ -38,7 +41,6 @@ std::vector HidapiWiimote::get_devices() { (it->usage); wiimote_devices.push_back(std::make_shared(dev, id)); } - it = it->next; } hid_free_enumeration(device_enumeration); return wiimote_devices; From 5476eb9cdc425b15b34525ee99099d2e113eb47f Mon Sep 17 00:00:00 2001 From: capitalistspz Date: Sat, 12 Aug 2023 17:03:26 +0100 Subject: [PATCH 12/12] more logging changes, handle output acknowledgements, --- .../api/Wiimote/WiimoteControllerProvider.cpp | 17 ++++++++++++++--- src/input/api/Wiimote/WiimoteMessages.h | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/input/api/Wiimote/WiimoteControllerProvider.cpp b/src/input/api/Wiimote/WiimoteControllerProvider.cpp index 685bc9f57..0ebf88aae 100644 --- a/src/input/api/Wiimote/WiimoteControllerProvider.cpp +++ b/src/input/api/Wiimote/WiimoteControllerProvider.cpp @@ -38,7 +38,7 @@ std::vector> WiimoteControllerProvider::get_cont { // only add unknown, connected devices to our list const bool is_new_device = std::none_of(m_wiimotes.cbegin(), m_wiimotes.cend(), - [&device](const auto& it) { return *it.device == *device; }); + [device](const auto& it) { return *it.device == *device; }); if (is_new_device) { m_wiimotes.push_back(std::make_unique(device)); @@ -290,7 +290,8 @@ void WiimoteControllerProvider::reader_thread() request_status(index); break; default: - new_state.m_extension = {}; + cemuLog_logDebug(LogType::Force,"Unknown extension: {:#x}", be_type.value()); + new_state.m_extension = {}; break; } @@ -356,6 +357,16 @@ void WiimoteControllerProvider::reader_thread() update_report = true; } break; + case kAcknowledge: + { + new_state.buttons = *(uint16*)data & (~0x60E0); + data += 2; + const auto report_id = *data++; + const auto error = *data++; + if (error) + cemuLog_logDebug(LogType::Force, "Error {:#x} from output report {:#x}", error, report_id); + break; + } case kDataCore: { // 30 BB BB @@ -580,7 +591,7 @@ void WiimoteControllerProvider::reader_thread() break; } default: - cemuLog_logDebug(LogType::Force,"unhandled input packet id {} for wiimote", data[0]); + cemuLog_logDebug(LogType::Force,"unhandled input packet id {} for wiimote {}", id, index); } // update motion data diff --git a/src/input/api/Wiimote/WiimoteMessages.h b/src/input/api/Wiimote/WiimoteMessages.h index 712c3a5c1..32dd46583 100644 --- a/src/input/api/Wiimote/WiimoteMessages.h +++ b/src/input/api/Wiimote/WiimoteMessages.h @@ -8,7 +8,7 @@ enum InputReportId : uint8 kStatus = 0x20, kRead = 0x21, - kWrite = 0x22, + kAcknowledge = 0x22, kDataCore = 0x30, kDataCoreAcc = 0x31,