diff options
| -rw-r--r-- | src/core/hle/service/hid/controllers/controller_base.h | 4 | ||||
| -rw-r--r-- | src/core/hle/service/hid/controllers/npad.cpp | 202 | ||||
| -rw-r--r-- | src/core/hle/service/hid/controllers/npad.h | 4 | ||||
| -rw-r--r-- | src/core/hle/service/hid/hid.cpp | 21 | ||||
| -rw-r--r-- | src/core/hle/service/hid/hid.h | 2 | 
5 files changed, 157 insertions, 76 deletions
| diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h index 8bc69c372..f47a9e61c 100644 --- a/src/core/hle/service/hid/controllers/controller_base.h +++ b/src/core/hle/service/hid/controllers/controller_base.h @@ -31,6 +31,10 @@ public:      virtual void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,                            std::size_t size) = 0; +    // When the controller is requesting a motion update for the shared memory +    virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, +                                std::size_t size) {} +      // Called when input devices should be loaded      virtual void OnLoadInputDevices() = 0; diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 620386cd1..e34ee519e 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -365,6 +365,135 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*          }          const u32 npad_index = static_cast<u32>(i); +        RequestPadStateUpdate(npad_index); +        auto& pad_state = npad_pad_states[npad_index]; + +        auto& main_controller = +            npad.main_controller_states.npad[npad.main_controller_states.common.last_entry_index]; +        auto& handheld_entry = +            npad.handheld_states.npad[npad.handheld_states.common.last_entry_index]; +        auto& dual_entry = npad.dual_states.npad[npad.dual_states.common.last_entry_index]; +        auto& left_entry = npad.left_joy_states.npad[npad.left_joy_states.common.last_entry_index]; +        auto& right_entry = +            npad.right_joy_states.npad[npad.right_joy_states.common.last_entry_index]; +        auto& pokeball_entry = +            npad.pokeball_states.npad[npad.pokeball_states.common.last_entry_index]; +        auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index]; + +        libnx_entry.connection_status.raw = 0; +        libnx_entry.connection_status.IsConnected.Assign(1); +        auto& full_sixaxis_entry = +            npad.sixaxis_full.sixaxis[npad.sixaxis_full.common.last_entry_index]; +        auto& handheld_sixaxis_entry = +            npad.sixaxis_handheld.sixaxis[npad.sixaxis_handheld.common.last_entry_index]; +        auto& dual_left_sixaxis_entry = +            npad.sixaxis_dual_left.sixaxis[npad.sixaxis_dual_left.common.last_entry_index]; +        auto& dual_right_sixaxis_entry = +            npad.sixaxis_dual_right.sixaxis[npad.sixaxis_dual_right.common.last_entry_index]; +        auto& left_sixaxis_entry = +            npad.sixaxis_left.sixaxis[npad.sixaxis_left.common.last_entry_index]; +        auto& right_sixaxis_entry = +            npad.sixaxis_right.sixaxis[npad.sixaxis_right.common.last_entry_index]; + +        switch (controller_type) { +        case NPadControllerType::None: +            UNREACHABLE(); +            break; +        case NPadControllerType::ProController: +            main_controller.connection_status.raw = 0; +            main_controller.connection_status.IsConnected.Assign(1); +            main_controller.connection_status.IsWired.Assign(1); +            main_controller.pad.pad_states.raw = pad_state.pad_states.raw; +            main_controller.pad.l_stick = pad_state.l_stick; +            main_controller.pad.r_stick = pad_state.r_stick; + +            libnx_entry.connection_status.IsWired.Assign(1); +            break; +        case NPadControllerType::Handheld: +            handheld_entry.connection_status.raw = 0; +            handheld_entry.connection_status.IsConnected.Assign(1); +            handheld_entry.connection_status.IsWired.Assign(1); +            handheld_entry.connection_status.IsLeftJoyConnected.Assign(1); +            handheld_entry.connection_status.IsRightJoyConnected.Assign(1); +            handheld_entry.connection_status.IsLeftJoyWired.Assign(1); +            handheld_entry.connection_status.IsRightJoyWired.Assign(1); +            handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw; +            handheld_entry.pad.l_stick = pad_state.l_stick; +            handheld_entry.pad.r_stick = pad_state.r_stick; + +            libnx_entry.connection_status.IsWired.Assign(1); +            libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); +            libnx_entry.connection_status.IsRightJoyConnected.Assign(1); +            libnx_entry.connection_status.IsLeftJoyWired.Assign(1); +            libnx_entry.connection_status.IsRightJoyWired.Assign(1); +            break; +        case NPadControllerType::JoyDual: +            dual_entry.connection_status.raw = 0; +            dual_entry.connection_status.IsConnected.Assign(1); +            dual_entry.connection_status.IsLeftJoyConnected.Assign(1); +            dual_entry.connection_status.IsRightJoyConnected.Assign(1); +            dual_entry.pad.pad_states.raw = pad_state.pad_states.raw; +            dual_entry.pad.l_stick = pad_state.l_stick; +            dual_entry.pad.r_stick = pad_state.r_stick; + +            libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); +            libnx_entry.connection_status.IsRightJoyConnected.Assign(1); +            break; +        case NPadControllerType::JoyLeft: +            left_entry.connection_status.raw = 0; +            left_entry.connection_status.IsConnected.Assign(1); +            left_entry.connection_status.IsLeftJoyConnected.Assign(1); +            left_entry.pad.pad_states.raw = pad_state.pad_states.raw; +            left_entry.pad.l_stick = pad_state.l_stick; +            left_entry.pad.r_stick = pad_state.r_stick; + +            libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); +            break; +        case NPadControllerType::JoyRight: +            right_entry.connection_status.raw = 0; +            right_entry.connection_status.IsConnected.Assign(1); +            right_entry.connection_status.IsRightJoyConnected.Assign(1); +            right_entry.pad.pad_states.raw = pad_state.pad_states.raw; +            right_entry.pad.l_stick = pad_state.l_stick; +            right_entry.pad.r_stick = pad_state.r_stick; + +            libnx_entry.connection_status.IsRightJoyConnected.Assign(1); +            break; +        case NPadControllerType::Pokeball: +            pokeball_entry.connection_status.raw = 0; +            pokeball_entry.connection_status.IsConnected.Assign(1); +            pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw; +            pokeball_entry.pad.l_stick = pad_state.l_stick; +            pokeball_entry.pad.r_stick = pad_state.r_stick; +            break; +        } + +        // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate +        // any controllers. +        libnx_entry.pad.pad_states.raw = pad_state.pad_states.raw; +        libnx_entry.pad.l_stick = pad_state.l_stick; +        libnx_entry.pad.r_stick = pad_state.r_stick; + +        press_state |= static_cast<u32>(pad_state.pad_states.raw); +    } +    std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(), +                shared_memory_entries.size() * sizeof(NPadEntry)); +} + +void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, +                                     std::size_t data_len) { +    if (!IsControllerActivated()) { +        return; +    } +    for (std::size_t i = 0; i < shared_memory_entries.size(); i++) { +        auto& npad = shared_memory_entries[i]; + +        const auto& controller_type = connected_controllers[i].type; + +        if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) { +            continue; +        } +          const std::array<SixAxisGeneric*, 6> controller_sixaxes{              &npad.sixaxis_full,       &npad.sixaxis_handheld, &npad.sixaxis_dual_left,              &npad.sixaxis_dual_right, &npad.sixaxis_left,     &npad.sixaxis_right, @@ -403,9 +532,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*              }          } -        RequestPadStateUpdate(npad_index); -        auto& pad_state = npad_pad_states[npad_index]; -          auto& main_controller =              npad.main_controller_states.npad[npad.main_controller_states.common.last_entry_index];          auto& handheld_entry = @@ -418,8 +544,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*              npad.pokeball_states.npad[npad.pokeball_states.common.last_entry_index];          auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index]; -        libnx_entry.connection_status.raw = 0; -        libnx_entry.connection_status.IsConnected.Assign(1);          auto& full_sixaxis_entry =              npad.sixaxis_full.sixaxis[npad.sixaxis_full.common.last_entry_index];          auto& handheld_sixaxis_entry = @@ -438,15 +562,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*              UNREACHABLE();              break;          case NPadControllerType::ProController: -            main_controller.connection_status.raw = 0; -            main_controller.connection_status.IsConnected.Assign(1); -            main_controller.connection_status.IsWired.Assign(1); -            main_controller.pad.pad_states.raw = pad_state.pad_states.raw; -            main_controller.pad.l_stick = pad_state.l_stick; -            main_controller.pad.r_stick = pad_state.r_stick; - -            libnx_entry.connection_status.IsWired.Assign(1); -              if (sixaxis_sensors_enabled && motions[i][0]) {                  full_sixaxis_entry.accel = motion_devices[0].accel;                  full_sixaxis_entry.gyro = motion_devices[0].gyro; @@ -455,23 +570,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*              }              break;          case NPadControllerType::Handheld: -            handheld_entry.connection_status.raw = 0; -            handheld_entry.connection_status.IsConnected.Assign(1); -            handheld_entry.connection_status.IsWired.Assign(1); -            handheld_entry.connection_status.IsLeftJoyConnected.Assign(1); -            handheld_entry.connection_status.IsRightJoyConnected.Assign(1); -            handheld_entry.connection_status.IsLeftJoyWired.Assign(1); -            handheld_entry.connection_status.IsRightJoyWired.Assign(1); -            handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw; -            handheld_entry.pad.l_stick = pad_state.l_stick; -            handheld_entry.pad.r_stick = pad_state.r_stick; - -            libnx_entry.connection_status.IsWired.Assign(1); -            libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); -            libnx_entry.connection_status.IsRightJoyConnected.Assign(1); -            libnx_entry.connection_status.IsLeftJoyWired.Assign(1); -            libnx_entry.connection_status.IsRightJoyWired.Assign(1); -              if (sixaxis_sensors_enabled && motions[i][0]) {                  handheld_sixaxis_entry.accel = motion_devices[0].accel;                  handheld_sixaxis_entry.gyro = motion_devices[0].gyro; @@ -480,17 +578,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*              }              break;          case NPadControllerType::JoyDual: -            dual_entry.connection_status.raw = 0; -            dual_entry.connection_status.IsConnected.Assign(1); -            dual_entry.connection_status.IsLeftJoyConnected.Assign(1); -            dual_entry.connection_status.IsRightJoyConnected.Assign(1); -            dual_entry.pad.pad_states.raw = pad_state.pad_states.raw; -            dual_entry.pad.l_stick = pad_state.l_stick; -            dual_entry.pad.r_stick = pad_state.r_stick; - -            libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); -            libnx_entry.connection_status.IsRightJoyConnected.Assign(1); -              if (sixaxis_sensors_enabled && motions[i][0]) {                  // Set motion for the left joycon                  dual_left_sixaxis_entry.accel = motion_devices[0].accel; @@ -507,15 +594,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*              }              break;          case NPadControllerType::JoyLeft: -            left_entry.connection_status.raw = 0; -            left_entry.connection_status.IsConnected.Assign(1); -            left_entry.connection_status.IsLeftJoyConnected.Assign(1); -            left_entry.pad.pad_states.raw = pad_state.pad_states.raw; -            left_entry.pad.l_stick = pad_state.l_stick; -            left_entry.pad.r_stick = pad_state.r_stick; - -            libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); -              if (sixaxis_sensors_enabled && motions[i][0]) {                  left_sixaxis_entry.accel = motion_devices[0].accel;                  left_sixaxis_entry.gyro = motion_devices[0].gyro; @@ -524,15 +602,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*              }              break;          case NPadControllerType::JoyRight: -            right_entry.connection_status.raw = 0; -            right_entry.connection_status.IsConnected.Assign(1); -            right_entry.connection_status.IsRightJoyConnected.Assign(1); -            right_entry.pad.pad_states.raw = pad_state.pad_states.raw; -            right_entry.pad.l_stick = pad_state.l_stick; -            right_entry.pad.r_stick = pad_state.r_stick; - -            libnx_entry.connection_status.IsRightJoyConnected.Assign(1); -              if (sixaxis_sensors_enabled && motions[i][1]) {                  right_sixaxis_entry.accel = motion_devices[1].accel;                  right_sixaxis_entry.gyro = motion_devices[1].gyro; @@ -541,21 +610,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*              }              break;          case NPadControllerType::Pokeball: -            pokeball_entry.connection_status.raw = 0; -            pokeball_entry.connection_status.IsConnected.Assign(1); -            pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw; -            pokeball_entry.pad.l_stick = pad_state.l_stick; -            pokeball_entry.pad.r_stick = pad_state.r_stick;              break;          } - -        // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate -        // any controllers. -        libnx_entry.pad.pad_states.raw = pad_state.pad_states.raw; -        libnx_entry.pad.l_stick = pad_state.l_stick; -        libnx_entry.pad.r_stick = pad_state.r_stick; - -        press_state |= static_cast<u32>(pad_state.pad_states.raw);      }      std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(),                  shared_memory_entries.size() * sizeof(NPadEntry)); diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 654d97c3f..0fa7455ba 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -32,6 +32,10 @@ public:      // When the controller is requesting an update for the shared memory      void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; +    // When the controller is requesting a motion update for the shared memory +    void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, +                        std::size_t size) override; +      // Called when input devices should be loaded      void OnLoadInputDevices() override; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 395e83b3f..9a7e5e265 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -40,7 +40,8 @@ namespace Service::HID {  // Updating period for each HID device.  // HID is polled every 15ms, this value was derived from  // https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering#joy-con-status-data-packet -constexpr auto pad_update_ns = std::chrono::nanoseconds{1000 * 1000}; // (1ms, 1000Hz) +constexpr auto pad_update_ns = std::chrono::nanoseconds{1000 * 1000};         // (1ms, 1000Hz) +constexpr auto motion_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000}; // (15ms, 66.666Hz)  constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000;  IAppletResource::IAppletResource(Core::System& system) @@ -79,10 +80,14 @@ IAppletResource::IAppletResource(Core::System& system)          [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {              UpdateControllers(user_data, ns_late);          }); - -    // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?) +    motion_update_event = Core::Timing::CreateEvent( +        "HID::MotionPadCallback", +        [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { +            UpdateMotion(user_data, ns_late); +        });      system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event); +    system.CoreTiming().ScheduleEvent(motion_update_ns, motion_update_event);      ReloadInputDevices();  } @@ -122,6 +127,16 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data,      core_timing.ScheduleEvent(pad_update_ns - ns_late, pad_update_event);  } +void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { +    auto& core_timing = system.CoreTiming(); + +    for (const auto& controller : controllers) { +        controller->OnMotionUpdate(core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE); +    } + +    core_timing.ScheduleEvent(motion_update_ns - ns_late, motion_update_event); +} +  class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> {  public:      IActiveVibrationDeviceList() : ServiceFramework("IActiveVibrationDeviceList") { diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index e04aaf1e9..3cfd72a51 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -65,10 +65,12 @@ private:      void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx);      void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); +    void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);      std::shared_ptr<Kernel::SharedMemory> shared_mem;      std::shared_ptr<Core::Timing::EventType> pad_update_event; +    std::shared_ptr<Core::Timing::EventType> motion_update_event;      Core::System& system;      std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)> | 
