diff options
Diffstat (limited to 'src/core/hle/service/hid')
-rw-r--r-- | src/core/hle/service/hid/controllers/controller_base.h | 4 | ||||
-rw-r--r-- | src/core/hle/service/hid/controllers/keyboard.cpp | 4 | ||||
-rw-r--r-- | src/core/hle/service/hid/controllers/npad.cpp | 621 | ||||
-rw-r--r-- | src/core/hle/service/hid/controllers/npad.h | 157 | ||||
-rw-r--r-- | src/core/hle/service/hid/hid.cpp | 797 | ||||
-rw-r--r-- | src/core/hle/service/hid/hid.h | 50 | ||||
-rw-r--r-- | src/core/hle/service/hid/irs.cpp | 4 | ||||
-rw-r--r-- | src/core/hle/service/hid/irs.h | 10 | ||||
-rw-r--r-- | src/core/hle/service/hid/xcd.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/service/hid/xcd.h | 6 |
10 files changed, 1161 insertions, 494 deletions
diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h index 8bc69c372..f47a9e61c 100644 --- a/src/core/hle/service/hid/controllers/controller_base.h +++ b/src/core/hle/service/hid/controllers/controller_base.h @@ -31,6 +31,10 @@ public: virtual void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) = 0; + // When the controller is requesting a motion update for the shared memory + virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, + std::size_t size) {} + // Called when input devices should be loaded virtual void OnLoadInputDevices() = 0; diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp index 0b896d5ad..59b694cd4 100644 --- a/src/core/hle/service/hid/controllers/keyboard.cpp +++ b/src/core/hle/service/hid/controllers/keyboard.cpp @@ -42,8 +42,8 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing, cur_entry.modifier = 0; if (Settings::values.keyboard_enabled) { for (std::size_t i = 0; i < keyboard_keys.size(); ++i) { - cur_entry.key[i / KEYS_PER_BYTE] |= - (keyboard_keys[i]->GetStatus() << (i % KEYS_PER_BYTE)); + auto& entry = cur_entry.key[i / KEYS_PER_BYTE]; + entry = static_cast<u8>(entry | (keyboard_keys[i]->GetStatus() << (i % KEYS_PER_BYTE))); } for (std::size_t i = 0; i < keyboard_mods.size(); ++i) { diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 620386cd1..d280e7caf 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -116,8 +116,36 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) { } } +bool Controller_NPad::IsNpadIdValid(u32 npad_id) { + switch (npad_id) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case NPAD_UNKNOWN: + case NPAD_HANDHELD: + return true; + default: + LOG_ERROR(Service_HID, "Invalid npad id {}", npad_id); + return false; + } +} + +bool Controller_NPad::IsDeviceHandleValid(const DeviceHandle& device_handle) { + return IsNpadIdValid(device_handle.npad_id) && + device_handle.npad_type < NpadType::MaxNpadType && + device_handle.device_index < DeviceIndex::MaxDeviceIndex; +} + Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {} -Controller_NPad::~Controller_NPad() = default; + +Controller_NPad::~Controller_NPad() { + OnRelease(); +} void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { const auto controller_type = connected_controllers[controller_idx].type; @@ -139,7 +167,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { controller.properties.is_vertical.Assign(1); controller.properties.use_plus.Assign(1); controller.properties.use_minus.Assign(1); - controller.pad_assignment = NPadAssignments::Single; + controller.pad_assignment = NpadAssignments::Single; break; case NPadControllerType::Handheld: controller.joy_styles.handheld.Assign(1); @@ -147,7 +175,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { controller.properties.is_vertical.Assign(1); controller.properties.use_plus.Assign(1); controller.properties.use_minus.Assign(1); - controller.pad_assignment = NPadAssignments::Dual; + controller.pad_assignment = NpadAssignments::Dual; break; case NPadControllerType::JoyDual: controller.joy_styles.joycon_dual.Assign(1); @@ -156,26 +184,26 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { controller.properties.is_vertical.Assign(1); controller.properties.use_plus.Assign(1); controller.properties.use_minus.Assign(1); - controller.pad_assignment = NPadAssignments::Dual; + controller.pad_assignment = NpadAssignments::Dual; break; case NPadControllerType::JoyLeft: controller.joy_styles.joycon_left.Assign(1); controller.device_type.joycon_left.Assign(1); controller.properties.is_horizontal.Assign(1); controller.properties.use_minus.Assign(1); - controller.pad_assignment = NPadAssignments::Single; + controller.pad_assignment = NpadAssignments::Single; break; case NPadControllerType::JoyRight: controller.joy_styles.joycon_right.Assign(1); controller.device_type.joycon_right.Assign(1); controller.properties.is_horizontal.Assign(1); controller.properties.use_plus.Assign(1); - controller.pad_assignment = NPadAssignments::Single; + controller.pad_assignment = NpadAssignments::Single; break; case NPadControllerType::Pokeball: controller.joy_styles.pokeball.Assign(1); controller.device_type.pokeball.Assign(1); - controller.pad_assignment = NPadAssignments::Single; + controller.pad_assignment = NpadAssignments::Single; break; } @@ -184,11 +212,14 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { controller.single_color.button_color = 0; controller.dual_color_error = ColorReadError::ReadOk; - controller.left_color.body_color = Settings::values.players[controller_idx].body_color_left; - controller.left_color.button_color = Settings::values.players[controller_idx].button_color_left; - controller.right_color.body_color = Settings::values.players[controller_idx].body_color_right; + controller.left_color.body_color = + Settings::values.players.GetValue()[controller_idx].body_color_left; + controller.left_color.button_color = + Settings::values.players.GetValue()[controller_idx].button_color_left; + controller.right_color.body_color = + Settings::values.players.GetValue()[controller_idx].body_color_right; controller.right_color.button_color = - Settings::values.players[controller_idx].button_color_right; + Settings::values.players.GetValue()[controller_idx].button_color_right; controller.battery_level[0] = BATTERY_FULL; controller.battery_level[1] = BATTERY_FULL; @@ -199,7 +230,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { void Controller_NPad::OnInit() { auto& kernel = system.Kernel(); - for (std::size_t i = 0; i < styleset_changed_events.size(); i++) { + for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) { styleset_changed_events[i] = Kernel::WritableEvent::CreateEventPair( kernel, fmt::format("npad:NpadStyleSetChanged_{}", i)); } @@ -208,6 +239,8 @@ void Controller_NPad::OnInit() { return; } + OnLoadInputDevices(); + if (style.raw == 0) { // We want to support all controllers style.handheld.Assign(1); @@ -218,12 +251,27 @@ void Controller_NPad::OnInit() { style.pokeball.Assign(1); } - std::transform(Settings::values.players.begin(), Settings::values.players.end(), - connected_controllers.begin(), [](const Settings::PlayerInput& player) { + std::transform(Settings::values.players.GetValue().begin(), + Settings::values.players.GetValue().end(), connected_controllers.begin(), + [](const Settings::PlayerInput& player) { return ControllerHolder{MapSettingsTypeToNPad(player.controller_type), player.connected}; }); + // Connect the Player 1 or Handheld controller if none are connected. + if (std::none_of(connected_controllers.begin(), connected_controllers.end(), + [](const ControllerHolder& controller) { return controller.is_connected; })) { + const auto controller = + MapSettingsTypeToNPad(Settings::values.players.GetValue()[0].controller_type); + if (controller == NPadControllerType::Handheld) { + Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true; + connected_controllers[HANDHELD_INDEX] = {controller, true}; + } else { + Settings::values.players.GetValue()[0].connected = true; + connected_controllers[0] = {controller, true}; + } + } + // Account for handheld if (connected_controllers[HANDHELD_INDEX].is_connected) { connected_controllers[HANDHELD_INDEX].type = NPadControllerType::Handheld; @@ -242,7 +290,7 @@ void Controller_NPad::OnInit() { } void Controller_NPad::OnLoadInputDevices() { - const auto& players = Settings::values.players; + const auto& players = Settings::values.players.GetValue(); for (std::size_t i = 0; i < players.size(); ++i) { std::transform(players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_END, @@ -250,17 +298,30 @@ void Controller_NPad::OnLoadInputDevices() { std::transform(players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_END, sticks[i].begin(), Input::CreateDevice<Input::AnalogDevice>); + std::transform(players[i].vibrations.begin() + + Settings::NativeVibration::VIBRATION_HID_BEGIN, + players[i].vibrations.begin() + Settings::NativeVibration::VIBRATION_HID_END, + vibrations[i].begin(), Input::CreateDevice<Input::VibrationDevice>); std::transform(players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_BEGIN, players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_END, motions[i].begin(), Input::CreateDevice<Input::MotionDevice>); + for (std::size_t device_idx = 0; device_idx < vibrations[i].size(); ++device_idx) { + InitializeVibrationDeviceAtIndex(i, device_idx); + } } } -void Controller_NPad::OnRelease() {} +void Controller_NPad::OnRelease() { + for (std::size_t npad_idx = 0; npad_idx < vibrations.size(); ++npad_idx) { + for (std::size_t device_idx = 0; device_idx < vibrations[npad_idx].size(); ++device_idx) { + VibrateControllerAtIndex(npad_idx, device_idx, {}); + } + } +} void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { const auto controller_idx = NPadIdToIndex(npad_id); - [[maybe_unused]] const auto controller_type = connected_controllers[controller_idx].type; + const auto controller_type = connected_controllers[controller_idx].type; if (!connected_controllers[controller_idx].is_connected) { return; } @@ -269,61 +330,69 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { auto& rstick_entry = npad_pad_states[controller_idx].r_stick; const auto& button_state = buttons[controller_idx]; const auto& analog_state = sticks[controller_idx]; - const auto& motion_state = motions[controller_idx]; const auto [stick_l_x_f, stick_l_y_f] = analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetStatus(); const auto [stick_r_x_f, stick_r_y_f] = analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]->GetStatus(); using namespace Settings::NativeButton; - pad_state.a.Assign(button_state[A - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.b.Assign(button_state[B - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.x.Assign(button_state[X - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.y.Assign(button_state[Y - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.l_stick.Assign(button_state[LStick - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.r_stick.Assign(button_state[RStick - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.l.Assign(button_state[L - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.r.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.zl.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.zr.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.plus.Assign(button_state[Plus - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.minus.Assign(button_state[Minus - BUTTON_HID_BEGIN]->GetStatus()); - - pad_state.d_left.Assign(button_state[DLeft - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.d_up.Assign(button_state[DUp - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.d_right.Assign(button_state[DRight - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.d_down.Assign(button_state[DDown - BUTTON_HID_BEGIN]->GetStatus()); - - pad_state.l_stick_right.Assign( - analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus( - Input::AnalogDirection::RIGHT)); - pad_state.l_stick_left.Assign( - analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus( - Input::AnalogDirection::LEFT)); - pad_state.l_stick_up.Assign( - analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus( - Input::AnalogDirection::UP)); - pad_state.l_stick_down.Assign( - analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus( - Input::AnalogDirection::DOWN)); - - pad_state.r_stick_right.Assign( - analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)] - ->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT)); - pad_state.r_stick_left.Assign(analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)] - ->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT)); - pad_state.r_stick_up.Assign(analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)] - ->GetAnalogDirectionStatus(Input::AnalogDirection::UP)); - pad_state.r_stick_down.Assign(analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)] - ->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN)); - - pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus()); - - lstick_entry.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX); - lstick_entry.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX); - rstick_entry.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX); - rstick_entry.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX); + if (controller_type != NPadControllerType::JoyLeft) { + pad_state.a.Assign(button_state[A - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.b.Assign(button_state[B - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.x.Assign(button_state[X - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.y.Assign(button_state[Y - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r_stick.Assign(button_state[RStick - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.zr.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.plus.Assign(button_state[Plus - BUTTON_HID_BEGIN]->GetStatus()); + + pad_state.r_stick_right.Assign( + analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)] + ->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT)); + pad_state.r_stick_left.Assign( + analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)] + ->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT)); + pad_state.r_stick_up.Assign( + analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)] + ->GetAnalogDirectionStatus(Input::AnalogDirection::UP)); + pad_state.r_stick_down.Assign( + analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)] + ->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN)); + rstick_entry.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX); + rstick_entry.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX); + } + + if (controller_type != NPadControllerType::JoyRight) { + pad_state.d_left.Assign(button_state[DLeft - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.d_up.Assign(button_state[DUp - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.d_right.Assign(button_state[DRight - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.d_down.Assign(button_state[DDown - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l_stick.Assign(button_state[LStick - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l.Assign(button_state[L - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.zl.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.minus.Assign(button_state[Minus - BUTTON_HID_BEGIN]->GetStatus()); + + pad_state.l_stick_right.Assign( + analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)] + ->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT)); + pad_state.l_stick_left.Assign( + analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)] + ->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT)); + pad_state.l_stick_up.Assign( + analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)] + ->GetAnalogDirectionStatus(Input::AnalogDirection::UP)); + pad_state.l_stick_down.Assign( + analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)] + ->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN)); + lstick_entry.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX); + lstick_entry.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX); + } + + if (controller_type == NPadControllerType::JoyLeft || + controller_type == NPadControllerType::JoyRight) { + pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus()); + } } void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, @@ -331,7 +400,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* if (!IsControllerActivated()) { return; } - for (std::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<NPadGeneric*, 7> controller_npads{&npad.main_controller_states, &npad.handheld_states, @@ -365,6 +434,123 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* } const u32 npad_index = static_cast<u32>(i); + RequestPadStateUpdate(npad_index); + auto& pad_state = npad_pad_states[npad_index]; + + 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]; + + libnx_entry.connection_status.raw = 0; + libnx_entry.connection_status.IsConnected.Assign(1); + + switch (controller_type) { + case NPadControllerType::None: + UNREACHABLE(); + 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.pad_states.raw = pad_state.pad_states.raw; + main_controller.pad.l_stick = pad_state.l_stick; + main_controller.pad.r_stick = pad_state.r_stick; + + libnx_entry.connection_status.IsWired.Assign(1); + break; + case NPadControllerType::Handheld: + handheld_entry.connection_status.raw = 0; + handheld_entry.connection_status.IsConnected.Assign(1); + handheld_entry.connection_status.IsWired.Assign(1); + handheld_entry.connection_status.IsLeftJoyConnected.Assign(1); + handheld_entry.connection_status.IsRightJoyConnected.Assign(1); + handheld_entry.connection_status.IsLeftJoyWired.Assign(1); + handheld_entry.connection_status.IsRightJoyWired.Assign(1); + handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw; + handheld_entry.pad.l_stick = pad_state.l_stick; + handheld_entry.pad.r_stick = pad_state.r_stick; + + libnx_entry.connection_status.IsWired.Assign(1); + libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); + libnx_entry.connection_status.IsRightJoyConnected.Assign(1); + libnx_entry.connection_status.IsLeftJoyWired.Assign(1); + libnx_entry.connection_status.IsRightJoyWired.Assign(1); + break; + case NPadControllerType::JoyDual: + dual_entry.connection_status.raw = 0; + dual_entry.connection_status.IsConnected.Assign(1); + dual_entry.connection_status.IsLeftJoyConnected.Assign(1); + dual_entry.connection_status.IsRightJoyConnected.Assign(1); + dual_entry.pad.pad_states.raw = pad_state.pad_states.raw; + dual_entry.pad.l_stick = pad_state.l_stick; + dual_entry.pad.r_stick = pad_state.r_stick; + + libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); + libnx_entry.connection_status.IsRightJoyConnected.Assign(1); + break; + case NPadControllerType::JoyLeft: + left_entry.connection_status.raw = 0; + left_entry.connection_status.IsConnected.Assign(1); + left_entry.connection_status.IsLeftJoyConnected.Assign(1); + left_entry.pad.pad_states.raw = pad_state.pad_states.raw; + left_entry.pad.l_stick = pad_state.l_stick; + left_entry.pad.r_stick = pad_state.r_stick; + + libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); + break; + case NPadControllerType::JoyRight: + right_entry.connection_status.raw = 0; + right_entry.connection_status.IsConnected.Assign(1); + right_entry.connection_status.IsRightJoyConnected.Assign(1); + right_entry.pad.pad_states.raw = pad_state.pad_states.raw; + right_entry.pad.l_stick = pad_state.l_stick; + right_entry.pad.r_stick = pad_state.r_stick; + + libnx_entry.connection_status.IsRightJoyConnected.Assign(1); + break; + case NPadControllerType::Pokeball: + pokeball_entry.connection_status.raw = 0; + pokeball_entry.connection_status.IsConnected.Assign(1); + pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw; + pokeball_entry.pad.l_stick = pad_state.l_stick; + pokeball_entry.pad.r_stick = pad_state.r_stick; + break; + } + + // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate + // any controllers. + libnx_entry.pad.pad_states.raw = pad_state.pad_states.raw; + libnx_entry.pad.l_stick = pad_state.l_stick; + libnx_entry.pad.r_stick = pad_state.r_stick; + + press_state |= static_cast<u32>(pad_state.pad_states.raw); + } + std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(), + shared_memory_entries.size() * sizeof(NPadEntry)); +} + +void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, + std::size_t data_len) { + if (!IsControllerActivated()) { + return; + } + for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) { + auto& npad = shared_memory_entries[i]; + + const auto& controller_type = connected_controllers[i].type; + + if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) { + continue; + } + const std::array<SixAxisGeneric*, 6> controller_sixaxes{ &npad.sixaxis_full, &npad.sixaxis_handheld, &npad.sixaxis_dual_left, &npad.sixaxis_dual_right, &npad.sixaxis_left, &npad.sixaxis_right, @@ -390,7 +576,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* // Try to read sixaxis sensor states std::array<MotionDevice, 2> motion_devices; - if (sixaxis_sensors_enabled && Settings::values.motion_enabled) { + if (sixaxis_sensors_enabled && Settings::values.motion_enabled.GetValue()) { sixaxis_at_rest = true; for (std::size_t e = 0; e < motion_devices.size(); ++e) { const auto& device = motions[i][e]; @@ -403,23 +589,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* } } - RequestPadStateUpdate(npad_index); - auto& pad_state = npad_pad_states[npad_index]; - - 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]; - - libnx_entry.connection_status.raw = 0; - libnx_entry.connection_status.IsConnected.Assign(1); auto& full_sixaxis_entry = npad.sixaxis_full.sixaxis[npad.sixaxis_full.common.last_entry_index]; auto& handheld_sixaxis_entry = @@ -438,15 +607,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* UNREACHABLE(); 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.pad_states.raw = pad_state.pad_states.raw; - main_controller.pad.l_stick = pad_state.l_stick; - main_controller.pad.r_stick = pad_state.r_stick; - - libnx_entry.connection_status.IsWired.Assign(1); - if (sixaxis_sensors_enabled && motions[i][0]) { full_sixaxis_entry.accel = motion_devices[0].accel; full_sixaxis_entry.gyro = motion_devices[0].gyro; @@ -455,23 +615,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* } break; case NPadControllerType::Handheld: - handheld_entry.connection_status.raw = 0; - handheld_entry.connection_status.IsConnected.Assign(1); - handheld_entry.connection_status.IsWired.Assign(1); - handheld_entry.connection_status.IsLeftJoyConnected.Assign(1); - handheld_entry.connection_status.IsRightJoyConnected.Assign(1); - handheld_entry.connection_status.IsLeftJoyWired.Assign(1); - handheld_entry.connection_status.IsRightJoyWired.Assign(1); - handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw; - handheld_entry.pad.l_stick = pad_state.l_stick; - handheld_entry.pad.r_stick = pad_state.r_stick; - - libnx_entry.connection_status.IsWired.Assign(1); - libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); - libnx_entry.connection_status.IsRightJoyConnected.Assign(1); - libnx_entry.connection_status.IsLeftJoyWired.Assign(1); - libnx_entry.connection_status.IsRightJoyWired.Assign(1); - if (sixaxis_sensors_enabled && motions[i][0]) { handheld_sixaxis_entry.accel = motion_devices[0].accel; handheld_sixaxis_entry.gyro = motion_devices[0].gyro; @@ -480,17 +623,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* } break; case NPadControllerType::JoyDual: - dual_entry.connection_status.raw = 0; - dual_entry.connection_status.IsConnected.Assign(1); - dual_entry.connection_status.IsLeftJoyConnected.Assign(1); - dual_entry.connection_status.IsRightJoyConnected.Assign(1); - dual_entry.pad.pad_states.raw = pad_state.pad_states.raw; - dual_entry.pad.l_stick = pad_state.l_stick; - dual_entry.pad.r_stick = pad_state.r_stick; - - libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); - libnx_entry.connection_status.IsRightJoyConnected.Assign(1); - if (sixaxis_sensors_enabled && motions[i][0]) { // Set motion for the left joycon dual_left_sixaxis_entry.accel = motion_devices[0].accel; @@ -507,15 +639,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* } break; case NPadControllerType::JoyLeft: - left_entry.connection_status.raw = 0; - left_entry.connection_status.IsConnected.Assign(1); - left_entry.connection_status.IsLeftJoyConnected.Assign(1); - left_entry.pad.pad_states.raw = pad_state.pad_states.raw; - left_entry.pad.l_stick = pad_state.l_stick; - left_entry.pad.r_stick = pad_state.r_stick; - - libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); - if (sixaxis_sensors_enabled && motions[i][0]) { left_sixaxis_entry.accel = motion_devices[0].accel; left_sixaxis_entry.gyro = motion_devices[0].gyro; @@ -524,15 +647,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* } break; case NPadControllerType::JoyRight: - right_entry.connection_status.raw = 0; - right_entry.connection_status.IsConnected.Assign(1); - right_entry.connection_status.IsRightJoyConnected.Assign(1); - right_entry.pad.pad_states.raw = pad_state.pad_states.raw; - right_entry.pad.l_stick = pad_state.l_stick; - right_entry.pad.r_stick = pad_state.r_stick; - - libnx_entry.connection_status.IsRightJoyConnected.Assign(1); - if (sixaxis_sensors_enabled && motions[i][1]) { right_sixaxis_entry.accel = motion_devices[1].accel; right_sixaxis_entry.gyro = motion_devices[1].gyro; @@ -541,35 +655,22 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* } break; case NPadControllerType::Pokeball: - pokeball_entry.connection_status.raw = 0; - pokeball_entry.connection_status.IsConnected.Assign(1); - pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw; - pokeball_entry.pad.l_stick = pad_state.l_stick; - pokeball_entry.pad.r_stick = pad_state.r_stick; break; } - - // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate - // any controllers. - libnx_entry.pad.pad_states.raw = pad_state.pad_states.raw; - libnx_entry.pad.l_stick = pad_state.l_stick; - libnx_entry.pad.r_stick = pad_state.r_stick; - - press_state |= static_cast<u32>(pad_state.pad_states.raw); } std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(), shared_memory_entries.size() * sizeof(NPadEntry)); } -void Controller_NPad::SetSupportedStyleSet(NPadType style_set) { +void Controller_NPad::SetSupportedStyleSet(NpadStyleSet style_set) { style.raw = style_set.raw; } -Controller_NPad::NPadType Controller_NPad::GetSupportedStyleSet() const { +Controller_NPad::NpadStyleSet Controller_NPad::GetSupportedStyleSet() const { return style; } -void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) { +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)); @@ -581,7 +682,7 @@ void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) std::memcpy(data, supported_npad_id_types.data(), supported_npad_id_types.size()); } -std::size_t Controller_NPad::GetSupportedNPadIdTypesSize() const { +std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const { return supported_npad_id_types.size(); } @@ -601,7 +702,15 @@ Controller_NPad::NpadHandheldActivationMode Controller_NPad::GetNpadHandheldActi return handheld_activation_mode; } -void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) { +void Controller_NPad::SetNpadCommunicationMode(NpadCommunicationMode communication_mode_) { + communication_mode = communication_mode_; +} + +Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode() const { + return communication_mode; +} + +void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) { const std::size_t npad_index = NPadIdToIndex(npad_id); ASSERT(npad_index < shared_memory_entries.size()); if (shared_memory_entries[npad_index].pad_assignment != assignment_mode) { @@ -609,24 +718,156 @@ void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) } } -void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids, - const std::vector<Vibration>& vibrations) { - LOG_DEBUG(Service_HID, "(STUBBED) called"); +bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, + const VibrationValue& vibration_value) { + if (!connected_controllers[npad_index].is_connected || !vibrations[npad_index][device_index]) { + return false; + } - if (!Settings::values.vibration_enabled || !can_controllers_vibrate) { - return; + const auto& player = Settings::values.players.GetValue()[npad_index]; + + if (!player.vibration_enabled) { + if (latest_vibration_values[npad_index][device_index].amp_low != 0.0f || + latest_vibration_values[npad_index][device_index].amp_high != 0.0f) { + // Send an empty vibration to stop any vibrations. + vibrations[npad_index][device_index]->SetRumblePlay(0.0f, 160.0f, 0.0f, 320.0f); + // Then reset the vibration value to its default value. + latest_vibration_values[npad_index][device_index] = {}; + } + + return false; } - for (std::size_t i = 0; i < controller_ids.size(); i++) { - std::size_t controller_pos = NPadIdToIndex(static_cast<u32>(i)); - if (connected_controllers[controller_pos].is_connected) { - // TODO(ogniK): Vibrate the physical controller + + if (!Settings::values.enable_accurate_vibrations.GetValue()) { + using std::chrono::duration_cast; + using std::chrono::milliseconds; + using std::chrono::steady_clock; + + const auto now = steady_clock::now(); + + // Filter out non-zero vibrations that are within 10ms of each other. + if ((vibration_value.amp_low != 0.0f || vibration_value.amp_high != 0.0f) && + duration_cast<milliseconds>(now - last_vibration_timepoints[npad_index][device_index]) < + milliseconds(10)) { + return false; } + + last_vibration_timepoints[npad_index][device_index] = now; + } + + auto& vibration = vibrations[npad_index][device_index]; + const auto player_vibration_strength = static_cast<f32>(player.vibration_strength); + const auto amp_low = + std::min(vibration_value.amp_low * player_vibration_strength / 100.0f, 1.0f); + const auto amp_high = + std::min(vibration_value.amp_high * player_vibration_strength / 100.0f, 1.0f); + return vibration->SetRumblePlay(amp_low, vibration_value.freq_low, amp_high, + vibration_value.freq_high); +} + +void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle, + const VibrationValue& vibration_value) { + if (!IsDeviceHandleValid(vibration_device_handle)) { + return; + } + + if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { + return; + } + + const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); + const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); + + if (!vibration_devices_mounted[npad_index][device_index] || + !connected_controllers[npad_index].is_connected) { + return; + } + + if (vibration_device_handle.device_index == DeviceIndex::None) { + UNREACHABLE_MSG("DeviceIndex should never be None!"); + return; + } + + // Some games try to send mismatched parameters in the device handle, block these. + if ((connected_controllers[npad_index].type == NPadControllerType::JoyLeft && + (vibration_device_handle.npad_type == NpadType::JoyconRight || + vibration_device_handle.device_index == DeviceIndex::Right)) || + (connected_controllers[npad_index].type == NPadControllerType::JoyRight && + (vibration_device_handle.npad_type == NpadType::JoyconLeft || + vibration_device_handle.device_index == DeviceIndex::Left))) { + return; + } + + // Filter out vibrations with equivalent values to reduce unnecessary state changes. + if (vibration_value.amp_low == latest_vibration_values[npad_index][device_index].amp_low && + vibration_value.amp_high == latest_vibration_values[npad_index][device_index].amp_high) { + return; + } + + if (VibrateControllerAtIndex(npad_index, device_index, vibration_value)) { + latest_vibration_values[npad_index][device_index] = vibration_value; } - last_processed_vibration = vibrations.back(); } -Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { - return last_processed_vibration; +void Controller_NPad::VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles, + const std::vector<VibrationValue>& vibration_values) { + if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { + return; + } + + ASSERT_OR_EXECUTE_MSG( + vibration_device_handles.size() == vibration_values.size(), { return; }, + "The amount of device handles does not match with the amount of vibration values," + "this is undefined behavior!"); + + for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) { + VibrateController(vibration_device_handles[i], vibration_values[i]); + } +} + +Controller_NPad::VibrationValue Controller_NPad::GetLastVibration( + const DeviceHandle& vibration_device_handle) const { + if (!IsDeviceHandleValid(vibration_device_handle)) { + return {}; + } + + const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); + const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); + return latest_vibration_values[npad_index][device_index]; +} + +void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_device_handle) { + if (!IsDeviceHandleValid(vibration_device_handle)) { + return; + } + + const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); + const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); + InitializeVibrationDeviceAtIndex(npad_index, device_index); +} + +void Controller_NPad::InitializeVibrationDeviceAtIndex(std::size_t npad_index, + std::size_t device_index) { + if (vibrations[npad_index][device_index]) { + vibration_devices_mounted[npad_index][device_index] = + vibrations[npad_index][device_index]->GetStatus() == 1; + } else { + vibration_devices_mounted[npad_index][device_index] = false; + } +} + +void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) { + permit_vibration_session_enabled = permit_vibration_session; +} + +bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const { + if (!IsDeviceHandleValid(vibration_device_handle)) { + return false; + } + + const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); + const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); + return vibration_devices_mounted[npad_index][device_index]; } std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const { @@ -645,31 +886,38 @@ void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::siz void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected) { if (!connected) { - DisconnectNPadAtIndex(npad_index); + DisconnectNpadAtIndex(npad_index); return; } if (controller == NPadControllerType::Handheld) { - Settings::values.players[HANDHELD_INDEX].controller_type = + Settings::values.players.GetValue()[HANDHELD_INDEX].controller_type = MapNPadToSettingsType(controller); - Settings::values.players[HANDHELD_INDEX].connected = true; + Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true; connected_controllers[HANDHELD_INDEX] = {controller, true}; InitNewlyAddedController(HANDHELD_INDEX); return; } - Settings::values.players[npad_index].controller_type = MapNPadToSettingsType(controller); - Settings::values.players[npad_index].connected = true; + Settings::values.players.GetValue()[npad_index].controller_type = + MapNPadToSettingsType(controller); + Settings::values.players.GetValue()[npad_index].connected = true; connected_controllers[npad_index] = {controller, true}; InitNewlyAddedController(npad_index); } -void Controller_NPad::DisconnectNPad(u32 npad_id) { - DisconnectNPadAtIndex(NPadIdToIndex(npad_id)); +void Controller_NPad::DisconnectNpad(u32 npad_id) { + DisconnectNpadAtIndex(NPadIdToIndex(npad_id)); } -void Controller_NPad::DisconnectNPadAtIndex(std::size_t npad_index) { - Settings::values.players[npad_index].connected = false; +void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) { + for (std::size_t device_idx = 0; device_idx < vibrations[npad_index].size(); ++device_idx) { + // Send an empty vibration to stop any vibrations. + VibrateControllerAtIndex(npad_index, device_idx, {}); + vibration_devices_mounted[npad_index][device_idx] = false; + } + + Settings::values.players.GetValue()[npad_index].connected = false; connected_controllers[npad_index].is_connected = false; auto& controller = shared_memory_entries[npad_index]; @@ -707,7 +955,7 @@ void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) { (connected_controllers[npad_index_2].type == NPadControllerType::JoyLeft && connected_controllers[npad_index_1].type == NPadControllerType::JoyRight)) { // Disconnect the joycon at the second id and connect the dual joycon at the first index. - DisconnectNPad(npad_id_2); + DisconnectNpad(npad_id_2); AddNewControllerAt(NPadControllerType::JoyDual, npad_index_1); } } @@ -770,12 +1018,13 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { } } -void Controller_NPad::SetVibrationEnabled(bool can_vibrate) { - can_controllers_vibrate = can_vibrate; +bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const { + return unintended_home_button_input_protection[NPadIdToIndex(npad_id)]; } -bool Controller_NPad::IsVibrationEnabled() const { - return can_controllers_vibrate; +void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, + u32 npad_id) { + unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled; } void Controller_NPad::ClearAllConnectedControllers() { @@ -809,7 +1058,7 @@ void Controller_NPad::ClearAllControllers() { } u32 Controller_NPad::GetAndResetPressState() { - return std::exchange(press_state, 0); + return press_state.exchange(0); } bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const { @@ -822,7 +1071,7 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const return false; } // Handheld should not be supported in docked mode - if (Settings::values.use_docked_mode) { + if (Settings::values.use_docked_mode.GetValue()) { return false; } diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 654d97c3f..e2e826623 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -5,6 +5,7 @@ #pragma once #include <array> +#include <atomic> #include "common/bit_field.h" #include "common/common_types.h" #include "core/frontend/input.h" @@ -32,31 +33,39 @@ public: // When the controller is requesting an update for the shared memory void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; + // When the controller is requesting a motion update for the shared memory + void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, + std::size_t size) override; + // Called when input devices should be loaded void OnLoadInputDevices() override; - struct NPadType { - union { - u32_le raw{}; - - BitField<0, 1, u32> pro_controller; - BitField<1, 1, u32> handheld; - BitField<2, 1, u32> joycon_dual; - BitField<3, 1, u32> joycon_left; - BitField<4, 1, u32> joycon_right; + enum class NPadControllerType { + None, + ProController, + Handheld, + JoyDual, + JoyLeft, + JoyRight, + Pokeball, + }; - BitField<6, 1, u32> pokeball; // TODO(ogniK): Confirm when possible - }; + enum class NpadType : u8 { + ProController = 3, + Handheld = 4, + JoyconDual = 5, + JoyconLeft = 6, + JoyconRight = 7, + Pokeball = 9, + MaxNpadType = 10, }; - static_assert(sizeof(NPadType) == 4, "NPadType is an invalid size"); - struct Vibration { - f32 amp_low; - f32 freq_low; - f32 amp_high; - f32 freq_high; + enum class DeviceIndex : u8 { + Left = 0, + Right = 1, + None = 2, + MaxDeviceIndex = 3, }; - static_assert(sizeof(Vibration) == 0x10, "Vibration is an invalid size"); enum class GyroscopeZeroDriftMode : u32 { Loose = 0, @@ -69,7 +78,7 @@ public: Horizontal = 1, }; - enum class NPadAssignments : u32_le { + enum class NpadAssignments : u32 { Dual = 0, Single = 1, }; @@ -80,15 +89,43 @@ public: None = 2, }; - enum class NPadControllerType { - None, - ProController, - Handheld, - JoyDual, - JoyLeft, - JoyRight, - Pokeball, + enum class NpadCommunicationMode : u64 { + Unknown0 = 0, + Unknown1 = 1, + Unknown2 = 2, + Unknown3 = 3, + }; + + struct DeviceHandle { + NpadType npad_type{}; + u8 npad_id{}; + DeviceIndex device_index{}; + INSERT_PADDING_BYTES(1); + }; + static_assert(sizeof(DeviceHandle) == 4, "DeviceHandle is an invalid size"); + + struct NpadStyleSet { + union { + u32_le raw{}; + + BitField<0, 1, u32> pro_controller; + BitField<1, 1, u32> handheld; + BitField<2, 1, u32> joycon_dual; + BitField<3, 1, u32> joycon_left; + BitField<4, 1, u32> joycon_right; + + BitField<6, 1, u32> pokeball; // TODO(ogniK): Confirm when possible + }; }; + static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size"); + + struct VibrationValue { + f32 amp_low{0.0f}; + f32 freq_low{160.0f}; + f32 amp_high{0.0f}; + f32 freq_high{320.0f}; + }; + static_assert(sizeof(VibrationValue) == 0x10, "Vibration is an invalid size"); struct LedPattern { explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) { @@ -106,12 +143,12 @@ public: }; }; - void SetSupportedStyleSet(NPadType style_set); - NPadType GetSupportedStyleSet() const; + void SetSupportedStyleSet(NpadStyleSet style_set); + NpadStyleSet GetSupportedStyleSet() const; - void SetSupportedNPadIdTypes(u8* data, std::size_t length); + void SetSupportedNpadIdTypes(u8* data, std::size_t length); void GetSupportedNpadIdTypes(u32* data, std::size_t max_length); - std::size_t GetSupportedNPadIdTypesSize() const; + std::size_t GetSupportedNpadIdTypesSize() const; void SetHoldType(NpadHoldType joy_hold_type); NpadHoldType GetHoldType() const; @@ -119,12 +156,29 @@ public: void SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode); NpadHandheldActivationMode GetNpadHandheldActivationMode() const; - void SetNpadMode(u32 npad_id, NPadAssignments assignment_mode); + void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_); + NpadCommunicationMode GetNpadCommunicationMode() const; + + void SetNpadMode(u32 npad_id, NpadAssignments assignment_mode); + + bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, + const VibrationValue& vibration_value); + + void VibrateController(const DeviceHandle& vibration_device_handle, + const VibrationValue& vibration_value); + + void VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles, + const std::vector<VibrationValue>& vibration_values); + + VibrationValue GetLastVibration(const DeviceHandle& vibration_device_handle) const; + + void InitializeVibrationDevice(const DeviceHandle& vibration_device_handle); + + void InitializeVibrationDeviceAtIndex(std::size_t npad_index, std::size_t device_index); - void VibrateController(const std::vector<u32>& controller_ids, - const std::vector<Vibration>& vibrations); + void SetPermitVibrationSession(bool permit_vibration_session); - Vibration GetLastVibration() const; + bool IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const; std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const; void SignalStyleSetChangedEvent(u32 npad_id) const; @@ -134,16 +188,16 @@ public: // Adds a new controller at an index with connection status. void UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected); - void DisconnectNPad(u32 npad_id); - void DisconnectNPadAtIndex(std::size_t index); + void DisconnectNpad(u32 npad_id); + void DisconnectNpadAtIndex(std::size_t index); void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode); GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const; bool IsSixAxisSensorAtRest() const; void SetSixAxisEnabled(bool six_axis_status); LedPattern GetLedPattern(u32 npad_id); - void SetVibrationEnabled(bool can_vibrate); - bool IsVibrationEnabled() const; + bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const; + void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id); void ClearAllConnectedControllers(); void DisconnectAllConnectedControllers(); void ConnectAllDisconnectedControllers(); @@ -162,6 +216,8 @@ public: static Settings::ControllerType MapNPadToSettingsType(Controller_NPad::NPadControllerType type); static std::size_t NPadIdToIndex(u32 npad_id); static u32 IndexToNPad(std::size_t index); + static bool IsNpadIdValid(u32 npad_id); + static bool IsDeviceHandleValid(const DeviceHandle& device_handle); private: struct CommonHeader { @@ -318,8 +374,8 @@ private: }; struct NPadEntry { - NPadType joy_styles; - NPadAssignments pad_assignment; + NpadStyleSet joy_styles; + NpadAssignments pad_assignment; ColorReadError single_color_error; ControllerColor single_color; @@ -360,9 +416,9 @@ private: bool IsControllerSupported(NPadControllerType controller) const; void RequestPadStateUpdate(u32 npad_id); - u32 press_state{}; + std::atomic<u32> press_state{}; - NPadType style{}; + NpadStyleSet style{}; std::array<NPadEntry, 10> shared_memory_entries{}; using ButtonArray = std::array< std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>, @@ -370,21 +426,30 @@ private: using StickArray = std::array< std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>, 10>; + using VibrationArray = std::array<std::array<std::unique_ptr<Input::VibrationDevice>, + Settings::NativeVibration::NUM_VIBRATIONS_HID>, + 10>; using MotionArray = std::array< - std::array<std::unique_ptr<Input::MotionDevice>, Settings::NativeMotion::NUM_MOTION_HID>, + std::array<std::unique_ptr<Input::MotionDevice>, Settings::NativeMotion::NUM_MOTIONS_HID>, 10>; ButtonArray buttons; StickArray sticks; + VibrationArray vibrations; MotionArray motions; std::vector<u32> supported_npad_id_types{}; NpadHoldType hold_type{NpadHoldType::Vertical}; NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; + // NpadCommunicationMode is unknown, default value is 1 + NpadCommunicationMode communication_mode{NpadCommunicationMode::Unknown1}; // Each controller should have their own styleset changed event std::array<Kernel::EventPair, 10> styleset_changed_events; - Vibration last_processed_vibration{}; + std::array<std::array<std::chrono::steady_clock::time_point, 2>, 10> last_vibration_timepoints; + std::array<std::array<VibrationValue, 2>, 10> latest_vibration_values{}; + bool permit_vibration_session_enabled{false}; + std::array<std::array<bool, 2>, 10> vibration_devices_mounted{}; std::array<ControllerHolder, 10> connected_controllers{}; + std::array<bool, 10> unintended_home_button_input_protection{}; GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; - bool can_controllers_vibrate{true}; bool sixaxis_sensors_enabled{true}; bool sixaxis_at_rest{true}; std::array<ControllerPad, 10> npad_pad_states{}; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 395e83b3f..8d95f74e6 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -40,11 +40,12 @@ namespace Service::HID { // Updating period for each HID device. // HID is polled every 15ms, this value was derived from // https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering#joy-con-status-data-packet -constexpr auto pad_update_ns = std::chrono::nanoseconds{1000 * 1000}; // (1ms, 1000Hz) +constexpr auto pad_update_ns = std::chrono::nanoseconds{1000 * 1000}; // (1ms, 1000Hz) +constexpr auto motion_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000}; // (15ms, 66.666Hz) constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; -IAppletResource::IAppletResource(Core::System& system) - : ServiceFramework("IAppletResource"), system(system) { +IAppletResource::IAppletResource(Core::System& system_) + : ServiceFramework{system_, "IAppletResource"} { static const FunctionInfo functions[] = { {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"}, }; @@ -77,12 +78,18 @@ IAppletResource::IAppletResource(Core::System& system) pad_update_event = Core::Timing::CreateEvent( "HID::UpdatePadCallback", [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { + const auto guard = LockService(); UpdateControllers(user_data, ns_late); }); - - // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?) + motion_update_event = Core::Timing::CreateEvent( + "HID::MotionPadCallback", + [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { + const auto guard = LockService(); + UpdateMotion(user_data, ns_late); + }); system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event); + system.CoreTiming().ScheduleEvent(motion_update_ns, motion_update_event); ReloadInputDevices(); } @@ -122,22 +129,50 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data, core_timing.ScheduleEvent(pad_update_ns - ns_late, pad_update_event); } +void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { + auto& core_timing = system.CoreTiming(); + + for (const auto& controller : controllers) { + controller->OnMotionUpdate(core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE); + } + + core_timing.ScheduleEvent(motion_update_ns - ns_late, motion_update_event); +} + class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> { public: - IActiveVibrationDeviceList() : ServiceFramework("IActiveVibrationDeviceList") { + explicit IActiveVibrationDeviceList(Core::System& system_, + std::shared_ptr<IAppletResource> applet_resource_) + : ServiceFramework{system_, "IActiveVibrationDeviceList"}, + applet_resource(applet_resource_) { + // clang-format off static const FunctionInfo functions[] = { - {0, &IActiveVibrationDeviceList::ActivateVibrationDevice, "ActivateVibrationDevice"}, + {0, &IActiveVibrationDeviceList::InitializeVibrationDevice, "InitializeVibrationDevice"}, }; + // clang-format on + RegisterHandlers(functions); } private: - void ActivateVibrationDevice(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_HID, "(STUBBED) called"); + void InitializeVibrationDevice(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto vibration_device_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()}; + + if (applet_resource != nullptr) { + applet_resource->GetController<Controller_NPad>(HidController::NPad) + .InitializeVibrationDevice(vibration_device_handle); + } + + LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}", + vibration_device_handle.npad_type, vibration_device_handle.npad_id, + vibration_device_handle.device_index); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } + + std::shared_ptr<IAppletResource> applet_resource; }; std::shared_ptr<IAppletResource> Hid::GetAppletResource() { @@ -148,7 +183,7 @@ std::shared_ptr<IAppletResource> Hid::GetAppletResource() { return applet_resource; } -Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) { +Hid::Hid(Core::System& system_) : ServiceFramework{system_, "hid"} { // clang-format off static const FunctionInfo functions[] = { {0, &Hid::CreateAppletResource, "CreateAppletResource"}, @@ -173,7 +208,7 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) { {66, &Hid::StartSixAxisSensor, "StartSixAxisSensor"}, {67, &Hid::StopSixAxisSensor, "StopSixAxisSensor"}, {68, nullptr, "IsSixAxisSensorFusionEnabled"}, - {69, nullptr, "EnableSixAxisSensorFusion"}, + {69, &Hid::EnableSixAxisSensorFusion, "EnableSixAxisSensorFusion"}, {70, nullptr, "SetSixAxisSensorFusionParameters"}, {71, nullptr, "GetSixAxisSensorFusionParameters"}, {72, nullptr, "ResetSixAxisSensorFusionParameters"}, @@ -209,8 +244,8 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) { {128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"}, {129, &Hid::GetNpadHandheldActivationMode, "GetNpadHandheldActivationMode"}, {130, &Hid::SwapNpadAssignment, "SwapNpadAssignment"}, - {131, nullptr, "IsUnintendedHomeButtonInputProtectionEnabled"}, - {132, nullptr, "EnableUnintendedHomeButtonInputProtection"}, + {131, &Hid::IsUnintendedHomeButtonInputProtectionEnabled, "IsUnintendedHomeButtonInputProtectionEnabled"}, + {132, &Hid::EnableUnintendedHomeButtonInputProtection, "EnableUnintendedHomeButtonInputProtection"}, {133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"}, {134, nullptr, "SetNpadAnalogStickUseCenterClamp"}, {135, nullptr, "SetNpadCaptureButtonAssignment"}, @@ -226,7 +261,7 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) { {208, nullptr, "GetActualVibrationGcErmCommand"}, {209, &Hid::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, {210, &Hid::EndPermitVibrationSession, "EndPermitVibrationSession"}, - {211, nullptr, "IsVibrationDeviceMounted"}, + {211, &Hid::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"}, {300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"}, {301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"}, {302, &Hid::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"}, @@ -245,7 +280,7 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) { {404, nullptr, "HasLeftRightBattery"}, {405, nullptr, "GetNpadInterfaceType"}, {406, nullptr, "GetNpadLeftRightInterfaceType"}, - {407, nullptr, "GetNpadOfHighestBatteryLevelForJoyLeft"}, + {407, nullptr, "GetNpadOfHighestBatteryLevel"}, {408, nullptr, "GetNpadOfHighestBatteryLevelForJoyRight"}, {500, nullptr, "GetPalmaConnectionHandle"}, {501, nullptr, "InitializePalma"}, @@ -277,8 +312,8 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) { {527, nullptr, "EnablePalmaBoostMode"}, {528, nullptr, "GetPalmaBluetoothAddress"}, {529, nullptr, "SetDisallowedPalmaConnection"}, - {1000, nullptr, "SetNpadCommunicationMode"}, - {1001, nullptr, "GetNpadCommunicationMode"}, + {1000, &Hid::SetNpadCommunicationMode, "SetNpadCommunicationMode"}, + {1001, &Hid::GetNpadCommunicationMode, "GetNpadCommunicationMode"}, {1002, nullptr, "SetTouchScreenConfiguration"}, {1003, nullptr, "IsFirmwareUpdateNeededForNotification"}, {2000, nullptr, "ActivateDigitizer"}, @@ -305,154 +340,195 @@ void Hid::CreateAppletResource(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface<IAppletResource>(applet_resource); } -void Hid::ActivateXpad(Kernel::HLERequestContext& ctx) { +void Hid::ActivateDebugPad(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto basic_xpad_id{rp.Pop<u32>()}; const auto applet_resource_user_id{rp.Pop<u64>()}; - LOG_DEBUG(Service_HID, "called, basic_xpad_id={}, applet_resource_user_id={}", basic_xpad_id, - applet_resource_user_id); + applet_resource->ActivateController(HidController::DebugPad); + + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - applet_resource->ActivateController(HidController::XPad); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } -void Hid::GetXpadIDs(Kernel::HLERequestContext& ctx) { +void Hid::ActivateTouchScreen(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; - LOG_DEBUG(Service_HID, "(STUBBED) called, applet_resource_user_id={}", applet_resource_user_id); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(RESULT_SUCCESS); - rb.Push(0); -} + applet_resource->ActivateController(HidController::Touchscreen); -void Hid::ActivateSixAxisSensor(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto handle{rp.Pop<u32>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; - applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(true); - LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle, - applet_resource_user_id); + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } -void Hid::DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx) { +void Hid::ActivateMouse(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto handle{rp.Pop<u32>()}; const auto applet_resource_user_id{rp.Pop<u64>()}; - applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(false); - LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle, - applet_resource_user_id); + applet_resource->ActivateController(HidController::Mouse); + + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } -void Hid::ActivateDebugPad(Kernel::HLERequestContext& ctx) { +void Hid::ActivateKeyboard(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; + applet_resource->ActivateController(HidController::Keyboard); + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - applet_resource->ActivateController(HidController::DebugPad); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } -void Hid::ActivateTouchScreen(Kernel::HLERequestContext& ctx) { +void Hid::SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto applet_resource_user_id{rp.Pop<u64>()}; + const auto flags{rp.Pop<u32>()}; - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + LOG_WARNING(Service_HID, "(STUBBED) called. flags={}", flags); - applet_resource->ActivateController(HidController::Touchscreen); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } -void Hid::ActivateMouse(Kernel::HLERequestContext& ctx) { +void Hid::ActivateXpad(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto applet_resource_user_id{rp.Pop<u64>()}; + struct Parameters { + u32 basic_xpad_id{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + }; - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + const auto parameters{rp.PopRaw<Parameters>()}; + + applet_resource->ActivateController(HidController::XPad); + + LOG_DEBUG(Service_HID, "called, basic_xpad_id={}, applet_resource_user_id={}", + parameters.basic_xpad_id, parameters.applet_resource_user_id); - applet_resource->ActivateController(HidController::Mouse); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } -void Hid::ActivateKeyboard(Kernel::HLERequestContext& ctx) { +void Hid::GetXpadIDs(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + LOG_DEBUG(Service_HID, "(STUBBED) called, applet_resource_user_id={}", applet_resource_user_id); - applet_resource->ActivateController(HidController::Keyboard); - IPC::ResponseBuilder rb{ctx, 2}; + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); + rb.Push(0); } -void Hid::SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx) { +void Hid::ActivateSixAxisSensor(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto flags{rp.Pop<u32>()}; - LOG_WARNING(Service_HID, "(STUBBED) called. flags={}", flags); + struct Parameters { + Controller_NPad::DeviceHandle sixaxis_handle{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + }; + + const auto parameters{rp.PopRaw<Parameters>()}; + + applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(true); + + LOG_DEBUG(Service_HID, + "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", + parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, + parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } -void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) { +void Hid::DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto unknown{rp.Pop<u32>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; + struct Parameters { + Controller_NPad::DeviceHandle sixaxis_handle{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + }; - LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", unknown, - applet_resource_user_id); + const auto parameters{rp.PopRaw<Parameters>()}; + + applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(false); + + LOG_DEBUG(Service_HID, + "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", + parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, + parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); - applet_resource->ActivateController(HidController::Gesture); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } -void Hid::ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) { - // Should have no effect with how our npad sets up the data +void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto unknown{rp.Pop<u32>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; + struct Parameters { + Controller_NPad::DeviceHandle sixaxis_handle{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + }; - LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", unknown, - applet_resource_user_id); + const auto parameters{rp.PopRaw<Parameters>()}; + + applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(true); + + LOG_DEBUG(Service_HID, + "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", + parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, + parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); - applet_resource->ActivateController(HidController::NPad); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } -void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) { +void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto handle{rp.Pop<u32>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; + struct Parameters { + Controller_NPad::DeviceHandle sixaxis_handle{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + }; - LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle, - applet_resource_user_id); + const auto parameters{rp.PopRaw<Parameters>()}; + + applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(false); + + LOG_DEBUG(Service_HID, + "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", + parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, + parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } -void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) { +void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto handle{rp.Pop<u32>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; + struct Parameters { + bool enable_sixaxis_sensor_fusion{}; + INSERT_PADDING_BYTES(3); + Controller_NPad::DeviceHandle sixaxis_handle{}; + u64 applet_resource_user_id{}; + }; - LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle, - applet_resource_user_id); + const auto parameters{rp.PopRaw<Parameters>()}; + + LOG_WARNING(Service_HID, + "(STUBBED) called, enable_sixaxis_sensor_fusion={}, npad_type={}, npad_id={}, " + "device_index={}, applet_resource_user_id={}", + parameters.enable_sixaxis_sensor_fusion, parameters.sixaxis_handle.npad_type, + parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index, + parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -460,14 +536,17 @@ void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) { void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto handle{rp.Pop<u32>()}; - const auto drift_mode{rp.Pop<u32>()}; + const auto sixaxis_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()}; + const auto drift_mode{rp.PopEnum<Controller_NPad::GyroscopeZeroDriftMode>()}; const auto applet_resource_user_id{rp.Pop<u64>()}; applet_resource->GetController<Controller_NPad>(HidController::NPad) - .SetGyroscopeZeroDriftMode(Controller_NPad::GyroscopeZeroDriftMode{drift_mode}); + .SetGyroscopeZeroDriftMode(drift_mode); - LOG_DEBUG(Service_HID, "called, handle={}, drift_mode={}, applet_resource_user_id={}", handle, + LOG_DEBUG(Service_HID, + "called, npad_type={}, npad_id={}, device_index={}, drift_mode={}, " + "applet_resource_user_id={}", + sixaxis_handle.npad_type, sixaxis_handle.npad_id, sixaxis_handle.device_index, drift_mode, applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; @@ -476,29 +555,42 @@ void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { void Hid::GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto handle{rp.Pop<u32>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; + struct Parameters { + Controller_NPad::DeviceHandle sixaxis_handle{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + }; + + const auto parameters{rp.PopRaw<Parameters>()}; - LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle, - applet_resource_user_id); + LOG_DEBUG(Service_HID, + "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", + parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, + parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push<u32>( - static_cast<u32>(applet_resource->GetController<Controller_NPad>(HidController::NPad) - .GetGyroscopeZeroDriftMode())); + rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad) + .GetGyroscopeZeroDriftMode()); } void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto handle{rp.Pop<u32>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; + struct Parameters { + Controller_NPad::DeviceHandle sixaxis_handle{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + }; + + const auto parameters{rp.PopRaw<Parameters>()}; applet_resource->GetController<Controller_NPad>(HidController::NPad) .SetGyroscopeZeroDriftMode(Controller_NPad::GyroscopeZeroDriftMode::Standard); - LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle, - applet_resource_user_id); + LOG_DEBUG(Service_HID, + "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", + parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, + parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -506,11 +598,18 @@ void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto handle{rp.Pop<u32>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; + struct Parameters { + Controller_NPad::DeviceHandle sixaxis_handle{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + }; + + const auto parameters{rp.PopRaw<Parameters>()}; - LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle, - applet_resource_user_id); + LOG_DEBUG(Service_HID, + "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", + parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, + parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); @@ -518,15 +617,34 @@ void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) { .IsSixAxisSensorAtRest()); } +void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + struct Parameters { + u32 unknown{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + }; + + const auto parameters{rp.PopRaw<Parameters>()}; + + applet_resource->ActivateController(HidController::Gesture); + + LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", parameters.unknown, + parameters.applet_resource_user_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + void Hid::SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto supported_styleset{rp.Pop<u32>()}; - LOG_DEBUG(Service_HID, "called, supported_styleset={}", supported_styleset); - applet_resource->GetController<Controller_NPad>(HidController::NPad) .SetSupportedStyleSet({supported_styleset}); + LOG_DEBUG(Service_HID, "called, supported_styleset={}", supported_styleset); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -537,21 +655,22 @@ void Hid::GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); - IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push<u32>(controller.GetSupportedStyleSet().raw); + rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad) + .GetSupportedStyleSet() + .raw); } void Hid::SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; + applet_resource->GetController<Controller_NPad>(HidController::NPad) + .SetSupportedNpadIdTypes(ctx.ReadBuffer().data(), ctx.GetReadBufferSize()); + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - applet_resource->GetController<Controller_NPad>(HidController::NPad) - .SetSupportedNPadIdTypes(ctx.ReadBuffer().data(), ctx.GetReadBufferSize()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -560,48 +679,62 @@ void Hid::ActivateNpad(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; + applet_resource->ActivateController(HidController::NPad); + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - applet_resource->ActivateController(HidController::NPad); } void Hid::DeactivateNpad(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; + applet_resource->DeactivateController(HidController::NPad); + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - applet_resource->DeactivateController(HidController::NPad); } void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto npad_id{rp.Pop<u32>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; - const auto unknown{rp.Pop<u64>()}; + struct Parameters { + u32 npad_id{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + u64 unknown{}; + }; - LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}, unknown={}", npad_id, - applet_resource_user_id, unknown); + const auto parameters{rp.PopRaw<Parameters>()}; + + LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}, unknown={}", + parameters.npad_id, parameters.applet_resource_user_id, parameters.unknown); IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(RESULT_SUCCESS); rb.PushCopyObjects(applet_resource->GetController<Controller_NPad>(HidController::NPad) - .GetStyleSetChangedEvent(npad_id)); + .GetStyleSetChangedEvent(parameters.npad_id)); } void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto npad_id{rp.Pop<u32>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; + struct Parameters { + u32 npad_id{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + }; + + const auto parameters{rp.PopRaw<Parameters>()}; + + applet_resource->GetController<Controller_NPad>(HidController::NPad) + .DisconnectNpad(parameters.npad_id); - LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id, - applet_resource_user_id); + LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, + parameters.applet_resource_user_id); - applet_resource->GetController<Controller_NPad>(HidController::NPad).DisconnectNPad(npad_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -614,22 +747,41 @@ void Hid::GetPlayerLedPattern(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); - rb.PushRaw<u64>(applet_resource->GetController<Controller_NPad>(HidController::NPad) - .GetLedPattern(npad_id) - .raw); + rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad) + .GetLedPattern(npad_id) + .raw); +} + +void Hid::ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) { + // Should have no effect with how our npad sets up the data + IPC::RequestParser rp{ctx}; + struct Parameters { + u32 unknown{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + }; + + const auto parameters{rp.PopRaw<Parameters>()}; + + applet_resource->ActivateController(HidController::NPad); + + LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", parameters.unknown, + parameters.applet_resource_user_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); } void Hid::SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; - const auto hold_type{rp.Pop<u64>()}; + const auto hold_type{rp.PopEnum<Controller_NPad::NpadHoldType>()}; + + applet_resource->GetController<Controller_NPad>(HidController::NPad).SetHoldType(hold_type); LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, hold_type={}", applet_resource_user_id, hold_type); - auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); - controller.SetHoldType(Controller_NPad::NpadHoldType{hold_type}); - IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -640,22 +792,26 @@ void Hid::GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - const auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); - rb.Push<u64>(static_cast<u64>(controller.GetHoldType())); + rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad).GetHoldType()); } void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto npad_id{rp.Pop<u32>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; + struct Parameters { + u32 npad_id{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + }; - LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", npad_id, - applet_resource_user_id); + const auto parameters{rp.PopRaw<Parameters>()}; + + applet_resource->GetController<Controller_NPad>(HidController::NPad) + .SetNpadMode(parameters.npad_id, Controller_NPad::NpadAssignments::Single); - auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); - controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Single); + LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", + parameters.npad_id, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -664,16 +820,22 @@ void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) { // TODO: Check the differences between this and SetNpadJoyAssignmentModeSingleByDefault IPC::RequestParser rp{ctx}; - const auto npad_id{rp.Pop<u32>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; - const auto npad_joy_device_type{rp.Pop<u64>()}; + struct Parameters { + u32 npad_id{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + u64 npad_joy_device_type{}; + }; + + const auto parameters{rp.PopRaw<Parameters>()}; + + applet_resource->GetController<Controller_NPad>(HidController::NPad) + .SetNpadMode(parameters.npad_id, Controller_NPad::NpadAssignments::Single); LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", - npad_id, applet_resource_user_id, npad_joy_device_type); - - auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); - controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Single); + parameters.npad_id, parameters.applet_resource_user_id, + parameters.npad_joy_device_type); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -681,14 +843,19 @@ void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) { void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto npad_id{rp.Pop<u32>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; + struct Parameters { + u32 npad_id{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + }; + + const auto parameters{rp.PopRaw<Parameters>()}; - LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id, - applet_resource_user_id); + applet_resource->GetController<Controller_NPad>(HidController::NPad) + .SetNpadMode(parameters.npad_id, Controller_NPad::NpadAssignments::Dual); - auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); - controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Dual); + LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", + parameters.npad_id, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -700,12 +867,12 @@ void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) { const auto npad_id_2{rp.Pop<u32>()}; const auto applet_resource_user_id{rp.Pop<u64>()}; + applet_resource->GetController<Controller_NPad>(HidController::NPad) + .MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2); + LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", npad_id_1, npad_id_2, applet_resource_user_id); - auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); - controller.MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2); - IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -714,9 +881,9 @@ void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; + applet_resource->GetController<Controller_NPad>(HidController::NPad).StartLRAssignmentMode(); + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); - controller.StartLRAssignmentMode(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -726,9 +893,9 @@ void Hid::StopLrAssignmentMode(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; + applet_resource->GetController<Controller_NPad>(HidController::NPad).StopLRAssignmentMode(); + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); - controller.StopLRAssignmentMode(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -737,13 +904,13 @@ void Hid::StopLrAssignmentMode(Kernel::HLERequestContext& ctx) { void Hid::SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; - const auto mode{rp.Pop<u64>()}; - - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, mode={}", applet_resource_user_id, - mode); + const auto activation_mode{rp.PopEnum<Controller_NPad::NpadHandheldActivationMode>()}; applet_resource->GetController<Controller_NPad>(HidController::NPad) - .SetNpadHandheldActivationMode(Controller_NPad::NpadHandheldActivationMode{mode}); + .SetNpadHandheldActivationMode(activation_mode); + + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, activation_mode={}", + applet_resource_user_id, activation_mode); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -757,23 +924,24 @@ void Hid::GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); - rb.Push<u64>( - static_cast<u64>(applet_resource->GetController<Controller_NPad>(HidController::NPad) - .GetNpadHandheldActivationMode())); + rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad) + .GetNpadHandheldActivationMode()); } void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto npad_1{rp.Pop<u32>()}; - const auto npad_2{rp.Pop<u32>()}; + const auto npad_id_1{rp.Pop<u32>()}; + const auto npad_id_2{rp.Pop<u32>()}; const auto applet_resource_user_id{rp.Pop<u64>()}; - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, npad_1={}, npad_2={}", - applet_resource_user_id, npad_1, npad_2); + const bool res = applet_resource->GetController<Controller_NPad>(HidController::NPad) + .SwapNpadAssignment(npad_id_1, npad_id_2); + + LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", + npad_id_1, npad_id_2, applet_resource_user_id); - auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); IPC::ResponseBuilder rb{ctx, 2}; - if (controller.SwapNpadAssignment(npad_1, npad_2)) { + if (res) { rb.Push(RESULT_SUCCESS); } else { LOG_ERROR(Service_HID, "Npads are not connected!"); @@ -781,61 +949,99 @@ void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) { } } -void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) { +void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto applet_resource_user_id{rp.Pop<u64>()}; - - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + struct Parameters { + u32 npad_id{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + }; - applet_resource->GetController<Controller_NPad>(HidController::NPad).SetVibrationEnabled(true); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); -} + const auto parameters{rp.PopRaw<Parameters>()}; -void Hid::EndPermitVibrationSession(Kernel::HLERequestContext& ctx) { - LOG_DEBUG(Service_HID, "called"); + LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", + parameters.npad_id, parameters.applet_resource_user_id); - applet_resource->GetController<Controller_NPad>(HidController::NPad).SetVibrationEnabled(false); - IPC::ResponseBuilder rb{ctx, 2}; + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); + rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad) + .IsUnintendedHomeButtonInputProtectionEnabled(parameters.npad_id)); } -void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { +void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto controller_id{rp.Pop<u32>()}; - const auto vibration_values{rp.PopRaw<Controller_NPad::Vibration>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; + struct Parameters { + bool unintended_home_button_input_protection{}; + INSERT_PADDING_BYTES(3); + u32 npad_id{}; + u64 applet_resource_user_id{}; + }; + + const auto parameters{rp.PopRaw<Parameters>()}; - LOG_DEBUG(Service_HID, "called, controller_id={}, applet_resource_user_id={}", controller_id, - applet_resource_user_id); + applet_resource->GetController<Controller_NPad>(HidController::NPad) + .SetUnintendedHomeButtonInputProtectionEnabled( + parameters.unintended_home_button_input_protection, parameters.npad_id); + + LOG_WARNING(Service_HID, + "(STUBBED) called, unintended_home_button_input_protection={}, npad_id={}," + "applet_resource_user_id={}", + parameters.unintended_home_button_input_protection, parameters.npad_id, + parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - - applet_resource->GetController<Controller_NPad>(HidController::NPad) - .VibrateController({controller_id}, {vibration_values}); } -void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { +void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto applet_resource_user_id{rp.Pop<u64>()}; + const auto vibration_device_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()}; + + VibrationDeviceInfo vibration_device_info; + + vibration_device_info.type = VibrationDeviceType::LinearResonantActuator; + + switch (vibration_device_handle.device_index) { + case Controller_NPad::DeviceIndex::Left: + vibration_device_info.position = VibrationDevicePosition::Left; + break; + case Controller_NPad::DeviceIndex::Right: + vibration_device_info.position = VibrationDevicePosition::Right; + break; + case Controller_NPad::DeviceIndex::None: + default: + UNREACHABLE_MSG("DeviceIndex should never be None!"); + vibration_device_info.position = VibrationDevicePosition::None; + break; + } - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + LOG_DEBUG(Service_HID, "called, vibration_device_type={}, vibration_device_position={}", + vibration_device_info.type, vibration_device_info.position); - const auto controllers = ctx.ReadBuffer(0); - const auto vibrations = ctx.ReadBuffer(1); + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw(vibration_device_info); +} - std::vector<u32> controller_list(controllers.size() / sizeof(u32)); - std::vector<Controller_NPad::Vibration> vibration_list(vibrations.size() / - sizeof(Controller_NPad::Vibration)); +void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + struct Parameters { + Controller_NPad::DeviceHandle vibration_device_handle{}; + Controller_NPad::VibrationValue vibration_value{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + }; - 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; }); + const auto parameters{rp.PopRaw<Parameters>()}; applet_resource->GetController<Controller_NPad>(HidController::NPad) - .VibrateController(controller_list, vibration_list); + .VibrateController(parameters.vibration_device_handle, parameters.vibration_value); + + LOG_DEBUG(Service_HID, + "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", + parameters.vibration_device_handle.npad_type, + parameters.vibration_device_handle.npad_id, + parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -843,25 +1049,24 @@ void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { void Hid::GetActualVibrationValue(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto controller_id{rp.Pop<u32>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; - - LOG_DEBUG(Service_HID, "called, controller_id={}, applet_resource_user_id={}", controller_id, - applet_resource_user_id); + struct Parameters { + Controller_NPad::DeviceHandle vibration_device_handle{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + }; - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(RESULT_SUCCESS); - rb.PushRaw<Controller_NPad::Vibration>( - applet_resource->GetController<Controller_NPad>(HidController::NPad).GetLastVibration()); -} + const auto parameters{rp.PopRaw<Parameters>()}; -void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { - LOG_DEBUG(Service_HID, "called"); + LOG_DEBUG(Service_HID, + "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", + parameters.vibration_device_handle.npad_type, + parameters.vibration_device_handle.npad_id, + parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); - IPC::ResponseBuilder rb{ctx, 4}; + IPC::ResponseBuilder rb{ctx, 6}; rb.Push(RESULT_SUCCESS); - rb.Push<u32>(1); - rb.Push<u32>(0); + rb.PushRaw(applet_resource->GetController<Controller_NPad>(HidController::NPad) + .GetLastVibration(parameters.vibration_device_handle)); } void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { @@ -869,13 +1074,14 @@ void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IActiveVibrationDeviceList>(); + rb.PushIpcInterface<IActiveVibrationDeviceList>(system, applet_resource); } void Hid::PermitVibration(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto can_vibrate{rp.Pop<bool>()}; - Settings::values.vibration_enabled = can_vibrate; + + Settings::values.vibration_enabled.SetValue(can_vibrate); LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate); @@ -888,7 +1094,76 @@ void Hid::IsVibrationPermitted(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push(Settings::values.vibration_enabled); + rb.Push(Settings::values.vibration_enabled.GetValue()); +} + +void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto applet_resource_user_id{rp.Pop<u64>()}; + + const auto handles = ctx.ReadBuffer(0); + const auto vibrations = ctx.ReadBuffer(1); + + std::vector<Controller_NPad::DeviceHandle> vibration_device_handles( + handles.size() / sizeof(Controller_NPad::DeviceHandle)); + std::vector<Controller_NPad::VibrationValue> vibration_values( + vibrations.size() / sizeof(Controller_NPad::VibrationValue)); + + std::memcpy(vibration_device_handles.data(), handles.data(), handles.size()); + std::memcpy(vibration_values.data(), vibrations.data(), vibrations.size()); + + applet_resource->GetController<Controller_NPad>(HidController::NPad) + .VibrateControllers(vibration_device_handles, vibration_values); + + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto applet_resource_user_id{rp.Pop<u64>()}; + + applet_resource->GetController<Controller_NPad>(HidController::NPad) + .SetPermitVibrationSession(true); + + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void Hid::EndPermitVibrationSession(Kernel::HLERequestContext& ctx) { + applet_resource->GetController<Controller_NPad>(HidController::NPad) + .SetPermitVibrationSession(false); + + LOG_DEBUG(Service_HID, "called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void Hid::IsVibrationDeviceMounted(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + struct Parameters { + Controller_NPad::DeviceHandle vibration_device_handle{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + }; + + const auto parameters{rp.PopRaw<Parameters>()}; + + LOG_DEBUG(Service_HID, + "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", + parameters.vibration_device_handle.npad_type, + parameters.vibration_device_handle.npad_id, + parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad) + .IsVibrationDeviceMounted(parameters.vibration_device_handle)); } void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { @@ -904,11 +1179,19 @@ void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { void Hid::StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto handle{rp.Pop<u32>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; + struct Parameters { + Controller_NPad::DeviceHandle sixaxis_handle{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + }; - LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle, - applet_resource_user_id); + const auto parameters{rp.PopRaw<Parameters>()}; + + LOG_WARNING( + Service_HID, + "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", + parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, + parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -916,11 +1199,19 @@ void Hid::StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { void Hid::StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto handle{rp.Pop<u32>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; + struct Parameters { + Controller_NPad::DeviceHandle sixaxis_handle{}; + INSERT_PADDING_WORDS(1); + u64 applet_resource_user_id{}; + }; - LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle, - applet_resource_user_id); + const auto parameters{rp.PopRaw<Parameters>()}; + + LOG_WARNING( + Service_HID, + "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", + parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, + parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -1011,9 +1302,37 @@ void Hid::SetPalmaBoostMode(Kernel::HLERequestContext& ctx) { rb.Push(RESULT_SUCCESS); } +void Hid::SetNpadCommunicationMode(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto applet_resource_user_id{rp.Pop<u64>()}; + const auto communication_mode{rp.PopEnum<Controller_NPad::NpadCommunicationMode>()}; + + applet_resource->GetController<Controller_NPad>(HidController::NPad) + .SetNpadCommunicationMode(communication_mode); + + LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, communication_mode={}", + applet_resource_user_id, communication_mode); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void Hid::GetNpadCommunicationMode(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto applet_resource_user_id{rp.Pop<u64>()}; + + LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", + applet_resource_user_id); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad) + .GetNpadCommunicationMode()); +} + class HidDbg final : public ServiceFramework<HidDbg> { public: - explicit HidDbg() : ServiceFramework{"hid:dbg"} { + explicit HidDbg(Core::System& system_) : ServiceFramework{system_, "hid:dbg"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "DeactivateDebugPad"}, @@ -1140,7 +1459,7 @@ public: class HidSys final : public ServiceFramework<HidSys> { public: - explicit HidSys() : ServiceFramework{"hid:sys"} { + explicit HidSys(Core::System& system_) : ServiceFramework{system_, "hid:sys"} { // clang-format off static const FunctionInfo functions[] = { {31, nullptr, "SendKeyboardLockKeyEvent"}, @@ -1274,7 +1593,7 @@ public: class HidTmp final : public ServiceFramework<HidTmp> { public: - explicit HidTmp() : ServiceFramework{"hid:tmp"} { + explicit HidTmp(Core::System& system_) : ServiceFramework{system_, "hid:tmp"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetConsoleSixAxisSensorCalibrationValues"}, @@ -1287,7 +1606,7 @@ public: class HidBus final : public ServiceFramework<HidBus> { public: - explicit HidBus() : ServiceFramework{"hidbus"} { + explicit HidBus(Core::System& system_) : ServiceFramework{system_, "hidbus"} { // clang-format off static const FunctionInfo functions[] = { {1, nullptr, "GetBusHandle"}, @@ -1317,15 +1636,15 @@ void ReloadInputDevices() { void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { std::make_shared<Hid>(system)->InstallAsService(service_manager); - std::make_shared<HidBus>()->InstallAsService(service_manager); - std::make_shared<HidDbg>()->InstallAsService(service_manager); - std::make_shared<HidSys>()->InstallAsService(service_manager); - std::make_shared<HidTmp>()->InstallAsService(service_manager); + std::make_shared<HidBus>(system)->InstallAsService(service_manager); + std::make_shared<HidDbg>(system)->InstallAsService(service_manager); + std::make_shared<HidSys>(system)->InstallAsService(service_manager); + std::make_shared<HidTmp>(system)->InstallAsService(service_manager); std::make_shared<IRS>(system)->InstallAsService(service_manager); - std::make_shared<IRS_SYS>()->InstallAsService(service_manager); + std::make_shared<IRS_SYS>(system)->InstallAsService(service_manager); - std::make_shared<XCD_SYS>()->InstallAsService(service_manager); + std::make_shared<XCD_SYS>(system)->InstallAsService(service_manager); } } // namespace Service::HID diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index e04aaf1e9..b87bfdde1 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -41,7 +41,7 @@ enum class HidController : std::size_t { class IAppletResource final : public ServiceFramework<IAppletResource> { public: - explicit IAppletResource(Core::System& system); + explicit IAppletResource(Core::System& system_); ~IAppletResource() override; void ActivateController(HidController controller); @@ -65,11 +65,12 @@ private: void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx); void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); + void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); std::shared_ptr<Kernel::SharedMemory> shared_mem; std::shared_ptr<Core::Timing::EventType> pad_update_event; - Core::System& system; + std::shared_ptr<Core::Timing::EventType> motion_update_event; std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)> controllers{}; @@ -77,30 +78,30 @@ private: class Hid final : public ServiceFramework<Hid> { public: - explicit Hid(Core::System& system); + explicit Hid(Core::System& system_); ~Hid() override; std::shared_ptr<IAppletResource> GetAppletResource(); private: void CreateAppletResource(Kernel::HLERequestContext& ctx); - void ActivateXpad(Kernel::HLERequestContext& ctx); - void GetXpadIDs(Kernel::HLERequestContext& ctx); - void ActivateSixAxisSensor(Kernel::HLERequestContext& ctx); - void DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx); void ActivateDebugPad(Kernel::HLERequestContext& ctx); void ActivateTouchScreen(Kernel::HLERequestContext& ctx); void ActivateMouse(Kernel::HLERequestContext& ctx); void ActivateKeyboard(Kernel::HLERequestContext& ctx); void SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx); - void ActivateGesture(Kernel::HLERequestContext& ctx); - void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx); + void ActivateXpad(Kernel::HLERequestContext& ctx); + void GetXpadIDs(Kernel::HLERequestContext& ctx); + void ActivateSixAxisSensor(Kernel::HLERequestContext& ctx); + void DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx); void StartSixAxisSensor(Kernel::HLERequestContext& ctx); void StopSixAxisSensor(Kernel::HLERequestContext& ctx); + void EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx); void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); void GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); void ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx); + void ActivateGesture(Kernel::HLERequestContext& ctx); void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx); void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx); void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx); @@ -109,6 +110,7 @@ private: void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx); void DisconnectNpad(Kernel::HLERequestContext& ctx); void GetPlayerLedPattern(Kernel::HLERequestContext& ctx); + void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx); void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx); void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx); void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx); @@ -120,15 +122,18 @@ private: void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx); void GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx); void SwapNpadAssignment(Kernel::HLERequestContext& ctx); - void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx); - void EndPermitVibrationSession(Kernel::HLERequestContext& ctx); + void IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx); + void EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx); + void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx); void SendVibrationValue(Kernel::HLERequestContext& ctx); - void SendVibrationValues(Kernel::HLERequestContext& ctx); void GetActualVibrationValue(Kernel::HLERequestContext& ctx); - void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx); void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx); void PermitVibration(Kernel::HLERequestContext& ctx); void IsVibrationPermitted(Kernel::HLERequestContext& ctx); + void SendVibrationValues(Kernel::HLERequestContext& ctx); + void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx); + void EndPermitVibrationSession(Kernel::HLERequestContext& ctx); + void IsVibrationDeviceMounted(Kernel::HLERequestContext& ctx); void ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); void StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); void StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); @@ -140,9 +145,26 @@ private: void ResetSevenSixAxisSensorTimestamp(Kernel::HLERequestContext& ctx); void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx); void SetPalmaBoostMode(Kernel::HLERequestContext& ctx); + void SetNpadCommunicationMode(Kernel::HLERequestContext& ctx); + void GetNpadCommunicationMode(Kernel::HLERequestContext& ctx); + + enum class VibrationDeviceType : u32 { + LinearResonantActuator = 1, + }; + + enum class VibrationDevicePosition : u32 { + None = 0, + Left = 1, + Right = 2, + }; + + struct VibrationDeviceInfo { + VibrationDeviceType type{}; + VibrationDevicePosition position{}; + }; + static_assert(sizeof(VibrationDeviceInfo) == 0x8, "VibrationDeviceInfo has incorrect size."); std::shared_ptr<IAppletResource> applet_resource; - Core::System& system; }; /// Reload input devices. Used when input configuration changed diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp index e82fd031b..c8413099f 100644 --- a/src/core/hle/service/hid/irs.cpp +++ b/src/core/hle/service/hid/irs.cpp @@ -12,7 +12,7 @@ namespace Service::HID { -IRS::IRS(Core::System& system) : ServiceFramework{"irs"}, system(system) { +IRS::IRS(Core::System& system_) : ServiceFramework{system_, "irs"} { // clang-format off static const FunctionInfo functions[] = { {302, &IRS::ActivateIrsensor, "ActivateIrsensor"}, @@ -175,7 +175,7 @@ void IRS::ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx) { IRS::~IRS() = default; -IRS_SYS::IRS_SYS() : ServiceFramework{"irs:sys"} { +IRS_SYS::IRS_SYS(Core::System& system_) : ServiceFramework{system_, "irs:sys"} { // clang-format off static const FunctionInfo functions[] = { {500, nullptr, "SetAppletResourceUserId"}, diff --git a/src/core/hle/service/hid/irs.h b/src/core/hle/service/hid/irs.h index 8918ad6ca..be0c486ba 100644 --- a/src/core/hle/service/hid/irs.h +++ b/src/core/hle/service/hid/irs.h @@ -7,6 +7,10 @@ #include "core/hle/kernel/object.h" #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Kernel { class SharedMemory; } @@ -15,7 +19,7 @@ namespace Service::HID { class IRS final : public ServiceFramework<IRS> { public: - explicit IRS(Core::System& system); + explicit IRS(Core::System& system_); ~IRS() override; private: @@ -37,14 +41,14 @@ private: void RunIrLedProcessor(Kernel::HLERequestContext& ctx); void StopImageProcessorAsync(Kernel::HLERequestContext& ctx); void ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx); + std::shared_ptr<Kernel::SharedMemory> shared_mem; const u32 device_handle{0xABCD}; - Core::System& system; }; class IRS_SYS final : public ServiceFramework<IRS_SYS> { public: - explicit IRS_SYS(); + explicit IRS_SYS(Core::System& system); ~IRS_SYS() override; }; diff --git a/src/core/hle/service/hid/xcd.cpp b/src/core/hle/service/hid/xcd.cpp index c8e9125f6..43a8840d0 100644 --- a/src/core/hle/service/hid/xcd.cpp +++ b/src/core/hle/service/hid/xcd.cpp @@ -6,7 +6,7 @@ namespace Service::HID { -XCD_SYS::XCD_SYS() : ServiceFramework{"xcd:sys"} { +XCD_SYS::XCD_SYS(Core::System& system_) : ServiceFramework{system_, "xcd:sys"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetDataFormat"}, diff --git a/src/core/hle/service/hid/xcd.h b/src/core/hle/service/hid/xcd.h index fd506d303..54932c228 100644 --- a/src/core/hle/service/hid/xcd.h +++ b/src/core/hle/service/hid/xcd.h @@ -6,11 +6,15 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::HID { class XCD_SYS final : public ServiceFramework<XCD_SYS> { public: - explicit XCD_SYS(); + explicit XCD_SYS(Core::System& system_); ~XCD_SYS() override; }; |