core/hid: Remove usage of native types, fix a couple of errors with motion

This commit is contained in:
german77 2021-11-08 20:28:09 -06:00 committed by Narr the Reg
parent a17550be98
commit 71f9b90dd9
11 changed files with 631 additions and 427 deletions

View File

@ -152,7 +152,7 @@ void EmulatedConsole::SetMotion(Common::Input::CallbackStatus callback) {
motion.rotation = emulated.GetGyroscope(); motion.rotation = emulated.GetGyroscope();
motion.orientation = emulated.GetOrientation(); motion.orientation = emulated.GetOrientation();
motion.quaternion = emulated.GetQuaternion(); motion.quaternion = emulated.GetQuaternion();
motion.is_at_rest = emulated.IsMoving(motion_sensitivity); motion.is_at_rest = !emulated.IsMoving(motion_sensitivity);
TriggerOnChange(ConsoleTriggerType::Motion); TriggerOnChange(ConsoleTriggerType::Motion);
} }

View File

@ -347,7 +347,7 @@ void EmulatedController::RestoreConfig() {
} }
std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices( std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices(
DeviceIndex device_index) const { EmulatedDeviceIndex device_index) const {
std::vector<Common::ParamPackage> devices; std::vector<Common::ParamPackage> devices;
for (const auto& param : button_params) { for (const auto& param : button_params) {
if (!param.Has("engine")) { if (!param.Has("engine")) {
@ -704,7 +704,7 @@ void EmulatedController::SetMotion(Common::Input::CallbackStatus callback, std::
motion.gyro = emulated.GetGyroscope(); motion.gyro = emulated.GetGyroscope();
motion.rotation = emulated.GetRotations(); motion.rotation = emulated.GetRotations();
motion.orientation = emulated.GetOrientation(); motion.orientation = emulated.GetOrientation();
motion.is_at_rest = emulated.IsMoving(motion_sensitivity); motion.is_at_rest = !emulated.IsMoving(motion_sensitivity);
TriggerOnChange(ControllerTriggerType::Motion, true); TriggerOnChange(ControllerTriggerType::Motion, true);
} }

View File

@ -81,7 +81,7 @@ struct ControllerMotion {
bool is_at_rest{}; bool is_at_rest{};
}; };
enum DeviceIndex : u8 { enum EmulatedDeviceIndex : u8 {
LeftIndex, LeftIndex,
RightIndex, RightIndex,
DualIndex, DualIndex,
@ -202,7 +202,7 @@ public:
void RestoreConfig(); void RestoreConfig();
/// Returns a vector of mapped devices from the mapped button and stick parameters /// Returns a vector of mapped devices from the mapped button and stick parameters
std::vector<Common::ParamPackage> GetMappedDevices(DeviceIndex device_index) const; std::vector<Common::ParamPackage> GetMappedDevices(EmulatedDeviceIndex device_index) const;
// Returns the current mapped button device // Returns the current mapped button device
Common::ParamPackage GetButtonParam(std::size_t index) const; Common::ParamPackage GetButtonParam(std::size_t index) const;

View File

@ -13,7 +13,7 @@
namespace Core::HID { namespace Core::HID {
// This is nn::hid::NpadIdType // This is nn::hid::NpadIdType
enum class NpadIdType : u8 { enum class NpadIdType : u32 {
Player1 = 0x0, Player1 = 0x0,
Player2 = 0x1, Player2 = 0x1,
Player3 = 0x2, Player3 = 0x2,
@ -25,7 +25,7 @@ enum class NpadIdType : u8 {
Other = 0x10, Other = 0x10,
Handheld = 0x20, Handheld = 0x20,
Invalid = 0xFF, Invalid = 0xFFFFFFFF,
}; };
/// Converts a NpadIdType to an array index. /// Converts a NpadIdType to an array index.
@ -104,10 +104,30 @@ enum class NpadStyleIndex : u8 {
MaxNpadType = 34, MaxNpadType = 34,
}; };
// This is nn::hid::NpadStyleSet
enum class NpadStyleSet : u32 {
None = 0,
Fullkey = 1U << 0,
Handheld = 1U << 1,
JoyDual = 1U << 2,
JoyLeft = 1U << 3,
JoyRight = 1U << 4,
Gc = 1U << 5,
Palma = 1U << 6,
Lark = 1U << 7,
HandheldLark = 1U << 8,
Lucia = 1U << 9,
Lagoon = 1U << 10,
Lager = 1U << 11,
SystemExt = 1U << 29,
System = 1U << 30,
};
static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size");
// This is nn::hid::NpadStyleTag // This is nn::hid::NpadStyleTag
struct NpadStyleTag { struct NpadStyleTag {
union { union {
u32 raw{}; NpadStyleSet raw{};
BitField<0, 1, u32> fullkey; BitField<0, 1, u32> fullkey;
BitField<1, 1, u32> handheld; BitField<1, 1, u32> handheld;
@ -322,6 +342,47 @@ struct DebugPadButton {
}; };
static_assert(sizeof(DebugPadButton) == 0x4, "DebugPadButton is an invalid size"); static_assert(sizeof(DebugPadButton) == 0x4, "DebugPadButton is an invalid size");
enum class DeviceIndex : u8 {
Left = 0,
Right = 1,
None = 2,
MaxDeviceIndex = 3,
};
// This is nn::hid::ConsoleSixAxisSensorHandle
struct ConsoleSixAxisSensorHandle {
u8 unknown_1;
u8 unknown_2;
INSERT_PADDING_BYTES_NOINIT(2);
};
static_assert(sizeof(ConsoleSixAxisSensorHandle) == 4,
"ConsoleSixAxisSensorHandle is an invalid size");
// This is nn::hid::SixAxisSensorHandle
struct SixAxisSensorHandle {
NpadStyleIndex npad_type;
u8 npad_id;
DeviceIndex device_index;
INSERT_PADDING_BYTES_NOINIT(1);
};
static_assert(sizeof(SixAxisSensorHandle) == 4, "SixAxisSensorHandle is an invalid size");
struct SixAxisSensorFusionParameters {
f32 parameter1;
f32 parameter2;
};
static_assert(sizeof(SixAxisSensorFusionParameters) == 8,
"SixAxisSensorFusionParameters is an invalid size");
// This is nn::hid::VibrationDeviceHandle
struct VibrationDeviceHandle {
NpadStyleIndex npad_type;
u8 npad_id;
DeviceIndex device_index;
INSERT_PADDING_BYTES_NOINIT(1);
};
static_assert(sizeof(VibrationDeviceHandle) == 4, "SixAxisSensorHandle is an invalid size");
// This is nn::hid::VibrationDeviceType // This is nn::hid::VibrationDeviceType
enum class VibrationDeviceType : u32 { enum class VibrationDeviceType : u32 {
Unknown = 0, Unknown = 0,

View File

@ -12,6 +12,7 @@
#include "core/frontend/applets/controller.h" #include "core/frontend/applets/controller.h"
#include "core/hid/emulated_controller.h" #include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h" #include "core/hid/hid_core.h"
#include "core/hid/hid_types.h"
#include "core/hle/result.h" #include "core/hle/result.h"
#include "core/hle/service/am/am.h" #include "core/hle/service/am/am.h"
#include "core/hle/service/am/applets/applet_controller.h" #include "core/hle/service/am/applets/applet_controller.h"

View File

@ -16,6 +16,10 @@ namespace Core {
class System; class System;
} }
namespace Core::HID {
enum class NpadStyleSet : u32;
}
namespace Service::AM::Applets { namespace Service::AM::Applets {
using IdentificationColor = std::array<u8, 4>; using IdentificationColor = std::array<u8, 4>;
@ -52,7 +56,7 @@ struct ControllerSupportArgPrivate {
bool flag_1{}; bool flag_1{};
ControllerSupportMode mode{}; ControllerSupportMode mode{};
ControllerSupportCaller caller{}; ControllerSupportCaller caller{};
u32 style_set{}; Core::HID::NpadStyleSet style_set{};
u32 joy_hold_type{}; u32 joy_hold_type{};
}; };
static_assert(sizeof(ControllerSupportArgPrivate) == 0x14, static_assert(sizeof(ControllerSupportArgPrivate) == 0x14,

View File

@ -21,68 +21,25 @@
namespace Service::HID { namespace Service::HID {
constexpr std::size_t NPAD_OFFSET = 0x9A00; constexpr std::size_t NPAD_OFFSET = 0x9A00;
constexpr u32 MAX_NPAD_ID = 7; constexpr std::array<Core::HID::NpadIdType, 10> npad_id_list{
constexpr std::size_t HANDHELD_INDEX = 8; Core::HID::NpadIdType::Player1, Core::HID::NpadIdType::Player2, Core::HID::NpadIdType::Player3,
constexpr std::array<u32, 10> npad_id_list{ Core::HID::NpadIdType::Player4, Core::HID::NpadIdType::Player5, Core::HID::NpadIdType::Player6,
0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN, Core::HID::NpadIdType::Player7, Core::HID::NpadIdType::Player8, Core::HID::NpadIdType::Other,
Core::HID::NpadIdType::Handheld,
}; };
std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) { bool Controller_NPad::IsNpadIdValid(Core::HID::NpadIdType npad_id) {
switch (npad_id) { switch (npad_id) {
case 0: case Core::HID::NpadIdType::Player1:
case 1: case Core::HID::NpadIdType::Player2:
case 2: case Core::HID::NpadIdType::Player3:
case 3: case Core::HID::NpadIdType::Player4:
case 4: case Core::HID::NpadIdType::Player5:
case 5: case Core::HID::NpadIdType::Player6:
case 6: case Core::HID::NpadIdType::Player7:
case 7: case Core::HID::NpadIdType::Player8:
return npad_id; case Core::HID::NpadIdType::Other:
case HANDHELD_INDEX: case Core::HID::NpadIdType::Handheld:
case NPAD_HANDHELD:
return HANDHELD_INDEX;
case 9:
case NPAD_UNKNOWN:
return 9;
default:
UNIMPLEMENTED_MSG("Unknown npad id {}", npad_id);
return 0;
}
}
u32 Controller_NPad::IndexToNPad(std::size_t index) {
switch (index) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
return static_cast<u32>(index);
case HANDHELD_INDEX:
return NPAD_HANDHELD;
case 9:
return NPAD_UNKNOWN;
default:
UNIMPLEMENTED_MSG("Unknown npad index {}", index);
return 0;
}
}
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; return true;
default: default:
LOG_ERROR(Service_HID, "Invalid npad id {}", npad_id); LOG_ERROR(Service_HID, "Invalid npad id {}", npad_id);
@ -90,10 +47,16 @@ bool Controller_NPad::IsNpadIdValid(u32 npad_id) {
} }
} }
bool Controller_NPad::IsDeviceHandleValid(const DeviceHandle& device_handle) { bool Controller_NPad::IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle) {
return IsNpadIdValid(device_handle.npad_id) && return IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id)) &&
device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType && device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType &&
device_handle.device_index < DeviceIndex::MaxDeviceIndex; device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
}
bool Controller_NPad::IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle& device_handle) {
return IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id)) &&
device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType &&
device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
} }
Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_, Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_,
@ -102,9 +65,9 @@ Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_,
for (std::size_t i = 0; i < controller_data.size(); ++i) { for (std::size_t i = 0; i < controller_data.size(); ++i) {
auto& controller = controller_data[i]; auto& controller = controller_data[i];
controller.device = hid_core.GetEmulatedControllerByIndex(i); controller.device = hid_core.GetEmulatedControllerByIndex(i);
controller.vibration[Core::HID::DeviceIndex::LeftIndex].latest_vibration_value = controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value =
DEFAULT_VIBRATION_VALUE; DEFAULT_VIBRATION_VALUE;
controller.vibration[Core::HID::DeviceIndex::RightIndex].latest_vibration_value = controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex].latest_vibration_value =
DEFAULT_VIBRATION_VALUE; DEFAULT_VIBRATION_VALUE;
Core::HID::ControllerUpdateCallback engine_callback{ Core::HID::ControllerUpdateCallback engine_callback{
.on_change = [this, .on_change = [this,
@ -130,17 +93,21 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx); ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx);
return; return;
} }
if (controller_idx >= controller_data.size()) {
return;
}
auto& controller = controller_data[controller_idx]; auto& controller = controller_data[controller_idx];
const auto is_connected = controller.device->IsConnected(); const auto is_connected = controller.device->IsConnected();
const auto npad_type = controller.device->GetNpadStyleIndex(); const auto npad_type = controller.device->GetNpadStyleIndex();
const auto npad_id = controller.device->GetNpadIdType();
switch (type) { switch (type) {
case Core::HID::ControllerTriggerType::Connected: case Core::HID::ControllerTriggerType::Connected:
case Core::HID::ControllerTriggerType::Disconnected: case Core::HID::ControllerTriggerType::Disconnected:
if (is_connected == controller.is_connected) { if (is_connected == controller.is_connected) {
return; return;
} }
UpdateControllerAt(npad_type, controller_idx, is_connected); UpdateControllerAt(npad_type, npad_id, is_connected);
break; break;
case Core::HID::ControllerTriggerType::Battery: { case Core::HID::ControllerTriggerType::Battery: {
if (!controller.is_connected) { if (!controller.is_connected) {
@ -158,15 +125,16 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
} }
} }
void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
auto& controller = controller_data[controller_idx]; LOG_DEBUG(Service_HID, "Npad connected {}", npad_id);
auto& controller = GetControllerFromNpadIdType(npad_id);
const auto controller_type = controller.device->GetNpadStyleIndex(); const auto controller_type = controller.device->GetNpadStyleIndex();
auto& shared_memory = controller.shared_memory_entry; auto& shared_memory = controller.shared_memory_entry;
if (controller_type == Core::HID::NpadStyleIndex::None) { if (controller_type == Core::HID::NpadStyleIndex::None) {
controller.styleset_changed_event->GetWritableEvent().Signal(); controller.styleset_changed_event->GetWritableEvent().Signal();
return; return;
} }
shared_memory.style_set.raw = 0; // Zero out shared_memory.style_tag.raw = Core::HID::NpadStyleSet::None;
shared_memory.device_type.raw = 0; shared_memory.device_type.raw = 0;
shared_memory.system_properties.raw = 0; shared_memory.system_properties.raw = 0;
switch (controller_type) { switch (controller_type) {
@ -174,7 +142,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
UNREACHABLE(); UNREACHABLE();
break; break;
case Core::HID::NpadStyleIndex::ProController: case Core::HID::NpadStyleIndex::ProController:
shared_memory.style_set.fullkey.Assign(1); shared_memory.style_tag.fullkey.Assign(1);
shared_memory.device_type.fullkey.Assign(1); shared_memory.device_type.fullkey.Assign(1);
shared_memory.system_properties.is_vertical.Assign(1); shared_memory.system_properties.is_vertical.Assign(1);
shared_memory.system_properties.use_plus.Assign(1); shared_memory.system_properties.use_plus.Assign(1);
@ -183,7 +151,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
shared_memory.applet_footer.type = AppletFooterUiType::SwitchProController; shared_memory.applet_footer.type = AppletFooterUiType::SwitchProController;
break; break;
case Core::HID::NpadStyleIndex::Handheld: case Core::HID::NpadStyleIndex::Handheld:
shared_memory.style_set.handheld.Assign(1); shared_memory.style_tag.handheld.Assign(1);
shared_memory.device_type.handheld_left.Assign(1); shared_memory.device_type.handheld_left.Assign(1);
shared_memory.device_type.handheld_right.Assign(1); shared_memory.device_type.handheld_right.Assign(1);
shared_memory.system_properties.is_vertical.Assign(1); shared_memory.system_properties.is_vertical.Assign(1);
@ -193,7 +161,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
shared_memory.applet_footer.type = AppletFooterUiType::HandheldJoyConLeftJoyConRight; shared_memory.applet_footer.type = AppletFooterUiType::HandheldJoyConLeftJoyConRight;
break; break;
case Core::HID::NpadStyleIndex::JoyconDual: case Core::HID::NpadStyleIndex::JoyconDual:
shared_memory.style_set.joycon_dual.Assign(1); shared_memory.style_tag.joycon_dual.Assign(1);
shared_memory.device_type.joycon_left.Assign(1); shared_memory.device_type.joycon_left.Assign(1);
shared_memory.device_type.joycon_right.Assign(1); shared_memory.device_type.joycon_right.Assign(1);
shared_memory.system_properties.is_vertical.Assign(1); shared_memory.system_properties.is_vertical.Assign(1);
@ -203,7 +171,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
shared_memory.applet_footer.type = AppletFooterUiType::JoyDual; shared_memory.applet_footer.type = AppletFooterUiType::JoyDual;
break; break;
case Core::HID::NpadStyleIndex::JoyconLeft: case Core::HID::NpadStyleIndex::JoyconLeft:
shared_memory.style_set.joycon_left.Assign(1); shared_memory.style_tag.joycon_left.Assign(1);
shared_memory.device_type.joycon_left.Assign(1); shared_memory.device_type.joycon_left.Assign(1);
shared_memory.system_properties.is_horizontal.Assign(1); shared_memory.system_properties.is_horizontal.Assign(1);
shared_memory.system_properties.use_minus.Assign(1); shared_memory.system_properties.use_minus.Assign(1);
@ -211,7 +179,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
shared_memory.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal; shared_memory.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal;
break; break;
case Core::HID::NpadStyleIndex::JoyconRight: case Core::HID::NpadStyleIndex::JoyconRight:
shared_memory.style_set.joycon_right.Assign(1); shared_memory.style_tag.joycon_right.Assign(1);
shared_memory.device_type.joycon_right.Assign(1); shared_memory.device_type.joycon_right.Assign(1);
shared_memory.system_properties.is_horizontal.Assign(1); shared_memory.system_properties.is_horizontal.Assign(1);
shared_memory.system_properties.use_plus.Assign(1); shared_memory.system_properties.use_plus.Assign(1);
@ -219,32 +187,32 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
shared_memory.applet_footer.type = AppletFooterUiType::JoyRightHorizontal; shared_memory.applet_footer.type = AppletFooterUiType::JoyRightHorizontal;
break; break;
case Core::HID::NpadStyleIndex::GameCube: case Core::HID::NpadStyleIndex::GameCube:
shared_memory.style_set.gamecube.Assign(1); shared_memory.style_tag.gamecube.Assign(1);
shared_memory.device_type.fullkey.Assign(1); shared_memory.device_type.fullkey.Assign(1);
shared_memory.system_properties.is_vertical.Assign(1); shared_memory.system_properties.is_vertical.Assign(1);
shared_memory.system_properties.use_plus.Assign(1); shared_memory.system_properties.use_plus.Assign(1);
break; break;
case Core::HID::NpadStyleIndex::Pokeball: case Core::HID::NpadStyleIndex::Pokeball:
shared_memory.style_set.palma.Assign(1); shared_memory.style_tag.palma.Assign(1);
shared_memory.device_type.palma.Assign(1); shared_memory.device_type.palma.Assign(1);
shared_memory.assignment_mode = NpadJoyAssignmentMode::Single; shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
break; break;
case Core::HID::NpadStyleIndex::NES: case Core::HID::NpadStyleIndex::NES:
shared_memory.style_set.lark.Assign(1); shared_memory.style_tag.lark.Assign(1);
shared_memory.device_type.fullkey.Assign(1); shared_memory.device_type.fullkey.Assign(1);
break; break;
case Core::HID::NpadStyleIndex::SNES: case Core::HID::NpadStyleIndex::SNES:
shared_memory.style_set.lucia.Assign(1); shared_memory.style_tag.lucia.Assign(1);
shared_memory.device_type.fullkey.Assign(1); shared_memory.device_type.fullkey.Assign(1);
shared_memory.applet_footer.type = AppletFooterUiType::Lucia; shared_memory.applet_footer.type = AppletFooterUiType::Lucia;
break; break;
case Core::HID::NpadStyleIndex::N64: case Core::HID::NpadStyleIndex::N64:
shared_memory.style_set.lagoon.Assign(1); shared_memory.style_tag.lagoon.Assign(1);
shared_memory.device_type.fullkey.Assign(1); shared_memory.device_type.fullkey.Assign(1);
shared_memory.applet_footer.type = AppletFooterUiType::Lagon; shared_memory.applet_footer.type = AppletFooterUiType::Lagon;
break; break;
case Core::HID::NpadStyleIndex::SegaGenesis: case Core::HID::NpadStyleIndex::SegaGenesis:
shared_memory.style_set.lager.Assign(1); shared_memory.style_tag.lager.Assign(1);
shared_memory.device_type.fullkey.Assign(1); shared_memory.device_type.fullkey.Assign(1);
break; break;
default: default:
@ -268,7 +236,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
controller.is_connected = true; controller.is_connected = true;
controller.device->Connect(); controller.device->Connect();
SignalStyleSetChangedEvent(IndexToNPad(controller_idx)); SignalStyleSetChangedEvent(npad_id);
WriteEmptyEntry(controller.shared_memory_entry); WriteEmptyEntry(controller.shared_memory_entry);
} }
@ -283,7 +251,7 @@ void Controller_NPad::OnInit() {
service_context.CreateEvent(fmt::format("npad:NpadStyleSetChanged_{}", i)); service_context.CreateEvent(fmt::format("npad:NpadStyleSetChanged_{}", i));
} }
if (hid_core.GetSupportedStyleTag().raw == 0) { if (hid_core.GetSupportedStyleTag().raw == Core::HID::NpadStyleSet::None) {
// We want to support all controllers // We want to support all controllers
Core::HID::NpadStyleTag style{}; Core::HID::NpadStyleTag style{};
style.handheld.Assign(1); style.handheld.Assign(1);
@ -298,7 +266,7 @@ void Controller_NPad::OnInit() {
supported_npad_id_types.resize(npad_id_list.size()); supported_npad_id_types.resize(npad_id_list.size());
std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), std::memcpy(supported_npad_id_types.data(), npad_id_list.data(),
npad_id_list.size() * sizeof(u32)); npad_id_list.size() * sizeof(Core::HID::NpadIdType));
// Prefill controller buffers // Prefill controller buffers
for (auto& controller : controller_data) { for (auto& controller : controller_data) {
@ -322,8 +290,7 @@ void Controller_NPad::OnInit() {
for (auto& controller : controller_data) { for (auto& controller : controller_data) {
const auto& device = controller.device; const auto& device = controller.device;
if (device->IsConnected()) { if (device->IsConnected()) {
const std::size_t index = Core::HID::NpadIdTypeToIndex(device->GetNpadIdType()); AddNewControllerAt(device->GetNpadStyleIndex(), device->GetNpadIdType());
AddNewControllerAt(device->GetNpadStyleIndex(), index);
} }
} }
} }
@ -354,15 +321,14 @@ void Controller_NPad::OnRelease() {
auto& controller = controller_data[i]; auto& controller = controller_data[i];
service_context.CloseEvent(controller.styleset_changed_event); service_context.CloseEvent(controller.styleset_changed_event);
for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) { for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) {
VibrateControllerAtIndex(i, device_idx, {}); VibrateControllerAtIndex(controller.device->GetNpadIdType(), device_idx, {});
} }
} }
} }
void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
std::lock_guard lock{mutex}; std::lock_guard lock{mutex};
const auto controller_idx = NPadIdToIndex(npad_id); auto& controller = GetControllerFromNpadIdType(npad_id);
auto& controller = controller_data[controller_idx];
const auto controller_type = controller.device->GetNpadStyleIndex(); const auto controller_type = controller.device->GetNpadStyleIndex();
if (!controller.device->IsConnected()) { if (!controller.device->IsConnected()) {
return; return;
@ -431,9 +397,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
&controller.shared_memory_entry, sizeof(NpadInternalState)); &controller.shared_memory_entry, sizeof(NpadInternalState));
continue; continue;
} }
const u32 npad_index = static_cast<u32>(i);
RequestPadStateUpdate(npad_index); RequestPadStateUpdate(controller.device->GetNpadIdType());
auto& pad_state = controller.npad_pad_state; auto& pad_state = controller.npad_pad_state;
auto& libnx_state = controller.npad_libnx_state; auto& libnx_state = controller.npad_libnx_state;
auto& trigger_state = controller.npad_trigger_state; auto& trigger_state = controller.npad_trigger_state;
@ -571,10 +536,11 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state; auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state;
auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state; auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state;
if (sixaxis_sensors_enabled && Settings::values.motion_enabled.GetValue()) { if (controller.sixaxis_sensor_enabled && Settings::values.motion_enabled.GetValue()) {
sixaxis_at_rest = true; controller.sixaxis_at_rest = true;
for (std::size_t e = 0; e < motion_state.size(); ++e) { for (std::size_t e = 0; e < motion_state.size(); ++e) {
sixaxis_at_rest = sixaxis_at_rest && motion_state[e].is_at_rest; controller.sixaxis_at_rest =
controller.sixaxis_at_rest && motion_state[e].is_at_rest;
} }
} }
@ -584,7 +550,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
break; break;
case Core::HID::NpadStyleIndex::ProController: case Core::HID::NpadStyleIndex::ProController:
sixaxis_fullkey_state.attribute.raw = 0; sixaxis_fullkey_state.attribute.raw = 0;
if (sixaxis_sensors_enabled) { if (controller.sixaxis_sensor_enabled) {
sixaxis_fullkey_state.attribute.is_connected.Assign(1); sixaxis_fullkey_state.attribute.is_connected.Assign(1);
sixaxis_fullkey_state.accel = motion_state[0].accel; sixaxis_fullkey_state.accel = motion_state[0].accel;
sixaxis_fullkey_state.gyro = motion_state[0].gyro; sixaxis_fullkey_state.gyro = motion_state[0].gyro;
@ -594,7 +560,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
break; break;
case Core::HID::NpadStyleIndex::Handheld: case Core::HID::NpadStyleIndex::Handheld:
sixaxis_handheld_state.attribute.raw = 0; sixaxis_handheld_state.attribute.raw = 0;
if (sixaxis_sensors_enabled) { if (controller.sixaxis_sensor_enabled) {
sixaxis_handheld_state.attribute.is_connected.Assign(1); sixaxis_handheld_state.attribute.is_connected.Assign(1);
sixaxis_handheld_state.accel = motion_state[0].accel; sixaxis_handheld_state.accel = motion_state[0].accel;
sixaxis_handheld_state.gyro = motion_state[0].gyro; sixaxis_handheld_state.gyro = motion_state[0].gyro;
@ -605,7 +571,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
case Core::HID::NpadStyleIndex::JoyconDual: case Core::HID::NpadStyleIndex::JoyconDual:
sixaxis_dual_left_state.attribute.raw = 0; sixaxis_dual_left_state.attribute.raw = 0;
sixaxis_dual_right_state.attribute.raw = 0; sixaxis_dual_right_state.attribute.raw = 0;
if (sixaxis_sensors_enabled) { if (controller.sixaxis_sensor_enabled) {
// Set motion for the left joycon // Set motion for the left joycon
sixaxis_dual_left_state.attribute.is_connected.Assign(1); sixaxis_dual_left_state.attribute.is_connected.Assign(1);
sixaxis_dual_left_state.accel = motion_state[0].accel; sixaxis_dual_left_state.accel = motion_state[0].accel;
@ -613,7 +579,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
sixaxis_dual_left_state.rotation = motion_state[0].rotation; sixaxis_dual_left_state.rotation = motion_state[0].rotation;
sixaxis_dual_left_state.orientation = motion_state[0].orientation; sixaxis_dual_left_state.orientation = motion_state[0].orientation;
} }
if (sixaxis_sensors_enabled) { if (controller.sixaxis_sensor_enabled) {
// Set motion for the right joycon // Set motion for the right joycon
sixaxis_dual_right_state.attribute.is_connected.Assign(1); sixaxis_dual_right_state.attribute.is_connected.Assign(1);
sixaxis_dual_right_state.accel = motion_state[1].accel; sixaxis_dual_right_state.accel = motion_state[1].accel;
@ -624,7 +590,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
break; break;
case Core::HID::NpadStyleIndex::JoyconLeft: case Core::HID::NpadStyleIndex::JoyconLeft:
sixaxis_left_lifo_state.attribute.raw = 0; sixaxis_left_lifo_state.attribute.raw = 0;
if (sixaxis_sensors_enabled) { if (controller.sixaxis_sensor_enabled) {
sixaxis_left_lifo_state.attribute.is_connected.Assign(1); sixaxis_left_lifo_state.attribute.is_connected.Assign(1);
sixaxis_left_lifo_state.accel = motion_state[0].accel; sixaxis_left_lifo_state.accel = motion_state[0].accel;
sixaxis_left_lifo_state.gyro = motion_state[0].gyro; sixaxis_left_lifo_state.gyro = motion_state[0].gyro;
@ -634,7 +600,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
break; break;
case Core::HID::NpadStyleIndex::JoyconRight: case Core::HID::NpadStyleIndex::JoyconRight:
sixaxis_right_lifo_state.attribute.raw = 0; sixaxis_right_lifo_state.attribute.raw = 0;
if (sixaxis_sensors_enabled) { if (controller.sixaxis_sensor_enabled) {
sixaxis_right_lifo_state.attribute.is_connected.Assign(1); sixaxis_right_lifo_state.attribute.is_connected.Assign(1);
sixaxis_right_lifo_state.accel = motion_state[1].accel; sixaxis_right_lifo_state.accel = motion_state[1].accel;
sixaxis_right_lifo_state.gyro = motion_state[1].gyro; sixaxis_right_lifo_state.gyro = motion_state[1].gyro;
@ -724,26 +690,30 @@ Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode
return communication_mode; return communication_mode;
} }
void Controller_NPad::SetNpadMode(u32 npad_id, NpadJoyAssignmentMode assignment_mode) { void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id,
const std::size_t npad_index = NPadIdToIndex(npad_id); NpadJoyAssignmentMode assignment_mode) {
ASSERT(npad_index < controller_data.size()); if (!IsNpadIdValid(npad_id)) {
auto& controller = controller_data[npad_index]; LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
return;
}
auto& controller = GetControllerFromNpadIdType(npad_id);
if (controller.shared_memory_entry.assignment_mode != assignment_mode) { if (controller.shared_memory_entry.assignment_mode != assignment_mode) {
controller.shared_memory_entry.assignment_mode = assignment_mode; controller.shared_memory_entry.assignment_mode = assignment_mode;
} }
} }
bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
const VibrationValue& vibration_value) { std::size_t device_index,
auto& controller = controller_data[npad_index]; const Core::HID::VibrationValue& vibration_value) {
auto& controller = GetControllerFromNpadIdType(npad_id);
if (!controller.device->IsConnected()) { if (!controller.device->IsConnected()) {
return false; return false;
} }
if (!controller.device->IsVibrationEnabled()) { if (!controller.device->IsVibrationEnabled()) {
if (controller.vibration[device_index].latest_vibration_value.amp_low != 0.0f || if (controller.vibration[device_index].latest_vibration_value.low_amplitude != 0.0f ||
controller.vibration[device_index].latest_vibration_value.amp_high != 0.0f) { controller.vibration[device_index].latest_vibration_value.high_amplitude != 0.0f) {
// Send an empty vibration to stop any vibrations. // Send an empty vibration to stop any vibrations.
Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f}; Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f};
controller.device->SetVibration(device_index, vibration); controller.device->SetVibration(device_index, vibration);
@ -762,7 +732,7 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size
const auto now = steady_clock::now(); const auto now = steady_clock::now();
// Filter out non-zero vibrations that are within 10ms of each other. // 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) && if ((vibration_value.low_amplitude != 0.0f || vibration_value.high_amplitude != 0.0f) &&
duration_cast<milliseconds>( duration_cast<milliseconds>(
now - controller.vibration[device_index].last_vibration_timepoint) < now - controller.vibration[device_index].last_vibration_timepoint) <
milliseconds(10)) { milliseconds(10)) {
@ -772,13 +742,15 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size
controller.vibration[device_index].last_vibration_timepoint = now; controller.vibration[device_index].last_vibration_timepoint = now;
} }
Core::HID::VibrationValue vibration{vibration_value.amp_low, vibration_value.freq_low, Core::HID::VibrationValue vibration{
vibration_value.amp_high, vibration_value.freq_high}; vibration_value.low_amplitude, vibration_value.low_frequency,
vibration_value.high_amplitude, vibration_value.high_frequency};
return controller.device->SetVibration(device_index, vibration); return controller.device->SetVibration(device_index, vibration);
} }
void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle, void Controller_NPad::VibrateController(
const VibrationValue& vibration_value) { const Core::HID::VibrationDeviceHandle& vibration_device_handle,
const Core::HID::VibrationValue& vibration_value) {
if (!IsDeviceHandleValid(vibration_device_handle)) { if (!IsDeviceHandleValid(vibration_device_handle)) {
return; return;
} }
@ -787,15 +759,14 @@ void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_han
return; return;
} }
const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); auto& controller = GetControllerFromHandle(vibration_device_handle);
auto& controller = controller_data[npad_index];
const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
if (!controller.vibration[device_index].device_mounted || !controller.device->IsConnected()) { if (!controller.vibration[device_index].device_mounted || !controller.device->IsConnected()) {
return; return;
} }
if (vibration_device_handle.device_index == DeviceIndex::None) { if (vibration_device_handle.device_index == Core::HID::DeviceIndex::None) {
UNREACHABLE_MSG("DeviceIndex should never be None!"); UNREACHABLE_MSG("DeviceIndex should never be None!");
return; return;
} }
@ -803,28 +774,30 @@ void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_han
// Some games try to send mismatched parameters in the device handle, block these. // Some games try to send mismatched parameters in the device handle, block these.
if ((controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft && if ((controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft &&
(vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconRight || (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconRight ||
vibration_device_handle.device_index == DeviceIndex::Right)) || vibration_device_handle.device_index == Core::HID::DeviceIndex::Right)) ||
(controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight && (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight &&
(vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconLeft || (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconLeft ||
vibration_device_handle.device_index == DeviceIndex::Left))) { vibration_device_handle.device_index == Core::HID::DeviceIndex::Left))) {
return; return;
} }
// Filter out vibrations with equivalent values to reduce unnecessary state changes. // Filter out vibrations with equivalent values to reduce unnecessary state changes.
if (vibration_value.amp_low == if (vibration_value.low_amplitude ==
controller.vibration[device_index].latest_vibration_value.amp_low && controller.vibration[device_index].latest_vibration_value.low_amplitude &&
vibration_value.amp_high == vibration_value.high_amplitude ==
controller.vibration[device_index].latest_vibration_value.amp_high) { controller.vibration[device_index].latest_vibration_value.high_amplitude) {
return; return;
} }
if (VibrateControllerAtIndex(npad_index, device_index, vibration_value)) { if (VibrateControllerAtIndex(controller.device->GetNpadIdType(), device_index,
vibration_value)) {
controller.vibration[device_index].latest_vibration_value = vibration_value; controller.vibration[device_index].latest_vibration_value = vibration_value;
} }
} }
void Controller_NPad::VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles, void Controller_NPad::VibrateControllers(
const std::vector<VibrationValue>& vibration_values) { const std::vector<Core::HID::VibrationDeviceHandle>& vibration_device_handles,
const std::vector<Core::HID::VibrationValue>& vibration_values) {
if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
return; return;
} }
@ -839,31 +812,31 @@ void Controller_NPad::VibrateControllers(const std::vector<DeviceHandle>& vibrat
} }
} }
Controller_NPad::VibrationValue Controller_NPad::GetLastVibration( Core::HID::VibrationValue Controller_NPad::GetLastVibration(
const DeviceHandle& vibration_device_handle) const { const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
if (!IsDeviceHandleValid(vibration_device_handle)) { if (!IsDeviceHandleValid(vibration_device_handle)) {
return {}; return {};
} }
const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); const auto& controller = GetControllerFromHandle(vibration_device_handle);
const auto& controller = controller_data[npad_index];
const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
return controller.vibration[device_index].latest_vibration_value; return controller.vibration[device_index].latest_vibration_value;
} }
void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_device_handle) { void Controller_NPad::InitializeVibrationDevice(
const Core::HID::VibrationDeviceHandle& vibration_device_handle) {
if (!IsDeviceHandleValid(vibration_device_handle)) { if (!IsDeviceHandleValid(vibration_device_handle)) {
return; return;
} }
const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); const auto npad_index = static_cast<Core::HID::NpadIdType>(vibration_device_handle.npad_id);
const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
InitializeVibrationDeviceAtIndex(npad_index, device_index); InitializeVibrationDeviceAtIndex(npad_index, device_index);
} }
void Controller_NPad::InitializeVibrationDeviceAtIndex(std::size_t npad_index, void Controller_NPad::InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npad_id,
std::size_t device_index) { std::size_t device_index) {
auto& controller = controller_data[npad_index]; auto& controller = GetControllerFromNpadIdType(npad_id);
if (!Settings::values.vibration_enabled.GetValue()) { if (!Settings::values.vibration_enabled.GetValue()) {
controller.vibration[device_index].device_mounted = false; controller.vibration[device_index].device_mounted = false;
return; return;
@ -877,58 +850,67 @@ void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) {
permit_vibration_session_enabled = permit_vibration_session; permit_vibration_session_enabled = permit_vibration_session;
} }
bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const { bool Controller_NPad::IsVibrationDeviceMounted(
const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
if (!IsDeviceHandleValid(vibration_device_handle)) { if (!IsDeviceHandleValid(vibration_device_handle)) {
return false; return false;
} }
const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); const auto& controller = GetControllerFromHandle(vibration_device_handle);
const auto& controller = controller_data[npad_index];
const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
return controller.vibration[device_index].device_mounted; return controller.vibration[device_index].device_mounted;
} }
Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) { Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(Core::HID::NpadIdType npad_id) {
const auto& controller = controller_data[NPadIdToIndex(npad_id)]; if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
// Fallback to player 1
const auto& controller = GetControllerFromNpadIdType(Core::HID::NpadIdType::Player1);
return controller.styleset_changed_event->GetReadableEvent(); return controller.styleset_changed_event->GetReadableEvent();
} }
void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const { const auto& controller = GetControllerFromNpadIdType(npad_id);
const auto& controller = controller_data[NPadIdToIndex(npad_id)]; return controller.styleset_changed_event->GetReadableEvent();
}
void Controller_NPad::SignalStyleSetChangedEvent(Core::HID::NpadIdType npad_id) const {
const auto& controller = GetControllerFromNpadIdType(npad_id);
controller.styleset_changed_event->GetWritableEvent().Signal(); controller.styleset_changed_event->GetWritableEvent().Signal();
} }
void Controller_NPad::AddNewControllerAt(Core::HID::NpadStyleIndex controller, void Controller_NPad::AddNewControllerAt(Core::HID::NpadStyleIndex controller,
std::size_t npad_index) { Core::HID::NpadIdType npad_id) {
UpdateControllerAt(controller, npad_index, true); UpdateControllerAt(controller, npad_id, true);
} }
void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type, std::size_t npad_index, void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type,
bool connected) { Core::HID::NpadIdType npad_id, bool connected) {
auto& controller = controller_data[npad_index]; auto& controller = GetControllerFromNpadIdType(npad_id);
if (!connected) { if (!connected) {
DisconnectNpadAtIndex(npad_index); DisconnectNpad(npad_id);
return; return;
} }
controller.device->SetNpadStyleIndex(type); controller.device->SetNpadStyleIndex(type);
InitNewlyAddedController(npad_index); InitNewlyAddedController(npad_id);
} }
void Controller_NPad::DisconnectNpad(u32 npad_id) { void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
DisconnectNpadAtIndex(NPadIdToIndex(npad_id)); if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
return;
} }
void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) { LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id);
auto& controller = controller_data[npad_index]; auto& controller = GetControllerFromNpadIdType(npad_id);
for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) { for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) {
// Send an empty vibration to stop any vibrations. // Send an empty vibration to stop any vibrations.
VibrateControllerAtIndex(npad_index, device_idx, {}); VibrateControllerAtIndex(npad_id, device_idx, {});
controller.vibration[device_idx].device_mounted = false; controller.vibration[device_idx].device_mounted = false;
} }
auto& shared_memory_entry = controller.shared_memory_entry; auto& shared_memory_entry = controller.shared_memory_entry;
shared_memory_entry.style_set.raw = 0; // Zero out shared_memory_entry.style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out
shared_memory_entry.device_type.raw = 0; shared_memory_entry.device_type.raw = 0;
shared_memory_entry.system_properties.raw = 0; shared_memory_entry.system_properties.raw = 0;
shared_memory_entry.button_properties.raw = 0; shared_memory_entry.button_properties.raw = 0;
@ -949,48 +931,102 @@ void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) {
controller.is_connected = false; controller.is_connected = false;
controller.device->Disconnect(); controller.device->Disconnect();
SignalStyleSetChangedEvent(IndexToNPad(npad_index)); SignalStyleSetChangedEvent(npad_id);
WriteEmptyEntry(controller.shared_memory_entry); WriteEmptyEntry(controller.shared_memory_entry);
} }
void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) { void Controller_NPad::SetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle,
gyroscope_zero_drift_mode = drift_mode; GyroscopeZeroDriftMode drift_mode) {
if (!IsDeviceHandleValid(sixaxis_handle)) {
LOG_ERROR(Service_HID, "Invalid handle");
return;
}
auto& controller = GetControllerFromHandle(sixaxis_handle);
controller.gyroscope_zero_drift_mode = drift_mode;
} }
Controller_NPad::GyroscopeZeroDriftMode Controller_NPad::GetGyroscopeZeroDriftMode() const { Controller_NPad::GyroscopeZeroDriftMode Controller_NPad::GetGyroscopeZeroDriftMode(
return gyroscope_zero_drift_mode; Core::HID::SixAxisSensorHandle sixaxis_handle) const {
if (!IsDeviceHandleValid(sixaxis_handle)) {
LOG_ERROR(Service_HID, "Invalid handle");
// Return the default value
return GyroscopeZeroDriftMode::Standard;
}
const auto& controller = GetControllerFromHandle(sixaxis_handle);
return controller.gyroscope_zero_drift_mode;
} }
bool Controller_NPad::IsSixAxisSensorAtRest() const { bool Controller_NPad::IsSixAxisSensorAtRest(Core::HID::SixAxisSensorHandle sixaxis_handle) const {
return sixaxis_at_rest; if (!IsDeviceHandleValid(sixaxis_handle)) {
LOG_ERROR(Service_HID, "Invalid handle");
// Return the default value
return true;
}
const auto& controller = GetControllerFromHandle(sixaxis_handle);
return controller.sixaxis_at_rest;
} }
void Controller_NPad::SetSixAxisEnabled(bool six_axis_status) { void Controller_NPad::SetSixAxisEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle,
sixaxis_sensors_enabled = six_axis_status; bool sixaxis_status) {
if (!IsDeviceHandleValid(sixaxis_handle)) {
LOG_ERROR(Service_HID, "Invalid handle");
return;
}
auto& controller = GetControllerFromHandle(sixaxis_handle);
controller.sixaxis_sensor_enabled = sixaxis_status;
} }
void Controller_NPad::SetSixAxisFusionParameters(f32 parameter1, f32 parameter2) { void Controller_NPad::SetSixAxisFusionEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle,
sixaxis_fusion_parameter1 = parameter1; bool sixaxis_fusion_status) {
sixaxis_fusion_parameter2 = parameter2; if (!IsDeviceHandleValid(sixaxis_handle)) {
LOG_ERROR(Service_HID, "Invalid handle");
return;
}
auto& controller = GetControllerFromHandle(sixaxis_handle);
controller.sixaxis_fusion_enabled = sixaxis_fusion_status;
} }
std::pair<f32, f32> Controller_NPad::GetSixAxisFusionParameters() { void Controller_NPad::SetSixAxisFusionParameters(
return { Core::HID::SixAxisSensorHandle sixaxis_handle,
sixaxis_fusion_parameter1, Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) {
sixaxis_fusion_parameter2, if (!IsDeviceHandleValid(sixaxis_handle)) {
}; LOG_ERROR(Service_HID, "Invalid handle");
return;
}
auto& controller = GetControllerFromHandle(sixaxis_handle);
controller.sixaxis_fusion = sixaxis_fusion_parameters;
} }
void Controller_NPad::ResetSixAxisFusionParameters() { Core::HID::SixAxisSensorFusionParameters Controller_NPad::GetSixAxisFusionParameters(
sixaxis_fusion_parameter1 = 0.0f; Core::HID::SixAxisSensorHandle sixaxis_handle) {
sixaxis_fusion_parameter2 = 0.0f; if (!IsDeviceHandleValid(sixaxis_handle)) {
LOG_ERROR(Service_HID, "Invalid handle");
// Since these parameters are unknow just return zeros
return {};
}
auto& controller = GetControllerFromHandle(sixaxis_handle);
return controller.sixaxis_fusion;
} }
void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) { void Controller_NPad::ResetSixAxisFusionParameters(Core::HID::SixAxisSensorHandle sixaxis_handle) {
const auto npad_index_1 = NPadIdToIndex(npad_id_1); if (!IsDeviceHandleValid(sixaxis_handle)) {
const auto npad_index_2 = NPadIdToIndex(npad_id_2); LOG_ERROR(Service_HID, "Invalid handle");
const auto& controller_1 = controller_data[npad_index_1].device; return;
const auto& controller_2 = controller_data[npad_index_2].device; }
auto& controller = GetControllerFromHandle(sixaxis_handle);
// Since these parameters are unknow just fill with zeros
controller.sixaxis_fusion = {};
}
void Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
Core::HID::NpadIdType npad_id_2) {
if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
npad_id_2);
return;
}
auto& controller_1 = GetControllerFromNpadIdType(npad_id_1).device;
auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device;
// If the controllers at both npad indices form a pair of left and right joycons, merge them. // If the controllers at both npad indices form a pair of left and right joycons, merge them.
// Otherwise, do nothing. // Otherwise, do nothing.
@ -1000,7 +1036,7 @@ void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) {
controller_1->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight)) { controller_1->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight)) {
// Disconnect the joycon at the second id and connect the dual joycon at the first index. // 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(Core::HID::NpadStyleIndex::JoyconDual, npad_index_1); AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_1);
} }
} }
@ -1014,15 +1050,20 @@ void Controller_NPad::StopLRAssignmentMode() {
is_in_lr_assignment_mode = false; is_in_lr_assignment_mode = false;
} }
bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) { bool Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1,
if (npad_id_1 == NPAD_HANDHELD || npad_id_2 == NPAD_HANDHELD || npad_id_1 == NPAD_UNKNOWN || Core::HID::NpadIdType npad_id_2) {
npad_id_2 == NPAD_UNKNOWN) { if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
npad_id_2);
return false;
}
if (npad_id_1 == Core::HID::NpadIdType::Handheld ||
npad_id_2 == Core::HID::NpadIdType::Handheld || npad_id_1 == Core::HID::NpadIdType::Other ||
npad_id_2 == Core::HID::NpadIdType::Other) {
return true; return true;
} }
const auto npad_index_1 = NPadIdToIndex(npad_id_1); const auto& controller_1 = GetControllerFromNpadIdType(npad_id_1).device;
const auto npad_index_2 = NPadIdToIndex(npad_id_2); const auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device;
const auto& controller_1 = controller_data[npad_index_1].device;
const auto& controller_2 = controller_data[npad_index_2].device;
const auto type_index_1 = controller_1->GetNpadStyleIndex(); const auto type_index_1 = controller_1->GetNpadStyleIndex();
const auto type_index_2 = controller_2->GetNpadStyleIndex(); const auto type_index_2 = controller_2->GetNpadStyleIndex();
@ -1030,28 +1071,39 @@ bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) {
return false; return false;
} }
AddNewControllerAt(type_index_2, npad_index_1); AddNewControllerAt(type_index_2, npad_id_1);
AddNewControllerAt(type_index_1, npad_index_2); AddNewControllerAt(type_index_1, npad_id_2);
return true; return true;
} }
Core::HID::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { Core::HID::LedPattern Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id) {
if (npad_id == npad_id_list.back() || npad_id == npad_id_list[npad_id_list.size() - 2]) { if (!IsNpadIdValid(npad_id)) {
// These are controllers without led patterns LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
return Core::HID::LedPattern{0, 0, 0, 0}; return Core::HID::LedPattern{0, 0, 0, 0};
} }
return controller_data[npad_id].device->GetLedPattern(); const auto& controller = GetControllerFromNpadIdType(npad_id).device;
return controller->GetLedPattern();
} }
bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const { bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(
auto& controller = controller_data[NPadIdToIndex(npad_id)]; Core::HID::NpadIdType npad_id) const {
if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
// Return the default value
return false;
}
const auto& controller = GetControllerFromNpadIdType(npad_id);
return controller.unintended_home_button_input_protection; return controller.unintended_home_button_input_protection;
} }
void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
u32 npad_id) { Core::HID::NpadIdType npad_id) {
auto& controller = controller_data[NPadIdToIndex(npad_id)]; if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
return;
}
auto& controller = GetControllerFromNpadIdType(npad_id);
controller.unintended_home_button_input_protection = is_protection_enabled; controller.unintended_home_button_input_protection = is_protection_enabled;
} }
@ -1099,7 +1151,7 @@ bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller
if (controller == Core::HID::NpadStyleIndex::Handheld) { if (controller == Core::HID::NpadStyleIndex::Handheld) {
const bool support_handheld = const bool support_handheld =
std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
NPAD_HANDHELD) != supported_npad_id_types.end(); Core::HID::NpadIdType::Handheld) != supported_npad_id_types.end();
// Handheld is not even a supported type, lets stop here // Handheld is not even a supported type, lets stop here
if (!support_handheld) { if (!support_handheld) {
return false; return false;
@ -1113,7 +1165,9 @@ bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller
} }
if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(), if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(),
[](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) { [](Core::HID::NpadIdType npad_id) {
return npad_id <= Core::HID::NpadIdType::Player8;
})) {
Core::HID::NpadStyleTag style = GetSupportedStyleSet(); Core::HID::NpadStyleTag style = GetSupportedStyleSet();
switch (controller) { switch (controller) {
case Core::HID::NpadStyleIndex::ProController: case Core::HID::NpadStyleIndex::ProController:
@ -1144,4 +1198,48 @@ bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller
return false; return false;
} }
Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
const Core::HID::SixAxisSensorHandle& device_handle) {
const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
return GetControllerFromNpadIdType(npad_id);
}
const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
const Core::HID::SixAxisSensorHandle& device_handle) const {
const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
return GetControllerFromNpadIdType(npad_id);
}
Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
const Core::HID::VibrationDeviceHandle& device_handle) {
const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
return GetControllerFromNpadIdType(npad_id);
}
const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
const Core::HID::VibrationDeviceHandle& device_handle) const {
const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
return GetControllerFromNpadIdType(npad_id);
}
Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpadIdType(
Core::HID::NpadIdType npad_id) {
if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
npad_id = Core::HID::NpadIdType::Player1;
}
const auto npad_index = Core::HID::NpadIdTypeToIndex(npad_id);
return controller_data[npad_index];
}
const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpadIdType(
Core::HID::NpadIdType npad_id) const {
if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
npad_id = Core::HID::NpadIdType::Player1;
}
const auto npad_index = Core::HID::NpadIdTypeToIndex(npad_id);
return controller_data[npad_index];
}
} // namespace Service::HID } // namespace Service::HID

View File

@ -31,9 +31,6 @@ class ServiceContext;
namespace Service::HID { namespace Service::HID {
constexpr u32 NPAD_HANDHELD = 32;
constexpr u32 NPAD_UNKNOWN = 16; // TODO(ogniK): What is this?
class Controller_NPad final : public ControllerBase { class Controller_NPad final : public ControllerBase {
public: public:
explicit Controller_NPad(Core::HID::HIDCore& hid_core_, explicit Controller_NPad(Core::HID::HIDCore& hid_core_,
@ -53,13 +50,6 @@ public:
void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
std::size_t size) override; std::size_t size) override;
enum class DeviceIndex : u8 {
Left = 0,
Right = 1,
None = 2,
MaxDeviceIndex = 3,
};
// This is nn::hid::GyroscopeZeroDriftMode // This is nn::hid::GyroscopeZeroDriftMode
enum class GyroscopeZeroDriftMode : u32 { enum class GyroscopeZeroDriftMode : u32 {
Loose = 0, Loose = 0,
@ -79,6 +69,12 @@ public:
Single = 1, Single = 1,
}; };
// This is nn::hid::NpadJoyDeviceType
enum class NpadJoyDeviceType : s64 {
Left = 0,
Right = 1,
};
// This is nn::hid::NpadHandheldActivationMode // This is nn::hid::NpadHandheldActivationMode
enum class NpadHandheldActivationMode : u64 { enum class NpadHandheldActivationMode : u64 {
Dual = 0, Dual = 0,
@ -94,28 +90,11 @@ public:
Default = 3, Default = 3,
}; };
struct DeviceHandle { static constexpr Core::HID::VibrationValue DEFAULT_VIBRATION_VALUE{
Core::HID::NpadStyleIndex npad_type; .low_amplitude = 0.0f,
u8 npad_id; .low_frequency = 160.0f,
DeviceIndex device_index; .high_amplitude = 0.0f,
INSERT_PADDING_BYTES_NOINIT(1); .high_frequency = 320.0f,
};
static_assert(sizeof(DeviceHandle) == 4, "DeviceHandle is an invalid size");
// This is nn::hid::VibrationValue
struct VibrationValue {
f32 amp_low;
f32 freq_low;
f32 amp_high;
f32 freq_high;
};
static_assert(sizeof(VibrationValue) == 0x10, "Vibration is an invalid size");
static constexpr VibrationValue DEFAULT_VIBRATION_VALUE{
.amp_low = 0.0f,
.freq_low = 160.0f,
.amp_high = 0.0f,
.freq_high = 320.0f,
}; };
void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set); void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
@ -134,68 +113,77 @@ public:
void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_); void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_);
NpadCommunicationMode GetNpadCommunicationMode() const; NpadCommunicationMode GetNpadCommunicationMode() const;
void SetNpadMode(u32 npad_id, NpadJoyAssignmentMode assignment_mode); void SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyAssignmentMode assignment_mode);
bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, bool VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index,
const VibrationValue& vibration_value); const Core::HID::VibrationValue& vibration_value);
void VibrateController(const DeviceHandle& vibration_device_handle, void VibrateController(const Core::HID::VibrationDeviceHandle& vibration_device_handle,
const VibrationValue& vibration_value); const Core::HID::VibrationValue& vibration_value);
void VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles, void VibrateControllers(
const std::vector<VibrationValue>& vibration_values); const std::vector<Core::HID::VibrationDeviceHandle>& vibration_device_handles,
const std::vector<Core::HID::VibrationValue>& vibration_values);
VibrationValue GetLastVibration(const DeviceHandle& vibration_device_handle) const; Core::HID::VibrationValue GetLastVibration(
const Core::HID::VibrationDeviceHandle& vibration_device_handle) const;
void InitializeVibrationDevice(const DeviceHandle& vibration_device_handle); void InitializeVibrationDevice(const Core::HID::VibrationDeviceHandle& vibration_device_handle);
void InitializeVibrationDeviceAtIndex(std::size_t npad_index, std::size_t device_index); void InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index);
void SetPermitVibrationSession(bool permit_vibration_session); void SetPermitVibrationSession(bool permit_vibration_session);
bool IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const; bool IsVibrationDeviceMounted(
const Core::HID::VibrationDeviceHandle& vibration_device_handle) const;
Kernel::KReadableEvent& GetStyleSetChangedEvent(u32 npad_id); Kernel::KReadableEvent& GetStyleSetChangedEvent(Core::HID::NpadIdType npad_id);
void SignalStyleSetChangedEvent(u32 npad_id) const; void SignalStyleSetChangedEvent(Core::HID::NpadIdType npad_id) const;
// Adds a new controller at an index. // Adds a new controller at an index.
void AddNewControllerAt(Core::HID::NpadStyleIndex controller, std::size_t npad_index); void AddNewControllerAt(Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id);
// Adds a new controller at an index with connection status. // Adds a new controller at an index with connection status.
void UpdateControllerAt(Core::HID::NpadStyleIndex controller, std::size_t npad_index, void UpdateControllerAt(Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id,
bool connected); bool connected);
void DisconnectNpad(u32 npad_id); void DisconnectNpad(Core::HID::NpadIdType npad_id);
void DisconnectNpadAtIndex(std::size_t index);
void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode); void SetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle,
GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const; GyroscopeZeroDriftMode drift_mode);
bool IsSixAxisSensorAtRest() const; GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode(
void SetSixAxisEnabled(bool six_axis_status); Core::HID::SixAxisSensorHandle sixaxis_handle) const;
void SetSixAxisFusionParameters(f32 parameter1, f32 parameter2); bool IsSixAxisSensorAtRest(Core::HID::SixAxisSensorHandle sixaxis_handle) const;
std::pair<f32, f32> GetSixAxisFusionParameters(); void SetSixAxisEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle, bool sixaxis_status);
void ResetSixAxisFusionParameters(); void SetSixAxisFusionEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle,
Core::HID::LedPattern GetLedPattern(u32 npad_id); bool sixaxis_fusion_status);
bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const; void SetSixAxisFusionParameters(
void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id); Core::HID::SixAxisSensorHandle sixaxis_handle,
Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters);
Core::HID::SixAxisSensorFusionParameters GetSixAxisFusionParameters(
Core::HID::SixAxisSensorHandle sixaxis_handle);
void ResetSixAxisFusionParameters(Core::HID::SixAxisSensorHandle sixaxis_handle);
Core::HID::LedPattern GetLedPattern(Core::HID::NpadIdType npad_id);
bool IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id) const;
void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
Core::HID::NpadIdType npad_id);
void SetAnalogStickUseCenterClamp(bool use_center_clamp); void SetAnalogStickUseCenterClamp(bool use_center_clamp);
void ClearAllConnectedControllers(); void ClearAllConnectedControllers();
void DisconnectAllConnectedControllers(); void DisconnectAllConnectedControllers();
void ConnectAllDisconnectedControllers(); void ConnectAllDisconnectedControllers();
void ClearAllControllers(); void ClearAllControllers();
void MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2); void MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2);
void StartLRAssignmentMode(); void StartLRAssignmentMode();
void StopLRAssignmentMode(); void StopLRAssignmentMode();
bool SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2); bool SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2);
// Logical OR for all buttons presses on all controllers // Logical OR for all buttons presses on all controllers
// Specifically for cheat engine and other features. // Specifically for cheat engine and other features.
u32 GetAndResetPressState(); u32 GetAndResetPressState();
static std::size_t NPadIdToIndex(u32 npad_id); static bool IsNpadIdValid(Core::HID::NpadIdType npad_id);
static u32 IndexToNPad(std::size_t index); static bool IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle& device_handle);
static bool IsNpadIdValid(u32 npad_id); static bool IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle);
static bool IsDeviceHandleValid(const DeviceHandle& device_handle);
private: private:
// This is nn::hid::detail::ColorAttribute // This is nn::hid::detail::ColorAttribute
@ -441,7 +429,7 @@ private:
// This is nn::hid::detail::NpadInternalState // This is nn::hid::detail::NpadInternalState
struct NpadInternalState { struct NpadInternalState {
Core::HID::NpadStyleTag style_set; Core::HID::NpadStyleTag style_tag;
NpadJoyAssignmentMode assignment_mode; NpadJoyAssignmentMode assignment_mode;
NpadFullKeyColorState fullkey_color; NpadFullKeyColorState fullkey_color;
NpadJoyColorState joycon_color; NpadJoyColorState joycon_color;
@ -476,19 +464,19 @@ private:
NpadLuciaType lucia_type; NpadLuciaType lucia_type;
NpadLagonType lagon_type; NpadLagonType lagon_type;
NpadLagerType lager_type; NpadLagerType lager_type;
INSERT_PADDING_BYTES( // FW 13.x Investigate there is some sort of bitflag related to joycons
0x4); // FW 13.x Investigate there is some sort of bitflag related to joycons INSERT_PADDING_BYTES(0x4);
INSERT_PADDING_BYTES(0xc08); // Unknown INSERT_PADDING_BYTES(0xc08); // Unknown
}; };
static_assert(sizeof(NpadInternalState) == 0x5000, "NpadInternalState is an invalid size"); static_assert(sizeof(NpadInternalState) == 0x5000, "NpadInternalState is an invalid size");
struct VibrationData { struct VibrationData {
bool device_mounted{}; bool device_mounted{};
VibrationValue latest_vibration_value{}; Core::HID::VibrationValue latest_vibration_value{};
std::chrono::steady_clock::time_point last_vibration_timepoint{}; std::chrono::steady_clock::time_point last_vibration_timepoint{};
}; };
struct ControllerData { struct NpadControllerData {
Core::HID::EmulatedController* device; Core::HID::EmulatedController* device;
Kernel::KEvent* styleset_changed_event{}; Kernel::KEvent* styleset_changed_event{};
NpadInternalState shared_memory_entry{}; NpadInternalState shared_memory_entry{};
@ -498,6 +486,13 @@ private:
bool is_connected{}; bool is_connected{};
Core::HID::NpadStyleIndex npad_type{Core::HID::NpadStyleIndex::None}; Core::HID::NpadStyleIndex npad_type{Core::HID::NpadStyleIndex::None};
// Motion parameters
bool sixaxis_at_rest{true};
bool sixaxis_sensor_enabled{true};
bool sixaxis_fusion_enabled{false};
Core::HID::SixAxisSensorFusionParameters sixaxis_fusion{};
GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard};
// Current pad state // Current pad state
NPadGenericState npad_pad_state{}; NPadGenericState npad_pad_state{};
NPadGenericState npad_libnx_state{}; NPadGenericState npad_libnx_state{};
@ -512,27 +507,33 @@ private:
}; };
void ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx); void ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx);
void InitNewlyAddedController(std::size_t controller_idx); void InitNewlyAddedController(Core::HID::NpadIdType npad_id);
bool IsControllerSupported(Core::HID::NpadStyleIndex controller) const; bool IsControllerSupported(Core::HID::NpadStyleIndex controller) const;
void RequestPadStateUpdate(u32 npad_id); void RequestPadStateUpdate(Core::HID::NpadIdType npad_id);
void WriteEmptyEntry(NpadInternalState& npad); void WriteEmptyEntry(NpadInternalState& npad);
NpadControllerData& GetControllerFromHandle(
const Core::HID::SixAxisSensorHandle& device_handle);
const NpadControllerData& GetControllerFromHandle(
const Core::HID::SixAxisSensorHandle& device_handle) const;
NpadControllerData& GetControllerFromHandle(
const Core::HID::VibrationDeviceHandle& device_handle);
const NpadControllerData& GetControllerFromHandle(
const Core::HID::VibrationDeviceHandle& device_handle) const;
NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id);
const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const;
std::atomic<u32> press_state{}; std::atomic<u32> press_state{};
std::array<ControllerData, 10> controller_data{}; std::array<NpadControllerData, 10> controller_data{};
KernelHelpers::ServiceContext& service_context; KernelHelpers::ServiceContext& service_context;
std::mutex mutex; std::mutex mutex;
std::vector<u32> supported_npad_id_types{}; std::vector<Core::HID::NpadIdType> supported_npad_id_types{};
NpadJoyHoldType hold_type{NpadJoyHoldType::Vertical}; NpadJoyHoldType hold_type{NpadJoyHoldType::Vertical};
NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual};
NpadCommunicationMode communication_mode{NpadCommunicationMode::Default}; NpadCommunicationMode communication_mode{NpadCommunicationMode::Default};
bool permit_vibration_session_enabled{false}; bool permit_vibration_session_enabled{false};
bool analog_stick_use_center_clamp{}; bool analog_stick_use_center_clamp{};
GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard};
bool sixaxis_sensors_enabled{true};
f32 sixaxis_fusion_parameter1{};
f32 sixaxis_fusion_parameter2{};
bool sixaxis_at_rest{true};
bool is_in_lr_assignment_mode{false}; bool is_in_lr_assignment_mode{false};
}; };
} // namespace Service::HID } // namespace Service::HID

View File

@ -161,7 +161,7 @@ public:
private: private:
void InitializeVibrationDevice(Kernel::HLERequestContext& ctx) { void InitializeVibrationDevice(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const auto vibration_device_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()}; const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()};
if (applet_resource != nullptr) { if (applet_resource != nullptr) {
applet_resource->GetController<Controller_NPad>(HidController::NPad) applet_resource->GetController<Controller_NPad>(HidController::NPad)
@ -417,6 +417,7 @@ void Hid::ActivateXpad(Kernel::HLERequestContext& ctx) {
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
@ -443,19 +444,18 @@ void Hid::GetXpadIDs(Kernel::HLERequestContext& ctx) {
void Hid::ActivateSixAxisSensor(Kernel::HLERequestContext& ctx) { void Hid::ActivateSixAxisSensor(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
Controller_NPad::DeviceHandle sixaxis_handle; u32 basic_xpad_id;
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(true); // This function does nothing on 10.0.0+
LOG_DEBUG(Service_HID, LOG_WARNING(Service_HID, "(STUBBED) called, basic_xpad_id={}, applet_resource_user_id={}",
"called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", parameters.basic_xpad_id, parameters.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}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
@ -464,19 +464,18 @@ void Hid::ActivateSixAxisSensor(Kernel::HLERequestContext& ctx) {
void Hid::DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx) { void Hid::DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
Controller_NPad::DeviceHandle sixaxis_handle; u32 basic_xpad_id;
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(false); // This function does nothing on 10.0.0+
LOG_DEBUG(Service_HID, LOG_WARNING(Service_HID, "(STUBBED) called, basic_xpad_id={}, applet_resource_user_id={}",
"called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", parameters.basic_xpad_id, parameters.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}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
@ -485,14 +484,16 @@ void Hid::DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx) {
void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) { void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
Controller_NPad::DeviceHandle sixaxis_handle; Core::HID::SixAxisSensorHandle sixaxis_handle;
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(true); applet_resource->GetController<Controller_NPad>(HidController::NPad)
.SetSixAxisEnabled(parameters.sixaxis_handle, true);
LOG_DEBUG(Service_HID, LOG_DEBUG(Service_HID,
"called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@ -506,14 +507,16 @@ void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) {
void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) { void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
Controller_NPad::DeviceHandle sixaxis_handle; Core::HID::SixAxisSensorHandle sixaxis_handle;
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(false); applet_resource->GetController<Controller_NPad>(HidController::NPad)
.SetSixAxisEnabled(parameters.sixaxis_handle, false);
LOG_DEBUG(Service_HID, LOG_DEBUG(Service_HID,
"called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@ -529,15 +532,19 @@ void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) {
struct Parameters { struct Parameters {
bool enable_sixaxis_sensor_fusion; bool enable_sixaxis_sensor_fusion;
INSERT_PADDING_BYTES_NOINIT(3); INSERT_PADDING_BYTES_NOINIT(3);
Controller_NPad::DeviceHandle sixaxis_handle; Core::HID::SixAxisSensorHandle sixaxis_handle;
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
LOG_WARNING(Service_HID, applet_resource->GetController<Controller_NPad>(HidController::NPad)
"(STUBBED) called, enable_sixaxis_sensor_fusion={}, npad_type={}, npad_id={}, " .SetSixAxisFusionEnabled(parameters.sixaxis_handle,
parameters.enable_sixaxis_sensor_fusion);
LOG_DEBUG(Service_HID,
"called, enable_sixaxis_sensor_fusion={}, npad_type={}, npad_id={}, "
"device_index={}, applet_resource_user_id={}", "device_index={}, applet_resource_user_id={}",
parameters.enable_sixaxis_sensor_fusion, parameters.sixaxis_handle.npad_type, parameters.enable_sixaxis_sensor_fusion, parameters.sixaxis_handle.npad_type,
parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index, parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index,
@ -550,9 +557,9 @@ void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) {
void Hid::SetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) { void Hid::SetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
Controller_NPad::DeviceHandle sixaxis_handle; Core::HID::SixAxisSensorHandle sixaxis_handle;
f32 parameter1; Core::HID::SixAxisSensorFusionParameters sixaxis_fusion;
f32 parameter2; INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
@ -560,14 +567,14 @@ void Hid::SetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
applet_resource->GetController<Controller_NPad>(HidController::NPad) applet_resource->GetController<Controller_NPad>(HidController::NPad)
.SetSixAxisFusionParameters(parameters.parameter1, parameters.parameter2); .SetSixAxisFusionParameters(parameters.sixaxis_handle, parameters.sixaxis_fusion);
LOG_WARNING(Service_HID, LOG_DEBUG(Service_HID,
"(STUBBED) called, npad_type={}, npad_id={}, device_index={}, parameter1={}, " "called, npad_type={}, npad_id={}, device_index={}, parameter1={}, "
"parameter2={}, applet_resource_user_id={}", "parameter2={}, applet_resource_user_id={}",
parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
parameters.sixaxis_handle.device_index, parameters.parameter1, parameters.sixaxis_handle.device_index, parameters.sixaxis_fusion.parameter1,
parameters.parameter2, parameters.applet_resource_user_id); parameters.sixaxis_fusion.parameter2, parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
@ -576,35 +583,33 @@ void Hid::SetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
void Hid::GetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) { void Hid::GetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
Controller_NPad::DeviceHandle sixaxis_handle; Core::HID::SixAxisSensorHandle sixaxis_handle;
INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
f32 parameter1 = 0;
f32 parameter2 = 0;
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
std::tie(parameter1, parameter2) = const auto sixaxis_fusion_parameters =
applet_resource->GetController<Controller_NPad>(HidController::NPad) applet_resource->GetController<Controller_NPad>(HidController::NPad)
.GetSixAxisFusionParameters(); .GetSixAxisFusionParameters(parameters.sixaxis_handle);
LOG_WARNING( LOG_DEBUG(Service_HID,
Service_HID, "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
"(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.npad_type, parameters.sixaxis_handle.npad_id,
parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.Push(parameter1); rb.PushRaw(sixaxis_fusion_parameters);
rb.Push(parameter2);
} }
void Hid::ResetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) { void Hid::ResetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
Controller_NPad::DeviceHandle sixaxis_handle; Core::HID::SixAxisSensorHandle sixaxis_handle;
INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
@ -612,11 +617,10 @@ void Hid::ResetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
applet_resource->GetController<Controller_NPad>(HidController::NPad) applet_resource->GetController<Controller_NPad>(HidController::NPad)
.ResetSixAxisFusionParameters(); .ResetSixAxisFusionParameters(parameters.sixaxis_handle);
LOG_WARNING( LOG_DEBUG(Service_HID,
Service_HID, "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
"(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.npad_type, parameters.sixaxis_handle.npad_id,
parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
@ -626,12 +630,12 @@ void Hid::ResetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const auto sixaxis_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()}; const auto sixaxis_handle{rp.PopRaw<Core::HID::SixAxisSensorHandle>()};
const auto drift_mode{rp.PopEnum<Controller_NPad::GyroscopeZeroDriftMode>()}; const auto drift_mode{rp.PopEnum<Controller_NPad::GyroscopeZeroDriftMode>()};
const auto applet_resource_user_id{rp.Pop<u64>()}; const auto applet_resource_user_id{rp.Pop<u64>()};
applet_resource->GetController<Controller_NPad>(HidController::NPad) applet_resource->GetController<Controller_NPad>(HidController::NPad)
.SetGyroscopeZeroDriftMode(drift_mode); .SetGyroscopeZeroDriftMode(sixaxis_handle, drift_mode);
LOG_DEBUG(Service_HID, LOG_DEBUG(Service_HID,
"called, npad_type={}, npad_id={}, device_index={}, drift_mode={}, " "called, npad_type={}, npad_id={}, device_index={}, drift_mode={}, "
@ -646,10 +650,11 @@ void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
void Hid::GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { void Hid::GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
Controller_NPad::DeviceHandle sixaxis_handle; Core::HID::SixAxisSensorHandle sixaxis_handle;
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
@ -661,21 +666,23 @@ void Hid::GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad) rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad)
.GetGyroscopeZeroDriftMode()); .GetGyroscopeZeroDriftMode(parameters.sixaxis_handle));
} }
void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
Controller_NPad::DeviceHandle sixaxis_handle; Core::HID::SixAxisSensorHandle sixaxis_handle;
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
const auto drift_mode{Controller_NPad::GyroscopeZeroDriftMode::Standard};
applet_resource->GetController<Controller_NPad>(HidController::NPad) applet_resource->GetController<Controller_NPad>(HidController::NPad)
.SetGyroscopeZeroDriftMode(Controller_NPad::GyroscopeZeroDriftMode::Standard); .SetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode);
LOG_DEBUG(Service_HID, LOG_DEBUG(Service_HID,
"called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@ -689,10 +696,11 @@ void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) { void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
Controller_NPad::DeviceHandle sixaxis_handle; Core::HID::SixAxisSensorHandle sixaxis_handle;
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
@ -704,16 +712,17 @@ void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad) rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad)
.IsSixAxisSensorAtRest()); .IsSixAxisSensorAtRest(parameters.sixaxis_handle));
} }
void Hid::IsFirmwareUpdateAvailableForSixAxisSensor(Kernel::HLERequestContext& ctx) { void Hid::IsFirmwareUpdateAvailableForSixAxisSensor(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
Controller_NPad::DeviceHandle sixaxis_handle; Core::HID::SixAxisSensorHandle sixaxis_handle;
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
@ -735,13 +744,14 @@ void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) {
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
applet_resource->ActivateController(HidController::Gesture); applet_resource->ActivateController(HidController::Gesture);
LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", parameters.unknown, LOG_WARNING(Service_HID, "(STUBBED) called, unknown={}, applet_resource_user_id={}",
parameters.applet_resource_user_id); parameters.unknown, parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
@ -749,12 +759,20 @@ void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) {
void Hid::SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { void Hid::SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const auto supported_styleset{rp.Pop<u32>()}; struct Parameters {
Core::HID::NpadStyleSet supported_styleset;
INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id;
};
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()};
applet_resource->GetController<Controller_NPad>(HidController::NPad) applet_resource->GetController<Controller_NPad>(HidController::NPad)
.SetSupportedStyleSet({supported_styleset}); .SetSupportedStyleSet({parameters.supported_styleset});
LOG_DEBUG(Service_HID, "called, supported_styleset={}", supported_styleset); LOG_DEBUG(Service_HID, "called, supported_styleset={}, applet_resource_user_id={}",
parameters.supported_styleset, parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
@ -768,7 +786,7 @@ void Hid::GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad) rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad)
.GetSupportedStyleSet() .GetSupportedStyleSet()
.raw); .raw);
} }
@ -813,11 +831,12 @@ void Hid::DeactivateNpad(Kernel::HLERequestContext& ctx) {
void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) { void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
u32 npad_id; Core::HID::NpadIdType npad_id;
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
u64 unknown; u64 unknown;
}; };
static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
@ -833,10 +852,11 @@ void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) {
void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) { void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
u32 npad_id; Core::HID::NpadIdType npad_id;
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
@ -852,7 +872,7 @@ void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) {
void Hid::GetPlayerLedPattern(Kernel::HLERequestContext& ctx) { void Hid::GetPlayerLedPattern(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const auto npad_id{rp.Pop<u32>()}; const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()};
LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id); LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id);
@ -867,16 +887,17 @@ void Hid::ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) {
// Should have no effect with how our npad sets up the data // Should have no effect with how our npad sets up the data
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
u32 unknown; s32 revision;
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
applet_resource->ActivateController(HidController::NPad); applet_resource->ActivateController(HidController::NPad);
LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", parameters.unknown, LOG_DEBUG(Service_HID, "called, revision={}, applet_resource_user_id={}", parameters.revision,
parameters.applet_resource_user_id); parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
@ -911,10 +932,11 @@ void Hid::GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) { void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
u32 npad_id; Core::HID::NpadIdType npad_id;
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
@ -932,11 +954,12 @@ void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) {
// TODO: Check the differences between this and SetNpadJoyAssignmentModeSingleByDefault // TODO: Check the differences between this and SetNpadJoyAssignmentModeSingleByDefault
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
u32 npad_id; Core::HID::NpadIdType npad_id;
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
u64 npad_joy_device_type; u64 npad_joy_device_type;
}; };
static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
@ -955,10 +978,11 @@ void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) {
void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
u32 npad_id; Core::HID::NpadIdType npad_id;
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
@ -974,8 +998,8 @@ void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) { void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const auto npad_id_1{rp.Pop<u32>()}; const auto npad_id_1{rp.PopEnum<Core::HID::NpadIdType>()};
const auto npad_id_2{rp.Pop<u32>()}; const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
const auto applet_resource_user_id{rp.Pop<u64>()}; const auto applet_resource_user_id{rp.Pop<u64>()};
applet_resource->GetController<Controller_NPad>(HidController::NPad) applet_resource->GetController<Controller_NPad>(HidController::NPad)
@ -1041,8 +1065,8 @@ void Hid::GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) { void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const auto npad_id_1{rp.Pop<u32>()}; const auto npad_id_1{rp.PopEnum<Core::HID::NpadIdType>()};
const auto npad_id_2{rp.Pop<u32>()}; const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
const auto applet_resource_user_id{rp.Pop<u64>()}; const auto applet_resource_user_id{rp.Pop<u64>()};
const bool res = applet_resource->GetController<Controller_NPad>(HidController::NPad) const bool res = applet_resource->GetController<Controller_NPad>(HidController::NPad)
@ -1063,10 +1087,11 @@ void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) {
void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx) { void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
u32 npad_id; Core::HID::NpadIdType npad_id;
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
@ -1084,9 +1109,10 @@ void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& c
struct Parameters { struct Parameters {
bool unintended_home_button_input_protection; bool unintended_home_button_input_protection;
INSERT_PADDING_BYTES_NOINIT(3); INSERT_PADDING_BYTES_NOINIT(3);
u32 npad_id; Core::HID::NpadIdType npad_id;
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
@ -1108,6 +1134,7 @@ void Hid::SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
bool analog_stick_use_center_clamp; bool analog_stick_use_center_clamp;
INSERT_PADDING_BYTES_NOINIT(7);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
@ -1127,7 +1154,7 @@ void Hid::SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx) {
void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const auto vibration_device_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()}; const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()};
Core::HID::VibrationDeviceInfo vibration_device_info; Core::HID::VibrationDeviceInfo vibration_device_info;
@ -1149,13 +1176,13 @@ void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
} }
switch (vibration_device_handle.device_index) { switch (vibration_device_handle.device_index) {
case Controller_NPad::DeviceIndex::Left: case Core::HID::DeviceIndex::Left:
vibration_device_info.position = Core::HID::VibrationDevicePosition::Left; vibration_device_info.position = Core::HID::VibrationDevicePosition::Left;
break; break;
case Controller_NPad::DeviceIndex::Right: case Core::HID::DeviceIndex::Right:
vibration_device_info.position = Core::HID::VibrationDevicePosition::Right; vibration_device_info.position = Core::HID::VibrationDevicePosition::Right;
break; break;
case Controller_NPad::DeviceIndex::None: case Core::HID::DeviceIndex::None:
default: default:
UNREACHABLE_MSG("DeviceIndex should never be None!"); UNREACHABLE_MSG("DeviceIndex should never be None!");
vibration_device_info.position = Core::HID::VibrationDevicePosition::None; vibration_device_info.position = Core::HID::VibrationDevicePosition::None;
@ -1173,11 +1200,12 @@ void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
Controller_NPad::DeviceHandle vibration_device_handle; Core::HID::VibrationDeviceHandle vibration_device_handle;
Controller_NPad::VibrationValue vibration_value; Core::HID::VibrationValue vibration_value;
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x20, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
@ -1197,10 +1225,11 @@ void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) {
void Hid::GetActualVibrationValue(Kernel::HLERequestContext& ctx) { void Hid::GetActualVibrationValue(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
Controller_NPad::DeviceHandle vibration_device_handle; Core::HID::VibrationDeviceHandle vibration_device_handle;
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
@ -1251,10 +1280,10 @@ void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) {
const auto handles = ctx.ReadBuffer(0); const auto handles = ctx.ReadBuffer(0);
const auto vibrations = ctx.ReadBuffer(1); const auto vibrations = ctx.ReadBuffer(1);
std::vector<Controller_NPad::DeviceHandle> vibration_device_handles( std::vector<Core::HID::VibrationDeviceHandle> vibration_device_handles(
handles.size() / sizeof(Controller_NPad::DeviceHandle)); handles.size() / sizeof(Core::HID::VibrationDeviceHandle));
std::vector<Controller_NPad::VibrationValue> vibration_values( std::vector<Core::HID::VibrationValue> vibration_values(vibrations.size() /
vibrations.size() / sizeof(Controller_NPad::VibrationValue)); sizeof(Core::HID::VibrationValue));
std::memcpy(vibration_device_handles.data(), handles.data(), handles.size()); std::memcpy(vibration_device_handles.data(), handles.data(), handles.size());
std::memcpy(vibration_values.data(), vibrations.data(), vibrations.size()); std::memcpy(vibration_values.data(), vibrations.data(), vibrations.size());
@ -1271,7 +1300,8 @@ void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) {
void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
Controller_NPad::DeviceHandle vibration_device_handle; Core::HID::VibrationDeviceHandle vibration_device_handle;
INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
Core::HID::VibrationGcErmCommand gc_erm_command; Core::HID::VibrationGcErmCommand gc_erm_command;
}; };
@ -1288,25 +1318,25 @@ void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
const auto vibration_value = [parameters] { const auto vibration_value = [parameters] {
switch (parameters.gc_erm_command) { switch (parameters.gc_erm_command) {
case Core::HID::VibrationGcErmCommand::Stop: case Core::HID::VibrationGcErmCommand::Stop:
return Controller_NPad::VibrationValue{ return Core::HID::VibrationValue{
.amp_low = 0.0f, .low_amplitude = 0.0f,
.freq_low = 160.0f, .low_frequency = 160.0f,
.amp_high = 0.0f, .high_amplitude = 0.0f,
.freq_high = 320.0f, .high_frequency = 320.0f,
}; };
case Core::HID::VibrationGcErmCommand::Start: case Core::HID::VibrationGcErmCommand::Start:
return Controller_NPad::VibrationValue{ return Core::HID::VibrationValue{
.amp_low = 1.0f, .low_amplitude = 1.0f,
.freq_low = 160.0f, .low_frequency = 160.0f,
.amp_high = 1.0f, .high_amplitude = 1.0f,
.freq_high = 320.0f, .high_frequency = 320.0f,
}; };
case Core::HID::VibrationGcErmCommand::StopHard: case Core::HID::VibrationGcErmCommand::StopHard:
return Controller_NPad::VibrationValue{ return Core::HID::VibrationValue{
.amp_low = 0.0f, .low_amplitude = 0.0f,
.freq_low = 0.0f, .low_frequency = 0.0f,
.amp_high = 0.0f, .high_amplitude = 0.0f,
.freq_high = 0.0f, .high_frequency = 0.0f,
}; };
default: default:
return Controller_NPad::DEFAULT_VIBRATION_VALUE; return Controller_NPad::DEFAULT_VIBRATION_VALUE;
@ -1331,7 +1361,7 @@ void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
Controller_NPad::DeviceHandle vibration_device_handle; Core::HID::VibrationDeviceHandle vibration_device_handle;
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
@ -1342,7 +1372,7 @@ void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
.GetLastVibration(parameters.vibration_device_handle); .GetLastVibration(parameters.vibration_device_handle);
const auto gc_erm_command = [last_vibration] { const auto gc_erm_command = [last_vibration] {
if (last_vibration.amp_low != 0.0f || last_vibration.amp_high != 0.0f) { if (last_vibration.low_amplitude != 0.0f || last_vibration.high_amplitude != 0.0f) {
return Core::HID::VibrationGcErmCommand::Start; return Core::HID::VibrationGcErmCommand::Start;
} }
@ -1352,7 +1382,7 @@ void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
* SendVibrationGcErmCommand, in order to differentiate between Stop and StopHard commands. * SendVibrationGcErmCommand, in order to differentiate between Stop and StopHard commands.
* This is done to reuse the controller vibration functions made for regular controllers. * This is done to reuse the controller vibration functions made for regular controllers.
*/ */
if (last_vibration.freq_low == 0.0f && last_vibration.freq_high == 0.0f) { if (last_vibration.low_frequency == 0.0f && last_vibration.high_frequency == 0.0f) {
return Core::HID::VibrationGcErmCommand::StopHard; return Core::HID::VibrationGcErmCommand::StopHard;
} }
@ -1396,10 +1426,11 @@ void Hid::EndPermitVibrationSession(Kernel::HLERequestContext& ctx) {
void Hid::IsVibrationDeviceMounted(Kernel::HLERequestContext& ctx) { void Hid::IsVibrationDeviceMounted(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
Controller_NPad::DeviceHandle vibration_device_handle; Core::HID::VibrationDeviceHandle vibration_device_handle;
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
@ -1430,18 +1461,18 @@ void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {
void Hid::StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { void Hid::StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
Controller_NPad::DeviceHandle sixaxis_handle; Core::HID::ConsoleSixAxisSensorHandle console_sixaxis_handle;
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
LOG_WARNING( LOG_WARNING(Service_HID,
Service_HID, "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}",
"(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", parameters.console_sixaxis_handle.unknown_1,
parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, parameters.console_sixaxis_handle.unknown_2, parameters.applet_resource_user_id);
parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
@ -1450,18 +1481,18 @@ void Hid::StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {
void Hid::StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { void Hid::StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
struct Parameters { struct Parameters {
Controller_NPad::DeviceHandle sixaxis_handle; Core::HID::ConsoleSixAxisSensorHandle console_sixaxis_handle;
INSERT_PADDING_WORDS_NOINIT(1); INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id; u64 applet_resource_user_id;
}; };
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()}; const auto parameters{rp.PopRaw<Parameters>()};
LOG_WARNING( LOG_WARNING(Service_HID,
Service_HID, "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}",
"(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", parameters.console_sixaxis_handle.unknown_1,
parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, parameters.console_sixaxis_handle.unknown_2, parameters.applet_resource_user_id);
parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
@ -1615,10 +1646,8 @@ void Hid::SetNpadCommunicationMode(Kernel::HLERequestContext& ctx) {
void Hid::GetNpadCommunicationMode(Kernel::HLERequestContext& ctx) { void Hid::GetNpadCommunicationMode(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", LOG_WARNING(Service_HID, "(STUBBED) called");
applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);

View File

@ -627,7 +627,8 @@ void ConfigureInputPlayer::UpdateInputDeviceCombobox() {
return; return;
} }
const auto devices = emulated_controller->GetMappedDevices(Core::HID::DeviceIndex::AllDevices); const auto devices =
emulated_controller->GetMappedDevices(Core::HID::EmulatedDeviceIndex::AllDevices);
UpdateInputDevices(); UpdateInputDevices();
if (devices.empty()) { if (devices.empty()) {
@ -846,6 +847,7 @@ void ConfigureInputPlayer::SetConnectableControllers() {
if (!is_powered_on) { if (!is_powered_on) {
add_controllers(true); add_controllers(true);
return;
} }
add_controllers(false, hid_core.GetSupportedStyleTag()); add_controllers(false, hid_core.GetSupportedStyleTag());

View File

@ -357,7 +357,8 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center)
DrawCircle(p, center + QPoint(26, 71), 5); DrawCircle(p, center + QPoint(26, 71), 5);
// Draw battery // Draw battery
DrawBattery(p, center + QPoint(-170, -140), battery_values[Core::HID::DeviceIndex::LeftIndex]); DrawBattery(p, center + QPoint(-170, -140),
battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);
} }
void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center) { void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center) {
@ -483,7 +484,8 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center
DrawSymbol(p, center + QPoint(-26, 66), Symbol::House, 5); DrawSymbol(p, center + QPoint(-26, 66), Symbol::House, 5);
// Draw battery // Draw battery
DrawBattery(p, center + QPoint(110, -140), battery_values[Core::HID::DeviceIndex::RightIndex]); DrawBattery(p, center + QPoint(110, -140),
battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]);
} }
void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) { void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) {
@ -619,8 +621,10 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center)
DrawSymbol(p, center + QPoint(50, 60), Symbol::House, 4.2f); DrawSymbol(p, center + QPoint(50, 60), Symbol::House, 4.2f);
// Draw battery // Draw battery
DrawBattery(p, center + QPoint(-100, -160), battery_values[Core::HID::DeviceIndex::LeftIndex]); DrawBattery(p, center + QPoint(-100, -160),
DrawBattery(p, center + QPoint(40, -160), battery_values[Core::HID::DeviceIndex::RightIndex]); battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);
DrawBattery(p, center + QPoint(40, -160),
battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]);
} }
void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF center) { void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF center) {
@ -721,8 +725,10 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen
DrawSymbol(p, center + QPoint(161, 37), Symbol::House, 2.75f); DrawSymbol(p, center + QPoint(161, 37), Symbol::House, 2.75f);
// Draw battery // Draw battery
DrawBattery(p, center + QPoint(-200, 110), battery_values[Core::HID::DeviceIndex::LeftIndex]); DrawBattery(p, center + QPoint(-200, 110),
DrawBattery(p, center + QPoint(130, 110), battery_values[Core::HID::DeviceIndex::RightIndex]); battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);
DrawBattery(p, center + QPoint(130, 110),
battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]);
} }
void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) { void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) {
@ -812,7 +818,8 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center)
DrawSymbol(p, center + QPoint(29, -56), Symbol::House, 3.9f); DrawSymbol(p, center + QPoint(29, -56), Symbol::House, 3.9f);
// Draw battery // Draw battery
DrawBattery(p, center + QPoint(-30, -160), battery_values[Core::HID::DeviceIndex::LeftIndex]); DrawBattery(p, center + QPoint(-30, -160),
battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);
} }
void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) { void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) {
@ -868,7 +875,8 @@ void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) {
DrawCircleButton(p, center + QPoint(0, -44), button_values[Plus], 8); DrawCircleButton(p, center + QPoint(0, -44), button_values[Plus], 8);
// Draw battery // Draw battery
DrawBattery(p, center + QPoint(-30, -165), battery_values[Core::HID::DeviceIndex::LeftIndex]); DrawBattery(p, center + QPoint(-30, -165),
battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);
} }
constexpr std::array<float, 13 * 2> symbol_a = { constexpr std::array<float, 13 * 2> symbol_a = {