diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/hid/controllers/npad.cpp | 1100 | ||||
| -rw-r--r-- | src/core/hle/service/hid/controllers/npad.h | 395 |
2 files changed, 605 insertions, 890 deletions
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 196876810..03cbd42f4 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | #include "common/settings.h" | 12 | #include "common/settings.h" |
| 13 | #include "core/core.h" | 13 | #include "core/core.h" |
| 14 | #include "core/core_timing.h" | 14 | #include "core/core_timing.h" |
| 15 | #include "core/frontend/input.h" | ||
| 16 | #include "core/hle/kernel/k_event.h" | 15 | #include "core/hle/kernel/k_event.h" |
| 17 | #include "core/hle/kernel/k_readable_event.h" | 16 | #include "core/hle/kernel/k_readable_event.h" |
| 18 | #include "core/hle/kernel/k_writable_event.h" | 17 | #include "core/hle/kernel/k_writable_event.h" |
| @@ -20,64 +19,13 @@ | |||
| 20 | #include "core/hle/service/kernel_helpers.h" | 19 | #include "core/hle/service/kernel_helpers.h" |
| 21 | 20 | ||
| 22 | namespace Service::HID { | 21 | namespace Service::HID { |
| 23 | constexpr s32 HID_JOYSTICK_MAX = 0x7fff; | ||
| 24 | constexpr s32 HID_TRIGGER_MAX = 0x7fff; | ||
| 25 | [[maybe_unused]] constexpr s32 HID_JOYSTICK_MIN = -0x7fff; | ||
| 26 | constexpr std::size_t NPAD_OFFSET = 0x9A00; | 22 | constexpr std::size_t NPAD_OFFSET = 0x9A00; |
| 27 | constexpr u32 BATTERY_FULL = 2; | ||
| 28 | constexpr u32 MAX_NPAD_ID = 7; | 23 | constexpr u32 MAX_NPAD_ID = 7; |
| 29 | constexpr std::size_t HANDHELD_INDEX = 8; | 24 | constexpr std::size_t HANDHELD_INDEX = 8; |
| 30 | constexpr std::array<u32, 10> npad_id_list{ | 25 | constexpr std::array<u32, 10> npad_id_list{ |
| 31 | 0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN, | 26 | 0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN, |
| 32 | }; | 27 | }; |
| 33 | 28 | ||
| 34 | enum class JoystickId : std::size_t { | ||
| 35 | Joystick_Left, | ||
| 36 | Joystick_Right, | ||
| 37 | }; | ||
| 38 | |||
| 39 | Controller_NPad::NPadControllerType Controller_NPad::MapSettingsTypeToNPad( | ||
| 40 | Settings::ControllerType type) { | ||
| 41 | switch (type) { | ||
| 42 | case Settings::ControllerType::ProController: | ||
| 43 | return NPadControllerType::ProController; | ||
| 44 | case Settings::ControllerType::DualJoyconDetached: | ||
| 45 | return NPadControllerType::JoyDual; | ||
| 46 | case Settings::ControllerType::LeftJoycon: | ||
| 47 | return NPadControllerType::JoyLeft; | ||
| 48 | case Settings::ControllerType::RightJoycon: | ||
| 49 | return NPadControllerType::JoyRight; | ||
| 50 | case Settings::ControllerType::Handheld: | ||
| 51 | return NPadControllerType::Handheld; | ||
| 52 | case Settings::ControllerType::GameCube: | ||
| 53 | return NPadControllerType::GameCube; | ||
| 54 | default: | ||
| 55 | UNREACHABLE(); | ||
| 56 | return NPadControllerType::ProController; | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | Settings::ControllerType Controller_NPad::MapNPadToSettingsType( | ||
| 61 | Controller_NPad::NPadControllerType type) { | ||
| 62 | switch (type) { | ||
| 63 | case NPadControllerType::ProController: | ||
| 64 | return Settings::ControllerType::ProController; | ||
| 65 | case NPadControllerType::JoyDual: | ||
| 66 | return Settings::ControllerType::DualJoyconDetached; | ||
| 67 | case NPadControllerType::JoyLeft: | ||
| 68 | return Settings::ControllerType::LeftJoycon; | ||
| 69 | case NPadControllerType::JoyRight: | ||
| 70 | return Settings::ControllerType::RightJoycon; | ||
| 71 | case NPadControllerType::Handheld: | ||
| 72 | return Settings::ControllerType::Handheld; | ||
| 73 | case NPadControllerType::GameCube: | ||
| 74 | return Settings::ControllerType::GameCube; | ||
| 75 | default: | ||
| 76 | UNREACHABLE(); | ||
| 77 | return Settings::ControllerType::ProController; | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) { | 29 | std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) { |
| 82 | switch (npad_id) { | 30 | switch (npad_id) { |
| 83 | case 0: | 31 | case 0: |
| @@ -143,118 +91,157 @@ bool Controller_NPad::IsNpadIdValid(u32 npad_id) { | |||
| 143 | 91 | ||
| 144 | bool Controller_NPad::IsDeviceHandleValid(const DeviceHandle& device_handle) { | 92 | bool Controller_NPad::IsDeviceHandleValid(const DeviceHandle& device_handle) { |
| 145 | return IsNpadIdValid(device_handle.npad_id) && | 93 | return IsNpadIdValid(device_handle.npad_id) && |
| 146 | device_handle.npad_type < NpadType::MaxNpadType && | 94 | device_handle.npad_type < Core::HID::NpadType::MaxNpadType && |
| 147 | device_handle.device_index < DeviceIndex::MaxDeviceIndex; | 95 | device_handle.device_index < DeviceIndex::MaxDeviceIndex; |
| 148 | } | 96 | } |
| 149 | 97 | ||
| 150 | Controller_NPad::Controller_NPad(Core::System& system_, | 98 | Controller_NPad::Controller_NPad(Core::System& system_, |
| 151 | KernelHelpers::ServiceContext& service_context_) | 99 | KernelHelpers::ServiceContext& service_context_) |
| 152 | : ControllerBase{system_}, service_context{service_context_} { | 100 | : ControllerBase{system_}, service_context{service_context_} { |
| 153 | latest_vibration_values.fill({DEFAULT_VIBRATION_VALUE, DEFAULT_VIBRATION_VALUE}); | 101 | for (std::size_t i = 0; i < controller_data.size(); ++i) { |
| 102 | auto& controller = controller_data[i]; | ||
| 103 | controller.device = system.HIDCore().GetEmulatedControllerByIndex(i); | ||
| 104 | controller.vibration[0].latest_vibration_value = DEFAULT_VIBRATION_VALUE; | ||
| 105 | controller.vibration[1].latest_vibration_value = DEFAULT_VIBRATION_VALUE; | ||
| 106 | Core::HID::ControllerUpdateCallback engine_callback{ | ||
| 107 | [this, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }}; | ||
| 108 | controller.callback_key = controller.device->SetCallback(engine_callback); | ||
| 109 | } | ||
| 154 | } | 110 | } |
| 155 | 111 | ||
| 156 | Controller_NPad::~Controller_NPad() { | 112 | Controller_NPad::~Controller_NPad() { |
| 113 | for (std::size_t i = 0; i < controller_data.size(); ++i) { | ||
| 114 | auto& controller = controller_data[i]; | ||
| 115 | controller.device->DeleteCallback(controller.callback_key); | ||
| 116 | } | ||
| 157 | OnRelease(); | 117 | OnRelease(); |
| 158 | } | 118 | } |
| 159 | 119 | ||
| 120 | void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, | ||
| 121 | std::size_t controller_idx) { | ||
| 122 | if (type == Core::HID::ControllerTriggerType::All) { | ||
| 123 | ControllerUpdate(Core::HID::ControllerTriggerType::Type, controller_idx); | ||
| 124 | ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx); | ||
| 125 | return; | ||
| 126 | } | ||
| 127 | |||
| 128 | switch (type) { | ||
| 129 | case Core::HID::ControllerTriggerType::Connected: | ||
| 130 | InitNewlyAddedController(controller_idx); | ||
| 131 | break; | ||
| 132 | case Core::HID::ControllerTriggerType::Disconnected: | ||
| 133 | DisconnectNpadAtIndex(controller_idx); | ||
| 134 | break; | ||
| 135 | case Core::HID::ControllerTriggerType::Type: { | ||
| 136 | auto& controller = controller_data[controller_idx]; | ||
| 137 | if (controller.device->IsConnected()) { | ||
| 138 | LOG_ERROR(Service_HID, "Controller type changed without turning off the controller"); | ||
| 139 | } | ||
| 140 | break; | ||
| 141 | } | ||
| 142 | default: | ||
| 143 | break; | ||
| 144 | } | ||
| 145 | } | ||
| 146 | |||
| 160 | void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { | 147 | void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { |
| 161 | const auto controller_type = connected_controllers[controller_idx].type; | 148 | auto& controller = controller_data[controller_idx]; |
| 162 | auto& controller = shared_memory_entries[controller_idx]; | 149 | const auto controller_type = controller.device->GetNpadType(); |
| 163 | if (controller_type == NPadControllerType::None) { | 150 | auto& shared_memory = controller.shared_memory_entry; |
| 164 | styleset_changed_events[controller_idx]->GetWritableEvent().Signal(); | 151 | if (controller_type == Core::HID::NpadType::None) { |
| 152 | controller.styleset_changed_event->GetWritableEvent().Signal(); | ||
| 165 | return; | 153 | return; |
| 166 | } | 154 | } |
| 167 | controller.style_set.raw = 0; // Zero out | 155 | shared_memory.style_set.raw = 0; // Zero out |
| 168 | controller.device_type.raw = 0; | 156 | shared_memory.device_type.raw = 0; |
| 169 | controller.system_properties.raw = 0; | 157 | shared_memory.system_properties.raw = 0; |
| 170 | switch (controller_type) { | 158 | switch (controller_type) { |
| 171 | case NPadControllerType::None: | 159 | case Core::HID::NpadType::None: |
| 172 | UNREACHABLE(); | 160 | UNREACHABLE(); |
| 173 | break; | 161 | break; |
| 174 | case NPadControllerType::ProController: | 162 | case Core::HID::NpadType::ProController: |
| 175 | controller.style_set.fullkey.Assign(1); | 163 | shared_memory.style_set.fullkey.Assign(1); |
| 176 | controller.device_type.fullkey.Assign(1); | 164 | shared_memory.device_type.fullkey.Assign(1); |
| 177 | controller.system_properties.is_vertical.Assign(1); | 165 | shared_memory.system_properties.is_vertical.Assign(1); |
| 178 | controller.system_properties.use_plus.Assign(1); | 166 | shared_memory.system_properties.use_plus.Assign(1); |
| 179 | controller.system_properties.use_minus.Assign(1); | 167 | shared_memory.system_properties.use_minus.Assign(1); |
| 180 | controller.assignment_mode = NpadAssignments::Single; | 168 | shared_memory.assignment_mode = NpadJoyAssignmentMode::Single; |
| 181 | controller.footer_type = AppletFooterUiType::SwitchProController; | 169 | shared_memory.footer_type = AppletFooterUiType::SwitchProController; |
| 182 | break; | 170 | break; |
| 183 | case NPadControllerType::Handheld: | 171 | case Core::HID::NpadType::Handheld: |
| 184 | controller.style_set.handheld.Assign(1); | 172 | shared_memory.style_set.handheld.Assign(1); |
| 185 | controller.device_type.handheld_left.Assign(1); | 173 | shared_memory.device_type.handheld_left.Assign(1); |
| 186 | controller.device_type.handheld_right.Assign(1); | 174 | shared_memory.device_type.handheld_right.Assign(1); |
| 187 | controller.system_properties.is_vertical.Assign(1); | 175 | shared_memory.system_properties.is_vertical.Assign(1); |
| 188 | controller.system_properties.use_plus.Assign(1); | 176 | shared_memory.system_properties.use_plus.Assign(1); |
| 189 | controller.system_properties.use_minus.Assign(1); | 177 | shared_memory.system_properties.use_minus.Assign(1); |
| 190 | controller.assignment_mode = NpadAssignments::Dual; | 178 | shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual; |
| 191 | controller.footer_type = AppletFooterUiType::HandheldJoyConLeftJoyConRight; | 179 | shared_memory.footer_type = AppletFooterUiType::HandheldJoyConLeftJoyConRight; |
| 192 | break; | 180 | break; |
| 193 | case NPadControllerType::JoyDual: | 181 | case Core::HID::NpadType::JoyconDual: |
| 194 | controller.style_set.joycon_dual.Assign(1); | 182 | shared_memory.style_set.joycon_dual.Assign(1); |
| 195 | controller.device_type.joycon_left.Assign(1); | 183 | shared_memory.device_type.joycon_left.Assign(1); |
| 196 | controller.device_type.joycon_right.Assign(1); | 184 | shared_memory.device_type.joycon_right.Assign(1); |
| 197 | controller.system_properties.is_vertical.Assign(1); | 185 | shared_memory.system_properties.is_vertical.Assign(1); |
| 198 | controller.system_properties.use_plus.Assign(1); | 186 | shared_memory.system_properties.use_plus.Assign(1); |
| 199 | controller.system_properties.use_minus.Assign(1); | 187 | shared_memory.system_properties.use_minus.Assign(1); |
| 200 | controller.assignment_mode = NpadAssignments::Dual; | 188 | shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual; |
| 201 | controller.footer_type = AppletFooterUiType::JoyDual; | 189 | shared_memory.footer_type = AppletFooterUiType::JoyDual; |
| 202 | break; | 190 | break; |
| 203 | case NPadControllerType::JoyLeft: | 191 | case Core::HID::NpadType::JoyconLeft: |
| 204 | controller.style_set.joycon_left.Assign(1); | 192 | shared_memory.style_set.joycon_left.Assign(1); |
| 205 | controller.device_type.joycon_left.Assign(1); | 193 | shared_memory.device_type.joycon_left.Assign(1); |
| 206 | controller.system_properties.is_horizontal.Assign(1); | 194 | shared_memory.system_properties.is_horizontal.Assign(1); |
| 207 | controller.system_properties.use_minus.Assign(1); | 195 | shared_memory.system_properties.use_minus.Assign(1); |
| 208 | controller.assignment_mode = NpadAssignments::Single; | 196 | shared_memory.assignment_mode = NpadJoyAssignmentMode::Single; |
| 209 | controller.footer_type = AppletFooterUiType::JoyLeftHorizontal; | 197 | shared_memory.footer_type = AppletFooterUiType::JoyLeftHorizontal; |
| 210 | break; | 198 | break; |
| 211 | case NPadControllerType::JoyRight: | 199 | case Core::HID::NpadType::JoyconRight: |
| 212 | controller.style_set.joycon_right.Assign(1); | 200 | shared_memory.style_set.joycon_right.Assign(1); |
| 213 | controller.device_type.joycon_right.Assign(1); | 201 | shared_memory.device_type.joycon_right.Assign(1); |
| 214 | controller.system_properties.is_horizontal.Assign(1); | 202 | shared_memory.system_properties.is_horizontal.Assign(1); |
| 215 | controller.system_properties.use_plus.Assign(1); | 203 | shared_memory.system_properties.use_plus.Assign(1); |
| 216 | controller.assignment_mode = NpadAssignments::Single; | 204 | shared_memory.assignment_mode = NpadJoyAssignmentMode::Single; |
| 217 | controller.footer_type = AppletFooterUiType::JoyRightHorizontal; | 205 | shared_memory.footer_type = AppletFooterUiType::JoyRightHorizontal; |
| 218 | break; | 206 | break; |
| 219 | case NPadControllerType::GameCube: | 207 | case Core::HID::NpadType::GameCube: |
| 220 | controller.style_set.gamecube.Assign(1); | 208 | shared_memory.style_set.gamecube.Assign(1); |
| 221 | // The GC Controller behaves like a wired Pro Controller | 209 | // The GC Controller behaves like a wired Pro Controller |
| 222 | controller.device_type.fullkey.Assign(1); | 210 | shared_memory.device_type.fullkey.Assign(1); |
| 223 | controller.system_properties.is_vertical.Assign(1); | 211 | shared_memory.system_properties.is_vertical.Assign(1); |
| 224 | controller.system_properties.use_plus.Assign(1); | 212 | shared_memory.system_properties.use_plus.Assign(1); |
| 225 | break; | 213 | break; |
| 226 | case NPadControllerType::Pokeball: | 214 | case Core::HID::NpadType::Pokeball: |
| 227 | controller.style_set.palma.Assign(1); | 215 | shared_memory.style_set.palma.Assign(1); |
| 228 | controller.device_type.palma.Assign(1); | 216 | shared_memory.device_type.palma.Assign(1); |
| 229 | controller.assignment_mode = NpadAssignments::Single; | 217 | shared_memory.assignment_mode = NpadJoyAssignmentMode::Single; |
| 218 | break; | ||
| 219 | default: | ||
| 230 | break; | 220 | break; |
| 231 | } | 221 | } |
| 232 | 222 | ||
| 233 | controller.fullkey_color.attribute = ColorAttributes::Ok; | 223 | const auto& body_colors = controller.device->GetColors(); |
| 234 | controller.fullkey_color.fullkey.body = 0; | ||
| 235 | controller.fullkey_color.fullkey.button = 0; | ||
| 236 | 224 | ||
| 237 | controller.joycon_color.attribute = ColorAttributes::Ok; | 225 | shared_memory.fullkey_color.attribute = ColorAttribute::Ok; |
| 238 | controller.joycon_color.left.body = | 226 | shared_memory.fullkey_color.fullkey = body_colors.fullkey; |
| 239 | Settings::values.players.GetValue()[controller_idx].body_color_left; | 227 | |
| 240 | controller.joycon_color.left.button = | 228 | shared_memory.joycon_color.attribute = ColorAttribute::Ok; |
| 241 | Settings::values.players.GetValue()[controller_idx].button_color_left; | 229 | shared_memory.joycon_color.left = body_colors.left; |
| 242 | controller.joycon_color.right.body = | 230 | shared_memory.joycon_color.right = body_colors.right; |
| 243 | Settings::values.players.GetValue()[controller_idx].body_color_right; | ||
| 244 | controller.joycon_color.right.button = | ||
| 245 | Settings::values.players.GetValue()[controller_idx].button_color_right; | ||
| 246 | 231 | ||
| 247 | // TODO: Investigate when we should report all batery types | 232 | // TODO: Investigate when we should report all batery types |
| 248 | controller.battery_level_dual = BATTERY_FULL; | 233 | const auto& battery_level = controller.device->GetBattery(); |
| 249 | controller.battery_level_left = BATTERY_FULL; | 234 | shared_memory.battery_level_dual = battery_level.dual.battery_level; |
| 250 | controller.battery_level_right = BATTERY_FULL; | 235 | shared_memory.battery_level_left = battery_level.left.battery_level; |
| 236 | shared_memory.battery_level_right = battery_level.right.battery_level; | ||
| 251 | 237 | ||
| 252 | SignalStyleSetChangedEvent(IndexToNPad(controller_idx)); | 238 | SignalStyleSetChangedEvent(IndexToNPad(controller_idx)); |
| 253 | } | 239 | } |
| 254 | 240 | ||
| 255 | void Controller_NPad::OnInit() { | 241 | void Controller_NPad::OnInit() { |
| 256 | for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) { | 242 | for (std::size_t i = 0; i < controller_data.size(); ++i) { |
| 257 | styleset_changed_events[i] = | 243 | auto& controller = controller_data[i]; |
| 244 | controller.styleset_changed_event = | ||
| 258 | service_context.CreateEvent(fmt::format("npad:NpadStyleSetChanged_{}", i)); | 245 | service_context.CreateEvent(fmt::format("npad:NpadStyleSetChanged_{}", i)); |
| 259 | } | 246 | } |
| 260 | 247 | ||
| @@ -262,10 +249,9 @@ void Controller_NPad::OnInit() { | |||
| 262 | return; | 249 | return; |
| 263 | } | 250 | } |
| 264 | 251 | ||
| 265 | OnLoadInputDevices(); | 252 | if (system.HIDCore().GetSupportedStyleTag().raw == 0) { |
| 266 | |||
| 267 | if (style.raw == 0) { | ||
| 268 | // We want to support all controllers | 253 | // We want to support all controllers |
| 254 | Core::HID::NpadStyleTag style{}; | ||
| 269 | style.handheld.Assign(1); | 255 | style.handheld.Assign(1); |
| 270 | style.joycon_left.Assign(1); | 256 | style.joycon_left.Assign(1); |
| 271 | style.joycon_right.Assign(1); | 257 | style.joycon_right.Assign(1); |
| @@ -273,173 +259,98 @@ void Controller_NPad::OnInit() { | |||
| 273 | style.fullkey.Assign(1); | 259 | style.fullkey.Assign(1); |
| 274 | style.gamecube.Assign(1); | 260 | style.gamecube.Assign(1); |
| 275 | style.palma.Assign(1); | 261 | style.palma.Assign(1); |
| 276 | } | 262 | system.HIDCore().SetSupportedStyleTag(style); |
| 277 | |||
| 278 | std::transform(Settings::values.players.GetValue().begin(), | ||
| 279 | Settings::values.players.GetValue().end(), connected_controllers.begin(), | ||
| 280 | [](const Settings::PlayerInput& player) { | ||
| 281 | return ControllerHolder{MapSettingsTypeToNPad(player.controller_type), | ||
| 282 | player.connected}; | ||
| 283 | }); | ||
| 284 | |||
| 285 | // Connect the Player 1 or Handheld controller if none are connected. | ||
| 286 | if (std::none_of(connected_controllers.begin(), connected_controllers.end(), | ||
| 287 | [](const ControllerHolder& controller) { return controller.is_connected; })) { | ||
| 288 | const auto controller = | ||
| 289 | MapSettingsTypeToNPad(Settings::values.players.GetValue()[0].controller_type); | ||
| 290 | if (controller == NPadControllerType::Handheld) { | ||
| 291 | Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true; | ||
| 292 | connected_controllers[HANDHELD_INDEX] = {controller, true}; | ||
| 293 | } else { | ||
| 294 | Settings::values.players.GetValue()[0].connected = true; | ||
| 295 | connected_controllers[0] = {controller, true}; | ||
| 296 | } | ||
| 297 | } | ||
| 298 | |||
| 299 | // Account for handheld | ||
| 300 | if (connected_controllers[HANDHELD_INDEX].is_connected) { | ||
| 301 | connected_controllers[HANDHELD_INDEX].type = NPadControllerType::Handheld; | ||
| 302 | } | 263 | } |
| 303 | 264 | ||
| 304 | supported_npad_id_types.resize(npad_id_list.size()); | 265 | supported_npad_id_types.resize(npad_id_list.size()); |
| 305 | std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), | 266 | std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), |
| 306 | npad_id_list.size() * sizeof(u32)); | 267 | npad_id_list.size() * sizeof(u32)); |
| 307 | 268 | ||
| 308 | for (std::size_t i = 0; i < connected_controllers.size(); ++i) { | 269 | for (std::size_t i = 0; i < controller_data.size(); ++i) { |
| 309 | const auto& controller = connected_controllers[i]; | 270 | auto& controller = controller_data[i].device; |
| 310 | if (controller.is_connected) { | 271 | if (controller->IsConnected()) { |
| 311 | AddNewControllerAt(controller.type, i); | 272 | AddNewControllerAt(controller->GetNpadType(), i); |
| 312 | } | 273 | } |
| 313 | } | 274 | } |
| 314 | } | ||
| 315 | 275 | ||
| 316 | void Controller_NPad::OnLoadInputDevices() { | 276 | // Prefill controller buffers |
| 317 | const auto& players = Settings::values.players.GetValue(); | 277 | for (auto& controller : controller_data) { |
| 318 | 278 | NPadGenericState dummy_pad_state{}; | |
| 319 | std::lock_guard lock{mutex}; | 279 | auto& npad = controller.shared_memory_entry; |
| 320 | for (std::size_t i = 0; i < players.size(); ++i) { | 280 | for (std::size_t i = 0; i < 17; ++i) { |
| 321 | std::transform(players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, | 281 | dummy_pad_state.sampling_number = |
| 322 | players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_END, | 282 | npad.fullkey_lifo.ReadCurrentEntry().sampling_number + 1; |
| 323 | buttons[i].begin(), Input::CreateDevice<Input::ButtonDevice>); | 283 | npad.fullkey_lifo.WriteNextEntry(dummy_pad_state); |
| 324 | std::transform(players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, | 284 | npad.handheld_lifo.WriteNextEntry(dummy_pad_state); |
| 325 | players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_END, | 285 | npad.joy_dual_lifo.WriteNextEntry(dummy_pad_state); |
| 326 | sticks[i].begin(), Input::CreateDevice<Input::AnalogDevice>); | 286 | npad.joy_left_lifo.WriteNextEntry(dummy_pad_state); |
| 327 | std::transform(players[i].vibrations.begin() + | 287 | npad.joy_right_lifo.WriteNextEntry(dummy_pad_state); |
| 328 | Settings::NativeVibration::VIBRATION_HID_BEGIN, | 288 | npad.joy_right_lifo.WriteNextEntry(dummy_pad_state); |
| 329 | players[i].vibrations.begin() + Settings::NativeVibration::VIBRATION_HID_END, | 289 | npad.palma_lifo.WriteNextEntry(dummy_pad_state); |
| 330 | vibrations[i].begin(), Input::CreateDevice<Input::VibrationDevice>); | ||
| 331 | std::transform(players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_BEGIN, | ||
| 332 | players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_END, | ||
| 333 | motions[i].begin(), Input::CreateDevice<Input::MotionDevice>); | ||
| 334 | for (std::size_t device_idx = 0; device_idx < vibrations[i].size(); ++device_idx) { | ||
| 335 | InitializeVibrationDeviceAtIndex(i, device_idx); | ||
| 336 | } | 290 | } |
| 337 | } | 291 | } |
| 338 | } | 292 | } |
| 339 | 293 | ||
| 340 | void Controller_NPad::OnRelease() { | 294 | void Controller_NPad::OnRelease() { |
| 341 | for (std::size_t npad_idx = 0; npad_idx < vibrations.size(); ++npad_idx) { | 295 | for (std::size_t i = 0; i < controller_data.size(); ++i) { |
| 342 | for (std::size_t device_idx = 0; device_idx < vibrations[npad_idx].size(); ++device_idx) { | 296 | auto& controller = controller_data[i]; |
| 343 | VibrateControllerAtIndex(npad_idx, device_idx, {}); | 297 | service_context.CloseEvent(controller.styleset_changed_event); |
| 298 | for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) { | ||
| 299 | VibrateControllerAtIndex(i, device_idx, {}); | ||
| 344 | } | 300 | } |
| 345 | } | 301 | } |
| 346 | |||
| 347 | for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) { | ||
| 348 | service_context.CloseEvent(styleset_changed_events[i]); | ||
| 349 | } | ||
| 350 | } | 302 | } |
| 351 | 303 | ||
| 352 | void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { | 304 | void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { |
| 353 | std::lock_guard lock{mutex}; | 305 | std::lock_guard lock{mutex}; |
| 354 | |||
| 355 | const auto controller_idx = NPadIdToIndex(npad_id); | 306 | const auto controller_idx = NPadIdToIndex(npad_id); |
| 356 | const auto controller_type = connected_controllers[controller_idx].type; | 307 | auto& controller = controller_data[controller_idx]; |
| 357 | if (!connected_controllers[controller_idx].is_connected) { | 308 | const auto controller_type = controller.device->GetNpadType(); |
| 309 | if (!controller.device->IsConnected()) { | ||
| 358 | return; | 310 | return; |
| 359 | } | 311 | } |
| 360 | auto& pad_state = npad_pad_states[controller_idx].pad_states; | 312 | |
| 361 | auto& lstick_entry = npad_pad_states[controller_idx].l_stick; | 313 | auto& pad_entry = controller.npad_pad_state; |
| 362 | auto& rstick_entry = npad_pad_states[controller_idx].r_stick; | 314 | auto& trigger_entry = controller.npad_trigger_state; |
| 363 | auto& trigger_entry = npad_trigger_states[controller_idx]; | 315 | const auto button_state = controller.device->GetNpadButtons(); |
| 364 | const auto& button_state = buttons[controller_idx]; | 316 | const auto stick_state = controller.device->GetSticks(); |
| 365 | const auto& analog_state = sticks[controller_idx]; | 317 | |
| 366 | const auto [stick_l_x_f, stick_l_y_f] = | 318 | using btn = Core::HID::NpadButton; |
| 367 | analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetStatus(); | 319 | pad_entry.npad_buttons.raw = btn::None; |
| 368 | const auto [stick_r_x_f, stick_r_y_f] = | 320 | if (controller_type != Core::HID::NpadType::JoyconLeft) { |
| 369 | analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]->GetStatus(); | 321 | constexpr btn right_button_mask = btn::A | btn::B | btn::X | btn::Y | btn::StickR | btn::R | |
| 370 | 322 | btn::ZR | btn::Plus | btn::StickRLeft | btn::StickRUp | | |
| 371 | using namespace Settings::NativeButton; | 323 | btn::StickRRight | btn::StickRDown; |
| 372 | if (controller_type != NPadControllerType::JoyLeft) { | 324 | pad_entry.npad_buttons.raw |= button_state.raw & right_button_mask; |
| 373 | pad_state.a.Assign(button_state[A - BUTTON_HID_BEGIN]->GetStatus()); | 325 | pad_entry.r_stick = stick_state.right; |
| 374 | pad_state.b.Assign(button_state[B - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 375 | pad_state.x.Assign(button_state[X - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 376 | pad_state.y.Assign(button_state[Y - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 377 | pad_state.r_stick.Assign(button_state[RStick - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 378 | pad_state.r.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 379 | pad_state.zr.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 380 | pad_state.plus.Assign(button_state[Plus - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 381 | |||
| 382 | pad_state.r_stick_right.Assign( | ||
| 383 | analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)] | ||
| 384 | ->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT)); | ||
| 385 | pad_state.r_stick_left.Assign( | ||
| 386 | analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)] | ||
| 387 | ->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT)); | ||
| 388 | pad_state.r_stick_up.Assign( | ||
| 389 | analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)] | ||
| 390 | ->GetAnalogDirectionStatus(Input::AnalogDirection::UP)); | ||
| 391 | pad_state.r_stick_down.Assign( | ||
| 392 | analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)] | ||
| 393 | ->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN)); | ||
| 394 | rstick_entry.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX); | ||
| 395 | rstick_entry.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX); | ||
| 396 | } | 326 | } |
| 397 | 327 | ||
| 398 | if (controller_type != NPadControllerType::JoyRight) { | 328 | if (controller_type != Core::HID::NpadType::JoyconRight) { |
| 399 | pad_state.d_left.Assign(button_state[DLeft - BUTTON_HID_BEGIN]->GetStatus()); | 329 | constexpr btn left_button_mask = |
| 400 | pad_state.d_up.Assign(button_state[DUp - BUTTON_HID_BEGIN]->GetStatus()); | 330 | btn::Left | btn::Up | btn::Right | btn::Down | btn::StickL | btn::L | btn::ZL | |
| 401 | pad_state.d_right.Assign(button_state[DRight - BUTTON_HID_BEGIN]->GetStatus()); | 331 | btn::Minus | btn::StickLLeft | btn::StickLUp | btn::StickLRight | btn::StickLDown; |
| 402 | pad_state.d_down.Assign(button_state[DDown - BUTTON_HID_BEGIN]->GetStatus()); | 332 | pad_entry.npad_buttons.raw |= button_state.raw & left_button_mask; |
| 403 | pad_state.l_stick.Assign(button_state[LStick - BUTTON_HID_BEGIN]->GetStatus()); | 333 | pad_entry.l_stick = stick_state.left; |
| 404 | pad_state.l.Assign(button_state[L - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 405 | pad_state.zl.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 406 | pad_state.minus.Assign(button_state[Minus - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 407 | |||
| 408 | pad_state.l_stick_right.Assign( | ||
| 409 | analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)] | ||
| 410 | ->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT)); | ||
| 411 | pad_state.l_stick_left.Assign( | ||
| 412 | analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)] | ||
| 413 | ->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT)); | ||
| 414 | pad_state.l_stick_up.Assign( | ||
| 415 | analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)] | ||
| 416 | ->GetAnalogDirectionStatus(Input::AnalogDirection::UP)); | ||
| 417 | pad_state.l_stick_down.Assign( | ||
| 418 | analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)] | ||
| 419 | ->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN)); | ||
| 420 | lstick_entry.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX); | ||
| 421 | lstick_entry.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX); | ||
| 422 | } | 334 | } |
| 423 | 335 | ||
| 424 | if (controller_type == NPadControllerType::JoyLeft) { | 336 | if (controller_type == Core::HID::NpadType::JoyconLeft) { |
| 425 | pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus()); | 337 | pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl); |
| 426 | pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus()); | 338 | pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr); |
| 427 | } | 339 | } |
| 428 | 340 | ||
| 429 | if (controller_type == NPadControllerType::JoyRight) { | 341 | if (controller_type == Core::HID::NpadType::JoyconRight) { |
| 430 | pad_state.right_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus()); | 342 | pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl); |
| 431 | pad_state.right_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus()); | 343 | pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr); |
| 432 | } | 344 | } |
| 433 | 345 | ||
| 434 | if (controller_type == NPadControllerType::GameCube) { | 346 | if (controller_type == Core::HID::NpadType::GameCube) { |
| 435 | trigger_entry.l_analog = static_cast<s32>( | 347 | const auto& trigger_state = controller.device->GetTriggers(); |
| 436 | button_state[ZL - BUTTON_HID_BEGIN]->GetStatus() ? HID_TRIGGER_MAX : 0); | 348 | trigger_entry.l_analog = trigger_state.left; |
| 437 | trigger_entry.r_analog = static_cast<s32>( | 349 | trigger_entry.r_analog = trigger_state.right; |
| 438 | button_state[ZR - BUTTON_HID_BEGIN]->GetStatus() ? HID_TRIGGER_MAX : 0); | 350 | pad_entry.npad_buttons.zl.Assign(false); |
| 439 | pad_state.zl.Assign(false); | 351 | pad_entry.npad_buttons.zr.Assign(button_state.r); |
| 440 | pad_state.zr.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus()); | 352 | pad_entry.npad_buttons.l.Assign(button_state.zl); |
| 441 | pad_state.l.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus()); | 353 | pad_entry.npad_buttons.r.Assign(button_state.zr); |
| 442 | pad_state.r.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 443 | } | 354 | } |
| 444 | } | 355 | } |
| 445 | 356 | ||
| @@ -448,173 +359,124 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* | |||
| 448 | if (!IsControllerActivated()) { | 359 | if (!IsControllerActivated()) { |
| 449 | return; | 360 | return; |
| 450 | } | 361 | } |
| 451 | for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) { | 362 | for (std::size_t i = 0; i < controller_data.size(); ++i) { |
| 452 | auto& npad = shared_memory_entries[i]; | 363 | auto& controller = controller_data[i]; |
| 453 | const std::array<NPadGeneric*, 7> controller_npads{ | 364 | auto& npad = controller.shared_memory_entry; |
| 454 | &npad.fullkey_states, &npad.handheld_states, &npad.joy_dual_states, | ||
| 455 | &npad.joy_left_states, &npad.joy_right_states, &npad.palma_states, | ||
| 456 | &npad.system_ext_states}; | ||
| 457 | |||
| 458 | // There is the posibility to have more controllers with analog triggers | ||
| 459 | const std::array<TriggerGeneric*, 1> controller_triggers{ | ||
| 460 | &npad.gc_trigger_states, | ||
| 461 | }; | ||
| 462 | |||
| 463 | for (auto* main_controller : controller_npads) { | ||
| 464 | main_controller->common.entry_count = 16; | ||
| 465 | main_controller->common.total_entry_count = 17; | ||
| 466 | |||
| 467 | const auto& last_entry = | ||
| 468 | main_controller->npad[main_controller->common.last_entry_index]; | ||
| 469 | |||
| 470 | main_controller->common.timestamp = core_timing.GetCPUTicks(); | ||
| 471 | main_controller->common.last_entry_index = | ||
| 472 | (main_controller->common.last_entry_index + 1) % 17; | ||
| 473 | |||
| 474 | auto& cur_entry = main_controller->npad[main_controller->common.last_entry_index]; | ||
| 475 | |||
| 476 | cur_entry.timestamp = last_entry.timestamp + 1; | ||
| 477 | cur_entry.timestamp2 = cur_entry.timestamp; | ||
| 478 | } | ||
| 479 | 365 | ||
| 480 | for (auto* analog_trigger : controller_triggers) { | 366 | const auto& controller_type = controller.device->GetNpadType(); |
| 481 | analog_trigger->entry_count = 16; | ||
| 482 | analog_trigger->total_entry_count = 17; | ||
| 483 | 367 | ||
| 484 | const auto& last_entry = analog_trigger->trigger[analog_trigger->last_entry_index]; | 368 | if (controller_type == Core::HID::NpadType::None || !controller.device->IsConnected()) { |
| 485 | |||
| 486 | analog_trigger->timestamp = core_timing.GetCPUTicks(); | ||
| 487 | analog_trigger->last_entry_index = (analog_trigger->last_entry_index + 1) % 17; | ||
| 488 | |||
| 489 | auto& cur_entry = analog_trigger->trigger[analog_trigger->last_entry_index]; | ||
| 490 | |||
| 491 | cur_entry.timestamp = last_entry.timestamp + 1; | ||
| 492 | cur_entry.timestamp2 = cur_entry.timestamp; | ||
| 493 | } | ||
| 494 | |||
| 495 | const auto& controller_type = connected_controllers[i].type; | ||
| 496 | |||
| 497 | if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) { | ||
| 498 | continue; | 369 | continue; |
| 499 | } | 370 | } |
| 500 | const u32 npad_index = static_cast<u32>(i); | 371 | const u32 npad_index = static_cast<u32>(i); |
| 501 | 372 | ||
| 502 | RequestPadStateUpdate(npad_index); | 373 | RequestPadStateUpdate(npad_index); |
| 503 | auto& pad_state = npad_pad_states[npad_index]; | 374 | auto& pad_state = controller.npad_pad_state; |
| 504 | auto& trigger_state = npad_trigger_states[npad_index]; | 375 | auto& libnx_state = controller.npad_libnx_state; |
| 505 | 376 | auto& trigger_state = controller.npad_trigger_state; | |
| 506 | auto& main_controller = | ||
| 507 | npad.fullkey_states.npad[npad.fullkey_states.common.last_entry_index]; | ||
| 508 | auto& handheld_entry = | ||
| 509 | npad.handheld_states.npad[npad.handheld_states.common.last_entry_index]; | ||
| 510 | auto& dual_entry = npad.joy_dual_states.npad[npad.joy_dual_states.common.last_entry_index]; | ||
| 511 | auto& left_entry = npad.joy_left_states.npad[npad.joy_left_states.common.last_entry_index]; | ||
| 512 | auto& right_entry = | ||
| 513 | npad.joy_right_states.npad[npad.joy_right_states.common.last_entry_index]; | ||
| 514 | auto& pokeball_entry = npad.palma_states.npad[npad.palma_states.common.last_entry_index]; | ||
| 515 | auto& libnx_entry = | ||
| 516 | npad.system_ext_states.npad[npad.system_ext_states.common.last_entry_index]; | ||
| 517 | auto& trigger_entry = | ||
| 518 | npad.gc_trigger_states.trigger[npad.gc_trigger_states.last_entry_index]; | ||
| 519 | |||
| 520 | libnx_entry.connection_status.raw = 0; | ||
| 521 | libnx_entry.connection_status.is_connected.Assign(1); | ||
| 522 | 377 | ||
| 378 | // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate | ||
| 379 | // any controllers. | ||
| 380 | libnx_state.connection_status.raw = 0; | ||
| 381 | libnx_state.connection_status.is_connected.Assign(1); | ||
| 523 | switch (controller_type) { | 382 | switch (controller_type) { |
| 524 | case NPadControllerType::None: | 383 | case Core::HID::NpadType::None: |
| 525 | UNREACHABLE(); | 384 | UNREACHABLE(); |
| 526 | break; | 385 | break; |
| 527 | case NPadControllerType::ProController: | 386 | case Core::HID::NpadType::ProController: |
| 528 | main_controller.connection_status.raw = 0; | 387 | pad_state.connection_status.raw = 0; |
| 529 | main_controller.connection_status.is_connected.Assign(1); | 388 | pad_state.connection_status.is_connected.Assign(1); |
| 530 | main_controller.connection_status.is_wired.Assign(1); | 389 | pad_state.connection_status.is_wired.Assign(1); |
| 531 | main_controller.pad.pad_states.raw = pad_state.pad_states.raw; | 390 | |
| 532 | main_controller.pad.l_stick = pad_state.l_stick; | 391 | libnx_state.connection_status.is_wired.Assign(1); |
| 533 | main_controller.pad.r_stick = pad_state.r_stick; | 392 | pad_state.sampling_number = |
| 534 | 393 | npad.fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; | |
| 535 | libnx_entry.connection_status.is_wired.Assign(1); | 394 | npad.fullkey_lifo.WriteNextEntry(pad_state); |
| 536 | break; | 395 | break; |
| 537 | case NPadControllerType::Handheld: | 396 | case Core::HID::NpadType::Handheld: |
| 538 | handheld_entry.connection_status.raw = 0; | 397 | pad_state.connection_status.raw = 0; |
| 539 | handheld_entry.connection_status.is_connected.Assign(1); | 398 | pad_state.connection_status.is_connected.Assign(1); |
| 540 | handheld_entry.connection_status.is_wired.Assign(1); | 399 | pad_state.connection_status.is_wired.Assign(1); |
| 541 | handheld_entry.connection_status.is_left_connected.Assign(1); | 400 | pad_state.connection_status.is_left_connected.Assign(1); |
| 542 | handheld_entry.connection_status.is_right_connected.Assign(1); | 401 | pad_state.connection_status.is_right_connected.Assign(1); |
| 543 | handheld_entry.connection_status.is_left_wired.Assign(1); | 402 | pad_state.connection_status.is_left_wired.Assign(1); |
| 544 | handheld_entry.connection_status.is_right_wired.Assign(1); | 403 | pad_state.connection_status.is_right_wired.Assign(1); |
| 545 | handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw; | 404 | |
| 546 | handheld_entry.pad.l_stick = pad_state.l_stick; | 405 | libnx_state.connection_status.is_wired.Assign(1); |
| 547 | handheld_entry.pad.r_stick = pad_state.r_stick; | 406 | libnx_state.connection_status.is_left_connected.Assign(1); |
| 548 | 407 | libnx_state.connection_status.is_right_connected.Assign(1); | |
| 549 | libnx_entry.connection_status.is_wired.Assign(1); | 408 | libnx_state.connection_status.is_left_wired.Assign(1); |
| 550 | libnx_entry.connection_status.is_left_connected.Assign(1); | 409 | libnx_state.connection_status.is_right_wired.Assign(1); |
| 551 | libnx_entry.connection_status.is_right_connected.Assign(1); | 410 | pad_state.sampling_number = |
| 552 | libnx_entry.connection_status.is_left_wired.Assign(1); | 411 | npad.handheld_lifo.ReadCurrentEntry().state.sampling_number + 1; |
| 553 | libnx_entry.connection_status.is_right_wired.Assign(1); | 412 | npad.handheld_lifo.WriteNextEntry(pad_state); |
| 554 | break; | 413 | break; |
| 555 | case NPadControllerType::JoyDual: | 414 | case Core::HID::NpadType::JoyconDual: |
| 556 | dual_entry.connection_status.raw = 0; | 415 | pad_state.connection_status.raw = 0; |
| 557 | dual_entry.connection_status.is_connected.Assign(1); | 416 | pad_state.connection_status.is_connected.Assign(1); |
| 558 | dual_entry.connection_status.is_left_connected.Assign(1); | 417 | pad_state.connection_status.is_left_connected.Assign(1); |
| 559 | dual_entry.connection_status.is_right_connected.Assign(1); | 418 | pad_state.connection_status.is_right_connected.Assign(1); |
| 560 | dual_entry.pad.pad_states.raw = pad_state.pad_states.raw; | 419 | |
| 561 | dual_entry.pad.l_stick = pad_state.l_stick; | 420 | libnx_state.connection_status.is_left_connected.Assign(1); |
| 562 | dual_entry.pad.r_stick = pad_state.r_stick; | 421 | libnx_state.connection_status.is_right_connected.Assign(1); |
| 563 | 422 | pad_state.sampling_number = | |
| 564 | libnx_entry.connection_status.is_left_connected.Assign(1); | 423 | npad.joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1; |
| 565 | libnx_entry.connection_status.is_right_connected.Assign(1); | 424 | npad.joy_dual_lifo.WriteNextEntry(pad_state); |
| 566 | break; | 425 | break; |
| 567 | case NPadControllerType::JoyLeft: | 426 | case Core::HID::NpadType::JoyconLeft: |
| 568 | left_entry.connection_status.raw = 0; | 427 | pad_state.connection_status.raw = 0; |
| 569 | left_entry.connection_status.is_connected.Assign(1); | 428 | pad_state.connection_status.is_connected.Assign(1); |
| 570 | left_entry.connection_status.is_left_connected.Assign(1); | 429 | pad_state.connection_status.is_left_connected.Assign(1); |
| 571 | left_entry.pad.pad_states.raw = pad_state.pad_states.raw; | 430 | |
| 572 | left_entry.pad.l_stick = pad_state.l_stick; | 431 | libnx_state.connection_status.is_left_connected.Assign(1); |
| 573 | left_entry.pad.r_stick = pad_state.r_stick; | 432 | pad_state.sampling_number = |
| 574 | 433 | npad.joy_left_lifo.ReadCurrentEntry().state.sampling_number + 1; | |
| 575 | libnx_entry.connection_status.is_left_connected.Assign(1); | 434 | npad.joy_left_lifo.WriteNextEntry(pad_state); |
| 576 | break; | 435 | break; |
| 577 | case NPadControllerType::JoyRight: | 436 | case Core::HID::NpadType::JoyconRight: |
| 578 | right_entry.connection_status.raw = 0; | 437 | pad_state.connection_status.raw = 0; |
| 579 | right_entry.connection_status.is_connected.Assign(1); | 438 | pad_state.connection_status.is_connected.Assign(1); |
| 580 | right_entry.connection_status.is_right_connected.Assign(1); | 439 | pad_state.connection_status.is_right_connected.Assign(1); |
| 581 | right_entry.pad.pad_states.raw = pad_state.pad_states.raw; | 440 | |
| 582 | right_entry.pad.l_stick = pad_state.l_stick; | 441 | libnx_state.connection_status.is_right_connected.Assign(1); |
| 583 | right_entry.pad.r_stick = pad_state.r_stick; | 442 | pad_state.sampling_number = |
| 584 | 443 | npad.joy_right_lifo.ReadCurrentEntry().state.sampling_number + 1; | |
| 585 | libnx_entry.connection_status.is_right_connected.Assign(1); | 444 | npad.joy_right_lifo.WriteNextEntry(pad_state); |
| 586 | break; | 445 | break; |
| 587 | case NPadControllerType::GameCube: | 446 | case Core::HID::NpadType::GameCube: |
| 588 | main_controller.connection_status.raw = 0; | 447 | pad_state.connection_status.raw = 0; |
| 589 | main_controller.connection_status.is_connected.Assign(1); | 448 | pad_state.connection_status.is_connected.Assign(1); |
| 590 | main_controller.connection_status.is_wired.Assign(1); | 449 | pad_state.connection_status.is_wired.Assign(1); |
| 591 | main_controller.pad.pad_states.raw = pad_state.pad_states.raw; | 450 | |
| 592 | main_controller.pad.l_stick = pad_state.l_stick; | 451 | libnx_state.connection_status.is_wired.Assign(1); |
| 593 | main_controller.pad.r_stick = pad_state.r_stick; | 452 | pad_state.sampling_number = |
| 594 | trigger_entry.l_analog = trigger_state.l_analog; | 453 | npad.fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; |
| 595 | trigger_entry.r_analog = trigger_state.r_analog; | 454 | trigger_state.sampling_number = |
| 596 | 455 | npad.gc_trigger_lifo.ReadCurrentEntry().state.sampling_number + 1; | |
| 597 | libnx_entry.connection_status.is_wired.Assign(1); | 456 | npad.fullkey_lifo.WriteNextEntry(pad_state); |
| 457 | npad.gc_trigger_lifo.WriteNextEntry(trigger_state); | ||
| 598 | break; | 458 | break; |
| 599 | case NPadControllerType::Pokeball: | 459 | case Core::HID::NpadType::Pokeball: |
| 600 | pokeball_entry.connection_status.raw = 0; | 460 | pad_state.connection_status.raw = 0; |
| 601 | pokeball_entry.connection_status.is_connected.Assign(1); | 461 | pad_state.connection_status.is_connected.Assign(1); |
| 602 | pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw; | 462 | pad_state.sampling_number = |
| 603 | pokeball_entry.pad.l_stick = pad_state.l_stick; | 463 | npad.palma_lifo.ReadCurrentEntry().state.sampling_number + 1; |
| 604 | pokeball_entry.pad.r_stick = pad_state.r_stick; | 464 | npad.palma_lifo.WriteNextEntry(pad_state); |
| 465 | break; | ||
| 466 | default: | ||
| 605 | break; | 467 | break; |
| 606 | } | 468 | } |
| 607 | 469 | ||
| 608 | // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate | 470 | libnx_state.npad_buttons.raw = pad_state.npad_buttons.raw; |
| 609 | // any controllers. | 471 | libnx_state.l_stick = pad_state.l_stick; |
| 610 | libnx_entry.pad.pad_states.raw = pad_state.pad_states.raw; | 472 | libnx_state.r_stick = pad_state.r_stick; |
| 611 | libnx_entry.pad.l_stick = pad_state.l_stick; | 473 | npad.system_ext_lifo.WriteNextEntry(pad_state); |
| 612 | libnx_entry.pad.r_stick = pad_state.r_stick; | 474 | |
| 475 | press_state |= static_cast<u32>(pad_state.npad_buttons.raw); | ||
| 613 | 476 | ||
| 614 | press_state |= static_cast<u32>(pad_state.pad_states.raw); | 477 | std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)), |
| 478 | &controller.shared_memory_entry, sizeof(NpadInternalState)); | ||
| 615 | } | 479 | } |
| 616 | std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(), | ||
| 617 | shared_memory_entries.size() * sizeof(NPadEntry)); | ||
| 618 | } | 480 | } |
| 619 | 481 | ||
| 620 | void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, | 482 | void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, |
| @@ -622,145 +484,130 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing | |||
| 622 | if (!IsControllerActivated()) { | 484 | if (!IsControllerActivated()) { |
| 623 | return; | 485 | return; |
| 624 | } | 486 | } |
| 625 | for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) { | ||
| 626 | auto& npad = shared_memory_entries[i]; | ||
| 627 | 487 | ||
| 628 | const auto& controller_type = connected_controllers[i].type; | 488 | for (std::size_t i = 0; i < controller_data.size(); ++i) { |
| 629 | 489 | auto& controller = controller_data[i]; | |
| 630 | if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) { | ||
| 631 | continue; | ||
| 632 | } | ||
| 633 | 490 | ||
| 634 | const std::array<SixAxisGeneric*, 6> controller_sixaxes{ | 491 | const auto& controller_type = controller.device->GetNpadType(); |
| 635 | &npad.sixaxis_fullkey, &npad.sixaxis_handheld, &npad.sixaxis_dual_left, | ||
| 636 | &npad.sixaxis_dual_right, &npad.sixaxis_left, &npad.sixaxis_right, | ||
| 637 | }; | ||
| 638 | 492 | ||
| 639 | for (auto* sixaxis_sensor : controller_sixaxes) { | 493 | if (controller_type == Core::HID::NpadType::None || !controller.device->IsConnected()) { |
| 640 | sixaxis_sensor->common.entry_count = 16; | 494 | continue; |
| 641 | sixaxis_sensor->common.total_entry_count = 17; | ||
| 642 | |||
| 643 | const auto& last_entry = | ||
| 644 | sixaxis_sensor->sixaxis[sixaxis_sensor->common.last_entry_index]; | ||
| 645 | |||
| 646 | sixaxis_sensor->common.timestamp = core_timing.GetCPUTicks(); | ||
| 647 | sixaxis_sensor->common.last_entry_index = | ||
| 648 | (sixaxis_sensor->common.last_entry_index + 1) % 17; | ||
| 649 | |||
| 650 | auto& cur_entry = sixaxis_sensor->sixaxis[sixaxis_sensor->common.last_entry_index]; | ||
| 651 | |||
| 652 | cur_entry.timestamp = last_entry.timestamp + 1; | ||
| 653 | cur_entry.timestamp2 = cur_entry.timestamp; | ||
| 654 | } | 495 | } |
| 655 | 496 | ||
| 656 | // Try to read sixaxis sensor states | 497 | auto& npad = controller.shared_memory_entry; |
| 657 | std::array<MotionDevice, 2> motion_devices; | 498 | const auto& motion_state = controller.device->GetMotions(); |
| 499 | auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state; | ||
| 500 | auto& sixaxis_handheld_state = controller.sixaxis_handheld_state; | ||
| 501 | auto& sixaxis_dual_left_state = controller.sixaxis_dual_left_state; | ||
| 502 | auto& sixaxis_dual_right_state = controller.sixaxis_dual_right_state; | ||
| 503 | auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state; | ||
| 504 | auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state; | ||
| 658 | 505 | ||
| 659 | if (sixaxis_sensors_enabled && Settings::values.motion_enabled.GetValue()) { | 506 | if (sixaxis_sensors_enabled && Settings::values.motion_enabled.GetValue()) { |
| 660 | sixaxis_at_rest = true; | 507 | sixaxis_at_rest = true; |
| 661 | for (std::size_t e = 0; e < motion_devices.size(); ++e) { | 508 | for (std::size_t e = 0; e < motion_state.size(); ++e) { |
| 662 | const auto& device = motions[i][e]; | 509 | sixaxis_at_rest = sixaxis_at_rest && motion_state[e].is_at_rest; |
| 663 | if (device) { | ||
| 664 | std::tie(motion_devices[e].accel, motion_devices[e].gyro, | ||
| 665 | motion_devices[e].rotation, motion_devices[e].orientation, | ||
| 666 | motion_devices[e].quaternion) = device->GetStatus(); | ||
| 667 | sixaxis_at_rest = sixaxis_at_rest && motion_devices[e].gyro.Length2() < 0.0001f; | ||
| 668 | } | ||
| 669 | } | 510 | } |
| 670 | } | 511 | } |
| 671 | 512 | ||
| 672 | auto& full_sixaxis_entry = | ||
| 673 | npad.sixaxis_fullkey.sixaxis[npad.sixaxis_fullkey.common.last_entry_index]; | ||
| 674 | auto& handheld_sixaxis_entry = | ||
| 675 | npad.sixaxis_handheld.sixaxis[npad.sixaxis_handheld.common.last_entry_index]; | ||
| 676 | auto& dual_left_sixaxis_entry = | ||
| 677 | npad.sixaxis_dual_left.sixaxis[npad.sixaxis_dual_left.common.last_entry_index]; | ||
| 678 | auto& dual_right_sixaxis_entry = | ||
| 679 | npad.sixaxis_dual_right.sixaxis[npad.sixaxis_dual_right.common.last_entry_index]; | ||
| 680 | auto& left_sixaxis_entry = | ||
| 681 | npad.sixaxis_left.sixaxis[npad.sixaxis_left.common.last_entry_index]; | ||
| 682 | auto& right_sixaxis_entry = | ||
| 683 | npad.sixaxis_right.sixaxis[npad.sixaxis_right.common.last_entry_index]; | ||
| 684 | |||
| 685 | switch (controller_type) { | 513 | switch (controller_type) { |
| 686 | case NPadControllerType::None: | 514 | case Core::HID::NpadType::None: |
| 687 | UNREACHABLE(); | 515 | UNREACHABLE(); |
| 688 | break; | 516 | break; |
| 689 | case NPadControllerType::ProController: | 517 | case Core::HID::NpadType::ProController: |
| 690 | full_sixaxis_entry.attribute.raw = 0; | 518 | sixaxis_fullkey_state.attribute.raw = 0; |
| 691 | if (sixaxis_sensors_enabled && motions[i][0]) { | 519 | if (sixaxis_sensors_enabled) { |
| 692 | full_sixaxis_entry.attribute.is_connected.Assign(1); | 520 | sixaxis_fullkey_state.attribute.is_connected.Assign(1); |
| 693 | full_sixaxis_entry.accel = motion_devices[0].accel; | 521 | sixaxis_fullkey_state.accel = motion_state[0].accel; |
| 694 | full_sixaxis_entry.gyro = motion_devices[0].gyro; | 522 | sixaxis_fullkey_state.gyro = motion_state[0].gyro; |
| 695 | full_sixaxis_entry.rotation = motion_devices[0].rotation; | 523 | sixaxis_fullkey_state.rotation = motion_state[0].rotation; |
| 696 | full_sixaxis_entry.orientation = motion_devices[0].orientation; | 524 | sixaxis_fullkey_state.orientation = motion_state[0].orientation; |
| 697 | } | 525 | } |
| 698 | break; | 526 | break; |
| 699 | case NPadControllerType::Handheld: | 527 | case Core::HID::NpadType::Handheld: |
| 700 | handheld_sixaxis_entry.attribute.raw = 0; | 528 | sixaxis_handheld_state.attribute.raw = 0; |
| 701 | if (sixaxis_sensors_enabled && motions[i][0]) { | 529 | if (sixaxis_sensors_enabled) { |
| 702 | handheld_sixaxis_entry.attribute.is_connected.Assign(1); | 530 | sixaxis_handheld_state.attribute.is_connected.Assign(1); |
| 703 | handheld_sixaxis_entry.accel = motion_devices[0].accel; | 531 | sixaxis_handheld_state.accel = motion_state[0].accel; |
| 704 | handheld_sixaxis_entry.gyro = motion_devices[0].gyro; | 532 | sixaxis_handheld_state.gyro = motion_state[0].gyro; |
| 705 | handheld_sixaxis_entry.rotation = motion_devices[0].rotation; | 533 | sixaxis_handheld_state.rotation = motion_state[0].rotation; |
| 706 | handheld_sixaxis_entry.orientation = motion_devices[0].orientation; | 534 | sixaxis_handheld_state.orientation = motion_state[0].orientation; |
| 707 | } | 535 | } |
| 708 | break; | 536 | break; |
| 709 | case NPadControllerType::JoyDual: | 537 | case Core::HID::NpadType::JoyconDual: |
| 710 | dual_left_sixaxis_entry.attribute.raw = 0; | 538 | sixaxis_dual_left_state.attribute.raw = 0; |
| 711 | dual_right_sixaxis_entry.attribute.raw = 0; | 539 | sixaxis_dual_right_state.attribute.raw = 0; |
| 712 | if (sixaxis_sensors_enabled && motions[i][0]) { | 540 | if (sixaxis_sensors_enabled) { |
| 713 | // Set motion for the left joycon | 541 | // Set motion for the left joycon |
| 714 | dual_left_sixaxis_entry.attribute.is_connected.Assign(1); | 542 | sixaxis_dual_left_state.attribute.is_connected.Assign(1); |
| 715 | dual_left_sixaxis_entry.accel = motion_devices[0].accel; | 543 | sixaxis_dual_left_state.accel = motion_state[0].accel; |
| 716 | dual_left_sixaxis_entry.gyro = motion_devices[0].gyro; | 544 | sixaxis_dual_left_state.gyro = motion_state[0].gyro; |
| 717 | dual_left_sixaxis_entry.rotation = motion_devices[0].rotation; | 545 | sixaxis_dual_left_state.rotation = motion_state[0].rotation; |
| 718 | dual_left_sixaxis_entry.orientation = motion_devices[0].orientation; | 546 | sixaxis_dual_left_state.orientation = motion_state[0].orientation; |
| 719 | } | 547 | } |
| 720 | if (sixaxis_sensors_enabled && motions[i][1]) { | 548 | if (sixaxis_sensors_enabled) { |
| 721 | // Set motion for the right joycon | 549 | // Set motion for the right joycon |
| 722 | dual_right_sixaxis_entry.attribute.is_connected.Assign(1); | 550 | sixaxis_dual_right_state.attribute.is_connected.Assign(1); |
| 723 | dual_right_sixaxis_entry.accel = motion_devices[1].accel; | 551 | sixaxis_dual_right_state.accel = motion_state[1].accel; |
| 724 | dual_right_sixaxis_entry.gyro = motion_devices[1].gyro; | 552 | sixaxis_dual_right_state.gyro = motion_state[1].gyro; |
| 725 | dual_right_sixaxis_entry.rotation = motion_devices[1].rotation; | 553 | sixaxis_dual_right_state.rotation = motion_state[1].rotation; |
| 726 | dual_right_sixaxis_entry.orientation = motion_devices[1].orientation; | 554 | sixaxis_dual_right_state.orientation = motion_state[1].orientation; |
| 727 | } | 555 | } |
| 728 | break; | 556 | break; |
| 729 | case NPadControllerType::JoyLeft: | 557 | case Core::HID::NpadType::JoyconLeft: |
| 730 | left_sixaxis_entry.attribute.raw = 0; | 558 | sixaxis_left_lifo_state.attribute.raw = 0; |
| 731 | if (sixaxis_sensors_enabled && motions[i][0]) { | 559 | if (sixaxis_sensors_enabled) { |
| 732 | left_sixaxis_entry.attribute.is_connected.Assign(1); | 560 | sixaxis_left_lifo_state.attribute.is_connected.Assign(1); |
| 733 | left_sixaxis_entry.accel = motion_devices[0].accel; | 561 | sixaxis_left_lifo_state.accel = motion_state[0].accel; |
| 734 | left_sixaxis_entry.gyro = motion_devices[0].gyro; | 562 | sixaxis_left_lifo_state.gyro = motion_state[0].gyro; |
| 735 | left_sixaxis_entry.rotation = motion_devices[0].rotation; | 563 | sixaxis_left_lifo_state.rotation = motion_state[0].rotation; |
| 736 | left_sixaxis_entry.orientation = motion_devices[0].orientation; | 564 | sixaxis_left_lifo_state.orientation = motion_state[0].orientation; |
| 737 | } | 565 | } |
| 738 | break; | 566 | break; |
| 739 | case NPadControllerType::JoyRight: | 567 | case Core::HID::NpadType::JoyconRight: |
| 740 | right_sixaxis_entry.attribute.raw = 0; | 568 | sixaxis_right_lifo_state.attribute.raw = 0; |
| 741 | if (sixaxis_sensors_enabled && motions[i][1]) { | 569 | if (sixaxis_sensors_enabled) { |
| 742 | right_sixaxis_entry.attribute.is_connected.Assign(1); | 570 | sixaxis_right_lifo_state.attribute.is_connected.Assign(1); |
| 743 | right_sixaxis_entry.accel = motion_devices[1].accel; | 571 | sixaxis_right_lifo_state.accel = motion_state[1].accel; |
| 744 | right_sixaxis_entry.gyro = motion_devices[1].gyro; | 572 | sixaxis_right_lifo_state.gyro = motion_state[1].gyro; |
| 745 | right_sixaxis_entry.rotation = motion_devices[1].rotation; | 573 | sixaxis_right_lifo_state.rotation = motion_state[1].rotation; |
| 746 | right_sixaxis_entry.orientation = motion_devices[1].orientation; | 574 | sixaxis_right_lifo_state.orientation = motion_state[1].orientation; |
| 747 | } | 575 | } |
| 748 | break; | 576 | break; |
| 749 | case NPadControllerType::GameCube: | 577 | default: |
| 750 | case NPadControllerType::Pokeball: | ||
| 751 | break; | 578 | break; |
| 752 | } | 579 | } |
| 580 | |||
| 581 | sixaxis_fullkey_state.sampling_number = | ||
| 582 | npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 583 | sixaxis_handheld_state.sampling_number = | ||
| 584 | npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 585 | sixaxis_dual_left_state.sampling_number = | ||
| 586 | npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 587 | sixaxis_dual_right_state.sampling_number = | ||
| 588 | npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 589 | sixaxis_left_lifo_state.sampling_number = | ||
| 590 | npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 591 | sixaxis_right_lifo_state.sampling_number = | ||
| 592 | npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 593 | |||
| 594 | npad.sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state); | ||
| 595 | npad.sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state); | ||
| 596 | npad.sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state); | ||
| 597 | npad.sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state); | ||
| 598 | npad.sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state); | ||
| 599 | npad.sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state); | ||
| 600 | std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)), | ||
| 601 | &controller.shared_memory_entry, sizeof(NpadInternalState)); | ||
| 753 | } | 602 | } |
| 754 | std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(), | ||
| 755 | shared_memory_entries.size() * sizeof(NPadEntry)); | ||
| 756 | } | 603 | } |
| 757 | 604 | ||
| 758 | void Controller_NPad::SetSupportedStyleSet(NpadStyleSet style_set) { | 605 | void Controller_NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) { |
| 759 | style.raw = style_set.raw; | 606 | system.HIDCore().SetSupportedStyleTag(style_set); |
| 760 | } | 607 | } |
| 761 | 608 | ||
| 762 | Controller_NPad::NpadStyleSet Controller_NPad::GetSupportedStyleSet() const { | 609 | Core::HID::NpadStyleTag Controller_NPad::GetSupportedStyleSet() const { |
| 763 | return style; | 610 | return system.HIDCore().GetSupportedStyleTag(); |
| 764 | } | 611 | } |
| 765 | 612 | ||
| 766 | void Controller_NPad::SetSupportedNpadIdTypes(u8* data, std::size_t length) { | 613 | void Controller_NPad::SetSupportedNpadIdTypes(u8* data, std::size_t length) { |
| @@ -779,11 +626,11 @@ std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const { | |||
| 779 | return supported_npad_id_types.size(); | 626 | return supported_npad_id_types.size(); |
| 780 | } | 627 | } |
| 781 | 628 | ||
| 782 | void Controller_NPad::SetHoldType(NpadHoldType joy_hold_type) { | 629 | void Controller_NPad::SetHoldType(NpadJoyHoldType joy_hold_type) { |
| 783 | hold_type = joy_hold_type; | 630 | hold_type = joy_hold_type; |
| 784 | } | 631 | } |
| 785 | 632 | ||
| 786 | Controller_NPad::NpadHoldType Controller_NPad::GetHoldType() const { | 633 | Controller_NPad::NpadJoyHoldType Controller_NPad::GetHoldType() const { |
| 787 | return hold_type; | 634 | return hold_type; |
| 788 | } | 635 | } |
| 789 | 636 | ||
| @@ -803,29 +650,31 @@ Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode | |||
| 803 | return communication_mode; | 650 | return communication_mode; |
| 804 | } | 651 | } |
| 805 | 652 | ||
| 806 | void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) { | 653 | void Controller_NPad::SetNpadMode(u32 npad_id, NpadJoyAssignmentMode assignment_mode) { |
| 807 | const std::size_t npad_index = NPadIdToIndex(npad_id); | 654 | const std::size_t npad_index = NPadIdToIndex(npad_id); |
| 808 | ASSERT(npad_index < shared_memory_entries.size()); | 655 | ASSERT(npad_index < controller_data.size()); |
| 809 | if (shared_memory_entries[npad_index].assignment_mode != assignment_mode) { | 656 | auto& controller = controller_data[npad_index]; |
| 810 | shared_memory_entries[npad_index].assignment_mode = assignment_mode; | 657 | if (controller.shared_memory_entry.assignment_mode != assignment_mode) { |
| 658 | controller.shared_memory_entry.assignment_mode = assignment_mode; | ||
| 811 | } | 659 | } |
| 812 | } | 660 | } |
| 813 | 661 | ||
| 814 | bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, | 662 | bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, |
| 815 | const VibrationValue& vibration_value) { | 663 | const VibrationValue& vibration_value) { |
| 816 | if (!connected_controllers[npad_index].is_connected || !vibrations[npad_index][device_index]) { | 664 | auto& controller = controller_data[npad_index]; |
| 665 | |||
| 666 | if (!controller.device->IsConnected()) { | ||
| 817 | return false; | 667 | return false; |
| 818 | } | 668 | } |
| 819 | 669 | ||
| 820 | const auto& player = Settings::values.players.GetValue()[npad_index]; | 670 | if (!controller.device->IsVibrationEnabled()) { |
| 821 | 671 | if (controller.vibration[device_index].latest_vibration_value.amp_low != 0.0f || | |
| 822 | if (!player.vibration_enabled) { | 672 | controller.vibration[device_index].latest_vibration_value.amp_high != 0.0f) { |
| 823 | if (latest_vibration_values[npad_index][device_index].amp_low != 0.0f || | ||
| 824 | latest_vibration_values[npad_index][device_index].amp_high != 0.0f) { | ||
| 825 | // Send an empty vibration to stop any vibrations. | 673 | // Send an empty vibration to stop any vibrations. |
| 826 | vibrations[npad_index][device_index]->SetRumblePlay(0.0f, 160.0f, 0.0f, 320.0f); | 674 | Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f}; |
| 675 | controller.device->SetVibration(device_index, vibration); | ||
| 827 | // Then reset the vibration value to its default value. | 676 | // Then reset the vibration value to its default value. |
| 828 | latest_vibration_values[npad_index][device_index] = DEFAULT_VIBRATION_VALUE; | 677 | controller.vibration[device_index].latest_vibration_value = DEFAULT_VIBRATION_VALUE; |
| 829 | } | 678 | } |
| 830 | 679 | ||
| 831 | return false; | 680 | return false; |
| @@ -840,22 +689,18 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size | |||
| 840 | 689 | ||
| 841 | // Filter out non-zero vibrations that are within 10ms of each other. | 690 | // Filter out non-zero vibrations that are within 10ms of each other. |
| 842 | if ((vibration_value.amp_low != 0.0f || vibration_value.amp_high != 0.0f) && | 691 | if ((vibration_value.amp_low != 0.0f || vibration_value.amp_high != 0.0f) && |
| 843 | duration_cast<milliseconds>(now - last_vibration_timepoints[npad_index][device_index]) < | 692 | duration_cast<milliseconds>( |
| 693 | now - controller.vibration[device_index].last_vibration_timepoint) < | ||
| 844 | milliseconds(10)) { | 694 | milliseconds(10)) { |
| 845 | return false; | 695 | return false; |
| 846 | } | 696 | } |
| 847 | 697 | ||
| 848 | last_vibration_timepoints[npad_index][device_index] = now; | 698 | controller.vibration[device_index].last_vibration_timepoint = now; |
| 849 | } | 699 | } |
| 850 | 700 | ||
| 851 | auto& vibration = vibrations[npad_index][device_index]; | 701 | Core::HID::VibrationValue vibration{vibration_value.amp_low, vibration_value.freq_low, |
| 852 | const auto player_vibration_strength = static_cast<f32>(player.vibration_strength); | 702 | vibration_value.amp_high, vibration_value.freq_high}; |
| 853 | const auto amp_low = | 703 | return controller.device->SetVibration(device_index, vibration); |
| 854 | std::min(vibration_value.amp_low * player_vibration_strength / 100.0f, 1.0f); | ||
| 855 | const auto amp_high = | ||
| 856 | std::min(vibration_value.amp_high * player_vibration_strength / 100.0f, 1.0f); | ||
| 857 | return vibration->SetRumblePlay(amp_low, vibration_value.freq_low, amp_high, | ||
| 858 | vibration_value.freq_high); | ||
| 859 | } | 704 | } |
| 860 | 705 | ||
| 861 | void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle, | 706 | void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle, |
| @@ -869,10 +714,10 @@ void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_han | |||
| 869 | } | 714 | } |
| 870 | 715 | ||
| 871 | const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); | 716 | const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); |
| 717 | auto& controller = controller_data[npad_index]; | ||
| 872 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | 718 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); |
| 873 | 719 | ||
| 874 | if (!vibration_devices_mounted[npad_index][device_index] || | 720 | if (!controller.vibration[device_index].device_mounted || !controller.device->IsConnected()) { |
| 875 | !connected_controllers[npad_index].is_connected) { | ||
| 876 | return; | 721 | return; |
| 877 | } | 722 | } |
| 878 | 723 | ||
| @@ -882,23 +727,25 @@ void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_han | |||
| 882 | } | 727 | } |
| 883 | 728 | ||
| 884 | // Some games try to send mismatched parameters in the device handle, block these. | 729 | // Some games try to send mismatched parameters in the device handle, block these. |
| 885 | if ((connected_controllers[npad_index].type == NPadControllerType::JoyLeft && | 730 | if ((controller.device->GetNpadType() == Core::HID::NpadType::JoyconLeft && |
| 886 | (vibration_device_handle.npad_type == NpadType::JoyconRight || | 731 | (vibration_device_handle.npad_type == Core::HID::NpadType::JoyconRight || |
| 887 | vibration_device_handle.device_index == DeviceIndex::Right)) || | 732 | vibration_device_handle.device_index == DeviceIndex::Right)) || |
| 888 | (connected_controllers[npad_index].type == NPadControllerType::JoyRight && | 733 | (controller.device->GetNpadType() == Core::HID::NpadType::JoyconRight && |
| 889 | (vibration_device_handle.npad_type == NpadType::JoyconLeft || | 734 | (vibration_device_handle.npad_type == Core::HID::NpadType::JoyconLeft || |
| 890 | vibration_device_handle.device_index == DeviceIndex::Left))) { | 735 | vibration_device_handle.device_index == DeviceIndex::Left))) { |
| 891 | return; | 736 | return; |
| 892 | } | 737 | } |
| 893 | 738 | ||
| 894 | // Filter out vibrations with equivalent values to reduce unnecessary state changes. | 739 | // Filter out vibrations with equivalent values to reduce unnecessary state changes. |
| 895 | if (vibration_value.amp_low == latest_vibration_values[npad_index][device_index].amp_low && | 740 | if (vibration_value.amp_low == |
| 896 | vibration_value.amp_high == latest_vibration_values[npad_index][device_index].amp_high) { | 741 | controller.vibration[device_index].latest_vibration_value.amp_low && |
| 742 | vibration_value.amp_high == | ||
| 743 | controller.vibration[device_index].latest_vibration_value.amp_high) { | ||
| 897 | return; | 744 | return; |
| 898 | } | 745 | } |
| 899 | 746 | ||
| 900 | if (VibrateControllerAtIndex(npad_index, device_index, vibration_value)) { | 747 | if (VibrateControllerAtIndex(npad_index, device_index, vibration_value)) { |
| 901 | latest_vibration_values[npad_index][device_index] = vibration_value; | 748 | controller.vibration[device_index].latest_vibration_value = vibration_value; |
| 902 | } | 749 | } |
| 903 | } | 750 | } |
| 904 | 751 | ||
| @@ -925,8 +772,9 @@ Controller_NPad::VibrationValue Controller_NPad::GetLastVibration( | |||
| 925 | } | 772 | } |
| 926 | 773 | ||
| 927 | const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); | 774 | const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); |
| 775 | const auto& controller = controller_data[npad_index]; | ||
| 928 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | 776 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); |
| 929 | return latest_vibration_values[npad_index][device_index]; | 777 | return controller.vibration[device_index].latest_vibration_value; |
| 930 | } | 778 | } |
| 931 | 779 | ||
| 932 | void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_device_handle) { | 780 | void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_device_handle) { |
| @@ -941,17 +789,14 @@ void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_de | |||
| 941 | 789 | ||
| 942 | void Controller_NPad::InitializeVibrationDeviceAtIndex(std::size_t npad_index, | 790 | void Controller_NPad::InitializeVibrationDeviceAtIndex(std::size_t npad_index, |
| 943 | std::size_t device_index) { | 791 | std::size_t device_index) { |
| 792 | auto& controller = controller_data[npad_index]; | ||
| 944 | if (!Settings::values.vibration_enabled.GetValue()) { | 793 | if (!Settings::values.vibration_enabled.GetValue()) { |
| 945 | vibration_devices_mounted[npad_index][device_index] = false; | 794 | controller.vibration[device_index].device_mounted = false; |
| 946 | return; | 795 | return; |
| 947 | } | 796 | } |
| 948 | 797 | ||
| 949 | if (vibrations[npad_index][device_index]) { | 798 | controller.vibration[device_index].device_mounted = |
| 950 | vibration_devices_mounted[npad_index][device_index] = | 799 | controller.device->TestVibration(device_index) == 1; |
| 951 | vibrations[npad_index][device_index]->GetStatus() == 1; | ||
| 952 | } else { | ||
| 953 | vibration_devices_mounted[npad_index][device_index] = false; | ||
| 954 | } | ||
| 955 | } | 800 | } |
| 956 | 801 | ||
| 957 | void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) { | 802 | void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) { |
| @@ -964,42 +809,35 @@ bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_dev | |||
| 964 | } | 809 | } |
| 965 | 810 | ||
| 966 | const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); | 811 | const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); |
| 812 | const auto& controller = controller_data[npad_index]; | ||
| 967 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | 813 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); |
| 968 | return vibration_devices_mounted[npad_index][device_index]; | 814 | return controller.vibration[device_index].device_mounted; |
| 969 | } | 815 | } |
| 970 | 816 | ||
| 971 | Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) { | 817 | Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) { |
| 972 | return styleset_changed_events[NPadIdToIndex(npad_id)]->GetReadableEvent(); | 818 | const auto& controller = controller_data[NPadIdToIndex(npad_id)]; |
| 819 | return controller.styleset_changed_event->GetReadableEvent(); | ||
| 973 | } | 820 | } |
| 974 | 821 | ||
| 975 | void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const { | 822 | void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const { |
| 976 | styleset_changed_events[NPadIdToIndex(npad_id)]->GetWritableEvent().Signal(); | 823 | const auto& controller = controller_data[NPadIdToIndex(npad_id)]; |
| 824 | controller.styleset_changed_event->GetWritableEvent().Signal(); | ||
| 977 | } | 825 | } |
| 978 | 826 | ||
| 979 | void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) { | 827 | void Controller_NPad::AddNewControllerAt(Core::HID::NpadType controller, std::size_t npad_index) { |
| 980 | UpdateControllerAt(controller, npad_index, true); | 828 | UpdateControllerAt(controller, npad_index, true); |
| 981 | } | 829 | } |
| 982 | 830 | ||
| 983 | void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, | 831 | void Controller_NPad::UpdateControllerAt(Core::HID::NpadType type, std::size_t npad_index, |
| 984 | bool connected) { | 832 | bool connected) { |
| 833 | auto& controller = controller_data[npad_index].device; | ||
| 985 | if (!connected) { | 834 | if (!connected) { |
| 986 | DisconnectNpadAtIndex(npad_index); | 835 | DisconnectNpadAtIndex(npad_index); |
| 987 | return; | 836 | return; |
| 988 | } | 837 | } |
| 989 | 838 | ||
| 990 | if (controller == NPadControllerType::Handheld && npad_index == HANDHELD_INDEX) { | 839 | controller->SetNpadType(type); |
| 991 | Settings::values.players.GetValue()[HANDHELD_INDEX].controller_type = | 840 | controller->Connect(); |
| 992 | MapNPadToSettingsType(controller); | ||
| 993 | Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true; | ||
| 994 | connected_controllers[HANDHELD_INDEX] = {controller, true}; | ||
| 995 | InitNewlyAddedController(HANDHELD_INDEX); | ||
| 996 | return; | ||
| 997 | } | ||
| 998 | |||
| 999 | Settings::values.players.GetValue()[npad_index].controller_type = | ||
| 1000 | MapNPadToSettingsType(controller); | ||
| 1001 | Settings::values.players.GetValue()[npad_index].connected = true; | ||
| 1002 | connected_controllers[npad_index] = {controller, true}; | ||
| 1003 | InitNewlyAddedController(npad_index); | 841 | InitNewlyAddedController(npad_index); |
| 1004 | } | 842 | } |
| 1005 | 843 | ||
| @@ -1008,27 +846,27 @@ void Controller_NPad::DisconnectNpad(u32 npad_id) { | |||
| 1008 | } | 846 | } |
| 1009 | 847 | ||
| 1010 | void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) { | 848 | void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) { |
| 1011 | for (std::size_t device_idx = 0; device_idx < vibrations[npad_index].size(); ++device_idx) { | 849 | auto& controller = controller_data[npad_index]; |
| 850 | for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) { | ||
| 1012 | // Send an empty vibration to stop any vibrations. | 851 | // Send an empty vibration to stop any vibrations. |
| 1013 | VibrateControllerAtIndex(npad_index, device_idx, {}); | 852 | VibrateControllerAtIndex(npad_index, device_idx, {}); |
| 1014 | vibration_devices_mounted[npad_index][device_idx] = false; | 853 | controller.vibration[device_idx].device_mounted = false; |
| 1015 | } | 854 | } |
| 1016 | 855 | ||
| 1017 | Settings::values.players.GetValue()[npad_index].connected = false; | 856 | controller.device->Disconnect(); |
| 1018 | connected_controllers[npad_index].is_connected = false; | 857 | |
| 1019 | 858 | auto& shared_memory_entry = controller.shared_memory_entry; | |
| 1020 | auto& controller = shared_memory_entries[npad_index]; | 859 | shared_memory_entry.style_set.raw = 0; // Zero out |
| 1021 | controller.style_set.raw = 0; // Zero out | 860 | shared_memory_entry.device_type.raw = 0; |
| 1022 | controller.device_type.raw = 0; | 861 | shared_memory_entry.system_properties.raw = 0; |
| 1023 | controller.system_properties.raw = 0; | 862 | shared_memory_entry.button_properties.raw = 0; |
| 1024 | controller.button_properties.raw = 0; | 863 | shared_memory_entry.battery_level_dual = 0; |
| 1025 | controller.battery_level_dual = 0; | 864 | shared_memory_entry.battery_level_left = 0; |
| 1026 | controller.battery_level_left = 0; | 865 | shared_memory_entry.battery_level_right = 0; |
| 1027 | controller.battery_level_right = 0; | 866 | shared_memory_entry.fullkey_color = {}; |
| 1028 | controller.fullkey_color = {}; | 867 | shared_memory_entry.joycon_color = {}; |
| 1029 | controller.joycon_color = {}; | 868 | shared_memory_entry.assignment_mode = NpadJoyAssignmentMode::Dual; |
| 1030 | controller.assignment_mode = NpadAssignments::Dual; | 869 | shared_memory_entry.footer_type = AppletFooterUiType::None; |
| 1031 | controller.footer_type = AppletFooterUiType::None; | ||
| 1032 | 870 | ||
| 1033 | SignalStyleSetChangedEvent(IndexToNPad(npad_index)); | 871 | SignalStyleSetChangedEvent(IndexToNPad(npad_index)); |
| 1034 | } | 872 | } |
| @@ -1069,16 +907,18 @@ void Controller_NPad::ResetSixAxisFusionParameters() { | |||
| 1069 | void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) { | 907 | void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) { |
| 1070 | const auto npad_index_1 = NPadIdToIndex(npad_id_1); | 908 | const auto npad_index_1 = NPadIdToIndex(npad_id_1); |
| 1071 | const auto npad_index_2 = NPadIdToIndex(npad_id_2); | 909 | const auto npad_index_2 = NPadIdToIndex(npad_id_2); |
| 910 | const auto& controller_1 = controller_data[npad_index_1].device; | ||
| 911 | const auto& controller_2 = controller_data[npad_index_2].device; | ||
| 1072 | 912 | ||
| 1073 | // If the controllers at both npad indices form a pair of left and right joycons, merge them. | 913 | // If the controllers at both npad indices form a pair of left and right joycons, merge them. |
| 1074 | // Otherwise, do nothing. | 914 | // Otherwise, do nothing. |
| 1075 | if ((connected_controllers[npad_index_1].type == NPadControllerType::JoyLeft && | 915 | if ((controller_1->GetNpadType() == Core::HID::NpadType::JoyconLeft && |
| 1076 | connected_controllers[npad_index_2].type == NPadControllerType::JoyRight) || | 916 | controller_2->GetNpadType() == Core::HID::NpadType::JoyconRight) || |
| 1077 | (connected_controllers[npad_index_2].type == NPadControllerType::JoyLeft && | 917 | (controller_2->GetNpadType() == Core::HID::NpadType::JoyconLeft && |
| 1078 | connected_controllers[npad_index_1].type == NPadControllerType::JoyRight)) { | 918 | controller_1->GetNpadType() == Core::HID::NpadType::JoyconRight)) { |
| 1079 | // Disconnect the joycon at the second id and connect the dual joycon at the first index. | 919 | // Disconnect the joycon at the second id and connect the dual joycon at the first index. |
| 1080 | DisconnectNpad(npad_id_2); | 920 | DisconnectNpad(npad_id_2); |
| 1081 | AddNewControllerAt(NPadControllerType::JoyDual, npad_index_1); | 921 | AddNewControllerAt(Core::HID::NpadType::JoyconDual, npad_index_1); |
| 1082 | } | 922 | } |
| 1083 | } | 923 | } |
| 1084 | 924 | ||
| @@ -1099,16 +939,17 @@ bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) { | |||
| 1099 | } | 939 | } |
| 1100 | const auto npad_index_1 = NPadIdToIndex(npad_id_1); | 940 | const auto npad_index_1 = NPadIdToIndex(npad_id_1); |
| 1101 | const auto npad_index_2 = NPadIdToIndex(npad_id_2); | 941 | const auto npad_index_2 = NPadIdToIndex(npad_id_2); |
| 942 | const auto& controller_1 = controller_data[npad_index_1].device; | ||
| 943 | const auto& controller_2 = controller_data[npad_index_2].device; | ||
| 944 | const auto type_index_1 = controller_1->GetNpadType(); | ||
| 945 | const auto type_index_2 = controller_2->GetNpadType(); | ||
| 1102 | 946 | ||
| 1103 | if (!IsControllerSupported(connected_controllers[npad_index_1].type) || | 947 | if (!IsControllerSupported(type_index_1) || !IsControllerSupported(type_index_2)) { |
| 1104 | !IsControllerSupported(connected_controllers[npad_index_2].type)) { | ||
| 1105 | return false; | 948 | return false; |
| 1106 | } | 949 | } |
| 1107 | 950 | ||
| 1108 | std::swap(connected_controllers[npad_index_1].type, connected_controllers[npad_index_2].type); | 951 | AddNewControllerAt(type_index_2, npad_index_1); |
| 1109 | 952 | AddNewControllerAt(type_index_1, npad_index_2); | |
| 1110 | AddNewControllerAt(connected_controllers[npad_index_1].type, npad_index_1); | ||
| 1111 | AddNewControllerAt(connected_controllers[npad_index_2].type, npad_index_2); | ||
| 1112 | 953 | ||
| 1113 | return true; | 954 | return true; |
| 1114 | } | 955 | } |
| @@ -1141,12 +982,14 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { | |||
| 1141 | } | 982 | } |
| 1142 | 983 | ||
| 1143 | bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const { | 984 | bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const { |
| 1144 | return unintended_home_button_input_protection[NPadIdToIndex(npad_id)]; | 985 | auto& controller = controller_data[NPadIdToIndex(npad_id)]; |
| 986 | return controller.unintended_home_button_input_protection; | ||
| 1145 | } | 987 | } |
| 1146 | 988 | ||
| 1147 | void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, | 989 | void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, |
| 1148 | u32 npad_id) { | 990 | u32 npad_id) { |
| 1149 | unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled; | 991 | auto& controller = controller_data[NPadIdToIndex(npad_id)]; |
| 992 | controller.unintended_home_button_input_protection = is_protection_enabled; | ||
| 1150 | } | 993 | } |
| 1151 | 994 | ||
| 1152 | void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) { | 995 | void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) { |
| @@ -1154,32 +997,34 @@ void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) { | |||
| 1154 | } | 997 | } |
| 1155 | 998 | ||
| 1156 | void Controller_NPad::ClearAllConnectedControllers() { | 999 | void Controller_NPad::ClearAllConnectedControllers() { |
| 1157 | for (auto& controller : connected_controllers) { | 1000 | for (auto& controller : controller_data) { |
| 1158 | if (controller.is_connected && controller.type != NPadControllerType::None) { | 1001 | if (controller.device->IsConnected() && |
| 1159 | controller.type = NPadControllerType::None; | 1002 | controller.device->GetNpadType() != Core::HID::NpadType::None) { |
| 1160 | controller.is_connected = false; | 1003 | controller.device->SetNpadType(Core::HID::NpadType::None); |
| 1004 | controller.device->Disconnect(); | ||
| 1161 | } | 1005 | } |
| 1162 | } | 1006 | } |
| 1163 | } | 1007 | } |
| 1164 | 1008 | ||
| 1165 | void Controller_NPad::DisconnectAllConnectedControllers() { | 1009 | void Controller_NPad::DisconnectAllConnectedControllers() { |
| 1166 | for (auto& controller : connected_controllers) { | 1010 | for (auto& controller : controller_data) { |
| 1167 | controller.is_connected = false; | 1011 | controller.device->Disconnect(); |
| 1168 | } | 1012 | } |
| 1169 | } | 1013 | } |
| 1170 | 1014 | ||
| 1171 | void Controller_NPad::ConnectAllDisconnectedControllers() { | 1015 | void Controller_NPad::ConnectAllDisconnectedControllers() { |
| 1172 | for (auto& controller : connected_controllers) { | 1016 | for (auto& controller : controller_data) { |
| 1173 | if (controller.type != NPadControllerType::None && !controller.is_connected) { | 1017 | if (controller.device->GetNpadType() != Core::HID::NpadType::None && |
| 1174 | controller.is_connected = true; | 1018 | !controller.device->IsConnected()) { |
| 1019 | controller.device->Connect(); | ||
| 1175 | } | 1020 | } |
| 1176 | } | 1021 | } |
| 1177 | } | 1022 | } |
| 1178 | 1023 | ||
| 1179 | void Controller_NPad::ClearAllControllers() { | 1024 | void Controller_NPad::ClearAllControllers() { |
| 1180 | for (auto& controller : connected_controllers) { | 1025 | for (auto& controller : controller_data) { |
| 1181 | controller.type = NPadControllerType::None; | 1026 | controller.device->SetNpadType(Core::HID::NpadType::None); |
| 1182 | controller.is_connected = false; | 1027 | controller.device->Disconnect(); |
| 1183 | } | 1028 | } |
| 1184 | } | 1029 | } |
| 1185 | 1030 | ||
| @@ -1187,8 +1032,8 @@ u32 Controller_NPad::GetAndResetPressState() { | |||
| 1187 | return press_state.exchange(0); | 1032 | return press_state.exchange(0); |
| 1188 | } | 1033 | } |
| 1189 | 1034 | ||
| 1190 | bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const { | 1035 | bool Controller_NPad::IsControllerSupported(Core::HID::NpadType controller) const { |
| 1191 | if (controller == NPadControllerType::Handheld) { | 1036 | if (controller == Core::HID::NpadType::Handheld) { |
| 1192 | const bool support_handheld = | 1037 | const bool support_handheld = |
| 1193 | std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), | 1038 | std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), |
| 1194 | NPAD_HANDHELD) != supported_npad_id_types.end(); | 1039 | NPAD_HANDHELD) != supported_npad_id_types.end(); |
| @@ -1196,7 +1041,7 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const | |||
| 1196 | if (!support_handheld) { | 1041 | if (!support_handheld) { |
| 1197 | return false; | 1042 | return false; |
| 1198 | } | 1043 | } |
| 1199 | // Handheld should not be supported in docked mode | 1044 | // Handheld shouldn't be supported in docked mode |
| 1200 | if (Settings::values.use_docked_mode.GetValue()) { | 1045 | if (Settings::values.use_docked_mode.GetValue()) { |
| 1201 | return false; | 1046 | return false; |
| 1202 | } | 1047 | } |
| @@ -1206,18 +1051,19 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const | |||
| 1206 | 1051 | ||
| 1207 | if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(), | 1052 | if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(), |
| 1208 | [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) { | 1053 | [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) { |
| 1054 | Core::HID::NpadStyleTag style = GetSupportedStyleSet(); | ||
| 1209 | switch (controller) { | 1055 | switch (controller) { |
| 1210 | case NPadControllerType::ProController: | 1056 | case Core::HID::NpadType::ProController: |
| 1211 | return style.fullkey; | 1057 | return style.fullkey; |
| 1212 | case NPadControllerType::JoyDual: | 1058 | case Core::HID::NpadType::JoyconDual: |
| 1213 | return style.joycon_dual; | 1059 | return style.joycon_dual; |
| 1214 | case NPadControllerType::JoyLeft: | 1060 | case Core::HID::NpadType::JoyconLeft: |
| 1215 | return style.joycon_left; | 1061 | return style.joycon_left; |
| 1216 | case NPadControllerType::JoyRight: | 1062 | case Core::HID::NpadType::JoyconRight: |
| 1217 | return style.joycon_right; | 1063 | return style.joycon_right; |
| 1218 | case NPadControllerType::GameCube: | 1064 | case Core::HID::NpadType::GameCube: |
| 1219 | return style.gamecube; | 1065 | return style.gamecube; |
| 1220 | case NPadControllerType::Pokeball: | 1066 | case Core::HID::NpadType::Pokeball: |
| 1221 | return style.palma; | 1067 | return style.palma; |
| 1222 | default: | 1068 | default: |
| 1223 | return false; | 1069 | return false; |
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index f3e868bdb..483cae5b6 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h | |||
| @@ -12,8 +12,10 @@ | |||
| 12 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 13 | #include "common/quaternion.h" | 13 | #include "common/quaternion.h" |
| 14 | #include "common/settings.h" | 14 | #include "common/settings.h" |
| 15 | #include "core/frontend/input.h" | 15 | #include "core/hid/hid_core.h" |
| 16 | #include "core/hid/hid_types.h" | ||
| 16 | #include "core/hle/service/hid/controllers/controller_base.h" | 17 | #include "core/hle/service/hid/controllers/controller_base.h" |
| 18 | #include "core/hle/service/hid/ring_lifo.h" | ||
| 17 | 19 | ||
| 18 | namespace Kernel { | 20 | namespace Kernel { |
| 19 | class KEvent; | 21 | class KEvent; |
| @@ -48,31 +50,6 @@ public: | |||
| 48 | void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, | 50 | void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, |
| 49 | std::size_t size) override; | 51 | std::size_t size) override; |
| 50 | 52 | ||
| 51 | // Called when input devices should be loaded | ||
| 52 | void OnLoadInputDevices() override; | ||
| 53 | |||
| 54 | enum class NPadControllerType { | ||
| 55 | None, | ||
| 56 | ProController, | ||
| 57 | Handheld, | ||
| 58 | JoyDual, | ||
| 59 | JoyLeft, | ||
| 60 | JoyRight, | ||
| 61 | GameCube, | ||
| 62 | Pokeball, | ||
| 63 | }; | ||
| 64 | |||
| 65 | enum class NpadType : u8 { | ||
| 66 | ProController = 3, | ||
| 67 | Handheld = 4, | ||
| 68 | JoyconDual = 5, | ||
| 69 | JoyconLeft = 6, | ||
| 70 | JoyconRight = 7, | ||
| 71 | GameCube = 8, | ||
| 72 | Pokeball = 9, | ||
| 73 | MaxNpadType = 10, | ||
| 74 | }; | ||
| 75 | |||
| 76 | enum class DeviceIndex : u8 { | 53 | enum class DeviceIndex : u8 { |
| 77 | Left = 0, | 54 | Left = 0, |
| 78 | Right = 1, | 55 | Right = 1, |
| @@ -80,28 +57,33 @@ public: | |||
| 80 | MaxDeviceIndex = 3, | 57 | MaxDeviceIndex = 3, |
| 81 | }; | 58 | }; |
| 82 | 59 | ||
| 60 | // This is nn::hid::GyroscopeZeroDriftMode | ||
| 83 | enum class GyroscopeZeroDriftMode : u32 { | 61 | enum class GyroscopeZeroDriftMode : u32 { |
| 84 | Loose = 0, | 62 | Loose = 0, |
| 85 | Standard = 1, | 63 | Standard = 1, |
| 86 | Tight = 2, | 64 | Tight = 2, |
| 87 | }; | 65 | }; |
| 88 | 66 | ||
| 89 | enum class NpadHoldType : u64 { | 67 | // This is nn::hid::NpadJoyHoldType |
| 68 | enum class NpadJoyHoldType : u64 { | ||
| 90 | Vertical = 0, | 69 | Vertical = 0, |
| 91 | Horizontal = 1, | 70 | Horizontal = 1, |
| 92 | }; | 71 | }; |
| 93 | 72 | ||
| 94 | enum class NpadAssignments : u32 { | 73 | // This is nn::hid::NpadJoyAssignmentMode |
| 74 | enum class NpadJoyAssignmentMode : u32 { | ||
| 95 | Dual = 0, | 75 | Dual = 0, |
| 96 | Single = 1, | 76 | Single = 1, |
| 97 | }; | 77 | }; |
| 98 | 78 | ||
| 79 | // This is nn::hid::NpadHandheldActivationMode | ||
| 99 | enum class NpadHandheldActivationMode : u64 { | 80 | enum class NpadHandheldActivationMode : u64 { |
| 100 | Dual = 0, | 81 | Dual = 0, |
| 101 | Single = 1, | 82 | Single = 1, |
| 102 | None = 2, | 83 | None = 2, |
| 103 | }; | 84 | }; |
| 104 | 85 | ||
| 86 | // This is nn::hid::NpadCommunicationMode | ||
| 105 | enum class NpadCommunicationMode : u64 { | 87 | enum class NpadCommunicationMode : u64 { |
| 106 | Mode_5ms = 0, | 88 | Mode_5ms = 0, |
| 107 | Mode_10ms = 1, | 89 | Mode_10ms = 1, |
| @@ -110,33 +92,14 @@ public: | |||
| 110 | }; | 92 | }; |
| 111 | 93 | ||
| 112 | struct DeviceHandle { | 94 | struct DeviceHandle { |
| 113 | NpadType npad_type; | 95 | Core::HID::NpadType npad_type; |
| 114 | u8 npad_id; | 96 | u8 npad_id; |
| 115 | DeviceIndex device_index; | 97 | DeviceIndex device_index; |
| 116 | INSERT_PADDING_BYTES_NOINIT(1); | 98 | INSERT_PADDING_BYTES_NOINIT(1); |
| 117 | }; | 99 | }; |
| 118 | static_assert(sizeof(DeviceHandle) == 4, "DeviceHandle is an invalid size"); | 100 | static_assert(sizeof(DeviceHandle) == 4, "DeviceHandle is an invalid size"); |
| 119 | 101 | ||
| 120 | struct NpadStyleSet { | 102 | // This is nn::hid::VibrationValue |
| 121 | union { | ||
| 122 | u32_le raw{}; | ||
| 123 | |||
| 124 | BitField<0, 1, u32> fullkey; | ||
| 125 | BitField<1, 1, u32> handheld; | ||
| 126 | BitField<2, 1, u32> joycon_dual; | ||
| 127 | BitField<3, 1, u32> joycon_left; | ||
| 128 | BitField<4, 1, u32> joycon_right; | ||
| 129 | BitField<5, 1, u32> gamecube; | ||
| 130 | BitField<6, 1, u32> palma; | ||
| 131 | BitField<7, 1, u32> lark; | ||
| 132 | BitField<8, 1, u32> handheld_lark; | ||
| 133 | BitField<9, 1, u32> lucia; | ||
| 134 | BitField<29, 1, u32> system_ext; | ||
| 135 | BitField<30, 1, u32> system; | ||
| 136 | }; | ||
| 137 | }; | ||
| 138 | static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size"); | ||
| 139 | |||
| 140 | struct VibrationValue { | 103 | struct VibrationValue { |
| 141 | f32 amp_low; | 104 | f32 amp_low; |
| 142 | f32 freq_low; | 105 | f32 freq_low; |
| @@ -168,15 +131,15 @@ public: | |||
| 168 | }; | 131 | }; |
| 169 | }; | 132 | }; |
| 170 | 133 | ||
| 171 | void SetSupportedStyleSet(NpadStyleSet style_set); | 134 | void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set); |
| 172 | NpadStyleSet GetSupportedStyleSet() const; | 135 | Core::HID::NpadStyleTag GetSupportedStyleSet() const; |
| 173 | 136 | ||
| 174 | void SetSupportedNpadIdTypes(u8* data, std::size_t length); | 137 | void SetSupportedNpadIdTypes(u8* data, std::size_t length); |
| 175 | void GetSupportedNpadIdTypes(u32* data, std::size_t max_length); | 138 | void GetSupportedNpadIdTypes(u32* data, std::size_t max_length); |
| 176 | std::size_t GetSupportedNpadIdTypesSize() const; | 139 | std::size_t GetSupportedNpadIdTypesSize() const; |
| 177 | 140 | ||
| 178 | void SetHoldType(NpadHoldType joy_hold_type); | 141 | void SetHoldType(NpadJoyHoldType joy_hold_type); |
| 179 | NpadHoldType GetHoldType() const; | 142 | NpadJoyHoldType GetHoldType() const; |
| 180 | 143 | ||
| 181 | void SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode); | 144 | void SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode); |
| 182 | NpadHandheldActivationMode GetNpadHandheldActivationMode() const; | 145 | NpadHandheldActivationMode GetNpadHandheldActivationMode() const; |
| @@ -184,7 +147,7 @@ public: | |||
| 184 | void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_); | 147 | void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_); |
| 185 | NpadCommunicationMode GetNpadCommunicationMode() const; | 148 | NpadCommunicationMode GetNpadCommunicationMode() const; |
| 186 | 149 | ||
| 187 | void SetNpadMode(u32 npad_id, NpadAssignments assignment_mode); | 150 | void SetNpadMode(u32 npad_id, NpadJoyAssignmentMode assignment_mode); |
| 188 | 151 | ||
| 189 | bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, | 152 | bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, |
| 190 | const VibrationValue& vibration_value); | 153 | const VibrationValue& vibration_value); |
| @@ -209,9 +172,9 @@ public: | |||
| 209 | void SignalStyleSetChangedEvent(u32 npad_id) const; | 172 | void SignalStyleSetChangedEvent(u32 npad_id) const; |
| 210 | 173 | ||
| 211 | // Adds a new controller at an index. | 174 | // Adds a new controller at an index. |
| 212 | void AddNewControllerAt(NPadControllerType controller, std::size_t npad_index); | 175 | void AddNewControllerAt(Core::HID::NpadType controller, std::size_t npad_index); |
| 213 | // Adds a new controller at an index with connection status. | 176 | // Adds a new controller at an index with connection status. |
| 214 | void UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected); | 177 | void UpdateControllerAt(Core::HID::NpadType controller, std::size_t npad_index, bool connected); |
| 215 | 178 | ||
| 216 | void DisconnectNpad(u32 npad_id); | 179 | void DisconnectNpad(u32 npad_id); |
| 217 | void DisconnectNpadAtIndex(std::size_t index); | 180 | void DisconnectNpadAtIndex(std::size_t index); |
| @@ -241,103 +204,37 @@ public: | |||
| 241 | // Specifically for cheat engine and other features. | 204 | // Specifically for cheat engine and other features. |
| 242 | u32 GetAndResetPressState(); | 205 | u32 GetAndResetPressState(); |
| 243 | 206 | ||
| 244 | static Controller_NPad::NPadControllerType MapSettingsTypeToNPad(Settings::ControllerType type); | ||
| 245 | static Settings::ControllerType MapNPadToSettingsType(Controller_NPad::NPadControllerType type); | ||
| 246 | static std::size_t NPadIdToIndex(u32 npad_id); | 207 | static std::size_t NPadIdToIndex(u32 npad_id); |
| 247 | static u32 IndexToNPad(std::size_t index); | 208 | static u32 IndexToNPad(std::size_t index); |
| 248 | static bool IsNpadIdValid(u32 npad_id); | 209 | static bool IsNpadIdValid(u32 npad_id); |
| 249 | static bool IsDeviceHandleValid(const DeviceHandle& device_handle); | 210 | static bool IsDeviceHandleValid(const DeviceHandle& device_handle); |
| 250 | 211 | ||
| 251 | private: | 212 | private: |
| 252 | struct CommonHeader { | 213 | // This is nn::hid::detail::ColorAttribute |
| 253 | s64_le timestamp; | 214 | enum class ColorAttribute : u32_le { |
| 254 | s64_le total_entry_count; | ||
| 255 | s64_le last_entry_index; | ||
| 256 | s64_le entry_count; | ||
| 257 | }; | ||
| 258 | static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); | ||
| 259 | |||
| 260 | enum class ColorAttributes : u32_le { | ||
| 261 | Ok = 0, | 215 | Ok = 0, |
| 262 | ReadError = 1, | 216 | ReadError = 1, |
| 263 | NoController = 2, | 217 | NoController = 2, |
| 264 | }; | 218 | }; |
| 265 | static_assert(sizeof(ColorAttributes) == 4, "ColorAttributes is an invalid size"); | 219 | static_assert(sizeof(ColorAttribute) == 4, "ColorAttribute is an invalid size"); |
| 266 | |||
| 267 | struct ControllerColor { | ||
| 268 | u32_le body; | ||
| 269 | u32_le button; | ||
| 270 | }; | ||
| 271 | static_assert(sizeof(ControllerColor) == 8, "ControllerColor is an invalid size"); | ||
| 272 | |||
| 273 | struct FullKeyColor { | ||
| 274 | ColorAttributes attribute; | ||
| 275 | ControllerColor fullkey; | ||
| 276 | }; | ||
| 277 | static_assert(sizeof(FullKeyColor) == 0xC, "FullKeyColor is an invalid size"); | ||
| 278 | |||
| 279 | struct JoyconColor { | ||
| 280 | ColorAttributes attribute; | ||
| 281 | ControllerColor left; | ||
| 282 | ControllerColor right; | ||
| 283 | }; | ||
| 284 | static_assert(sizeof(JoyconColor) == 0x14, "JoyconColor is an invalid size"); | ||
| 285 | 220 | ||
| 286 | struct ControllerPadState { | 221 | // This is nn::hid::detail::NpadFullKeyColorState |
| 287 | union { | 222 | struct NpadFullKeyColorState { |
| 288 | u64_le raw{}; | 223 | ColorAttribute attribute; |
| 289 | // Button states | 224 | Core::HID::NpadControllerColor fullkey; |
| 290 | BitField<0, 1, u64> a; | ||
| 291 | BitField<1, 1, u64> b; | ||
| 292 | BitField<2, 1, u64> x; | ||
| 293 | BitField<3, 1, u64> y; | ||
| 294 | BitField<4, 1, u64> l_stick; | ||
| 295 | BitField<5, 1, u64> r_stick; | ||
| 296 | BitField<6, 1, u64> l; | ||
| 297 | BitField<7, 1, u64> r; | ||
| 298 | BitField<8, 1, u64> zl; | ||
| 299 | BitField<9, 1, u64> zr; | ||
| 300 | BitField<10, 1, u64> plus; | ||
| 301 | BitField<11, 1, u64> minus; | ||
| 302 | |||
| 303 | // D-Pad | ||
| 304 | BitField<12, 1, u64> d_left; | ||
| 305 | BitField<13, 1, u64> d_up; | ||
| 306 | BitField<14, 1, u64> d_right; | ||
| 307 | BitField<15, 1, u64> d_down; | ||
| 308 | |||
| 309 | // Left JoyStick | ||
| 310 | BitField<16, 1, u64> l_stick_left; | ||
| 311 | BitField<17, 1, u64> l_stick_up; | ||
| 312 | BitField<18, 1, u64> l_stick_right; | ||
| 313 | BitField<19, 1, u64> l_stick_down; | ||
| 314 | |||
| 315 | // Right JoyStick | ||
| 316 | BitField<20, 1, u64> r_stick_left; | ||
| 317 | BitField<21, 1, u64> r_stick_up; | ||
| 318 | BitField<22, 1, u64> r_stick_right; | ||
| 319 | BitField<23, 1, u64> r_stick_down; | ||
| 320 | |||
| 321 | // Not always active? | ||
| 322 | BitField<24, 1, u64> left_sl; | ||
| 323 | BitField<25, 1, u64> left_sr; | ||
| 324 | |||
| 325 | BitField<26, 1, u64> right_sl; | ||
| 326 | BitField<27, 1, u64> right_sr; | ||
| 327 | |||
| 328 | BitField<28, 1, u64> palma; | ||
| 329 | BitField<30, 1, u64> handheld_left_b; | ||
| 330 | }; | ||
| 331 | }; | 225 | }; |
| 332 | static_assert(sizeof(ControllerPadState) == 8, "ControllerPadState is an invalid size"); | 226 | static_assert(sizeof(NpadFullKeyColorState) == 0xC, "NpadFullKeyColorState is an invalid size"); |
| 333 | 227 | ||
| 334 | struct AnalogPosition { | 228 | // This is nn::hid::detail::NpadJoyColorState |
| 335 | s32_le x; | 229 | struct NpadJoyColorState { |
| 336 | s32_le y; | 230 | ColorAttribute attribute; |
| 231 | Core::HID::NpadControllerColor left; | ||
| 232 | Core::HID::NpadControllerColor right; | ||
| 337 | }; | 233 | }; |
| 338 | static_assert(sizeof(AnalogPosition) == 8, "AnalogPosition is an invalid size"); | 234 | static_assert(sizeof(NpadJoyColorState) == 0x14, "NpadJoyColorState is an invalid size"); |
| 339 | 235 | ||
| 340 | struct ConnectionState { | 236 | // This is nn::hid::NpadAttribute |
| 237 | struct NpadAttribute { | ||
| 341 | union { | 238 | union { |
| 342 | u32_le raw{}; | 239 | u32_le raw{}; |
| 343 | BitField<0, 1, u32> is_connected; | 240 | BitField<0, 1, u32> is_connected; |
| @@ -348,76 +245,57 @@ private: | |||
| 348 | BitField<5, 1, u32> is_right_wired; | 245 | BitField<5, 1, u32> is_right_wired; |
| 349 | }; | 246 | }; |
| 350 | }; | 247 | }; |
| 351 | static_assert(sizeof(ConnectionState) == 4, "ConnectionState is an invalid size"); | 248 | static_assert(sizeof(NpadAttribute) == 4, "NpadAttribute is an invalid size"); |
| 352 | 249 | ||
| 353 | struct ControllerPad { | 250 | // This is nn::hid::NpadFullKeyState |
| 354 | ControllerPadState pad_states; | 251 | // This is nn::hid::NpadHandheldState |
| 355 | AnalogPosition l_stick; | 252 | // This is nn::hid::NpadJoyDualState |
| 356 | AnalogPosition r_stick; | 253 | // This is nn::hid::NpadJoyLeftState |
| 357 | }; | 254 | // This is nn::hid::NpadJoyRightState |
| 358 | static_assert(sizeof(ControllerPad) == 0x18, "ControllerPad is an invalid size"); | 255 | // This is nn::hid::NpadPalmaState |
| 359 | 256 | // This is nn::hid::NpadSystemExtState | |
| 360 | struct GenericStates { | 257 | struct NPadGenericState { |
| 361 | s64_le timestamp; | 258 | s64_le sampling_number; |
| 362 | s64_le timestamp2; | 259 | Core::HID::NpadButtonState npad_buttons; |
| 363 | ControllerPad pad; | 260 | Core::HID::AnalogStickState l_stick; |
| 364 | ConnectionState connection_status; | 261 | Core::HID::AnalogStickState r_stick; |
| 365 | }; | 262 | NpadAttribute connection_status; |
| 366 | static_assert(sizeof(GenericStates) == 0x30, "NPadGenericStates is an invalid size"); | 263 | INSERT_PADDING_BYTES(4); // Reserved |
| 367 | |||
| 368 | struct NPadGeneric { | ||
| 369 | CommonHeader common; | ||
| 370 | std::array<GenericStates, 17> npad; | ||
| 371 | }; | 264 | }; |
| 372 | static_assert(sizeof(NPadGeneric) == 0x350, "NPadGeneric is an invalid size"); | 265 | static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size"); |
| 373 | 266 | ||
| 374 | struct SixAxisAttributes { | 267 | // This is nn::hid::SixAxisSensorAttribute |
| 268 | struct SixAxisSensorAttribute { | ||
| 375 | union { | 269 | union { |
| 376 | u32_le raw{}; | 270 | u32_le raw{}; |
| 377 | BitField<0, 1, u32> is_connected; | 271 | BitField<0, 1, u32> is_connected; |
| 378 | BitField<1, 1, u32> is_interpolated; | 272 | BitField<1, 1, u32> is_interpolated; |
| 379 | }; | 273 | }; |
| 380 | }; | 274 | }; |
| 381 | static_assert(sizeof(SixAxisAttributes) == 4, "SixAxisAttributes is an invalid size"); | 275 | static_assert(sizeof(SixAxisSensorAttribute) == 4, "SixAxisSensorAttribute is an invalid size"); |
| 382 | 276 | ||
| 383 | struct SixAxisStates { | 277 | // This is nn::hid::SixAxisSensorState |
| 384 | s64_le timestamp{}; | 278 | struct SixAxisSensorState { |
| 385 | INSERT_PADDING_WORDS(2); | 279 | s64_le delta_time{}; |
| 386 | s64_le timestamp2{}; | 280 | s64_le sampling_number{}; |
| 387 | Common::Vec3f accel{}; | 281 | Common::Vec3f accel{}; |
| 388 | Common::Vec3f gyro{}; | 282 | Common::Vec3f gyro{}; |
| 389 | Common::Vec3f rotation{}; | 283 | Common::Vec3f rotation{}; |
| 390 | std::array<Common::Vec3f, 3> orientation{}; | 284 | std::array<Common::Vec3f, 3> orientation{}; |
| 391 | SixAxisAttributes attribute; | 285 | SixAxisSensorAttribute attribute; |
| 392 | INSERT_PADDING_BYTES(4); // Reserved | 286 | INSERT_PADDING_BYTES(4); // Reserved |
| 393 | }; | 287 | }; |
| 394 | static_assert(sizeof(SixAxisStates) == 0x68, "SixAxisStates is an invalid size"); | 288 | static_assert(sizeof(SixAxisSensorState) == 0x60, "SixAxisSensorState is an invalid size"); |
| 395 | |||
| 396 | struct SixAxisGeneric { | ||
| 397 | CommonHeader common{}; | ||
| 398 | std::array<SixAxisStates, 17> sixaxis{}; | ||
| 399 | }; | ||
| 400 | static_assert(sizeof(SixAxisGeneric) == 0x708, "SixAxisGeneric is an invalid size"); | ||
| 401 | 289 | ||
| 402 | struct TriggerState { | 290 | // This is nn::hid::server::NpadGcTriggerState |
| 403 | s64_le timestamp{}; | 291 | struct NpadGcTriggerState { |
| 404 | s64_le timestamp2{}; | 292 | s64_le sampling_number{}; |
| 405 | s32_le l_analog{}; | 293 | s32_le l_analog{}; |
| 406 | s32_le r_analog{}; | 294 | s32_le r_analog{}; |
| 407 | }; | 295 | }; |
| 408 | static_assert(sizeof(TriggerState) == 0x18, "TriggerState is an invalid size"); | 296 | static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size"); |
| 409 | |||
| 410 | struct TriggerGeneric { | ||
| 411 | INSERT_PADDING_BYTES(0x4); | ||
| 412 | s64_le timestamp; | ||
| 413 | INSERT_PADDING_BYTES(0x4); | ||
| 414 | s64_le total_entry_count; | ||
| 415 | s64_le last_entry_index; | ||
| 416 | s64_le entry_count; | ||
| 417 | std::array<TriggerState, 17> trigger{}; | ||
| 418 | }; | ||
| 419 | static_assert(sizeof(TriggerGeneric) == 0x1C8, "TriggerGeneric is an invalid size"); | ||
| 420 | 297 | ||
| 298 | // This is nn::hid::NpadSystemProperties | ||
| 421 | struct NPadSystemProperties { | 299 | struct NPadSystemProperties { |
| 422 | union { | 300 | union { |
| 423 | s64_le raw{}; | 301 | s64_le raw{}; |
| @@ -438,15 +316,18 @@ private: | |||
| 438 | }; | 316 | }; |
| 439 | static_assert(sizeof(NPadSystemProperties) == 0x8, "NPadSystemProperties is an invalid size"); | 317 | static_assert(sizeof(NPadSystemProperties) == 0x8, "NPadSystemProperties is an invalid size"); |
| 440 | 318 | ||
| 441 | struct NPadButtonProperties { | 319 | // This is nn::hid::NpadSystemButtonProperties |
| 320 | struct NpadSystemButtonProperties { | ||
| 442 | union { | 321 | union { |
| 443 | s32_le raw{}; | 322 | s32_le raw{}; |
| 444 | BitField<0, 1, s32> is_home_button_protection_enabled; | 323 | BitField<0, 1, s32> is_home_button_protection_enabled; |
| 445 | }; | 324 | }; |
| 446 | }; | 325 | }; |
| 447 | static_assert(sizeof(NPadButtonProperties) == 0x4, "NPadButtonProperties is an invalid size"); | 326 | static_assert(sizeof(NpadSystemButtonProperties) == 0x4, |
| 327 | "NPadButtonProperties is an invalid size"); | ||
| 448 | 328 | ||
| 449 | struct NPadDevice { | 329 | // This is nn::hid::system::DeviceType |
| 330 | struct DeviceType { | ||
| 450 | union { | 331 | union { |
| 451 | u32_le raw{}; | 332 | u32_le raw{}; |
| 452 | BitField<0, 1, s32> fullkey; | 333 | BitField<0, 1, s32> fullkey; |
| @@ -469,14 +350,6 @@ private: | |||
| 469 | }; | 350 | }; |
| 470 | }; | 351 | }; |
| 471 | 352 | ||
| 472 | struct MotionDevice { | ||
| 473 | Common::Vec3f accel; | ||
| 474 | Common::Vec3f gyro; | ||
| 475 | Common::Vec3f rotation; | ||
| 476 | std::array<Common::Vec3f, 3> orientation; | ||
| 477 | Common::Quaternion<f32> quaternion; | ||
| 478 | }; | ||
| 479 | |||
| 480 | struct NfcXcdHandle { | 353 | struct NfcXcdHandle { |
| 481 | INSERT_PADDING_BYTES(0x60); | 354 | INSERT_PADDING_BYTES(0x60); |
| 482 | }; | 355 | }; |
| @@ -485,6 +358,7 @@ private: | |||
| 485 | INSERT_PADDING_BYTES(0x4); | 358 | INSERT_PADDING_BYTES(0x4); |
| 486 | }; | 359 | }; |
| 487 | 360 | ||
| 361 | // This is nn::hid::server::NpadGcTriggerState | ||
| 488 | enum class AppletFooterUiType : u8 { | 362 | enum class AppletFooterUiType : u8 { |
| 489 | None = 0, | 363 | None = 0, |
| 490 | HandheldNone = 1, | 364 | HandheldNone = 1, |
| @@ -510,95 +384,90 @@ private: | |||
| 510 | Lagon = 21, | 384 | Lagon = 21, |
| 511 | }; | 385 | }; |
| 512 | 386 | ||
| 513 | struct NPadEntry { | 387 | // This is nn::hid::detail::NpadInternalState |
| 514 | NpadStyleSet style_set; | 388 | struct NpadInternalState { |
| 515 | NpadAssignments assignment_mode; | 389 | Core::HID::NpadStyleTag style_set; |
| 516 | FullKeyColor fullkey_color; | 390 | NpadJoyAssignmentMode assignment_mode; |
| 517 | JoyconColor joycon_color; | 391 | NpadFullKeyColorState fullkey_color; |
| 518 | 392 | NpadJoyColorState joycon_color; | |
| 519 | NPadGeneric fullkey_states; | 393 | Lifo<NPadGenericState> fullkey_lifo; |
| 520 | NPadGeneric handheld_states; | 394 | Lifo<NPadGenericState> handheld_lifo; |
| 521 | NPadGeneric joy_dual_states; | 395 | Lifo<NPadGenericState> joy_dual_lifo; |
| 522 | NPadGeneric joy_left_states; | 396 | Lifo<NPadGenericState> joy_left_lifo; |
| 523 | NPadGeneric joy_right_states; | 397 | Lifo<NPadGenericState> joy_right_lifo; |
| 524 | NPadGeneric palma_states; | 398 | Lifo<NPadGenericState> palma_lifo; |
| 525 | NPadGeneric system_ext_states; | 399 | Lifo<NPadGenericState> system_ext_lifo; |
| 526 | SixAxisGeneric sixaxis_fullkey; | 400 | Lifo<SixAxisSensorState> sixaxis_fullkey_lifo; |
| 527 | SixAxisGeneric sixaxis_handheld; | 401 | Lifo<SixAxisSensorState> sixaxis_handheld_lifo; |
| 528 | SixAxisGeneric sixaxis_dual_left; | 402 | Lifo<SixAxisSensorState> sixaxis_dual_left_lifo; |
| 529 | SixAxisGeneric sixaxis_dual_right; | 403 | Lifo<SixAxisSensorState> sixaxis_dual_right_lifo; |
| 530 | SixAxisGeneric sixaxis_left; | 404 | Lifo<SixAxisSensorState> sixaxis_left_lifo; |
| 531 | SixAxisGeneric sixaxis_right; | 405 | Lifo<SixAxisSensorState> sixaxis_right_lifo; |
| 532 | NPadDevice device_type; | 406 | DeviceType device_type; |
| 533 | INSERT_PADDING_BYTES(0x4); // reserved | 407 | INSERT_PADDING_BYTES(0x4); // Reserved |
| 534 | NPadSystemProperties system_properties; | 408 | NPadSystemProperties system_properties; |
| 535 | NPadButtonProperties button_properties; | 409 | NpadSystemButtonProperties button_properties; |
| 536 | u32 battery_level_dual; | 410 | Core::HID::BatteryLevel battery_level_dual; |
| 537 | u32 battery_level_left; | 411 | Core::HID::BatteryLevel battery_level_left; |
| 538 | u32 battery_level_right; | 412 | Core::HID::BatteryLevel battery_level_right; |
| 539 | AppletFooterUiAttributes footer_attributes; | 413 | AppletFooterUiAttributes footer_attributes; |
| 540 | AppletFooterUiType footer_type; | 414 | AppletFooterUiType footer_type; |
| 541 | // nfc_states needs to be checked switchbrew does not match with HW | 415 | // nfc_states needs to be checked switchbrew doesn't match with HW |
| 542 | NfcXcdHandle nfc_states; | 416 | NfcXcdHandle nfc_states; |
| 543 | INSERT_PADDING_BYTES(0x8); // Mutex | 417 | INSERT_PADDING_BYTES(0x18); // Unknown |
| 544 | TriggerGeneric gc_trigger_states; | 418 | Lifo<NpadGcTriggerState> gc_trigger_lifo; |
| 545 | INSERT_PADDING_BYTES(0xc1f); | 419 | INSERT_PADDING_BYTES(0xc1f); // Unknown |
| 546 | }; | 420 | }; |
| 547 | static_assert(sizeof(NPadEntry) == 0x5000, "NPadEntry is an invalid size"); | 421 | static_assert(sizeof(NpadInternalState) == 0x5000, "NpadInternalState is an invalid size"); |
| 548 | 422 | ||
| 549 | struct ControllerHolder { | 423 | struct VibrationData { |
| 550 | NPadControllerType type; | 424 | bool device_mounted{}; |
| 551 | bool is_connected; | 425 | VibrationValue latest_vibration_value{}; |
| 426 | std::chrono::steady_clock::time_point last_vibration_timepoint{}; | ||
| 552 | }; | 427 | }; |
| 553 | 428 | ||
| 429 | struct ControllerData { | ||
| 430 | Core::HID::EmulatedController* device; | ||
| 431 | Kernel::KEvent* styleset_changed_event{}; | ||
| 432 | NpadInternalState shared_memory_entry{}; | ||
| 433 | |||
| 434 | std::array<VibrationData, 2> vibration{}; | ||
| 435 | bool unintended_home_button_input_protection{}; | ||
| 436 | |||
| 437 | // Current pad state | ||
| 438 | NPadGenericState npad_pad_state{}; | ||
| 439 | NPadGenericState npad_libnx_state{}; | ||
| 440 | NpadGcTriggerState npad_trigger_state{}; | ||
| 441 | SixAxisSensorState sixaxis_fullkey_state{}; | ||
| 442 | SixAxisSensorState sixaxis_handheld_state{}; | ||
| 443 | SixAxisSensorState sixaxis_dual_left_state{}; | ||
| 444 | SixAxisSensorState sixaxis_dual_right_state{}; | ||
| 445 | SixAxisSensorState sixaxis_left_lifo_state{}; | ||
| 446 | SixAxisSensorState sixaxis_right_lifo_state{}; | ||
| 447 | int callback_key; | ||
| 448 | }; | ||
| 449 | |||
| 450 | void ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx); | ||
| 554 | void InitNewlyAddedController(std::size_t controller_idx); | 451 | void InitNewlyAddedController(std::size_t controller_idx); |
| 555 | bool IsControllerSupported(NPadControllerType controller) const; | 452 | bool IsControllerSupported(Core::HID::NpadType controller) const; |
| 556 | void RequestPadStateUpdate(u32 npad_id); | 453 | void RequestPadStateUpdate(u32 npad_id); |
| 557 | 454 | ||
| 558 | std::atomic<u32> press_state{}; | 455 | std::atomic<u32> press_state{}; |
| 559 | 456 | ||
| 560 | NpadStyleSet style{}; | 457 | std::array<ControllerData, 10> controller_data{}; |
| 561 | std::array<NPadEntry, 10> shared_memory_entries{}; | ||
| 562 | using ButtonArray = std::array< | ||
| 563 | std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>, | ||
| 564 | 10>; | ||
| 565 | using StickArray = std::array< | ||
| 566 | std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NumAnalogs>, | ||
| 567 | 10>; | ||
| 568 | using VibrationArray = std::array<std::array<std::unique_ptr<Input::VibrationDevice>, | ||
| 569 | Settings::NativeVibration::NUM_VIBRATIONS_HID>, | ||
| 570 | 10>; | ||
| 571 | using MotionArray = std::array< | ||
| 572 | std::array<std::unique_ptr<Input::MotionDevice>, Settings::NativeMotion::NUM_MOTIONS_HID>, | ||
| 573 | 10>; | ||
| 574 | |||
| 575 | KernelHelpers::ServiceContext& service_context; | 458 | KernelHelpers::ServiceContext& service_context; |
| 576 | std::mutex mutex; | 459 | std::mutex mutex; |
| 577 | ButtonArray buttons; | ||
| 578 | StickArray sticks; | ||
| 579 | VibrationArray vibrations; | ||
| 580 | MotionArray motions; | ||
| 581 | std::vector<u32> supported_npad_id_types{}; | 460 | std::vector<u32> supported_npad_id_types{}; |
| 582 | NpadHoldType hold_type{NpadHoldType::Vertical}; | 461 | NpadJoyHoldType hold_type{NpadJoyHoldType::Vertical}; |
| 583 | NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; | 462 | NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; |
| 584 | NpadCommunicationMode communication_mode{NpadCommunicationMode::Default}; | 463 | NpadCommunicationMode communication_mode{NpadCommunicationMode::Default}; |
| 585 | // Each controller should have their own styleset changed event | ||
| 586 | std::array<Kernel::KEvent*, 10> styleset_changed_events{}; | ||
| 587 | std::array<std::array<std::chrono::steady_clock::time_point, 2>, 10> | ||
| 588 | last_vibration_timepoints{}; | ||
| 589 | std::array<std::array<VibrationValue, 2>, 10> latest_vibration_values{}; | ||
| 590 | bool permit_vibration_session_enabled{false}; | 464 | bool permit_vibration_session_enabled{false}; |
| 591 | std::array<std::array<bool, 2>, 10> vibration_devices_mounted{}; | ||
| 592 | std::array<ControllerHolder, 10> connected_controllers{}; | ||
| 593 | std::array<bool, 10> unintended_home_button_input_protection{}; | ||
| 594 | bool analog_stick_use_center_clamp{}; | 465 | bool analog_stick_use_center_clamp{}; |
| 595 | GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; | 466 | GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; |
| 596 | bool sixaxis_sensors_enabled{true}; | 467 | bool sixaxis_sensors_enabled{true}; |
| 597 | f32 sixaxis_fusion_parameter1{}; | 468 | f32 sixaxis_fusion_parameter1{}; |
| 598 | f32 sixaxis_fusion_parameter2{}; | 469 | f32 sixaxis_fusion_parameter2{}; |
| 599 | bool sixaxis_at_rest{true}; | 470 | bool sixaxis_at_rest{true}; |
| 600 | std::array<ControllerPad, 10> npad_pad_states{}; | ||
| 601 | std::array<TriggerState, 10> npad_trigger_states{}; | ||
| 602 | bool is_in_lr_assignment_mode{false}; | 471 | bool is_in_lr_assignment_mode{false}; |
| 603 | }; | 472 | }; |
| 604 | } // namespace Service::HID | 473 | } // namespace Service::HID |