diff options
| author | 2024-01-20 13:34:54 -0500 | |
|---|---|---|
| committer | 2024-01-20 13:34:54 -0500 | |
| commit | 5838779162897606a3525eb619379a56b2eec027 (patch) | |
| tree | 3c3530e2f955545968fcc605122aa7565f4b5f1a | |
| parent | Merge pull request #12701 from liamwhite/flinger-layer-issues (diff) | |
| parent | service: hid: Fully implement abstract vibration (diff) | |
| download | yuzu-5838779162897606a3525eb619379a56b2eec027.tar.gz yuzu-5838779162897606a3525eb619379a56b2eec027.tar.xz yuzu-5838779162897606a3525eb619379a56b2eec027.zip | |
Merge pull request #12660 from german77/better-vibration
service: hid: Fully implement abstract vibration
31 files changed, 905 insertions, 448 deletions
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 03ebdc137..595a3372e 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -26,6 +26,7 @@ void LoopProcess(Core::System& system) { | |||
| 26 | resource_manager->Initialize(); | 26 | resource_manager->Initialize(); |
| 27 | resource_manager->RegisterAppletResourceUserId(system.ApplicationProcess()->GetProcessId(), | 27 | resource_manager->RegisterAppletResourceUserId(system.ApplicationProcess()->GetProcessId(), |
| 28 | true); | 28 | true); |
| 29 | resource_manager->SetAruidValidForVibration(system.ApplicationProcess()->GetProcessId(), true); | ||
| 29 | 30 | ||
| 30 | server_manager->RegisterNamedService( | 31 | server_manager->RegisterNamedService( |
| 31 | "hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings)); | 32 | "hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings)); |
diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp index 1951da33b..30afed812 100644 --- a/src/core/hle/service/hid/hid_server.cpp +++ b/src/core/hle/service/hid/hid_server.cpp | |||
| @@ -22,12 +22,16 @@ | |||
| 22 | #include "hid_core/resources/mouse/mouse.h" | 22 | #include "hid_core/resources/mouse/mouse.h" |
| 23 | #include "hid_core/resources/npad/npad.h" | 23 | #include "hid_core/resources/npad/npad.h" |
| 24 | #include "hid_core/resources/npad/npad_types.h" | 24 | #include "hid_core/resources/npad/npad_types.h" |
| 25 | #include "hid_core/resources/npad/npad_vibration.h" | ||
| 25 | #include "hid_core/resources/palma/palma.h" | 26 | #include "hid_core/resources/palma/palma.h" |
| 26 | #include "hid_core/resources/six_axis/console_six_axis.h" | 27 | #include "hid_core/resources/six_axis/console_six_axis.h" |
| 27 | #include "hid_core/resources/six_axis/seven_six_axis.h" | 28 | #include "hid_core/resources/six_axis/seven_six_axis.h" |
| 28 | #include "hid_core/resources/six_axis/six_axis.h" | 29 | #include "hid_core/resources/six_axis/six_axis.h" |
| 29 | #include "hid_core/resources/touch_screen/gesture.h" | 30 | #include "hid_core/resources/touch_screen/gesture.h" |
| 30 | #include "hid_core/resources/touch_screen/touch_screen.h" | 31 | #include "hid_core/resources/touch_screen/touch_screen.h" |
| 32 | #include "hid_core/resources/vibration/gc_vibration_device.h" | ||
| 33 | #include "hid_core/resources/vibration/n64_vibration_device.h" | ||
| 34 | #include "hid_core/resources/vibration/vibration_device.h" | ||
| 31 | 35 | ||
| 32 | namespace Service::HID { | 36 | namespace Service::HID { |
| 33 | 37 | ||
| @@ -38,7 +42,7 @@ public: | |||
| 38 | : ServiceFramework{system_, "IActiveVibrationDeviceList"}, resource_manager(resource) { | 42 | : ServiceFramework{system_, "IActiveVibrationDeviceList"}, resource_manager(resource) { |
| 39 | // clang-format off | 43 | // clang-format off |
| 40 | static const FunctionInfo functions[] = { | 44 | static const FunctionInfo functions[] = { |
| 41 | {0, &IActiveVibrationDeviceList::InitializeVibrationDevice, "InitializeVibrationDevice"}, | 45 | {0, &IActiveVibrationDeviceList::ActivateVibrationDevice, "ActivateVibrationDevice"}, |
| 42 | }; | 46 | }; |
| 43 | // clang-format on | 47 | // clang-format on |
| 44 | 48 | ||
| @@ -46,22 +50,49 @@ public: | |||
| 46 | } | 50 | } |
| 47 | 51 | ||
| 48 | private: | 52 | private: |
| 49 | void InitializeVibrationDevice(HLERequestContext& ctx) { | 53 | void ActivateVibrationDevice(HLERequestContext& ctx) { |
| 50 | IPC::RequestParser rp{ctx}; | 54 | IPC::RequestParser rp{ctx}; |
| 51 | const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()}; | 55 | const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()}; |
| 52 | 56 | ||
| 53 | if (resource_manager != nullptr && resource_manager->GetNpad()) { | ||
| 54 | resource_manager->GetNpad()->InitializeVibrationDevice(vibration_device_handle); | ||
| 55 | } | ||
| 56 | |||
| 57 | LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}", | 57 | LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}", |
| 58 | vibration_device_handle.npad_type, vibration_device_handle.npad_id, | 58 | vibration_device_handle.npad_type, vibration_device_handle.npad_id, |
| 59 | vibration_device_handle.device_index); | 59 | vibration_device_handle.device_index); |
| 60 | 60 | ||
| 61 | const auto result = ActivateVibrationDeviceImpl(vibration_device_handle); | ||
| 62 | |||
| 61 | IPC::ResponseBuilder rb{ctx, 2}; | 63 | IPC::ResponseBuilder rb{ctx, 2}; |
| 62 | rb.Push(ResultSuccess); | 64 | rb.Push(result); |
| 63 | } | 65 | } |
| 64 | 66 | ||
| 67 | Result ActivateVibrationDeviceImpl(const Core::HID::VibrationDeviceHandle& handle) { | ||
| 68 | std::scoped_lock lock{mutex}; | ||
| 69 | |||
| 70 | const Result is_valid = IsVibrationHandleValid(handle); | ||
| 71 | if (is_valid.IsError()) { | ||
| 72 | return is_valid; | ||
| 73 | } | ||
| 74 | |||
| 75 | for (std::size_t i = 0; i < list_size; i++) { | ||
| 76 | if (handle.device_index == vibration_device_list[i].device_index && | ||
| 77 | handle.npad_id == vibration_device_list[i].npad_id && | ||
| 78 | handle.npad_type == vibration_device_list[i].npad_type) { | ||
| 79 | return ResultSuccess; | ||
| 80 | } | ||
| 81 | } | ||
| 82 | if (list_size == vibration_device_list.size()) { | ||
| 83 | return ResultVibrationDeviceIndexOutOfRange; | ||
| 84 | } | ||
| 85 | const Result result = resource_manager->GetVibrationDevice(handle)->Activate(); | ||
| 86 | if (result.IsError()) { | ||
| 87 | return result; | ||
| 88 | } | ||
| 89 | vibration_device_list[list_size++] = handle; | ||
| 90 | return ResultSuccess; | ||
| 91 | } | ||
| 92 | |||
| 93 | mutable std::mutex mutex; | ||
| 94 | std::size_t list_size{}; | ||
| 95 | std::array<Core::HID::VibrationDeviceHandle, 0x100> vibration_device_list{}; | ||
| 65 | std::shared_ptr<ResourceManager> resource_manager; | 96 | std::shared_ptr<ResourceManager> resource_manager; |
| 66 | }; | 97 | }; |
| 67 | 98 | ||
| @@ -153,7 +184,7 @@ IHidServer::IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> r | |||
| 153 | {209, &IHidServer::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, | 184 | {209, &IHidServer::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, |
| 154 | {210, &IHidServer::EndPermitVibrationSession, "EndPermitVibrationSession"}, | 185 | {210, &IHidServer::EndPermitVibrationSession, "EndPermitVibrationSession"}, |
| 155 | {211, &IHidServer::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"}, | 186 | {211, &IHidServer::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"}, |
| 156 | {212, nullptr, "SendVibrationValueInBool"}, | 187 | {212, &IHidServer::SendVibrationValueInBool, "SendVibrationValueInBool"}, |
| 157 | {300, &IHidServer::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"}, | 188 | {300, &IHidServer::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"}, |
| 158 | {301, &IHidServer::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"}, | 189 | {301, &IHidServer::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"}, |
| 159 | {302, &IHidServer::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"}, | 190 | {302, &IHidServer::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"}, |
| @@ -1492,59 +1523,13 @@ void IHidServer::ClearNpadCaptureButtonAssignment(HLERequestContext& ctx) { | |||
| 1492 | void IHidServer::GetVibrationDeviceInfo(HLERequestContext& ctx) { | 1523 | void IHidServer::GetVibrationDeviceInfo(HLERequestContext& ctx) { |
| 1493 | IPC::RequestParser rp{ctx}; | 1524 | IPC::RequestParser rp{ctx}; |
| 1494 | const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()}; | 1525 | const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()}; |
| 1495 | const auto controller = GetResourceManager()->GetNpad(); | ||
| 1496 | |||
| 1497 | Core::HID::VibrationDeviceInfo vibration_device_info; | ||
| 1498 | bool check_device_index = false; | ||
| 1499 | |||
| 1500 | switch (vibration_device_handle.npad_type) { | ||
| 1501 | case Core::HID::NpadStyleIndex::Fullkey: | ||
| 1502 | case Core::HID::NpadStyleIndex::Handheld: | ||
| 1503 | case Core::HID::NpadStyleIndex::JoyconDual: | ||
| 1504 | case Core::HID::NpadStyleIndex::JoyconLeft: | ||
| 1505 | case Core::HID::NpadStyleIndex::JoyconRight: | ||
| 1506 | vibration_device_info.type = Core::HID::VibrationDeviceType::LinearResonantActuator; | ||
| 1507 | check_device_index = true; | ||
| 1508 | break; | ||
| 1509 | case Core::HID::NpadStyleIndex::GameCube: | ||
| 1510 | vibration_device_info.type = Core::HID::VibrationDeviceType::GcErm; | ||
| 1511 | break; | ||
| 1512 | case Core::HID::NpadStyleIndex::N64: | ||
| 1513 | vibration_device_info.type = Core::HID::VibrationDeviceType::N64; | ||
| 1514 | break; | ||
| 1515 | default: | ||
| 1516 | vibration_device_info.type = Core::HID::VibrationDeviceType::Unknown; | ||
| 1517 | break; | ||
| 1518 | } | ||
| 1519 | |||
| 1520 | vibration_device_info.position = Core::HID::VibrationDevicePosition::None; | ||
| 1521 | if (check_device_index) { | ||
| 1522 | switch (vibration_device_handle.device_index) { | ||
| 1523 | case Core::HID::DeviceIndex::Left: | ||
| 1524 | vibration_device_info.position = Core::HID::VibrationDevicePosition::Left; | ||
| 1525 | break; | ||
| 1526 | case Core::HID::DeviceIndex::Right: | ||
| 1527 | vibration_device_info.position = Core::HID::VibrationDevicePosition::Right; | ||
| 1528 | break; | ||
| 1529 | case Core::HID::DeviceIndex::None: | ||
| 1530 | default: | ||
| 1531 | ASSERT_MSG(false, "DeviceIndex should never be None!"); | ||
| 1532 | break; | ||
| 1533 | } | ||
| 1534 | } | ||
| 1535 | 1526 | ||
| 1536 | LOG_DEBUG(Service_HID, "called, vibration_device_type={}, vibration_device_position={}", | 1527 | Core::HID::VibrationDeviceInfo vibration_device_info{}; |
| 1537 | vibration_device_info.type, vibration_device_info.position); | 1528 | const auto result = GetResourceManager()->GetVibrationDeviceInfo(vibration_device_info, |
| 1538 | 1529 | vibration_device_handle); | |
| 1539 | const auto result = IsVibrationHandleValid(vibration_device_handle); | ||
| 1540 | if (result.IsError()) { | ||
| 1541 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1542 | rb.Push(result); | ||
| 1543 | return; | ||
| 1544 | } | ||
| 1545 | 1530 | ||
| 1546 | IPC::ResponseBuilder rb{ctx, 4}; | 1531 | IPC::ResponseBuilder rb{ctx, 4}; |
| 1547 | rb.Push(ResultSuccess); | 1532 | rb.Push(result); |
| 1548 | rb.PushRaw(vibration_device_info); | 1533 | rb.PushRaw(vibration_device_info); |
| 1549 | } | 1534 | } |
| 1550 | 1535 | ||
| @@ -1560,16 +1545,16 @@ void IHidServer::SendVibrationValue(HLERequestContext& ctx) { | |||
| 1560 | 1545 | ||
| 1561 | const auto parameters{rp.PopRaw<Parameters>()}; | 1546 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 1562 | 1547 | ||
| 1563 | GetResourceManager()->GetNpad()->VibrateController(parameters.applet_resource_user_id, | ||
| 1564 | parameters.vibration_device_handle, | ||
| 1565 | parameters.vibration_value); | ||
| 1566 | |||
| 1567 | LOG_DEBUG(Service_HID, | 1548 | LOG_DEBUG(Service_HID, |
| 1568 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | 1549 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", |
| 1569 | parameters.vibration_device_handle.npad_type, | 1550 | parameters.vibration_device_handle.npad_type, |
| 1570 | parameters.vibration_device_handle.npad_id, | 1551 | parameters.vibration_device_handle.npad_id, |
| 1571 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); | 1552 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); |
| 1572 | 1553 | ||
| 1554 | GetResourceManager()->SendVibrationValue(parameters.applet_resource_user_id, | ||
| 1555 | parameters.vibration_device_handle, | ||
| 1556 | parameters.vibration_value); | ||
| 1557 | |||
| 1573 | IPC::ResponseBuilder rb{ctx, 2}; | 1558 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1574 | rb.Push(ResultSuccess); | 1559 | rb.Push(ResultSuccess); |
| 1575 | } | 1560 | } |
| @@ -1591,10 +1576,28 @@ void IHidServer::GetActualVibrationValue(HLERequestContext& ctx) { | |||
| 1591 | parameters.vibration_device_handle.npad_id, | 1576 | parameters.vibration_device_handle.npad_id, |
| 1592 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); | 1577 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); |
| 1593 | 1578 | ||
| 1579 | bool has_active_aruid{}; | ||
| 1580 | NpadVibrationDevice* device{nullptr}; | ||
| 1581 | Core::HID::VibrationValue vibration_value{}; | ||
| 1582 | Result result = GetResourceManager()->IsVibrationAruidActive(parameters.applet_resource_user_id, | ||
| 1583 | has_active_aruid); | ||
| 1584 | |||
| 1585 | if (result.IsSuccess() && has_active_aruid) { | ||
| 1586 | result = IsVibrationHandleValid(parameters.vibration_device_handle); | ||
| 1587 | } | ||
| 1588 | if (result.IsSuccess() && has_active_aruid) { | ||
| 1589 | device = GetResourceManager()->GetNSVibrationDevice(parameters.vibration_device_handle); | ||
| 1590 | } | ||
| 1591 | if (device != nullptr) { | ||
| 1592 | result = device->GetActualVibrationValue(vibration_value); | ||
| 1593 | } | ||
| 1594 | if (result.IsError()) { | ||
| 1595 | vibration_value = Core::HID::DEFAULT_VIBRATION_VALUE; | ||
| 1596 | } | ||
| 1597 | |||
| 1594 | IPC::ResponseBuilder rb{ctx, 6}; | 1598 | IPC::ResponseBuilder rb{ctx, 6}; |
| 1595 | rb.Push(ResultSuccess); | 1599 | rb.Push(ResultSuccess); |
| 1596 | rb.PushRaw(GetResourceManager()->GetNpad()->GetLastVibration( | 1600 | rb.PushRaw(vibration_value); |
| 1597 | parameters.applet_resource_user_id, parameters.vibration_device_handle)); | ||
| 1598 | } | 1601 | } |
| 1599 | 1602 | ||
| 1600 | void IHidServer::CreateActiveVibrationDeviceList(HLERequestContext& ctx) { | 1603 | void IHidServer::CreateActiveVibrationDeviceList(HLERequestContext& ctx) { |
| @@ -1609,25 +1612,27 @@ void IHidServer::PermitVibration(HLERequestContext& ctx) { | |||
| 1609 | IPC::RequestParser rp{ctx}; | 1612 | IPC::RequestParser rp{ctx}; |
| 1610 | const auto can_vibrate{rp.Pop<bool>()}; | 1613 | const auto can_vibrate{rp.Pop<bool>()}; |
| 1611 | 1614 | ||
| 1612 | // nnSDK saves this value as a float. Since it can only be 1.0f or 0.0f we simplify this value | ||
| 1613 | // by converting it to a bool | ||
| 1614 | Settings::values.vibration_enabled.SetValue(can_vibrate); | ||
| 1615 | |||
| 1616 | LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate); | 1615 | LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate); |
| 1617 | 1616 | ||
| 1617 | const auto result = | ||
| 1618 | GetResourceManager()->GetNpad()->GetVibrationHandler()->SetVibrationMasterVolume( | ||
| 1619 | can_vibrate ? 1.0f : 0.0f); | ||
| 1620 | |||
| 1618 | IPC::ResponseBuilder rb{ctx, 2}; | 1621 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1619 | rb.Push(ResultSuccess); | 1622 | rb.Push(result); |
| 1620 | } | 1623 | } |
| 1621 | 1624 | ||
| 1622 | void IHidServer::IsVibrationPermitted(HLERequestContext& ctx) { | 1625 | void IHidServer::IsVibrationPermitted(HLERequestContext& ctx) { |
| 1623 | LOG_DEBUG(Service_HID, "called"); | 1626 | LOG_DEBUG(Service_HID, "called"); |
| 1624 | 1627 | ||
| 1625 | // nnSDK checks if a float is greater than zero. We return the bool we stored earlier | 1628 | f32 master_volume{}; |
| 1626 | const auto is_enabled = Settings::values.vibration_enabled.GetValue(); | 1629 | const auto result = |
| 1630 | GetResourceManager()->GetNpad()->GetVibrationHandler()->GetVibrationMasterVolume( | ||
| 1631 | master_volume); | ||
| 1627 | 1632 | ||
| 1628 | IPC::ResponseBuilder rb{ctx, 3}; | 1633 | IPC::ResponseBuilder rb{ctx, 3}; |
| 1629 | rb.Push(ResultSuccess); | 1634 | rb.Push(result); |
| 1630 | rb.Push(is_enabled); | 1635 | rb.Push(master_volume > 0.0f); |
| 1631 | } | 1636 | } |
| 1632 | 1637 | ||
| 1633 | void IHidServer::SendVibrationValues(HLERequestContext& ctx) { | 1638 | void IHidServer::SendVibrationValues(HLERequestContext& ctx) { |
| @@ -1645,13 +1650,22 @@ void IHidServer::SendVibrationValues(HLERequestContext& ctx) { | |||
| 1645 | auto vibration_values = std::span( | 1650 | auto vibration_values = std::span( |
| 1646 | reinterpret_cast<const Core::HID::VibrationValue*>(vibration_data.data()), vibration_count); | 1651 | reinterpret_cast<const Core::HID::VibrationValue*>(vibration_data.data()), vibration_count); |
| 1647 | 1652 | ||
| 1648 | GetResourceManager()->GetNpad()->VibrateControllers(applet_resource_user_id, | ||
| 1649 | vibration_device_handles, vibration_values); | ||
| 1650 | |||
| 1651 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 1653 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 1652 | 1654 | ||
| 1655 | Result result = ResultSuccess; | ||
| 1656 | if (handle_count != vibration_count) { | ||
| 1657 | result = ResultVibrationArraySizeMismatch; | ||
| 1658 | } | ||
| 1659 | |||
| 1660 | for (std::size_t i = 0; i < handle_count; i++) { | ||
| 1661 | if (result.IsSuccess()) { | ||
| 1662 | result = GetResourceManager()->SendVibrationValue( | ||
| 1663 | applet_resource_user_id, vibration_device_handles[i], vibration_values[i]); | ||
| 1664 | } | ||
| 1665 | } | ||
| 1666 | |||
| 1653 | IPC::ResponseBuilder rb{ctx, 2}; | 1667 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1654 | rb.Push(ResultSuccess); | 1668 | rb.Push(result); |
| 1655 | } | 1669 | } |
| 1656 | 1670 | ||
| 1657 | void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) { | 1671 | void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) { |
| @@ -1666,43 +1680,6 @@ void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) { | |||
| 1666 | 1680 | ||
| 1667 | const auto parameters{rp.PopRaw<Parameters>()}; | 1681 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 1668 | 1682 | ||
| 1669 | /** | ||
| 1670 | * Note: This uses yuzu-specific behavior such that the StopHard command produces | ||
| 1671 | * vibrations where freq_low == 0.0f and freq_high == 0.0f, as defined below, | ||
| 1672 | * in order to differentiate between Stop and StopHard commands. | ||
| 1673 | * This is done to reuse the controller vibration functions made for regular controllers. | ||
| 1674 | */ | ||
| 1675 | const auto vibration_value = [parameters] { | ||
| 1676 | switch (parameters.gc_erm_command) { | ||
| 1677 | case Core::HID::VibrationGcErmCommand::Stop: | ||
| 1678 | return Core::HID::VibrationValue{ | ||
| 1679 | .low_amplitude = 0.0f, | ||
| 1680 | .low_frequency = 160.0f, | ||
| 1681 | .high_amplitude = 0.0f, | ||
| 1682 | .high_frequency = 320.0f, | ||
| 1683 | }; | ||
| 1684 | case Core::HID::VibrationGcErmCommand::Start: | ||
| 1685 | return Core::HID::VibrationValue{ | ||
| 1686 | .low_amplitude = 1.0f, | ||
| 1687 | .low_frequency = 160.0f, | ||
| 1688 | .high_amplitude = 1.0f, | ||
| 1689 | .high_frequency = 320.0f, | ||
| 1690 | }; | ||
| 1691 | case Core::HID::VibrationGcErmCommand::StopHard: | ||
| 1692 | return Core::HID::VibrationValue{ | ||
| 1693 | .low_amplitude = 0.0f, | ||
| 1694 | .low_frequency = 0.0f, | ||
| 1695 | .high_amplitude = 0.0f, | ||
| 1696 | .high_frequency = 0.0f, | ||
| 1697 | }; | ||
| 1698 | default: | ||
| 1699 | return Core::HID::DEFAULT_VIBRATION_VALUE; | ||
| 1700 | } | ||
| 1701 | }(); | ||
| 1702 | |||
| 1703 | GetResourceManager()->GetNpad()->VibrateController( | ||
| 1704 | parameters.applet_resource_user_id, parameters.vibration_device_handle, vibration_value); | ||
| 1705 | |||
| 1706 | LOG_DEBUG(Service_HID, | 1683 | LOG_DEBUG(Service_HID, |
| 1707 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}, " | 1684 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}, " |
| 1708 | "gc_erm_command={}", | 1685 | "gc_erm_command={}", |
| @@ -1711,8 +1688,23 @@ void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) { | |||
| 1711 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id, | 1688 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id, |
| 1712 | parameters.gc_erm_command); | 1689 | parameters.gc_erm_command); |
| 1713 | 1690 | ||
| 1691 | bool has_active_aruid{}; | ||
| 1692 | NpadGcVibrationDevice* gc_device{nullptr}; | ||
| 1693 | Result result = GetResourceManager()->IsVibrationAruidActive(parameters.applet_resource_user_id, | ||
| 1694 | has_active_aruid); | ||
| 1695 | |||
| 1696 | if (result.IsSuccess() && has_active_aruid) { | ||
| 1697 | result = IsVibrationHandleValid(parameters.vibration_device_handle); | ||
| 1698 | } | ||
| 1699 | if (result.IsSuccess() && has_active_aruid) { | ||
| 1700 | gc_device = GetResourceManager()->GetGcVibrationDevice(parameters.vibration_device_handle); | ||
| 1701 | } | ||
| 1702 | if (gc_device != nullptr) { | ||
| 1703 | result = gc_device->SendVibrationGcErmCommand(parameters.gc_erm_command); | ||
| 1704 | } | ||
| 1705 | |||
| 1714 | IPC::ResponseBuilder rb{ctx, 2}; | 1706 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1715 | rb.Push(ResultSuccess); | 1707 | rb.Push(result); |
| 1716 | } | 1708 | } |
| 1717 | 1709 | ||
| 1718 | void IHidServer::GetActualVibrationGcErmCommand(HLERequestContext& ctx) { | 1710 | void IHidServer::GetActualVibrationGcErmCommand(HLERequestContext& ctx) { |
| @@ -1725,33 +1717,31 @@ void IHidServer::GetActualVibrationGcErmCommand(HLERequestContext& ctx) { | |||
| 1725 | 1717 | ||
| 1726 | const auto parameters{rp.PopRaw<Parameters>()}; | 1718 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 1727 | 1719 | ||
| 1728 | const auto last_vibration = GetResourceManager()->GetNpad()->GetLastVibration( | ||
| 1729 | parameters.applet_resource_user_id, parameters.vibration_device_handle); | ||
| 1730 | |||
| 1731 | const auto gc_erm_command = [last_vibration] { | ||
| 1732 | if (last_vibration.low_amplitude != 0.0f || last_vibration.high_amplitude != 0.0f) { | ||
| 1733 | return Core::HID::VibrationGcErmCommand::Start; | ||
| 1734 | } | ||
| 1735 | |||
| 1736 | /** | ||
| 1737 | * Note: This uses yuzu-specific behavior such that the StopHard command produces | ||
| 1738 | * vibrations where freq_low == 0.0f and freq_high == 0.0f, as defined in the HID function | ||
| 1739 | * SendVibrationGcErmCommand, in order to differentiate between Stop and StopHard commands. | ||
| 1740 | * This is done to reuse the controller vibration functions made for regular controllers. | ||
| 1741 | */ | ||
| 1742 | if (last_vibration.low_frequency == 0.0f && last_vibration.high_frequency == 0.0f) { | ||
| 1743 | return Core::HID::VibrationGcErmCommand::StopHard; | ||
| 1744 | } | ||
| 1745 | |||
| 1746 | return Core::HID::VibrationGcErmCommand::Stop; | ||
| 1747 | }(); | ||
| 1748 | |||
| 1749 | LOG_DEBUG(Service_HID, | 1720 | LOG_DEBUG(Service_HID, |
| 1750 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | 1721 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", |
| 1751 | parameters.vibration_device_handle.npad_type, | 1722 | parameters.vibration_device_handle.npad_type, |
| 1752 | parameters.vibration_device_handle.npad_id, | 1723 | parameters.vibration_device_handle.npad_id, |
| 1753 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); | 1724 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); |
| 1754 | 1725 | ||
| 1726 | bool has_active_aruid{}; | ||
| 1727 | NpadGcVibrationDevice* gc_device{nullptr}; | ||
| 1728 | Core::HID::VibrationGcErmCommand gc_erm_command{}; | ||
| 1729 | Result result = GetResourceManager()->IsVibrationAruidActive(parameters.applet_resource_user_id, | ||
| 1730 | has_active_aruid); | ||
| 1731 | |||
| 1732 | if (result.IsSuccess() && has_active_aruid) { | ||
| 1733 | result = IsVibrationHandleValid(parameters.vibration_device_handle); | ||
| 1734 | } | ||
| 1735 | if (result.IsSuccess() && has_active_aruid) { | ||
| 1736 | gc_device = GetResourceManager()->GetGcVibrationDevice(parameters.vibration_device_handle); | ||
| 1737 | } | ||
| 1738 | if (gc_device != nullptr) { | ||
| 1739 | result = gc_device->GetActualVibrationGcErmCommand(gc_erm_command); | ||
| 1740 | } | ||
| 1741 | if (result.IsError()) { | ||
| 1742 | gc_erm_command = Core::HID::VibrationGcErmCommand::Stop; | ||
| 1743 | } | ||
| 1744 | |||
| 1755 | IPC::ResponseBuilder rb{ctx, 4}; | 1745 | IPC::ResponseBuilder rb{ctx, 4}; |
| 1756 | rb.Push(ResultSuccess); | 1746 | rb.Push(ResultSuccess); |
| 1757 | rb.PushEnum(gc_erm_command); | 1747 | rb.PushEnum(gc_erm_command); |
| @@ -1761,21 +1751,24 @@ void IHidServer::BeginPermitVibrationSession(HLERequestContext& ctx) { | |||
| 1761 | IPC::RequestParser rp{ctx}; | 1751 | IPC::RequestParser rp{ctx}; |
| 1762 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 1752 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 1763 | 1753 | ||
| 1764 | GetResourceManager()->GetNpad()->SetPermitVibrationSession(true); | ||
| 1765 | |||
| 1766 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 1754 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 1767 | 1755 | ||
| 1756 | const auto result = | ||
| 1757 | GetResourceManager()->GetNpad()->GetVibrationHandler()->BeginPermitVibrationSession( | ||
| 1758 | applet_resource_user_id); | ||
| 1759 | |||
| 1768 | IPC::ResponseBuilder rb{ctx, 2}; | 1760 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1769 | rb.Push(ResultSuccess); | 1761 | rb.Push(result); |
| 1770 | } | 1762 | } |
| 1771 | 1763 | ||
| 1772 | void IHidServer::EndPermitVibrationSession(HLERequestContext& ctx) { | 1764 | void IHidServer::EndPermitVibrationSession(HLERequestContext& ctx) { |
| 1773 | GetResourceManager()->GetNpad()->SetPermitVibrationSession(false); | ||
| 1774 | |||
| 1775 | LOG_DEBUG(Service_HID, "called"); | 1765 | LOG_DEBUG(Service_HID, "called"); |
| 1776 | 1766 | ||
| 1767 | const auto result = | ||
| 1768 | GetResourceManager()->GetNpad()->GetVibrationHandler()->EndPermitVibrationSession(); | ||
| 1769 | |||
| 1777 | IPC::ResponseBuilder rb{ctx, 2}; | 1770 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1778 | rb.Push(ResultSuccess); | 1771 | rb.Push(result); |
| 1779 | } | 1772 | } |
| 1780 | 1773 | ||
| 1781 | void IHidServer::IsVibrationDeviceMounted(HLERequestContext& ctx) { | 1774 | void IHidServer::IsVibrationDeviceMounted(HLERequestContext& ctx) { |
| @@ -1795,10 +1788,61 @@ void IHidServer::IsVibrationDeviceMounted(HLERequestContext& ctx) { | |||
| 1795 | parameters.vibration_device_handle.npad_id, | 1788 | parameters.vibration_device_handle.npad_id, |
| 1796 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); | 1789 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); |
| 1797 | 1790 | ||
| 1791 | bool is_mounted{}; | ||
| 1792 | NpadVibrationBase* device{nullptr}; | ||
| 1793 | Result result = IsVibrationHandleValid(parameters.vibration_device_handle); | ||
| 1794 | |||
| 1795 | if (result.IsSuccess()) { | ||
| 1796 | device = GetResourceManager()->GetVibrationDevice(parameters.vibration_device_handle); | ||
| 1797 | } | ||
| 1798 | |||
| 1799 | if (device != nullptr) { | ||
| 1800 | is_mounted = device->IsVibrationMounted(); | ||
| 1801 | } | ||
| 1802 | |||
| 1798 | IPC::ResponseBuilder rb{ctx, 3}; | 1803 | IPC::ResponseBuilder rb{ctx, 3}; |
| 1799 | rb.Push(ResultSuccess); | 1804 | rb.Push(result); |
| 1800 | rb.Push(GetResourceManager()->GetNpad()->IsVibrationDeviceMounted( | 1805 | rb.Push(is_mounted); |
| 1801 | parameters.applet_resource_user_id, parameters.vibration_device_handle)); | 1806 | } |
| 1807 | |||
| 1808 | void IHidServer::SendVibrationValueInBool(HLERequestContext& ctx) { | ||
| 1809 | IPC::RequestParser rp{ctx}; | ||
| 1810 | struct Parameters { | ||
| 1811 | Core::HID::VibrationDeviceHandle vibration_device_handle; | ||
| 1812 | INSERT_PADDING_WORDS_NOINIT(1); | ||
| 1813 | u64 applet_resource_user_id; | ||
| 1814 | bool is_vibrating; | ||
| 1815 | }; | ||
| 1816 | static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); | ||
| 1817 | |||
| 1818 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 1819 | |||
| 1820 | LOG_DEBUG(Service_HID, | ||
| 1821 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}, " | ||
| 1822 | "is_vibrating={}", | ||
| 1823 | parameters.vibration_device_handle.npad_type, | ||
| 1824 | parameters.vibration_device_handle.npad_id, | ||
| 1825 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id, | ||
| 1826 | parameters.is_vibrating); | ||
| 1827 | |||
| 1828 | bool has_active_aruid{}; | ||
| 1829 | NpadN64VibrationDevice* n64_device{nullptr}; | ||
| 1830 | Result result = GetResourceManager()->IsVibrationAruidActive(parameters.applet_resource_user_id, | ||
| 1831 | has_active_aruid); | ||
| 1832 | |||
| 1833 | if (result.IsSuccess() && has_active_aruid) { | ||
| 1834 | result = IsVibrationHandleValid(parameters.vibration_device_handle); | ||
| 1835 | } | ||
| 1836 | if (result.IsSuccess() && has_active_aruid) { | ||
| 1837 | n64_device = | ||
| 1838 | GetResourceManager()->GetN64VibrationDevice(parameters.vibration_device_handle); | ||
| 1839 | } | ||
| 1840 | if (n64_device != nullptr) { | ||
| 1841 | result = n64_device->SendValueInBool(parameters.is_vibrating); | ||
| 1842 | } | ||
| 1843 | |||
| 1844 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1845 | rb.Push(result); | ||
| 1802 | } | 1846 | } |
| 1803 | 1847 | ||
| 1804 | void IHidServer::ActivateConsoleSixAxisSensor(HLERequestContext& ctx) { | 1848 | void IHidServer::ActivateConsoleSixAxisSensor(HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/hid/hid_server.h b/src/core/hle/service/hid/hid_server.h index cc7c4ebdd..3a2e0a230 100644 --- a/src/core/hle/service/hid/hid_server.h +++ b/src/core/hle/service/hid/hid_server.h | |||
| @@ -97,6 +97,7 @@ private: | |||
| 97 | void BeginPermitVibrationSession(HLERequestContext& ctx); | 97 | void BeginPermitVibrationSession(HLERequestContext& ctx); |
| 98 | void EndPermitVibrationSession(HLERequestContext& ctx); | 98 | void EndPermitVibrationSession(HLERequestContext& ctx); |
| 99 | void IsVibrationDeviceMounted(HLERequestContext& ctx); | 99 | void IsVibrationDeviceMounted(HLERequestContext& ctx); |
| 100 | void SendVibrationValueInBool(HLERequestContext& ctx); | ||
| 100 | void ActivateConsoleSixAxisSensor(HLERequestContext& ctx); | 101 | void ActivateConsoleSixAxisSensor(HLERequestContext& ctx); |
| 101 | void StartConsoleSixAxisSensor(HLERequestContext& ctx); | 102 | void StartConsoleSixAxisSensor(HLERequestContext& ctx); |
| 102 | void StopConsoleSixAxisSensor(HLERequestContext& ctx); | 103 | void StopConsoleSixAxisSensor(HLERequestContext& ctx); |
diff --git a/src/core/hle/service/hid/hid_system_server.cpp b/src/core/hle/service/hid/hid_system_server.cpp index 3a0cb3cb1..4466a189b 100644 --- a/src/core/hle/service/hid/hid_system_server.cpp +++ b/src/core/hle/service/hid/hid_system_server.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include "hid_core/resource_manager.h" | 7 | #include "hid_core/resource_manager.h" |
| 8 | #include "hid_core/resources/npad/npad.h" | 8 | #include "hid_core/resources/npad/npad.h" |
| 9 | #include "hid_core/resources/npad/npad_types.h" | 9 | #include "hid_core/resources/npad/npad_types.h" |
| 10 | #include "hid_core/resources/npad/npad_vibration.h" | ||
| 10 | #include "hid_core/resources/palma/palma.h" | 11 | #include "hid_core/resources/palma/palma.h" |
| 11 | #include "hid_core/resources/touch_screen/touch_screen.h" | 12 | #include "hid_core/resources/touch_screen/touch_screen.h" |
| 12 | 13 | ||
| @@ -67,14 +68,14 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour | |||
| 67 | {501, &IHidSystemServer::RegisterAppletResourceUserId, "RegisterAppletResourceUserId"}, | 68 | {501, &IHidSystemServer::RegisterAppletResourceUserId, "RegisterAppletResourceUserId"}, |
| 68 | {502, &IHidSystemServer::UnregisterAppletResourceUserId, "UnregisterAppletResourceUserId"}, | 69 | {502, &IHidSystemServer::UnregisterAppletResourceUserId, "UnregisterAppletResourceUserId"}, |
| 69 | {503, &IHidSystemServer::EnableAppletToGetInput, "EnableAppletToGetInput"}, | 70 | {503, &IHidSystemServer::EnableAppletToGetInput, "EnableAppletToGetInput"}, |
| 70 | {504, nullptr, "SetAruidValidForVibration"}, | 71 | {504, &IHidSystemServer::SetAruidValidForVibration, "SetAruidValidForVibration"}, |
| 71 | {505, &IHidSystemServer::EnableAppletToGetSixAxisSensor, "EnableAppletToGetSixAxisSensor"}, | 72 | {505, &IHidSystemServer::EnableAppletToGetSixAxisSensor, "EnableAppletToGetSixAxisSensor"}, |
| 72 | {506, &IHidSystemServer::EnableAppletToGetPadInput, "EnableAppletToGetPadInput"}, | 73 | {506, &IHidSystemServer::EnableAppletToGetPadInput, "EnableAppletToGetPadInput"}, |
| 73 | {507, &IHidSystemServer::EnableAppletToGetTouchScreen, "EnableAppletToGetTouchScreen"}, | 74 | {507, &IHidSystemServer::EnableAppletToGetTouchScreen, "EnableAppletToGetTouchScreen"}, |
| 74 | {510, nullptr, "SetVibrationMasterVolume"}, | 75 | {510, &IHidSystemServer::SetVibrationMasterVolume, "SetVibrationMasterVolume"}, |
| 75 | {511, nullptr, "GetVibrationMasterVolume"}, | 76 | {511, &IHidSystemServer::GetVibrationMasterVolume, "GetVibrationMasterVolume"}, |
| 76 | {512, nullptr, "BeginPermitVibrationSession"}, | 77 | {512, &IHidSystemServer::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, |
| 77 | {513, nullptr, "EndPermitVibrationSession"}, | 78 | {513, &IHidSystemServer::EndPermitVibrationSession, "EndPermitVibrationSession"}, |
| 78 | {514, nullptr, "Unknown514"}, | 79 | {514, nullptr, "Unknown514"}, |
| 79 | {520, nullptr, "EnableHandheldHids"}, | 80 | {520, nullptr, "EnableHandheldHids"}, |
| 80 | {521, nullptr, "DisableHandheldHids"}, | 81 | {521, nullptr, "DisableHandheldHids"}, |
| @@ -156,7 +157,7 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour | |||
| 156 | {1152, nullptr, "SetTouchScreenDefaultConfiguration"}, | 157 | {1152, nullptr, "SetTouchScreenDefaultConfiguration"}, |
| 157 | {1153, &IHidSystemServer::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"}, | 158 | {1153, &IHidSystemServer::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"}, |
| 158 | {1154, nullptr, "IsFirmwareAvailableForNotification"}, | 159 | {1154, nullptr, "IsFirmwareAvailableForNotification"}, |
| 159 | {1155, nullptr, "SetForceHandheldStyleVibration"}, | 160 | {1155, &IHidSystemServer::SetForceHandheldStyleVibration, "SetForceHandheldStyleVibration"}, |
| 160 | {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"}, | 161 | {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"}, |
| 161 | {1157, nullptr, "CancelConnectionTrigger"}, | 162 | {1157, nullptr, "CancelConnectionTrigger"}, |
| 162 | {1200, nullptr, "IsButtonConfigSupported"}, | 163 | {1200, nullptr, "IsButtonConfigSupported"}, |
| @@ -538,6 +539,27 @@ void IHidSystemServer::EnableAppletToGetInput(HLERequestContext& ctx) { | |||
| 538 | rb.Push(ResultSuccess); | 539 | rb.Push(ResultSuccess); |
| 539 | } | 540 | } |
| 540 | 541 | ||
| 542 | void IHidSystemServer::SetAruidValidForVibration(HLERequestContext& ctx) { | ||
| 543 | IPC::RequestParser rp{ctx}; | ||
| 544 | struct Parameters { | ||
| 545 | bool is_enabled; | ||
| 546 | INSERT_PADDING_WORDS_NOINIT(1); | ||
| 547 | u64 applet_resource_user_id; | ||
| 548 | }; | ||
| 549 | static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); | ||
| 550 | |||
| 551 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 552 | |||
| 553 | LOG_INFO(Service_HID, "called, is_enabled={}, applet_resource_user_id={}", | ||
| 554 | parameters.is_enabled, parameters.applet_resource_user_id); | ||
| 555 | |||
| 556 | GetResourceManager()->SetAruidValidForVibration(parameters.applet_resource_user_id, | ||
| 557 | parameters.is_enabled); | ||
| 558 | |||
| 559 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 560 | rb.Push(ResultSuccess); | ||
| 561 | } | ||
| 562 | |||
| 541 | void IHidSystemServer::EnableAppletToGetSixAxisSensor(HLERequestContext& ctx) { | 563 | void IHidSystemServer::EnableAppletToGetSixAxisSensor(HLERequestContext& ctx) { |
| 542 | IPC::RequestParser rp{ctx}; | 564 | IPC::RequestParser rp{ctx}; |
| 543 | struct Parameters { | 565 | struct Parameters { |
| @@ -601,6 +623,57 @@ void IHidSystemServer::EnableAppletToGetTouchScreen(HLERequestContext& ctx) { | |||
| 601 | rb.Push(ResultSuccess); | 623 | rb.Push(ResultSuccess); |
| 602 | } | 624 | } |
| 603 | 625 | ||
| 626 | void IHidSystemServer::SetVibrationMasterVolume(HLERequestContext& ctx) { | ||
| 627 | IPC::RequestParser rp{ctx}; | ||
| 628 | const auto master_volume{rp.Pop<f32>()}; | ||
| 629 | |||
| 630 | LOG_INFO(Service_HID, "called, volume={}", master_volume); | ||
| 631 | |||
| 632 | const auto result = | ||
| 633 | GetResourceManager()->GetNpad()->GetVibrationHandler()->SetVibrationMasterVolume( | ||
| 634 | master_volume); | ||
| 635 | |||
| 636 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 637 | rb.Push(result); | ||
| 638 | } | ||
| 639 | |||
| 640 | void IHidSystemServer::GetVibrationMasterVolume(HLERequestContext& ctx) { | ||
| 641 | f32 master_volume{}; | ||
| 642 | const auto result = | ||
| 643 | GetResourceManager()->GetNpad()->GetVibrationHandler()->GetVibrationMasterVolume( | ||
| 644 | master_volume); | ||
| 645 | |||
| 646 | LOG_INFO(Service_HID, "called, volume={}", master_volume); | ||
| 647 | |||
| 648 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 649 | rb.Push(result); | ||
| 650 | rb.Push(master_volume); | ||
| 651 | } | ||
| 652 | |||
| 653 | void IHidSystemServer::BeginPermitVibrationSession(HLERequestContext& ctx) { | ||
| 654 | IPC::RequestParser rp{ctx}; | ||
| 655 | const auto applet_resource_user_id{rp.Pop<u64>()}; | ||
| 656 | |||
| 657 | LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | ||
| 658 | |||
| 659 | const auto result = | ||
| 660 | GetResourceManager()->GetNpad()->GetVibrationHandler()->BeginPermitVibrationSession( | ||
| 661 | applet_resource_user_id); | ||
| 662 | |||
| 663 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 664 | rb.Push(result); | ||
| 665 | } | ||
| 666 | |||
| 667 | void IHidSystemServer::EndPermitVibrationSession(HLERequestContext& ctx) { | ||
| 668 | LOG_INFO(Service_HID, "called"); | ||
| 669 | |||
| 670 | const auto result = | ||
| 671 | GetResourceManager()->GetNpad()->GetVibrationHandler()->EndPermitVibrationSession(); | ||
| 672 | |||
| 673 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 674 | rb.Push(result); | ||
| 675 | } | ||
| 676 | |||
| 604 | void IHidSystemServer::IsJoyConAttachedOnAllRail(HLERequestContext& ctx) { | 677 | void IHidSystemServer::IsJoyConAttachedOnAllRail(HLERequestContext& ctx) { |
| 605 | const bool is_attached = true; | 678 | const bool is_attached = true; |
| 606 | 679 | ||
| @@ -749,6 +822,19 @@ void IHidSystemServer::GetTouchScreenDefaultConfiguration(HLERequestContext& ctx | |||
| 749 | rb.PushRaw(touchscreen_config); | 822 | rb.PushRaw(touchscreen_config); |
| 750 | } | 823 | } |
| 751 | 824 | ||
| 825 | void IHidSystemServer::SetForceHandheldStyleVibration(HLERequestContext& ctx) { | ||
| 826 | IPC::RequestParser rp{ctx}; | ||
| 827 | const auto is_forced{rp.Pop<bool>()}; | ||
| 828 | |||
| 829 | LOG_INFO(Service_HID, "called, is_forced={}", is_forced); | ||
| 830 | |||
| 831 | GetResourceManager()->SetForceHandheldStyleVibration(is_forced); | ||
| 832 | GetResourceManager()->GetNpad()->UpdateHandheldAbstractState(); | ||
| 833 | |||
| 834 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 835 | rb.Push(ResultSuccess); | ||
| 836 | } | ||
| 837 | |||
| 752 | void IHidSystemServer::IsUsingCustomButtonConfig(HLERequestContext& ctx) { | 838 | void IHidSystemServer::IsUsingCustomButtonConfig(HLERequestContext& ctx) { |
| 753 | const bool is_enabled = false; | 839 | const bool is_enabled = false; |
| 754 | 840 | ||
diff --git a/src/core/hle/service/hid/hid_system_server.h b/src/core/hle/service/hid/hid_system_server.h index 0c2634e3f..90a719f02 100644 --- a/src/core/hle/service/hid/hid_system_server.h +++ b/src/core/hle/service/hid/hid_system_server.h | |||
| @@ -42,9 +42,14 @@ private: | |||
| 42 | void RegisterAppletResourceUserId(HLERequestContext& ctx); | 42 | void RegisterAppletResourceUserId(HLERequestContext& ctx); |
| 43 | void UnregisterAppletResourceUserId(HLERequestContext& ctx); | 43 | void UnregisterAppletResourceUserId(HLERequestContext& ctx); |
| 44 | void EnableAppletToGetInput(HLERequestContext& ctx); | 44 | void EnableAppletToGetInput(HLERequestContext& ctx); |
| 45 | void SetAruidValidForVibration(HLERequestContext& ctx); | ||
| 45 | void EnableAppletToGetSixAxisSensor(HLERequestContext& ctx); | 46 | void EnableAppletToGetSixAxisSensor(HLERequestContext& ctx); |
| 46 | void EnableAppletToGetPadInput(HLERequestContext& ctx); | 47 | void EnableAppletToGetPadInput(HLERequestContext& ctx); |
| 47 | void EnableAppletToGetTouchScreen(HLERequestContext& ctx); | 48 | void EnableAppletToGetTouchScreen(HLERequestContext& ctx); |
| 49 | void SetVibrationMasterVolume(HLERequestContext& ctx); | ||
| 50 | void GetVibrationMasterVolume(HLERequestContext& ctx); | ||
| 51 | void BeginPermitVibrationSession(HLERequestContext& ctx); | ||
| 52 | void EndPermitVibrationSession(HLERequestContext& ctx); | ||
| 48 | void IsJoyConAttachedOnAllRail(HLERequestContext& ctx); | 53 | void IsJoyConAttachedOnAllRail(HLERequestContext& ctx); |
| 49 | void AcquireConnectionTriggerTimeoutEvent(HLERequestContext& ctx); | 54 | void AcquireConnectionTriggerTimeoutEvent(HLERequestContext& ctx); |
| 50 | void AcquireDeviceRegisteredEventForControllerSupport(HLERequestContext& ctx); | 55 | void AcquireDeviceRegisteredEventForControllerSupport(HLERequestContext& ctx); |
| @@ -61,6 +66,7 @@ private: | |||
| 61 | void FinalizeUsbFirmwareUpdate(HLERequestContext& ctx); | 66 | void FinalizeUsbFirmwareUpdate(HLERequestContext& ctx); |
| 62 | void InitializeUsbFirmwareUpdateWithoutMemory(HLERequestContext& ctx); | 67 | void InitializeUsbFirmwareUpdateWithoutMemory(HLERequestContext& ctx); |
| 63 | void GetTouchScreenDefaultConfiguration(HLERequestContext& ctx); | 68 | void GetTouchScreenDefaultConfiguration(HLERequestContext& ctx); |
| 69 | void SetForceHandheldStyleVibration(HLERequestContext& ctx); | ||
| 64 | void IsUsingCustomButtonConfig(HLERequestContext& ctx); | 70 | void IsUsingCustomButtonConfig(HLERequestContext& ctx); |
| 65 | 71 | ||
| 66 | std::shared_ptr<ResourceManager> GetResourceManager(); | 72 | std::shared_ptr<ResourceManager> GetResourceManager(); |
diff --git a/src/hid_core/frontend/emulated_controller.cpp b/src/hid_core/frontend/emulated_controller.cpp index b001cf2fd..f2499502d 100644 --- a/src/hid_core/frontend/emulated_controller.cpp +++ b/src/hid_core/frontend/emulated_controller.cpp | |||
| @@ -145,8 +145,8 @@ void EmulatedController::ReloadColorsFromSettings() { | |||
| 145 | 145 | ||
| 146 | void EmulatedController::LoadDevices() { | 146 | void EmulatedController::LoadDevices() { |
| 147 | // TODO(german77): Use more buttons to detect the correct device | 147 | // TODO(german77): Use more buttons to detect the correct device |
| 148 | const auto left_joycon = button_params[Settings::NativeButton::DRight]; | 148 | const auto& left_joycon = button_params[Settings::NativeButton::DRight]; |
| 149 | const auto right_joycon = button_params[Settings::NativeButton::A]; | 149 | const auto& right_joycon = button_params[Settings::NativeButton::A]; |
| 150 | 150 | ||
| 151 | // Triggers for GC controllers | 151 | // Triggers for GC controllers |
| 152 | trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL]; | 152 | trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL]; |
| @@ -1209,20 +1209,43 @@ void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) { | |||
| 1209 | controller.nfc_state = controller.nfc_values; | 1209 | controller.nfc_state = controller.nfc_values; |
| 1210 | } | 1210 | } |
| 1211 | 1211 | ||
| 1212 | bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) { | 1212 | bool EmulatedController::SetVibration(bool should_vibrate) { |
| 1213 | VibrationValue vibration_value = DEFAULT_VIBRATION_VALUE; | ||
| 1214 | if (should_vibrate) { | ||
| 1215 | vibration_value.high_amplitude = 1.0f; | ||
| 1216 | vibration_value.low_amplitude = 1.0f; | ||
| 1217 | } | ||
| 1218 | |||
| 1219 | return SetVibration(DeviceIndex::Left, vibration_value); | ||
| 1220 | } | ||
| 1221 | |||
| 1222 | bool EmulatedController::SetVibration(u32 slot, Core::HID::VibrationGcErmCommand erm_command) { | ||
| 1223 | VibrationValue vibration_value = DEFAULT_VIBRATION_VALUE; | ||
| 1224 | if (erm_command == Core::HID::VibrationGcErmCommand::Start) { | ||
| 1225 | vibration_value.high_amplitude = 1.0f; | ||
| 1226 | vibration_value.low_amplitude = 1.0f; | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | return SetVibration(DeviceIndex::Left, vibration_value); | ||
| 1230 | } | ||
| 1231 | |||
| 1232 | bool EmulatedController::SetVibration(DeviceIndex device_index, const VibrationValue& vibration) { | ||
| 1213 | if (!is_initialized) { | 1233 | if (!is_initialized) { |
| 1214 | return false; | 1234 | return false; |
| 1215 | } | 1235 | } |
| 1216 | if (device_index >= output_devices.size()) { | 1236 | if (device_index >= DeviceIndex::MaxDeviceIndex) { |
| 1217 | return false; | 1237 | return false; |
| 1218 | } | 1238 | } |
| 1219 | if (!output_devices[device_index]) { | 1239 | const std::size_t index = static_cast<std::size_t>(device_index); |
| 1240 | if (!output_devices[index]) { | ||
| 1220 | return false; | 1241 | return false; |
| 1221 | } | 1242 | } |
| 1222 | const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type); | 1243 | const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type); |
| 1223 | const auto& player = Settings::values.players.GetValue()[player_index]; | 1244 | const auto& player = Settings::values.players.GetValue()[player_index]; |
| 1224 | const f32 strength = static_cast<f32>(player.vibration_strength) / 100.0f; | 1245 | const f32 strength = static_cast<f32>(player.vibration_strength) / 100.0f; |
| 1225 | 1246 | ||
| 1247 | last_vibration_value = vibration; | ||
| 1248 | |||
| 1226 | if (!player.vibration_enabled) { | 1249 | if (!player.vibration_enabled) { |
| 1227 | return false; | 1250 | return false; |
| 1228 | } | 1251 | } |
| @@ -1240,8 +1263,11 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v | |||
| 1240 | .high_frequency = vibration.high_frequency, | 1263 | .high_frequency = vibration.high_frequency, |
| 1241 | .type = type, | 1264 | .type = type, |
| 1242 | }; | 1265 | }; |
| 1243 | return output_devices[device_index]->SetVibration(status) == | 1266 | return output_devices[index]->SetVibration(status) == Common::Input::DriverResult::Success; |
| 1244 | Common::Input::DriverResult::Success; | 1267 | } |
| 1268 | |||
| 1269 | VibrationValue EmulatedController::GetActualVibrationValue(DeviceIndex device_index) const { | ||
| 1270 | return last_vibration_value; | ||
| 1245 | } | 1271 | } |
| 1246 | 1272 | ||
| 1247 | bool EmulatedController::IsVibrationEnabled(std::size_t device_index) { | 1273 | bool EmulatedController::IsVibrationEnabled(std::size_t device_index) { |
diff --git a/src/hid_core/frontend/emulated_controller.h b/src/hid_core/frontend/emulated_controller.h index 90e536e07..168abe089 100644 --- a/src/hid_core/frontend/emulated_controller.h +++ b/src/hid_core/frontend/emulated_controller.h | |||
| @@ -356,10 +356,27 @@ public: | |||
| 356 | const NfcState& GetNfc() const; | 356 | const NfcState& GetNfc() const; |
| 357 | 357 | ||
| 358 | /** | 358 | /** |
| 359 | * Sends an on/off vibration to the left device | ||
| 360 | * @return true if vibration had no errors | ||
| 361 | */ | ||
| 362 | bool SetVibration(bool should_vibrate); | ||
| 363 | |||
| 364 | /** | ||
| 365 | * Sends an GC vibration to the left device | ||
| 366 | * @return true if vibration had no errors | ||
| 367 | */ | ||
| 368 | bool SetVibration(u32 slot, Core::HID::VibrationGcErmCommand erm_command); | ||
| 369 | |||
| 370 | /** | ||
| 359 | * Sends a specific vibration to the output device | 371 | * Sends a specific vibration to the output device |
| 360 | * @return true if vibration had no errors | 372 | * @return true if vibration had no errors |
| 361 | */ | 373 | */ |
| 362 | bool SetVibration(std::size_t device_index, VibrationValue vibration); | 374 | bool SetVibration(DeviceIndex device_index, const VibrationValue& vibration); |
| 375 | |||
| 376 | /** | ||
| 377 | * @return The last sent vibration | ||
| 378 | */ | ||
| 379 | VibrationValue GetActualVibrationValue(DeviceIndex device_index) const; | ||
| 363 | 380 | ||
| 364 | /** | 381 | /** |
| 365 | * Sends a small vibration to the output device | 382 | * Sends a small vibration to the output device |
| @@ -564,6 +581,7 @@ private: | |||
| 564 | f32 motion_sensitivity{Core::HID::MotionInput::IsAtRestStandard}; | 581 | f32 motion_sensitivity{Core::HID::MotionInput::IsAtRestStandard}; |
| 565 | u32 turbo_button_state{0}; | 582 | u32 turbo_button_state{0}; |
| 566 | std::size_t nfc_handles{0}; | 583 | std::size_t nfc_handles{0}; |
| 584 | VibrationValue last_vibration_value{DEFAULT_VIBRATION_VALUE}; | ||
| 567 | 585 | ||
| 568 | // Temporary values to avoid doing changes while the controller is in configuring mode | 586 | // Temporary values to avoid doing changes while the controller is in configuring mode |
| 569 | NpadStyleIndex tmp_npad_type{NpadStyleIndex::None}; | 587 | NpadStyleIndex tmp_npad_type{NpadStyleIndex::None}; |
diff --git a/src/hid_core/resource_manager.cpp b/src/hid_core/resource_manager.cpp index 2c5fe6d51..ca824b4a3 100644 --- a/src/hid_core/resource_manager.cpp +++ b/src/hid_core/resource_manager.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include "core/hle/kernel/k_shared_memory.h" | 7 | #include "core/hle/kernel/k_shared_memory.h" |
| 8 | #include "core/hle/service/ipc_helpers.h" | 8 | #include "core/hle/service/ipc_helpers.h" |
| 9 | #include "hid_core/hid_core.h" | 9 | #include "hid_core/hid_core.h" |
| 10 | #include "hid_core/hid_util.h" | ||
| 10 | #include "hid_core/resource_manager.h" | 11 | #include "hid_core/resource_manager.h" |
| 11 | 12 | ||
| 12 | #include "hid_core/resources/applet_resource.h" | 13 | #include "hid_core/resources/applet_resource.h" |
| @@ -27,6 +28,10 @@ | |||
| 27 | #include "hid_core/resources/touch_screen/gesture.h" | 28 | #include "hid_core/resources/touch_screen/gesture.h" |
| 28 | #include "hid_core/resources/touch_screen/touch_screen.h" | 29 | #include "hid_core/resources/touch_screen/touch_screen.h" |
| 29 | #include "hid_core/resources/unique_pad/unique_pad.h" | 30 | #include "hid_core/resources/unique_pad/unique_pad.h" |
| 31 | #include "hid_core/resources/vibration/gc_vibration_device.h" | ||
| 32 | #include "hid_core/resources/vibration/n64_vibration_device.h" | ||
| 33 | #include "hid_core/resources/vibration/vibration_base.h" | ||
| 34 | #include "hid_core/resources/vibration/vibration_device.h" | ||
| 30 | 35 | ||
| 31 | namespace Service::HID { | 36 | namespace Service::HID { |
| 32 | 37 | ||
| @@ -52,6 +57,7 @@ void ResourceManager::Initialize() { | |||
| 52 | 57 | ||
| 53 | system.HIDCore().ReloadInputDevices(); | 58 | system.HIDCore().ReloadInputDevices(); |
| 54 | 59 | ||
| 60 | handheld_config = std::make_shared<HandheldConfig>(); | ||
| 55 | InitializeHidCommonSampler(); | 61 | InitializeHidCommonSampler(); |
| 56 | InitializeTouchScreenSampler(); | 62 | InitializeTouchScreenSampler(); |
| 57 | InitializeConsoleSixAxisSampler(); | 63 | InitializeConsoleSixAxisSampler(); |
| @@ -174,7 +180,7 @@ void ResourceManager::InitializeHidCommonSampler() { | |||
| 174 | debug_pad->SetAppletResource(applet_resource, &shared_mutex); | 180 | debug_pad->SetAppletResource(applet_resource, &shared_mutex); |
| 175 | digitizer->SetAppletResource(applet_resource, &shared_mutex); | 181 | digitizer->SetAppletResource(applet_resource, &shared_mutex); |
| 176 | keyboard->SetAppletResource(applet_resource, &shared_mutex); | 182 | keyboard->SetAppletResource(applet_resource, &shared_mutex); |
| 177 | npad->SetNpadExternals(applet_resource, &shared_mutex); | 183 | npad->SetNpadExternals(applet_resource, &shared_mutex, handheld_config); |
| 178 | six_axis->SetAppletResource(applet_resource, &shared_mutex); | 184 | six_axis->SetAppletResource(applet_resource, &shared_mutex); |
| 179 | mouse->SetAppletResource(applet_resource, &shared_mutex); | 185 | mouse->SetAppletResource(applet_resource, &shared_mutex); |
| 180 | debug_mouse->SetAppletResource(applet_resource, &shared_mutex); | 186 | debug_mouse->SetAppletResource(applet_resource, &shared_mutex); |
| @@ -257,6 +263,121 @@ void ResourceManager::EnableTouchScreen(u64 aruid, bool is_enabled) { | |||
| 257 | applet_resource->EnableTouchScreen(aruid, is_enabled); | 263 | applet_resource->EnableTouchScreen(aruid, is_enabled); |
| 258 | } | 264 | } |
| 259 | 265 | ||
| 266 | NpadVibrationBase* ResourceManager::GetVibrationDevice( | ||
| 267 | const Core::HID::VibrationDeviceHandle& handle) { | ||
| 268 | return npad->GetVibrationDevice(handle); | ||
| 269 | } | ||
| 270 | |||
| 271 | NpadN64VibrationDevice* ResourceManager::GetN64VibrationDevice( | ||
| 272 | const Core::HID::VibrationDeviceHandle& handle) { | ||
| 273 | return npad->GetN64VibrationDevice(handle); | ||
| 274 | } | ||
| 275 | |||
| 276 | NpadVibrationDevice* ResourceManager::GetNSVibrationDevice( | ||
| 277 | const Core::HID::VibrationDeviceHandle& handle) { | ||
| 278 | return npad->GetNSVibrationDevice(handle); | ||
| 279 | } | ||
| 280 | |||
| 281 | NpadGcVibrationDevice* ResourceManager::GetGcVibrationDevice( | ||
| 282 | const Core::HID::VibrationDeviceHandle& handle) { | ||
| 283 | return npad->GetGcVibrationDevice(handle); | ||
| 284 | } | ||
| 285 | |||
| 286 | Result ResourceManager::SetAruidValidForVibration(u64 aruid, bool is_enabled) { | ||
| 287 | std::scoped_lock lock{shared_mutex}; | ||
| 288 | const bool has_changed = applet_resource->SetAruidValidForVibration(aruid, is_enabled); | ||
| 289 | |||
| 290 | if (has_changed) { | ||
| 291 | auto devices = npad->GetAllVibrationDevices(); | ||
| 292 | for ([[maybe_unused]] auto* device : devices) { | ||
| 293 | // TODO | ||
| 294 | } | ||
| 295 | } | ||
| 296 | |||
| 297 | auto* vibration_handler = npad->GetVibrationHandler(); | ||
| 298 | if (aruid != vibration_handler->GetSessionAruid()) { | ||
| 299 | vibration_handler->EndPermitVibrationSession(); | ||
| 300 | } | ||
| 301 | |||
| 302 | return ResultSuccess; | ||
| 303 | } | ||
| 304 | |||
| 305 | void ResourceManager::SetForceHandheldStyleVibration(bool is_forced) { | ||
| 306 | handheld_config->is_force_handheld_style_vibration = is_forced; | ||
| 307 | } | ||
| 308 | |||
| 309 | Result ResourceManager::IsVibrationAruidActive(u64 aruid, bool& is_active) const { | ||
| 310 | std::scoped_lock lock{shared_mutex}; | ||
| 311 | is_active = applet_resource->IsVibrationAruidActive(aruid); | ||
| 312 | return ResultSuccess; | ||
| 313 | } | ||
| 314 | |||
| 315 | Result ResourceManager::GetVibrationDeviceInfo(Core::HID::VibrationDeviceInfo& device_info, | ||
| 316 | const Core::HID::VibrationDeviceHandle& handle) { | ||
| 317 | bool check_device_index = false; | ||
| 318 | |||
| 319 | const Result is_valid = IsVibrationHandleValid(handle); | ||
| 320 | if (is_valid.IsError()) { | ||
| 321 | return is_valid; | ||
| 322 | } | ||
| 323 | |||
| 324 | switch (handle.npad_type) { | ||
| 325 | case Core::HID::NpadStyleIndex::Fullkey: | ||
| 326 | case Core::HID::NpadStyleIndex::Handheld: | ||
| 327 | case Core::HID::NpadStyleIndex::JoyconDual: | ||
| 328 | case Core::HID::NpadStyleIndex::JoyconLeft: | ||
| 329 | case Core::HID::NpadStyleIndex::JoyconRight: | ||
| 330 | device_info.type = Core::HID::VibrationDeviceType::LinearResonantActuator; | ||
| 331 | check_device_index = true; | ||
| 332 | break; | ||
| 333 | case Core::HID::NpadStyleIndex::GameCube: | ||
| 334 | device_info.type = Core::HID::VibrationDeviceType::GcErm; | ||
| 335 | break; | ||
| 336 | case Core::HID::NpadStyleIndex::N64: | ||
| 337 | device_info.type = Core::HID::VibrationDeviceType::N64; | ||
| 338 | break; | ||
| 339 | default: | ||
| 340 | device_info.type = Core::HID::VibrationDeviceType::Unknown; | ||
| 341 | break; | ||
| 342 | } | ||
| 343 | |||
| 344 | device_info.position = Core::HID::VibrationDevicePosition::None; | ||
| 345 | if (check_device_index) { | ||
| 346 | switch (handle.device_index) { | ||
| 347 | case Core::HID::DeviceIndex::Left: | ||
| 348 | device_info.position = Core::HID::VibrationDevicePosition::Left; | ||
| 349 | break; | ||
| 350 | case Core::HID::DeviceIndex::Right: | ||
| 351 | device_info.position = Core::HID::VibrationDevicePosition::Right; | ||
| 352 | break; | ||
| 353 | case Core::HID::DeviceIndex::None: | ||
| 354 | default: | ||
| 355 | ASSERT_MSG(false, "DeviceIndex should never be None!"); | ||
| 356 | break; | ||
| 357 | } | ||
| 358 | } | ||
| 359 | return ResultSuccess; | ||
| 360 | } | ||
| 361 | |||
| 362 | Result ResourceManager::SendVibrationValue(u64 aruid, | ||
| 363 | const Core::HID::VibrationDeviceHandle& handle, | ||
| 364 | const Core::HID::VibrationValue& value) { | ||
| 365 | bool has_active_aruid{}; | ||
| 366 | NpadVibrationDevice* device{nullptr}; | ||
| 367 | Result result = IsVibrationAruidActive(aruid, has_active_aruid); | ||
| 368 | |||
| 369 | if (result.IsSuccess() && has_active_aruid) { | ||
| 370 | result = IsVibrationHandleValid(handle); | ||
| 371 | } | ||
| 372 | if (result.IsSuccess() && has_active_aruid) { | ||
| 373 | device = GetNSVibrationDevice(handle); | ||
| 374 | } | ||
| 375 | if (device != nullptr) { | ||
| 376 | result = device->SendVibrationValue(value); | ||
| 377 | } | ||
| 378 | return result; | ||
| 379 | } | ||
| 380 | |||
| 260 | void ResourceManager::UpdateControllers(std::chrono::nanoseconds ns_late) { | 381 | void ResourceManager::UpdateControllers(std::chrono::nanoseconds ns_late) { |
| 261 | auto& core_timing = system.CoreTiming(); | 382 | auto& core_timing = system.CoreTiming(); |
| 262 | debug_pad->OnUpdate(core_timing); | 383 | debug_pad->OnUpdate(core_timing); |
diff --git a/src/hid_core/resource_manager.h b/src/hid_core/resource_manager.h index 7a21d8eb8..128e00125 100644 --- a/src/hid_core/resource_manager.h +++ b/src/hid_core/resource_manager.h | |||
| @@ -10,6 +10,12 @@ namespace Core { | |||
| 10 | class System; | 10 | class System; |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | namespace Core::HID { | ||
| 14 | struct VibrationDeviceHandle; | ||
| 15 | struct VibrationValue; | ||
| 16 | struct VibrationDeviceInfo; | ||
| 17 | } // namespace Core::HID | ||
| 18 | |||
| 13 | namespace Core::Timing { | 19 | namespace Core::Timing { |
| 14 | struct EventType; | 20 | struct EventType; |
| 15 | } | 21 | } |
| @@ -37,6 +43,11 @@ class SixAxis; | |||
| 37 | class SleepButton; | 43 | class SleepButton; |
| 38 | class TouchScreen; | 44 | class TouchScreen; |
| 39 | class UniquePad; | 45 | class UniquePad; |
| 46 | class NpadVibrationBase; | ||
| 47 | class NpadN64VibrationDevice; | ||
| 48 | class NpadGcVibrationDevice; | ||
| 49 | class NpadVibrationDevice; | ||
| 50 | struct HandheldConfig; | ||
| 40 | 51 | ||
| 41 | class ResourceManager { | 52 | class ResourceManager { |
| 42 | 53 | ||
| @@ -79,6 +90,18 @@ public: | |||
| 79 | void EnablePadInput(u64 aruid, bool is_enabled); | 90 | void EnablePadInput(u64 aruid, bool is_enabled); |
| 80 | void EnableTouchScreen(u64 aruid, bool is_enabled); | 91 | void EnableTouchScreen(u64 aruid, bool is_enabled); |
| 81 | 92 | ||
| 93 | NpadVibrationBase* GetVibrationDevice(const Core::HID::VibrationDeviceHandle& handle); | ||
| 94 | NpadN64VibrationDevice* GetN64VibrationDevice(const Core::HID::VibrationDeviceHandle& handle); | ||
| 95 | NpadVibrationDevice* GetNSVibrationDevice(const Core::HID::VibrationDeviceHandle& handle); | ||
| 96 | NpadGcVibrationDevice* GetGcVibrationDevice(const Core::HID::VibrationDeviceHandle& handle); | ||
| 97 | Result SetAruidValidForVibration(u64 aruid, bool is_enabled); | ||
| 98 | void SetForceHandheldStyleVibration(bool is_forced); | ||
| 99 | Result IsVibrationAruidActive(u64 aruid, bool& is_active) const; | ||
| 100 | Result GetVibrationDeviceInfo(Core::HID::VibrationDeviceInfo& device_info, | ||
| 101 | const Core::HID::VibrationDeviceHandle& handle); | ||
| 102 | Result SendVibrationValue(u64 aruid, const Core::HID::VibrationDeviceHandle& handle, | ||
| 103 | const Core::HID::VibrationValue& value); | ||
| 104 | |||
| 82 | void UpdateControllers(std::chrono::nanoseconds ns_late); | 105 | void UpdateControllers(std::chrono::nanoseconds ns_late); |
| 83 | void UpdateNpad(std::chrono::nanoseconds ns_late); | 106 | void UpdateNpad(std::chrono::nanoseconds ns_late); |
| 84 | void UpdateMouseKeyboard(std::chrono::nanoseconds ns_late); | 107 | void UpdateMouseKeyboard(std::chrono::nanoseconds ns_late); |
| @@ -113,6 +136,8 @@ private: | |||
| 113 | std::shared_ptr<TouchScreen> touch_screen = nullptr; | 136 | std::shared_ptr<TouchScreen> touch_screen = nullptr; |
| 114 | std::shared_ptr<UniquePad> unique_pad = nullptr; | 137 | std::shared_ptr<UniquePad> unique_pad = nullptr; |
| 115 | 138 | ||
| 139 | std::shared_ptr<HandheldConfig> handheld_config = nullptr; | ||
| 140 | |||
| 116 | // TODO: Create these resources | 141 | // TODO: Create these resources |
| 117 | // std::shared_ptr<AudioControl> audio_control = nullptr; | 142 | // std::shared_ptr<AudioControl> audio_control = nullptr; |
| 118 | // std::shared_ptr<ButtonConfig> button_config = nullptr; | 143 | // std::shared_ptr<ButtonConfig> button_config = nullptr; |
diff --git a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp index d4e4181bf..e399edfd7 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp | |||
| @@ -115,7 +115,7 @@ Result NpadAbstractIrSensorHandler::GetXcdHandleForNpadWithIrSensor(u64& handle) | |||
| 115 | if (sensor_state < NpadIrSensorState::Available) { | 115 | if (sensor_state < NpadIrSensorState::Available) { |
| 116 | return ResultIrSensorIsNotReady; | 116 | return ResultIrSensorIsNotReady; |
| 117 | } | 117 | } |
| 118 | handle = xcd_handle; | 118 | // handle = xcd_handle; |
| 119 | return ResultSuccess; | 119 | return ResultSuccess; |
| 120 | } | 120 | } |
| 121 | 121 | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h index fe8e005af..997811511 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h | |||
| @@ -7,6 +7,10 @@ | |||
| 7 | #include "core/hle/result.h" | 7 | #include "core/hle/result.h" |
| 8 | #include "hid_core/hid_types.h" | 8 | #include "hid_core/hid_types.h" |
| 9 | 9 | ||
| 10 | namespace Core::HID { | ||
| 11 | class EmulatedController; | ||
| 12 | } | ||
| 13 | |||
| 10 | namespace Kernel { | 14 | namespace Kernel { |
| 11 | class KEvent; | 15 | class KEvent; |
| 12 | class KReadableEvent; | 16 | class KReadableEvent; |
| @@ -50,7 +54,7 @@ private: | |||
| 50 | 54 | ||
| 51 | s32 ref_counter{}; | 55 | s32 ref_counter{}; |
| 52 | Kernel::KEvent* ir_sensor_event{nullptr}; | 56 | Kernel::KEvent* ir_sensor_event{nullptr}; |
| 53 | u64 xcd_handle{}; | 57 | Core::HID::EmulatedController* xcd_handle{}; |
| 54 | NpadIrSensorState sensor_state{}; | 58 | NpadIrSensorState sensor_state{}; |
| 55 | }; | 59 | }; |
| 56 | } // namespace Service::HID | 60 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/abstracted_pad/abstract_pad.cpp b/src/hid_core/resources/abstracted_pad/abstract_pad.cpp index 2c7691d7c..435b095f0 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_pad.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_pad.cpp | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #include "hid_core/hid_core.h" | ||
| 4 | #include "hid_core/hid_result.h" | 5 | #include "hid_core/hid_result.h" |
| 5 | #include "hid_core/resources/abstracted_pad/abstract_pad.h" | 6 | #include "hid_core/resources/abstracted_pad/abstract_pad.h" |
| 6 | #include "hid_core/resources/applet_resource.h" | 7 | #include "hid_core/resources/applet_resource.h" |
| @@ -16,7 +17,7 @@ void AbstractPad::SetExternals(AppletResourceHolder* applet_resource, | |||
| 16 | CaptureButtonResource* capture_button_resource, | 17 | CaptureButtonResource* capture_button_resource, |
| 17 | HomeButtonResource* home_button_resource, | 18 | HomeButtonResource* home_button_resource, |
| 18 | SixAxisResource* sixaxis_resource, PalmaResource* palma_resource, | 19 | SixAxisResource* sixaxis_resource, PalmaResource* palma_resource, |
| 19 | VibrationHandler* vibration) { | 20 | NpadVibration* vibration, Core::HID::HIDCore* core) { |
| 20 | applet_resource_holder = applet_resource; | 21 | applet_resource_holder = applet_resource; |
| 21 | 22 | ||
| 22 | properties_handler.SetAppletResource(applet_resource_holder); | 23 | properties_handler.SetAppletResource(applet_resource_holder); |
| @@ -35,13 +36,14 @@ void AbstractPad::SetExternals(AppletResourceHolder* applet_resource, | |||
| 35 | mcu_handler.SetAbstractPadHolder(&abstract_pad_holder); | 36 | mcu_handler.SetAbstractPadHolder(&abstract_pad_holder); |
| 36 | mcu_handler.SetPropertiesHandler(&properties_handler); | 37 | mcu_handler.SetPropertiesHandler(&properties_handler); |
| 37 | 38 | ||
| 38 | std::array<NpadVibrationDevice*, 2> vibration_devices{&vibration_left, &vibration_right}; | ||
| 39 | vibration_handler.SetAppletResource(applet_resource_holder); | 39 | vibration_handler.SetAppletResource(applet_resource_holder); |
| 40 | vibration_handler.SetAbstractPadHolder(&abstract_pad_holder); | 40 | vibration_handler.SetAbstractPadHolder(&abstract_pad_holder); |
| 41 | vibration_handler.SetPropertiesHandler(&properties_handler); | 41 | vibration_handler.SetPropertiesHandler(&properties_handler); |
| 42 | vibration_handler.SetN64Vibration(&vibration_n64); | 42 | vibration_handler.SetN64Vibration(&vibration_n64); |
| 43 | vibration_handler.SetVibration(vibration_devices); | 43 | vibration_handler.SetVibration(&vibration_left, &vibration_right); |
| 44 | vibration_handler.SetGcVibration(&vibration_gc); | 44 | vibration_handler.SetGcVibration(&vibration_gc); |
| 45 | vibration_handler.SetVibrationHandler(vibration); | ||
| 46 | vibration_handler.SetHidCore(core); | ||
| 45 | 47 | ||
| 46 | sixaxis_handler.SetAppletResource(applet_resource_holder); | 48 | sixaxis_handler.SetAppletResource(applet_resource_holder); |
| 47 | sixaxis_handler.SetAbstractPadHolder(&abstract_pad_holder); | 49 | sixaxis_handler.SetAbstractPadHolder(&abstract_pad_holder); |
| @@ -239,11 +241,6 @@ NpadVibrationDevice* AbstractPad::GetVibrationDevice(Core::HID::DeviceIndex devi | |||
| 239 | return &vibration_left; | 241 | return &vibration_left; |
| 240 | } | 242 | } |
| 241 | 243 | ||
| 242 | void AbstractPad::GetLeftRightVibrationDevice(std::vector<NpadVibrationDevice*> list) { | ||
| 243 | list.emplace_back(&vibration_left); | ||
| 244 | list.emplace_back(&vibration_right); | ||
| 245 | } | ||
| 246 | |||
| 247 | NpadGcVibrationDevice* AbstractPad::GetGCVibrationDevice() { | 244 | NpadGcVibrationDevice* AbstractPad::GetGCVibrationDevice() { |
| 248 | return &vibration_gc; | 245 | return &vibration_gc; |
| 249 | } | 246 | } |
diff --git a/src/hid_core/resources/abstracted_pad/abstract_pad.h b/src/hid_core/resources/abstracted_pad/abstract_pad.h index cbdf84af7..329792457 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_pad.h +++ b/src/hid_core/resources/abstracted_pad/abstract_pad.h | |||
| @@ -32,7 +32,6 @@ class AppletResource; | |||
| 32 | class SixAxisResource; | 32 | class SixAxisResource; |
| 33 | class PalmaResource; | 33 | class PalmaResource; |
| 34 | class NPadResource; | 34 | class NPadResource; |
| 35 | class AbstractPad; | ||
| 36 | class NpadLastActiveHandler; | 35 | class NpadLastActiveHandler; |
| 37 | class NpadIrNfcHandler; | 36 | class NpadIrNfcHandler; |
| 38 | class UniquePads; | 37 | class UniquePads; |
| @@ -44,7 +43,6 @@ class NpadGcVibration; | |||
| 44 | 43 | ||
| 45 | class CaptureButtonResource; | 44 | class CaptureButtonResource; |
| 46 | class HomeButtonResource; | 45 | class HomeButtonResource; |
| 47 | class VibrationHandler; | ||
| 48 | 46 | ||
| 49 | struct HandheldConfig; | 47 | struct HandheldConfig; |
| 50 | 48 | ||
| @@ -57,7 +55,8 @@ public: | |||
| 57 | void SetExternals(AppletResourceHolder* applet_resource, | 55 | void SetExternals(AppletResourceHolder* applet_resource, |
| 58 | CaptureButtonResource* capture_button_resource, | 56 | CaptureButtonResource* capture_button_resource, |
| 59 | HomeButtonResource* home_button_resource, SixAxisResource* sixaxis_resource, | 57 | HomeButtonResource* home_button_resource, SixAxisResource* sixaxis_resource, |
| 60 | PalmaResource* palma_resource, VibrationHandler* vibration); | 58 | PalmaResource* palma_resource, NpadVibration* vibration, |
| 59 | Core::HID::HIDCore* core); | ||
| 61 | void SetNpadId(Core::HID::NpadIdType npad_id); | 60 | void SetNpadId(Core::HID::NpadIdType npad_id); |
| 62 | 61 | ||
| 63 | Result Activate(); | 62 | Result Activate(); |
| @@ -78,7 +77,6 @@ public: | |||
| 78 | 77 | ||
| 79 | NpadN64VibrationDevice* GetN64VibrationDevice(); | 78 | NpadN64VibrationDevice* GetN64VibrationDevice(); |
| 80 | NpadVibrationDevice* GetVibrationDevice(Core::HID::DeviceIndex device_index); | 79 | NpadVibrationDevice* GetVibrationDevice(Core::HID::DeviceIndex device_index); |
| 81 | void GetLeftRightVibrationDevice(std::vector<NpadVibrationDevice*> list); | ||
| 82 | NpadGcVibrationDevice* GetGCVibrationDevice(); | 80 | NpadGcVibrationDevice* GetGCVibrationDevice(); |
| 83 | 81 | ||
| 84 | Core::HID::NpadIdType GetLastActiveNpad(); | 82 | Core::HID::NpadIdType GetLastActiveNpad(); |
diff --git a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp index a00d6c9de..ca64b0a43 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #include "hid_core/frontend/emulated_controller.h" | ||
| 5 | #include "hid_core/hid_core.h" | ||
| 4 | #include "hid_core/hid_result.h" | 6 | #include "hid_core/hid_result.h" |
| 5 | #include "hid_core/hid_util.h" | 7 | #include "hid_core/hid_util.h" |
| 6 | #include "hid_core/resources/abstracted_pad/abstract_pad_holder.h" | 8 | #include "hid_core/resources/abstracted_pad/abstract_pad_holder.h" |
| @@ -30,14 +32,22 @@ void NpadAbstractVibrationHandler::SetPropertiesHandler(NpadAbstractPropertiesHa | |||
| 30 | properties_handler = handler; | 32 | properties_handler = handler; |
| 31 | } | 33 | } |
| 32 | 34 | ||
| 35 | void NpadAbstractVibrationHandler::SetVibrationHandler(NpadVibration* handler) { | ||
| 36 | vibration_handler = handler; | ||
| 37 | } | ||
| 38 | |||
| 39 | void NpadAbstractVibrationHandler::SetHidCore(Core::HID::HIDCore* core) { | ||
| 40 | hid_core = core; | ||
| 41 | } | ||
| 42 | |||
| 33 | void NpadAbstractVibrationHandler::SetN64Vibration(NpadN64VibrationDevice* n64_device) { | 43 | void NpadAbstractVibrationHandler::SetN64Vibration(NpadN64VibrationDevice* n64_device) { |
| 34 | n64_vibration_device = n64_device; | 44 | n64_vibration_device = n64_device; |
| 35 | } | 45 | } |
| 36 | 46 | ||
| 37 | void NpadAbstractVibrationHandler::SetVibration(std::span<NpadVibrationDevice*> device) { | 47 | void NpadAbstractVibrationHandler::SetVibration(NpadVibrationDevice* left_device, |
| 38 | for (std::size_t i = 0; i < device.size() && i < vibration_device.size(); i++) { | 48 | NpadVibrationDevice* right_device) { |
| 39 | vibration_device[i] = device[i]; | 49 | left_vibration_device = left_device; |
| 40 | } | 50 | right_vibration_device = right_device; |
| 41 | } | 51 | } |
| 42 | 52 | ||
| 43 | void NpadAbstractVibrationHandler::SetGcVibration(NpadGcVibrationDevice* gc_device) { | 53 | void NpadAbstractVibrationHandler::SetGcVibration(NpadGcVibrationDevice* gc_device) { |
| @@ -69,5 +79,29 @@ void NpadAbstractVibrationHandler::UpdateVibrationState() { | |||
| 69 | if (!is_handheld_hid_enabled && is_force_handheld_style_vibration) { | 79 | if (!is_handheld_hid_enabled && is_force_handheld_style_vibration) { |
| 70 | // TODO | 80 | // TODO |
| 71 | } | 81 | } |
| 82 | |||
| 83 | // TODO: This function isn't accurate. It's supposed to get 5 abstracted pads from the | ||
| 84 | // NpadAbstractPropertiesHandler but this handler isn't fully implemented yet | ||
| 85 | IAbstractedPad abstracted_pad{}; | ||
| 86 | const auto npad_id = properties_handler->GetNpadId(); | ||
| 87 | abstracted_pad.xcd_handle = hid_core->GetEmulatedController(npad_id); | ||
| 88 | abstracted_pad.internal_flags.is_connected.Assign(abstracted_pad.xcd_handle->IsConnected()); | ||
| 89 | |||
| 90 | if (abstracted_pad.internal_flags.is_connected) { | ||
| 91 | left_vibration_device->Mount(abstracted_pad, Core::HID::DeviceIndex::Left, | ||
| 92 | vibration_handler); | ||
| 93 | right_vibration_device->Mount(abstracted_pad, Core::HID::DeviceIndex::Right, | ||
| 94 | vibration_handler); | ||
| 95 | gc_vibration_device->Mount(abstracted_pad, 0, vibration_handler); | ||
| 96 | gc_vibration_device->Mount(abstracted_pad, 0, vibration_handler); | ||
| 97 | n64_vibration_device->Mount(abstracted_pad, vibration_handler); | ||
| 98 | return; | ||
| 99 | } | ||
| 100 | |||
| 101 | left_vibration_device->Unmount(); | ||
| 102 | right_vibration_device->Unmount(); | ||
| 103 | gc_vibration_device->Unmount(); | ||
| 104 | gc_vibration_device->Unmount(); | ||
| 105 | n64_vibration_device->Unmount(); | ||
| 72 | } | 106 | } |
| 73 | } // namespace Service::HID | 107 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h index aeb07ce86..8bc8129c2 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h | |||
| @@ -9,6 +9,10 @@ | |||
| 9 | #include "core/hle/result.h" | 9 | #include "core/hle/result.h" |
| 10 | #include "hid_core/hid_types.h" | 10 | #include "hid_core/hid_types.h" |
| 11 | 11 | ||
| 12 | namespace Core::HID { | ||
| 13 | class HIDCore; | ||
| 14 | } | ||
| 15 | |||
| 12 | namespace Service::HID { | 16 | namespace Service::HID { |
| 13 | struct AppletResourceHolder; | 17 | struct AppletResourceHolder; |
| 14 | class NpadAbstractedPadHolder; | 18 | class NpadAbstractedPadHolder; |
| @@ -27,9 +31,11 @@ public: | |||
| 27 | void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); | 31 | void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); |
| 28 | void SetAppletResource(AppletResourceHolder* applet_resource); | 32 | void SetAppletResource(AppletResourceHolder* applet_resource); |
| 29 | void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); | 33 | void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); |
| 34 | void SetVibrationHandler(NpadVibration* handler); | ||
| 35 | void SetHidCore(Core::HID::HIDCore* core); | ||
| 30 | 36 | ||
| 31 | void SetN64Vibration(NpadN64VibrationDevice* n64_device); | 37 | void SetN64Vibration(NpadN64VibrationDevice* n64_device); |
| 32 | void SetVibration(std::span<NpadVibrationDevice*> device); | 38 | void SetVibration(NpadVibrationDevice* left_device, NpadVibrationDevice* right_device); |
| 33 | void SetGcVibration(NpadGcVibrationDevice* gc_device); | 39 | void SetGcVibration(NpadGcVibrationDevice* gc_device); |
| 34 | 40 | ||
| 35 | Result IncrementRefCounter(); | 41 | Result IncrementRefCounter(); |
| @@ -41,9 +47,11 @@ private: | |||
| 41 | AppletResourceHolder* applet_resource_holder{nullptr}; | 47 | AppletResourceHolder* applet_resource_holder{nullptr}; |
| 42 | NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; | 48 | NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; |
| 43 | NpadAbstractPropertiesHandler* properties_handler{nullptr}; | 49 | NpadAbstractPropertiesHandler* properties_handler{nullptr}; |
| 50 | Core::HID::HIDCore* hid_core{nullptr}; | ||
| 44 | 51 | ||
| 45 | NpadN64VibrationDevice* n64_vibration_device{nullptr}; | 52 | NpadN64VibrationDevice* n64_vibration_device{nullptr}; |
| 46 | std::array<NpadVibrationDevice*, 2> vibration_device{}; | 53 | NpadVibrationDevice* left_vibration_device{}; |
| 54 | NpadVibrationDevice* right_vibration_device{}; | ||
| 47 | NpadGcVibrationDevice* gc_vibration_device{nullptr}; | 55 | NpadGcVibrationDevice* gc_vibration_device{nullptr}; |
| 48 | NpadVibration* vibration_handler{nullptr}; | 56 | NpadVibration* vibration_handler{nullptr}; |
| 49 | s32 ref_counter{}; | 57 | s32 ref_counter{}; |
diff --git a/src/hid_core/resources/applet_resource.cpp b/src/hid_core/resources/applet_resource.cpp index a84826050..db4134037 100644 --- a/src/hid_core/resources/applet_resource.cpp +++ b/src/hid_core/resources/applet_resource.cpp | |||
| @@ -200,6 +200,25 @@ void AppletResource::EnableInput(u64 aruid, bool is_enabled) { | |||
| 200 | data[index].flag.enable_touchscreen.Assign(is_enabled); | 200 | data[index].flag.enable_touchscreen.Assign(is_enabled); |
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | bool AppletResource::SetAruidValidForVibration(u64 aruid, bool is_enabled) { | ||
| 204 | const u64 index = GetIndexFromAruid(aruid); | ||
| 205 | if (index >= AruidIndexMax) { | ||
| 206 | return false; | ||
| 207 | } | ||
| 208 | |||
| 209 | if (!is_enabled && aruid == active_vibration_aruid) { | ||
| 210 | active_vibration_aruid = SystemAruid; | ||
| 211 | return true; | ||
| 212 | } | ||
| 213 | |||
| 214 | if (is_enabled && aruid != active_vibration_aruid) { | ||
| 215 | active_vibration_aruid = aruid; | ||
| 216 | return true; | ||
| 217 | } | ||
| 218 | |||
| 219 | return false; | ||
| 220 | } | ||
| 221 | |||
| 203 | void AppletResource::EnableSixAxisSensor(u64 aruid, bool is_enabled) { | 222 | void AppletResource::EnableSixAxisSensor(u64 aruid, bool is_enabled) { |
| 204 | const u64 index = GetIndexFromAruid(aruid); | 223 | const u64 index = GetIndexFromAruid(aruid); |
| 205 | if (index >= AruidIndexMax) { | 224 | if (index >= AruidIndexMax) { |
diff --git a/src/hid_core/resources/applet_resource.h b/src/hid_core/resources/applet_resource.h index f3f32bac1..e9710d306 100644 --- a/src/hid_core/resources/applet_resource.h +++ b/src/hid_core/resources/applet_resource.h | |||
| @@ -101,6 +101,7 @@ public: | |||
| 101 | Result DestroySevenSixAxisTransferMemory(); | 101 | Result DestroySevenSixAxisTransferMemory(); |
| 102 | 102 | ||
| 103 | void EnableInput(u64 aruid, bool is_enabled); | 103 | void EnableInput(u64 aruid, bool is_enabled); |
| 104 | bool SetAruidValidForVibration(u64 aruid, bool is_enabled); | ||
| 104 | void EnableSixAxisSensor(u64 aruid, bool is_enabled); | 105 | void EnableSixAxisSensor(u64 aruid, bool is_enabled); |
| 105 | void EnablePadInput(u64 aruid, bool is_enabled); | 106 | void EnablePadInput(u64 aruid, bool is_enabled); |
| 106 | void EnableTouchScreen(u64 aruid, bool is_enabled); | 107 | void EnableTouchScreen(u64 aruid, bool is_enabled); |
diff --git a/src/hid_core/resources/npad/npad.cpp b/src/hid_core/resources/npad/npad.cpp index de0f9cbb9..212f01429 100644 --- a/src/hid_core/resources/npad/npad.cpp +++ b/src/hid_core/resources/npad/npad.cpp | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include "hid_core/hid_util.h" | 21 | #include "hid_core/hid_util.h" |
| 22 | #include "hid_core/resources/applet_resource.h" | 22 | #include "hid_core/resources/applet_resource.h" |
| 23 | #include "hid_core/resources/npad/npad.h" | 23 | #include "hid_core/resources/npad/npad.h" |
| 24 | #include "hid_core/resources/npad/npad_vibration.h" | ||
| 24 | #include "hid_core/resources/shared_memory_format.h" | 25 | #include "hid_core/resources/shared_memory_format.h" |
| 25 | 26 | ||
| 26 | namespace Service::HID { | 27 | namespace Service::HID { |
| @@ -31,10 +32,6 @@ NPad::NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service | |||
| 31 | for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) { | 32 | for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) { |
| 32 | auto& controller = controller_data[aruid_index][i]; | 33 | auto& controller = controller_data[aruid_index][i]; |
| 33 | controller.device = hid_core.GetEmulatedControllerByIndex(i); | 34 | controller.device = hid_core.GetEmulatedControllerByIndex(i); |
| 34 | controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value = | ||
| 35 | Core::HID::DEFAULT_VIBRATION_VALUE; | ||
| 36 | controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex] | ||
| 37 | .latest_vibration_value = Core::HID::DEFAULT_VIBRATION_VALUE; | ||
| 38 | Core::HID::ControllerUpdateCallback engine_callback{ | 35 | Core::HID::ControllerUpdateCallback engine_callback{ |
| 39 | .on_change = | 36 | .on_change = |
| 40 | [this, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }, | 37 | [this, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }, |
| @@ -43,6 +40,10 @@ NPad::NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service | |||
| 43 | controller.callback_key = controller.device->SetCallback(engine_callback); | 40 | controller.callback_key = controller.device->SetCallback(engine_callback); |
| 44 | } | 41 | } |
| 45 | } | 42 | } |
| 43 | for (std::size_t i = 0; i < abstracted_pads.size(); ++i) { | ||
| 44 | abstracted_pads[i] = AbstractPad{}; | ||
| 45 | abstracted_pads[i].SetNpadId(IndexToNpadIdType(i)); | ||
| 46 | } | ||
| 46 | } | 47 | } |
| 47 | 48 | ||
| 48 | NPad::~NPad() { | 49 | NPad::~NPad() { |
| @@ -359,6 +360,7 @@ void NPad::InitNewlyAddedController(u64 aruid, Core::HID::NpadIdType npad_id) { | |||
| 359 | npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id); | 360 | npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id); |
| 360 | WriteEmptyEntry(controller.shared_memory); | 361 | WriteEmptyEntry(controller.shared_memory); |
| 361 | hid_core.SetLastActiveController(npad_id); | 362 | hid_core.SetLastActiveController(npad_id); |
| 363 | abstracted_pads[NpadIdTypeToIndex(npad_id)].Update(); | ||
| 362 | } | 364 | } |
| 363 | 365 | ||
| 364 | void NPad::WriteEmptyEntry(NpadInternalState* npad) { | 366 | void NPad::WriteEmptyEntry(NpadInternalState* npad) { |
| @@ -740,171 +742,6 @@ bool NPad::SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID: | |||
| 740 | return true; | 742 | return true; |
| 741 | } | 743 | } |
| 742 | 744 | ||
| 743 | bool NPad::VibrateControllerAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 744 | std::size_t device_index, | ||
| 745 | const Core::HID::VibrationValue& vibration_value) { | ||
| 746 | auto& controller = GetControllerFromNpadIdType(aruid, npad_id); | ||
| 747 | if (!controller.device->IsConnected()) { | ||
| 748 | return false; | ||
| 749 | } | ||
| 750 | |||
| 751 | if (!controller.device->IsVibrationEnabled(device_index)) { | ||
| 752 | if (controller.vibration[device_index].latest_vibration_value.low_amplitude != 0.0f || | ||
| 753 | controller.vibration[device_index].latest_vibration_value.high_amplitude != 0.0f) { | ||
| 754 | // Send an empty vibration to stop any vibrations. | ||
| 755 | Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f}; | ||
| 756 | controller.device->SetVibration(device_index, vibration); | ||
| 757 | // Then reset the vibration value to its default value. | ||
| 758 | controller.vibration[device_index].latest_vibration_value = | ||
| 759 | Core::HID::DEFAULT_VIBRATION_VALUE; | ||
| 760 | } | ||
| 761 | |||
| 762 | return false; | ||
| 763 | } | ||
| 764 | |||
| 765 | if (!Settings::values.enable_accurate_vibrations.GetValue()) { | ||
| 766 | using std::chrono::duration_cast; | ||
| 767 | using std::chrono::milliseconds; | ||
| 768 | using std::chrono::steady_clock; | ||
| 769 | |||
| 770 | const auto now = steady_clock::now(); | ||
| 771 | |||
| 772 | // Filter out non-zero vibrations that are within 15ms of each other. | ||
| 773 | if ((vibration_value.low_amplitude != 0.0f || vibration_value.high_amplitude != 0.0f) && | ||
| 774 | duration_cast<milliseconds>( | ||
| 775 | now - controller.vibration[device_index].last_vibration_timepoint) < | ||
| 776 | milliseconds(15)) { | ||
| 777 | return false; | ||
| 778 | } | ||
| 779 | |||
| 780 | controller.vibration[device_index].last_vibration_timepoint = now; | ||
| 781 | } | ||
| 782 | |||
| 783 | Core::HID::VibrationValue vibration{ | ||
| 784 | vibration_value.low_amplitude, vibration_value.low_frequency, | ||
| 785 | vibration_value.high_amplitude, vibration_value.high_frequency}; | ||
| 786 | return controller.device->SetVibration(device_index, vibration); | ||
| 787 | } | ||
| 788 | |||
| 789 | void NPad::VibrateController(u64 aruid, | ||
| 790 | const Core::HID::VibrationDeviceHandle& vibration_device_handle, | ||
| 791 | const Core::HID::VibrationValue& vibration_value) { | ||
| 792 | if (IsVibrationHandleValid(vibration_device_handle).IsError()) { | ||
| 793 | return; | ||
| 794 | } | ||
| 795 | |||
| 796 | if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { | ||
| 797 | return; | ||
| 798 | } | ||
| 799 | |||
| 800 | auto& controller = GetControllerFromHandle(aruid, vibration_device_handle); | ||
| 801 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 802 | |||
| 803 | if (!controller.vibration[device_index].device_mounted || !controller.device->IsConnected()) { | ||
| 804 | return; | ||
| 805 | } | ||
| 806 | |||
| 807 | if (vibration_device_handle.device_index == Core::HID::DeviceIndex::None) { | ||
| 808 | ASSERT_MSG(false, "DeviceIndex should never be None!"); | ||
| 809 | return; | ||
| 810 | } | ||
| 811 | |||
| 812 | // Some games try to send mismatched parameters in the device handle, block these. | ||
| 813 | if ((controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft && | ||
| 814 | (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconRight || | ||
| 815 | vibration_device_handle.device_index == Core::HID::DeviceIndex::Right)) || | ||
| 816 | (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight && | ||
| 817 | (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconLeft || | ||
| 818 | vibration_device_handle.device_index == Core::HID::DeviceIndex::Left))) { | ||
| 819 | return; | ||
| 820 | } | ||
| 821 | |||
| 822 | // Filter out vibrations with equivalent values to reduce unnecessary state changes. | ||
| 823 | if (vibration_value.low_amplitude == | ||
| 824 | controller.vibration[device_index].latest_vibration_value.low_amplitude && | ||
| 825 | vibration_value.high_amplitude == | ||
| 826 | controller.vibration[device_index].latest_vibration_value.high_amplitude) { | ||
| 827 | return; | ||
| 828 | } | ||
| 829 | |||
| 830 | if (VibrateControllerAtIndex(aruid, controller.device->GetNpadIdType(), device_index, | ||
| 831 | vibration_value)) { | ||
| 832 | controller.vibration[device_index].latest_vibration_value = vibration_value; | ||
| 833 | } | ||
| 834 | } | ||
| 835 | |||
| 836 | void NPad::VibrateControllers( | ||
| 837 | u64 aruid, std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles, | ||
| 838 | std::span<const Core::HID::VibrationValue> vibration_values) { | ||
| 839 | if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { | ||
| 840 | return; | ||
| 841 | } | ||
| 842 | |||
| 843 | ASSERT_OR_EXECUTE_MSG( | ||
| 844 | vibration_device_handles.size() == vibration_values.size(), { return; }, | ||
| 845 | "The amount of device handles does not match with the amount of vibration values," | ||
| 846 | "this is undefined behavior!"); | ||
| 847 | |||
| 848 | for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) { | ||
| 849 | VibrateController(aruid, vibration_device_handles[i], vibration_values[i]); | ||
| 850 | } | ||
| 851 | } | ||
| 852 | |||
| 853 | Core::HID::VibrationValue NPad::GetLastVibration( | ||
| 854 | u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const { | ||
| 855 | if (IsVibrationHandleValid(vibration_device_handle).IsError()) { | ||
| 856 | return {}; | ||
| 857 | } | ||
| 858 | |||
| 859 | const auto& controller = GetControllerFromHandle(aruid, vibration_device_handle); | ||
| 860 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 861 | return controller.vibration[device_index].latest_vibration_value; | ||
| 862 | } | ||
| 863 | |||
| 864 | void NPad::InitializeVibrationDevice( | ||
| 865 | const Core::HID::VibrationDeviceHandle& vibration_device_handle) { | ||
| 866 | if (IsVibrationHandleValid(vibration_device_handle).IsError()) { | ||
| 867 | return; | ||
| 868 | } | ||
| 869 | |||
| 870 | const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid(); | ||
| 871 | const auto npad_index = static_cast<Core::HID::NpadIdType>(vibration_device_handle.npad_id); | ||
| 872 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 873 | |||
| 874 | if (aruid == 0) { | ||
| 875 | return; | ||
| 876 | } | ||
| 877 | |||
| 878 | InitializeVibrationDeviceAtIndex(aruid, npad_index, device_index); | ||
| 879 | } | ||
| 880 | |||
| 881 | void NPad::InitializeVibrationDeviceAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 882 | std::size_t device_index) { | ||
| 883 | auto& controller = GetControllerFromNpadIdType(aruid, npad_id); | ||
| 884 | if (!Settings::values.vibration_enabled.GetValue()) { | ||
| 885 | controller.vibration[device_index].device_mounted = false; | ||
| 886 | return; | ||
| 887 | } | ||
| 888 | |||
| 889 | controller.vibration[device_index].device_mounted = | ||
| 890 | controller.device->IsVibrationEnabled(device_index); | ||
| 891 | } | ||
| 892 | |||
| 893 | void NPad::SetPermitVibrationSession(bool permit_vibration_session) { | ||
| 894 | permit_vibration_session_enabled = permit_vibration_session; | ||
| 895 | } | ||
| 896 | |||
| 897 | bool NPad::IsVibrationDeviceMounted( | ||
| 898 | u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const { | ||
| 899 | if (IsVibrationHandleValid(vibration_device_handle).IsError()) { | ||
| 900 | return false; | ||
| 901 | } | ||
| 902 | |||
| 903 | const auto& controller = GetControllerFromHandle(aruid, vibration_device_handle); | ||
| 904 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 905 | return controller.vibration[device_index].device_mounted; | ||
| 906 | } | ||
| 907 | |||
| 908 | Result NPad::AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, | 745 | Result NPad::AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, |
| 909 | Core::HID::NpadIdType npad_id) { | 746 | Core::HID::NpadIdType npad_id) { |
| 910 | std::scoped_lock lock{mutex}; | 747 | std::scoped_lock lock{mutex}; |
| @@ -936,11 +773,6 @@ Result NPad::DisconnectNpad(u64 aruid, Core::HID::NpadIdType npad_id) { | |||
| 936 | 773 | ||
| 937 | LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id); | 774 | LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id); |
| 938 | auto& controller = GetControllerFromNpadIdType(aruid, npad_id); | 775 | auto& controller = GetControllerFromNpadIdType(aruid, npad_id); |
| 939 | for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) { | ||
| 940 | // Send an empty vibration to stop any vibrations. | ||
| 941 | VibrateControllerAtIndex(aruid, npad_id, device_idx, {}); | ||
| 942 | controller.vibration[device_idx].device_mounted = false; | ||
| 943 | } | ||
| 944 | 776 | ||
| 945 | auto* shared_memory = controller.shared_memory; | 777 | auto* shared_memory = controller.shared_memory; |
| 946 | // Don't reset shared_memory->assignment_mode this value is persistent | 778 | // Don't reset shared_memory->assignment_mode this value is persistent |
| @@ -1243,22 +1075,17 @@ void NPad::UnregisterAppletResourceUserId(u64 aruid) { | |||
| 1243 | } | 1075 | } |
| 1244 | 1076 | ||
| 1245 | void NPad::SetNpadExternals(std::shared_ptr<AppletResource> resource, | 1077 | void NPad::SetNpadExternals(std::shared_ptr<AppletResource> resource, |
| 1246 | std::recursive_mutex* shared_mutex) { | 1078 | std::recursive_mutex* shared_mutex, |
| 1079 | std::shared_ptr<HandheldConfig> handheld_config) { | ||
| 1247 | applet_resource_holder.applet_resource = resource; | 1080 | applet_resource_holder.applet_resource = resource; |
| 1248 | applet_resource_holder.shared_mutex = shared_mutex; | 1081 | applet_resource_holder.shared_mutex = shared_mutex; |
| 1249 | applet_resource_holder.shared_npad_resource = &npad_resource; | 1082 | applet_resource_holder.shared_npad_resource = &npad_resource; |
| 1250 | } | 1083 | applet_resource_holder.handheld_config = handheld_config; |
| 1251 | 1084 | ||
| 1252 | NPad::NpadControllerData& NPad::GetControllerFromHandle( | 1085 | for (auto& abstract_pad : abstracted_pads) { |
| 1253 | u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) { | 1086 | abstract_pad.SetExternals(&applet_resource_holder, nullptr, nullptr, nullptr, nullptr, |
| 1254 | const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); | 1087 | &vibration_handler, &hid_core); |
| 1255 | return GetControllerFromNpadIdType(aruid, npad_id); | 1088 | } |
| 1256 | } | ||
| 1257 | |||
| 1258 | const NPad::NpadControllerData& NPad::GetControllerFromHandle( | ||
| 1259 | u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) const { | ||
| 1260 | const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); | ||
| 1261 | return GetControllerFromNpadIdType(aruid, npad_id); | ||
| 1262 | } | 1089 | } |
| 1263 | 1090 | ||
| 1264 | NPad::NpadControllerData& NPad::GetControllerFromHandle( | 1091 | NPad::NpadControllerData& NPad::GetControllerFromHandle( |
| @@ -1396,4 +1223,97 @@ Result NPad::GetLastActiveNpad(Core::HID::NpadIdType& out_npad_id) const { | |||
| 1396 | return ResultSuccess; | 1223 | return ResultSuccess; |
| 1397 | } | 1224 | } |
| 1398 | 1225 | ||
| 1226 | NpadVibration* NPad::GetVibrationHandler() { | ||
| 1227 | return &vibration_handler; | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | std::vector<NpadVibrationBase*> NPad::GetAllVibrationDevices() { | ||
| 1231 | std::vector<NpadVibrationBase*> vibration_devices; | ||
| 1232 | |||
| 1233 | for (auto& abstract_pad : abstracted_pads) { | ||
| 1234 | auto* left_device = abstract_pad.GetVibrationDevice(Core::HID::DeviceIndex::Left); | ||
| 1235 | auto* right_device = abstract_pad.GetVibrationDevice(Core::HID::DeviceIndex::Right); | ||
| 1236 | auto* n64_device = abstract_pad.GetGCVibrationDevice(); | ||
| 1237 | auto* gc_device = abstract_pad.GetGCVibrationDevice(); | ||
| 1238 | |||
| 1239 | if (left_device != nullptr) { | ||
| 1240 | vibration_devices.emplace_back(left_device); | ||
| 1241 | } | ||
| 1242 | if (right_device != nullptr) { | ||
| 1243 | vibration_devices.emplace_back(right_device); | ||
| 1244 | } | ||
| 1245 | if (n64_device != nullptr) { | ||
| 1246 | vibration_devices.emplace_back(n64_device); | ||
| 1247 | } | ||
| 1248 | if (gc_device != nullptr) { | ||
| 1249 | vibration_devices.emplace_back(gc_device); | ||
| 1250 | } | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | return vibration_devices; | ||
| 1254 | } | ||
| 1255 | |||
| 1256 | NpadVibrationBase* NPad::GetVibrationDevice(const Core::HID::VibrationDeviceHandle& handle) { | ||
| 1257 | if (IsVibrationHandleValid(handle).IsError()) { | ||
| 1258 | return nullptr; | ||
| 1259 | } | ||
| 1260 | |||
| 1261 | const auto npad_index = NpadIdTypeToIndex(static_cast<Core::HID::NpadIdType>(handle.npad_id)); | ||
| 1262 | const auto style_inde = static_cast<Core::HID::NpadStyleIndex>(handle.npad_type); | ||
| 1263 | if (style_inde == Core::HID::NpadStyleIndex::GameCube) { | ||
| 1264 | return abstracted_pads[npad_index].GetGCVibrationDevice(); | ||
| 1265 | } | ||
| 1266 | if (style_inde == Core::HID::NpadStyleIndex::N64) { | ||
| 1267 | return abstracted_pads[npad_index].GetN64VibrationDevice(); | ||
| 1268 | } | ||
| 1269 | return abstracted_pads[npad_index].GetVibrationDevice(handle.device_index); | ||
| 1270 | } | ||
| 1271 | |||
| 1272 | NpadN64VibrationDevice* NPad::GetN64VibrationDevice( | ||
| 1273 | const Core::HID::VibrationDeviceHandle& handle) { | ||
| 1274 | if (IsVibrationHandleValid(handle).IsError()) { | ||
| 1275 | return nullptr; | ||
| 1276 | } | ||
| 1277 | |||
| 1278 | const auto npad_index = NpadIdTypeToIndex(static_cast<Core::HID::NpadIdType>(handle.npad_id)); | ||
| 1279 | const auto style_inde = static_cast<Core::HID::NpadStyleIndex>(handle.npad_type); | ||
| 1280 | if (style_inde != Core::HID::NpadStyleIndex::N64) { | ||
| 1281 | return nullptr; | ||
| 1282 | } | ||
| 1283 | return abstracted_pads[npad_index].GetN64VibrationDevice(); | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | NpadVibrationDevice* NPad::GetNSVibrationDevice(const Core::HID::VibrationDeviceHandle& handle) { | ||
| 1287 | if (IsVibrationHandleValid(handle).IsError()) { | ||
| 1288 | return nullptr; | ||
| 1289 | } | ||
| 1290 | |||
| 1291 | const auto npad_index = NpadIdTypeToIndex(static_cast<Core::HID::NpadIdType>(handle.npad_id)); | ||
| 1292 | const auto style_inde = static_cast<Core::HID::NpadStyleIndex>(handle.npad_type); | ||
| 1293 | if (style_inde == Core::HID::NpadStyleIndex::GameCube || | ||
| 1294 | style_inde == Core::HID::NpadStyleIndex::N64) { | ||
| 1295 | return nullptr; | ||
| 1296 | } | ||
| 1297 | |||
| 1298 | return abstracted_pads[npad_index].GetVibrationDevice(handle.device_index); | ||
| 1299 | } | ||
| 1300 | |||
| 1301 | NpadGcVibrationDevice* NPad::GetGcVibrationDevice(const Core::HID::VibrationDeviceHandle& handle) { | ||
| 1302 | if (IsVibrationHandleValid(handle).IsError()) { | ||
| 1303 | return nullptr; | ||
| 1304 | } | ||
| 1305 | |||
| 1306 | const auto npad_index = NpadIdTypeToIndex(static_cast<Core::HID::NpadIdType>(handle.npad_id)); | ||
| 1307 | const auto style_inde = static_cast<Core::HID::NpadStyleIndex>(handle.npad_type); | ||
| 1308 | if (style_inde != Core::HID::NpadStyleIndex::GameCube) { | ||
| 1309 | return nullptr; | ||
| 1310 | } | ||
| 1311 | return abstracted_pads[npad_index].GetGCVibrationDevice(); | ||
| 1312 | } | ||
| 1313 | |||
| 1314 | void NPad::UpdateHandheldAbstractState() { | ||
| 1315 | std::scoped_lock lock{mutex}; | ||
| 1316 | abstracted_pads[NpadIdTypeToIndex(Core::HID::NpadIdType::Handheld)].Update(); | ||
| 1317 | } | ||
| 1318 | |||
| 1399 | } // namespace Service::HID | 1319 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/npad/npad.h b/src/hid_core/resources/npad/npad.h index 01f3dabb1..18b25c688 100644 --- a/src/hid_core/resources/npad/npad.h +++ b/src/hid_core/resources/npad/npad.h | |||
| @@ -10,9 +10,15 @@ | |||
| 10 | 10 | ||
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | #include "hid_core/hid_types.h" | 12 | #include "hid_core/hid_types.h" |
| 13 | #include "hid_core/resources/abstracted_pad/abstract_pad.h" | ||
| 13 | #include "hid_core/resources/controller_base.h" | 14 | #include "hid_core/resources/controller_base.h" |
| 14 | #include "hid_core/resources/npad/npad_resource.h" | 15 | #include "hid_core/resources/npad/npad_resource.h" |
| 15 | #include "hid_core/resources/npad/npad_types.h" | 16 | #include "hid_core/resources/npad/npad_types.h" |
| 17 | #include "hid_core/resources/npad/npad_vibration.h" | ||
| 18 | #include "hid_core/resources/vibration/gc_vibration_device.h" | ||
| 19 | #include "hid_core/resources/vibration/n64_vibration_device.h" | ||
| 20 | #include "hid_core/resources/vibration/vibration_base.h" | ||
| 21 | #include "hid_core/resources/vibration/vibration_device.h" | ||
| 16 | 22 | ||
| 17 | namespace Core::HID { | 23 | namespace Core::HID { |
| 18 | class EmulatedController; | 24 | class EmulatedController; |
| @@ -32,6 +38,7 @@ union Result; | |||
| 32 | 38 | ||
| 33 | namespace Service::HID { | 39 | namespace Service::HID { |
| 34 | class AppletResource; | 40 | class AppletResource; |
| 41 | struct HandheldConfig; | ||
| 35 | struct NpadInternalState; | 42 | struct NpadInternalState; |
| 36 | struct NpadSixAxisSensorLifo; | 43 | struct NpadSixAxisSensorLifo; |
| 37 | struct NpadSharedMemoryFormat; | 44 | struct NpadSharedMemoryFormat; |
| @@ -68,31 +75,6 @@ public: | |||
| 68 | bool SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, | 75 | bool SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, |
| 69 | NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode); | 76 | NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode); |
| 70 | 77 | ||
| 71 | bool VibrateControllerAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 72 | std::size_t device_index, | ||
| 73 | const Core::HID::VibrationValue& vibration_value); | ||
| 74 | |||
| 75 | void VibrateController(u64 aruid, | ||
| 76 | const Core::HID::VibrationDeviceHandle& vibration_device_handle, | ||
| 77 | const Core::HID::VibrationValue& vibration_value); | ||
| 78 | |||
| 79 | void VibrateControllers( | ||
| 80 | u64 aruid, std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles, | ||
| 81 | std::span<const Core::HID::VibrationValue> vibration_values); | ||
| 82 | |||
| 83 | Core::HID::VibrationValue GetLastVibration( | ||
| 84 | u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const; | ||
| 85 | |||
| 86 | void InitializeVibrationDevice(const Core::HID::VibrationDeviceHandle& vibration_device_handle); | ||
| 87 | |||
| 88 | void InitializeVibrationDeviceAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 89 | std::size_t device_index); | ||
| 90 | |||
| 91 | void SetPermitVibrationSession(bool permit_vibration_session); | ||
| 92 | |||
| 93 | bool IsVibrationDeviceMounted( | ||
| 94 | u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const; | ||
| 95 | |||
| 96 | Result AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, | 78 | Result AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, |
| 97 | Core::HID::NpadIdType npad_id); | 79 | Core::HID::NpadIdType npad_id); |
| 98 | 80 | ||
| @@ -145,7 +127,8 @@ public: | |||
| 145 | Result RegisterAppletResourceUserId(u64 aruid); | 127 | Result RegisterAppletResourceUserId(u64 aruid); |
| 146 | void UnregisterAppletResourceUserId(u64 aruid); | 128 | void UnregisterAppletResourceUserId(u64 aruid); |
| 147 | void SetNpadExternals(std::shared_ptr<AppletResource> resource, | 129 | void SetNpadExternals(std::shared_ptr<AppletResource> resource, |
| 148 | std::recursive_mutex* shared_mutex); | 130 | std::recursive_mutex* shared_mutex, |
| 131 | std::shared_ptr<HandheldConfig> handheld_config); | ||
| 149 | 132 | ||
| 150 | AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id); | 133 | AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id); |
| 151 | 134 | ||
| @@ -161,18 +144,20 @@ public: | |||
| 161 | 144 | ||
| 162 | Result GetLastActiveNpad(Core::HID::NpadIdType& out_npad_id) const; | 145 | Result GetLastActiveNpad(Core::HID::NpadIdType& out_npad_id) const; |
| 163 | 146 | ||
| 164 | private: | 147 | NpadVibration* GetVibrationHandler(); |
| 165 | struct VibrationData { | 148 | std::vector<NpadVibrationBase*> GetAllVibrationDevices(); |
| 166 | bool device_mounted{}; | 149 | NpadVibrationBase* GetVibrationDevice(const Core::HID::VibrationDeviceHandle& handle); |
| 167 | Core::HID::VibrationValue latest_vibration_value{}; | 150 | NpadN64VibrationDevice* GetN64VibrationDevice(const Core::HID::VibrationDeviceHandle& handle); |
| 168 | std::chrono::steady_clock::time_point last_vibration_timepoint{}; | 151 | NpadVibrationDevice* GetNSVibrationDevice(const Core::HID::VibrationDeviceHandle& handle); |
| 169 | }; | 152 | NpadGcVibrationDevice* GetGcVibrationDevice(const Core::HID::VibrationDeviceHandle& handle); |
| 170 | 153 | ||
| 154 | void UpdateHandheldAbstractState(); | ||
| 155 | |||
| 156 | private: | ||
| 171 | struct NpadControllerData { | 157 | struct NpadControllerData { |
| 172 | NpadInternalState* shared_memory = nullptr; | 158 | NpadInternalState* shared_memory = nullptr; |
| 173 | Core::HID::EmulatedController* device = nullptr; | 159 | Core::HID::EmulatedController* device = nullptr; |
| 174 | 160 | ||
| 175 | std::array<VibrationData, 2> vibration{}; | ||
| 176 | bool is_connected{}; | 161 | bool is_connected{}; |
| 177 | 162 | ||
| 178 | // Dual joycons can have only one side connected | 163 | // Dual joycons can have only one side connected |
| @@ -192,10 +177,6 @@ private: | |||
| 192 | void WriteEmptyEntry(NpadInternalState* npad); | 177 | void WriteEmptyEntry(NpadInternalState* npad); |
| 193 | 178 | ||
| 194 | NpadControllerData& GetControllerFromHandle( | 179 | NpadControllerData& GetControllerFromHandle( |
| 195 | u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle); | ||
| 196 | const NpadControllerData& GetControllerFromHandle( | ||
| 197 | u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) const; | ||
| 198 | NpadControllerData& GetControllerFromHandle( | ||
| 199 | u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle); | 180 | u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle); |
| 200 | const NpadControllerData& GetControllerFromHandle( | 181 | const NpadControllerData& GetControllerFromHandle( |
| 201 | u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle) const; | 182 | u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle) const; |
| @@ -215,11 +196,13 @@ private: | |||
| 215 | mutable std::mutex mutex; | 196 | mutable std::mutex mutex; |
| 216 | NPadResource npad_resource; | 197 | NPadResource npad_resource; |
| 217 | AppletResourceHolder applet_resource_holder{}; | 198 | AppletResourceHolder applet_resource_holder{}; |
| 199 | std::array<AbstractPad, MaxSupportedNpadIdTypes> abstracted_pads; | ||
| 200 | NpadVibration vibration_handler{}; | ||
| 201 | |||
| 218 | Kernel::KEvent* input_event{nullptr}; | 202 | Kernel::KEvent* input_event{nullptr}; |
| 219 | std::mutex* input_mutex{nullptr}; | 203 | std::mutex* input_mutex{nullptr}; |
| 220 | 204 | ||
| 221 | std::atomic<u64> press_state{}; | 205 | std::atomic<u64> press_state{}; |
| 222 | bool permit_vibration_session_enabled; | ||
| 223 | std::array<std::array<NpadControllerData, MaxSupportedNpadIdTypes>, AruidIndexMax> | 206 | std::array<std::array<NpadControllerData, MaxSupportedNpadIdTypes>, AruidIndexMax> |
| 224 | controller_data{}; | 207 | controller_data{}; |
| 225 | }; | 208 | }; |
diff --git a/src/hid_core/resources/npad/npad_types.h b/src/hid_core/resources/npad/npad_types.h index fd86c8e40..92700d69a 100644 --- a/src/hid_core/resources/npad/npad_types.h +++ b/src/hid_core/resources/npad/npad_types.h | |||
| @@ -8,6 +8,10 @@ | |||
| 8 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 9 | #include "hid_core/hid_types.h" | 9 | #include "hid_core/hid_types.h" |
| 10 | 10 | ||
| 11 | namespace Core::HID { | ||
| 12 | class EmulatedController; | ||
| 13 | } | ||
| 14 | |||
| 11 | namespace Service::HID { | 15 | namespace Service::HID { |
| 12 | static constexpr std::size_t MaxSupportedNpadIdTypes = 10; | 16 | static constexpr std::size_t MaxSupportedNpadIdTypes = 10; |
| 13 | static constexpr std::size_t StyleIndexCount = 7; | 17 | static constexpr std::size_t StyleIndexCount = 7; |
| @@ -348,7 +352,7 @@ struct IAbstractedPad { | |||
| 348 | u8 indicator; | 352 | u8 indicator; |
| 349 | std::vector<f32> virtual_six_axis_sensor_acceleration; | 353 | std::vector<f32> virtual_six_axis_sensor_acceleration; |
| 350 | std::vector<f32> virtual_six_axis_sensor_angle; | 354 | std::vector<f32> virtual_six_axis_sensor_angle; |
| 351 | u64 xcd_handle; | 355 | Core::HID::EmulatedController* xcd_handle; |
| 352 | u64 color; | 356 | u64 color; |
| 353 | }; | 357 | }; |
| 354 | } // namespace Service::HID | 358 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/npad/npad_vibration.cpp b/src/hid_core/resources/npad/npad_vibration.cpp index 7056e8eab..05aad4c54 100644 --- a/src/hid_core/resources/npad/npad_vibration.cpp +++ b/src/hid_core/resources/npad/npad_vibration.cpp | |||
| @@ -77,4 +77,8 @@ Result NpadVibration::EndPermitVibrationSession() { | |||
| 77 | return ResultSuccess; | 77 | return ResultSuccess; |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | u64 NpadVibration::GetSessionAruid() const { | ||
| 81 | return session_aruid; | ||
| 82 | } | ||
| 83 | |||
| 80 | } // namespace Service::HID | 84 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/npad/npad_vibration.h b/src/hid_core/resources/npad/npad_vibration.h index 0748aeffc..d5a95f2a0 100644 --- a/src/hid_core/resources/npad/npad_vibration.h +++ b/src/hid_core/resources/npad/npad_vibration.h | |||
| @@ -25,6 +25,8 @@ public: | |||
| 25 | Result BeginPermitVibrationSession(u64 aruid); | 25 | Result BeginPermitVibrationSession(u64 aruid); |
| 26 | Result EndPermitVibrationSession(); | 26 | Result EndPermitVibrationSession(); |
| 27 | 27 | ||
| 28 | u64 GetSessionAruid() const; | ||
| 29 | |||
| 28 | private: | 30 | private: |
| 29 | f32 volume{}; | 31 | f32 volume{}; |
| 30 | u64 session_aruid{}; | 32 | u64 session_aruid{}; |
diff --git a/src/hid_core/resources/vibration/gc_vibration_device.cpp b/src/hid_core/resources/vibration/gc_vibration_device.cpp index f01f81b9a..ad42b9d66 100644 --- a/src/hid_core/resources/vibration/gc_vibration_device.cpp +++ b/src/hid_core/resources/vibration/gc_vibration_device.cpp | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #include "hid_core/frontend/emulated_controller.h" | ||
| 4 | #include "hid_core/hid_result.h" | 5 | #include "hid_core/hid_result.h" |
| 5 | #include "hid_core/resources/npad/npad_types.h" | 6 | #include "hid_core/resources/npad/npad_types.h" |
| 6 | #include "hid_core/resources/npad/npad_vibration.h" | 7 | #include "hid_core/resources/npad/npad_vibration.h" |
| @@ -10,24 +11,25 @@ namespace Service::HID { | |||
| 10 | 11 | ||
| 11 | NpadGcVibrationDevice::NpadGcVibrationDevice() {} | 12 | NpadGcVibrationDevice::NpadGcVibrationDevice() {} |
| 12 | 13 | ||
| 13 | Result NpadGcVibrationDevice::IncrementRefCounter() { | 14 | Result NpadGcVibrationDevice::Activate() { |
| 14 | if (ref_counter == 0 && is_mounted) { | 15 | if (ref_counter == 0 && is_mounted) { |
| 15 | f32 volume = 1.0f; | 16 | f32 volume = 1.0f; |
| 16 | const auto result = vibration_handler->GetVibrationVolume(volume); | 17 | const auto result = vibration_handler->GetVibrationVolume(volume); |
| 17 | if (result.IsSuccess()) { | 18 | if (result.IsSuccess()) { |
| 18 | // TODO: SendVibrationGcErmCommand | 19 | xcd_handle->SetVibration(adapter_slot, Core::HID::VibrationGcErmCommand::Stop); |
| 19 | } | 20 | } |
| 20 | } | 21 | } |
| 22 | |||
| 21 | ref_counter++; | 23 | ref_counter++; |
| 22 | return ResultSuccess; | 24 | return ResultSuccess; |
| 23 | } | 25 | } |
| 24 | 26 | ||
| 25 | Result NpadGcVibrationDevice::DecrementRefCounter() { | 27 | Result NpadGcVibrationDevice::Deactivate() { |
| 26 | if (ref_counter == 1 && !is_mounted) { | 28 | if (ref_counter == 1 && is_mounted) { |
| 27 | f32 volume = 1.0f; | 29 | f32 volume = 1.0f; |
| 28 | const auto result = vibration_handler->GetVibrationVolume(volume); | 30 | const auto result = vibration_handler->GetVibrationVolume(volume); |
| 29 | if (result.IsSuccess()) { | 31 | if (result.IsSuccess()) { |
| 30 | // TODO: SendVibrationGcErmCommand | 32 | xcd_handle->SetVibration(adapter_slot, Core::HID::VibrationGcErmCommand::Stop); |
| 31 | } | 33 | } |
| 32 | } | 34 | } |
| 33 | 35 | ||
| @@ -38,6 +40,48 @@ Result NpadGcVibrationDevice::DecrementRefCounter() { | |||
| 38 | return ResultSuccess; | 40 | return ResultSuccess; |
| 39 | } | 41 | } |
| 40 | 42 | ||
| 43 | Result NpadGcVibrationDevice::Mount(IAbstractedPad& abstracted_pad, u32 slot, | ||
| 44 | NpadVibration* handler) { | ||
| 45 | if (!abstracted_pad.internal_flags.is_connected) { | ||
| 46 | return ResultSuccess; | ||
| 47 | } | ||
| 48 | |||
| 49 | // TODO: This device doesn't use a xcd handle instead has an GC adapter handle. This is just to | ||
| 50 | // keep compatibility with the front end. | ||
| 51 | xcd_handle = abstracted_pad.xcd_handle; | ||
| 52 | adapter_slot = slot; | ||
| 53 | vibration_handler = handler; | ||
| 54 | is_mounted = true; | ||
| 55 | |||
| 56 | if (ref_counter == 0) { | ||
| 57 | return ResultSuccess; | ||
| 58 | } | ||
| 59 | |||
| 60 | f32 volume{1.0f}; | ||
| 61 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 62 | if (result.IsSuccess()) { | ||
| 63 | xcd_handle->SetVibration(adapter_slot, Core::HID::VibrationGcErmCommand::Stop); | ||
| 64 | } | ||
| 65 | |||
| 66 | return ResultSuccess; | ||
| 67 | } | ||
| 68 | |||
| 69 | Result NpadGcVibrationDevice::Unmount() { | ||
| 70 | if (ref_counter == 0 || !is_mounted) { | ||
| 71 | is_mounted = false; | ||
| 72 | return ResultSuccess; | ||
| 73 | } | ||
| 74 | |||
| 75 | f32 volume{1.0f}; | ||
| 76 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 77 | if (result.IsSuccess()) { | ||
| 78 | xcd_handle->SetVibration(adapter_slot, Core::HID::VibrationGcErmCommand::Stop); | ||
| 79 | } | ||
| 80 | |||
| 81 | is_mounted = false; | ||
| 82 | return ResultSuccess; | ||
| 83 | } | ||
| 84 | |||
| 41 | Result NpadGcVibrationDevice::SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command) { | 85 | Result NpadGcVibrationDevice::SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command) { |
| 42 | if (!is_mounted) { | 86 | if (!is_mounted) { |
| 43 | return ResultSuccess; | 87 | return ResultSuccess; |
| @@ -55,7 +99,7 @@ Result NpadGcVibrationDevice::SendVibrationGcErmCommand(Core::HID::VibrationGcEr | |||
| 55 | return ResultSuccess; | 99 | return ResultSuccess; |
| 56 | } | 100 | } |
| 57 | } | 101 | } |
| 58 | // TODO: SendVibrationGcErmCommand | 102 | xcd_handle->SetVibration(adapter_slot, command); |
| 59 | return ResultSuccess; | 103 | return ResultSuccess; |
| 60 | } | 104 | } |
| 61 | 105 | ||
diff --git a/src/hid_core/resources/vibration/gc_vibration_device.h b/src/hid_core/resources/vibration/gc_vibration_device.h index 87abca57d..c624cbb28 100644 --- a/src/hid_core/resources/vibration/gc_vibration_device.h +++ b/src/hid_core/resources/vibration/gc_vibration_device.h | |||
| @@ -20,12 +20,18 @@ class NpadGcVibrationDevice final : public NpadVibrationBase { | |||
| 20 | public: | 20 | public: |
| 21 | explicit NpadGcVibrationDevice(); | 21 | explicit NpadGcVibrationDevice(); |
| 22 | 22 | ||
| 23 | Result IncrementRefCounter() override; | 23 | Result Activate() override; |
| 24 | Result DecrementRefCounter() override; | 24 | Result Deactivate() override; |
| 25 | |||
| 26 | Result Mount(IAbstractedPad& abstracted_pad, u32 slot, NpadVibration* handler); | ||
| 27 | Result Unmount(); | ||
| 25 | 28 | ||
| 26 | Result SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command); | 29 | Result SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command); |
| 27 | 30 | ||
| 28 | Result GetActualVibrationGcErmCommand(Core::HID::VibrationGcErmCommand& out_command); | 31 | Result GetActualVibrationGcErmCommand(Core::HID::VibrationGcErmCommand& out_command); |
| 29 | Result SendVibrationNotificationPattern(Core::HID::VibrationGcErmCommand command); | 32 | Result SendVibrationNotificationPattern(Core::HID::VibrationGcErmCommand command); |
| 33 | |||
| 34 | private: | ||
| 35 | u32 adapter_slot; | ||
| 30 | }; | 36 | }; |
| 31 | } // namespace Service::HID | 37 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/vibration/n64_vibration_device.cpp b/src/hid_core/resources/vibration/n64_vibration_device.cpp index 639f87abf..94ad37c8f 100644 --- a/src/hid_core/resources/vibration/n64_vibration_device.cpp +++ b/src/hid_core/resources/vibration/n64_vibration_device.cpp | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #include "hid_core/frontend/emulated_controller.h" | ||
| 4 | #include "hid_core/hid_result.h" | 5 | #include "hid_core/hid_result.h" |
| 5 | #include "hid_core/resources/npad/npad_types.h" | 6 | #include "hid_core/resources/npad/npad_types.h" |
| 6 | #include "hid_core/resources/npad/npad_vibration.h" | 7 | #include "hid_core/resources/npad/npad_vibration.h" |
| @@ -10,12 +11,12 @@ namespace Service::HID { | |||
| 10 | 11 | ||
| 11 | NpadN64VibrationDevice::NpadN64VibrationDevice() {} | 12 | NpadN64VibrationDevice::NpadN64VibrationDevice() {} |
| 12 | 13 | ||
| 13 | Result NpadN64VibrationDevice::IncrementRefCounter() { | 14 | Result NpadN64VibrationDevice::Activate() { |
| 14 | if (ref_counter == 0 && is_mounted) { | 15 | if (ref_counter == 0 && is_mounted) { |
| 15 | f32 volume = 1.0f; | 16 | f32 volume = 1.0f; |
| 16 | const auto result = vibration_handler->GetVibrationVolume(volume); | 17 | const auto result = vibration_handler->GetVibrationVolume(volume); |
| 17 | if (result.IsSuccess()) { | 18 | if (result.IsSuccess()) { |
| 18 | // TODO: SendVibrationInBool | 19 | xcd_handle->SetVibration(false); |
| 19 | } | 20 | } |
| 20 | } | 21 | } |
| 21 | 22 | ||
| @@ -23,19 +24,12 @@ Result NpadN64VibrationDevice::IncrementRefCounter() { | |||
| 23 | return ResultSuccess; | 24 | return ResultSuccess; |
| 24 | } | 25 | } |
| 25 | 26 | ||
| 26 | Result NpadN64VibrationDevice::DecrementRefCounter() { | 27 | Result NpadN64VibrationDevice::Deactivate() { |
| 27 | if (ref_counter == 1) { | 28 | if (ref_counter == 1 && is_mounted) { |
| 28 | if (!is_mounted) { | ||
| 29 | ref_counter = 0; | ||
| 30 | if (is_mounted != false) { | ||
| 31 | // TODO: SendVibrationInBool | ||
| 32 | } | ||
| 33 | return ResultSuccess; | ||
| 34 | } | ||
| 35 | f32 volume = 1.0f; | 29 | f32 volume = 1.0f; |
| 36 | const auto result = vibration_handler->GetVibrationVolume(volume); | 30 | const auto result = vibration_handler->GetVibrationVolume(volume); |
| 37 | if (result.IsSuccess()) { | 31 | if (result.IsSuccess()) { |
| 38 | // TODO | 32 | xcd_handle->SetVibration(false); |
| 39 | } | 33 | } |
| 40 | } | 34 | } |
| 41 | 35 | ||
| @@ -46,6 +40,43 @@ Result NpadN64VibrationDevice::DecrementRefCounter() { | |||
| 46 | return ResultSuccess; | 40 | return ResultSuccess; |
| 47 | } | 41 | } |
| 48 | 42 | ||
| 43 | Result NpadN64VibrationDevice::Mount(IAbstractedPad& abstracted_pad, NpadVibration* handler) { | ||
| 44 | if (!abstracted_pad.internal_flags.is_connected) { | ||
| 45 | return ResultSuccess; | ||
| 46 | } | ||
| 47 | xcd_handle = abstracted_pad.xcd_handle; | ||
| 48 | vibration_handler = handler; | ||
| 49 | is_mounted = true; | ||
| 50 | |||
| 51 | if (ref_counter == 0) { | ||
| 52 | return ResultSuccess; | ||
| 53 | } | ||
| 54 | |||
| 55 | f32 volume{1.0f}; | ||
| 56 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 57 | if (result.IsSuccess()) { | ||
| 58 | xcd_handle->SetVibration(false); | ||
| 59 | } | ||
| 60 | |||
| 61 | return ResultSuccess; | ||
| 62 | } | ||
| 63 | |||
| 64 | Result NpadN64VibrationDevice::Unmount() { | ||
| 65 | if (ref_counter == 0 || !is_mounted) { | ||
| 66 | is_mounted = false; | ||
| 67 | return ResultSuccess; | ||
| 68 | } | ||
| 69 | |||
| 70 | f32 volume{1.0f}; | ||
| 71 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 72 | if (result.IsSuccess()) { | ||
| 73 | xcd_handle->SetVibration(false); | ||
| 74 | } | ||
| 75 | |||
| 76 | is_mounted = false; | ||
| 77 | return ResultSuccess; | ||
| 78 | } | ||
| 79 | |||
| 49 | Result NpadN64VibrationDevice::SendValueInBool(bool is_vibrating) { | 80 | Result NpadN64VibrationDevice::SendValueInBool(bool is_vibrating) { |
| 50 | if (ref_counter < 1) { | 81 | if (ref_counter < 1) { |
| 51 | return ResultVibrationNotInitialized; | 82 | return ResultVibrationNotInitialized; |
| @@ -56,7 +87,7 @@ Result NpadN64VibrationDevice::SendValueInBool(bool is_vibrating) { | |||
| 56 | if (result.IsError()) { | 87 | if (result.IsError()) { |
| 57 | return result; | 88 | return result; |
| 58 | } | 89 | } |
| 59 | // TODO: SendVibrationInBool | 90 | xcd_handle->SetVibration(false); |
| 60 | } | 91 | } |
| 61 | return ResultSuccess; | 92 | return ResultSuccess; |
| 62 | } | 93 | } |
diff --git a/src/hid_core/resources/vibration/n64_vibration_device.h b/src/hid_core/resources/vibration/n64_vibration_device.h index 54e6efc1a..09de7701c 100644 --- a/src/hid_core/resources/vibration/n64_vibration_device.h +++ b/src/hid_core/resources/vibration/n64_vibration_device.h | |||
| @@ -14,14 +14,18 @@ | |||
| 14 | 14 | ||
| 15 | namespace Service::HID { | 15 | namespace Service::HID { |
| 16 | class NpadVibration; | 16 | class NpadVibration; |
| 17 | struct IAbstractedPad; | ||
| 17 | 18 | ||
| 18 | /// Handles Npad request from HID interfaces | 19 | /// Handles Npad request from HID interfaces |
| 19 | class NpadN64VibrationDevice final : public NpadVibrationBase { | 20 | class NpadN64VibrationDevice final : public NpadVibrationBase { |
| 20 | public: | 21 | public: |
| 21 | explicit NpadN64VibrationDevice(); | 22 | explicit NpadN64VibrationDevice(); |
| 22 | 23 | ||
| 23 | Result IncrementRefCounter() override; | 24 | Result Activate() override; |
| 24 | Result DecrementRefCounter() override; | 25 | Result Deactivate() override; |
| 26 | |||
| 27 | Result Mount(IAbstractedPad& abstracted_pad, NpadVibration* handler); | ||
| 28 | Result Unmount(); | ||
| 25 | 29 | ||
| 26 | Result SendValueInBool(bool is_vibrating); | 30 | Result SendValueInBool(bool is_vibrating); |
| 27 | Result SendVibrationNotificationPattern(u32 pattern); | 31 | Result SendVibrationNotificationPattern(u32 pattern); |
diff --git a/src/hid_core/resources/vibration/vibration_base.cpp b/src/hid_core/resources/vibration/vibration_base.cpp index 350f349c2..f28d30406 100644 --- a/src/hid_core/resources/vibration/vibration_base.cpp +++ b/src/hid_core/resources/vibration/vibration_base.cpp | |||
| @@ -10,12 +10,12 @@ namespace Service::HID { | |||
| 10 | 10 | ||
| 11 | NpadVibrationBase::NpadVibrationBase() {} | 11 | NpadVibrationBase::NpadVibrationBase() {} |
| 12 | 12 | ||
| 13 | Result NpadVibrationBase::IncrementRefCounter() { | 13 | Result NpadVibrationBase::Activate() { |
| 14 | ref_counter++; | 14 | ref_counter++; |
| 15 | return ResultSuccess; | 15 | return ResultSuccess; |
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | Result NpadVibrationBase::DecrementRefCounter() { | 18 | Result NpadVibrationBase::Deactivate() { |
| 19 | if (ref_counter > 0) { | 19 | if (ref_counter > 0) { |
| 20 | ref_counter--; | 20 | ref_counter--; |
| 21 | } | 21 | } |
diff --git a/src/hid_core/resources/vibration/vibration_base.h b/src/hid_core/resources/vibration/vibration_base.h index c6c5fc4d9..69c26e669 100644 --- a/src/hid_core/resources/vibration/vibration_base.h +++ b/src/hid_core/resources/vibration/vibration_base.h | |||
| @@ -6,6 +6,10 @@ | |||
| 6 | #include "common/common_types.h" | 6 | #include "common/common_types.h" |
| 7 | #include "core/hle/result.h" | 7 | #include "core/hle/result.h" |
| 8 | 8 | ||
| 9 | namespace Core::HID { | ||
| 10 | class EmulatedController; | ||
| 11 | } | ||
| 12 | |||
| 9 | namespace Service::HID { | 13 | namespace Service::HID { |
| 10 | class NpadVibration; | 14 | class NpadVibration; |
| 11 | 15 | ||
| @@ -14,13 +18,13 @@ class NpadVibrationBase { | |||
| 14 | public: | 18 | public: |
| 15 | explicit NpadVibrationBase(); | 19 | explicit NpadVibrationBase(); |
| 16 | 20 | ||
| 17 | virtual Result IncrementRefCounter(); | 21 | virtual Result Activate(); |
| 18 | virtual Result DecrementRefCounter(); | 22 | virtual Result Deactivate(); |
| 19 | 23 | ||
| 20 | bool IsVibrationMounted() const; | 24 | bool IsVibrationMounted() const; |
| 21 | 25 | ||
| 22 | protected: | 26 | protected: |
| 23 | u64 xcd_handle{}; | 27 | Core::HID::EmulatedController* xcd_handle{nullptr}; |
| 24 | s32 ref_counter{}; | 28 | s32 ref_counter{}; |
| 25 | bool is_mounted{}; | 29 | bool is_mounted{}; |
| 26 | NpadVibration* vibration_handler{nullptr}; | 30 | NpadVibration* vibration_handler{nullptr}; |
diff --git a/src/hid_core/resources/vibration/vibration_device.cpp b/src/hid_core/resources/vibration/vibration_device.cpp index 888c3a7ed..08b14591f 100644 --- a/src/hid_core/resources/vibration/vibration_device.cpp +++ b/src/hid_core/resources/vibration/vibration_device.cpp | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #include "hid_core/frontend/emulated_controller.h" | ||
| 4 | #include "hid_core/hid_result.h" | 5 | #include "hid_core/hid_result.h" |
| 5 | #include "hid_core/resources/npad/npad_types.h" | 6 | #include "hid_core/resources/npad/npad_types.h" |
| 6 | #include "hid_core/resources/npad/npad_vibration.h" | 7 | #include "hid_core/resources/npad/npad_vibration.h" |
| @@ -10,12 +11,30 @@ namespace Service::HID { | |||
| 10 | 11 | ||
| 11 | NpadVibrationDevice::NpadVibrationDevice() {} | 12 | NpadVibrationDevice::NpadVibrationDevice() {} |
| 12 | 13 | ||
| 13 | Result NpadVibrationDevice::IncrementRefCounter() { | 14 | Result NpadVibrationDevice::Activate() { |
| 15 | if (ref_counter == 0 && is_mounted) { | ||
| 16 | f32 volume = 1.0f; | ||
| 17 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 18 | if (result.IsSuccess()) { | ||
| 19 | xcd_handle->SetVibration(device_index, Core::HID::DEFAULT_VIBRATION_VALUE); | ||
| 20 | // TODO: SendNotificationPattern; | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 14 | ref_counter++; | 24 | ref_counter++; |
| 15 | return ResultSuccess; | 25 | return ResultSuccess; |
| 16 | } | 26 | } |
| 17 | 27 | ||
| 18 | Result NpadVibrationDevice::DecrementRefCounter() { | 28 | Result NpadVibrationDevice::Deactivate() { |
| 29 | if (ref_counter == 1 && is_mounted) { | ||
| 30 | f32 volume = 1.0f; | ||
| 31 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 32 | if (result.IsSuccess()) { | ||
| 33 | xcd_handle->SetVibration(device_index, Core::HID::DEFAULT_VIBRATION_VALUE); | ||
| 34 | // TODO: SendNotificationPattern; | ||
| 35 | } | ||
| 36 | } | ||
| 37 | |||
| 19 | if (ref_counter > 0) { | 38 | if (ref_counter > 0) { |
| 20 | ref_counter--; | 39 | ref_counter--; |
| 21 | } | 40 | } |
| @@ -23,6 +42,45 @@ Result NpadVibrationDevice::DecrementRefCounter() { | |||
| 23 | return ResultSuccess; | 42 | return ResultSuccess; |
| 24 | } | 43 | } |
| 25 | 44 | ||
| 45 | Result NpadVibrationDevice::Mount(IAbstractedPad& abstracted_pad, Core::HID::DeviceIndex index, | ||
| 46 | NpadVibration* handler) { | ||
| 47 | if (!abstracted_pad.internal_flags.is_connected) { | ||
| 48 | return ResultSuccess; | ||
| 49 | } | ||
| 50 | xcd_handle = abstracted_pad.xcd_handle; | ||
| 51 | device_index = index; | ||
| 52 | vibration_handler = handler; | ||
| 53 | is_mounted = true; | ||
| 54 | |||
| 55 | if (ref_counter == 0) { | ||
| 56 | return ResultSuccess; | ||
| 57 | } | ||
| 58 | |||
| 59 | f32 volume{1.0f}; | ||
| 60 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 61 | if (result.IsSuccess()) { | ||
| 62 | xcd_handle->SetVibration(false); | ||
| 63 | } | ||
| 64 | |||
| 65 | return ResultSuccess; | ||
| 66 | } | ||
| 67 | |||
| 68 | Result NpadVibrationDevice::Unmount() { | ||
| 69 | if (ref_counter == 0 || !is_mounted) { | ||
| 70 | is_mounted = false; | ||
| 71 | return ResultSuccess; | ||
| 72 | } | ||
| 73 | |||
| 74 | f32 volume{1.0f}; | ||
| 75 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 76 | if (result.IsSuccess()) { | ||
| 77 | xcd_handle->SetVibration(device_index, Core::HID::DEFAULT_VIBRATION_VALUE); | ||
| 78 | } | ||
| 79 | |||
| 80 | is_mounted = false; | ||
| 81 | return ResultSuccess; | ||
| 82 | } | ||
| 83 | |||
| 26 | Result NpadVibrationDevice::SendVibrationValue(const Core::HID::VibrationValue& value) { | 84 | Result NpadVibrationDevice::SendVibrationValue(const Core::HID::VibrationValue& value) { |
| 27 | if (ref_counter == 0) { | 85 | if (ref_counter == 0) { |
| 28 | return ResultVibrationNotInitialized; | 86 | return ResultVibrationNotInitialized; |
| @@ -37,7 +95,7 @@ Result NpadVibrationDevice::SendVibrationValue(const Core::HID::VibrationValue& | |||
| 37 | return result; | 95 | return result; |
| 38 | } | 96 | } |
| 39 | if (volume <= 0.0f) { | 97 | if (volume <= 0.0f) { |
| 40 | // TODO: SendVibrationValue | 98 | xcd_handle->SetVibration(device_index, Core::HID::DEFAULT_VIBRATION_VALUE); |
| 41 | return ResultSuccess; | 99 | return ResultSuccess; |
| 42 | } | 100 | } |
| 43 | 101 | ||
| @@ -45,7 +103,7 @@ Result NpadVibrationDevice::SendVibrationValue(const Core::HID::VibrationValue& | |||
| 45 | vibration_value.high_amplitude *= volume; | 103 | vibration_value.high_amplitude *= volume; |
| 46 | vibration_value.low_amplitude *= volume; | 104 | vibration_value.low_amplitude *= volume; |
| 47 | 105 | ||
| 48 | // TODO: SendVibrationValue | 106 | xcd_handle->SetVibration(device_index, vibration_value); |
| 49 | return ResultSuccess; | 107 | return ResultSuccess; |
| 50 | } | 108 | } |
| 51 | 109 | ||
| @@ -63,11 +121,11 @@ Result NpadVibrationDevice::SendVibrationNotificationPattern([[maybe_unused]] u3 | |||
| 63 | pattern = 0; | 121 | pattern = 0; |
| 64 | } | 122 | } |
| 65 | 123 | ||
| 66 | // return xcd_handle->SendVibrationNotificationPattern(pattern); | 124 | // TODO: SendVibrationNotificationPattern; |
| 67 | return ResultSuccess; | 125 | return ResultSuccess; |
| 68 | } | 126 | } |
| 69 | 127 | ||
| 70 | Result NpadVibrationDevice::GetActualVibrationValue(Core::HID::VibrationValue& out_value) { | 128 | Result NpadVibrationDevice::GetActualVibrationValue(Core::HID::VibrationValue& out_value) const { |
| 71 | if (ref_counter < 1) { | 129 | if (ref_counter < 1) { |
| 72 | return ResultVibrationNotInitialized; | 130 | return ResultVibrationNotInitialized; |
| 73 | } | 131 | } |
| @@ -77,7 +135,7 @@ Result NpadVibrationDevice::GetActualVibrationValue(Core::HID::VibrationValue& o | |||
| 77 | return ResultSuccess; | 135 | return ResultSuccess; |
| 78 | } | 136 | } |
| 79 | 137 | ||
| 80 | // TODO: SendVibrationValue | 138 | out_value = xcd_handle->GetActualVibrationValue(device_index); |
| 81 | return ResultSuccess; | 139 | return ResultSuccess; |
| 82 | } | 140 | } |
| 83 | 141 | ||
diff --git a/src/hid_core/resources/vibration/vibration_device.h b/src/hid_core/resources/vibration/vibration_device.h index 3574ad60b..c2f9891d3 100644 --- a/src/hid_core/resources/vibration/vibration_device.h +++ b/src/hid_core/resources/vibration/vibration_device.h | |||
| @@ -12,6 +12,10 @@ | |||
| 12 | #include "hid_core/resources/npad/npad_types.h" | 12 | #include "hid_core/resources/npad/npad_types.h" |
| 13 | #include "hid_core/resources/vibration/vibration_base.h" | 13 | #include "hid_core/resources/vibration/vibration_base.h" |
| 14 | 14 | ||
| 15 | namespace Core::HID { | ||
| 16 | enum class DeviceIndex : u8; | ||
| 17 | } | ||
| 18 | |||
| 15 | namespace Service::HID { | 19 | namespace Service::HID { |
| 16 | class NpadVibration; | 20 | class NpadVibration; |
| 17 | 21 | ||
| @@ -20,16 +24,20 @@ class NpadVibrationDevice final : public NpadVibrationBase { | |||
| 20 | public: | 24 | public: |
| 21 | explicit NpadVibrationDevice(); | 25 | explicit NpadVibrationDevice(); |
| 22 | 26 | ||
| 23 | Result IncrementRefCounter(); | 27 | Result Activate(); |
| 24 | Result DecrementRefCounter(); | 28 | Result Deactivate(); |
| 29 | |||
| 30 | Result Mount(IAbstractedPad& abstracted_pad, Core::HID::DeviceIndex index, | ||
| 31 | NpadVibration* handler); | ||
| 32 | Result Unmount(); | ||
| 25 | 33 | ||
| 26 | Result SendVibrationValue(const Core::HID::VibrationValue& value); | 34 | Result SendVibrationValue(const Core::HID::VibrationValue& value); |
| 27 | Result SendVibrationNotificationPattern(u32 pattern); | 35 | Result SendVibrationNotificationPattern(u32 pattern); |
| 28 | 36 | ||
| 29 | Result GetActualVibrationValue(Core::HID::VibrationValue& out_value); | 37 | Result GetActualVibrationValue(Core::HID::VibrationValue& out_value) const; |
| 30 | 38 | ||
| 31 | private: | 39 | private: |
| 32 | u32 device_index{}; | 40 | Core::HID::DeviceIndex device_index{}; |
| 33 | }; | 41 | }; |
| 34 | 42 | ||
| 35 | } // namespace Service::HID | 43 | } // namespace Service::HID |
diff --git a/src/yuzu/configuration/configure_vibration.cpp b/src/yuzu/configuration/configure_vibration.cpp index d898d8acc..6b1f4527b 100644 --- a/src/yuzu/configuration/configure_vibration.cpp +++ b/src/yuzu/configuration/configure_vibration.cpp | |||
| @@ -116,8 +116,8 @@ void ConfigureVibration::VibrateController(Core::HID::ControllerTriggerType type | |||
| 116 | .high_amplitude = 1.0f, | 116 | .high_amplitude = 1.0f, |
| 117 | .high_frequency = 320.0f, | 117 | .high_frequency = 320.0f, |
| 118 | }; | 118 | }; |
| 119 | controller->SetVibration(0, vibration); | 119 | controller->SetVibration(Core::HID::DeviceIndex::Left, vibration); |
| 120 | controller->SetVibration(1, vibration); | 120 | controller->SetVibration(Core::HID::DeviceIndex::Right, vibration); |
| 121 | 121 | ||
| 122 | // Restore previous values | 122 | // Restore previous values |
| 123 | player.vibration_enabled = old_vibration_enabled; | 123 | player.vibration_enabled = old_vibration_enabled; |
| @@ -127,7 +127,7 @@ void ConfigureVibration::VibrateController(Core::HID::ControllerTriggerType type | |||
| 127 | void ConfigureVibration::StopVibrations() { | 127 | void ConfigureVibration::StopVibrations() { |
| 128 | for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { | 128 | for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { |
| 129 | auto controller = hid_core.GetEmulatedControllerByIndex(i); | 129 | auto controller = hid_core.GetEmulatedControllerByIndex(i); |
| 130 | controller->SetVibration(0, Core::HID::DEFAULT_VIBRATION_VALUE); | 130 | controller->SetVibration(Core::HID::DeviceIndex::Left, Core::HID::DEFAULT_VIBRATION_VALUE); |
| 131 | controller->SetVibration(1, Core::HID::DEFAULT_VIBRATION_VALUE); | 131 | controller->SetVibration(Core::HID::DeviceIndex::Right, Core::HID::DEFAULT_VIBRATION_VALUE); |
| 132 | } | 132 | } |
| 133 | } | 133 | } |