early-access version 2835

This commit is contained in:
pineappleEA
2022-07-15 04:00:50 +02:00
parent 5c0ee5eba6
commit 0e7aef7e36
1173 changed files with 55320 additions and 18881 deletions

View File

@@ -128,7 +128,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
SUB(Service, PM) \
SUB(Service, PREPO) \
SUB(Service, PSC) \
SUB(Service, PSM) \
SUB(Service, PTM) \
SUB(Service, SET) \
SUB(Service, SM) \
SUB(Service, SPL) \

View File

@@ -95,7 +95,7 @@ enum class Class : u8 {
Service_PM, ///< The PM service
Service_PREPO, ///< The PREPO (Play report) service
Service_PSC, ///< The PSC service
Service_PSM, ///< The PSM service
Service_PTM, ///< The PTM service
Service_SET, ///< The SET (Settings) service
Service_SM, ///< The SM (Service manager) service
Service_SPL, ///< The SPL service

View File

@@ -67,7 +67,7 @@ std::unique_ptr<WallClock> CreateBestMatchingClock(u64 emulated_cpu_frequency,
const auto& caps = GetCPUCaps();
u64 rtsc_frequency = 0;
if (caps.invariant_tsc) {
rtsc_frequency = EstimateRDTSCFrequency();
rtsc_frequency = caps.tsc_frequency ? caps.tsc_frequency : EstimateRDTSCFrequency();
}
// Fallback to StandardWallClock if the hardware TSC does not have the precision greater than:

View File

@@ -161,6 +161,22 @@ static CPUCaps Detect() {
caps.invariant_tsc = Common::Bit<8>(cpu_id[3]);
}
if (max_std_fn >= 0x15) {
__cpuid(cpu_id, 0x15);
caps.tsc_crystal_ratio_denominator = cpu_id[0];
caps.tsc_crystal_ratio_numerator = cpu_id[1];
caps.crystal_frequency = cpu_id[2];
// Some CPU models might not return a crystal frequency.
// The CPU model can be detected to use the values from turbostat
// https://github.com/torvalds/linux/blob/master/tools/power/x86/turbostat/turbostat.c#L5569
// but it's easier to just estimate the TSC tick rate for these cases.
if (caps.tsc_crystal_ratio_denominator) {
caps.tsc_frequency = static_cast<u64>(caps.crystal_frequency) *
caps.tsc_crystal_ratio_numerator /
caps.tsc_crystal_ratio_denominator;
}
}
if (max_std_fn >= 0x16) {
__cpuid(cpu_id, 0x16);
caps.base_frequency = cpu_id[0];

View File

@@ -30,6 +30,11 @@ struct CPUCaps {
u32 max_frequency;
u32 bus_frequency;
u32 tsc_crystal_ratio_denominator;
u32 tsc_crystal_ratio_numerator;
u32 crystal_frequency;
u64 tsc_frequency; // Derived from the above three values
bool sse : 1;
bool sse2 : 1;
bool sse3 : 1;

View File

@@ -607,6 +607,10 @@ add_library(core STATIC
hle/service/psc/psc.h
hle/service/ptm/psm.cpp
hle/service/ptm/psm.h
hle/service/ptm/ptm.cpp
hle/service/ptm/ptm.h
hle/service/ptm/ts.cpp
hle/service/ptm/ts.h
hle/service/kernel_helpers.cpp
hle/service/kernel_helpers.h
hle/service/service.cpp

View File

@@ -290,7 +290,7 @@ protected:
void Get(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_ACC, "called user_id=0x{}", user_id.RawString());
ProfileBase profile_base{};
ProfileData data{};
UserData data{};
if (profile_manager.GetProfileBaseAndData(user_id, profile_base, data)) {
ctx.WriteBuffer(data);
IPC::ResponseBuilder rb{ctx, 16};
@@ -373,18 +373,18 @@ protected:
reinterpret_cast<const char*>(base.username.data()), base.username.size()),
base.timestamp, base.user_uuid.RawString());
if (user_data.size() < sizeof(ProfileData)) {
LOG_ERROR(Service_ACC, "ProfileData buffer too small!");
if (user_data.size() < sizeof(UserData)) {
LOG_ERROR(Service_ACC, "UserData buffer too small!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_INVALID_BUFFER);
return;
}
ProfileData data;
std::memcpy(&data, user_data.data(), sizeof(ProfileData));
UserData data;
std::memcpy(&data, user_data.data(), sizeof(UserData));
if (!profile_manager.SetProfileBaseAndData(user_id, base, data)) {
LOG_ERROR(Service_ACC, "Failed to update profile data and base!");
LOG_ERROR(Service_ACC, "Failed to update user data and base!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_FAILED_SAVE_DATA);
return;
@@ -406,15 +406,15 @@ protected:
reinterpret_cast<const char*>(base.username.data()), base.username.size()),
base.timestamp, base.user_uuid.RawString());
if (user_data.size() < sizeof(ProfileData)) {
LOG_ERROR(Service_ACC, "ProfileData buffer too small!");
if (user_data.size() < sizeof(UserData)) {
LOG_ERROR(Service_ACC, "UserData buffer too small!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_INVALID_BUFFER);
return;
}
ProfileData data;
std::memcpy(&data, user_data.data(), sizeof(ProfileData));
UserData data;
std::memcpy(&data, user_data.data(), sizeof(UserData));
Common::FS::IOFile image(GetImagePath(user_id), Common::FS::FileAccessMode::Write,
Common::FS::FileType::BinaryFile);

View File

@@ -22,7 +22,7 @@ struct UserRaw {
UUID uuid2{};
u64 timestamp{};
ProfileUsername username{};
ProfileData extra_data{};
UserData extra_data{};
};
static_assert(sizeof(UserRaw) == 0xC8, "UserRaw has incorrect size.");
@@ -263,7 +263,7 @@ UUID ProfileManager::GetLastOpenedUser() const {
/// Return the users profile base and the unknown arbitary data.
bool ProfileManager::GetProfileBaseAndData(std::optional<std::size_t> index, ProfileBase& profile,
ProfileData& data) const {
UserData& data) const {
if (GetProfileBase(index, profile)) {
data = profiles[*index].data;
return true;
@@ -272,15 +272,14 @@ bool ProfileManager::GetProfileBaseAndData(std::optional<std::size_t> index, Pro
}
/// Return the users profile base and the unknown arbitary data.
bool ProfileManager::GetProfileBaseAndData(UUID uuid, ProfileBase& profile,
ProfileData& data) const {
bool ProfileManager::GetProfileBaseAndData(UUID uuid, ProfileBase& profile, UserData& data) const {
const auto idx = GetUserIndex(uuid);
return GetProfileBaseAndData(idx, profile, data);
}
/// Return the users profile base and the unknown arbitary data.
bool ProfileManager::GetProfileBaseAndData(const ProfileInfo& user, ProfileBase& profile,
ProfileData& data) const {
UserData& data) const {
return GetProfileBaseAndData(user.user_uuid, profile, data);
}
@@ -318,7 +317,7 @@ bool ProfileManager::SetProfileBase(UUID uuid, const ProfileBase& profile_new) {
}
bool ProfileManager::SetProfileBaseAndData(Common::UUID uuid, const ProfileBase& profile_new,
const ProfileData& data_new) {
const UserData& data_new) {
const auto index = GetUserIndex(uuid);
if (index.has_value() && SetProfileBase(uuid, profile_new)) {
profiles[*index].data = data_new;

View File

@@ -22,7 +22,7 @@ using UserIDArray = std::array<Common::UUID, MAX_USERS>;
/// Contains extra data related to a user.
/// TODO: RE this structure
struct ProfileData {
struct UserData {
INSERT_PADDING_WORDS_NOINIT(1);
u32 icon_id;
u8 bg_color_id;
@@ -30,7 +30,7 @@ struct ProfileData {
INSERT_PADDING_BYTES_NOINIT(0x10);
INSERT_PADDING_BYTES_NOINIT(0x60);
};
static_assert(sizeof(ProfileData) == 0x80, "ProfileData structure has incorrect size");
static_assert(sizeof(UserData) == 0x80, "UserData structure has incorrect size");
/// This holds general information about a users profile. This is where we store all the information
/// based on a specific user
@@ -38,7 +38,7 @@ struct ProfileInfo {
Common::UUID user_uuid{};
ProfileUsername username{};
u64 creation_time{};
ProfileData data{}; // TODO(ognik): Work out what this is
UserData data{}; // TODO(ognik): Work out what this is
bool is_open{};
};
@@ -74,10 +74,9 @@ public:
bool GetProfileBase(Common::UUID uuid, ProfileBase& profile) const;
bool GetProfileBase(const ProfileInfo& user, ProfileBase& profile) const;
bool GetProfileBaseAndData(std::optional<std::size_t> index, ProfileBase& profile,
ProfileData& data) const;
bool GetProfileBaseAndData(Common::UUID uuid, ProfileBase& profile, ProfileData& data) const;
bool GetProfileBaseAndData(const ProfileInfo& user, ProfileBase& profile,
ProfileData& data) const;
UserData& data) const;
bool GetProfileBaseAndData(Common::UUID uuid, ProfileBase& profile, UserData& data) const;
bool GetProfileBaseAndData(const ProfileInfo& user, ProfileBase& profile, UserData& data) const;
std::size_t GetUserCount() const;
std::size_t GetOpenUserCount() const;
bool UserExists(Common::UUID uuid) const;
@@ -93,7 +92,7 @@ public:
bool RemoveUser(Common::UUID uuid);
bool SetProfileBase(Common::UUID uuid, const ProfileBase& profile_new);
bool SetProfileBaseAndData(Common::UUID uuid, const ProfileBase& profile_new,
const ProfileData& data_new);
const UserData& data_new);
private:
void ParseUserSaveFile();

View File

@@ -237,6 +237,7 @@ IDebugFunctions::IDebugFunctions(Core::System& system_)
{130, nullptr, "FriendInvitationSetApplicationParameter"},
{131, nullptr, "FriendInvitationClearApplicationParameter"},
{132, nullptr, "FriendInvitationPushApplicationParameter"},
{140, nullptr, "RestrictPowerOperationForSecureLaunchModeForDebug"},
{900, nullptr, "GetGrcProcessLaunchedSystemEvent"},
};
// clang-format on
@@ -1316,6 +1317,8 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
{33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"},
{34, nullptr, "SelectApplicationLicense"},
{35, nullptr, "GetDeviceSaveDataSizeMax"},
{36, nullptr, "GetLimitedApplicationLicense"},
{37, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"},
{40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"},
{50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"},
{60, nullptr, "SetMediaPlaybackStateForApplication"},

View File

@@ -140,8 +140,8 @@ public:
{20401, nullptr, "UnregisterSystemApplicationDeliveryTask"},
{20410, nullptr, "SetSystemApplicationDeliveryTaskTimer"},
{30100, &IBcatService::SetPassphrase, "SetPassphrase"},
{30101, nullptr, "Unknown"},
{30102, nullptr, "Unknown2"},
{30101, nullptr, "Unknown30101"},
{30102, nullptr, "Unknown30102"},
{30200, nullptr, "RegisterBackgroundDeliveryTask"},
{30201, nullptr, "UnregisterBackgroundDeliveryTask"},
{30202, nullptr, "BlockDeliveryTask"},

View File

@@ -181,6 +181,11 @@ public:
{147, nullptr, "RegisterAudioControlNotification"},
{148, nullptr, "SendAudioControlPassthroughCommand"},
{149, nullptr, "SendAudioControlSetAbsoluteVolumeCommand"},
{150, nullptr, "AcquireAudioSinkVolumeLocallyChangedEvent"},
{151, nullptr, "AcquireAudioSinkVolumeUpdateRequestCompletedEvent"},
{152, nullptr, "GetAudioSinkVolume"},
{153, nullptr, "RequestUpdateAudioSinkVolume"},
{154, nullptr, "IsAudioSinkVolumeSupported"},
{256, nullptr, "IsManufacturingMode"},
{257, nullptr, "EmulateBluetoothCrash"},
{258, nullptr, "GetBleChannelMap"},

View File

@@ -214,8 +214,12 @@ public:
{76, nullptr, "Unknown76"},
{100, nullptr, "Unknown100"},
{101, nullptr, "Unknown101"},
{110, nullptr, "Unknown102"},
{111, nullptr, "Unknown103"},
{110, nullptr, "Unknown110"},
{111, nullptr, "Unknown111"},
{112, nullptr, "Unknown112"},
{113, nullptr, "Unknown113"},
{114, nullptr, "Unknown114"},
{115, nullptr, "Unknown115"},
};
// clang-format on

View File

@@ -6,7 +6,13 @@
namespace Service::Fatal {
Fatal_P::Fatal_P(std::shared_ptr<Module> module_, Core::System& system_)
: Interface(std::move(module_), system_, "fatal:p") {}
: Interface(std::move(module_), system_, "fatal:p") {
static const FunctionInfo functions[] = {
{0, nullptr, "GetFatalEvent"},
{10, nullptr, "GetFatalContext"},
};
RegisterHandlers(functions);
}
Fatal_P::~Fatal_P() = default;

View File

@@ -30,6 +30,19 @@ enum class RequestState : u32 {
Connected = 3,
};
enum class InternetConnectionType : u8 {
WiFi = 1,
Ethernet = 2,
};
enum class InternetConnectionStatus : u8 {
ConnectingUnknown1,
ConnectingUnknown2,
ConnectingUnknown3,
ConnectingUnknown4,
Connected,
};
struct IpAddressSetting {
bool is_automatic{};
Network::IPv4Address current_address{};
@@ -271,6 +284,7 @@ private:
rb.Push(ResultSuccess);
rb.Push<u64>(client_id); // Client ID needs to be non zero otherwise it's considered invalid
}
void CreateScanRequest(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NIFM, "called");
@@ -279,6 +293,7 @@ private:
rb.Push(ResultSuccess);
rb.PushIpcInterface<IScanRequest>(system);
}
void CreateRequest(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NIFM, "called");
@@ -287,6 +302,7 @@ private:
rb.Push(ResultSuccess);
rb.PushIpcInterface<IRequest>(system);
}
void GetCurrentNetworkProfile(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
@@ -335,12 +351,14 @@ private:
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void RemoveNetworkProfile(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void GetCurrentIpAddress(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
@@ -354,6 +372,7 @@ private:
rb.Push(ResultSuccess);
rb.PushRaw(*ipv4);
}
void CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NIFM, "called");
@@ -369,6 +388,7 @@ private:
rb.PushIpcInterface<INetworkProfile>(system);
rb.PushRaw<u128>(uuid);
}
void GetCurrentIpConfigInfo(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
@@ -405,6 +425,7 @@ private:
rb.Push(ResultSuccess);
rb.PushRaw<IpConfigInfo>(ip_config_info);
}
void IsWirelessCommunicationEnabled(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
@@ -412,6 +433,24 @@ private:
rb.Push(ResultSuccess);
rb.Push<u8>(0);
}
void GetInternetConnectionStatus(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
struct Output {
InternetConnectionType type{InternetConnectionType::WiFi};
u8 wifi_strength{3};
InternetConnectionStatus state{InternetConnectionStatus::Connected};
};
static_assert(sizeof(Output) == 0x3, "Output has incorrect size.");
constexpr Output out{};
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.PushRaw(out);
}
void IsEthernetCommunicationEnabled(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
@@ -423,6 +462,7 @@ private:
rb.Push<u8>(0);
}
}
void IsAnyInternetRequestAccepted(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
@@ -456,7 +496,7 @@ IGeneralService::IGeneralService(Core::System& system_)
{15, &IGeneralService::GetCurrentIpConfigInfo, "GetCurrentIpConfigInfo"},
{16, nullptr, "SetWirelessCommunicationEnabled"},
{17, &IGeneralService::IsWirelessCommunicationEnabled, "IsWirelessCommunicationEnabled"},
{18, nullptr, "GetInternetConnectionStatus"},
{18, &IGeneralService::GetInternetConnectionStatus, "GetInternetConnectionStatus"},
{19, nullptr, "SetEthernetCommunicationEnabled"},
{20, &IGeneralService::IsEthernetCommunicationEnabled, "IsEthernetCommunicationEnabled"},
{21, &IGeneralService::IsAnyInternetRequestAccepted, "IsAnyInternetRequestAccepted"},

View File

@@ -9,10 +9,8 @@
#include "core/hle/kernel/k_event.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/ptm/psm.h"
#include "core/hle/service/service.h"
#include "core/hle/service/sm/sm.h"
namespace Service::PSM {
namespace Service::PTM {
class IPsmSession final : public ServiceFramework<IPsmSession> {
public:
@@ -57,7 +55,7 @@ public:
private:
void BindStateChangeEvent(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_PSM, "called");
LOG_DEBUG(Service_PTM, "called");
should_signal = true;
@@ -67,7 +65,7 @@ private:
}
void UnbindStateChangeEvent(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_PSM, "called");
LOG_DEBUG(Service_PTM, "called");
should_signal = false;
@@ -78,7 +76,7 @@ private:
void SetChargerTypeChangeEventEnabled(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto state = rp.Pop<bool>();
LOG_DEBUG(Service_PSM, "called, state={}", state);
LOG_DEBUG(Service_PTM, "called, state={}", state);
should_signal_charger_type = state;
@@ -89,7 +87,7 @@ private:
void SetPowerSupplyChangeEventEnabled(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto state = rp.Pop<bool>();
LOG_DEBUG(Service_PSM, "called, state={}", state);
LOG_DEBUG(Service_PTM, "called, state={}", state);
should_signal_power_supply = state;
@@ -100,7 +98,7 @@ private:
void SetBatteryVoltageStateChangeEventEnabled(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto state = rp.Pop<bool>();
LOG_DEBUG(Service_PSM, "called, state={}", state);
LOG_DEBUG(Service_PTM, "called, state={}", state);
should_signal_battery_voltage = state;
@@ -117,76 +115,58 @@ private:
Kernel::KEvent* state_change_event;
};
class PSM final : public ServiceFramework<PSM> {
public:
explicit PSM(Core::System& system_) : ServiceFramework{system_, "psm"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &PSM::GetBatteryChargePercentage, "GetBatteryChargePercentage"},
{1, &PSM::GetChargerType, "GetChargerType"},
{2, nullptr, "EnableBatteryCharging"},
{3, nullptr, "DisableBatteryCharging"},
{4, nullptr, "IsBatteryChargingEnabled"},
{5, nullptr, "AcquireControllerPowerSupply"},
{6, nullptr, "ReleaseControllerPowerSupply"},
{7, &PSM::OpenSession, "OpenSession"},
{8, nullptr, "EnableEnoughPowerChargeEmulation"},
{9, nullptr, "DisableEnoughPowerChargeEmulation"},
{10, nullptr, "EnableFastBatteryCharging"},
{11, nullptr, "DisableFastBatteryCharging"},
{12, nullptr, "GetBatteryVoltageState"},
{13, nullptr, "GetRawBatteryChargePercentage"},
{14, nullptr, "IsEnoughPowerSupplied"},
{15, nullptr, "GetBatteryAgePercentage"},
{16, nullptr, "GetBatteryChargeInfoEvent"},
{17, nullptr, "GetBatteryChargeInfoFields"},
{18, nullptr, "GetBatteryChargeCalibratedEvent"},
};
// clang-format on
RegisterHandlers(functions);
}
~PSM() override = default;
private:
void GetBatteryChargePercentage(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_PSM, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u32>(battery_charge_percentage);
}
void GetChargerType(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_PSM, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.PushEnum(charger_type);
}
void OpenSession(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_PSM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IPsmSession>(system);
}
enum class ChargerType : u32 {
Unplugged = 0,
RegularCharger = 1,
LowPowerCharger = 2,
Unknown = 3,
PSM::PSM(Core::System& system_) : ServiceFramework{system_, "psm"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &PSM::GetBatteryChargePercentage, "GetBatteryChargePercentage"},
{1, &PSM::GetChargerType, "GetChargerType"},
{2, nullptr, "EnableBatteryCharging"},
{3, nullptr, "DisableBatteryCharging"},
{4, nullptr, "IsBatteryChargingEnabled"},
{5, nullptr, "AcquireControllerPowerSupply"},
{6, nullptr, "ReleaseControllerPowerSupply"},
{7, &PSM::OpenSession, "OpenSession"},
{8, nullptr, "EnableEnoughPowerChargeEmulation"},
{9, nullptr, "DisableEnoughPowerChargeEmulation"},
{10, nullptr, "EnableFastBatteryCharging"},
{11, nullptr, "DisableFastBatteryCharging"},
{12, nullptr, "GetBatteryVoltageState"},
{13, nullptr, "GetRawBatteryChargePercentage"},
{14, nullptr, "IsEnoughPowerSupplied"},
{15, nullptr, "GetBatteryAgePercentage"},
{16, nullptr, "GetBatteryChargeInfoEvent"},
{17, nullptr, "GetBatteryChargeInfoFields"},
{18, nullptr, "GetBatteryChargeCalibratedEvent"},
};
// clang-format on
u32 battery_charge_percentage{100}; // 100%
ChargerType charger_type{ChargerType::RegularCharger};
};
void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
std::make_shared<PSM>(system)->InstallAsService(sm);
RegisterHandlers(functions);
}
} // namespace Service::PSM
PSM::~PSM() = default;
void PSM::GetBatteryChargePercentage(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_PTM, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u32>(battery_charge_percentage);
}
void PSM::GetChargerType(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_PTM, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.PushEnum(charger_type);
}
void PSM::OpenSession(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_PTM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IPsmSession>(system);
}
} // namespace Service::PTM

View File

@@ -3,16 +3,29 @@
#pragma once
namespace Core {
class System;
}
#include "core/hle/service/service.h"
namespace Service::SM {
class ServiceManager;
}
namespace Service::PTM {
namespace Service::PSM {
class PSM final : public ServiceFramework<PSM> {
public:
explicit PSM(Core::System& system_);
~PSM() override;
void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
private:
enum class ChargerType : u32 {
Unplugged = 0,
RegularCharger = 1,
LowPowerCharger = 2,
Unknown = 3,
};
} // namespace Service::PSM
void GetBatteryChargePercentage(Kernel::HLERequestContext& ctx);
void GetChargerType(Kernel::HLERequestContext& ctx);
void OpenSession(Kernel::HLERequestContext& ctx);
u32 battery_charge_percentage{100};
ChargerType charger_type{ChargerType::RegularCharger};
};
} // namespace Service::PTM

View File

@@ -0,0 +1,18 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include <memory>
#include "core/core.h"
#include "core/hle/service/ptm/psm.h"
#include "core/hle/service/ptm/ptm.h"
#include "core/hle/service/ptm/ts.h"
namespace Service::PTM {
void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
std::make_shared<PSM>(system)->InstallAsService(sm);
std::make_shared<TS>(system)->InstallAsService(sm);
}
} // namespace Service::PTM

18
src/core/hle/service/ptm/ptm.h Executable file
View File

@@ -0,0 +1,18 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
namespace Core {
class System;
}
namespace Service::SM {
class ServiceManager;
}
namespace Service::PTM {
void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
} // namespace Service::PTM

41
src/core/hle/service/ptm/ts.cpp Executable file
View File

@@ -0,0 +1,41 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include <memory>
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/ptm/ts.h"
namespace Service::PTM {
TS::TS(Core::System& system_) : ServiceFramework{system_, "ts"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetTemperatureRange"},
{1, &TS::GetTemperature, "GetTemperature"},
{2, nullptr, "SetMeasurementMode"},
{3, nullptr, "GetTemperatureMilliC"},
{4, nullptr, "OpenSession"},
};
// clang-format on
RegisterHandlers(functions);
}
TS::~TS() = default;
void TS::GetTemperature(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto location{rp.PopEnum<Location>()};
LOG_WARNING(Service_HID, "(STUBBED) called. location={}", location);
const s32 temperature = location == Location::Internal ? 35 : 20;
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(temperature);
}
} // namespace Service::PTM

25
src/core/hle/service/ptm/ts.h Executable file
View File

@@ -0,0 +1,25 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "common/common_types.h"
#include "core/hle/service/service.h"
namespace Service::PTM {
class TS final : public ServiceFramework<TS> {
public:
explicit TS(Core::System& system_);
~TS() override;
private:
enum class Location : u8 {
Internal,
External,
};
void GetTemperature(Kernel::HLERequestContext& ctx);
};
} // namespace Service::PTM

View File

@@ -58,7 +58,7 @@
#include "core/hle/service/pm/pm.h"
#include "core/hle/service/prepo/prepo.h"
#include "core/hle/service/psc/psc.h"
#include "core/hle/service/ptm/psm.h"
#include "core/hle/service/ptm/ptm.h"
#include "core/hle/service/service.h"
#include "core/hle/service/set/settings.h"
#include "core/hle/service/sm/sm.h"
@@ -287,7 +287,7 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system
PlayReport::InstallInterfaces(*sm, system);
PM::InstallInterfaces(system);
PSC::InstallInterfaces(*sm, system);
PSM::InstallInterfaces(*sm, system);
PTM::InstallInterfaces(*sm, system);
Set::InstallInterfaces(*sm, system);
Sockets::InstallInterfaces(*sm, system);
SPL::InstallInterfaces(*sm, system);