summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp115
-rw-r--r--src/core/hle/service/hid/controllers/npad.h17
-rw-r--r--src/core/hle/service/hid/hid.cpp4
3 files changed, 59 insertions, 77 deletions
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 9aa8d6f92..d17e64b2a 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -27,7 +27,7 @@ constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E;
27constexpr s32 HID_JOYSTICK_MAX = 0x7fff; 27constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
28constexpr s32 HID_JOYSTICK_MIN = -0x7fff; 28constexpr s32 HID_JOYSTICK_MIN = -0x7fff;
29constexpr std::size_t NPAD_OFFSET = 0x9A00; 29constexpr std::size_t NPAD_OFFSET = 0x9A00;
30 30constexpr u32 BATTERY_FULL = 2;
31enum class JoystickId : std::size_t { Joystick_Left, Joystick_Right }; 31enum class JoystickId : std::size_t { Joystick_Left, Joystick_Right };
32 32
33Controller_NPad::Controller_NPad() = default; 33Controller_NPad::Controller_NPad() = default;
@@ -46,6 +46,12 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) {
46 controller.device_type.handheld.Assign(1); 46 controller.device_type.handheld.Assign(1);
47 controller.pad_assignment = NPadAssignments::Dual; 47 controller.pad_assignment = NPadAssignments::Dual;
48 break; 48 break;
49 case NPadControllerType::JoyDual:
50 controller.joy_styles.joycon_dual.Assign(1);
51 controller.device_type.joycon_left.Assign(1);
52 controller.device_type.joycon_right.Assign(1);
53 controller.pad_assignment = NPadAssignments::Dual;
54 break;
49 case NPadControllerType::JoyLeft: 55 case NPadControllerType::JoyLeft:
50 controller.joy_styles.joycon_left.Assign(1); 56 controller.joy_styles.joycon_left.Assign(1);
51 controller.device_type.joycon_left.Assign(1); 57 controller.device_type.joycon_left.Assign(1);
@@ -56,9 +62,6 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) {
56 controller.device_type.joycon_right.Assign(1); 62 controller.device_type.joycon_right.Assign(1);
57 controller.pad_assignment = NPadAssignments::Dual; 63 controller.pad_assignment = NPadAssignments::Dual;
58 break; 64 break;
59 case NPadControllerType::Tabletop:
60 UNIMPLEMENTED_MSG("Tabletop is not implemented");
61 break;
62 case NPadControllerType::Pokeball: 65 case NPadControllerType::Pokeball:
63 controller.joy_styles.pokeball.Assign(1); 66 controller.joy_styles.pokeball.Assign(1);
64 controller.device_type.pokeball.Assign(1); 67 controller.device_type.pokeball.Assign(1);
@@ -82,6 +85,11 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) {
82 controller.right_color.button_color = JOYCON_BUTTONS_NEON_RED; 85 controller.right_color.button_color = JOYCON_BUTTONS_NEON_RED;
83 86
84 controller.properties.is_vertical.Assign(1); // TODO(ogniK): Swap joycons orientations 87 controller.properties.is_vertical.Assign(1); // TODO(ogniK): Swap joycons orientations
88 controller.properties.use_plus.Assign(1);
89 controller.properties.use_minus.Assign(1);
90 controller.battery_level[0] = BATTERY_FULL;
91 controller.battery_level[1] = BATTERY_FULL;
92 controller.battery_level[2] = BATTERY_FULL;
85} 93}
86 94
87void Controller_NPad::OnInit() { 95void Controller_NPad::OnInit() {
@@ -106,7 +114,7 @@ void Controller_NPad::OnInit() {
106 supported_npad_id_types.resize(npad_id_list.size()); 114 supported_npad_id_types.resize(npad_id_list.size());
107 std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), 115 std::memcpy(supported_npad_id_types.data(), npad_id_list.data(),
108 npad_id_list.size() * sizeof(u32)); 116 npad_id_list.size() * sizeof(u32));
109 AddNewController(NPadControllerType::Handheld); 117 AddNewController(NPadControllerType::JoyDual);
110 } 118 }
111} 119}
112 120
@@ -218,9 +226,11 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) {
218 if (hold_type == NpadHoldType::Horizontal) { 226 if (hold_type == NpadHoldType::Horizontal) {
219 // TODO(ogniK): Remap buttons for different orientations 227 // TODO(ogniK): Remap buttons for different orientations
220 } 228 }
229 libnx_entry.connection_status.raw = 0;
221 230
222 switch (controller_type) { 231 switch (controller_type) {
223 case NPadControllerType::Handheld: 232 case NPadControllerType::Handheld:
233 handheld_entry.connection_status.raw = 0;
224 handheld_entry.connection_status.IsConnected.Assign(1); 234 handheld_entry.connection_status.IsConnected.Assign(1);
225 if (!Settings::values.use_docked_mode) { 235 if (!Settings::values.use_docked_mode) {
226 handheld_entry.connection_status.IsWired.Assign(1); 236 handheld_entry.connection_status.IsWired.Assign(1);
@@ -229,26 +239,39 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) {
229 handheld_entry.l_stick = lstick_entry; 239 handheld_entry.l_stick = lstick_entry;
230 handheld_entry.r_stick = rstick_entry; 240 handheld_entry.r_stick = rstick_entry;
231 break; 241 break;
242 case NPadControllerType::JoyDual:
243 dual_entry.connection_status.raw = 0;
244
245 dual_entry.connection_status.IsLeftJoyConnected.Assign(1);
246 dual_entry.connection_status.IsRightJoyConnected.Assign(1);
247 dual_entry.connection_status.IsConnected.Assign(1);
248
249 libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
250 libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
251 libnx_entry.connection_status.IsConnected.Assign(1);
252
253 dual_entry.pad_states.raw = pad_state.raw;
254 dual_entry.l_stick = lstick_entry;
255 dual_entry.r_stick = rstick_entry;
232 case NPadControllerType::JoyLeft: 256 case NPadControllerType::JoyLeft:
257 left_entry.connection_status.raw = 0;
258
233 left_entry.connection_status.IsConnected.Assign(1); 259 left_entry.connection_status.IsConnected.Assign(1);
234 left_entry.pad_states.raw = pad_state.raw; 260 left_entry.pad_states.raw = pad_state.raw;
235 left_entry.l_stick = lstick_entry; 261 left_entry.l_stick = lstick_entry;
236 left_entry.r_stick = rstick_entry; 262 left_entry.r_stick = rstick_entry;
237 break; 263 break;
238 case NPadControllerType::JoyRight: 264 case NPadControllerType::JoyRight:
265 right_entry.connection_status.raw = 0;
266
239 right_entry.connection_status.IsConnected.Assign(1); 267 right_entry.connection_status.IsConnected.Assign(1);
240 right_entry.pad_states.raw = pad_state.raw; 268 right_entry.pad_states.raw = pad_state.raw;
241 right_entry.l_stick = lstick_entry; 269 right_entry.l_stick = lstick_entry;
242 right_entry.r_stick = rstick_entry; 270 right_entry.r_stick = rstick_entry;
243 break; 271 break;
244 case NPadControllerType::Tabletop:
245 // TODO(ogniK): Figure out how to add proper tabletop support
246 dual_entry.pad_states.raw = pad_state.raw;
247 dual_entry.l_stick = lstick_entry;
248 dual_entry.r_stick = rstick_entry;
249 dual_entry.connection_status.IsConnected.Assign(1);
250 break;
251 case NPadControllerType::Pokeball: 272 case NPadControllerType::Pokeball:
273 pokeball_entry.connection_status.raw = 0;
274
252 pokeball_entry.connection_status.IsConnected.Assign(1); 275 pokeball_entry.connection_status.IsConnected.Assign(1);
253 pokeball_entry.connection_status.IsWired.Assign(1); 276 pokeball_entry.connection_status.IsWired.Assign(1);
254 277
@@ -257,18 +280,18 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) {
257 pokeball_entry.r_stick = rstick_entry; 280 pokeball_entry.r_stick = rstick_entry;
258 break; 281 break;
259 case NPadControllerType::ProController: 282 case NPadControllerType::ProController:
283 main_controller.connection_status.raw = 0;
284
285 main_controller.connection_status.IsConnected.Assign(1);
286 main_controller.connection_status.IsWired.Assign(1);
260 main_controller.pad_states.raw = pad_state.raw; 287 main_controller.pad_states.raw = pad_state.raw;
261 main_controller.l_stick = lstick_entry; 288 main_controller.l_stick = lstick_entry;
262 main_controller.r_stick = rstick_entry; 289 main_controller.r_stick = rstick_entry;
263 main_controller.connection_status.IsConnected.Assign(1);
264 main_controller.connection_status.IsWired.Assign(1);
265 break; 290 break;
266 } 291 }
267 292
268 // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate 293 // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate
269 // any controllers. 294 // any controllers.
270 libnx_entry.connection_status.IsConnected.Assign(1);
271 libnx_entry.connection_status.IsWired.Assign(1);
272 libnx_entry.pad_states.raw = pad_state.raw; 295 libnx_entry.pad_states.raw = pad_state.raw;
273 libnx_entry.l_stick = lstick_entry; 296 libnx_entry.l_stick = lstick_entry;
274 libnx_entry.r_stick = rstick_entry; 297 libnx_entry.r_stick = rstick_entry;
@@ -290,44 +313,6 @@ void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) {
290 supported_npad_id_types.clear(); 313 supported_npad_id_types.clear();
291 supported_npad_id_types.resize(length / sizeof(u32)); 314 supported_npad_id_types.resize(length / sizeof(u32));
292 std::memcpy(supported_npad_id_types.data(), data, length); 315 std::memcpy(supported_npad_id_types.data(), data, length);
293 CheckForHandheldVariant();
294}
295#pragma optimize("", off)
296void Controller_NPad::CheckForHandheldVariant() {
297 // As some games expect us to use the variant of handheld mode and some games don't. It's
298 // consistent that games set the npad ids in order of priority. We can just swap the controller
299 // ids on the fly then if we're in handheld mode
300 if (std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), 32) !=
301 supported_npad_id_types.end()) {
302 const auto& first_controller = connected_controllers.front();
303 if (first_controller.is_connected &&
304 first_controller.type == NPadControllerType::Handheld) {
305 DisconnectNPad(0);
306 AddNewController(NPadControllerType::Handheld, true);
307 }
308 } else {
309 if (connected_controllers[8].is_connected) {
310 DisconnectNPad(8);
311 AddNewController(NPadControllerType::Handheld);
312 }
313 }
314 /*
315 if (supported_npad_id_types.size() > 0) {
316 const auto& first_controller = supported_npad_id_types.front();
317 if (first_controller == 32 && !connected_controllers[8].is_connected) {
318 const auto& first_controller = connected_controllers.front();
319 if (first_controller.is_connected &&
320 first_controller.type == NPadControllerType::Handheld) {
321 DisconnectNPad(0);
322 AddNewController(NPadControllerType::Handheld, true);
323 }
324 } else if (first_controller != 32 && connected_controllers[8].is_connected) {
325 if (!connected_controllers[0].is_connected) {
326 DisconnectNPad(8);
327 AddNewController(NPadControllerType::Handheld);
328 }
329 }
330 }*/
331} 316}
332 317
333const void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { 318const void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
@@ -358,11 +343,14 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids,
358 } 343 }
359 for (std::size_t i = 0; i < controller_ids.size(); i++) { 344 for (std::size_t i = 0; i < controller_ids.size(); i++) {
360 std::size_t controller_pos = i; 345 std::size_t controller_pos = i;
361 if (controller_pos == 32) 346 // Handheld controller conversion
347 if (controller_pos == 32) {
362 controller_pos = 8; 348 controller_pos = 8;
363 if (controller_pos == 16) 349 }
350 // Unknown controller conversion
351 if (controller_pos == 16) {
364 controller_pos = 9; 352 controller_pos = 9;
365 353 }
366 if (connected_controllers[controller_pos].is_connected) { 354 if (connected_controllers[controller_pos].is_connected) {
367 // TODO(ogniK): Vibrate the physical controller 355 // TODO(ogniK): Vibrate the physical controller
368 } 356 }
@@ -378,8 +366,8 @@ Kernel::SharedPtr<Kernel::Event> Controller_NPad::GetStyleSetChangedEvent() cons
378Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { 366Controller_NPad::Vibration Controller_NPad::GetLastVibration() const {
379 return last_processed_vibration; 367 return last_processed_vibration;
380} 368}
381void Controller_NPad::AddNewController(NPadControllerType controller, bool is_handheld_variant) { 369void Controller_NPad::AddNewController(NPadControllerType controller) {
382 if (is_handheld_variant) { 370 if (controller == NPadControllerType::Handheld) {
383 connected_controllers[8] = {controller, true}; 371 connected_controllers[8] = {controller, true};
384 InitNewlyAddedControler(8); 372 InitNewlyAddedControler(8);
385 return; 373 return;
@@ -438,13 +426,4 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
438void Controller_NPad::SetVibrationEnabled(bool can_vibrate) { 426void Controller_NPad::SetVibrationEnabled(bool can_vibrate) {
439 can_controllers_vibrate = can_vibrate; 427 can_controllers_vibrate = can_vibrate;
440} 428}
441
442void Controller_NPad::SetHandheldActiviationMode(u32 mode) {
443 const auto& first_controller = connected_controllers.front();
444 if (!first_controller.is_connected || connected_controllers[8].is_connected) {
445 return;
446 }
447 DisconnectNPad(0);
448 AddNewController(NPadControllerType::Handheld, true);
449}
450} // namespace Service::HID 429} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index bc3d15ce6..9d07d258d 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -65,9 +65,9 @@ public:
65 None, 65 None,
66 ProController, 66 ProController,
67 Handheld, 67 Handheld,
68 JoyDual,
68 JoyLeft, 69 JoyLeft,
69 JoyRight, 70 JoyRight,
70 Tabletop,
71 Pokeball, 71 Pokeball,
72 }; 72 };
73 73
@@ -105,13 +105,12 @@ public:
105 Kernel::SharedPtr<Kernel::Event> GetStyleSetChangedEvent() const; 105 Kernel::SharedPtr<Kernel::Event> GetStyleSetChangedEvent() const;
106 Vibration GetLastVibration() const; 106 Vibration GetLastVibration() const;
107 107
108 void AddNewController(NPadControllerType controller, bool is_handheld_variant = false); 108 void AddNewController(NPadControllerType controller);
109 109
110 void ConnectNPad(u32 npad_id); 110 void ConnectNPad(u32 npad_id);
111 void DisconnectNPad(u32 npad_id); 111 void DisconnectNPad(u32 npad_id);
112 LedPattern GetLedPattern(u32 npad_id); 112 LedPattern GetLedPattern(u32 npad_id);
113 void SetVibrationEnabled(bool can_vibrate); 113 void SetVibrationEnabled(bool can_vibrate);
114 void SetHandheldActiviationMode(u32 mode);
115 114
116private: 115private:
117 struct CommonHeader { 116 struct CommonHeader {
@@ -181,6 +180,10 @@ private:
181 u32_le raw{}; 180 u32_le raw{};
182 BitField<0, 1, u32_le> IsConnected; 181 BitField<0, 1, u32_le> IsConnected;
183 BitField<1, 1, u32_le> IsWired; 182 BitField<1, 1, u32_le> IsWired;
183 BitField<2, 1, u32_le> IsLeftJoyConnected;
184 BitField<3, 1, u32_le> IsLeftJoyWired;
185 BitField<4, 1, u32_le> IsRightJoyConnected;
186 BitField<5, 1, u32_le> IsRightJoyWired;
184 }; 187 };
185 }; 188 };
186 static_assert(sizeof(ConnectionState) == 4, "ConnectionState is an invalid size"); 189 static_assert(sizeof(ConnectionState) == 4, "ConnectionState is an invalid size");
@@ -212,6 +215,8 @@ private:
212 s64_le raw{}; 215 s64_le raw{};
213 BitField<11, 1, s64_le> is_vertical; 216 BitField<11, 1, s64_le> is_vertical;
214 BitField<12, 1, s64_le> is_horizontal; 217 BitField<12, 1, s64_le> is_horizontal;
218 BitField<13, 1, s64_le> use_plus;
219 BitField<14, 1, s64_le> use_minus;
215 }; 220 };
216 }; 221 };
217 222
@@ -252,8 +257,9 @@ private:
252 6); // TODO(ogniK): SixAxis states, require more information before implementation 257 6); // TODO(ogniK): SixAxis states, require more information before implementation
253 NPadDevice device_type; 258 NPadDevice device_type;
254 NPadProperties properties; 259 NPadProperties properties;
255 INSERT_PADDING_WORDS(4); 260 INSERT_PADDING_WORDS(1);
256 INSERT_PADDING_BYTES(0x60); 261 std::array<u32, 3> battery_level;
262 INSERT_PADDING_BYTES(0x5c);
257 INSERT_PADDING_BYTES(0xdf8); 263 INSERT_PADDING_BYTES(0xdf8);
258 }; 264 };
259 static_assert(sizeof(NPadEntry) == 0x5000, "NPadEntry is an invalid size"); 265 static_assert(sizeof(NPadEntry) == 0x5000, "NPadEntry is an invalid size");
@@ -276,7 +282,6 @@ private:
276 static constexpr std::array<u32, 10> npad_id_list{0, 1, 2, 3, 4, 5, 6, 7, 32, 16}; 282 static constexpr std::array<u32, 10> npad_id_list{0, 1, 2, 3, 4, 5, 6, 7, 32, 16};
277 std::array<ControllerHolder, 10> connected_controllers{}; 283 std::array<ControllerHolder, 10> connected_controllers{};
278 bool can_controllers_vibrate{true}; 284 bool can_controllers_vibrate{true};
279 void CheckForHandheldVariant();
280 285
281 void InitNewlyAddedControler(std::size_t controller_idx); 286 void InitNewlyAddedControler(std::size_t controller_idx);
282}; 287};
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index db1537b40..8aca0f197 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -284,7 +284,7 @@ public:
284 284
285private: 285private:
286 std::shared_ptr<IAppletResource> applet_resource; 286 std::shared_ptr<IAppletResource> applet_resource;
287#pragma optimize("", off) 287
288 void CreateAppletResource(Kernel::HLERequestContext& ctx) { 288 void CreateAppletResource(Kernel::HLERequestContext& ctx) {
289 if (applet_resource == nullptr) { 289 if (applet_resource == nullptr) {
290 applet_resource = std::make_shared<IAppletResource>(); 290 applet_resource = std::make_shared<IAppletResource>();
@@ -545,8 +545,6 @@ private:
545 IPC::ResponseBuilder rb{ctx, 2}; 545 IPC::ResponseBuilder rb{ctx, 2};
546 rb.Push(RESULT_SUCCESS); 546 rb.Push(RESULT_SUCCESS);
547 LOG_WARNING(Service_HID, "(STUBBED) called"); 547 LOG_WARNING(Service_HID, "(STUBBED) called");
548 applet_resource->GetController<Controller_NPad>(HidController::NPad)
549 .SetHandheldActiviationMode(mode);
550 } 548 }
551 549
552 void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { 550 void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {