From 56f35ab2629c3753dbb624799bd8aaff2a179f58 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Sat, 6 Oct 2018 00:23:21 +1000 Subject: [PATCH 01/10] "Better Hid" rework part 1 --- src/core/CMakeLists.txt | 18 + .../hid/controllers/controller_base.cpp | 27 ++ .../service/hid/controllers/controller_base.h | 43 ++ .../hle/service/hid/controllers/debug_pad.cpp | 35 ++ .../hle/service/hid/controllers/debug_pad.h | 54 +++ .../hle/service/hid/controllers/gesture.cpp | 36 ++ .../hle/service/hid/controllers/gesture.h | 61 +++ .../hle/service/hid/controllers/keyboard.cpp | 36 ++ .../hle/service/hid/controllers/keyboard.h | 48 ++ .../hle/service/hid/controllers/mouse.cpp | 36 ++ src/core/hle/service/hid/controllers/mouse.h | 48 ++ src/core/hle/service/hid/controllers/npad.cpp | 336 ++++++++++++++ src/core/hle/service/hid/controllers/npad.h | 249 ++++++++++ .../hle/service/hid/controllers/stubbed.cpp | 32 ++ .../hle/service/hid/controllers/stubbed.h | 32 ++ .../service/hid/controllers/touchscreen.cpp | 58 +++ .../hle/service/hid/controllers/touchscreen.h | 61 +++ src/core/hle/service/hid/controllers/xpad.cpp | 38 ++ src/core/hle/service/hid/controllers/xpad.h | 59 +++ src/core/hle/service/hid/hid.cpp | 435 ++++++++---------- src/core/hle/service/hid/hid.h | 402 +--------------- src/core/hle/service/nfp/nfp.cpp | 2 +- 22 files changed, 1501 insertions(+), 645 deletions(-) create mode 100644 src/core/hle/service/hid/controllers/controller_base.cpp create mode 100644 src/core/hle/service/hid/controllers/controller_base.h create mode 100644 src/core/hle/service/hid/controllers/debug_pad.cpp create mode 100644 src/core/hle/service/hid/controllers/debug_pad.h create mode 100644 src/core/hle/service/hid/controllers/gesture.cpp create mode 100644 src/core/hle/service/hid/controllers/gesture.h create mode 100644 src/core/hle/service/hid/controllers/keyboard.cpp create mode 100644 src/core/hle/service/hid/controllers/keyboard.h create mode 100644 src/core/hle/service/hid/controllers/mouse.cpp create mode 100644 src/core/hle/service/hid/controllers/mouse.h create mode 100644 src/core/hle/service/hid/controllers/npad.cpp create mode 100644 src/core/hle/service/hid/controllers/npad.h create mode 100644 src/core/hle/service/hid/controllers/stubbed.cpp create mode 100644 src/core/hle/service/hid/controllers/stubbed.h create mode 100644 src/core/hle/service/hid/controllers/touchscreen.cpp create mode 100644 src/core/hle/service/hid/controllers/touchscreen.h create mode 100644 src/core/hle/service/hid/controllers/xpad.cpp create mode 100644 src/core/hle/service/hid/controllers/xpad.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index e4a676e918..1a9ec459f5 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -233,6 +233,24 @@ add_library(core STATIC hle/service/hid/irs.h hle/service/hid/xcd.cpp hle/service/hid/xcd.h + hle/service/hid/controllers/controller_base.cpp + hle/service/hid/controllers/controller_base.h + hle/service/hid/controllers/debug_pad.cpp + hle/service/hid/controllers/debug_pad.h + hle/service/hid/controllers/gesture.cpp + hle/service/hid/controllers/gesture.h + hle/service/hid/controllers/keyboard.cpp + hle/service/hid/controllers/keyboard.h + hle/service/hid/controllers/mouse.cpp + hle/service/hid/controllers/mouse.h + hle/service/hid/controllers/npad.cpp + hle/service/hid/controllers/npad.h + hle/service/hid/controllers/stubbed.cpp + hle/service/hid/controllers/stubbed.h + hle/service/hid/controllers/touchscreen.cpp + hle/service/hid/controllers/touchscreen.h + hle/service/hid/controllers/xpad.cpp + hle/service/hid/controllers/xpad.h hle/service/lbl/lbl.cpp hle/service/lbl/lbl.h hle/service/ldn/ldn.cpp diff --git a/src/core/hle/service/hid/controllers/controller_base.cpp b/src/core/hle/service/hid/controllers/controller_base.cpp new file mode 100644 index 0000000000..f2aef56421 --- /dev/null +++ b/src/core/hle/service/hid/controllers/controller_base.cpp @@ -0,0 +1,27 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/hid/controllers/controller_base.h" + +namespace Service::HID { +void ControllerBase::ActivateController() { + if (is_activated) { + OnRelease(); + } + is_activated = true; + OnInit(); +} + +void ControllerBase::DeactivateController() { + if (is_activated) { + OnRelease(); + } + is_activated = false; +} + +bool ControllerBase::IsControllerActivated() const { + return is_activated; +} +// ControllerBase::~ControllerBase() = default; +}; // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h new file mode 100644 index 0000000000..3b1c8aad6b --- /dev/null +++ b/src/core/hle/service/hid/controllers/controller_base.h @@ -0,0 +1,43 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once +#include "common/common_types.h" +#include "common/swap.h" + +namespace Service::HID { +class ControllerBase { +public: + ControllerBase() = default; + + // Called when the controller is initialized + virtual void OnInit() = 0; + + // When the controller is released + virtual void OnRelease() = 0; + + // When the controller is requesting an update for the shared memory + virtual void OnUpdate(u8* data, size_t size) = 0; + + // Called when input devices should be loaded + virtual void OnLoadInputDevices() = 0; + + void ActivateController(); + + void DeactivateController(); + + bool IsControllerActivated() const; + +protected: + bool is_activated{false}; + + struct CommonHeader { + s64_le timestamp; + s64_le total_entry_count; + s64_le last_entry_index; + s64_le entry_count; + }; + static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); +}; +}; // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp new file mode 100644 index 0000000000..04799b233b --- /dev/null +++ b/src/core/hle/service/hid/controllers/debug_pad.cpp @@ -0,0 +1,35 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/common_types.h" +#include "common/swap.h" +#include "core/core_timing.h" +#include "core/hle/service/hid/controllers/debug_pad.h" + +namespace Service::HID { +void Controller_DebugPad::OnInit() {} +void Controller_DebugPad::OnRelease() {} +void Controller_DebugPad::OnUpdate(u8* data, size_t size) { + shared_memory.header.timestamp = CoreTiming::GetTicks(); + shared_memory.header.total_entry_count = 17; + + if (!IsControllerActivated()) { + shared_memory.header.entry_count = 0; + shared_memory.header.last_entry_index = 0; + return; + } + shared_memory.header.entry_count = 16; + + auto& last_entry = shared_memory.pad_states[shared_memory.header.last_entry_index]; + shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; + auto& cur_entry = shared_memory.pad_states[shared_memory.header.last_entry_index]; + + cur_entry.sampling_number = last_entry.sampling_number + 1; + cur_entry.sampling_number2 = cur_entry.sampling_number; + // TODO(ogniK): Update debug pad states + + std::memcpy(data, &shared_memory, sizeof(SharedMemory)); +} +void Controller_DebugPad::OnLoadInputDevices() {} +}; // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h new file mode 100644 index 0000000000..fc6f99a0b1 --- /dev/null +++ b/src/core/hle/service/hid/controllers/debug_pad.h @@ -0,0 +1,54 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once +#include +#include "common/common_funcs.h" +#include "common/common_types.h" +#include "common/swap.h" +#include "core/hle/service/hid/controllers/controller_base.h" + +namespace Service::HID { +class Controller_DebugPad final : public ControllerBase { +public: + Controller_DebugPad() = default; + + // Called when the controller is initialized + void OnInit() override; + + // When the controller is released + void OnRelease() override; + + // When the controller is requesting an update for the shared memory + void OnUpdate(u8* data, size_t size) override; + + // Called when input devices should be loaded + void OnLoadInputDevices() override; + +private: + struct AnalogStick { + s32_le x; + s32_le y; + }; + static_assert(sizeof(AnalogStick) == 0x8); + + struct PadStates { + s64_le sampling_number; + s64_le sampling_number2; + u32_le attribute; + u32_le button_state; + AnalogStick r_stick; + AnalogStick l_stick; + }; + static_assert(sizeof(PadStates) == 0x28, "PadStates is an invalid state"); + + struct SharedMemory { + CommonHeader header; + std::array pad_states; + INSERT_PADDING_BYTES(0x138); + }; + static_assert(sizeof(SharedMemory) == 0x400, "SharedMemory is an invalid size"); + SharedMemory shared_memory{}; +}; +}; // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp new file mode 100644 index 0000000000..851ea66f34 --- /dev/null +++ b/src/core/hle/service/hid/controllers/gesture.cpp @@ -0,0 +1,36 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/common_types.h" +#include "common/swap.h" +#include "core/core_timing.h" +#include "core/hle/service/hid/controllers/gesture.h" + +namespace Service::HID { +constexpr size_t SHARED_MEMORY_OFFSET = 0x3BA00; +void Controller_Gesture::OnInit() {} +void Controller_Gesture::OnRelease() {} +void Controller_Gesture::OnUpdate(u8* data, size_t size) { + shared_memory.header.timestamp = CoreTiming::GetTicks(); + shared_memory.header.total_entry_count = 17; + + if (!IsControllerActivated()) { + shared_memory.header.entry_count = 0; + shared_memory.header.last_entry_index = 0; + return; + } + shared_memory.header.entry_count = 16; + + auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; + shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; + auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; + + cur_entry.sampling_number = last_entry.sampling_number + 1; + cur_entry.sampling_number2 = cur_entry.sampling_number; + // TODO(ogniK): Update gesture states + + std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); +} +void Controller_Gesture::OnLoadInputDevices() {} +}; // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h new file mode 100644 index 0000000000..f468198296 --- /dev/null +++ b/src/core/hle/service/hid/controllers/gesture.h @@ -0,0 +1,61 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once +#include +#include "common/common_types.h" +#include "common/swap.h" +#include "core/hle/service/hid/controllers/controller_base.h" + +namespace Service::HID { +class Controller_Gesture final : public ControllerBase { +public: + Controller_Gesture() = default; + + // Called when the controller is initialized + void OnInit() override; + + // When the controller is released + void OnRelease() override; + + // When the controller is requesting an update for the shared memory + void OnUpdate(u8* data, size_t size) override; + + // Called when input devices should be loaded + void OnLoadInputDevices() override; + +private: + struct Locations { + s32_le x; + s32_le y; + }; + + struct GestureState { + s64_le sampling_number; + s64_le sampling_number2; + + s64_le detection_count; + s32_le type; + s32_le dir; + s32_le x; + s32_le y; + s32_le delta_x; + s32_le delta_y; + f32 vel_x; + f32 vel_y; + s32_le attributes; + f32 scale; + f32 rotation; + s32_le location_count; + std::array locations{}; + }; + static_assert(sizeof(GestureState) == 0x68, "GestureState is an invalid size"); + + struct SharedMemory { + CommonHeader header; + std::array gesture_states; + }; + SharedMemory shared_memory{}; +}; +}; // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp new file mode 100644 index 0000000000..27c39ad08b --- /dev/null +++ b/src/core/hle/service/hid/controllers/keyboard.cpp @@ -0,0 +1,36 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/common_types.h" +#include "common/swap.h" +#include "core/core_timing.h" +#include "core/hle/service/hid/controllers/keyboard.h" + +namespace Service::HID { +constexpr size_t SHARED_MEMORY_OFFSET = 0x3800; +void Controller_Keyboard::OnInit() {} +void Controller_Keyboard::OnRelease() {} +void Controller_Keyboard::OnUpdate(u8* data, size_t size) { + shared_memory.header.timestamp = CoreTiming::GetTicks(); + shared_memory.header.total_entry_count = 17; + + if (!IsControllerActivated()) { + shared_memory.header.entry_count = 0; + shared_memory.header.last_entry_index = 0; + return; + } + shared_memory.header.entry_count = 16; + + auto& last_entry = shared_memory.pad_states[shared_memory.header.last_entry_index]; + shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; + auto& cur_entry = shared_memory.pad_states[shared_memory.header.last_entry_index]; + + cur_entry.sampling_number = last_entry.sampling_number + 1; + cur_entry.sampling_number2 = cur_entry.sampling_number; + // TODO(ogniK): Update keyboard states + + std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); +} +void Controller_Keyboard::OnLoadInputDevices() {} +}; // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h new file mode 100644 index 0000000000..0463e16197 --- /dev/null +++ b/src/core/hle/service/hid/controllers/keyboard.h @@ -0,0 +1,48 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once +#include +#include "common/common_funcs.h" +#include "common/common_types.h" +#include "common/swap.h" +#include "core/hle/service/hid/controllers/controller_base.h" + +namespace Service::HID { +class Controller_Keyboard final : public ControllerBase { +public: + Controller_Keyboard() = default; + + // Called when the controller is initialized + void OnInit() override; + + // When the controller is released + void OnRelease() override; + + // When the controller is requesting an update for the shared memory + void OnUpdate(u8* data, size_t size) override; + + // Called when input devices should be loaded + void OnLoadInputDevices() override; + +private: + struct KeyboardState { + s64_le sampling_number; + s64_le sampling_number2; + + s32_le modifier; + s32_le attribute; + std::array key{}; + }; + static_assert(sizeof(KeyboardState) == 0x38, "KeyboardState is an invalid size"); + + struct SharedMemory { + CommonHeader header; + std::array pad_states; + INSERT_PADDING_BYTES(0x28); + }; + static_assert(sizeof(SharedMemory) == 0x400, "SharedMemory is an invalid size"); + SharedMemory shared_memory{}; +}; +}; // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp new file mode 100644 index 0000000000..df30239e20 --- /dev/null +++ b/src/core/hle/service/hid/controllers/mouse.cpp @@ -0,0 +1,36 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/common_types.h" +#include "common/swap.h" +#include "core/core_timing.h" +#include "core/hle/service/hid/controllers/mouse.h" + +namespace Service::HID { +constexpr size_t SHARED_MEMORY_OFFSET = 0x3400; +void Controller_Mouse::OnInit() {} +void Controller_Mouse::OnRelease() {} +void Controller_Mouse::OnUpdate(u8* data, size_t size) { + shared_memory.header.timestamp = CoreTiming::GetTicks(); + shared_memory.header.total_entry_count = 17; + + if (!IsControllerActivated()) { + shared_memory.header.entry_count = 0; + shared_memory.header.last_entry_index = 0; + return; + } + shared_memory.header.entry_count = 16; + + auto& last_entry = shared_memory.mouse_states[shared_memory.header.last_entry_index]; + shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; + auto& cur_entry = shared_memory.mouse_states[shared_memory.header.last_entry_index]; + + cur_entry.sampling_number = last_entry.sampling_number + 1; + cur_entry.sampling_number2 = cur_entry.sampling_number; + // TODO(ogniK): Update mouse states + + std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); +} +void Controller_Mouse::OnLoadInputDevices() {} +}; // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h new file mode 100644 index 0000000000..0d7fd372d2 --- /dev/null +++ b/src/core/hle/service/hid/controllers/mouse.h @@ -0,0 +1,48 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once +#include +#include "common/common_types.h" +#include "common/swap.h" +#include "core/hle/service/hid/controllers/controller_base.h" + +namespace Service::HID { +class Controller_Mouse final : public ControllerBase { +public: + Controller_Mouse() = default; + + // Called when the controller is initialized + void OnInit() override; + + // When the controller is released + void OnRelease() override; + + // When the controller is requesting an update for the shared memory + void OnUpdate(u8* data, size_t size) override; + + // Called when input devices should be loaded + void OnLoadInputDevices() override; + +private: + struct MouseState { + s64_le sampling_number; + s64_le sampling_number2; + s32_le x; + s32_le y; + s32_le delta_x; + s32_le delta_y; + s32_le mouse_wheel; + s32_le button; + s32_le attribute; + }; + static_assert(sizeof(MouseState) == 0x30, "MouseState is an invalid size"); + + struct SharedMemory { + CommonHeader header; + std::array mouse_states; + }; + SharedMemory shared_memory{}; +}; +}; // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp new file mode 100644 index 0000000000..a53687b91e --- /dev/null +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -0,0 +1,336 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once +#include +#include "common/assert.h" +#include "common/bit_field.h" +#include "common/common_types.h" +#include "common/swap.h" +#include "core/core.h" +#include "core/core_timing.h" +#include "core/frontend/input.h" +#include "core/hle/kernel/event.h" +#include "core/hle/service/hid/controllers/npad.h" +#include "core/settings.h" + +namespace Service::HID { +constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28; +constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A; +constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6; +constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E; +constexpr s32 HID_JOYSTICK_MAX = 0x7fff; +constexpr s32 HID_JOYSTICK_MIN = -0x7fff; +constexpr size_t NPAD_OFFSET = 0x9A00; +constexpr size_t MAX_CONTROLLER_COUNT = 9; + +enum class JoystickId : size_t { Joystick_Left, Joystick_Right }; +constexpr std::array NPAD_ID_LIST{0, 1, 2, 3, 4, 5, 6, 7, 32}; +size_t CONTROLLER_COUNT{}; +std::array CONNECTED_CONTROLLERS{}; + +void Controller_NPad::InitNewlyAddedControler(size_t controller_idx) { + const auto controller_type = CONNECTED_CONTROLLERS[controller_idx]; + auto& controller = shared_memory_entries[controller_idx]; + if (controller_type == NPadControllerType::None) { + return; + } + controller.joy_styles.raw = 0; // Zero out + controller.device_type.raw = 0; + switch (controller_type) { + case NPadControllerType::Handheld: + controller.joy_styles.handheld.Assign(1); + controller.device_type.handheld.Assign(1); + controller.pad_assignment = NPadAssignments::Dual; + break; + case NPadControllerType::JoyLeft: + controller.joy_styles.joycon_left.Assign(1); + controller.device_type.joycon_left.Assign(1); + controller.pad_assignment = NPadAssignments::Dual; + break; + case NPadControllerType::JoyRight: + controller.joy_styles.joycon_right.Assign(1); + controller.device_type.joycon_right.Assign(1); + controller.pad_assignment = NPadAssignments::Dual; + break; + case NPadControllerType::Tabletop: + UNIMPLEMENTED_MSG("Tabletop is not implemented"); + break; + case NPadControllerType::Pokeball: + controller.joy_styles.pokeball.Assign(1); + controller.device_type.pokeball.Assign(1); + controller.pad_assignment = NPadAssignments::Single; + break; + case NPadControllerType::ProController: + controller.joy_styles.pro_controller.Assign(1); + controller.device_type.pro_controller.Assign(1); + controller.pad_assignment = NPadAssignments::Single; + break; + } + + controller.single_color_error = ColorReadError::ReadOk; + controller.single_color.body_color = 0; + controller.single_color.button_color = 0; + + controller.dual_color_error = ColorReadError::ReadOk; + controller.left_color.body_color = JOYCON_BODY_NEON_BLUE; + controller.left_color.button_color = JOYCON_BUTTONS_NEON_BLUE; + controller.right_color.body_color = JOYCON_BODY_NEON_RED; + controller.right_color.button_color = JOYCON_BUTTONS_NEON_RED; + + controller.properties.is_verticle.Assign(1); // TODO(ogniK): Swap joycons orientations +} + +void Controller_NPad::OnInit() { + auto& kernel = Core::System::GetInstance().Kernel(); + styleset_changed_event = + Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "npad:NpadStyleSetChanged"); + + if (!IsControllerActivated()) + return; + size_t controller{}; + supported_npad_id_types.resize(NPAD_ID_LIST.size()); + if (style.raw == 0) { + // We want to support all controllers + style.handheld.Assign(1); + style.joycon_left.Assign(1); + style.joycon_right.Assign(1); + style.joycon_dual.Assign(1); + style.pro_controller.Assign(1); + style.pokeball.Assign(1); + } + std::memcpy(supported_npad_id_types.data(), NPAD_ID_LIST.data(), + NPAD_ID_LIST.size() * sizeof(u32)); + if (CONTROLLER_COUNT == 0) { + AddNewController(NPadControllerType::Handheld); + } +} + +void Controller_NPad::OnLoadInputDevices() { + std::transform(Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, + Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_END, + buttons.begin(), Input::CreateDevice); + std::transform(Settings::values.analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, + Settings::values.analogs.begin() + Settings::NativeAnalog::STICK_HID_END, + sticks.begin(), Input::CreateDevice); +} + +void Controller_NPad::OnRelease() {} + +void Controller_NPad::OnUpdate(u8* data, size_t data_len) { + if (!IsControllerActivated()) + return; + for (size_t i = 0; i < shared_memory_entries.size(); i++) { + auto& npad = shared_memory_entries[i]; + const std::array controller_npads{&npad.main_controller_states, + &npad.handheld_states, + &npad.dual_states, + &npad.left_joy_states, + &npad.right_joy_states, + &npad.pokeball_states, + &npad.libnx}; + + for (auto main_controller : controller_npads) { + main_controller->common.entry_count = 16; + main_controller->common.total_entry_count = 17; + + auto& last_entry = main_controller->npad[main_controller->common.last_entry_index]; + + main_controller->common.timestamp = CoreTiming::GetTicks(); + main_controller->common.last_entry_index = + (main_controller->common.last_entry_index + 1) % 17; + + auto& cur_entry = main_controller->npad[main_controller->common.last_entry_index]; + + cur_entry.timestamp = last_entry.timestamp + 1; + cur_entry.timestamp2 = cur_entry.timestamp; + } + + if (CONNECTED_CONTROLLERS[i] == NPadControllerType::None) { + continue; + } + + const auto& controller_type = CONNECTED_CONTROLLERS[i]; + + // Pad states + auto pad_state = ControllerPadState{}; + using namespace Settings::NativeButton; + pad_state.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l_stick.Assign(buttons[LStick - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r_stick.Assign(buttons[RStick - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus()); + + pad_state.dleft.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.dup.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.dright.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.ddown.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus()); + + pad_state.lstickleft.Assign(buttons[LStick_Left - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.lstickup.Assign(buttons[LStick_Up - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.lstickright.Assign(buttons[LStick_Right - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.lstickdown.Assign(buttons[LStick_Down - BUTTON_HID_BEGIN]->GetStatus()); + + pad_state.rstickleft.Assign(buttons[RStick_Left - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.rstickup.Assign(buttons[RStick_Up - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.rstickright.Assign(buttons[RStick_Right - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.rstickdown.Assign(buttons[RStick_Down - BUTTON_HID_BEGIN]->GetStatus()); + + pad_state.sl.Assign(buttons[SL - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.sr.Assign(buttons[SR - BUTTON_HID_BEGIN]->GetStatus()); + + AnalogPosition lstick_entry{}; + AnalogPosition rstick_entry{}; + + const auto [stick_l_x_f, stick_l_y_f] = + sticks[static_cast(JoystickId::Joystick_Left)]->GetStatus(); + const auto [stick_r_x_f, stick_r_y_f] = + sticks[static_cast(JoystickId::Joystick_Right)]->GetStatus(); + lstick_entry.x = static_cast(stick_l_x_f * HID_JOYSTICK_MAX); + lstick_entry.y = static_cast(stick_l_y_f * HID_JOYSTICK_MAX); + rstick_entry.x = static_cast(stick_r_x_f * HID_JOYSTICK_MAX); + rstick_entry.y = static_cast(stick_r_y_f * HID_JOYSTICK_MAX); + + auto& main_controller = + npad.main_controller_states.npad[npad.main_controller_states.common.last_entry_index]; + auto& handheld_entry = + npad.handheld_states.npad[npad.handheld_states.common.last_entry_index]; + auto& dual_entry = npad.dual_states.npad[npad.dual_states.common.last_entry_index]; + auto& left_entry = npad.left_joy_states.npad[npad.left_joy_states.common.last_entry_index]; + auto& right_entry = + npad.right_joy_states.npad[npad.right_joy_states.common.last_entry_index]; + auto& pokeball_entry = + npad.pokeball_states.npad[npad.pokeball_states.common.last_entry_index]; + auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index]; + + if (hold_type == NpadHoldType::Horizontal) { + // TODO(ogniK): Remap buttons for different orientations + } + + switch (controller_type) { + case NPadControllerType::Handheld: + handheld_entry.connection_status.IsConnected.Assign(1); + handheld_entry.connection_status.IsWired.Assign(1); + handheld_entry.pad_states.raw = pad_state.raw; + handheld_entry.lstick = lstick_entry; + handheld_entry.rstick = rstick_entry; + break; + case NPadControllerType::JoyLeft: + left_entry.connection_status.IsConnected.Assign(1); + left_entry.pad_states.raw = pad_state.raw; + left_entry.lstick = lstick_entry; + left_entry.rstick = rstick_entry; + break; + case NPadControllerType::JoyRight: + right_entry.connection_status.IsConnected.Assign(1); + right_entry.pad_states.raw = pad_state.raw; + right_entry.lstick = lstick_entry; + right_entry.rstick = rstick_entry; + break; + case NPadControllerType::Tabletop: + // TODO(ogniK): Figure out how to add proper tabletop support + dual_entry.pad_states.raw = pad_state.raw; + dual_entry.lstick = lstick_entry; + dual_entry.rstick = rstick_entry; + dual_entry.connection_status.IsConnected.Assign(1); + break; + case NPadControllerType::Pokeball: + pokeball_entry.connection_status.IsConnected.Assign(1); + pokeball_entry.connection_status.IsWired.Assign(1); + + pokeball_entry.pad_states.raw = pad_state.raw; + pokeball_entry.lstick = lstick_entry; + pokeball_entry.rstick = rstick_entry; + break; + case NPadControllerType::ProController: + main_controller.pad_states.raw = pad_state.raw; + main_controller.lstick = lstick_entry; + main_controller.rstick = rstick_entry; + main_controller.connection_status.IsConnected.Assign(1); + main_controller.connection_status.IsWired.Assign(1); + break; + } + + // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate + // any controllers. + libnx_entry.connection_status.IsConnected.Assign(1); + libnx_entry.connection_status.IsWired.Assign(1); + libnx_entry.pad_states.raw = pad_state.raw; + libnx_entry.lstick = lstick_entry; + libnx_entry.rstick = rstick_entry; + } + std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(), + shared_memory_entries.size() * sizeof(NPadEntry)); +} + +void Controller_NPad::SetSupportedStyleSet(NPadType style_set) { + style.raw = style_set.raw; +} + +Controller_NPad::NPadType Controller_NPad::GetSupportedStyleSet() const { + return style; +} + +void Controller_NPad::SetSupportedNPadIdTypes(u8* data, size_t length) { + ASSERT(length > 0 && (length % sizeof(u32)) == 0); + supported_npad_id_types.resize(length / 4); + std::memcpy(supported_npad_id_types.data(), data, length); +} + +void Controller_NPad::GetSupportedNpadIdTypes(u32* data, size_t max_length) { + ASSERT(max_length < supported_npad_id_types.size()); + std::memcpy(data, supported_npad_id_types.data(), supported_npad_id_types.size()); +} + +size_t Controller_NPad::GetSupportedNPadIdTypesSize() const { + return supported_npad_id_types.size(); +} + +void Controller_NPad::SetHoldType(NpadHoldType joy_hold_type) { + hold_type = joy_hold_type; +} +Controller_NPad::NpadHoldType Controller_NPad::GetHoldType() const { + return hold_type; +} + +void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) { + ASSERT(npad_id < shared_memory_entries.size()); + shared_memory_entries[npad_id].pad_assignment = assignment_mode; +} + +void Controller_NPad::VibrateController(const std::vector& controller_ids, + const std::vector& vibrations) { + for (size_t i = 0; i < controller_ids.size(); i++) { + if (i >= CONTROLLER_COUNT) { + continue; + } + // TODO(ogniK): Vibrate the physical controller + } + LOG_WARNING(Service_HID, "(STUBBED) called"); + last_processed_vibration = vibrations.back(); +} + +Kernel::SharedPtr Controller_NPad::GetStyleSetChangedEvent() const { + return styleset_changed_event; +} + +Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { + return last_processed_vibration; +} +void Controller_NPad::AddNewController(NPadControllerType controller) { + if (CONTROLLER_COUNT >= MAX_CONTROLLER_COUNT) { + LOG_ERROR(Service_HID, "Cannot connect any more controllers!"); + return; + } + CONNECTED_CONTROLLERS[CONTROLLER_COUNT] = controller; + InitNewlyAddedControler(CONTROLLER_COUNT++); +} +}; // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h new file mode 100644 index 0000000000..e57b67da4b --- /dev/null +++ b/src/core/hle/service/hid/controllers/npad.h @@ -0,0 +1,249 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once +#include +#include "common/common_types.h" +#include "core/frontend/input.h" +#include "core/hle/service/hid/controllers/controller_base.h" +#include "core/settings.h" + +namespace Service::HID { + +class Controller_NPad final : public ControllerBase { +public: + Controller_NPad() = default; + + // Called when the controller is initialized + void OnInit() override; + + // When the controller is released + void OnRelease() override; + + // When the controller is requesting an update for the shared memory + void OnUpdate(u8* data, size_t size) override; + + // Called when input devices should be loaded + void OnLoadInputDevices() override; + + struct NPadType { + union { + u32_le raw{}; + + BitField<0, 1, u32_le> pro_controller; + BitField<1, 1, u32_le> handheld; + BitField<2, 1, u32_le> joycon_dual; + BitField<3, 1, u32_le> joycon_left; + BitField<4, 1, u32_le> joycon_right; + + BitField<6, 1, u32_le> pokeball; // TODO(ogniK): Confirm when possible + }; + }; + static_assert(sizeof(NPadType) == 4, "NPadType is an invalid size"); + + struct Vibration { + f32 amp_low; + f32 freq_low; + f32 amp_high; + f32 freq_high; + }; + static_assert(sizeof(Vibration) == 0x10, "Vibration is an invalid size"); + + enum class NpadHoldType : u64 { + Vertical = 0, + Horizontal = 1, + }; + + enum class NPadAssignments : u32_le { + Dual = 0, + Single = 1, + }; + + enum class NPadControllerType { + None, + ProController, + Handheld, + JoyLeft, + JoyRight, + Tabletop, + Pokeball + }; + + void SetSupportedStyleSet(NPadType style_set); + NPadType GetSupportedStyleSet() const; + + void SetSupportedNPadIdTypes(u8* data, size_t length); + void GetSupportedNpadIdTypes(u32* data, size_t max_length); + size_t GetSupportedNPadIdTypesSize() const; + + void SetHoldType(NpadHoldType joy_hold_type); + NpadHoldType GetHoldType() const; + + void SetNpadMode(u32 npad_id, NPadAssignments assignment_mode); + + void VibrateController(const std::vector& controller_ids, + const std::vector& vibrations); + + Kernel::SharedPtr GetStyleSetChangedEvent() const; + Vibration GetLastVibration() const; + + void AddNewController(NPadControllerType controller); + +private: + struct CommonHeader { + s64_le timestamp; + s64_le total_entry_count; + s64_le last_entry_index; + s64_le entry_count; + }; + static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); + + struct ControllerColor { + u32_le body_color; + u32_le button_color; + }; + static_assert(sizeof(ControllerColor) == 8, "ControllerColor is an invalid size"); + + struct ControllerPadState { + union { + u64_le raw{}; + // Button states + BitField<0, 1, u64_le> a; + BitField<1, 1, u64_le> b; + BitField<2, 1, u64_le> x; + BitField<3, 1, u64_le> y; + BitField<4, 1, u64_le> l_stick; + BitField<5, 1, u64_le> r_stick; + BitField<6, 1, u64_le> l; + BitField<7, 1, u64_le> r; + BitField<8, 1, u64_le> zl; + BitField<9, 1, u64_le> zr; + BitField<10, 1, u64_le> plus; + BitField<11, 1, u64_le> minus; + + // D-Pad + BitField<12, 1, u64_le> dleft; + BitField<13, 1, u64_le> dup; + BitField<14, 1, u64_le> dright; + BitField<15, 1, u64_le> ddown; + + // Left JoyStick + BitField<16, 1, u64_le> lstickleft; + BitField<17, 1, u64_le> lstickup; + BitField<18, 1, u64_le> lstickright; + BitField<19, 1, u64_le> lstickdown; + + // Right JoyStick + BitField<20, 1, u64_le> rstickleft; + BitField<21, 1, u64_le> rstickup; + BitField<22, 1, u64_le> rstickright; + BitField<23, 1, u64_le> rstickdown; + + // Not always active? + BitField<24, 1, u64_le> sl; + BitField<25, 1, u64_le> sr; + }; + }; + static_assert(sizeof(ControllerPadState) == 8, "ControllerPadState is an invalid size"); + + struct AnalogPosition { + s32_le x; + s32_le y; + }; + static_assert(sizeof(AnalogPosition) == 8, "AnalogPosition is an invalid size"); + + struct ConnectionState { + union { + u32_le raw{}; + BitField<0, 1, u32_le> IsConnected; + BitField<1, 1, u32_le> IsWired; + }; + }; + static_assert(sizeof(ConnectionState) == 4, "ConnectionState is an invalid size"); + + struct GenericStates { + s64_le timestamp; + s64_le timestamp2; + ControllerPadState pad_states; + AnalogPosition lstick; + AnalogPosition rstick; + ConnectionState connection_status; + }; + static_assert(sizeof(GenericStates) == 0x30, "NPadGenericStates is an invalid size"); + + struct NPadGeneric { + CommonHeader common; + std::array npad; + }; + static_assert(sizeof(NPadGeneric) == 0x350, "NPadGeneric is an invalid size"); + + enum class ColorReadError : u32_le { + ReadOk = 0, + ColorDoesntExist = 1, + NoController = 2, + }; + + struct NPadProperties { + union { + s64_le raw{}; + BitField<11, 1, s64_le> is_verticle; + BitField<12, 1, s64_le> is_horizontal; + }; + }; + + struct NPadDevice { + union { + u32_le raw{}; + BitField<0, 1, s32_le> pro_controller; + BitField<1, 1, s32_le> handheld; + BitField<2, 1, s32_le> handheld_left; + BitField<3, 1, s32_le> handheld_right; + BitField<4, 1, s32_le> joycon_left; + BitField<5, 1, s32_le> joycon_right; + BitField<6, 1, s32_le> pokeball; + }; + }; + + struct NPadEntry { + NPadType joy_styles; + NPadAssignments pad_assignment; + + ColorReadError single_color_error; + ControllerColor single_color; + + ColorReadError dual_color_error; + ControllerColor left_color; + ControllerColor right_color; + + NPadGeneric main_controller_states; + NPadGeneric handheld_states; + NPadGeneric dual_states; + NPadGeneric left_joy_states; + NPadGeneric right_joy_states; + NPadGeneric pokeball_states; + NPadGeneric libnx; // TODO(ogniK): Find out what this actually is, libnx seems to only be + // relying on this for the time being + INSERT_PADDING_BYTES( + 0x708 * + 6); // TODO(ogniK)L SixAxis states, require more information before implementation + NPadDevice device_type; + NPadProperties properties; + INSERT_PADDING_WORDS(4); + INSERT_PADDING_BYTES(0x60); + INSERT_PADDING_BYTES(0xdf8); + }; + static_assert(sizeof(NPadEntry) == 0x5000, "NPadEntry is an invalid size"); + NPadType style{}; + std::array shared_memory_entries{}; + std::array, Settings::NativeButton::NUM_BUTTONS_HID> + buttons; + std::array, Settings::NativeAnalog::NUM_STICKS_HID> sticks; + std::vector supported_npad_id_types{}; + NpadHoldType hold_type{NpadHoldType::Vertical}; + Kernel::SharedPtr styleset_changed_event; + size_t dump_idx{}; + Vibration last_processed_vibration{}; + void InitNewlyAddedControler(size_t controller_idx); +}; +}; // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/stubbed.cpp b/src/core/hle/service/hid/controllers/stubbed.cpp new file mode 100644 index 0000000000..0a602fce2b --- /dev/null +++ b/src/core/hle/service/hid/controllers/stubbed.cpp @@ -0,0 +1,32 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/common_types.h" +#include "common/swap.h" +#include "core/core_timing.h" +#include "core/hle/service/hid/controllers/stubbed.h" + +namespace Service::HID { +void Controller_Stubbed::OnInit() {} +void Controller_Stubbed::OnRelease() {} +void Controller_Stubbed::OnUpdate(u8* data, size_t size) { + if (!smart_update) { + return; + } + + CommonHeader header{}; + header.timestamp = CoreTiming::GetTicks(); + header.total_entry_count = 17; + header.entry_count = 0; + header.last_entry_index = 0; + + std::memcpy(data + common_offset, &header, sizeof(CommonHeader)); +} +void Controller_Stubbed::OnLoadInputDevices() {} + +void Controller_Stubbed::SetCommonHeaderOffset(size_t off) { + common_offset = off; + smart_update = true; +} +}; // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/stubbed.h b/src/core/hle/service/hid/controllers/stubbed.h new file mode 100644 index 0000000000..ec7adacb35 --- /dev/null +++ b/src/core/hle/service/hid/controllers/stubbed.h @@ -0,0 +1,32 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once +#include "common/common_types.h" +#include "core/hle/service/hid/controllers/controller_base.h" + +namespace Service::HID { +class Controller_Stubbed final : public ControllerBase { +public: + Controller_Stubbed() = default; + + // Called when the controller is initialized + void OnInit() override; + + // When the controller is released + void OnRelease() override; + + // When the controller is requesting an update for the shared memory + void OnUpdate(u8* data, size_t size) override; + + // Called when input devices should be loaded + void OnLoadInputDevices() override; + + void SetCommonHeaderOffset(size_t off); + +private: + bool smart_update{}; + size_t common_offset{}; +}; +}; // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp new file mode 100644 index 0000000000..b675dec8e5 --- /dev/null +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp @@ -0,0 +1,58 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/common_types.h" +#include "common/swap.h" +#include "core/core_timing.h" +#include "core/frontend/emu_window.h" +#include "core/frontend/input.h" +#include "core/hle/service/hid/controllers/touchscreen.h" +#include "core/settings.h" + +namespace Service::HID { +constexpr size_t SHARED_MEMORY_OFFSET = 0x400; +void Controller_Touchscreen::OnInit() {} +void Controller_Touchscreen::OnRelease() {} +void Controller_Touchscreen::OnUpdate(u8* data, size_t size) { + shared_memory.header.timestamp = CoreTiming::GetTicks(); + shared_memory.header.total_entry_count = 17; + + if (!IsControllerActivated()) { + shared_memory.header.entry_count = 0; + shared_memory.header.last_entry_index = 0; + return; + } + shared_memory.header.entry_count = 16; + + auto& last_entry = shared_memory.shared_memory_entries[shared_memory.header.last_entry_index]; + shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; + auto& cur_entry = shared_memory.shared_memory_entries[shared_memory.header.last_entry_index]; + + cur_entry.sampling_number = last_entry.sampling_number + 1; + cur_entry.sampling_number2 = cur_entry.sampling_number; + + auto [x, y, pressed] = touch_device->GetStatus(); + auto& touch_entry = cur_entry.states[0]; + if (pressed) { + touch_entry.x = static_cast(x * Layout::ScreenUndocked::Width); + touch_entry.y = static_cast(y * Layout::ScreenUndocked::Height); + touch_entry.diameter_x = 15; + touch_entry.diameter_y = 15; + touch_entry.rotation_angle = 0; + const u64 tick = CoreTiming::GetTicks(); + touch_entry.delta_time = tick - last_touch; + last_touch = tick; + touch_entry.finger = 0; + cur_entry.entry_count = 1; + } else { + cur_entry.entry_count = 0; + } + + std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(TouchScreenSharedMemory)); +} + +void Controller_Touchscreen::OnLoadInputDevices() { + touch_device = Input::CreateDevice(Settings::values.touch_device); +} +}; // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h new file mode 100644 index 0000000000..a516128aca --- /dev/null +++ b/src/core/hle/service/hid/controllers/touchscreen.h @@ -0,0 +1,61 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once +#include "common/common_funcs.h" +#include "common/common_types.h" +#include "common/swap.h" +#include "core/frontend/input.h" +#include "core/hle/service/hid/controllers/controller_base.h" + +namespace Service::HID { +class Controller_Touchscreen final : public ControllerBase { +public: + Controller_Touchscreen() = default; + + // Called when the controller is initialized + void OnInit() override; + + // When the controller is released + void OnRelease() override; + + // When the controller is requesting an update for the shared memory + void OnUpdate(u8* data, size_t size) override; + + // Called when input devices should be loaded + void OnLoadInputDevices() override; + +private: + struct TouchState { + u64_le delta_time; + u32_le attribute; + u32_le finger; + u32_le x; + u32_le y; + u32_le diameter_x; + u32_le diameter_y; + u32_le rotation_angle; + }; + static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size"); + + struct TouchScreenEntry { + s64_le sampling_number; + s64_le sampling_number2; + s32_le entry_count; + std::array states; + }; + static_assert(sizeof(TouchScreenEntry) == 0x298, "TouchScreenEntry is an invalid size"); + + struct TouchScreenSharedMemory { + CommonHeader header; + std::array shared_memory_entries{}; + INSERT_PADDING_BYTES(0x3c8); + }; + static_assert(sizeof(TouchScreenSharedMemory) == 0x3000, + "TouchScreenSharedMemory is an invalid size"); + TouchScreenSharedMemory shared_memory{}; + std::unique_ptr touch_device; + s64_le last_touch{}; +}; +}; // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/xpad.cpp b/src/core/hle/service/hid/controllers/xpad.cpp new file mode 100644 index 0000000000..521e925b7c --- /dev/null +++ b/src/core/hle/service/hid/controllers/xpad.cpp @@ -0,0 +1,38 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/common_types.h" +#include "common/swap.h" +#include "core/core_timing.h" +#include "core/hle/service/hid/controllers/xpad.h" + +namespace Service::HID { +constexpr size_t SHARED_MEMORY_OFFSET = 0x3C00; +void Controller_XPad::OnInit() {} +void Controller_XPad::OnRelease() {} +void Controller_XPad::OnUpdate(u8* data, size_t size) { + for (auto& xpad_entry : shared_memory.shared_memory_entries) { + xpad_entry.header.timestamp = CoreTiming::GetTicks(); + xpad_entry.header.total_entry_count = 17; + + if (!IsControllerActivated()) { + xpad_entry.header.entry_count = 0; + xpad_entry.header.last_entry_index = 0; + return; + } + xpad_entry.header.entry_count = 16; + + auto& last_entry = xpad_entry.pad_states[xpad_entry.header.last_entry_index]; + xpad_entry.header.last_entry_index = (xpad_entry.header.last_entry_index + 1) % 17; + auto& cur_entry = xpad_entry.pad_states[xpad_entry.header.last_entry_index]; + + cur_entry.sampling_number = last_entry.sampling_number + 1; + cur_entry.sampling_number2 = cur_entry.sampling_number; + } + // TODO(ogniK): Update xpad states + + std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); +} +void Controller_XPad::OnLoadInputDevices() {} +}; // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h new file mode 100644 index 0000000000..898fadfdc9 --- /dev/null +++ b/src/core/hle/service/hid/controllers/xpad.h @@ -0,0 +1,59 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once +#include "common/common_funcs.h" +#include "common/common_types.h" +#include "common/swap.h" +#include "core/frontend/input.h" +#include "core/hle/service/hid/controllers/controller_base.h" + +namespace Service::HID { +class Controller_XPad final : public ControllerBase { +public: + Controller_XPad() = default; + + // Called when the controller is initialized + void OnInit() override; + + // When the controller is released + void OnRelease() override; + + // When the controller is requesting an update for the shared memory + void OnUpdate(u8* data, size_t size) override; + + // Called when input devices should be loaded + void OnLoadInputDevices() override; + +private: + struct AnalogStick { + s32_le x; + s32_le y; + }; + static_assert(sizeof(AnalogStick) == 0x8, "AnalogStick is an invalid size"); + + struct XPadState { + s64_le sampling_number; + s64_le sampling_number2; + s32_le attributes; + u32_le pad_states; + AnalogStick x_stick; + AnalogStick y_stick; + }; + static_assert(sizeof(XPadState) == 0x28, "XPadState is an invalid size"); + + struct XPadEntry { + CommonHeader header; + std::array pad_states{}; + INSERT_PADDING_BYTES(0x138); + }; + static_assert(sizeof(XPadEntry) == 0x400, "XPadEntry is an invalid size"); + + struct SharedMemory { + std::array shared_memory_entries{}; + }; + static_assert(sizeof(SharedMemory) == 0x1000, "SharedMemory is an invalid size"); + SharedMemory shared_memory{}; +}; +}; // namespace Service::HID diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 7c6b0a4e6f..757b3b7702 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include +#include "common/common_types.h" #include "common/logging/log.h" #include "core/core.h" #include "core/core_timing.h" @@ -19,6 +21,16 @@ #include "core/hle/service/service.h" #include "core/settings.h" +#include "core/hle/service/hid/controllers/controller_base.h" +#include "core/hle/service/hid/controllers/debug_pad.h" +#include "core/hle/service/hid/controllers/gesture.h" +#include "core/hle/service/hid/controllers/keyboard.h" +#include "core/hle/service/hid/controllers/mouse.h" +#include "core/hle/service/hid/controllers/npad.h" +#include "core/hle/service/hid/controllers/stubbed.h" +#include "core/hle/service/hid/controllers/touchscreen.h" +#include "core/hle/service/hid/controllers/xpad.h" + namespace Service::HID { // Updating period for each HID device. @@ -26,6 +38,22 @@ namespace Service::HID { constexpr u64 pad_update_ticks = CoreTiming::BASE_CLOCK_RATE / 100; constexpr u64 accelerometer_update_ticks = CoreTiming::BASE_CLOCK_RATE / 100; constexpr u64 gyroscope_update_ticks = CoreTiming::BASE_CLOCK_RATE / 100; +constexpr size_t SHARED_MEMORY_SIZE = 0x40000; +enum class HidController : size_t { + DebugPad, + Touchscreen, + Mouse, + Keyboard, + XPad, + Unknown1, + Unknown2, + Unknown3, + SixAxisSensor, + NPad, + Gesture, + + MaxControllers +}; class IAppletResource final : public ServiceFramework { public: @@ -37,19 +65,64 @@ public: auto& kernel = Core::System::GetInstance().Kernel(); shared_mem = Kernel::SharedMemory::Create( - kernel, nullptr, 0x40000, Kernel::MemoryPermission::ReadWrite, + kernel, nullptr, SHARED_MEMORY_SIZE, Kernel::MemoryPermission::ReadWrite, Kernel::MemoryPermission::Read, 0, Kernel::MemoryRegion::BASE, "HID:SharedMemory"); + controllers[static_cast(HidController::DebugPad)] = + std::make_unique(); + controllers[static_cast(HidController::Touchscreen)] = + std::make_unique(); + controllers[static_cast(HidController::Mouse)] = + std::make_unique(); + controllers[static_cast(HidController::Keyboard)] = + std::make_unique(); + controllers[static_cast(HidController::XPad)] = std::make_unique(); + + controllers[static_cast(HidController::Unknown1)] = + std::make_unique(); + controllers[static_cast(HidController::Unknown2)] = + std::make_unique(); + controllers[static_cast(HidController::Unknown3)] = + std::make_unique(); + + controllers[static_cast(HidController::SixAxisSensor)] = + std::make_unique(); + + controllers[static_cast(HidController::NPad)] = std::make_unique(); + controllers[static_cast(HidController::Gesture)] = + std::make_unique(); + + // Homebrew doesn't try to activate some controllers, so we activate them by default + controllers[static_cast(HidController::NPad)]->ActivateController(); + controllers[static_cast(HidController::Touchscreen)]->ActivateController(); + + GetController(HidController::Unknown1).SetCommonHeaderOffset(0x4c00); + GetController(HidController::Unknown2).SetCommonHeaderOffset(0x4e00); + GetController(HidController::Unknown3).SetCommonHeaderOffset(0x5000); + // Register update callbacks pad_update_event = CoreTiming::RegisterEvent( "HID::UpdatePadCallback", - [this](u64 userdata, int cycles_late) { UpdatePadCallback(userdata, cycles_late); }); + [this](u64 userdata, int cycles_late) { UpdateControllers(userdata, cycles_late); }); // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?) CoreTiming::ScheduleEvent(pad_update_ticks, pad_update_event); } + void ActivateController(HidController controller) { + controllers[static_cast(controller)]->ActivateController(); + } + + void DeactivateController(HidController controller) { + controllers[static_cast(controller)]->DeactivateController(); + } + + template + T& GetController(HidController controller) { + return static_cast(*controllers[static_cast(controller)]); + } + ~IAppletResource() { CoreTiming::UnscheduleEvent(pad_update_event, 0); } @@ -62,200 +135,15 @@ private: LOG_DEBUG(Service_HID, "called"); } - void LoadInputDevices() { - std::transform(Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, - Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_END, - buttons.begin(), Input::CreateDevice); - std::transform(Settings::values.analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, - Settings::values.analogs.begin() + Settings::NativeAnalog::STICK_HID_END, - sticks.begin(), Input::CreateDevice); - touch_device = Input::CreateDevice(Settings::values.touch_device); - // TODO(shinyquagsire23): gyro, mouse, keyboard - } - - void UpdatePadCallback(u64 userdata, int cycles_late) { - SharedMemory mem{}; - std::memcpy(&mem, shared_mem->GetPointer(), sizeof(SharedMemory)); - - if (Settings::values.is_device_reload_pending.exchange(false)) - LoadInputDevices(); - - // Set up controllers as neon red+blue Joy-Con attached to console - ControllerHeader& controller_header = mem.controllers[Controller_Handheld].header; - controller_header.type = ControllerType_Handheld; - controller_header.single_colors_descriptor = ColorDesc_ColorsNonexistent; - controller_header.right_color_body = JOYCON_BODY_NEON_RED; - controller_header.right_color_buttons = JOYCON_BUTTONS_NEON_RED; - controller_header.left_color_body = JOYCON_BODY_NEON_BLUE; - controller_header.left_color_buttons = JOYCON_BUTTONS_NEON_BLUE; - - for (std::size_t controller = 0; controller < mem.controllers.size(); controller++) { - for (auto& layout : mem.controllers[controller].layouts) { - layout.header.num_entries = HID_NUM_ENTRIES; - layout.header.max_entry_index = HID_NUM_ENTRIES - 1; - - // HID shared memory stores the state of the past 17 samples in a circlular buffer, - // each with a timestamp in number of samples since boot. - const ControllerInputEntry& last_entry = layout.entries[layout.header.latest_entry]; - - layout.header.timestamp_ticks = CoreTiming::GetTicks(); - layout.header.latest_entry = (layout.header.latest_entry + 1) % HID_NUM_ENTRIES; - - ControllerInputEntry& entry = layout.entries[layout.header.latest_entry]; - entry.timestamp = last_entry.timestamp + 1; - // TODO(shinyquagsire23): Is this always identical to timestamp? - entry.timestamp_2 = entry.timestamp; - - // TODO(shinyquagsire23): More than just handheld input - if (controller != Controller_Handheld) - continue; - - entry.connection_state = ConnectionState_Connected | ConnectionState_Wired; - - // TODO(shinyquagsire23): Set up some LUTs for each layout mapping in the future? - // For now everything is just the default handheld layout, but split Joy-Con will - // rotate the face buttons and directions for certain layouts. - ControllerPadState& state = entry.buttons; - using namespace Settings::NativeButton; - state.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus()); - state.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus()); - state.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus()); - state.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus()); - state.lstick.Assign(buttons[LStick - BUTTON_HID_BEGIN]->GetStatus()); - state.rstick.Assign(buttons[RStick - BUTTON_HID_BEGIN]->GetStatus()); - state.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus()); - state.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus()); - state.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus()); - state.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus()); - state.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus()); - state.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus()); - - state.dleft.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus()); - state.dup.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus()); - state.dright.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus()); - state.ddown.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus()); - - state.lstick_left.Assign(buttons[LStick_Left - BUTTON_HID_BEGIN]->GetStatus()); - state.lstick_up.Assign(buttons[LStick_Up - BUTTON_HID_BEGIN]->GetStatus()); - state.lstick_right.Assign(buttons[LStick_Right - BUTTON_HID_BEGIN]->GetStatus()); - state.lstick_down.Assign(buttons[LStick_Down - BUTTON_HID_BEGIN]->GetStatus()); - - state.rstick_left.Assign(buttons[RStick_Left - BUTTON_HID_BEGIN]->GetStatus()); - state.rstick_up.Assign(buttons[RStick_Up - BUTTON_HID_BEGIN]->GetStatus()); - state.rstick_right.Assign(buttons[RStick_Right - BUTTON_HID_BEGIN]->GetStatus()); - state.rstick_down.Assign(buttons[RStick_Down - BUTTON_HID_BEGIN]->GetStatus()); - - state.sl.Assign(buttons[SL - BUTTON_HID_BEGIN]->GetStatus()); - state.sr.Assign(buttons[SR - BUTTON_HID_BEGIN]->GetStatus()); - - const auto [stick_l_x_f, stick_l_y_f] = sticks[Joystick_Left]->GetStatus(); - const auto [stick_r_x_f, stick_r_y_f] = sticks[Joystick_Right]->GetStatus(); - entry.joystick_left_x = static_cast(stick_l_x_f * HID_JOYSTICK_MAX); - entry.joystick_left_y = static_cast(stick_l_y_f * HID_JOYSTICK_MAX); - entry.joystick_right_x = static_cast(stick_r_x_f * HID_JOYSTICK_MAX); - entry.joystick_right_y = static_cast(stick_r_y_f * HID_JOYSTICK_MAX); + void UpdateControllers(u64 userdata, int cycles_late) { + bool should_reload = Settings::values.is_device_reload_pending.exchange(false); + for (const auto& controller : controllers) { + if (should_reload) { + controller->OnLoadInputDevices(); } + controller->OnUpdate(shared_mem->GetPointer(), SHARED_MEMORY_SIZE); } - TouchScreen& touchscreen = mem.touchscreen; - const u64 last_entry = touchscreen.header.latest_entry; - const u64 curr_entry = (last_entry + 1) % touchscreen.entries.size(); - const u64 timestamp = CoreTiming::GetTicks(); - const u64 sample_counter = touchscreen.entries[last_entry].header.timestamp + 1; - touchscreen.header.timestamp_ticks = timestamp; - touchscreen.header.num_entries = touchscreen.entries.size(); - touchscreen.header.latest_entry = curr_entry; - touchscreen.header.max_entry_index = touchscreen.entries.size(); - touchscreen.header.timestamp = timestamp; - touchscreen.entries[curr_entry].header.timestamp = sample_counter; - - TouchScreenEntryTouch touch_entry{}; - auto [x, y, pressed] = touch_device->GetStatus(); - touch_entry.timestamp = timestamp; - touch_entry.x = static_cast(x * Layout::ScreenUndocked::Width); - touch_entry.y = static_cast(y * Layout::ScreenUndocked::Height); - touch_entry.touch_index = 0; - - // TODO(DarkLordZach): Maybe try to derive these from EmuWindow? - touch_entry.diameter_x = 15; - touch_entry.diameter_y = 15; - touch_entry.angle = 0; - - // TODO(DarkLordZach): Implement multi-touch support - if (pressed) { - touchscreen.entries[curr_entry].header.num_touches = 1; - touchscreen.entries[curr_entry].touches[0] = touch_entry; - } else { - touchscreen.entries[curr_entry].header.num_touches = 0; - } - - // TODO(shinyquagsire23): Properly implement mouse - Mouse& mouse = mem.mouse; - const u64 last_mouse_entry = mouse.header.latest_entry; - const u64 curr_mouse_entry = (mouse.header.latest_entry + 1) % mouse.entries.size(); - const u64 mouse_sample_counter = mouse.entries[last_mouse_entry].timestamp + 1; - mouse.header.timestamp_ticks = timestamp; - mouse.header.num_entries = mouse.entries.size(); - mouse.header.max_entry_index = mouse.entries.size(); - mouse.header.latest_entry = curr_mouse_entry; - - mouse.entries[curr_mouse_entry].timestamp = mouse_sample_counter; - mouse.entries[curr_mouse_entry].timestamp_2 = mouse_sample_counter; - - // TODO(shinyquagsire23): Properly implement keyboard - Keyboard& keyboard = mem.keyboard; - const u64 last_keyboard_entry = keyboard.header.latest_entry; - const u64 curr_keyboard_entry = - (keyboard.header.latest_entry + 1) % keyboard.entries.size(); - const u64 keyboard_sample_counter = keyboard.entries[last_keyboard_entry].timestamp + 1; - keyboard.header.timestamp_ticks = timestamp; - keyboard.header.num_entries = keyboard.entries.size(); - keyboard.header.latest_entry = last_keyboard_entry; - keyboard.header.max_entry_index = keyboard.entries.size(); - - keyboard.entries[curr_keyboard_entry].timestamp = keyboard_sample_counter; - keyboard.entries[curr_keyboard_entry].timestamp_2 = keyboard_sample_counter; - - // TODO(shinyquagsire23): Figure out what any of these are - for (auto& input : mem.unk_input_1) { - const u64 last_input_entry = input.header.latest_entry; - const u64 curr_input_entry = (input.header.latest_entry + 1) % input.entries.size(); - const u64 input_sample_counter = input.entries[last_input_entry].timestamp + 1; - - input.header.timestamp_ticks = timestamp; - input.header.num_entries = input.entries.size(); - input.header.latest_entry = last_input_entry; - input.header.max_entry_index = input.entries.size(); - - input.entries[curr_input_entry].timestamp = input_sample_counter; - input.entries[curr_input_entry].timestamp_2 = input_sample_counter; - } - - for (auto& input : mem.unk_input_2) { - input.header.timestamp_ticks = timestamp; - input.header.num_entries = 17; - input.header.latest_entry = 0; - input.header.max_entry_index = 0; - } - - UnkInput3& input = mem.unk_input_3; - const u64 last_input_entry = input.header.latest_entry; - const u64 curr_input_entry = (input.header.latest_entry + 1) % input.entries.size(); - const u64 input_sample_counter = input.entries[last_input_entry].timestamp + 1; - - input.header.timestamp_ticks = timestamp; - input.header.num_entries = input.entries.size(); - input.header.latest_entry = last_input_entry; - input.header.max_entry_index = input.entries.size(); - - input.entries[curr_input_entry].timestamp = input_sample_counter; - input.entries[curr_input_entry].timestamp_2 = input_sample_counter; - - // TODO(shinyquagsire23): Signal events - - std::memcpy(shared_mem->GetPointer(), &mem, sizeof(SharedMemory)); - - // Reschedule recurrent event CoreTiming::ScheduleEvent(pad_update_ticks - cycles_late, pad_update_event); } @@ -265,11 +153,8 @@ private: // CoreTiming update events CoreTiming::EventType* pad_update_event; - // Stored input state info - std::array, Settings::NativeButton::NUM_BUTTONS_HID> - buttons; - std::array, Settings::NativeAnalog::NUM_STICKS_HID> sticks; - std::unique_ptr touch_device; + std::array, static_cast(HidController::MaxControllers)> + controllers{}; }; class IActiveVibrationDeviceList final : public ServiceFramework { @@ -301,7 +186,7 @@ public: {31, &Hid::ActivateKeyboard, "ActivateKeyboard"}, {40, nullptr, "AcquireXpadIdEventHandle"}, {41, nullptr, "ReleaseXpadIdEventHandle"}, - {51, nullptr, "ActivateXpad"}, + {51, &Hid::ActivateXpad, "ActivateXpad"}, {55, nullptr, "GetXpadIds"}, {56, nullptr, "ActivateJoyXpad"}, {58, nullptr, "GetJoyXpadLifoHandle"}, @@ -401,16 +286,11 @@ public: // clang-format on RegisterHandlers(functions); - - auto& kernel = Core::System::GetInstance().Kernel(); - event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "hid:EventHandle"); } ~Hid() = default; private: std::shared_ptr applet_resource; - u32 joy_hold_type{0}; - Kernel::SharedPtr event; void CreateAppletResource(Kernel::HLERequestContext& ctx) { if (applet_resource == nullptr) { @@ -423,28 +303,54 @@ private: LOG_DEBUG(Service_HID, "called"); } - void ActivateDebugPad(Kernel::HLERequestContext& ctx) { + void ActivateXpad(Kernel::HLERequestContext& ctx) { + applet_resource->ActivateController(HidController::XPad); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + LOG_DEBUG(Service_HID, "called"); + } + + void ActivateDebugPad(Kernel::HLERequestContext& ctx) { + applet_resource->ActivateController(HidController::DebugPad); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_DEBUG(Service_HID, "called"); } void ActivateTouchScreen(Kernel::HLERequestContext& ctx) { + applet_resource->ActivateController(HidController::Touchscreen); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + LOG_DEBUG(Service_HID, "called"); } void ActivateMouse(Kernel::HLERequestContext& ctx) { + applet_resource->ActivateController(HidController::Mouse); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + LOG_DEBUG(Service_HID, "called"); } void ActivateKeyboard(Kernel::HLERequestContext& ctx) { + applet_resource->ActivateController(HidController::Keyboard); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + LOG_DEBUG(Service_HID, "called"); + } + + void ActivateGesture(Kernel::HLERequestContext& ctx) { + applet_resource->ActivateController(HidController::Gesture); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_DEBUG(Service_HID, "called"); + } + + void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) { + // Should have no effect with how our npad sets up the data + applet_resource->ActivateController(HidController::NPad); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_DEBUG(Service_HID, "called"); } void StartSixAxisSensor(Kernel::HLERequestContext& ctx) { @@ -468,41 +374,55 @@ private: } void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + auto supported_styleset = rp.PopRaw(); + applet_resource->GetController(HidController::NPad) + .SetSupportedStyleSet({supported_styleset}); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + + LOG_DEBUG(Service_HID, "called"); } void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { + std::string blah = ctx.Description(); + auto& controller = applet_resource->GetController(HidController::NPad); + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push(0); - LOG_WARNING(Service_HID, "(STUBBED) called"); + rb.Push(controller.GetSupportedStyleSet().raw); + LOG_DEBUG(Service_HID, "called"); } void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) { + applet_resource->GetController(HidController::NPad) + .SetSupportedNPadIdTypes(ctx.ReadBuffer().data(), ctx.GetReadBufferSize()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + LOG_DEBUG(Service_HID, "called"); } void ActivateNpad(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + applet_resource->ActivateController(HidController::NPad); + LOG_DEBUG(Service_HID, "called"); } void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(RESULT_SUCCESS); - rb.PushCopyObjects(event); - LOG_WARNING(Service_HID, "(STUBBED) called"); + rb.PushCopyObjects(applet_resource->GetController(HidController::NPad) + .GetStyleSetChangedEvent()); + LOG_DEBUG(Service_HID, "called"); } void DisconnectNpad(Kernel::HLERequestContext& ctx) { + applet_resource->DeactivateController(HidController::NPad); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + LOG_DEBUG(Service_HID, "called"); } void GetPlayerLedPattern(Kernel::HLERequestContext& ctx) { @@ -512,16 +432,22 @@ private: } void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { + auto& controller = applet_resource->GetController(HidController::NPad); + IPC::RequestParser rp{ctx}; + auto hold_type = rp.PopRaw(); + controller.SetHoldType(Controller_NPad::NpadHoldType{hold_type}); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + LOG_DEBUG(Service_HID, "called"); } void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 3}; + auto& controller = applet_resource->GetController(HidController::NPad); + IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); - rb.Push(joy_hold_type); - LOG_WARNING(Service_HID, "(STUBBED) called"); + rb.Push(static_cast(controller.GetHoldType())); + LOG_DEBUG(Service_HID, "called"); } void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) { @@ -531,21 +457,57 @@ private: } void SendVibrationValue(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + auto controller_id = rp.PopRaw(); + auto vibration_values = rp.PopRaw(); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + + applet_resource->GetController(HidController::NPad) + .VibrateController({controller_id}, {vibration_values}); + LOG_DEBUG(Service_HID, "called"); + } + + void SendVibrationValues(Kernel::HLERequestContext& ctx) { + auto controllers = ctx.ReadBuffer(0); + auto vibrations = ctx.ReadBuffer(1); + + std::vector controller_list(controllers.size() / sizeof(u32)); + std::vector vibration_list(vibrations.size() / + sizeof(Controller_NPad::Vibration)); + + std::memcpy(controller_list.data(), controllers.data(), controllers.size()); + std::memcpy(vibration_list.data(), vibrations.data(), vibrations.size()); + std::transform(controller_list.begin(), controller_list.end(), controller_list.begin(), + [](u32 controller_id) { return controller_id - 3; }); + + applet_resource->GetController(HidController::NPad) + .VibrateController(controller_list, vibration_list); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_DEBUG(Service_HID, "called"); } void GetActualVibrationValue(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2}; + IPC::ResponseBuilder rb{ctx, 6}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + rb.PushRaw( + applet_resource->GetController(HidController::NPad) + .GetLastVibration()); + LOG_DEBUG(Service_HID, "called"); } void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + auto npad_id = rp.PopRaw(); + auto& controller = applet_resource->GetController(HidController::NPad); + controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Dual); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + LOG_DEBUG(Service_HID, "called"); } void MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) { @@ -563,8 +525,9 @@ private: void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); - rb.Push(0); - LOG_WARNING(Service_HID, "(STUBBED) called"); + rb.Push(1); + rb.Push(0); + LOG_DEBUG(Service_HID, "called"); } void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { @@ -574,12 +537,6 @@ private: LOG_DEBUG(Service_HID, "called"); } - void SendVibrationValues(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); - } - void ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -597,18 +554,6 @@ private: rb.Push(RESULT_SUCCESS); LOG_WARNING(Service_HID, "(STUBBED) called"); } - - void ActivateGesture(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); - } - - void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); - } }; class HidDbg final : public ServiceFramework { diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 88d9268084..7730354602 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -4,408 +4,12 @@ #pragma once -#include -#include "common/bit_field.h" -#include "common/common_types.h" -#include "core/hle/service/service.h" +namespace SM { +class ServiceManager; +} namespace Service::HID { -// Begin enums and output structs - -constexpr u32 HID_NUM_ENTRIES = 17; -constexpr u32 HID_NUM_LAYOUTS = 7; -constexpr s32 HID_JOYSTICK_MAX = 0x8000; -constexpr s32 HID_JOYSTICK_MIN = -0x8000; - -constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28; -constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A; -constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6; -constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E; - -enum ControllerType : u32 { - ControllerType_ProController = 1 << 0, - ControllerType_Handheld = 1 << 1, - ControllerType_JoyconPair = 1 << 2, - ControllerType_JoyconLeft = 1 << 3, - ControllerType_JoyconRight = 1 << 4, -}; - -enum ControllerLayoutType : u32 { - Layout_ProController = 0, // Pro Controller or HID gamepad - Layout_Handheld = 1, // Two Joy-Con docked to rails - Layout_Single = 2, // Horizontal single Joy-Con or pair of Joy-Con, adjusted for orientation - Layout_Left = 3, // Only raw left Joy-Con state, no orientation adjustment - Layout_Right = 4, // Only raw right Joy-Con state, no orientation adjustment - Layout_DefaultDigital = 5, // Same as next, but sticks have 8-direction values only - Layout_Default = 6, // Safe default, single Joy-Con have buttons/sticks rotated for orientation -}; - -enum ControllerColorDescription { - ColorDesc_ColorsNonexistent = 1 << 1, -}; - -enum ControllerConnectionState { - ConnectionState_Connected = 1 << 0, - ConnectionState_Wired = 1 << 1, -}; - -enum ControllerJoystick { - Joystick_Left = 0, - Joystick_Right = 1, -}; - -enum ControllerID { - Controller_Player1 = 0, - Controller_Player2 = 1, - Controller_Player3 = 2, - Controller_Player4 = 3, - Controller_Player5 = 4, - Controller_Player6 = 5, - Controller_Player7 = 6, - Controller_Player8 = 7, - Controller_Handheld = 8, - Controller_Unknown = 9, -}; - -// End enums and output structs - -// Begin UnkInput3 - -struct UnkInput3Header { - u64 timestamp_ticks; - u64 num_entries; - u64 latest_entry; - u64 max_entry_index; -}; -static_assert(sizeof(UnkInput3Header) == 0x20, "HID UnkInput3 header structure has incorrect size"); - -struct UnkInput3Entry { - u64 timestamp; - u64 timestamp_2; - u64 unk_8; - u64 unk_10; - u64 unk_18; -}; -static_assert(sizeof(UnkInput3Entry) == 0x28, "HID UnkInput3 entry structure has incorrect size"); - -struct UnkInput3 { - UnkInput3Header header; - std::array entries; - std::array padding; -}; -static_assert(sizeof(UnkInput3) == 0x400, "HID UnkInput3 structure has incorrect size"); - -// End UnkInput3 - -// Begin TouchScreen - -struct TouchScreenHeader { - u64 timestamp_ticks; - u64 num_entries; - u64 latest_entry; - u64 max_entry_index; - u64 timestamp; -}; -static_assert(sizeof(TouchScreenHeader) == 0x28, - "HID touch screen header structure has incorrect size"); - -struct TouchScreenEntryHeader { - u64 timestamp; - u64 num_touches; -}; -static_assert(sizeof(TouchScreenEntryHeader) == 0x10, - "HID touch screen entry header structure has incorrect size"); - -struct TouchScreenEntryTouch { - u64 timestamp; - u32 padding; - u32 touch_index; - u32 x; - u32 y; - u32 diameter_x; - u32 diameter_y; - u32 angle; - u32 padding_2; -}; -static_assert(sizeof(TouchScreenEntryTouch) == 0x28, - "HID touch screen touch structure has incorrect size"); - -struct TouchScreenEntry { - TouchScreenEntryHeader header; - std::array touches; - u64 unk; -}; -static_assert(sizeof(TouchScreenEntry) == 0x298, - "HID touch screen entry structure has incorrect size"); - -struct TouchScreen { - TouchScreenHeader header; - std::array entries; - std::array padding; -}; -static_assert(sizeof(TouchScreen) == 0x3000, "HID touch screen structure has incorrect size"); - -// End TouchScreen - -// Begin Mouse - -struct MouseHeader { - u64 timestamp_ticks; - u64 num_entries; - u64 latest_entry; - u64 max_entry_index; -}; -static_assert(sizeof(MouseHeader) == 0x20, "HID mouse header structure has incorrect size"); - -struct MouseButtonState { - union { - u64 hex{}; - - // Buttons - BitField<0, 1, u64> left; - BitField<1, 1, u64> right; - BitField<2, 1, u64> middle; - BitField<3, 1, u64> forward; - BitField<4, 1, u64> back; - }; -}; - -struct MouseEntry { - u64 timestamp; - u64 timestamp_2; - u32 x; - u32 y; - u32 velocity_x; - u32 velocity_y; - u32 scroll_velocity_x; - u32 scroll_velocity_y; - MouseButtonState buttons; -}; -static_assert(sizeof(MouseEntry) == 0x30, "HID mouse entry structure has incorrect size"); - -struct Mouse { - MouseHeader header; - std::array entries; - std::array padding; -}; -static_assert(sizeof(Mouse) == 0x400, "HID mouse structure has incorrect size"); - -// End Mouse - -// Begin Keyboard - -struct KeyboardHeader { - u64 timestamp_ticks; - u64 num_entries; - u64 latest_entry; - u64 max_entry_index; -}; -static_assert(sizeof(KeyboardHeader) == 0x20, "HID keyboard header structure has incorrect size"); - -struct KeyboardModifierKeyState { - union { - u64 hex{}; - - // Buttons - BitField<0, 1, u64> lctrl; - BitField<1, 1, u64> lshift; - BitField<2, 1, u64> lalt; - BitField<3, 1, u64> lmeta; - BitField<4, 1, u64> rctrl; - BitField<5, 1, u64> rshift; - BitField<6, 1, u64> ralt; - BitField<7, 1, u64> rmeta; - BitField<8, 1, u64> capslock; - BitField<9, 1, u64> scrolllock; - BitField<10, 1, u64> numlock; - }; -}; - -struct KeyboardEntry { - u64 timestamp; - u64 timestamp_2; - KeyboardModifierKeyState modifier; - u32 keys[8]; -}; -static_assert(sizeof(KeyboardEntry) == 0x38, "HID keyboard entry structure has incorrect size"); - -struct Keyboard { - KeyboardHeader header; - std::array entries; - std::array padding; -}; -static_assert(sizeof(Keyboard) == 0x400, "HID keyboard structure has incorrect size"); - -// End Keyboard - -// Begin UnkInput1 - -struct UnkInput1Header { - u64 timestamp_ticks; - u64 num_entries; - u64 latest_entry; - u64 max_entry_index; -}; -static_assert(sizeof(UnkInput1Header) == 0x20, "HID UnkInput1 header structure has incorrect size"); - -struct UnkInput1Entry { - u64 timestamp; - u64 timestamp_2; - u64 unk_8; - u64 unk_10; - u64 unk_18; -}; -static_assert(sizeof(UnkInput1Entry) == 0x28, "HID UnkInput1 entry structure has incorrect size"); - -struct UnkInput1 { - UnkInput1Header header; - std::array entries; - std::array padding; -}; -static_assert(sizeof(UnkInput1) == 0x400, "HID UnkInput1 structure has incorrect size"); - -// End UnkInput1 - -// Begin UnkInput2 - -struct UnkInput2Header { - u64 timestamp_ticks; - u64 num_entries; - u64 latest_entry; - u64 max_entry_index; -}; -static_assert(sizeof(UnkInput2Header) == 0x20, "HID UnkInput2 header structure has incorrect size"); - -struct UnkInput2 { - UnkInput2Header header; - std::array padding; -}; -static_assert(sizeof(UnkInput2) == 0x200, "HID UnkInput2 structure has incorrect size"); - -// End UnkInput2 - -// Begin Controller - -struct ControllerMAC { - u64 timestamp; - std::array mac; - u64 unk; - u64 timestamp_2; -}; -static_assert(sizeof(ControllerMAC) == 0x20, "HID controller MAC structure has incorrect size"); - -struct ControllerHeader { - u32 type; - u32 is_half; - u32 single_colors_descriptor; - u32 single_color_body; - u32 single_color_buttons; - u32 split_colors_descriptor; - u32 left_color_body; - u32 left_color_buttons; - u32 right_color_body; - u32 right_color_buttons; -}; -static_assert(sizeof(ControllerHeader) == 0x28, - "HID controller header structure has incorrect size"); - -struct ControllerLayoutHeader { - u64 timestamp_ticks; - u64 num_entries; - u64 latest_entry; - u64 max_entry_index; -}; -static_assert(sizeof(ControllerLayoutHeader) == 0x20, - "HID controller layout header structure has incorrect size"); - -struct ControllerPadState { - union { - u64 hex{}; - - // Buttons - BitField<0, 1, u64> a; - BitField<1, 1, u64> b; - BitField<2, 1, u64> x; - BitField<3, 1, u64> y; - BitField<4, 1, u64> lstick; - BitField<5, 1, u64> rstick; - BitField<6, 1, u64> l; - BitField<7, 1, u64> r; - BitField<8, 1, u64> zl; - BitField<9, 1, u64> zr; - BitField<10, 1, u64> plus; - BitField<11, 1, u64> minus; - - // D-pad buttons - BitField<12, 1, u64> dleft; - BitField<13, 1, u64> dup; - BitField<14, 1, u64> dright; - BitField<15, 1, u64> ddown; - - // Left stick directions - BitField<16, 1, u64> lstick_left; - BitField<17, 1, u64> lstick_up; - BitField<18, 1, u64> lstick_right; - BitField<19, 1, u64> lstick_down; - - // Right stick directions - BitField<20, 1, u64> rstick_left; - BitField<21, 1, u64> rstick_up; - BitField<22, 1, u64> rstick_right; - BitField<23, 1, u64> rstick_down; - - BitField<24, 1, u64> sl; - BitField<25, 1, u64> sr; - }; -}; - -struct ControllerInputEntry { - u64 timestamp; - u64 timestamp_2; - ControllerPadState buttons; - s32 joystick_left_x; - s32 joystick_left_y; - s32 joystick_right_x; - s32 joystick_right_y; - u64 connection_state; -}; -static_assert(sizeof(ControllerInputEntry) == 0x30, - "HID controller input entry structure has incorrect size"); - -struct ControllerLayout { - ControllerLayoutHeader header; - std::array entries; -}; -static_assert(sizeof(ControllerLayout) == 0x350, - "HID controller layout structure has incorrect size"); - -struct Controller { - ControllerHeader header; - std::array layouts; - std::array unk_1; - ControllerMAC mac_left; - ControllerMAC mac_right; - std::array unk_2; -}; -static_assert(sizeof(Controller) == 0x5000, "HID controller structure has incorrect size"); - -// End Controller - -struct SharedMemory { - UnkInput3 unk_input_3; - TouchScreen touchscreen; - Mouse mouse; - Keyboard keyboard; - std::array unk_input_1; - std::array unk_input_2; - std::array unk_section_8; - std::array controller_serials; - std::array controllers; - std::array unk_section_9; -}; -static_assert(sizeof(SharedMemory) == 0x40000, "HID Shared Memory structure has incorrect size"); - /// Reload input devices. Used when input configuration changed void ReloadInputDevices(); diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp index 8c07a05c21..39c0c1e63f 100644 --- a/src/core/hle/service/nfp/nfp.cpp +++ b/src/core/hle/service/nfp/nfp.cpp @@ -144,7 +144,7 @@ private: } const u64 device_handle{0xDEAD}; - const HID::ControllerID npad_id{HID::Controller_Player1}; + const u32 npad_id{0}; // This is the first player controller id State state{State::NonInitialized}; DeviceState device_state{DeviceState::Initialized}; Kernel::SharedPtr activate_event; From 5857aea94ef52186f64a6794adf418ba92329329 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Sat, 6 Oct 2018 13:14:42 +1000 Subject: [PATCH 02/10] Addressed changes for better hid --- .../hid/controllers/controller_base.cpp | 5 +- .../service/hid/controllers/controller_base.h | 6 +- .../hle/service/hid/controllers/debug_pad.cpp | 13 ++- .../hle/service/hid/controllers/debug_pad.h | 7 +- .../hle/service/hid/controllers/gesture.cpp | 15 ++- .../hle/service/hid/controllers/gesture.h | 7 +- .../hle/service/hid/controllers/keyboard.cpp | 15 ++- .../hle/service/hid/controllers/keyboard.h | 9 +- .../hle/service/hid/controllers/mouse.cpp | 13 ++- src/core/hle/service/hid/controllers/mouse.h | 7 +- src/core/hle/service/hid/controllers/npad.cpp | 101 +++++++++--------- src/core/hle/service/hid/controllers/npad.h | 63 ++++++----- .../hle/service/hid/controllers/stubbed.cpp | 13 ++- .../hle/service/hid/controllers/stubbed.h | 11 +- .../service/hid/controllers/touchscreen.cpp | 17 ++- .../hle/service/hid/controllers/touchscreen.h | 14 ++- src/core/hle/service/hid/controllers/xpad.cpp | 15 ++- src/core/hle/service/hid/controllers/xpad.h | 7 +- src/core/hle/service/hid/hid.cpp | 67 ++++++------ 19 files changed, 238 insertions(+), 167 deletions(-) diff --git a/src/core/hle/service/hid/controllers/controller_base.cpp b/src/core/hle/service/hid/controllers/controller_base.cpp index f2aef56421..1625e9c3d0 100644 --- a/src/core/hle/service/hid/controllers/controller_base.cpp +++ b/src/core/hle/service/hid/controllers/controller_base.cpp @@ -5,6 +5,8 @@ #include "core/hle/service/hid/controllers/controller_base.h" namespace Service::HID { +ControllerBase::~ControllerBase() = default; + void ControllerBase::ActivateController() { if (is_activated) { OnRelease(); @@ -23,5 +25,4 @@ void ControllerBase::DeactivateController() { bool ControllerBase::IsControllerActivated() const { return is_activated; } -// ControllerBase::~ControllerBase() = default; -}; // namespace Service::HID +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h index 3b1c8aad6b..fa98e2354c 100644 --- a/src/core/hle/service/hid/controllers/controller_base.h +++ b/src/core/hle/service/hid/controllers/controller_base.h @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #pragma once + #include "common/common_types.h" #include "common/swap.h" @@ -10,6 +11,7 @@ namespace Service::HID { class ControllerBase { public: ControllerBase() = default; + virtual ~ControllerBase() = 0; // Called when the controller is initialized virtual void OnInit() = 0; @@ -18,7 +20,7 @@ public: virtual void OnRelease() = 0; // When the controller is requesting an update for the shared memory - virtual void OnUpdate(u8* data, size_t size) = 0; + virtual void OnUpdate(u8* data, std::size_t size) = 0; // Called when input devices should be loaded virtual void OnLoadInputDevices() = 0; @@ -40,4 +42,4 @@ protected: }; static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); }; -}; // namespace Service::HID +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp index 04799b233b..6f8ef6e3fb 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.cpp +++ b/src/core/hle/service/hid/controllers/debug_pad.cpp @@ -2,15 +2,21 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include "common/common_types.h" #include "common/swap.h" #include "core/core_timing.h" #include "core/hle/service/hid/controllers/debug_pad.h" namespace Service::HID { + +Controller_DebugPad::Controller_DebugPad() = default; + void Controller_DebugPad::OnInit() {} + void Controller_DebugPad::OnRelease() {} -void Controller_DebugPad::OnUpdate(u8* data, size_t size) { + +void Controller_DebugPad::OnUpdate(u8* data, std::size_t size) { shared_memory.header.timestamp = CoreTiming::GetTicks(); shared_memory.header.total_entry_count = 17; @@ -21,7 +27,7 @@ void Controller_DebugPad::OnUpdate(u8* data, size_t size) { } shared_memory.header.entry_count = 16; - auto& last_entry = shared_memory.pad_states[shared_memory.header.last_entry_index]; + const auto& last_entry = shared_memory.pad_states[shared_memory.header.last_entry_index]; shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; auto& cur_entry = shared_memory.pad_states[shared_memory.header.last_entry_index]; @@ -31,5 +37,6 @@ void Controller_DebugPad::OnUpdate(u8* data, size_t size) { std::memcpy(data, &shared_memory, sizeof(SharedMemory)); } + void Controller_DebugPad::OnLoadInputDevices() {} -}; // namespace Service::HID +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h index fc6f99a0b1..e35675fa16 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.h +++ b/src/core/hle/service/hid/controllers/debug_pad.h @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #pragma once + #include #include "common/common_funcs.h" #include "common/common_types.h" @@ -12,7 +13,7 @@ namespace Service::HID { class Controller_DebugPad final : public ControllerBase { public: - Controller_DebugPad() = default; + Controller_DebugPad(); // Called when the controller is initialized void OnInit() override; @@ -21,7 +22,7 @@ public: void OnRelease() override; // When the controller is requesting an update for the shared memory - void OnUpdate(u8* data, size_t size) override; + void OnUpdate(u8* data, std::size_t size) override; // Called when input devices should be loaded void OnLoadInputDevices() override; @@ -51,4 +52,4 @@ private: static_assert(sizeof(SharedMemory) == 0x400, "SharedMemory is an invalid size"); SharedMemory shared_memory{}; }; -}; // namespace Service::HID +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp index 851ea66f34..b473b9e2b6 100644 --- a/src/core/hle/service/hid/controllers/gesture.cpp +++ b/src/core/hle/service/hid/controllers/gesture.cpp @@ -2,16 +2,22 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include "common/common_types.h" #include "common/swap.h" #include "core/core_timing.h" #include "core/hle/service/hid/controllers/gesture.h" namespace Service::HID { -constexpr size_t SHARED_MEMORY_OFFSET = 0x3BA00; +constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3BA00; + +Controller_Gesture::Controller_Gesture() = default; + void Controller_Gesture::OnInit() {} + void Controller_Gesture::OnRelease() {} -void Controller_Gesture::OnUpdate(u8* data, size_t size) { + +void Controller_Gesture::OnUpdate(u8* data, std::size_t size) { shared_memory.header.timestamp = CoreTiming::GetTicks(); shared_memory.header.total_entry_count = 17; @@ -22,7 +28,7 @@ void Controller_Gesture::OnUpdate(u8* data, size_t size) { } shared_memory.header.entry_count = 16; - auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; + const auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; @@ -32,5 +38,6 @@ void Controller_Gesture::OnUpdate(u8* data, size_t size) { std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); } + void Controller_Gesture::OnLoadInputDevices() {} -}; // namespace Service::HID +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h index f468198296..0ced50dfda 100644 --- a/src/core/hle/service/hid/controllers/gesture.h +++ b/src/core/hle/service/hid/controllers/gesture.h @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #pragma once + #include #include "common/common_types.h" #include "common/swap.h" @@ -11,7 +12,7 @@ namespace Service::HID { class Controller_Gesture final : public ControllerBase { public: - Controller_Gesture() = default; + Controller_Gesture(); // Called when the controller is initialized void OnInit() override; @@ -48,7 +49,7 @@ private: f32 scale; f32 rotation; s32_le location_count; - std::array locations{}; + std::array locations; }; static_assert(sizeof(GestureState) == 0x68, "GestureState is an invalid size"); @@ -58,4 +59,4 @@ private: }; SharedMemory shared_memory{}; }; -}; // namespace Service::HID +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp index 27c39ad08b..089c02ac41 100644 --- a/src/core/hle/service/hid/controllers/keyboard.cpp +++ b/src/core/hle/service/hid/controllers/keyboard.cpp @@ -2,16 +2,22 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include "common/common_types.h" #include "common/swap.h" #include "core/core_timing.h" #include "core/hle/service/hid/controllers/keyboard.h" namespace Service::HID { -constexpr size_t SHARED_MEMORY_OFFSET = 0x3800; +constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800; + +Controller_Keyboard::Controller_Keyboard() = default; + void Controller_Keyboard::OnInit() {} + void Controller_Keyboard::OnRelease() {} -void Controller_Keyboard::OnUpdate(u8* data, size_t size) { + +void Controller_Keyboard::OnUpdate(u8* data, std::size_t size) { shared_memory.header.timestamp = CoreTiming::GetTicks(); shared_memory.header.total_entry_count = 17; @@ -22,7 +28,7 @@ void Controller_Keyboard::OnUpdate(u8* data, size_t size) { } shared_memory.header.entry_count = 16; - auto& last_entry = shared_memory.pad_states[shared_memory.header.last_entry_index]; + const auto& last_entry = shared_memory.pad_states[shared_memory.header.last_entry_index]; shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; auto& cur_entry = shared_memory.pad_states[shared_memory.header.last_entry_index]; @@ -32,5 +38,6 @@ void Controller_Keyboard::OnUpdate(u8* data, size_t size) { std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); } + void Controller_Keyboard::OnLoadInputDevices() {} -}; // namespace Service::HID +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h index 0463e16197..778e14f7e5 100644 --- a/src/core/hle/service/hid/controllers/keyboard.h +++ b/src/core/hle/service/hid/controllers/keyboard.h @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #pragma once + #include #include "common/common_funcs.h" #include "common/common_types.h" @@ -12,7 +13,7 @@ namespace Service::HID { class Controller_Keyboard final : public ControllerBase { public: - Controller_Keyboard() = default; + Controller_Keyboard(); // Called when the controller is initialized void OnInit() override; @@ -21,7 +22,7 @@ public: void OnRelease() override; // When the controller is requesting an update for the shared memory - void OnUpdate(u8* data, size_t size) override; + void OnUpdate(u8* data, std::size_t size) override; // Called when input devices should be loaded void OnLoadInputDevices() override; @@ -33,7 +34,7 @@ private: s32_le modifier; s32_le attribute; - std::array key{}; + std::array key; }; static_assert(sizeof(KeyboardState) == 0x38, "KeyboardState is an invalid size"); @@ -45,4 +46,4 @@ private: static_assert(sizeof(SharedMemory) == 0x400, "SharedMemory is an invalid size"); SharedMemory shared_memory{}; }; -}; // namespace Service::HID +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp index df30239e20..78e9b5e9e5 100644 --- a/src/core/hle/service/hid/controllers/mouse.cpp +++ b/src/core/hle/service/hid/controllers/mouse.cpp @@ -2,16 +2,22 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include "common/common_types.h" #include "common/swap.h" #include "core/core_timing.h" #include "core/hle/service/hid/controllers/mouse.h" namespace Service::HID { -constexpr size_t SHARED_MEMORY_OFFSET = 0x3400; +constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400; + +Controller_Mouse::Controller_Mouse() = default; + void Controller_Mouse::OnInit() {} + void Controller_Mouse::OnRelease() {} -void Controller_Mouse::OnUpdate(u8* data, size_t size) { + +void Controller_Mouse::OnUpdate(u8* data, std::size_t size) { shared_memory.header.timestamp = CoreTiming::GetTicks(); shared_memory.header.total_entry_count = 17; @@ -32,5 +38,6 @@ void Controller_Mouse::OnUpdate(u8* data, size_t size) { std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); } + void Controller_Mouse::OnLoadInputDevices() {} -}; // namespace Service::HID +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h index 0d7fd372d2..05358a4f52 100644 --- a/src/core/hle/service/hid/controllers/mouse.h +++ b/src/core/hle/service/hid/controllers/mouse.h @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #pragma once + #include #include "common/common_types.h" #include "common/swap.h" @@ -11,7 +12,7 @@ namespace Service::HID { class Controller_Mouse final : public ControllerBase { public: - Controller_Mouse() = default; + Controller_Mouse(); // Called when the controller is initialized void OnInit() override; @@ -20,7 +21,7 @@ public: void OnRelease() override; // When the controller is requesting an update for the shared memory - void OnUpdate(u8* data, size_t size) override; + void OnUpdate(u8* data, std::size_t size) override; // Called when input devices should be loaded void OnLoadInputDevices() override; @@ -45,4 +46,4 @@ private: }; SharedMemory shared_memory{}; }; -}; // namespace Service::HID +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index a53687b91e..8a713a4078 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -3,10 +3,14 @@ // Refer to the license.txt file included. #pragma once + +#include #include +#include #include "common/assert.h" #include "common/bit_field.h" #include "common/common_types.h" +#include "common/logging/log.h" #include "common/swap.h" #include "core/core.h" #include "core/core_timing.h" @@ -22,15 +26,13 @@ constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6; constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E; constexpr s32 HID_JOYSTICK_MAX = 0x7fff; constexpr s32 HID_JOYSTICK_MIN = -0x7fff; -constexpr size_t NPAD_OFFSET = 0x9A00; -constexpr size_t MAX_CONTROLLER_COUNT = 9; +constexpr std::size_t NPAD_OFFSET = 0x9A00; -enum class JoystickId : size_t { Joystick_Left, Joystick_Right }; -constexpr std::array NPAD_ID_LIST{0, 1, 2, 3, 4, 5, 6, 7, 32}; -size_t CONTROLLER_COUNT{}; -std::array CONNECTED_CONTROLLERS{}; +enum class JoystickId : std::size_t { Joystick_Left, Joystick_Right }; -void Controller_NPad::InitNewlyAddedControler(size_t controller_idx) { +Controller_NPad::Controller_NPad() = default; + +void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { const auto controller_type = CONNECTED_CONTROLLERS[controller_idx]; auto& controller = shared_memory_entries[controller_idx]; if (controller_type == NPadControllerType::None) { @@ -79,7 +81,7 @@ void Controller_NPad::InitNewlyAddedControler(size_t controller_idx) { controller.right_color.body_color = JOYCON_BODY_NEON_RED; controller.right_color.button_color = JOYCON_BUTTONS_NEON_RED; - controller.properties.is_verticle.Assign(1); // TODO(ogniK): Swap joycons orientations + controller.properties.is_vertical.Assign(1); // TODO(ogniK): Swap joycons orientations } void Controller_NPad::OnInit() { @@ -89,7 +91,7 @@ void Controller_NPad::OnInit() { if (!IsControllerActivated()) return; - size_t controller{}; + std::size_t controller{}; supported_npad_id_types.resize(NPAD_ID_LIST.size()); if (style.raw == 0) { // We want to support all controllers @@ -118,10 +120,10 @@ void Controller_NPad::OnLoadInputDevices() { void Controller_NPad::OnRelease() {} -void Controller_NPad::OnUpdate(u8* data, size_t data_len) { +void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { if (!IsControllerActivated()) return; - for (size_t i = 0; i < shared_memory_entries.size(); i++) { + for (std::size_t i = 0; i < shared_memory_entries.size(); i++) { auto& npad = shared_memory_entries[i]; const std::array controller_npads{&npad.main_controller_states, &npad.handheld_states, @@ -131,11 +133,12 @@ void Controller_NPad::OnUpdate(u8* data, size_t data_len) { &npad.pokeball_states, &npad.libnx}; - for (auto main_controller : controller_npads) { + for (auto* main_controller : controller_npads) { main_controller->common.entry_count = 16; main_controller->common.total_entry_count = 17; - auto& last_entry = main_controller->npad[main_controller->common.last_entry_index]; + const auto& last_entry = + main_controller->npad[main_controller->common.last_entry_index]; main_controller->common.timestamp = CoreTiming::GetTicks(); main_controller->common.last_entry_index = @@ -154,7 +157,7 @@ void Controller_NPad::OnUpdate(u8* data, size_t data_len) { const auto& controller_type = CONNECTED_CONTROLLERS[i]; // Pad states - auto pad_state = ControllerPadState{}; + ControllerPadState pad_state{}; using namespace Settings::NativeButton; pad_state.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus()); pad_state.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus()); @@ -169,20 +172,20 @@ void Controller_NPad::OnUpdate(u8* data, size_t data_len) { pad_state.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus()); pad_state.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.dleft.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.dup.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.dright.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.ddown.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.d_left.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.d_up.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.d_right.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.d_down.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.lstickleft.Assign(buttons[LStick_Left - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.lstickup.Assign(buttons[LStick_Up - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.lstickright.Assign(buttons[LStick_Right - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.lstickdown.Assign(buttons[LStick_Down - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l_stick_left.Assign(buttons[LStick_Left - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l_stick_up.Assign(buttons[LStick_Up - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l_stick_right.Assign(buttons[LStick_Right - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l_stick_down.Assign(buttons[LStick_Down - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.rstickleft.Assign(buttons[RStick_Left - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.rstickup.Assign(buttons[RStick_Up - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.rstickright.Assign(buttons[RStick_Right - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.rstickdown.Assign(buttons[RStick_Down - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r_stick_left.Assign(buttons[RStick_Left - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r_stick_up.Assign(buttons[RStick_Up - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r_stick_right.Assign(buttons[RStick_Right - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r_stick_down.Assign(buttons[RStick_Down - BUTTON_HID_BEGIN]->GetStatus()); pad_state.sl.Assign(buttons[SL - BUTTON_HID_BEGIN]->GetStatus()); pad_state.sr.Assign(buttons[SR - BUTTON_HID_BEGIN]->GetStatus()); @@ -191,9 +194,9 @@ void Controller_NPad::OnUpdate(u8* data, size_t data_len) { AnalogPosition rstick_entry{}; const auto [stick_l_x_f, stick_l_y_f] = - sticks[static_cast(JoystickId::Joystick_Left)]->GetStatus(); + sticks[static_cast(JoystickId::Joystick_Left)]->GetStatus(); const auto [stick_r_x_f, stick_r_y_f] = - sticks[static_cast(JoystickId::Joystick_Right)]->GetStatus(); + sticks[static_cast(JoystickId::Joystick_Right)]->GetStatus(); lstick_entry.x = static_cast(stick_l_x_f * HID_JOYSTICK_MAX); lstick_entry.y = static_cast(stick_l_y_f * HID_JOYSTICK_MAX); rstick_entry.x = static_cast(stick_r_x_f * HID_JOYSTICK_MAX); @@ -220,26 +223,26 @@ void Controller_NPad::OnUpdate(u8* data, size_t data_len) { handheld_entry.connection_status.IsConnected.Assign(1); handheld_entry.connection_status.IsWired.Assign(1); handheld_entry.pad_states.raw = pad_state.raw; - handheld_entry.lstick = lstick_entry; - handheld_entry.rstick = rstick_entry; + handheld_entry.l_stick = lstick_entry; + handheld_entry.r_stick = rstick_entry; break; case NPadControllerType::JoyLeft: left_entry.connection_status.IsConnected.Assign(1); left_entry.pad_states.raw = pad_state.raw; - left_entry.lstick = lstick_entry; - left_entry.rstick = rstick_entry; + left_entry.l_stick = lstick_entry; + left_entry.r_stick = rstick_entry; break; case NPadControllerType::JoyRight: right_entry.connection_status.IsConnected.Assign(1); right_entry.pad_states.raw = pad_state.raw; - right_entry.lstick = lstick_entry; - right_entry.rstick = rstick_entry; + right_entry.l_stick = lstick_entry; + right_entry.r_stick = rstick_entry; break; case NPadControllerType::Tabletop: // TODO(ogniK): Figure out how to add proper tabletop support dual_entry.pad_states.raw = pad_state.raw; - dual_entry.lstick = lstick_entry; - dual_entry.rstick = rstick_entry; + dual_entry.l_stick = lstick_entry; + dual_entry.r_stick = rstick_entry; dual_entry.connection_status.IsConnected.Assign(1); break; case NPadControllerType::Pokeball: @@ -247,13 +250,13 @@ void Controller_NPad::OnUpdate(u8* data, size_t data_len) { pokeball_entry.connection_status.IsWired.Assign(1); pokeball_entry.pad_states.raw = pad_state.raw; - pokeball_entry.lstick = lstick_entry; - pokeball_entry.rstick = rstick_entry; + pokeball_entry.l_stick = lstick_entry; + pokeball_entry.r_stick = rstick_entry; break; case NPadControllerType::ProController: main_controller.pad_states.raw = pad_state.raw; - main_controller.lstick = lstick_entry; - main_controller.rstick = rstick_entry; + main_controller.l_stick = lstick_entry; + main_controller.r_stick = rstick_entry; main_controller.connection_status.IsConnected.Assign(1); main_controller.connection_status.IsWired.Assign(1); break; @@ -264,8 +267,8 @@ void Controller_NPad::OnUpdate(u8* data, size_t data_len) { libnx_entry.connection_status.IsConnected.Assign(1); libnx_entry.connection_status.IsWired.Assign(1); libnx_entry.pad_states.raw = pad_state.raw; - libnx_entry.lstick = lstick_entry; - libnx_entry.rstick = rstick_entry; + libnx_entry.l_stick = lstick_entry; + libnx_entry.r_stick = rstick_entry; } std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(), shared_memory_entries.size() * sizeof(NPadEntry)); @@ -279,18 +282,18 @@ Controller_NPad::NPadType Controller_NPad::GetSupportedStyleSet() const { return style; } -void Controller_NPad::SetSupportedNPadIdTypes(u8* data, size_t length) { +void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) { ASSERT(length > 0 && (length % sizeof(u32)) == 0); - supported_npad_id_types.resize(length / 4); + supported_npad_id_types.resize(length / sizeof(u32)); std::memcpy(supported_npad_id_types.data(), data, length); } -void Controller_NPad::GetSupportedNpadIdTypes(u32* data, size_t max_length) { +const void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { ASSERT(max_length < supported_npad_id_types.size()); std::memcpy(data, supported_npad_id_types.data(), supported_npad_id_types.size()); } -size_t Controller_NPad::GetSupportedNPadIdTypesSize() const { +std::size_t Controller_NPad::GetSupportedNPadIdTypesSize() const { return supported_npad_id_types.size(); } @@ -308,7 +311,7 @@ void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) void Controller_NPad::VibrateController(const std::vector& controller_ids, const std::vector& vibrations) { - for (size_t i = 0; i < controller_ids.size(); i++) { + for (std::size_t i = 0; i < controller_ids.size(); i++) { if (i >= CONTROLLER_COUNT) { continue; } @@ -326,11 +329,11 @@ Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { return last_processed_vibration; } void Controller_NPad::AddNewController(NPadControllerType controller) { - if (CONTROLLER_COUNT >= MAX_CONTROLLER_COUNT) { + if (CONTROLLER_COUNT >= CONNECTED_CONTROLLERS.size()) { LOG_ERROR(Service_HID, "Cannot connect any more controllers!"); return; } CONNECTED_CONTROLLERS[CONTROLLER_COUNT] = controller; InitNewlyAddedControler(CONTROLLER_COUNT++); } -}; // namespace Service::HID +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index e57b67da4b..e5c212aa58 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -3,17 +3,24 @@ // Refer to the license.txt file included. #pragma once + #include #include "common/common_types.h" -#include "core/frontend/input.h" #include "core/hle/service/hid/controllers/controller_base.h" #include "core/settings.h" +namespace Input { +template +class InputDevice; +using ButtonDevice = InputDevice; +using AnalogDevice = InputDevice>; +} // namespace Input + namespace Service::HID { class Controller_NPad final : public ControllerBase { public: - Controller_NPad() = default; + Controller_NPad(); // Called when the controller is initialized void OnInit() override; @@ -22,7 +29,7 @@ public: void OnRelease() override; // When the controller is requesting an update for the shared memory - void OnUpdate(u8* data, size_t size) override; + void OnUpdate(u8* data, std::size_t size) override; // Called when input devices should be loaded void OnLoadInputDevices() override; @@ -67,15 +74,15 @@ public: JoyLeft, JoyRight, Tabletop, - Pokeball + Pokeball, }; void SetSupportedStyleSet(NPadType style_set); NPadType GetSupportedStyleSet() const; - void SetSupportedNPadIdTypes(u8* data, size_t length); - void GetSupportedNpadIdTypes(u32* data, size_t max_length); - size_t GetSupportedNPadIdTypesSize() const; + void SetSupportedNPadIdTypes(u8* data, std::size_t length); + const void GetSupportedNpadIdTypes(u32* data, std::size_t max_length); + std::size_t GetSupportedNPadIdTypesSize() const; void SetHoldType(NpadHoldType joy_hold_type); NpadHoldType GetHoldType() const; @@ -123,22 +130,22 @@ private: BitField<11, 1, u64_le> minus; // D-Pad - BitField<12, 1, u64_le> dleft; - BitField<13, 1, u64_le> dup; - BitField<14, 1, u64_le> dright; - BitField<15, 1, u64_le> ddown; + BitField<12, 1, u64_le> d_left; + BitField<13, 1, u64_le> d_up; + BitField<14, 1, u64_le> d_right; + BitField<15, 1, u64_le> d_down; // Left JoyStick - BitField<16, 1, u64_le> lstickleft; - BitField<17, 1, u64_le> lstickup; - BitField<18, 1, u64_le> lstickright; - BitField<19, 1, u64_le> lstickdown; + BitField<16, 1, u64_le> l_stick_left; + BitField<17, 1, u64_le> l_stick_up; + BitField<18, 1, u64_le> l_stick_right; + BitField<19, 1, u64_le> l_stick_down; // Right JoyStick - BitField<20, 1, u64_le> rstickleft; - BitField<21, 1, u64_le> rstickup; - BitField<22, 1, u64_le> rstickright; - BitField<23, 1, u64_le> rstickdown; + BitField<20, 1, u64_le> r_stick_left; + BitField<21, 1, u64_le> r_stick_up; + BitField<22, 1, u64_le> r_stick_right; + BitField<23, 1, u64_le> r_stick_down; // Not always active? BitField<24, 1, u64_le> sl; @@ -166,8 +173,8 @@ private: s64_le timestamp; s64_le timestamp2; ControllerPadState pad_states; - AnalogPosition lstick; - AnalogPosition rstick; + AnalogPosition l_stick; + AnalogPosition r_stick; ConnectionState connection_status; }; static_assert(sizeof(GenericStates) == 0x30, "NPadGenericStates is an invalid size"); @@ -187,7 +194,7 @@ private: struct NPadProperties { union { s64_le raw{}; - BitField<11, 1, s64_le> is_verticle; + BitField<11, 1, s64_le> is_vertical; BitField<12, 1, s64_le> is_horizontal; }; }; @@ -226,7 +233,7 @@ private: // relying on this for the time being INSERT_PADDING_BYTES( 0x708 * - 6); // TODO(ogniK)L SixAxis states, require more information before implementation + 6); // TODO(ogniK): SixAxis states, require more information before implementation NPadDevice device_type; NPadProperties properties; INSERT_PADDING_WORDS(4); @@ -242,8 +249,12 @@ private: std::vector supported_npad_id_types{}; NpadHoldType hold_type{NpadHoldType::Vertical}; Kernel::SharedPtr styleset_changed_event; - size_t dump_idx{}; + std::size_t dump_idx{}; Vibration last_processed_vibration{}; - void InitNewlyAddedControler(size_t controller_idx); + std::size_t CONTROLLER_COUNT{}; + const std::array NPAD_ID_LIST{0, 1, 2, 3, 4, 5, 6, 7, 32}; + std::array CONNECTED_CONTROLLERS{}; + + void InitNewlyAddedControler(std::size_t controller_idx); }; -}; // namespace Service::HID +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/stubbed.cpp b/src/core/hle/service/hid/controllers/stubbed.cpp index 0a602fce2b..3a13d5991e 100644 --- a/src/core/hle/service/hid/controllers/stubbed.cpp +++ b/src/core/hle/service/hid/controllers/stubbed.cpp @@ -2,15 +2,21 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include "common/common_types.h" #include "common/swap.h" #include "core/core_timing.h" #include "core/hle/service/hid/controllers/stubbed.h" namespace Service::HID { + +Controller_Stubbed::Controller_Stubbed() = default; + void Controller_Stubbed::OnInit() {} + void Controller_Stubbed::OnRelease() {} -void Controller_Stubbed::OnUpdate(u8* data, size_t size) { + +void Controller_Stubbed::OnUpdate(u8* data, std::size_t size) { if (!smart_update) { return; } @@ -23,10 +29,11 @@ void Controller_Stubbed::OnUpdate(u8* data, size_t size) { std::memcpy(data + common_offset, &header, sizeof(CommonHeader)); } + void Controller_Stubbed::OnLoadInputDevices() {} -void Controller_Stubbed::SetCommonHeaderOffset(size_t off) { +void Controller_Stubbed::SetCommonHeaderOffset(std::size_t off) { common_offset = off; smart_update = true; } -}; // namespace Service::HID +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/stubbed.h b/src/core/hle/service/hid/controllers/stubbed.h index ec7adacb35..9c1b57f83e 100644 --- a/src/core/hle/service/hid/controllers/stubbed.h +++ b/src/core/hle/service/hid/controllers/stubbed.h @@ -3,13 +3,14 @@ // Refer to the license.txt file included. #pragma once + #include "common/common_types.h" #include "core/hle/service/hid/controllers/controller_base.h" namespace Service::HID { class Controller_Stubbed final : public ControllerBase { public: - Controller_Stubbed() = default; + Controller_Stubbed(); // Called when the controller is initialized void OnInit() override; @@ -18,15 +19,15 @@ public: void OnRelease() override; // When the controller is requesting an update for the shared memory - void OnUpdate(u8* data, size_t size) override; + void OnUpdate(u8* data, std::size_t size) override; // Called when input devices should be loaded void OnLoadInputDevices() override; - void SetCommonHeaderOffset(size_t off); + void SetCommonHeaderOffset(std::size_t off); private: bool smart_update{}; - size_t common_offset{}; + std::size_t common_offset{}; }; -}; // namespace Service::HID +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp index b675dec8e5..e97f84ea14 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include "common/common_types.h" #include "common/swap.h" #include "core/core_timing.h" @@ -11,10 +12,15 @@ #include "core/settings.h" namespace Service::HID { -constexpr size_t SHARED_MEMORY_OFFSET = 0x400; +constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400; + +Controller_Touchscreen::Controller_Touchscreen() = default; + void Controller_Touchscreen::OnInit() {} + void Controller_Touchscreen::OnRelease() {} -void Controller_Touchscreen::OnUpdate(u8* data, size_t size) { + +void Controller_Touchscreen::OnUpdate(u8* data, std::size_t size) { shared_memory.header.timestamp = CoreTiming::GetTicks(); shared_memory.header.total_entry_count = 17; @@ -25,14 +31,15 @@ void Controller_Touchscreen::OnUpdate(u8* data, size_t size) { } shared_memory.header.entry_count = 16; - auto& last_entry = shared_memory.shared_memory_entries[shared_memory.header.last_entry_index]; + const auto& last_entry = + shared_memory.shared_memory_entries[shared_memory.header.last_entry_index]; shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; auto& cur_entry = shared_memory.shared_memory_entries[shared_memory.header.last_entry_index]; cur_entry.sampling_number = last_entry.sampling_number + 1; cur_entry.sampling_number2 = cur_entry.sampling_number; - auto [x, y, pressed] = touch_device->GetStatus(); + const auto [x, y, pressed] = touch_device->GetStatus(); auto& touch_entry = cur_entry.states[0]; if (pressed) { touch_entry.x = static_cast(x * Layout::ScreenUndocked::Width); @@ -55,4 +62,4 @@ void Controller_Touchscreen::OnUpdate(u8* data, size_t size) { void Controller_Touchscreen::OnLoadInputDevices() { touch_device = Input::CreateDevice(Settings::values.touch_device); } -}; // namespace Service::HID +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index a516128aca..82a3d4a1a1 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h @@ -3,16 +3,22 @@ // Refer to the license.txt file included. #pragma once + #include "common/common_funcs.h" #include "common/common_types.h" #include "common/swap.h" -#include "core/frontend/input.h" #include "core/hle/service/hid/controllers/controller_base.h" +namespace Input { +template +class InputDevice; +using TouchDevice = InputDevice>; +} // namespace Input + namespace Service::HID { class Controller_Touchscreen final : public ControllerBase { public: - Controller_Touchscreen() = default; + Controller_Touchscreen(); // Called when the controller is initialized void OnInit() override; @@ -21,7 +27,7 @@ public: void OnRelease() override; // When the controller is requesting an update for the shared memory - void OnUpdate(u8* data, size_t size) override; + void OnUpdate(u8* data, std::size_t size) override; // Called when input devices should be loaded void OnLoadInputDevices() override; @@ -58,4 +64,4 @@ private: std::unique_ptr touch_device; s64_le last_touch{}; }; -}; // namespace Service::HID +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/xpad.cpp b/src/core/hle/service/hid/controllers/xpad.cpp index 521e925b7c..df0b484519 100644 --- a/src/core/hle/service/hid/controllers/xpad.cpp +++ b/src/core/hle/service/hid/controllers/xpad.cpp @@ -2,16 +2,22 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include "common/common_types.h" #include "common/swap.h" #include "core/core_timing.h" #include "core/hle/service/hid/controllers/xpad.h" namespace Service::HID { -constexpr size_t SHARED_MEMORY_OFFSET = 0x3C00; +constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C00; + +Controller_XPad::Controller_XPad() = default; + void Controller_XPad::OnInit() {} + void Controller_XPad::OnRelease() {} -void Controller_XPad::OnUpdate(u8* data, size_t size) { + +void Controller_XPad::OnUpdate(u8* data, std::size_t size) { for (auto& xpad_entry : shared_memory.shared_memory_entries) { xpad_entry.header.timestamp = CoreTiming::GetTicks(); xpad_entry.header.total_entry_count = 17; @@ -23,7 +29,7 @@ void Controller_XPad::OnUpdate(u8* data, size_t size) { } xpad_entry.header.entry_count = 16; - auto& last_entry = xpad_entry.pad_states[xpad_entry.header.last_entry_index]; + const auto& last_entry = xpad_entry.pad_states[xpad_entry.header.last_entry_index]; xpad_entry.header.last_entry_index = (xpad_entry.header.last_entry_index + 1) % 17; auto& cur_entry = xpad_entry.pad_states[xpad_entry.header.last_entry_index]; @@ -34,5 +40,6 @@ void Controller_XPad::OnUpdate(u8* data, size_t size) { std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); } + void Controller_XPad::OnLoadInputDevices() {} -}; // namespace Service::HID +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h index 898fadfdc9..e2007183d0 100644 --- a/src/core/hle/service/hid/controllers/xpad.h +++ b/src/core/hle/service/hid/controllers/xpad.h @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #pragma once + #include "common/common_funcs.h" #include "common/common_types.h" #include "common/swap.h" @@ -12,7 +13,7 @@ namespace Service::HID { class Controller_XPad final : public ControllerBase { public: - Controller_XPad() = default; + Controller_XPad(); // Called when the controller is initialized void OnInit() override; @@ -21,7 +22,7 @@ public: void OnRelease() override; // When the controller is requesting an update for the shared memory - void OnUpdate(u8* data, size_t size) override; + void OnUpdate(u8* data, std::size_t size) override; // Called when input devices should be loaded void OnLoadInputDevices() override; @@ -56,4 +57,4 @@ private: static_assert(sizeof(SharedMemory) == 0x1000, "SharedMemory is an invalid size"); SharedMemory shared_memory{}; }; -}; // namespace Service::HID +} // namespace Service::HID diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 757b3b7702..ba4aefa6c0 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -38,8 +38,8 @@ namespace Service::HID { constexpr u64 pad_update_ticks = CoreTiming::BASE_CLOCK_RATE / 100; constexpr u64 accelerometer_update_ticks = CoreTiming::BASE_CLOCK_RATE / 100; constexpr u64 gyroscope_update_ticks = CoreTiming::BASE_CLOCK_RATE / 100; -constexpr size_t SHARED_MEMORY_SIZE = 0x40000; -enum class HidController : size_t { +constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; +enum class HidController : std::size_t { DebugPad, Touchscreen, Mouse, @@ -52,7 +52,7 @@ enum class HidController : size_t { NPad, Gesture, - MaxControllers + MaxControllers, }; class IAppletResource final : public ServiceFramework { @@ -68,33 +68,21 @@ public: kernel, nullptr, SHARED_MEMORY_SIZE, Kernel::MemoryPermission::ReadWrite, Kernel::MemoryPermission::Read, 0, Kernel::MemoryRegion::BASE, "HID:SharedMemory"); - controllers[static_cast(HidController::DebugPad)] = - std::make_unique(); - controllers[static_cast(HidController::Touchscreen)] = - std::make_unique(); - controllers[static_cast(HidController::Mouse)] = - std::make_unique(); - controllers[static_cast(HidController::Keyboard)] = - std::make_unique(); - controllers[static_cast(HidController::XPad)] = std::make_unique(); - - controllers[static_cast(HidController::Unknown1)] = - std::make_unique(); - controllers[static_cast(HidController::Unknown2)] = - std::make_unique(); - controllers[static_cast(HidController::Unknown3)] = - std::make_unique(); - - controllers[static_cast(HidController::SixAxisSensor)] = - std::make_unique(); - - controllers[static_cast(HidController::NPad)] = std::make_unique(); - controllers[static_cast(HidController::Gesture)] = - std::make_unique(); + MakeController(HidController::DebugPad); + MakeController(HidController::Touchscreen); + MakeController(HidController::Mouse); + MakeController(HidController::Keyboard); + MakeController(HidController::XPad); + MakeController(HidController::Unknown1); + MakeController(HidController::Unknown2); + MakeController(HidController::Unknown3); + MakeController(HidController::SixAxisSensor); + MakeController(HidController::NPad); + MakeController(HidController::Gesture); // Homebrew doesn't try to activate some controllers, so we activate them by default - controllers[static_cast(HidController::NPad)]->ActivateController(); - controllers[static_cast(HidController::Touchscreen)]->ActivateController(); + GetController(HidController::NPad).ActivateController(); + GetController(HidController::Touchscreen).ActivateController(); GetController(HidController::Unknown1).SetCommonHeaderOffset(0x4c00); GetController(HidController::Unknown2).SetCommonHeaderOffset(0x4e00); @@ -118,6 +106,11 @@ public: controllers[static_cast(controller)]->DeactivateController(); } + template + void MakeController(HidController controller) { + controllers[static_cast(controller)] = std::make_unique(); + } + template T& GetController(HidController controller) { return static_cast(*controllers[static_cast(controller)]); @@ -136,7 +129,7 @@ private: } void UpdateControllers(u64 userdata, int cycles_late) { - bool should_reload = Settings::values.is_device_reload_pending.exchange(false); + const bool should_reload = Settings::values.is_device_reload_pending.exchange(false); for (const auto& controller : controllers) { if (should_reload) { controller->OnLoadInputDevices(); @@ -386,7 +379,6 @@ private: } void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { - std::string blah = ctx.Description(); auto& controller = applet_resource->GetController(HidController::NPad); IPC::ResponseBuilder rb{ctx, 3}; @@ -434,7 +426,7 @@ private: void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { auto& controller = applet_resource->GetController(HidController::NPad); IPC::RequestParser rp{ctx}; - auto hold_type = rp.PopRaw(); + const auto hold_type = rp.PopRaw(); controller.SetHoldType(Controller_NPad::NpadHoldType{hold_type}); IPC::ResponseBuilder rb{ctx, 2}; @@ -443,7 +435,8 @@ private: } void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { - auto& controller = applet_resource->GetController(HidController::NPad); + const auto& controller = + applet_resource->GetController(HidController::NPad); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); rb.Push(static_cast(controller.GetHoldType())); @@ -458,8 +451,8 @@ private: void SendVibrationValue(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - auto controller_id = rp.PopRaw(); - auto vibration_values = rp.PopRaw(); + const auto controller_id = rp.PopRaw(); + const auto vibration_values = rp.PopRaw(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -470,8 +463,8 @@ private: } void SendVibrationValues(Kernel::HLERequestContext& ctx) { - auto controllers = ctx.ReadBuffer(0); - auto vibrations = ctx.ReadBuffer(1); + const auto controllers = ctx.ReadBuffer(0); + const auto vibrations = ctx.ReadBuffer(1); std::vector controller_list(controllers.size() / sizeof(u32)); std::vector vibration_list(vibrations.size() / @@ -501,7 +494,7 @@ private: void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - auto npad_id = rp.PopRaw(); + const auto npad_id = rp.PopRaw(); auto& controller = applet_resource->GetController(HidController::NPad); controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Dual); From b79c294c0290886266e8c9059314903c38978db6 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Sat, 6 Oct 2018 13:27:06 +1000 Subject: [PATCH 03/10] Removed unneeded forward declarations --- src/core/hle/service/hid/controllers/npad.h | 8 +------- src/core/hle/service/hid/controllers/touchscreen.h | 7 +------ 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index e5c212aa58..2d1614747b 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -6,16 +6,10 @@ #include #include "common/common_types.h" +#include "core/frontend/input.h" #include "core/hle/service/hid/controllers/controller_base.h" #include "core/settings.h" -namespace Input { -template -class InputDevice; -using ButtonDevice = InputDevice; -using AnalogDevice = InputDevice>; -} // namespace Input - namespace Service::HID { class Controller_NPad final : public ControllerBase { diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index 82a3d4a1a1..1d97b6c2ae 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h @@ -7,14 +7,9 @@ #include "common/common_funcs.h" #include "common/common_types.h" #include "common/swap.h" +#include "core/frontend/input.h" #include "core/hle/service/hid/controllers/controller_base.h" -namespace Input { -template -class InputDevice; -using TouchDevice = InputDevice>; -} // namespace Input - namespace Service::HID { class Controller_Touchscreen final : public ControllerBase { public: From f43815af5d59bb1b31696f317c2e2ce243445cb5 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Sun, 7 Oct 2018 20:17:04 +1100 Subject: [PATCH 04/10] Added the ability to "disconnect" individual npads Fixes arms --- src/core/hle/service/hid/controllers/npad.cpp | 36 ++++++++++++------- src/core/hle/service/hid/controllers/npad.h | 15 ++++++-- src/core/hle/service/hid/hid.cpp | 5 ++- 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 8a713a4078..211b8bb60a 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -33,7 +33,7 @@ enum class JoystickId : std::size_t { Joystick_Left, Joystick_Right }; Controller_NPad::Controller_NPad() = default; void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { - const auto controller_type = CONNECTED_CONTROLLERS[controller_idx]; + const auto controller_type = connected_controllers[controller_idx].type; auto& controller = shared_memory_entries[controller_idx]; if (controller_type == NPadControllerType::None) { return; @@ -92,7 +92,7 @@ void Controller_NPad::OnInit() { if (!IsControllerActivated()) return; std::size_t controller{}; - supported_npad_id_types.resize(NPAD_ID_LIST.size()); + supported_npad_id_types.resize(npad_id_list.size()); if (style.raw == 0) { // We want to support all controllers style.handheld.Assign(1); @@ -102,9 +102,9 @@ void Controller_NPad::OnInit() { style.pro_controller.Assign(1); style.pokeball.Assign(1); } - std::memcpy(supported_npad_id_types.data(), NPAD_ID_LIST.data(), - NPAD_ID_LIST.size() * sizeof(u32)); - if (CONTROLLER_COUNT == 0) { + std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), + npad_id_list.size() * sizeof(u32)); + if (controller_count == 0) { AddNewController(NPadControllerType::Handheld); } } @@ -150,12 +150,12 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { cur_entry.timestamp2 = cur_entry.timestamp; } - if (CONNECTED_CONTROLLERS[i] == NPadControllerType::None) { + const auto& controller_type = connected_controllers[i].type; + + if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) { continue; } - const auto& controller_type = CONNECTED_CONTROLLERS[i]; - // Pad states ControllerPadState pad_state{}; using namespace Settings::NativeButton; @@ -312,7 +312,7 @@ void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) void Controller_NPad::VibrateController(const std::vector& controller_ids, const std::vector& vibrations) { for (std::size_t i = 0; i < controller_ids.size(); i++) { - if (i >= CONTROLLER_COUNT) { + if (i >= controller_count) { continue; } // TODO(ogniK): Vibrate the physical controller @@ -329,11 +329,23 @@ Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { return last_processed_vibration; } void Controller_NPad::AddNewController(NPadControllerType controller) { - if (CONTROLLER_COUNT >= CONNECTED_CONTROLLERS.size()) { + if (controller_count >= connected_controllers.size()) { LOG_ERROR(Service_HID, "Cannot connect any more controllers!"); return; } - CONNECTED_CONTROLLERS[CONTROLLER_COUNT] = controller; - InitNewlyAddedControler(CONTROLLER_COUNT++); + connected_controllers[controller_count] = {controller, true}; + InitNewlyAddedControler(controller_count++); +} + +void Controller_NPad::ConnectNPad(u32 npad_id) { + if (npad_id >= connected_controllers.size()) + return; + connected_controllers[npad_id].is_connected = true; +} + +void Controller_NPad::DisconnectNPad(u32 npad_id) { + if (npad_id >= connected_controllers.size()) + return; + connected_controllers[npad_id].is_connected = false; } } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 2d1614747b..86ab0e4290 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -91,6 +91,9 @@ public: void AddNewController(NPadControllerType controller); + void ConnectNPad(u32 npad_id); + void DisconnectNPad(u32 npad_id); + private: struct CommonHeader { s64_le timestamp; @@ -235,6 +238,12 @@ private: INSERT_PADDING_BYTES(0xdf8); }; static_assert(sizeof(NPadEntry) == 0x5000, "NPadEntry is an invalid size"); + + struct ControllerHolder { + Controller_NPad::NPadControllerType type; + bool is_connected; + }; + NPadType style{}; std::array shared_memory_entries{}; std::array, Settings::NativeButton::NUM_BUTTONS_HID> @@ -245,9 +254,9 @@ private: Kernel::SharedPtr styleset_changed_event; std::size_t dump_idx{}; Vibration last_processed_vibration{}; - std::size_t CONTROLLER_COUNT{}; - const std::array NPAD_ID_LIST{0, 1, 2, 3, 4, 5, 6, 7, 32}; - std::array CONNECTED_CONTROLLERS{}; + std::size_t controller_count{}; + static constexpr std::array npad_id_list{0, 1, 2, 3, 4, 5, 6, 7, 32}; + std::array connected_controllers{}; void InitNewlyAddedControler(std::size_t controller_idx); }; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index ba4aefa6c0..dfee289d2e 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -411,7 +411,10 @@ private: } void DisconnectNpad(Kernel::HLERequestContext& ctx) { - applet_resource->DeactivateController(HidController::NPad); + IPC::RequestParser rp{ctx}; + auto npad_id = rp.PopRaw(); + applet_resource->GetController(HidController::NPad) + .DisconnectNPad(npad_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); LOG_DEBUG(Service_HID, "called"); From 46cdeb4549dbd549f9700967c25c089594f3b4ff Mon Sep 17 00:00:00 2001 From: David Marcec Date: Wed, 10 Oct 2018 14:21:56 +1100 Subject: [PATCH 05/10] Kirby expects handheld controllers to be at position 8 --- src/core/hle/service/hid/controllers/npad.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 211b8bb60a..282953bab2 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -104,7 +104,8 @@ void Controller_NPad::OnInit() { } std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), npad_id_list.size() * sizeof(u32)); - if (controller_count == 0) { + if (std::none_of(connected_controllers.begin(), connected_controllers.end(), + [](const ControllerHolder& controller) { return controller.is_connected; })) { AddNewController(NPadControllerType::Handheld); } } @@ -272,7 +273,7 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { } std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(), shared_memory_entries.size() * sizeof(NPadEntry)); -} +} // namespace Service::HID void Controller_NPad::SetSupportedStyleSet(NPadType style_set) { style.raw = style_set.raw; @@ -333,6 +334,11 @@ void Controller_NPad::AddNewController(NPadControllerType controller) { LOG_ERROR(Service_HID, "Cannot connect any more controllers!"); return; } + if (controller == NPadControllerType::Handheld) { + connected_controllers[8] = {controller, true}; + InitNewlyAddedControler(8); + return; + } connected_controllers[controller_count] = {controller, true}; InitNewlyAddedControler(controller_count++); } From 3d75c9cd7a75f7ef97e2e14fc2eb15e4bba92934 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Wed, 10 Oct 2018 21:38:43 +1100 Subject: [PATCH 06/10] Added GetLedPattern and HandheldVariant HandheldVariant is for specific games which expect handheld controllers to be at position 8(kirby), however this doesn't fix all games as some games require handhelds to be at position 0(snipperclips) --- src/core/hle/service/hid/controllers/npad.cpp | 36 +++++++++++++++++-- src/core/hle/service/hid/controllers/npad.h | 22 ++++++++++-- src/core/hle/service/hid/hid.cpp | 11 ++++-- 3 files changed, 63 insertions(+), 6 deletions(-) diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 282953bab2..069e0d5dec 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -41,6 +41,7 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { controller.joy_styles.raw = 0; // Zero out controller.device_type.raw = 0; switch (controller_type) { + case NPadControllerType::HandheldVariant: case NPadControllerType::Handheld: controller.joy_styles.handheld.Assign(1); controller.device_type.handheld.Assign(1); @@ -220,9 +221,12 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { } switch (controller_type) { + case NPadControllerType::HandheldVariant: case NPadControllerType::Handheld: handheld_entry.connection_status.IsConnected.Assign(1); - handheld_entry.connection_status.IsWired.Assign(1); + if (!Settings::values.use_docked_mode) { + handheld_entry.connection_status.IsWired.Assign(1); + } handheld_entry.pad_states.raw = pad_state.raw; handheld_entry.l_stick = lstick_entry; handheld_entry.r_stick = rstick_entry; @@ -334,7 +338,7 @@ void Controller_NPad::AddNewController(NPadControllerType controller) { LOG_ERROR(Service_HID, "Cannot connect any more controllers!"); return; } - if (controller == NPadControllerType::Handheld) { + if (controller == NPadControllerType::HandheldVariant) { connected_controllers[8] = {controller, true}; InitNewlyAddedControler(8); return; @@ -354,4 +358,32 @@ void Controller_NPad::DisconnectNPad(u32 npad_id) { return; connected_controllers[npad_id].is_connected = false; } + +Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { + if (npad_id == npad_id_list.back() || npad_id == npad_id_list[npad_id_list.size() - 2]) { + // These are controllers without led patterns + return LedPattern{0, 0, 0, 0}; + } + switch (npad_id) { + case 0: + return LedPattern{1, 0, 0, 0}; + case 1: + return LedPattern{0, 1, 0, 0}; + case 2: + return LedPattern{0, 0, 1, 0}; + case 3: + return LedPattern{0, 0, 0, 1}; + case 4: + return LedPattern{1, 0, 0, 1}; + case 5: + return LedPattern{1, 0, 1, 0}; + case 6: + return LedPattern{1, 0, 1, 1}; + case 7: + return LedPattern{0, 1, 1, 0}; + default: + UNIMPLEMENTED_MSG("Unhandled npad_id {}", npad_id); + return LedPattern{0, 0, 0, 0}; + }; +} } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 86ab0e4290..28c89768c1 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -65,12 +65,29 @@ public: None, ProController, Handheld, + HandheldVariant, // Games which require the handheld controller to be at index 8 JoyLeft, JoyRight, Tabletop, Pokeball, }; + struct LedPattern { + explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) { + position1.Assign(light1); + position1.Assign(light2); + position1.Assign(light3); + position1.Assign(light4); + }; + union { + u64 raw{}; + BitField<0, 1, u64> position1; + BitField<1, 1, u64> position2; + BitField<2, 1, u64> position3; + BitField<3, 1, u64> position4; + }; + }; + void SetSupportedStyleSet(NPadType style_set); NPadType GetSupportedStyleSet() const; @@ -93,6 +110,7 @@ public: void ConnectNPad(u32 npad_id); void DisconnectNPad(u32 npad_id); + LedPattern GetLedPattern(u32 npad_id); private: struct CommonHeader { @@ -255,8 +273,8 @@ private: std::size_t dump_idx{}; Vibration last_processed_vibration{}; std::size_t controller_count{}; - static constexpr std::array npad_id_list{0, 1, 2, 3, 4, 5, 6, 7, 32}; - std::array connected_controllers{}; + static constexpr std::array npad_id_list{0, 1, 2, 3, 4, 5, 6, 7, 32, 16}; + std::array connected_controllers{}; void InitNewlyAddedControler(std::size_t controller_idx); }; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index dfee289d2e..4c0d96cc20 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -421,9 +421,14 @@ private: } void GetPlayerLedPattern(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2}; + IPC::RequestParser rp{ctx}; + auto npad_id = rp.PopRaw(); + IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + rb.PushRaw(applet_resource->GetController(HidController::NPad) + .GetLedPattern(npad_id) + .raw); + LOG_DEBUG(Service_HID, "called"); } void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { @@ -513,6 +518,8 @@ private: } void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + auto mode = rp.PopRaw(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); LOG_WARNING(Service_HID, "(STUBBED) called"); From 9e924f2ef2add0f351df6addc01c356b52c8d7be Mon Sep 17 00:00:00 2001 From: David Marcec Date: Thu, 11 Oct 2018 00:58:47 +1100 Subject: [PATCH 07/10] Added BeginPermitVibrationSession and EndPermitVibrationSession Used by Mario Party --- src/core/hle/service/hid/controllers/npad.cpp | 6 ++++++ src/core/hle/service/hid/controllers/npad.h | 2 ++ src/core/hle/service/hid/hid.cpp | 20 +++++++++++++++++-- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 069e0d5dec..27b38ababf 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -316,6 +316,9 @@ void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) void Controller_NPad::VibrateController(const std::vector& controller_ids, const std::vector& vibrations) { + if (!can_controllers_vibrate) { + return; + } for (std::size_t i = 0; i < controller_ids.size(); i++) { if (i >= controller_count) { continue; @@ -386,4 +389,7 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { return LedPattern{0, 0, 0, 0}; }; } +void Controller_NPad::SetVibrationEnabled(bool can_vibrate) { + can_controllers_vibrate = can_vibrate; +} } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 28c89768c1..b1aa988205 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -111,6 +111,7 @@ public: void ConnectNPad(u32 npad_id); void DisconnectNPad(u32 npad_id); LedPattern GetLedPattern(u32 npad_id); + void SetVibrationEnabled(bool can_vibrate); private: struct CommonHeader { @@ -275,6 +276,7 @@ private: std::size_t controller_count{}; static constexpr std::array npad_id_list{0, 1, 2, 3, 4, 5, 6, 7, 32, 16}; std::array connected_controllers{}; + bool can_controllers_vibrate{true}; void InitNewlyAddedControler(std::size_t controller_idx); }; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 4c0d96cc20..65ee1d9bbc 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -240,8 +240,8 @@ public: {206, &Hid::SendVibrationValues, "SendVibrationValues"}, {207, nullptr, "SendVibrationGcErmCommand"}, {208, nullptr, "GetActualVibrationGcErmCommand"}, - {209, nullptr, "BeginPermitVibrationSession"}, - {210, nullptr, "EndPermitVibrationSession"}, + {209, &Hid::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, + {210, &Hid::EndPermitVibrationSession, "EndPermitVibrationSession"}, {300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"}, {301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"}, {302, nullptr, "StopConsoleSixAxisSensor"}, @@ -457,6 +457,22 @@ private: LOG_WARNING(Service_HID, "(STUBBED) called"); } + void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) { + applet_resource->GetController(HidController::NPad) + .SetVibrationEnabled(true); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_DEBUG(Service_HID, "called"); + } + + void EndPermitVibrationSession(Kernel::HLERequestContext& ctx) { + applet_resource->GetController(HidController::NPad) + .SetVibrationEnabled(false); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_DEBUG(Service_HID, "called"); + } + void SendVibrationValue(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto controller_id = rp.PopRaw(); From 85b0d9a7be05eeec2fc230003341f9b444a17bf5 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Fri, 12 Oct 2018 02:56:49 +1100 Subject: [PATCH 08/10] Dynamically decide handheld variant based on supported npad id priority Kirby input still doesn't work, should fix a lot of other games --- src/core/hle/service/hid/controllers/npad.cpp | 71 ++++++++++++++----- src/core/hle/service/hid/controllers/npad.h | 6 +- src/core/hle/service/hid/hid.cpp | 4 ++ 3 files changed, 62 insertions(+), 19 deletions(-) diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 27b38ababf..dbb0dd72d8 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -41,7 +41,6 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { controller.joy_styles.raw = 0; // Zero out controller.device_type.raw = 0; switch (controller_type) { - case NPadControllerType::HandheldVariant: case NPadControllerType::Handheld: controller.joy_styles.handheld.Assign(1); controller.device_type.handheld.Assign(1); @@ -93,7 +92,6 @@ void Controller_NPad::OnInit() { if (!IsControllerActivated()) return; std::size_t controller{}; - supported_npad_id_types.resize(npad_id_list.size()); if (style.raw == 0) { // We want to support all controllers style.handheld.Assign(1); @@ -103,10 +101,11 @@ void Controller_NPad::OnInit() { style.pro_controller.Assign(1); style.pokeball.Assign(1); } - std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), - npad_id_list.size() * sizeof(u32)); if (std::none_of(connected_controllers.begin(), connected_controllers.end(), [](const ControllerHolder& controller) { return controller.is_connected; })) { + supported_npad_id_types.resize(npad_id_list.size()); + std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), + npad_id_list.size() * sizeof(u32)); AddNewController(NPadControllerType::Handheld); } } @@ -221,7 +220,6 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { } switch (controller_type) { - case NPadControllerType::HandheldVariant: case NPadControllerType::Handheld: handheld_entry.connection_status.IsConnected.Assign(1); if (!Settings::values.use_docked_mode) { @@ -291,6 +289,29 @@ void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) { ASSERT(length > 0 && (length % sizeof(u32)) == 0); supported_npad_id_types.resize(length / sizeof(u32)); std::memcpy(supported_npad_id_types.data(), data, length); + CheckForHandheldVariant(); +} + +void Controller_NPad::CheckForHandheldVariant() { + // As some games expect us to use the variant of handheld mode and some games don't. It's + // consistent that games set the npad ids in order of priority. We can just swap the controller + // ids on the fly then if we're in handheld mode + if (supported_npad_id_types.size() > 0) { + const auto& first_controller = supported_npad_id_types.front(); + if (first_controller == 32 && !connected_controllers[8].is_connected) { + const auto& first_controller = connected_controllers.front(); + if (first_controller.is_connected && + first_controller.type == NPadControllerType::Handheld) { + DisconnectNPad(0); + AddNewController(NPadControllerType::Handheld, true); + } + } else if (first_controller != 32 && connected_controllers[8].is_connected) { + if (!connected_controllers[0].is_connected) { + DisconnectNPad(8); + AddNewController(NPadControllerType::Handheld); + } + } + } } const void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { @@ -320,10 +341,15 @@ void Controller_NPad::VibrateController(const std::vector& controller_ids, return; } for (std::size_t i = 0; i < controller_ids.size(); i++) { - if (i >= controller_count) { - continue; + std::size_t controller_pos = i; + if (controller_pos == 32) + controller_pos = 8; + if (controller_pos == 16) + controller_pos = 9; + + if (connected_controllers[controller_pos].is_connected) { + // TODO(ogniK): Vibrate the physical controller } - // TODO(ogniK): Vibrate the physical controller } LOG_WARNING(Service_HID, "(STUBBED) called"); last_processed_vibration = vibrations.back(); @@ -336,18 +362,22 @@ Kernel::SharedPtr Controller_NPad::GetStyleSetChangedEvent() cons Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { return last_processed_vibration; } -void Controller_NPad::AddNewController(NPadControllerType controller) { - if (controller_count >= connected_controllers.size()) { - LOG_ERROR(Service_HID, "Cannot connect any more controllers!"); - return; - } - if (controller == NPadControllerType::HandheldVariant) { +void Controller_NPad::AddNewController(NPadControllerType controller, bool is_handheld_variant) { + if (is_handheld_variant) { connected_controllers[8] = {controller, true}; InitNewlyAddedControler(8); return; } - connected_controllers[controller_count] = {controller, true}; - InitNewlyAddedControler(controller_count++); + const auto pos = + std::find_if(connected_controllers.begin(), connected_controllers.end() - 2, + [](const ControllerHolder& holder) { return !holder.is_connected; }); + if (pos == connected_controllers.end() - 2) { + LOG_ERROR(Service_HID, "Cannot connect any more controllers!"); + return; + } + const auto controller_id = std::distance(connected_controllers.begin(), pos); + connected_controllers[controller_id] = {controller, true}; + InitNewlyAddedControler(controller_id); } void Controller_NPad::ConnectNPad(u32 npad_id) { @@ -392,4 +422,13 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { void Controller_NPad::SetVibrationEnabled(bool can_vibrate) { can_controllers_vibrate = can_vibrate; } + +void Controller_NPad::SetHandheldActiviationMode(u32 mode) { + const auto& first_controller = connected_controllers.front(); + if (!first_controller.is_connected || connected_controllers[8].is_connected) { + return; + } + DisconnectNPad(0); + AddNewController(NPadControllerType::Handheld, true); +} } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index b1aa988205..bc3d15ce6c 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -65,7 +65,6 @@ public: None, ProController, Handheld, - HandheldVariant, // Games which require the handheld controller to be at index 8 JoyLeft, JoyRight, Tabletop, @@ -106,12 +105,13 @@ public: Kernel::SharedPtr GetStyleSetChangedEvent() const; Vibration GetLastVibration() const; - void AddNewController(NPadControllerType controller); + void AddNewController(NPadControllerType controller, bool is_handheld_variant = false); void ConnectNPad(u32 npad_id); void DisconnectNPad(u32 npad_id); LedPattern GetLedPattern(u32 npad_id); void SetVibrationEnabled(bool can_vibrate); + void SetHandheldActiviationMode(u32 mode); private: struct CommonHeader { @@ -273,10 +273,10 @@ private: Kernel::SharedPtr styleset_changed_event; std::size_t dump_idx{}; Vibration last_processed_vibration{}; - std::size_t controller_count{}; static constexpr std::array npad_id_list{0, 1, 2, 3, 4, 5, 6, 7, 32, 16}; std::array connected_controllers{}; bool can_controllers_vibrate{true}; + void CheckForHandheldVariant(); void InitNewlyAddedControler(std::size_t controller_idx); }; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 65ee1d9bbc..e5cbd2ef6f 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -347,6 +347,8 @@ private: } void StartSixAxisSensor(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + auto handle = rp.PopRaw(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); LOG_WARNING(Service_HID, "(STUBBED) called"); @@ -539,6 +541,8 @@ private: IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); LOG_WARNING(Service_HID, "(STUBBED) called"); + applet_resource->GetController(HidController::NPad) + .SetHandheldActiviationMode(mode); } void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { From 98b760c645088ef690c7fe5941bdebeed34a3012 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Fri, 12 Oct 2018 16:28:00 +1100 Subject: [PATCH 09/10] Wip --- src/core/hle/service/hid/controllers/npad.cpp | 20 +++++++++++++++++-- src/core/hle/service/hid/hid.cpp | 6 +++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index dbb0dd72d8..9aa8d6f924 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -287,15 +287,31 @@ Controller_NPad::NPadType Controller_NPad::GetSupportedStyleSet() const { void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) { ASSERT(length > 0 && (length % sizeof(u32)) == 0); + supported_npad_id_types.clear(); supported_npad_id_types.resize(length / sizeof(u32)); std::memcpy(supported_npad_id_types.data(), data, length); CheckForHandheldVariant(); } - +#pragma optimize("", off) void Controller_NPad::CheckForHandheldVariant() { // As some games expect us to use the variant of handheld mode and some games don't. It's // consistent that games set the npad ids in order of priority. We can just swap the controller // ids on the fly then if we're in handheld mode + if (std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), 32) != + supported_npad_id_types.end()) { + const auto& first_controller = connected_controllers.front(); + if (first_controller.is_connected && + first_controller.type == NPadControllerType::Handheld) { + DisconnectNPad(0); + AddNewController(NPadControllerType::Handheld, true); + } + } else { + if (connected_controllers[8].is_connected) { + DisconnectNPad(8); + AddNewController(NPadControllerType::Handheld); + } + } + /* if (supported_npad_id_types.size() > 0) { const auto& first_controller = supported_npad_id_types.front(); if (first_controller == 32 && !connected_controllers[8].is_connected) { @@ -311,7 +327,7 @@ void Controller_NPad::CheckForHandheldVariant() { AddNewController(NPadControllerType::Handheld); } } - } + }*/ } const void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index e5cbd2ef6f..db1537b405 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -284,7 +284,7 @@ public: private: std::shared_ptr applet_resource; - +#pragma optimize("", off) void CreateAppletResource(Kernel::HLERequestContext& ctx) { if (applet_resource == nullptr) { applet_resource = std::make_shared(); @@ -405,6 +405,8 @@ private: } void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + auto npad_id = rp.PopRaw(); IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(RESULT_SUCCESS); rb.PushCopyObjects(applet_resource->GetController(HidController::NPad) @@ -454,6 +456,8 @@ private: } void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + auto npad_id = rp.PopRaw(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); LOG_WARNING(Service_HID, "(STUBBED) called"); From 8144fa42bdeb96524f506f935109df128f961847 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Thu, 18 Oct 2018 00:11:47 +1100 Subject: [PATCH 10/10] Using dual joycons as the default controller Reason for the change is to allow both docked and undocked mode to work --- src/core/hle/service/hid/controllers/npad.cpp | 115 +++++++----------- src/core/hle/service/hid/controllers/npad.h | 17 ++- src/core/hle/service/hid/hid.cpp | 4 +- 3 files changed, 59 insertions(+), 77 deletions(-) diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 9aa8d6f924..d17e64b2ad 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -27,7 +27,7 @@ constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E; constexpr s32 HID_JOYSTICK_MAX = 0x7fff; constexpr s32 HID_JOYSTICK_MIN = -0x7fff; constexpr std::size_t NPAD_OFFSET = 0x9A00; - +constexpr u32 BATTERY_FULL = 2; enum class JoystickId : std::size_t { Joystick_Left, Joystick_Right }; Controller_NPad::Controller_NPad() = default; @@ -46,6 +46,12 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { controller.device_type.handheld.Assign(1); controller.pad_assignment = NPadAssignments::Dual; break; + case NPadControllerType::JoyDual: + controller.joy_styles.joycon_dual.Assign(1); + controller.device_type.joycon_left.Assign(1); + controller.device_type.joycon_right.Assign(1); + controller.pad_assignment = NPadAssignments::Dual; + break; case NPadControllerType::JoyLeft: controller.joy_styles.joycon_left.Assign(1); controller.device_type.joycon_left.Assign(1); @@ -56,9 +62,6 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { controller.device_type.joycon_right.Assign(1); controller.pad_assignment = NPadAssignments::Dual; break; - case NPadControllerType::Tabletop: - UNIMPLEMENTED_MSG("Tabletop is not implemented"); - break; case NPadControllerType::Pokeball: controller.joy_styles.pokeball.Assign(1); controller.device_type.pokeball.Assign(1); @@ -82,6 +85,11 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { controller.right_color.button_color = JOYCON_BUTTONS_NEON_RED; controller.properties.is_vertical.Assign(1); // TODO(ogniK): Swap joycons orientations + controller.properties.use_plus.Assign(1); + controller.properties.use_minus.Assign(1); + controller.battery_level[0] = BATTERY_FULL; + controller.battery_level[1] = BATTERY_FULL; + controller.battery_level[2] = BATTERY_FULL; } void Controller_NPad::OnInit() { @@ -106,7 +114,7 @@ void Controller_NPad::OnInit() { supported_npad_id_types.resize(npad_id_list.size()); std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), npad_id_list.size() * sizeof(u32)); - AddNewController(NPadControllerType::Handheld); + AddNewController(NPadControllerType::JoyDual); } } @@ -218,9 +226,11 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { if (hold_type == NpadHoldType::Horizontal) { // TODO(ogniK): Remap buttons for different orientations } + libnx_entry.connection_status.raw = 0; switch (controller_type) { case NPadControllerType::Handheld: + handheld_entry.connection_status.raw = 0; handheld_entry.connection_status.IsConnected.Assign(1); if (!Settings::values.use_docked_mode) { handheld_entry.connection_status.IsWired.Assign(1); @@ -229,26 +239,39 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { handheld_entry.l_stick = lstick_entry; handheld_entry.r_stick = rstick_entry; break; + case NPadControllerType::JoyDual: + dual_entry.connection_status.raw = 0; + + dual_entry.connection_status.IsLeftJoyConnected.Assign(1); + dual_entry.connection_status.IsRightJoyConnected.Assign(1); + dual_entry.connection_status.IsConnected.Assign(1); + + libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); + libnx_entry.connection_status.IsRightJoyConnected.Assign(1); + libnx_entry.connection_status.IsConnected.Assign(1); + + dual_entry.pad_states.raw = pad_state.raw; + dual_entry.l_stick = lstick_entry; + dual_entry.r_stick = rstick_entry; case NPadControllerType::JoyLeft: + left_entry.connection_status.raw = 0; + left_entry.connection_status.IsConnected.Assign(1); left_entry.pad_states.raw = pad_state.raw; left_entry.l_stick = lstick_entry; left_entry.r_stick = rstick_entry; break; case NPadControllerType::JoyRight: + right_entry.connection_status.raw = 0; + right_entry.connection_status.IsConnected.Assign(1); right_entry.pad_states.raw = pad_state.raw; right_entry.l_stick = lstick_entry; right_entry.r_stick = rstick_entry; break; - case NPadControllerType::Tabletop: - // TODO(ogniK): Figure out how to add proper tabletop support - dual_entry.pad_states.raw = pad_state.raw; - dual_entry.l_stick = lstick_entry; - dual_entry.r_stick = rstick_entry; - dual_entry.connection_status.IsConnected.Assign(1); - break; case NPadControllerType::Pokeball: + pokeball_entry.connection_status.raw = 0; + pokeball_entry.connection_status.IsConnected.Assign(1); pokeball_entry.connection_status.IsWired.Assign(1); @@ -257,18 +280,18 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { pokeball_entry.r_stick = rstick_entry; break; case NPadControllerType::ProController: + main_controller.connection_status.raw = 0; + + main_controller.connection_status.IsConnected.Assign(1); + main_controller.connection_status.IsWired.Assign(1); main_controller.pad_states.raw = pad_state.raw; main_controller.l_stick = lstick_entry; main_controller.r_stick = rstick_entry; - main_controller.connection_status.IsConnected.Assign(1); - main_controller.connection_status.IsWired.Assign(1); break; } // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate // any controllers. - libnx_entry.connection_status.IsConnected.Assign(1); - libnx_entry.connection_status.IsWired.Assign(1); libnx_entry.pad_states.raw = pad_state.raw; libnx_entry.l_stick = lstick_entry; libnx_entry.r_stick = rstick_entry; @@ -290,44 +313,6 @@ void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) { supported_npad_id_types.clear(); supported_npad_id_types.resize(length / sizeof(u32)); std::memcpy(supported_npad_id_types.data(), data, length); - CheckForHandheldVariant(); -} -#pragma optimize("", off) -void Controller_NPad::CheckForHandheldVariant() { - // As some games expect us to use the variant of handheld mode and some games don't. It's - // consistent that games set the npad ids in order of priority. We can just swap the controller - // ids on the fly then if we're in handheld mode - if (std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), 32) != - supported_npad_id_types.end()) { - const auto& first_controller = connected_controllers.front(); - if (first_controller.is_connected && - first_controller.type == NPadControllerType::Handheld) { - DisconnectNPad(0); - AddNewController(NPadControllerType::Handheld, true); - } - } else { - if (connected_controllers[8].is_connected) { - DisconnectNPad(8); - AddNewController(NPadControllerType::Handheld); - } - } - /* - if (supported_npad_id_types.size() > 0) { - const auto& first_controller = supported_npad_id_types.front(); - if (first_controller == 32 && !connected_controllers[8].is_connected) { - const auto& first_controller = connected_controllers.front(); - if (first_controller.is_connected && - first_controller.type == NPadControllerType::Handheld) { - DisconnectNPad(0); - AddNewController(NPadControllerType::Handheld, true); - } - } else if (first_controller != 32 && connected_controllers[8].is_connected) { - if (!connected_controllers[0].is_connected) { - DisconnectNPad(8); - AddNewController(NPadControllerType::Handheld); - } - } - }*/ } const void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { @@ -358,11 +343,14 @@ void Controller_NPad::VibrateController(const std::vector& controller_ids, } for (std::size_t i = 0; i < controller_ids.size(); i++) { std::size_t controller_pos = i; - if (controller_pos == 32) + // Handheld controller conversion + if (controller_pos == 32) { controller_pos = 8; - if (controller_pos == 16) + } + // Unknown controller conversion + if (controller_pos == 16) { controller_pos = 9; - + } if (connected_controllers[controller_pos].is_connected) { // TODO(ogniK): Vibrate the physical controller } @@ -378,8 +366,8 @@ Kernel::SharedPtr Controller_NPad::GetStyleSetChangedEvent() cons Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { return last_processed_vibration; } -void Controller_NPad::AddNewController(NPadControllerType controller, bool is_handheld_variant) { - if (is_handheld_variant) { +void Controller_NPad::AddNewController(NPadControllerType controller) { + if (controller == NPadControllerType::Handheld) { connected_controllers[8] = {controller, true}; InitNewlyAddedControler(8); return; @@ -438,13 +426,4 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { void Controller_NPad::SetVibrationEnabled(bool can_vibrate) { can_controllers_vibrate = can_vibrate; } - -void Controller_NPad::SetHandheldActiviationMode(u32 mode) { - const auto& first_controller = connected_controllers.front(); - if (!first_controller.is_connected || connected_controllers[8].is_connected) { - return; - } - DisconnectNPad(0); - AddNewController(NPadControllerType::Handheld, true); -} } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index bc3d15ce6c..9d07d258d8 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -65,9 +65,9 @@ public: None, ProController, Handheld, + JoyDual, JoyLeft, JoyRight, - Tabletop, Pokeball, }; @@ -105,13 +105,12 @@ public: Kernel::SharedPtr GetStyleSetChangedEvent() const; Vibration GetLastVibration() const; - void AddNewController(NPadControllerType controller, bool is_handheld_variant = false); + void AddNewController(NPadControllerType controller); void ConnectNPad(u32 npad_id); void DisconnectNPad(u32 npad_id); LedPattern GetLedPattern(u32 npad_id); void SetVibrationEnabled(bool can_vibrate); - void SetHandheldActiviationMode(u32 mode); private: struct CommonHeader { @@ -181,6 +180,10 @@ private: u32_le raw{}; BitField<0, 1, u32_le> IsConnected; BitField<1, 1, u32_le> IsWired; + BitField<2, 1, u32_le> IsLeftJoyConnected; + BitField<3, 1, u32_le> IsLeftJoyWired; + BitField<4, 1, u32_le> IsRightJoyConnected; + BitField<5, 1, u32_le> IsRightJoyWired; }; }; static_assert(sizeof(ConnectionState) == 4, "ConnectionState is an invalid size"); @@ -212,6 +215,8 @@ private: s64_le raw{}; BitField<11, 1, s64_le> is_vertical; BitField<12, 1, s64_le> is_horizontal; + BitField<13, 1, s64_le> use_plus; + BitField<14, 1, s64_le> use_minus; }; }; @@ -252,8 +257,9 @@ private: 6); // TODO(ogniK): SixAxis states, require more information before implementation NPadDevice device_type; NPadProperties properties; - INSERT_PADDING_WORDS(4); - INSERT_PADDING_BYTES(0x60); + INSERT_PADDING_WORDS(1); + std::array battery_level; + INSERT_PADDING_BYTES(0x5c); INSERT_PADDING_BYTES(0xdf8); }; static_assert(sizeof(NPadEntry) == 0x5000, "NPadEntry is an invalid size"); @@ -276,7 +282,6 @@ private: static constexpr std::array npad_id_list{0, 1, 2, 3, 4, 5, 6, 7, 32, 16}; std::array connected_controllers{}; bool can_controllers_vibrate{true}; - void CheckForHandheldVariant(); void InitNewlyAddedControler(std::size_t controller_idx); }; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index db1537b405..8aca0f1978 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -284,7 +284,7 @@ public: private: std::shared_ptr applet_resource; -#pragma optimize("", off) + void CreateAppletResource(Kernel::HLERequestContext& ctx) { if (applet_resource == nullptr) { applet_resource = std::make_shared(); @@ -545,8 +545,6 @@ private: IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); LOG_WARNING(Service_HID, "(STUBBED) called"); - applet_resource->GetController(HidController::NPad) - .SetHandheldActiviationMode(mode); } void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {