summaryrefslogtreecommitdiff
path: root/src/core/hle/service/hid
diff options
context:
space:
mode:
authorGravatar Narr the Reg2024-01-10 22:06:54 -0600
committerGravatar german772024-01-15 23:15:40 -0600
commit2cacb9d48c98603176e52ecc94f2374a934797fb (patch)
tree12badf5b4eede22b22dece03a9074197ec631a1e /src/core/hle/service/hid
parentMerge pull request #12686 from szepeviktor/typos3 (diff)
downloadyuzu-2cacb9d48c98603176e52ecc94f2374a934797fb.tar.gz
yuzu-2cacb9d48c98603176e52ecc94f2374a934797fb.tar.xz
yuzu-2cacb9d48c98603176e52ecc94f2374a934797fb.zip
service: hid: Fully implement abstract vibration
Diffstat (limited to 'src/core/hle/service/hid')
-rw-r--r--src/core/hle/service/hid/hid.cpp1
-rw-r--r--src/core/hle/service/hid/hid_server.cpp334
-rw-r--r--src/core/hle/service/hid/hid_server.h1
-rw-r--r--src/core/hle/service/hid/hid_system_server.cpp98
-rw-r--r--src/core/hle/service/hid/hid_system_server.h6
5 files changed, 289 insertions, 151 deletions
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 4ce0a9834..0c0b3cd47 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
32namespace Service::HID { 36namespace 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
48private: 52private:
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) {
1492void IHidServer::GetVibrationDeviceInfo(HLERequestContext& ctx) { 1523void 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
1600void IHidServer::CreateActiveVibrationDeviceList(HLERequestContext& ctx) { 1603void 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
1622void IHidServer::IsVibrationPermitted(HLERequestContext& ctx) { 1625void 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
1633void IHidServer::SendVibrationValues(HLERequestContext& ctx) { 1638void 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
1657void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) { 1671void 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
1718void IHidServer::GetActualVibrationGcErmCommand(HLERequestContext& ctx) { 1710void 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
1772void IHidServer::EndPermitVibrationSession(HLERequestContext& ctx) { 1764void 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
1781void IHidServer::IsVibrationDeviceMounted(HLERequestContext& ctx) { 1774void 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
1808void 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
1804void IHidServer::ActivateConsoleSixAxisSensor(HLERequestContext& ctx) { 1848void 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
542void 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
541void IHidSystemServer::EnableAppletToGetSixAxisSensor(HLERequestContext& ctx) { 563void 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
626void 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
640void 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
653void 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
667void 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
604void IHidSystemServer::IsJoyConAttachedOnAllRail(HLERequestContext& ctx) { 677void 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
825void 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
752void IHidSystemServer::IsUsingCustomButtonConfig(HLERequestContext& ctx) { 838void 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();