nfp: Move IUser class to header and add missing enum and structs

This commit is contained in:
german77 2021-06-16 01:03:56 -05:00
parent 3d24eb54ec
commit c001a2af25
2 changed files with 347 additions and 305 deletions

View File

@ -17,23 +17,9 @@ namespace ErrCodes {
constexpr ResultCode ERR_NO_APPLICATION_AREA(ErrorModule::NFP, 152); constexpr ResultCode ERR_NO_APPLICATION_AREA(ErrorModule::NFP, 152);
} // namespace ErrCodes } // namespace ErrCodes
Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& system_, IUser::IUser(Module::Interface& nfp_interface_, Core::System& system_)
const char* name)
: ServiceFramework{system_, name}, module{std::move(module_)}, service_context{system_,
"NFP::IUser"} {
nfc_tag_load = service_context.CreateEvent("NFP::IUser:NFCTagDetected");
}
Module::Interface::~Interface() {
service_context.CloseEvent(nfc_tag_load);
}
class IUser final : public ServiceFramework<IUser> {
public:
explicit IUser(Module::Interface& nfp_interface_, Core::System& system_,
KernelHelpers::ServiceContext& service_context_)
: ServiceFramework{system_, "NFP::IUser"}, nfp_interface{nfp_interface_}, : ServiceFramework{system_, "NFP::IUser"}, nfp_interface{nfp_interface_},
service_context{service_context_} { deactivate_event{system.Kernel()}, availability_change_event{system.Kernel()} {
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, &IUser::Initialize, "Initialize"}, {0, &IUser::Initialize, "Initialize"},
{1, &IUser::Finalize, "Finalize"}, {1, &IUser::Finalize, "Finalize"},
@ -63,73 +49,32 @@ public:
}; };
RegisterHandlers(functions); RegisterHandlers(functions);
deactivate_event = service_context.CreateEvent("NFP::IUser:DeactivateEvent"); Kernel::KAutoObject::Create(std::addressof(deactivate_event));
availability_change_event = Kernel::KAutoObject::Create(std::addressof(availability_change_event));
service_context.CreateEvent("NFP::IUser:AvailabilityChangeEvent");
}
~IUser() override { deactivate_event.Initialize("IUser:DeactivateEvent");
service_context.CloseEvent(deactivate_event); availability_change_event.Initialize("IUser:AvailabilityChangeEvent");
service_context.CloseEvent(availability_change_event); }
}
private: void IUser::Initialize(Kernel::HLERequestContext& ctx) {
struct TagInfo {
std::array<u8, 10> uuid;
u8 uuid_length; // TODO(ogniK): Figure out if this is actual the uuid length or does it
// mean something else
std::array<u8, 0x15> padding_1;
u32_le protocol;
u32_le tag_type;
std::array<u8, 0x2c> padding_2;
};
static_assert(sizeof(TagInfo) == 0x54, "TagInfo is an invalid size");
enum class State : u32 {
NonInitialized = 0,
Initialized = 1,
};
enum class DeviceState : u32 {
Initialized = 0,
SearchingForTag = 1,
TagFound = 2,
TagRemoved = 3,
TagNearby = 4,
Unknown5 = 5,
Finalized = 6
};
struct CommonInfo {
u16_be last_write_year;
u8 last_write_month;
u8 last_write_day;
u16_be write_counter;
u16_be version;
u32_be application_area_size;
INSERT_PADDING_BYTES(0x34);
};
static_assert(sizeof(CommonInfo) == 0x40, "CommonInfo is an invalid size");
void Initialize(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFC, "called"); LOG_DEBUG(Service_NFC, "called");
IPC::ResponseBuilder rb{ctx, 2, 0}; IPC::ResponseBuilder rb{ctx, 2, 0};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
state = State::Initialized; state = State::Initialized;
} }
void Finalize(Kernel::HLERequestContext& ctx) { void IUser::Finalize(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFP, "called"); LOG_DEBUG(Service_NFP, "called");
device_state = DeviceState::Finalized; device_state = DeviceState::Finalized;
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} }
void ListDevices(Kernel::HLERequestContext& ctx) { void IUser::ListDevices(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const u32 array_size = rp.Pop<u32>(); const u32 array_size = rp.Pop<u32>();
LOG_DEBUG(Service_NFP, "called, array_size={}", array_size); LOG_DEBUG(Service_NFP, "called, array_size={}", array_size);
@ -139,9 +84,9 @@ private:
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.Push<u32>(1); rb.Push<u32>(1);
} }
void StartDetection(Kernel::HLERequestContext& ctx) { void IUser::StartDetection(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFP, "called"); LOG_DEBUG(Service_NFP, "called");
if (device_state == DeviceState::Initialized || device_state == DeviceState::TagRemoved) { if (device_state == DeviceState::Initialized || device_state == DeviceState::TagRemoved) {
@ -149,15 +94,15 @@ private:
} }
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} }
void StopDetection(Kernel::HLERequestContext& ctx) { void IUser::StopDetection(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFP, "called"); LOG_DEBUG(Service_NFP, "called");
switch (device_state) { switch (device_state) {
case DeviceState::TagFound: case DeviceState::TagFound:
case DeviceState::TagNearby: case DeviceState::TagMounted:
deactivate_event->GetWritableEvent().Signal(); deactivate_event.GetWritableEvent().Signal();
device_state = DeviceState::Initialized; device_state = DeviceState::Initialized;
break; break;
case DeviceState::SearchingForTag: case DeviceState::SearchingForTag:
@ -169,32 +114,32 @@ private:
} }
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} }
void Mount(Kernel::HLERequestContext& ctx) { void IUser::Mount(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFP, "called"); LOG_DEBUG(Service_NFP, "called");
device_state = DeviceState::TagNearby; device_state = DeviceState::TagMounted;
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} }
void Unmount(Kernel::HLERequestContext& ctx) { void IUser::Unmount(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFP, "called"); LOG_DEBUG(Service_NFP, "called");
device_state = DeviceState::TagFound; device_state = DeviceState::TagFound;
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} }
void OpenApplicationArea(Kernel::HLERequestContext& ctx) { void IUser::OpenApplicationArea(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NFP, "(STUBBED) called"); LOG_WARNING(Service_NFP, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ErrCodes::ERR_NO_APPLICATION_AREA); rb.Push(ErrCodes::ERR_NO_APPLICATION_AREA);
} }
void GetApplicationArea(Kernel::HLERequestContext& ctx) { void IUser::GetApplicationArea(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NFP, "(STUBBED) called"); LOG_WARNING(Service_NFP, "(STUBBED) called");
// TODO(ogniK): Pull application area from amiibo // TODO(ogniK): Pull application area from amiibo
@ -202,9 +147,9 @@ private:
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushRaw<u32>(0); // This is from the GetCommonInfo stub rb.PushRaw<u32>(0); // This is from the GetCommonInfo stub
} }
void GetTagInfo(Kernel::HLERequestContext& ctx) { void IUser::GetTagInfo(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFP, "called"); LOG_DEBUG(Service_NFP, "called");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
@ -212,25 +157,23 @@ private:
const TagInfo tag_info{ const TagInfo tag_info{
.uuid = amiibo.uuid, .uuid = amiibo.uuid,
.uuid_length = static_cast<u8>(amiibo.uuid.size()), .uuid_length = static_cast<u8>(amiibo.uuid.size()),
.padding_1 = {},
.protocol = 1, // TODO(ogniK): Figure out actual values .protocol = 1, // TODO(ogniK): Figure out actual values
.tag_type = 2, .tag_type = 2,
.padding_2 = {},
}; };
ctx.WriteBuffer(tag_info); ctx.WriteBuffer(tag_info);
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} }
void GetRegisterInfo(Kernel::HLERequestContext& ctx) { void IUser::GetRegisterInfo(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NFP, "(STUBBED) called"); LOG_WARNING(Service_NFP, "(STUBBED) called");
// TODO(ogniK): Pull Mii and owner data from amiibo // TODO(ogniK): Pull Mii and owner data from amiibo
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} }
void GetCommonInfo(Kernel::HLERequestContext& ctx) { void IUser::GetCommonInfo(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NFP, "(STUBBED) called"); LOG_WARNING(Service_NFP, "(STUBBED) called");
// TODO(ogniK): Pull common information from amiibo // TODO(ogniK): Pull common information from amiibo
@ -241,18 +184,18 @@ private:
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} }
void GetModelInfo(Kernel::HLERequestContext& ctx) { void IUser::GetModelInfo(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFP, "called"); LOG_DEBUG(Service_NFP, "called");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
const auto& amiibo = nfp_interface.GetAmiiboBuffer(); const auto& amiibo = nfp_interface.GetAmiiboBuffer();
ctx.WriteBuffer(amiibo.model_info); ctx.WriteBuffer(amiibo.model_info);
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} }
void AttachActivateEvent(Kernel::HLERequestContext& ctx) { void IUser::AttachActivateEvent(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const u64 dev_handle = rp.Pop<u64>(); const u64 dev_handle = rp.Pop<u64>();
LOG_DEBUG(Service_NFP, "called, dev_handle=0x{:X}", dev_handle); LOG_DEBUG(Service_NFP, "called, dev_handle=0x{:X}", dev_handle);
@ -261,9 +204,9 @@ private:
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushCopyObjects(nfp_interface.GetNFCEvent()); rb.PushCopyObjects(nfp_interface.GetNFCEvent());
has_attached_handle = true; has_attached_handle = true;
} }
void AttachDeactivateEvent(Kernel::HLERequestContext& ctx) { void IUser::AttachDeactivateEvent(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const u64 dev_handle = rp.Pop<u64>(); const u64 dev_handle = rp.Pop<u64>();
LOG_DEBUG(Service_NFP, "called, dev_handle=0x{:X}", dev_handle); LOG_DEBUG(Service_NFP, "called, dev_handle=0x{:X}", dev_handle);
@ -271,25 +214,25 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1}; IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushCopyObjects(deactivate_event.GetReadableEvent()); rb.PushCopyObjects(deactivate_event.GetReadableEvent());
} }
void GetState(Kernel::HLERequestContext& ctx) { void IUser::GetState(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFC, "called"); LOG_DEBUG(Service_NFC, "called");
IPC::ResponseBuilder rb{ctx, 3, 0}; IPC::ResponseBuilder rb{ctx, 3, 0};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushRaw<u32>(static_cast<u32>(state)); rb.PushRaw<u32>(static_cast<u32>(state));
} }
void GetDeviceState(Kernel::HLERequestContext& ctx) { void IUser::GetDeviceState(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFP, "called"); LOG_DEBUG(Service_NFP, "called");
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.Push<u32>(static_cast<u32>(device_state)); rb.Push<u32>(static_cast<u32>(device_state));
} }
void GetNpadId(Kernel::HLERequestContext& ctx) { void IUser::GetNpadId(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const u64 dev_handle = rp.Pop<u64>(); const u64 dev_handle = rp.Pop<u64>();
LOG_DEBUG(Service_NFP, "called, dev_handle=0x{:X}", dev_handle); LOG_DEBUG(Service_NFP, "called, dev_handle=0x{:X}", dev_handle);
@ -297,35 +240,32 @@ private:
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.Push<u32>(npad_id); rb.Push<u32>(npad_id);
} }
void GetApplicationAreaSize(Kernel::HLERequestContext& ctx) { void IUser::GetApplicationAreaSize(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NFP, "(STUBBED) called"); LOG_WARNING(Service_NFP, "(STUBBED) called");
// We don't need to worry about this since we can just open the file // We don't need to worry about this since we can just open the file
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushRaw<u32>(0); // This is from the GetCommonInfo stub rb.PushRaw<u32>(0); // This is from the GetCommonInfo stub
} }
void AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx) { void IUser::AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NFP, "(STUBBED) called"); LOG_WARNING(Service_NFP, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1}; IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushCopyObjects(availability_change_event.GetReadableEvent()); rb.PushCopyObjects(availability_change_event.GetReadableEvent());
} }
Module::Interface& nfp_interface; Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& system_,
KernelHelpers::ServiceContext& service_context; const char* name)
: ServiceFramework{system_, name}, nfc_tag_load{system.Kernel()}, module{std::move(module_)} {
Kernel::KAutoObject::Create(std::addressof(nfc_tag_load));
nfc_tag_load.Initialize("IUser:NFCTagDetected");
}
bool has_attached_handle{}; Module::Interface::~Interface() = default;
const u64 device_handle{0}; // Npad device 1
const u32 npad_id{0}; // Player 1 controller
State state{State::NonInitialized};
DeviceState device_state{DeviceState::Initialized};
Kernel::KEvent* deactivate_event;
Kernel::KEvent* availability_change_event;
};
void Module::Interface::CreateUserInterface(Kernel::HLERequestContext& ctx) { void Module::Interface::CreateUserInterface(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFP, "called"); LOG_DEBUG(Service_NFP, "called");

View File

@ -8,6 +8,8 @@
#include <vector> #include <vector>
#include "core/hle/service/kernel_helpers.h" #include "core/hle/service/kernel_helpers.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/service/mii/manager.h"
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
namespace Kernel { namespace Kernel {
@ -16,6 +18,106 @@ class KEvent;
namespace Service::NFP { namespace Service::NFP {
enum class ServiceType : u32 {
User = 0,
Debug = 1,
System = 2,
};
enum class State : u32 {
NonInitialized = 0,
Initialized = 1,
};
enum class DeviceState : u32 {
Initialized = 0,
SearchingForTag = 1,
TagFound = 2,
TagRemoved = 3,
TagMounted = 4,
Unaviable = 5,
Finalized = 6
};
enum class MountTarget : u32 {
Rom = 1,
Ram = 2,
All = 3,
};
struct TagInfo {
std::array<u8, 10> uuid;
u8 uuid_length;
INSERT_PADDING_BYTES(0x15);
u32_le protocol;
u32_le tag_type;
INSERT_PADDING_BYTES(0x2c);
};
static_assert(sizeof(TagInfo) == 0x54, "TagInfo is an invalid size");
struct CommonInfo {
u16_be last_write_year;
u8 last_write_month;
u8 last_write_day;
u16_be write_counter;
u16_be version;
u32_be application_area_size;
INSERT_PADDING_BYTES(0x34);
};
static_assert(sizeof(CommonInfo) == 0x40, "CommonInfo is an invalid size");
struct ModelInfo {
std::array<u8, 0x8> ammibo_id;
INSERT_PADDING_BYTES(0x38);
};
static_assert(sizeof(ModelInfo) == 0x40, "ModelInfo is an invalid size");
struct RegisterInfo {
Service::Mii::MiiInfo mii;
u16_be first_write_year;
u8 first_write_month;
u8 first_write_day;
std::array<u8, 11> amiibo_name;
INSERT_PADDING_BYTES(0x99);
};
// static_assert(sizeof(RegisterInfo) == 0x106, "RegisterInfo is an invalid size");
class IUser final : public ServiceFramework<IUser> {
public:
explicit IUser(Module::Interface& nfp_interface_, Core::System& system_);
private:
void Initialize(Kernel::HLERequestContext& ctx);
void Finalize(Kernel::HLERequestContext& ctx);
void ListDevices(Kernel::HLERequestContext& ctx);
void StartDetection(Kernel::HLERequestContext& ctx);
void StopDetection(Kernel::HLERequestContext& ctx);
void Mount(Kernel::HLERequestContext& ctx);
void Unmount(Kernel::HLERequestContext& ctx);
void OpenApplicationArea(Kernel::HLERequestContext& ctx);
void GetApplicationArea(Kernel::HLERequestContext& ctx);
void GetTagInfo(Kernel::HLERequestContext& ctx);
void GetRegisterInfo(Kernel::HLERequestContext& ctx);
void GetCommonInfo(Kernel::HLERequestContext& ctx);
void GetModelInfo(Kernel::HLERequestContext& ctx);
void AttachActivateEvent(Kernel::HLERequestContext& ctx);
void AttachDeactivateEvent(Kernel::HLERequestContext& ctx);
void GetState(Kernel::HLERequestContext& ctx);
void GetDeviceState(Kernel::HLERequestContext& ctx);
void GetNpadId(Kernel::HLERequestContext& ctx);
void GetApplicationAreaSize(Kernel::HLERequestContext& ctx);
void AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx);
bool has_attached_handle{};
const u64 device_handle{0}; // Npad device 1
const u32 npad_id{0}; // Player 1 controller
State state{State::NonInitialized};
DeviceState device_state{DeviceState::Initialized};
Module::Interface& nfp_interface;
Kernel::KEvent deactivate_event;
Kernel::KEvent availability_change_event;
};
class Module final { class Module final {
public: public:
class Interface : public ServiceFramework<Interface> { class Interface : public ServiceFramework<Interface> {