psm.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <memory>
  5. #include "common/logging/log.h"
  6. #include "core/core.h"
  7. #include "core/hle/ipc_helpers.h"
  8. #include "core/hle/kernel/k_event.h"
  9. #include "core/hle/kernel/k_readable_event.h"
  10. #include "core/hle/kernel/k_writable_event.h"
  11. #include "core/hle/kernel/kernel.h"
  12. #include "core/hle/service/ptm/psm.h"
  13. #include "core/hle/service/service.h"
  14. #include "core/hle/service/sm/sm.h"
  15. namespace Service::PSM {
  16. class IPsmSession final : public ServiceFramework<IPsmSession> {
  17. public:
  18. explicit IPsmSession(Core::System& system_)
  19. : ServiceFramework{system_, "IPsmSession"}, state_change_event{system.Kernel()} {
  20. // clang-format off
  21. static const FunctionInfo functions[] = {
  22. {0, &IPsmSession::BindStateChangeEvent, "BindStateChangeEvent"},
  23. {1, &IPsmSession::UnbindStateChangeEvent, "UnbindStateChangeEvent"},
  24. {2, &IPsmSession::SetChargerTypeChangeEventEnabled, "SetChargerTypeChangeEventEnabled"},
  25. {3, &IPsmSession::SetPowerSupplyChangeEventEnabled, "SetPowerSupplyChangeEventEnabled"},
  26. {4, &IPsmSession::SetBatteryVoltageStateChangeEventEnabled, "SetBatteryVoltageStateChangeEventEnabled"},
  27. };
  28. // clang-format on
  29. RegisterHandlers(functions);
  30. Kernel::KAutoObject::Create(std::addressof(state_change_event));
  31. state_change_event.Initialize("IPsmSession::state_change_event");
  32. }
  33. ~IPsmSession() override = default;
  34. void SignalChargerTypeChanged() {
  35. if (should_signal && should_signal_charger_type) {
  36. state_change_event.GetWritableEvent().Signal();
  37. }
  38. }
  39. void SignalPowerSupplyChanged() {
  40. if (should_signal && should_signal_power_supply) {
  41. state_change_event.GetWritableEvent().Signal();
  42. }
  43. }
  44. void SignalBatteryVoltageStateChanged() {
  45. if (should_signal && should_signal_battery_voltage) {
  46. state_change_event.GetWritableEvent().Signal();
  47. }
  48. }
  49. private:
  50. void BindStateChangeEvent(Kernel::HLERequestContext& ctx) {
  51. LOG_DEBUG(Service_PSM, "called");
  52. should_signal = true;
  53. IPC::ResponseBuilder rb{ctx, 2, 1};
  54. rb.Push(ResultSuccess);
  55. rb.PushCopyObjects(state_change_event.GetReadableEvent());
  56. }
  57. void UnbindStateChangeEvent(Kernel::HLERequestContext& ctx) {
  58. LOG_DEBUG(Service_PSM, "called");
  59. should_signal = false;
  60. IPC::ResponseBuilder rb{ctx, 2};
  61. rb.Push(ResultSuccess);
  62. }
  63. void SetChargerTypeChangeEventEnabled(Kernel::HLERequestContext& ctx) {
  64. IPC::RequestParser rp{ctx};
  65. const auto state = rp.Pop<bool>();
  66. LOG_DEBUG(Service_PSM, "called, state={}", state);
  67. should_signal_charger_type = state;
  68. IPC::ResponseBuilder rb{ctx, 2};
  69. rb.Push(ResultSuccess);
  70. }
  71. void SetPowerSupplyChangeEventEnabled(Kernel::HLERequestContext& ctx) {
  72. IPC::RequestParser rp{ctx};
  73. const auto state = rp.Pop<bool>();
  74. LOG_DEBUG(Service_PSM, "called, state={}", state);
  75. should_signal_power_supply = state;
  76. IPC::ResponseBuilder rb{ctx, 2};
  77. rb.Push(ResultSuccess);
  78. }
  79. void SetBatteryVoltageStateChangeEventEnabled(Kernel::HLERequestContext& ctx) {
  80. IPC::RequestParser rp{ctx};
  81. const auto state = rp.Pop<bool>();
  82. LOG_DEBUG(Service_PSM, "called, state={}", state);
  83. should_signal_battery_voltage = state;
  84. IPC::ResponseBuilder rb{ctx, 2};
  85. rb.Push(ResultSuccess);
  86. }
  87. bool should_signal_charger_type{};
  88. bool should_signal_power_supply{};
  89. bool should_signal_battery_voltage{};
  90. bool should_signal{};
  91. Kernel::KEvent state_change_event;
  92. };
  93. class PSM final : public ServiceFramework<PSM> {
  94. public:
  95. explicit PSM(Core::System& system_) : ServiceFramework{system_, "psm"} {
  96. // clang-format off
  97. static const FunctionInfo functions[] = {
  98. {0, &PSM::GetBatteryChargePercentage, "GetBatteryChargePercentage"},
  99. {1, &PSM::GetChargerType, "GetChargerType"},
  100. {2, nullptr, "EnableBatteryCharging"},
  101. {3, nullptr, "DisableBatteryCharging"},
  102. {4, nullptr, "IsBatteryChargingEnabled"},
  103. {5, nullptr, "AcquireControllerPowerSupply"},
  104. {6, nullptr, "ReleaseControllerPowerSupply"},
  105. {7, &PSM::OpenSession, "OpenSession"},
  106. {8, nullptr, "EnableEnoughPowerChargeEmulation"},
  107. {9, nullptr, "DisableEnoughPowerChargeEmulation"},
  108. {10, nullptr, "EnableFastBatteryCharging"},
  109. {11, nullptr, "DisableFastBatteryCharging"},
  110. {12, nullptr, "GetBatteryVoltageState"},
  111. {13, nullptr, "GetRawBatteryChargePercentage"},
  112. {14, nullptr, "IsEnoughPowerSupplied"},
  113. {15, nullptr, "GetBatteryAgePercentage"},
  114. {16, nullptr, "GetBatteryChargeInfoEvent"},
  115. {17, nullptr, "GetBatteryChargeInfoFields"},
  116. {18, nullptr, "GetBatteryChargeCalibratedEvent"},
  117. };
  118. // clang-format on
  119. RegisterHandlers(functions);
  120. }
  121. ~PSM() override = default;
  122. private:
  123. void GetBatteryChargePercentage(Kernel::HLERequestContext& ctx) {
  124. LOG_DEBUG(Service_PSM, "called");
  125. IPC::ResponseBuilder rb{ctx, 3};
  126. rb.Push(ResultSuccess);
  127. rb.Push<u32>(battery_charge_percentage);
  128. }
  129. void GetChargerType(Kernel::HLERequestContext& ctx) {
  130. LOG_DEBUG(Service_PSM, "called");
  131. IPC::ResponseBuilder rb{ctx, 3};
  132. rb.Push(ResultSuccess);
  133. rb.PushEnum(charger_type);
  134. }
  135. void OpenSession(Kernel::HLERequestContext& ctx) {
  136. LOG_DEBUG(Service_PSM, "called");
  137. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  138. rb.Push(ResultSuccess);
  139. rb.PushIpcInterface<IPsmSession>(system);
  140. }
  141. enum class ChargerType : u32 {
  142. Unplugged = 0,
  143. RegularCharger = 1,
  144. LowPowerCharger = 2,
  145. Unknown = 3,
  146. };
  147. u32 battery_charge_percentage{100}; // 100%
  148. ChargerType charger_type{ChargerType::RegularCharger};
  149. };
  150. void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
  151. std::make_shared<PSM>(system)->InstallAsService(sm);
  152. }
  153. } // namespace Service::PSM