mirror of
https://github.com/starr-dusT/citra.git
synced 2024-10-02 10:26:17 -07:00
698 lines
20 KiB
C++
698 lines
20 KiB
C++
// Copyright 2016 Citra Emulator Project
|
|
// Licensed under GPLv2 or any later version
|
|
// Refer to the license.txt file included.
|
|
|
|
#include "common/archives.h"
|
|
#include "core/core.h"
|
|
#include "core/hle/ipc_helpers.h"
|
|
#include "core/hle/kernel/event.h"
|
|
#include "core/hle/lock.h"
|
|
#include "core/hle/service/nfc/nfc.h"
|
|
#include "core/hle/service/nfc/nfc_m.h"
|
|
#include "core/hle/service/nfc/nfc_u.h"
|
|
|
|
SERVICE_CONSTRUCT_IMPL(Service::NFC::Module)
|
|
SERIALIZE_EXPORT_IMPL(Service::NFC::Module)
|
|
|
|
namespace Service::NFC {
|
|
|
|
template <class Archive>
|
|
void Module::serialize(Archive& ar, const unsigned int) {
|
|
ar& nfc_mode;
|
|
ar& device;
|
|
}
|
|
SERIALIZE_IMPL(Module)
|
|
|
|
void Module::Interface::Initialize(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x01, 1, 0);
|
|
const auto communication_mode = rp.PopEnum<CommunicationMode>();
|
|
|
|
LOG_INFO(Service_NFC, "called, communication_mode={}", communication_mode);
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
|
|
if (nfc->nfc_mode != CommunicationMode::NotInitialized) {
|
|
rb.Push(ResultCommandInvalidForState);
|
|
return;
|
|
}
|
|
|
|
ResultCode result = RESULT_SUCCESS;
|
|
switch (communication_mode) {
|
|
case CommunicationMode::Ntag:
|
|
case CommunicationMode::Amiibo:
|
|
nfc->device->Initialize();
|
|
break;
|
|
case CommunicationMode::TrainTag:
|
|
LOG_ERROR(Service_NFC, "CommunicationMode {} not implemented", communication_mode);
|
|
break;
|
|
default:
|
|
result = ResultInvalidArgumentValue;
|
|
break;
|
|
}
|
|
|
|
if (result.IsSuccess()) {
|
|
nfc->nfc_mode = communication_mode;
|
|
}
|
|
|
|
rb.Push(result);
|
|
}
|
|
|
|
void Module::Interface::Shutdown(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x02, 1, 0);
|
|
const auto communication_mode = rp.PopEnum<CommunicationMode>();
|
|
|
|
LOG_INFO(Service_NFC, "called, communication_mode={}", communication_mode);
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
|
|
if (nfc->nfc_mode != communication_mode) {
|
|
rb.Push(ResultCommandInvalidForState);
|
|
return;
|
|
}
|
|
|
|
ResultCode result = RESULT_SUCCESS;
|
|
switch (communication_mode) {
|
|
case CommunicationMode::Ntag:
|
|
case CommunicationMode::Amiibo:
|
|
nfc->device->Finalize();
|
|
break;
|
|
case CommunicationMode::TrainTag:
|
|
LOG_ERROR(Service_NFC, "CommunicationMode {} not implemented", communication_mode);
|
|
break;
|
|
default:
|
|
result = ResultInvalidArgumentValue;
|
|
break;
|
|
}
|
|
|
|
if (result.IsSuccess()) {
|
|
nfc->nfc_mode = CommunicationMode::NotInitialized;
|
|
}
|
|
|
|
rb.Push(result);
|
|
}
|
|
|
|
void Module::Interface::StartCommunication(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x03, 0, 0);
|
|
|
|
LOG_WARNING(Service_NFC, "(STUBBED) called");
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
if (nfc->nfc_mode == CommunicationMode::TrainTag) {
|
|
LOG_ERROR(Service_NFC, "CommunicationMode {} not implemented", nfc->nfc_mode);
|
|
rb.Push(RESULT_SUCCESS);
|
|
return;
|
|
}
|
|
|
|
// TODO: call start communication instead
|
|
const auto result = nfc->device->StartCommunication();
|
|
rb.Push(result);
|
|
}
|
|
|
|
void Module::Interface::StopCommunication(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x04, 0, 0);
|
|
|
|
LOG_WARNING(Service_NFC, "(STUBBED) called");
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
if (nfc->nfc_mode == CommunicationMode::TrainTag) {
|
|
LOG_ERROR(Service_NFC, "CommunicationMode {} not implemented", nfc->nfc_mode);
|
|
rb.Push(RESULT_SUCCESS);
|
|
return;
|
|
}
|
|
|
|
// TODO: call stop communication instead
|
|
const auto result = nfc->device->StopCommunication();
|
|
rb.Push(result);
|
|
}
|
|
|
|
void Module::Interface::StartTagScanning(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x05, 1, 0);
|
|
u16 in_val = rp.Pop<u16>();
|
|
|
|
LOG_INFO(Service_NFC, "called, in_val={:04x}", in_val);
|
|
|
|
ResultCode result = RESULT_SUCCESS;
|
|
switch (nfc->nfc_mode) {
|
|
case CommunicationMode::Ntag:
|
|
case CommunicationMode::Amiibo:
|
|
// in_val probably correlates to the tag protocol to be detected
|
|
result = nfc->device->StartDetection(TagProtocol::All);
|
|
break;
|
|
default:
|
|
result = ResultInvalidArgumentValue;
|
|
break;
|
|
}
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(result);
|
|
}
|
|
|
|
void Module::Interface::StopTagScanning(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x06, 0, 0);
|
|
|
|
LOG_INFO(Service_NFC, "called");
|
|
|
|
ResultCode result = RESULT_SUCCESS;
|
|
switch (nfc->nfc_mode) {
|
|
case CommunicationMode::Ntag:
|
|
case CommunicationMode::Amiibo:
|
|
result = nfc->device->StopDetection();
|
|
break;
|
|
case CommunicationMode::TrainTag:
|
|
LOG_ERROR(Service_NFC, "CommunicationMode {} not implemented", nfc->nfc_mode);
|
|
break;
|
|
default:
|
|
result = ResultCommandInvalidForState;
|
|
break;
|
|
}
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(result);
|
|
}
|
|
|
|
void Module::Interface::LoadAmiiboData(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x07, 0, 0);
|
|
|
|
LOG_INFO(Service_NFC, "called");
|
|
|
|
ResultCode result = RESULT_SUCCESS;
|
|
switch (nfc->nfc_mode) {
|
|
case CommunicationMode::Ntag:
|
|
result = nfc->device->Mount();
|
|
break;
|
|
case CommunicationMode::Amiibo:
|
|
result = nfc->device->MountAmiibo();
|
|
break;
|
|
default:
|
|
result = ResultCommandInvalidForState;
|
|
break;
|
|
}
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(result);
|
|
}
|
|
|
|
void Module::Interface::ResetTagScanState(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x08, 0, 0);
|
|
|
|
LOG_INFO(Service_NFC, "called");
|
|
|
|
ResultCode result = RESULT_SUCCESS;
|
|
switch (nfc->nfc_mode) {
|
|
case CommunicationMode::Ntag:
|
|
case CommunicationMode::Amiibo:
|
|
result = nfc->device->ResetTagScanState();
|
|
break;
|
|
default:
|
|
result = ResultCommandInvalidForState;
|
|
break;
|
|
}
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(result);
|
|
}
|
|
|
|
void Module::Interface::UpdateStoredAmiiboData(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x09, 0, 0);
|
|
|
|
LOG_INFO(Service_NFC, "called");
|
|
|
|
ResultCode result = RESULT_SUCCESS;
|
|
switch (nfc->nfc_mode) {
|
|
case CommunicationMode::Ntag:
|
|
LOG_ERROR(Service_NFC, "CommunicationMode {} not implemented", nfc->nfc_mode);
|
|
break;
|
|
case CommunicationMode::Amiibo:
|
|
result = nfc->device->Flush();
|
|
break;
|
|
default:
|
|
result = ResultCommandInvalidForState;
|
|
break;
|
|
}
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(result);
|
|
}
|
|
|
|
void Module::Interface::GetTagInRangeEvent(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x0B, 0, 0);
|
|
|
|
LOG_INFO(Service_NFC, "called");
|
|
|
|
if (nfc->nfc_mode == CommunicationMode::TrainTag) {
|
|
LOG_ERROR(Service_NFC, "CommunicationMode {} not implemented", nfc->nfc_mode);
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(ResultCommandInvalidForState);
|
|
return;
|
|
}
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
|
rb.Push(RESULT_SUCCESS);
|
|
rb.PushCopyObjects(nfc->device->GetActivateEvent());
|
|
}
|
|
|
|
void Module::Interface::GetTagOutOfRangeEvent(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x0C, 0, 0);
|
|
|
|
LOG_INFO(Service_NFC, "called");
|
|
|
|
if (nfc->nfc_mode == CommunicationMode::TrainTag) {
|
|
LOG_ERROR(Service_NFC, "CommunicationMode {} not implemented", nfc->nfc_mode);
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(ResultCommandInvalidForState);
|
|
return;
|
|
}
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
|
rb.Push(RESULT_SUCCESS);
|
|
rb.PushCopyObjects(nfc->device->GetDeactivateEvent());
|
|
}
|
|
|
|
void Module::Interface::GetTagState(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x0D, 0, 0);
|
|
DeviceState state = DeviceState::NotInitialized;
|
|
|
|
LOG_DEBUG(Service_NFC, "called");
|
|
|
|
if (nfc->nfc_mode == CommunicationMode::TrainTag) {
|
|
LOG_ERROR(Service_NFC, "CommunicationMode {} not implemented", nfc->nfc_mode);
|
|
} else {
|
|
state = nfc->device->GetCurrentState();
|
|
}
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
|
rb.Push(RESULT_SUCCESS);
|
|
rb.PushEnum(state);
|
|
}
|
|
|
|
void Module::Interface::CommunicationGetStatus(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x0F, 0, 0);
|
|
|
|
LOG_DEBUG(Service_NFC, "called");
|
|
|
|
if (nfc->nfc_mode == CommunicationMode::TrainTag) {
|
|
LOG_ERROR(Service_NFC, "CommunicationMode {} not implemented", nfc->nfc_mode);
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
|
rb.Push(RESULT_SUCCESS);
|
|
rb.PushEnum(CommunicationState::Idle);
|
|
return;
|
|
}
|
|
|
|
CommunicationState status{};
|
|
const auto result = nfc->device->GetCommunicationStatus(status);
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
|
rb.Push(result);
|
|
rb.PushEnum(status);
|
|
}
|
|
|
|
void Module::Interface::GetTagInfo2(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x10, 0, 0);
|
|
|
|
LOG_INFO(Service_NFC, "called");
|
|
|
|
if (nfc->nfc_mode == CommunicationMode::TrainTag) {
|
|
LOG_ERROR(Service_NFC, "CommunicationMode {} not implemented", nfc->nfc_mode);
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(26, 0);
|
|
rb.Push(RESULT_SUCCESS);
|
|
rb.PushRaw<TagInfo2>({});
|
|
return;
|
|
}
|
|
|
|
TagInfo2 tag_info{};
|
|
const auto result = nfc->device->GetTagInfo2(tag_info);
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(26, 0);
|
|
rb.Push(result);
|
|
rb.PushRaw<TagInfo2>(tag_info);
|
|
}
|
|
|
|
void Module::Interface::GetTagInfo(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x11, 0, 0);
|
|
|
|
LOG_INFO(Service_NFC, "called");
|
|
|
|
if (nfc->nfc_mode == CommunicationMode::TrainTag) {
|
|
LOG_ERROR(Service_NFC, "CommunicationMode {} not implemented", nfc->nfc_mode);
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(12, 0);
|
|
rb.Push(RESULT_SUCCESS);
|
|
rb.PushRaw<TagInfo>({});
|
|
return;
|
|
}
|
|
|
|
TagInfo tag_info{};
|
|
const auto result = nfc->device->GetTagInfo(tag_info);
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(12, 0);
|
|
rb.Push(result);
|
|
rb.PushRaw<TagInfo>(tag_info);
|
|
}
|
|
|
|
void Module::Interface::CommunicationGetResult(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x12, 0, 0);
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
|
rb.Push(RESULT_SUCCESS);
|
|
rb.Push(0);
|
|
LOG_WARNING(Service_NFC, "(STUBBED) called");
|
|
}
|
|
|
|
void Module::Interface::OpenAppData(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x13, 1, 0);
|
|
u32 access_id = rp.Pop<u32>();
|
|
|
|
LOG_INFO(Service_NFC, "called, access_id={}", access_id);
|
|
|
|
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(ResultCommandInvalidForState);
|
|
return;
|
|
}
|
|
|
|
const auto result = nfc->device->OpenApplicationArea(access_id);
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(result);
|
|
}
|
|
|
|
void Module::Interface::InitializeWriteAppData(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x14, 18, 2);
|
|
u32 access_id = rp.Pop<u32>();
|
|
[[maybe_unused]] u32 size = rp.Pop<u32>();
|
|
std::vector<u8> buffer = rp.PopStaticBuffer();
|
|
|
|
LOG_CRITICAL(Service_NFC, "called, size={}", size);
|
|
|
|
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(ResultCommandInvalidForState);
|
|
return;
|
|
}
|
|
|
|
const auto result = nfc->device->CreateApplicationArea(access_id, buffer);
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(result);
|
|
}
|
|
|
|
void Module::Interface::ReadAppData(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x15, 0, 0);
|
|
|
|
LOG_INFO(Service_NFC, "called");
|
|
|
|
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(ResultCommandInvalidForState);
|
|
return;
|
|
}
|
|
|
|
std::vector<u8> buffer(sizeof(ApplicationArea));
|
|
const auto result = nfc->device->GetApplicationArea(buffer);
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
|
rb.Push(result);
|
|
rb.PushStaticBuffer(buffer, 0);
|
|
}
|
|
|
|
void Module::Interface::WriteAppData(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x16, 12, 2);
|
|
[[maybe_unused]] u32 size = rp.Pop<u32>();
|
|
std::vector<u8> tag_uuid_info = rp.PopStaticBuffer();
|
|
std::vector<u8> buffer = rp.PopStaticBuffer();
|
|
|
|
LOG_CRITICAL(Service_NFC, "called, size={}", size);
|
|
|
|
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(ResultCommandInvalidForState);
|
|
return;
|
|
}
|
|
|
|
const auto result = nfc->device->SetApplicationArea(buffer);
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(result);
|
|
}
|
|
|
|
void Module::Interface::GetRegisterInfo(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x17, 0, 0);
|
|
|
|
LOG_INFO(Service_NFC, "called");
|
|
|
|
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(ResultCommandInvalidForState);
|
|
return;
|
|
}
|
|
|
|
RegisterInfo settings_info{};
|
|
const auto result = nfc->device->GetRegisterInfo(settings_info);
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(43, 0);
|
|
rb.Push(result);
|
|
rb.PushRaw<RegisterInfo>(settings_info);
|
|
}
|
|
|
|
void Module::Interface::GetCommonInfo(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x18, 0, 0);
|
|
|
|
LOG_INFO(Service_NFC, "called");
|
|
|
|
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(ResultCommandInvalidForState);
|
|
return;
|
|
}
|
|
|
|
CommonInfo amiibo_config{};
|
|
const auto result = nfc->device->GetCommonInfo(amiibo_config);
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(17, 0);
|
|
rb.Push(result);
|
|
rb.PushRaw<CommonInfo>(amiibo_config);
|
|
}
|
|
|
|
void Module::Interface::GetAppDataInitStruct(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x19, 0, 0);
|
|
|
|
LOG_INFO(Service_NFC, "called");
|
|
|
|
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(ResultCommandInvalidForState);
|
|
return;
|
|
}
|
|
|
|
using InitialStruct = std::array<u8, 0x3c>;
|
|
InitialStruct empty{};
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(16, 0);
|
|
rb.Push(RESULT_SUCCESS);
|
|
rb.PushRaw<InitialStruct>(empty);
|
|
}
|
|
|
|
void Module::Interface::LoadAmiiboPartially(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x1A, 0, 0);
|
|
|
|
LOG_INFO(Service_NFC, "called");
|
|
|
|
ResultCode result = RESULT_SUCCESS;
|
|
switch (nfc->nfc_mode) {
|
|
case CommunicationMode::Ntag:
|
|
result = nfc->device->PartiallyMount();
|
|
break;
|
|
case CommunicationMode::Amiibo:
|
|
result = nfc->device->PartiallyMountAmiibo();
|
|
break;
|
|
default:
|
|
result = ResultCommandInvalidForState;
|
|
break;
|
|
}
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(result);
|
|
}
|
|
|
|
void Module::Interface::GetIdentificationBlock(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x1B, 0, 0);
|
|
|
|
LOG_INFO(Service_NFC, "called");
|
|
|
|
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(ResultCommandInvalidForState);
|
|
return;
|
|
}
|
|
|
|
ModelInfo model_info{};
|
|
const auto result = nfc->device->GetModelInfo(model_info);
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(0x1F, 0);
|
|
rb.Push(result);
|
|
rb.PushRaw<ModelInfo>(model_info);
|
|
}
|
|
|
|
void Module::Interface::Format(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x401, 3, 2);
|
|
[[maybe_unused]] u32 unknown1 = rp.Pop<u32>();
|
|
[[maybe_unused]] u32 unknown2 = rp.Pop<u32>();
|
|
[[maybe_unused]] u32 unknown3 = rp.Pop<u32>();
|
|
[[maybe_unused]] std::vector<u8> buffer = rp.PopStaticBuffer();
|
|
|
|
const auto result = nfc->device->Format();
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(result);
|
|
LOG_WARNING(Service_NFC, "(STUBBED) called");
|
|
}
|
|
|
|
void Module::Interface::GetAdminInfo(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x402, 0, 0);
|
|
|
|
LOG_INFO(Service_NFC, "called");
|
|
|
|
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(ResultCommandInvalidForState);
|
|
return;
|
|
}
|
|
|
|
AdminInfo admin_info{};
|
|
const auto result = nfc->device->GetAdminInfo(admin_info);
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(17, 0);
|
|
rb.Push(result);
|
|
rb.PushRaw<AdminInfo>(admin_info);
|
|
}
|
|
|
|
void Module::Interface::GetEmptyRegisterInfo(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x403, 0, 0);
|
|
|
|
LOG_INFO(Service_NFC, "called");
|
|
|
|
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(ResultCommandInvalidForState);
|
|
return;
|
|
}
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(43, 0);
|
|
rb.Push(RESULT_SUCCESS);
|
|
rb.PushRaw<RegisterInfo>({});
|
|
}
|
|
|
|
void Module::Interface::SetRegisterInfo(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x404, 41, 0);
|
|
const auto register_info = rp.PopRaw<RegisterInfoPrivate>();
|
|
|
|
LOG_INFO(Service_NFC, "called");
|
|
|
|
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(ResultCommandInvalidForState);
|
|
return;
|
|
}
|
|
|
|
const auto result = nfc->device->SetRegisterInfoPrivate(register_info);
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(result);
|
|
}
|
|
|
|
void Module::Interface::DeleteRegisterInfo(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x405, 0, 0);
|
|
|
|
LOG_INFO(Service_NFC, "called");
|
|
|
|
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(ResultCommandInvalidForState);
|
|
return;
|
|
}
|
|
|
|
const auto result = nfc->device->DeleteRegisterInfo();
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(result);
|
|
}
|
|
|
|
void Module::Interface::DeleteApplicationArea(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x406, 0, 0);
|
|
|
|
LOG_INFO(Service_NFC, "called");
|
|
|
|
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(ResultCommandInvalidForState);
|
|
return;
|
|
}
|
|
|
|
const auto result = nfc->device->DeleteApplicationArea();
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(result);
|
|
}
|
|
|
|
void Module::Interface::ExistsApplicationArea(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x407, 0, 0);
|
|
|
|
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(ResultCommandInvalidForState);
|
|
return;
|
|
}
|
|
|
|
bool has_application_area = false;
|
|
const auto result = nfc->device->ApplicationAreaExist(has_application_area);
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(0x2, 0);
|
|
rb.Push(result);
|
|
rb.Push(has_application_area);
|
|
LOG_INFO(Service_NFC, "called");
|
|
}
|
|
|
|
std::shared_ptr<Module> Module::Interface::GetModule() const {
|
|
return nfc;
|
|
}
|
|
|
|
bool Module::Interface::IsSearchingForAmiibos() {
|
|
std::lock_guard lock(HLE::g_hle_lock);
|
|
|
|
const auto state = nfc->device->GetCurrentState();
|
|
return state == DeviceState::SearchingForTag;
|
|
}
|
|
|
|
bool Module::Interface::IsTagActive() {
|
|
std::lock_guard lock(HLE::g_hle_lock);
|
|
|
|
const auto state = nfc->device->GetCurrentState();
|
|
return state == DeviceState::TagFound || state == DeviceState::TagMounted ||
|
|
state == DeviceState::TagPartiallyMounted;
|
|
}
|
|
bool Module::Interface::LoadAmiibo(const std::string& fullpath) {
|
|
std::lock_guard lock(HLE::g_hle_lock);
|
|
return nfc->device->LoadAmiibo(fullpath);
|
|
}
|
|
|
|
void Module::Interface::RemoveAmiibo() {
|
|
std::lock_guard lock(HLE::g_hle_lock);
|
|
nfc->device->UnloadAmiibo();
|
|
}
|
|
|
|
Module::Interface::Interface(std::shared_ptr<Module> nfc, const char* name, u32 max_session)
|
|
: ServiceFramework(name, max_session), nfc(std::move(nfc)) {}
|
|
|
|
Module::Interface::~Interface() = default;
|
|
|
|
Module::Module(Core::System& system) {
|
|
device = std::make_shared<NfcDevice>(system);
|
|
}
|
|
|
|
Module::~Module() = default;
|
|
|
|
void InstallInterfaces(Core::System& system) {
|
|
auto& service_manager = system.ServiceManager();
|
|
auto nfc = std::make_shared<Module>(system);
|
|
std::make_shared<NFC_M>(nfc)->InstallAsService(service_manager);
|
|
std::make_shared<NFC_U>(nfc)->InstallAsService(service_manager);
|
|
}
|
|
|
|
} // namespace Service::NFC
|