diff --git a/libraries/libstratosphere/include/stratosphere/powctl/powctl_battery_api.hpp b/libraries/libstratosphere/include/stratosphere/powctl/powctl_battery_api.hpp index 83a605864..e80cbf675 100644 --- a/libraries/libstratosphere/include/stratosphere/powctl/powctl_battery_api.hpp +++ b/libraries/libstratosphere/include/stratosphere/powctl/powctl_battery_api.hpp @@ -21,16 +21,20 @@ namespace ams::powctl { /* Battery API. */ - Result GetBatterySocRep(float *out_percent, Session &session); + Result GetBatteryChargePercentage(float *out_percent, Session &session); - Result GetBatterySocVf(float *out_percent, Session &session); + Result GetBatteryVoltageFuelGaugePercentage(float *out_percent, Session &session); Result GetBatteryFullCapacity(int *out_mah, Session &session); Result GetBatteryRemainingCapacity(int *out_mah, Session &session); - Result SetBatteryPercentageMinimumAlertThreshold(Session &session, float percentage); - Result SetBatteryPercentageMaximumAlertThreshold(Session &session, float percentage); - Result SetBatteryPercentageFullThreshold(Session &session, float percentage); + Result SetBatteryChargePercentageMinimumAlertThreshold(Session &session, float percentage); + Result SetBatteryChargePercentageMaximumAlertThreshold(Session &session, float percentage); + + Result SetBatteryVoltageFuelGaugePercentageMinimumAlertThreshold(Session &session, float percentage); + Result SetBatteryVoltageFuelGaugePercentageMaximumAlertThreshold(Session &session, float percentage); + + Result SetBatteryFullChargeThreshold(Session &session, float percentage); Result GetBatteryAverageCurrent(int *out_ma, Session &session); Result GetBatteryCurrent(int *out_ma, Session &session); diff --git a/libraries/libstratosphere/include/stratosphere/powctl/powctl_session_api.hpp b/libraries/libstratosphere/include/stratosphere/powctl/powctl_session_api.hpp index 3984decfb..f60021067 100644 --- a/libraries/libstratosphere/include/stratosphere/powctl/powctl_session_api.hpp +++ b/libraries/libstratosphere/include/stratosphere/powctl/powctl_session_api.hpp @@ -37,6 +37,10 @@ namespace ams::powctl { bool has_session; util::TypedStorage impl_storage; + struct ConstantInitializeTag{}; + + constexpr Session(ConstantInitializeTag) : has_session(false), impl_storage() { /* ... */ } + Session() : has_session(false) { /* ... */ } }; diff --git a/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_battery_driver.cpp b/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_battery_driver.cpp index 7542971f7..aef142cd4 100644 --- a/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_battery_driver.cpp +++ b/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_battery_driver.cpp @@ -25,21 +25,10 @@ namespace ams::powctl::impl::board::nintendo::nx { constinit util::optional g_battery_device; - constinit util::TypedStorage g_max17050_driver; - constinit bool g_constructed_max17050_driver; - constinit os::SdkMutex g_max17050_driver_mutex; + constinit Max17050Driver g_max17050_driver; - Max17050Driver &GetMax17050Driver() { - if (AMS_UNLIKELY(!g_constructed_max17050_driver)) { - std::scoped_lock lk(g_max17050_driver_mutex); - - if (AMS_LIKELY(!g_constructed_max17050_driver)) { - util::ConstructAt(g_max17050_driver); - g_constructed_max17050_driver = true; - } - } - - return util::GetReference(g_max17050_driver); + ALWAYS_INLINE Max17050Driver &GetMax17050Driver() { + return g_max17050_driver; } constexpr inline const double SenseResistorValue = 0.005; @@ -143,28 +132,28 @@ namespace ams::powctl::impl::board::nintendo::nx { AMS_ABORT(); } - Result BatteryDriver::GetBatterySocRep(float *out_percent, IDevice *device) { + Result BatteryDriver::GetBatteryChargePercentage(float *out_percent, IDevice *device) { /* Validate arguments. */ R_UNLESS(out_percent != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); /* Get the value. */ double percent; - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetSocRep(std::addressof(percent))); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetChargePercentage(std::addressof(percent))); /* Set output. */ *out_percent = percent; return ResultSuccess(); } - Result BatteryDriver::GetBatterySocVf(float *out_percent, IDevice *device) { + Result BatteryDriver::GetBatteryVoltageFuelGaugePercentage(float *out_percent, IDevice *device) { /* Validate arguments. */ R_UNLESS(out_percent != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); /* Get the value. */ double percent; - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetSocVf(std::addressof(percent))); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetVoltageFuelGaugePercentage(std::addressof(percent))); /* Set output. */ *out_percent = percent; @@ -178,7 +167,7 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Get the value. */ double mah; - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetFullCapacity(std::addressof(mah), SenseResistorValue)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetFullCapacity(std::addressof(mah), SenseResistorValue)); /* Set output. */ *out_mah = mah; @@ -192,36 +181,54 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Get the value. */ double mah; - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetRemainingCapacity(std::addressof(mah), SenseResistorValue)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetRemainingCapacity(std::addressof(mah), SenseResistorValue)); /* Set output. */ *out_mah = mah; return ResultSuccess(); } - Result BatteryDriver::SetBatteryPercentageMinimumAlertThreshold(IDevice *device, float percentage) { + Result BatteryDriver::SetBatteryChargePercentageMinimumAlertThreshold(IDevice *device, float percentage) { /* Validate arguments. */ R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetPercentageMinimumAlertThreshold(percentage)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().SetChargePercentageMinimumAlertThreshold(percentage)); return ResultSuccess(); } - Result BatteryDriver::SetBatteryPercentageMaximumAlertThreshold(IDevice *device, float percentage) { + Result BatteryDriver::SetBatteryChargePercentageMaximumAlertThreshold(IDevice *device, float percentage) { /* Validate arguments. */ R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetPercentageMaximumAlertThreshold(percentage)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().SetChargePercentageMaximumAlertThreshold(percentage)); return ResultSuccess(); } - Result BatteryDriver::SetBatteryPercentageFullThreshold(IDevice *device, float percentage) { + Result BatteryDriver::SetBatteryVoltageFuelGaugePercentageMinimumAlertThreshold(IDevice *device, float percentage) { /* Validate arguments. */ R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetPercentageFullThreshold(percentage)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().SetVoltageFuelGaugePercentageMinimumAlertThreshold(percentage)); + + return ResultSuccess(); + } + + Result BatteryDriver::SetBatteryVoltageFuelGaugePercentageMaximumAlertThreshold(IDevice *device, float percentage) { + /* Validate arguments. */ + R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); + + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().SetVoltageFuelGaugePercentageMaximumAlertThreshold(percentage)); + + return ResultSuccess(); + } + + Result BatteryDriver::SetBatteryFullChargeThreshold(IDevice *device, float percentage) { + /* Validate arguments. */ + R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); + + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().SetFullChargeThreshold(percentage)); return ResultSuccess(); } @@ -233,7 +240,7 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Get the value. */ double ma; - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetAverageCurrent(std::addressof(ma), SenseResistorValue)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetAverageCurrent(std::addressof(ma), SenseResistorValue)); /* Set output. */ *out_ma = ma; @@ -247,7 +254,7 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Get the value. */ double ma; - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetCurrent(std::addressof(ma), SenseResistorValue)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetCurrent(std::addressof(ma), SenseResistorValue)); /* Set output. */ *out_ma = ma; @@ -262,7 +269,7 @@ namespace ams::powctl::impl::board::nintendo::nx { R_UNLESS(dst_size == sizeof(max17050::InternalState), powctl::ResultInvalidArgument()); R_UNLESS(util::IsAligned(reinterpret_cast(dst), alignof(max17050::InternalState)), powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().ReadInternalState()); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().ReadInternalState()); GetMax17050Driver().GetInternalState(static_cast(dst)); return ResultSuccess(); @@ -276,7 +283,7 @@ namespace ams::powctl::impl::board::nintendo::nx { R_UNLESS(util::IsAligned(reinterpret_cast(src), alignof(max17050::InternalState)), powctl::ResultInvalidArgument()); GetMax17050Driver().SetInternalState(*static_cast(src)); - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().WriteInternalState()); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().WriteInternalState()); return ResultSuccess(); } @@ -287,7 +294,7 @@ namespace ams::powctl::impl::board::nintendo::nx { R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); /* Get the value. */ - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetNeedToRestoreParameters(out)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetNeedToRestoreParameters(out)); return ResultSuccess(); } @@ -297,7 +304,7 @@ namespace ams::powctl::impl::board::nintendo::nx { R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); /* Set the value. */ - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetNeedToRestoreParameters(en)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().SetNeedToRestoreParameters(en)); return ResultSuccess(); } @@ -308,7 +315,7 @@ namespace ams::powctl::impl::board::nintendo::nx { R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); /* Get the value. */ - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().IsI2cShutdownEnabled(out)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().IsI2cShutdownEnabled(out)); return ResultSuccess(); } @@ -318,7 +325,7 @@ namespace ams::powctl::impl::board::nintendo::nx { R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); /* Set the value. */ - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetI2cShutdownEnabled(en)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().SetI2cShutdownEnabled(en)); return ResultSuccess(); } @@ -330,7 +337,7 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Get the battery status. */ u16 status; - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetStatus(std::addressof(status))); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetStatus(std::addressof(status))); /* Set output. */ *out = (status & 0x0008) == 0; @@ -344,7 +351,7 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Get the battery cycles. */ u16 cycles; - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetCycles(std::addressof(cycles))); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetCycles(std::addressof(cycles))); /* Set output. */ *out = cycles; @@ -355,7 +362,7 @@ namespace ams::powctl::impl::board::nintendo::nx { R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(cycles == 0, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().ResetCycles()); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().ResetCycles()); return ResultSuccess(); } @@ -367,7 +374,7 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Get the value. */ double percent; - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetAge(std::addressof(percent))); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetAge(std::addressof(percent))); /* Set output. */ *out_percent = percent; @@ -381,7 +388,7 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Get the value. */ double temp; - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetTemperature(std::addressof(temp))); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetTemperature(std::addressof(temp))); /* Set output. */ *out_c = temp; @@ -395,7 +402,7 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Get the value. */ u8 max_temp; - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetMaximumTemperature(std::addressof(max_temp))); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetMaximumTemperature(std::addressof(max_temp))); /* Set output. */ *out_c = static_cast(max_temp); @@ -406,7 +413,7 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Validate arguments. */ R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetTemperatureMinimumAlertThreshold(c)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().SetTemperatureMinimumAlertThreshold(c)); return ResultSuccess(); } @@ -415,7 +422,7 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Validate arguments. */ R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetTemperatureMaximumAlertThreshold(c)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().SetTemperatureMaximumAlertThreshold(c)); return ResultSuccess(); } @@ -426,7 +433,7 @@ namespace ams::powctl::impl::board::nintendo::nx { R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); /* Get the value. */ - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetVCell(out_mv)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetVCell(out_mv)); return ResultSuccess(); } @@ -437,7 +444,7 @@ namespace ams::powctl::impl::board::nintendo::nx { R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); /* Get the value. */ - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetAverageVCell(out_mv)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetAverageVCell(out_mv)); return ResultSuccess(); } @@ -449,7 +456,7 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Get the value. */ double ms; - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetAverageVCellTime(std::addressof(ms))); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetAverageVCellTime(std::addressof(ms))); /* Set output. */ *out = TimeSpan::FromMicroSeconds(static_cast(ms * 1000.0)); @@ -460,7 +467,7 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Validate arguments. */ R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetVoltageMinimumAlertThreshold(mv)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().SetVoltageMinimumAlertThreshold(mv)); return ResultSuccess(); } @@ -471,7 +478,7 @@ namespace ams::powctl::impl::board::nintendo::nx { R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); /* Get the value. */ - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetOpenCircuitVoltage(out_mv)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetOpenCircuitVoltage(out_mv)); return ResultSuccess(); } @@ -480,7 +487,7 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Validate arguments. */ R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetVoltageMaximumAlertThreshold(mv)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().SetVoltageMaximumAlertThreshold(mv)); return ResultSuccess(); } diff --git a/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_battery_driver.hpp b/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_battery_driver.hpp index a8a963f75..0af47a18e 100644 --- a/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_battery_driver.hpp +++ b/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_battery_driver.hpp @@ -58,16 +58,19 @@ namespace ams::powctl::impl::board::nintendo::nx { virtual Result SetDeviceErrorStatus(IDevice *device, u32 status) override; /* Battery API. */ - virtual Result GetBatterySocRep(float *out_percent, IDevice *device) override; - - virtual Result GetBatterySocVf(float *out_percent, IDevice *device) override; + virtual Result GetBatteryChargePercentage(float *out_percent, IDevice *device) override; + virtual Result GetBatteryVoltageFuelGaugePercentage(float *out_percent, IDevice *device) override; virtual Result GetBatteryFullCapacity(int *out_mah, IDevice *device) override; virtual Result GetBatteryRemainingCapacity(int *out_mah, IDevice *device) override; - virtual Result SetBatteryPercentageMinimumAlertThreshold(IDevice *device, float percentage) override; - virtual Result SetBatteryPercentageMaximumAlertThreshold(IDevice *device, float percentage) override; - virtual Result SetBatteryPercentageFullThreshold(IDevice *device, float percentage) override; + virtual Result SetBatteryChargePercentageMinimumAlertThreshold(IDevice *device, float percentage) override; + virtual Result SetBatteryChargePercentageMaximumAlertThreshold(IDevice *device, float percentage) override; + + virtual Result SetBatteryVoltageFuelGaugePercentageMinimumAlertThreshold(IDevice *device, float percentage) override; + virtual Result SetBatteryVoltageFuelGaugePercentageMaximumAlertThreshold(IDevice *device, float percentage) override; + + virtual Result SetBatteryFullChargeThreshold(IDevice *device, float percentage) override; virtual Result GetBatteryAverageCurrent(int *out_ma, IDevice *device) override; virtual Result GetBatteryCurrent(int *out_ma, IDevice *device) override; diff --git a/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_bq24193_driver.cpp b/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_bq24193_driver.cpp index 57e4fc878..bd8dc244d 100644 --- a/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_bq24193_driver.cpp +++ b/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_bq24193_driver.cpp @@ -84,8 +84,9 @@ namespace ams::powctl::impl::board::nintendo::nx { constexpr int DecodeChargeVoltageLimit(u8 reg) { constexpr int Minimum = 3504; + constexpr int Maximum = 4400; - return Minimum + (static_cast(reg & 0xFC) << 2); + return std::min(Maximum, Minimum + (static_cast(reg & 0xFC) << 2)); } static_assert(DecodeChargeVoltageLimit(EncodeChargeVoltageLimit(3504)) == 3504); diff --git a/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_bq24193_driver.hpp b/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_bq24193_driver.hpp index 6b684ef0d..f050bf946 100644 --- a/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_bq24193_driver.hpp +++ b/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_bq24193_driver.hpp @@ -43,7 +43,7 @@ namespace ams::powctl::impl::board::nintendo::nx { private: Result InitializeSession(); public: - Bq24193Driver() : m_mutex(), m_init_count(0), m_i2c_session() { + constexpr Bq24193Driver() : m_mutex(), m_init_count(0), m_i2c_session() { /* ... */ } diff --git a/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_charger_driver.cpp b/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_charger_driver.cpp index f5b8227b9..361397ef7 100644 --- a/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_charger_driver.cpp +++ b/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_charger_driver.cpp @@ -25,21 +25,10 @@ namespace ams::powctl::impl::board::nintendo::nx { constinit util::optional g_charger_device; - constinit util::TypedStorage g_bq24193_driver; - constinit bool g_constructed_bq24193_driver; - constinit os::SdkMutex g_bq24193_driver_mutex; + constinit Bq24193Driver g_bq24193_driver; - Bq24193Driver &GetBq24193Driver() { - if (AMS_UNLIKELY(!g_constructed_bq24193_driver)) { - std::scoped_lock lk(g_bq24193_driver_mutex); - - if (AMS_LIKELY(!g_constructed_bq24193_driver)) { - util::ConstructAt(g_bq24193_driver); - g_constructed_bq24193_driver = true; - } - } - - return util::GetReference(g_bq24193_driver); + ALWAYS_INLINE Bq24193Driver &GetBq24193Driver() { + return g_bq24193_driver; } } @@ -141,13 +130,15 @@ namespace ams::powctl::impl::board::nintendo::nx { R_UNLESS(out != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); + /* NOTE: Nintendo doesn't hold the mutex while doing the gpio:: call here, for some reason. */ + /* Check if we're not charging. */ if (gpio::GetValue(device->SafeCastTo().GetPadSession()) == gpio::GpioValue_High) { *out = ChargeCurrentState_NotCharging; } else { /* Get force 20 percent charge state. */ bool force_20_percent; - AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().GetForce20PercentChargeCurrent(std::addressof(force_20_percent))); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().GetForce20PercentChargeCurrent(std::addressof(force_20_percent))); /* Set output appropriately. */ if (force_20_percent) { @@ -164,6 +155,8 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Validate arguments. */ R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); + std::scoped_lock lk(this->GetMutex()); + switch (state) { case ChargeCurrentState_NotCharging: gpio::SetValue(device->SafeCastTo().GetPadSession(), gpio::GpioValue_High); @@ -171,7 +164,7 @@ namespace ams::powctl::impl::board::nintendo::nx { case ChargeCurrentState_ChargingForce20Percent: case ChargeCurrentState_Charging: gpio::SetValue(device->SafeCastTo().GetPadSession(), gpio::GpioValue_Low); - AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetForce20PercentChargeCurrent(state == ChargeCurrentState_ChargingForce20Percent)); + AMS_POWCTL_DRIVER_R_TRY_WITH_RETRY(GetBq24193Driver().SetForce20PercentChargeCurrent(state == ChargeCurrentState_ChargingForce20Percent)); break; case ChargeCurrentState_Unknown: return powctl::ResultInvalidArgument(); @@ -185,7 +178,7 @@ namespace ams::powctl::impl::board::nintendo::nx { R_UNLESS(out_ma != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().GetFastChargeCurrentLimit(out_ma)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().GetFastChargeCurrentLimit(out_ma)); return ResultSuccess(); } @@ -193,7 +186,7 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Validate arguments. */ R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetFastChargeCurrentLimit(ma)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().SetFastChargeCurrentLimit(ma)); return ResultSuccess(); } @@ -202,7 +195,7 @@ namespace ams::powctl::impl::board::nintendo::nx { R_UNLESS(out_mv != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().GetChargeVoltageLimit(out_mv)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().GetChargeVoltageLimit(out_mv)); return ResultSuccess(); } @@ -210,7 +203,7 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Validate arguments. */ R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetChargeVoltageLimit(mv)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().SetChargeVoltageLimit(mv)); return ResultSuccess(); } @@ -226,7 +219,7 @@ namespace ams::powctl::impl::board::nintendo::nx { AMS_UNREACHABLE_DEFAULT_CASE(); } - AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetChargerConfiguration(bq_cfg)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().SetChargerConfiguration(bq_cfg)); return ResultSuccess(); } @@ -235,7 +228,7 @@ namespace ams::powctl::impl::board::nintendo::nx { R_UNLESS(out != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().IsHiZEnabled(out)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().IsHiZEnabled(out)); return ResultSuccess(); } @@ -243,7 +236,7 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Validate arguments. */ R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetHiZEnabled(en)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().SetHiZEnabled(en)); return ResultSuccess(); } @@ -252,7 +245,7 @@ namespace ams::powctl::impl::board::nintendo::nx { R_UNLESS(out_ma != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().GetInputCurrentLimit(out_ma)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().GetInputCurrentLimit(out_ma)); return ResultSuccess(); } @@ -260,7 +253,7 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Validate arguments. */ R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetInputCurrentLimit(ma)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().SetInputCurrentLimit(ma)); return ResultSuccess(); } @@ -268,7 +261,7 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Validate arguments. */ R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetInputVoltageLimit(mv)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().SetInputVoltageLimit(mv)); return ResultSuccess(); } @@ -276,7 +269,7 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Validate arguments. */ R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetBoostModeCurrentLimit(ma)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().SetBoostModeCurrentLimit(ma)); return ResultSuccess(); } @@ -285,7 +278,7 @@ namespace ams::powctl::impl::board::nintendo::nx { R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); bq24193::ChargerStatus bq_status; - AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().GetChargerStatus(std::addressof(bq_status))); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().GetChargerStatus(std::addressof(bq_status))); switch (bq_status) { case bq24193::ChargerStatus_NotCharging: @@ -320,10 +313,11 @@ namespace ams::powctl::impl::board::nintendo::nx { auto &charger_device = device->SafeCastTo(); if (en) { - AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().ResetWatchdogTimer()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetWatchdogTimerSetting(charger_device.GetWatchdogTimerTimeout().GetSeconds())); + std::scoped_lock lk(this->GetMutex()); + AMS_POWCTL_DRIVER_R_TRY_WITH_RETRY(GetBq24193Driver().ResetWatchdogTimer()); + AMS_POWCTL_DRIVER_R_TRY_WITH_RETRY(GetBq24193Driver().SetWatchdogTimerSetting(charger_device.GetWatchdogTimerTimeout().GetSeconds())); } else { - AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetWatchdogTimerSetting(0)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().SetWatchdogTimerSetting(0)); } charger_device.SetWatchdogTimerEnabled(en); @@ -342,7 +336,7 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Validate arguments. */ R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().ResetWatchdogTimer()); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().ResetWatchdogTimer()); return ResultSuccess(); } @@ -351,7 +345,7 @@ namespace ams::powctl::impl::board::nintendo::nx { R_UNLESS(out_mo != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().GetBatteryCompensation(out_mo)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().GetBatteryCompensation(out_mo)); return ResultSuccess(); } @@ -359,7 +353,7 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Validate arguments. */ R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetBatteryCompensation(mo)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().SetBatteryCompensation(mo)); return ResultSuccess(); } @@ -368,7 +362,7 @@ namespace ams::powctl::impl::board::nintendo::nx { R_UNLESS(out_mv != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().GetVoltageClamp(out_mv)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().GetVoltageClamp(out_mv)); return ResultSuccess(); } @@ -376,7 +370,7 @@ namespace ams::powctl::impl::board::nintendo::nx { /* Validate arguments. */ R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); - AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetVoltageClamp(mv)); + AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().SetVoltageClamp(mv)); return ResultSuccess(); } diff --git a/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_charger_driver.hpp b/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_charger_driver.hpp index 588dc28e5..5bb90bca7 100644 --- a/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_charger_driver.hpp +++ b/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_charger_driver.hpp @@ -105,16 +105,20 @@ namespace ams::powctl::impl::board::nintendo::nx { virtual Result SetChargerVoltageClamp(IDevice *device, int mv) override; /* Unsupported Battery API. */ - virtual Result GetBatterySocRep(float *out_percent, IDevice *device) override { AMS_UNUSED(out_percent, device); return powctl::ResultNotSupported(); } + virtual Result GetBatteryChargePercentage(float *out_percent, IDevice *device) override { AMS_UNUSED(out_percent, device); return powctl::ResultNotSupported(); } - virtual Result GetBatterySocVf(float *out_percent, IDevice *device) override { AMS_UNUSED(out_percent, device); return powctl::ResultNotSupported(); } + virtual Result GetBatteryVoltageFuelGaugePercentage(float *out_percent, IDevice *device) override { AMS_UNUSED(out_percent, device); return powctl::ResultNotSupported(); } virtual Result GetBatteryFullCapacity(int *out_mah, IDevice *device) override { AMS_UNUSED(out_mah, device); return powctl::ResultNotSupported(); } virtual Result GetBatteryRemainingCapacity(int *out_mah, IDevice *device) override { AMS_UNUSED(out_mah, device); return powctl::ResultNotSupported(); } - virtual Result SetBatteryPercentageMinimumAlertThreshold(IDevice *device, float percentage) override { AMS_UNUSED(device, percentage); return powctl::ResultNotSupported(); } - virtual Result SetBatteryPercentageMaximumAlertThreshold(IDevice *device, float percentage) override { AMS_UNUSED(device, percentage); return powctl::ResultNotSupported(); } - virtual Result SetBatteryPercentageFullThreshold(IDevice *device, float percentage) override { AMS_UNUSED(device, percentage); return powctl::ResultNotSupported(); } + virtual Result SetBatteryChargePercentageMinimumAlertThreshold(IDevice *device, float percentage) override { AMS_UNUSED(device, percentage); return powctl::ResultNotSupported(); } + virtual Result SetBatteryChargePercentageMaximumAlertThreshold(IDevice *device, float percentage) override { AMS_UNUSED(device, percentage); return powctl::ResultNotSupported(); } + + virtual Result SetBatteryVoltageFuelGaugePercentageMinimumAlertThreshold(IDevice *device, float percentage) override { AMS_UNUSED(device, percentage); return powctl::ResultNotSupported(); } + virtual Result SetBatteryVoltageFuelGaugePercentageMaximumAlertThreshold(IDevice *device, float percentage) override { AMS_UNUSED(device, percentage); return powctl::ResultNotSupported(); } + + virtual Result SetBatteryFullChargeThreshold(IDevice *device, float percentage) override { AMS_UNUSED(device, percentage); return powctl::ResultNotSupported(); } virtual Result GetBatteryAverageCurrent(int *out_ma, IDevice *device) override { AMS_UNUSED(out_ma, device); return powctl::ResultNotSupported(); } virtual Result GetBatteryCurrent(int *out_ma, IDevice *device) override { AMS_UNUSED(out_ma, device); return powctl::ResultNotSupported(); } diff --git a/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_max17050_driver.cpp b/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_max17050_driver.cpp index 24efcad04..66448f14d 100644 --- a/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_max17050_driver.cpp +++ b/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_max17050_driver.cpp @@ -330,11 +330,11 @@ namespace ams::powctl::impl::board::nintendo::nx { u16 vfsoc, qh; { R_TRY(ReadRegister(m_i2c_session, max17050::SocVf, std::addressof(vfsoc))); - R_TRY(this->UnlockVfSoc()); + R_TRY(this->UnlockVoltageFuelGauge()); while (!WriteValidateRegister(m_i2c_session, max17050::SocVf0, vfsoc)) { /* ... */ } R_TRY(ReadRegister(m_i2c_session, max17050::Qh, std::addressof(qh))); R_TRY(WriteRegister(m_i2c_session, max17050::Qh0, qh)); - R_TRY(this->LockVfSoc()); + R_TRY(this->LockVoltageFuelGauge()); } /* Reset cycles. */ @@ -371,6 +371,14 @@ namespace ams::powctl::impl::board::nintendo::nx { return WriteRegister(m_i2c_session, max17050::ShdnTimer, 0xE000); } + Result Max17050Driver::SetAlertByChargePercentage() { + return ReadWriteRegister(m_i2c_session, max17050::MiscCfg, 0x0003, 0x0000); + } + + Result Max17050Driver::SetAlertByVoltageFuelGaugePercentage() { + return ReadWriteRegister(m_i2c_session, max17050::MiscCfg, 0x0003, 0x0003); + } + bool Max17050Driver::IsPowerOnReset() { /* Get the register. */ u16 val; @@ -380,11 +388,11 @@ namespace ams::powctl::impl::board::nintendo::nx { return (val & 0x0002) != 0; } - Result Max17050Driver::LockVfSoc() { + Result Max17050Driver::LockVoltageFuelGauge() { return WriteRegister(m_i2c_session, max17050::SocVfAccess, 0x0000); } - Result Max17050Driver::UnlockVfSoc() { + Result Max17050Driver::UnlockVoltageFuelGauge() { return WriteRegister(m_i2c_session, max17050::SocVfAccess, 0x0080); } @@ -479,7 +487,7 @@ namespace ams::powctl::impl::board::nintendo::nx { return ResultSuccess(); } - Result Max17050Driver::GetSocRep(double *out) { + Result Max17050Driver::GetChargePercentage(double *out) { /* Validate parameters. */ AMS_ABORT_UNLESS(out != nullptr); @@ -492,7 +500,7 @@ namespace ams::powctl::impl::board::nintendo::nx { return ResultSuccess(); } - Result Max17050Driver::GetSocVf(double *out) { + Result Max17050Driver::GetVoltageFuelGaugePercentage(double *out) { /* Validate parameters. */ AMS_ABORT_UNLESS(out != nullptr); @@ -535,15 +543,27 @@ namespace ams::powctl::impl::board::nintendo::nx { return ResultSuccess(); } - Result Max17050Driver::SetPercentageMinimumAlertThreshold(int percentage) { + Result Max17050Driver::SetChargePercentageMinimumAlertThreshold(int percentage) { + R_TRY(this->SetAlertByChargePercentage()); return ReadWriteRegister(m_i2c_session, max17050::SocAlrtThreshold, 0x00FF, static_cast(percentage)); } - Result Max17050Driver::SetPercentageMaximumAlertThreshold(int percentage) { + Result Max17050Driver::SetChargePercentageMaximumAlertThreshold(int percentage) { + R_TRY(this->SetAlertByChargePercentage()); return ReadWriteRegister(m_i2c_session, max17050::SocAlrtThreshold, 0xFF00, static_cast(static_cast(percentage)) << 8); } - Result Max17050Driver::SetPercentageFullThreshold(double percentage) { + Result Max17050Driver::SetVoltageFuelGaugePercentageMinimumAlertThreshold(int percentage) { + R_TRY(this->SetAlertByVoltageFuelGaugePercentage()); + return ReadWriteRegister(m_i2c_session, max17050::SocAlrtThreshold, 0x00FF, static_cast(percentage)); + } + + Result Max17050Driver::SetVoltageFuelGaugePercentageMaximumAlertThreshold(int percentage) { + R_TRY(this->SetAlertByVoltageFuelGaugePercentage()); + return ReadWriteRegister(m_i2c_session, max17050::SocAlrtThreshold, 0xFF00, static_cast(static_cast(percentage)) << 8); + } + + Result Max17050Driver::SetFullChargeThreshold(double percentage) { #if defined(ATMOSPHERE_ARCH_ARM64) const u16 val = vcvtd_n_s64_f64(percentage, BITSIZEOF(u8)); #else diff --git a/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_max17050_driver.hpp b/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_max17050_driver.hpp index 3849439d3..0041354da 100644 --- a/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_max17050_driver.hpp +++ b/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_max17050_driver.hpp @@ -45,16 +45,19 @@ namespace ams::powctl::impl::board::nintendo::nx { Result InitializeSession(const char *battery_vendor, u8 battery_version); Result SetMaximumShutdownTimerThreshold(); + Result SetAlertByChargePercentage(); + Result SetAlertByVoltageFuelGaugePercentage(); + bool IsPowerOnReset(); - Result LockVfSoc(); - Result UnlockVfSoc(); + Result LockVoltageFuelGauge(); + Result UnlockVoltageFuelGauge(); Result LockModelTable(); Result UnlockModelTable(); bool IsModelTableLocked(); Result SetModelTable(const u16 *model_table); bool IsModelTableSet(const u16 *model_table); public: - Max17050Driver() : m_mutex(), m_init_count(0), m_i2c_session(), m_internal_state() { + constexpr Max17050Driver() : m_mutex(), m_init_count(0), m_i2c_session(), m_internal_state() { /* ... */ } @@ -97,16 +100,19 @@ namespace ams::powctl::impl::board::nintendo::nx { m_internal_state = src; } - Result GetSocRep(double *out); - Result GetSocVf(double *out); + Result GetChargePercentage(double *out); + Result GetVoltageFuelGaugePercentage(double *out); Result GetFullCapacity(double *out, double sense_resistor); Result GetRemainingCapacity(double *out, double sense_resistor); - Result SetPercentageMinimumAlertThreshold(int percentage); - Result SetPercentageMaximumAlertThreshold(int percentage); + Result SetChargePercentageMinimumAlertThreshold(int percentage); + Result SetChargePercentageMaximumAlertThreshold(int percentage); - Result SetPercentageFullThreshold(double percentage); + Result SetVoltageFuelGaugePercentageMinimumAlertThreshold(int percentage); + Result SetVoltageFuelGaugePercentageMaximumAlertThreshold(int percentage); + + Result SetFullChargeThreshold(double percentage); Result GetAverageCurrent(double *out, double sense_resistor); Result GetCurrent(double *out, double sense_resistor); diff --git a/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_retry_helper.hpp b/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_retry_helper.hpp index a1bfa8d2a..60e56c215 100644 --- a/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_retry_helper.hpp +++ b/libraries/libstratosphere/source/powctl/impl/board/nintendo/nx/powctl_retry_helper.hpp @@ -21,11 +21,11 @@ namespace ams::powctl::impl { constexpr inline const TimeSpan PowerControlRetryTimeout = TimeSpan::FromSeconds(10); constexpr inline const TimeSpan PowerControlRetryInterval = TimeSpan::FromMilliSeconds(20); - #define AMS_POWCTL_R_TRY_WITH_RETRY(__EXPR__) \ + #define AMS_POWCTL_DRIVER_R_TRY_WITH_RETRY(__EXPR__) \ ({ \ TimeSpan __powctl_retry_current_time = 0; \ while (true) { \ - const Result __powctl_retry_result = (__EXPR__); \ + const Result __powctl_retry_result = ( __EXPR__ ); \ if (R_SUCCEEDED(__powctl_retry_result)) { \ break; \ } \ @@ -37,5 +37,6 @@ namespace ams::powctl::impl { } \ }) + #define AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(__EXPR__) AMS_POWCTL_DRIVER_R_TRY_WITH_RETRY( ({ std::scoped_lock lk(this->GetMutex()); ( __EXPR__ ); }) ) } diff --git a/libraries/libstratosphere/source/powctl/impl/powctl_i_power_control_driver.hpp b/libraries/libstratosphere/source/powctl/impl/powctl_i_power_control_driver.hpp index 346e67fd3..34fc92032 100644 --- a/libraries/libstratosphere/source/powctl/impl/powctl_i_power_control_driver.hpp +++ b/libraries/libstratosphere/source/powctl/impl/powctl_i_power_control_driver.hpp @@ -33,12 +33,17 @@ namespace ams::powctl::impl { AMS_DDSF_CASTABLE_TRAITS(ams::powctl::impl::IPowerControlDriver, ::ams::ddsf::IDriver); private: bool m_event_handler_enabled; + os::SdkMutex m_mutex; protected: constexpr bool IsEventHandlerEnabled() const { return m_event_handler_enabled; } + + ALWAYS_INLINE os::SdkMutex &GetMutex() { + return m_mutex; + } public: - IPowerControlDriver(bool ev) : IDriver(), m_event_handler_enabled(ev) { /* ... */ } + IPowerControlDriver(bool ev) : IDriver(), m_event_handler_enabled(ev), m_mutex() { /* ... */ } virtual ~IPowerControlDriver() { /* ... */ } virtual void InitializeDriver() = 0; @@ -51,16 +56,19 @@ namespace ams::powctl::impl { virtual Result GetDeviceErrorStatus(u32 *out, IDevice *device) = 0; virtual Result SetDeviceErrorStatus(IDevice *device, u32 status) = 0; - virtual Result GetBatterySocRep(float *out_percent, IDevice *device) = 0; + virtual Result GetBatteryChargePercentage(float *out_percent, IDevice *device) = 0; - virtual Result GetBatterySocVf(float *out_percent, IDevice *device) = 0; + virtual Result GetBatteryVoltageFuelGaugePercentage(float *out_percent, IDevice *device) = 0; virtual Result GetBatteryFullCapacity(int *out_mah, IDevice *device) = 0; virtual Result GetBatteryRemainingCapacity(int *out_mah, IDevice *device) = 0; - virtual Result SetBatteryPercentageMinimumAlertThreshold(IDevice *device, float percentage) = 0; - virtual Result SetBatteryPercentageMaximumAlertThreshold(IDevice *device, float percentage) = 0; - virtual Result SetBatteryPercentageFullThreshold(IDevice *device, float percentage) = 0; + virtual Result SetBatteryChargePercentageMinimumAlertThreshold(IDevice *device, float percentage) = 0; + virtual Result SetBatteryChargePercentageMaximumAlertThreshold(IDevice *device, float percentage) = 0; + virtual Result SetBatteryVoltageFuelGaugePercentageMinimumAlertThreshold(IDevice *device, float percentage) = 0; + virtual Result SetBatteryVoltageFuelGaugePercentageMaximumAlertThreshold(IDevice *device, float percentage) = 0; + + virtual Result SetBatteryFullChargeThreshold(IDevice *device, float percentage) = 0; virtual Result GetChargerChargeCurrentState(ChargeCurrentState *out, IDevice *device) = 0; virtual Result SetChargerChargeCurrentState(IDevice *device, ChargeCurrentState state) = 0; diff --git a/libraries/libstratosphere/source/powctl/powctl_battery_api.cpp b/libraries/libstratosphere/source/powctl/powctl_battery_api.cpp index 87746c439..89593ae07 100644 --- a/libraries/libstratosphere/source/powctl/powctl_battery_api.cpp +++ b/libraries/libstratosphere/source/powctl/powctl_battery_api.cpp @@ -30,7 +30,7 @@ namespace ams::powctl { } - Result GetBatterySocRep(float *out_percent, Session &session) { + Result GetBatteryChargePercentage(float *out_percent, Session &session) { /* Get the session impl. */ auto &impl = GetOpenSessionImpl(session); @@ -41,10 +41,10 @@ namespace ams::powctl { auto &device = impl.GetDevice().SafeCastTo(); /* Call into the driver. */ - return device.GetDriver().SafeCastTo().GetBatterySocRep(out_percent, std::addressof(device)); + return device.GetDriver().SafeCastTo().GetBatteryChargePercentage(out_percent, std::addressof(device)); } - Result GetBatterySocVf(float *out_percent, Session &session) { + Result GetBatteryVoltageFuelGaugePercentage(float *out_percent, Session &session) { /* Get the session impl. */ auto &impl = GetOpenSessionImpl(session); @@ -55,7 +55,7 @@ namespace ams::powctl { auto &device = impl.GetDevice().SafeCastTo(); /* Call into the driver. */ - return device.GetDriver().SafeCastTo().GetBatterySocVf(out_percent, std::addressof(device)); + return device.GetDriver().SafeCastTo().GetBatteryVoltageFuelGaugePercentage(out_percent, std::addressof(device)); } Result GetBatteryFullCapacity(int *out_mah, Session &session) { @@ -86,7 +86,7 @@ namespace ams::powctl { return device.GetDriver().SafeCastTo().GetBatteryRemainingCapacity(out_mah, std::addressof(device)); } - Result SetBatteryPercentageMinimumAlertThreshold(Session &session, float percentage) { + Result SetBatteryChargePercentageMinimumAlertThreshold(Session &session, float percentage) { /* Get the session impl. */ auto &impl = GetOpenSessionImpl(session); @@ -97,10 +97,10 @@ namespace ams::powctl { auto &device = impl.GetDevice().SafeCastTo(); /* Call into the driver. */ - return device.GetDriver().SafeCastTo().SetBatteryPercentageMinimumAlertThreshold(std::addressof(device), percentage); + return device.GetDriver().SafeCastTo().SetBatteryChargePercentageMinimumAlertThreshold(std::addressof(device), percentage); } - Result SetBatteryPercentageMaximumAlertThreshold(Session &session, float percentage) { + Result SetBatteryChargePercentageMaximumAlertThreshold(Session &session, float percentage) { /* Get the session impl. */ auto &impl = GetOpenSessionImpl(session); @@ -111,10 +111,10 @@ namespace ams::powctl { auto &device = impl.GetDevice().SafeCastTo(); /* Call into the driver. */ - return device.GetDriver().SafeCastTo().SetBatteryPercentageMaximumAlertThreshold(std::addressof(device), percentage); + return device.GetDriver().SafeCastTo().SetBatteryChargePercentageMaximumAlertThreshold(std::addressof(device), percentage); } - Result SetBatteryPercentageFullThreshold(Session &session, float percentage) { + Result SetBatteryVoltageFuelGaugePercentageMinimumAlertThreshold(Session &session, float percentage) { /* Get the session impl. */ auto &impl = GetOpenSessionImpl(session); @@ -125,7 +125,35 @@ namespace ams::powctl { auto &device = impl.GetDevice().SafeCastTo(); /* Call into the driver. */ - return device.GetDriver().SafeCastTo().SetBatteryPercentageFullThreshold(std::addressof(device), percentage); + return device.GetDriver().SafeCastTo().SetBatteryVoltageFuelGaugePercentageMinimumAlertThreshold(std::addressof(device), percentage); + } + + Result SetBatteryVoltageFuelGaugePercentageMaximumAlertThreshold(Session &session, float percentage) { + /* Get the session impl. */ + auto &impl = GetOpenSessionImpl(session); + + /* Check the access mode. */ + R_UNLESS(impl.CheckAccess(ddsf::AccessMode_Write), ddsf::ResultPermissionDenied()); + + /* Get the device. */ + auto &device = impl.GetDevice().SafeCastTo(); + + /* Call into the driver. */ + return device.GetDriver().SafeCastTo().SetBatteryVoltageFuelGaugePercentageMaximumAlertThreshold(std::addressof(device), percentage); + } + + Result SetBatteryFullChargeThreshold(Session &session, float percentage) { + /* Get the session impl. */ + auto &impl = GetOpenSessionImpl(session); + + /* Check the access mode. */ + R_UNLESS(impl.CheckAccess(ddsf::AccessMode_Write), ddsf::ResultPermissionDenied()); + + /* Get the device. */ + auto &device = impl.GetDevice().SafeCastTo(); + + /* Call into the driver. */ + return device.GetDriver().SafeCastTo().SetBatteryFullChargeThreshold(std::addressof(device), percentage); } Result GetBatteryAverageCurrent(int *out_ma, Session &session) { diff --git a/stratosphere/boot/source/boot_battery_driver.hpp b/stratosphere/boot/source/boot_battery_driver.hpp index 59664cc5b..3d3ef63e4 100644 --- a/stratosphere/boot/source/boot_battery_driver.hpp +++ b/stratosphere/boot/source/boot_battery_driver.hpp @@ -19,55 +19,62 @@ namespace ams::boot { class BatteryDriver { + NON_COPYABLE(BatteryDriver); + NON_MOVEABLE(BatteryDriver); private: - powctl::Session m_battery_session; + static constinit inline powctl::Session s_battery_session{powctl::Session::ConstantInitializeTag{}}; + static constinit inline int s_reference_count{0}; public: - BatteryDriver() : m_battery_session() { - R_ABORT_UNLESS(powctl::OpenSession(std::addressof(m_battery_session), powctl::DeviceCode_Max17050, ddsf::AccessMode_ReadWrite)); + BatteryDriver() { + if ((s_reference_count++) == 0) { + R_ABORT_UNLESS(powctl::OpenSession(std::addressof(s_battery_session), powctl::DeviceCode_Max17050, ddsf::AccessMode_ReadWrite)); + } } ~BatteryDriver() { - powctl::CloseSession(m_battery_session); + if ((--s_reference_count) == 0) { + powctl::CloseSession(s_battery_session); + } } public: Result IsBatteryRemoved(bool *out) { bool present; - R_TRY(powctl::IsBatteryPresent(std::addressof(present), m_battery_session)); + R_TRY(powctl::IsBatteryPresent(std::addressof(present), s_battery_session)); *out = !present; return ResultSuccess(); } - Result GetSocRep(float *out) { - return powctl::GetBatterySocRep(out, m_battery_session); + Result GetChargePercentage(float *out) { + return powctl::GetBatteryChargePercentage(out, s_battery_session); } Result GetAverageVCell(int *out) { - return powctl::GetBatteryAverageVCell(out, m_battery_session); + return powctl::GetBatteryAverageVCell(out, s_battery_session); } Result GetOpenCircuitVoltage(int *out) { - return powctl::GetBatteryOpenCircuitVoltage(out, m_battery_session); + return powctl::GetBatteryOpenCircuitVoltage(out, s_battery_session); } Result GetAverageCurrent(int *out) { - return powctl::GetBatteryAverageCurrent(out, m_battery_session); + return powctl::GetBatteryAverageCurrent(out, s_battery_session); } Result GetCurrent(int *out) { - return powctl::GetBatteryCurrent(out, m_battery_session); + return powctl::GetBatteryCurrent(out, s_battery_session); } Result GetTemperature(float *out) { - return powctl::GetBatteryTemperature(out, m_battery_session); + return powctl::GetBatteryTemperature(out, s_battery_session); } Result IsI2cShutdownEnabled(bool *out) { - return powctl::IsBatteryI2cShutdownEnabled(out, m_battery_session); + return powctl::IsBatteryI2cShutdownEnabled(out, s_battery_session); } Result SetI2cShutdownEnabled(bool en) { - return powctl::SetBatteryI2cShutdownEnabled(m_battery_session, en); + return powctl::SetBatteryI2cShutdownEnabled(s_battery_session, en); } }; diff --git a/stratosphere/boot/source/boot_check_battery.cpp b/stratosphere/boot/source/boot_check_battery.cpp index e8bdd981c..f911f4c31 100644 --- a/stratosphere/boot/source/boot_check_battery.cpp +++ b/stratosphere/boot/source/boot_check_battery.cpp @@ -357,7 +357,7 @@ namespace ams::boot { if (show_charging_display) { /* Get the raw battery charge. */ float raw_battery_charge; - if (R_FAILED(m_battery_driver.GetSocRep(std::addressof(raw_battery_charge)))) { + if (R_FAILED(m_battery_driver.GetChargePercentage(std::addressof(raw_battery_charge)))) { return CheckBatteryResult::Shutdown; } @@ -372,7 +372,7 @@ namespace ams::boot { while (true) { /* Get the raw battery charge. */ float raw_battery_charge; - if (R_FAILED(m_battery_driver.GetSocRep(std::addressof(raw_battery_charge)))) { + if (R_FAILED(m_battery_driver.GetChargePercentage(std::addressof(raw_battery_charge)))) { return CheckBatteryResult::Shutdown; } diff --git a/stratosphere/boot/source/boot_pmic_driver.cpp b/stratosphere/boot/source/boot_pmic_driver.cpp index 0303a0d12..d02f4068b 100644 --- a/stratosphere/boot/source/boot_pmic_driver.cpp +++ b/stratosphere/boot/source/boot_pmic_driver.cpp @@ -100,7 +100,7 @@ namespace ams::boot { bool use_desired_shutdown = true; if (spl::GetHardwareType() == spl::HardwareType::Hoag) { float battery_charge_raw; - if (R_FAILED(battery_driver.GetSocRep(std::addressof(battery_charge_raw))) || battery_charge_raw >= 80.0) { + if (R_FAILED(battery_driver.GetChargePercentage(std::addressof(battery_charge_raw))) || battery_charge_raw >= 80.0) { use_desired_shutdown = false; } }