2016-12-08 07:43:27 +00:00
|
|
|
// Copyright 2016 Citra Emulator Project
|
|
|
|
// Licensed under GPLv2 or any later version
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
2018-10-05 14:59:43 +00:00
|
|
|
#include "core/core.h"
|
2017-12-01 19:37:00 +00:00
|
|
|
#include "core/hle/ipc_helpers.h"
|
2016-12-29 20:38:47 +00:00
|
|
|
#include "core/hle/kernel/event.h"
|
2018-10-25 01:01:38 +00:00
|
|
|
#include "core/hle/lock.h"
|
2016-12-08 07:43:27 +00:00
|
|
|
#include "core/hle/service/nfc/nfc.h"
|
|
|
|
#include "core/hle/service/nfc/nfc_m.h"
|
|
|
|
#include "core/hle/service/nfc/nfc_u.h"
|
|
|
|
|
2018-09-22 12:23:08 +00:00
|
|
|
namespace Service::NFC {
|
2016-12-08 07:43:27 +00:00
|
|
|
|
2018-10-25 01:01:38 +00:00
|
|
|
struct TagInfo {
|
|
|
|
u16_le id_offset_size;
|
|
|
|
u8 unk1;
|
|
|
|
u8 unk2;
|
|
|
|
std::array<u8, 7> uuid;
|
|
|
|
INSERT_PADDING_BYTES(0x20);
|
|
|
|
};
|
|
|
|
static_assert(sizeof(TagInfo) == 0x2C, "TagInfo is an invalid size");
|
|
|
|
|
|
|
|
struct AmiiboConfig {
|
|
|
|
u16_le lastwritedate_year;
|
|
|
|
u8 lastwritedate_month;
|
|
|
|
u8 lastwritedate_day;
|
|
|
|
u16_le write_counter;
|
|
|
|
std::array<u8, 3> characterID;
|
|
|
|
u16_le amiiboID;
|
|
|
|
u8 type;
|
|
|
|
u8 pagex4_byte3;
|
|
|
|
u16_le appdata_size;
|
|
|
|
INSERT_PADDING_BYTES(0x30);
|
|
|
|
};
|
|
|
|
static_assert(sizeof(AmiiboConfig) == 0x40, "AmiiboConfig is an invalid size");
|
|
|
|
|
|
|
|
struct IdentificationBlockReply {
|
|
|
|
u16_le char_id;
|
|
|
|
u8 char_variant;
|
|
|
|
u8 series;
|
|
|
|
u16_le model_number;
|
|
|
|
u8 figure_type;
|
|
|
|
INSERT_PADDING_BYTES(0x2F);
|
|
|
|
};
|
|
|
|
static_assert(sizeof(IdentificationBlockReply) == 0x36,
|
|
|
|
"IdentificationBlockReply is an invalid size");
|
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
void Module::Interface::Initialize(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0x01, 1, 0);
|
|
|
|
u8 param = rp.Pop<u8>();
|
2017-01-14 07:42:56 +00:00
|
|
|
|
2018-10-25 01:01:38 +00:00
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
|
|
if (nfc->nfc_tag_state != TagState::NotInitialized) {
|
|
|
|
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state.load()));
|
|
|
|
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
|
|
|
ErrorSummary::InvalidState, ErrorLevel::Status));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
nfc->nfc_tag_state = TagState::NotScanning;
|
2017-01-14 07:42:56 +00:00
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
rb.Push(RESULT_SUCCESS);
|
2018-06-29 11:18:07 +00:00
|
|
|
LOG_WARNING(Service_NFC, "(STUBBED) called, param={}", param);
|
2017-01-14 07:42:56 +00:00
|
|
|
}
|
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
void Module::Interface::Shutdown(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0x02, 1, 0);
|
|
|
|
u8 param = rp.Pop<u8>();
|
2017-01-14 07:42:56 +00:00
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
nfc->nfc_tag_state = TagState::NotInitialized;
|
2017-01-14 07:42:56 +00:00
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2018-06-29 11:18:07 +00:00
|
|
|
LOG_WARNING(Service_NFC, "(STUBBED) called, param={}", param);
|
2017-01-14 07:42:56 +00:00
|
|
|
}
|
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
void Module::Interface::StartCommunication(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0x03, 0, 0);
|
2017-01-14 07:42:56 +00:00
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2018-06-29 11:18:07 +00:00
|
|
|
LOG_WARNING(Service_NFC, "(STUBBED) called");
|
2017-01-14 07:42:56 +00:00
|
|
|
}
|
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
void Module::Interface::StopCommunication(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0x04, 0, 0);
|
2017-01-14 07:42:56 +00:00
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2018-06-29 11:18:07 +00:00
|
|
|
LOG_WARNING(Service_NFC, "(STUBBED) called");
|
2017-01-14 07:42:56 +00:00
|
|
|
}
|
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
void Module::Interface::StartTagScanning(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0x05, 1, 0); // 0x00050040
|
2017-12-01 19:37:00 +00:00
|
|
|
u16 in_val = rp.Pop<u16>();
|
2017-01-14 07:42:56 +00:00
|
|
|
|
2018-10-25 01:01:38 +00:00
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
|
|
if (nfc->nfc_tag_state != TagState::NotScanning &&
|
|
|
|
nfc->nfc_tag_state != TagState::TagOutOfRange) {
|
|
|
|
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state.load()));
|
|
|
|
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
|
|
|
ErrorSummary::InvalidState, ErrorLevel::Status));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nfc->nfc_tag_state = TagState::Scanning;
|
2017-01-14 07:42:56 +00:00
|
|
|
|
2018-10-25 01:01:38 +00:00
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
LOG_WARNING(Service_NFC, "(STUBBED) called, in_val={:04x}", in_val);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Module::Interface::GetTagInfo(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0x11, 0, 0);
|
2017-12-01 19:37:00 +00:00
|
|
|
|
2018-10-25 01:01:38 +00:00
|
|
|
if (nfc->nfc_tag_state != TagState::TagInRange &&
|
|
|
|
nfc->nfc_tag_state != TagState::TagDataLoaded && nfc->nfc_tag_state != TagState::Unknown6) {
|
|
|
|
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state.load()));
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
|
|
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
|
|
|
ErrorSummary::InvalidState, ErrorLevel::Status));
|
|
|
|
return;
|
2017-12-01 19:37:00 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 01:01:38 +00:00
|
|
|
TagInfo tag_info{};
|
|
|
|
tag_info.uuid = nfc->amiibo_data.uuid;
|
|
|
|
tag_info.id_offset_size = tag_info.uuid.size();
|
|
|
|
tag_info.unk1 = 0x0;
|
|
|
|
tag_info.unk2 = 0x2;
|
|
|
|
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(12, 0);
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
rb.PushRaw<TagInfo>(tag_info);
|
|
|
|
LOG_WARNING(Service_NFC, "(STUBBED) called");
|
|
|
|
}
|
|
|
|
|
|
|
|
void Module::Interface::GetAmiiboConfig(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0x18, 0, 0);
|
|
|
|
|
|
|
|
AmiiboConfig amiibo_config{};
|
|
|
|
amiibo_config.lastwritedate_year = 2017;
|
|
|
|
amiibo_config.lastwritedate_month = 10;
|
|
|
|
amiibo_config.lastwritedate_day = 10;
|
|
|
|
// TODO(FearlessTobi): Find the right values for the struct
|
|
|
|
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(17, 0);
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
rb.PushRaw<AmiiboConfig>(amiibo_config);
|
|
|
|
LOG_WARNING(Service_NFC, "(STUBBED) called");
|
2017-01-14 07:42:56 +00:00
|
|
|
}
|
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
void Module::Interface::StopTagScanning(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0x06, 0, 0);
|
2017-01-14 07:42:56 +00:00
|
|
|
|
2018-10-25 01:01:38 +00:00
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
|
|
if (nfc->nfc_tag_state == TagState::NotInitialized ||
|
|
|
|
nfc->nfc_tag_state == TagState::NotScanning) {
|
|
|
|
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state.load()));
|
|
|
|
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
|
|
|
ErrorSummary::InvalidState, ErrorLevel::Status));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
nfc->nfc_tag_state = TagState::NotScanning;
|
2017-01-14 07:42:56 +00:00
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
rb.Push(RESULT_SUCCESS);
|
2018-10-25 01:01:38 +00:00
|
|
|
LOG_DEBUG(Service_NFC, "called");
|
2017-01-14 07:42:56 +00:00
|
|
|
}
|
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
void Module::Interface::LoadAmiiboData(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0x07, 0, 0);
|
2017-01-14 07:42:56 +00:00
|
|
|
|
2018-10-25 01:01:38 +00:00
|
|
|
// TODO(FearlessTobi): Add state checking when this function gets properly implemented
|
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
nfc->nfc_tag_state = TagState::TagDataLoaded;
|
2017-01-14 07:42:56 +00:00
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2018-06-29 11:18:07 +00:00
|
|
|
LOG_WARNING(Service_NFC, "(STUBBED) called");
|
2017-01-14 07:42:56 +00:00
|
|
|
}
|
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
void Module::Interface::ResetTagScanState(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0x08, 0, 0);
|
2017-01-14 07:42:56 +00:00
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
2018-10-25 01:01:38 +00:00
|
|
|
if (nfc->nfc_tag_state != TagState::TagDataLoaded && nfc->nfc_tag_state != TagState::Unknown6) {
|
|
|
|
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state.load()));
|
|
|
|
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
|
|
|
ErrorSummary::InvalidState, ErrorLevel::Status));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nfc->nfc_tag_state = TagState::TagInRange;
|
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
rb.Push(RESULT_SUCCESS);
|
2018-10-25 01:01:38 +00:00
|
|
|
LOG_DEBUG(Service_NFC, "called");
|
2017-01-14 07:42:56 +00:00
|
|
|
}
|
2016-12-29 20:38:47 +00:00
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
void Module::Interface::GetTagInRangeEvent(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0x0B, 0, 0);
|
2016-12-29 20:38:47 +00:00
|
|
|
|
2018-10-25 01:01:38 +00:00
|
|
|
if (nfc->nfc_tag_state != TagState::NotScanning) {
|
|
|
|
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state.load()));
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
|
|
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
|
|
|
ErrorSummary::InvalidState, ErrorLevel::Status));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
rb.PushCopyObjects(nfc->tag_in_range_event);
|
2018-10-25 01:01:38 +00:00
|
|
|
LOG_DEBUG(Service_NFC, "called");
|
2016-12-29 20:38:47 +00:00
|
|
|
}
|
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
void Module::Interface::GetTagOutOfRangeEvent(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0x0C, 0, 0);
|
2017-01-14 07:42:56 +00:00
|
|
|
|
2018-10-25 01:01:38 +00:00
|
|
|
if (nfc->nfc_tag_state != TagState::NotScanning) {
|
|
|
|
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state.load()));
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
|
|
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
|
|
|
ErrorSummary::InvalidState, ErrorLevel::Status));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
rb.PushCopyObjects(nfc->tag_out_of_range_event);
|
2018-10-25 01:01:38 +00:00
|
|
|
LOG_DEBUG(Service_NFC, "called");
|
2017-01-14 07:42:56 +00:00
|
|
|
}
|
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
void Module::Interface::GetTagState(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0x0D, 0, 0);
|
2017-01-14 07:42:56 +00:00
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2018-10-25 01:01:38 +00:00
|
|
|
rb.PushEnum(nfc->nfc_tag_state.load());
|
|
|
|
LOG_DEBUG(Service_NFC, "called");
|
2017-01-14 07:42:56 +00:00
|
|
|
}
|
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
void Module::Interface::CommunicationGetStatus(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0x0F, 0, 0);
|
2017-01-14 07:42:56 +00:00
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
rb.PushEnum(nfc->nfc_status);
|
2018-06-29 11:18:07 +00:00
|
|
|
LOG_DEBUG(Service_NFC, "(STUBBED) called");
|
2017-01-14 07:42:56 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 01:01:38 +00:00
|
|
|
void Module::Interface::Unknown0x1A(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0x1A, 0, 0);
|
|
|
|
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
|
|
if (nfc->nfc_tag_state != TagState::TagInRange) {
|
|
|
|
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state.load()));
|
|
|
|
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
|
|
|
ErrorSummary::InvalidState, ErrorLevel::Status));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nfc->nfc_tag_state = TagState::Unknown6;
|
|
|
|
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
LOG_DEBUG(Service_NFC, "called");
|
|
|
|
}
|
|
|
|
|
|
|
|
void Module::Interface::GetIdentificationBlock(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp(ctx, 0x1B, 0, 0);
|
|
|
|
|
|
|
|
if (nfc->nfc_tag_state != TagState::TagDataLoaded && nfc->nfc_tag_state != TagState::Unknown6) {
|
|
|
|
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state.load()));
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
|
|
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
|
|
|
ErrorSummary::InvalidState, ErrorLevel::Status));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
IdentificationBlockReply identification_block_reply{};
|
|
|
|
identification_block_reply.char_id = nfc->amiibo_data.char_id;
|
|
|
|
identification_block_reply.char_variant = nfc->amiibo_data.char_variant;
|
|
|
|
identification_block_reply.series = nfc->amiibo_data.series;
|
|
|
|
identification_block_reply.model_number = nfc->amiibo_data.model_number;
|
|
|
|
identification_block_reply.figure_type = nfc->amiibo_data.figure_type;
|
|
|
|
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(0x1F, 0);
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
rb.PushRaw<IdentificationBlockReply>(identification_block_reply);
|
|
|
|
LOG_DEBUG(Service_NFC, "called");
|
|
|
|
}
|
|
|
|
|
|
|
|
std::shared_ptr<Module> Module::Interface::GetModule() const {
|
|
|
|
return nfc;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Module::Interface::LoadAmiibo(const AmiiboData& amiibo_data) {
|
|
|
|
std::lock_guard lock(HLE::g_hle_lock);
|
|
|
|
nfc->amiibo_data = amiibo_data;
|
|
|
|
nfc->nfc_tag_state = Service::NFC::TagState::TagInRange;
|
|
|
|
nfc->tag_in_range_event->Signal();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Module::Interface::RemoveAmiibo() {
|
|
|
|
std::lock_guard lock(HLE::g_hle_lock);
|
|
|
|
nfc->nfc_tag_state = Service::NFC::TagState::TagOutOfRange;
|
|
|
|
nfc->tag_out_of_range_event->Signal();
|
|
|
|
nfc->amiibo_data = {};
|
|
|
|
}
|
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
Module::Interface::Interface(std::shared_ptr<Module> nfc, const char* name, u32 max_session)
|
|
|
|
: ServiceFramework(name, max_session), nfc(std::move(nfc)) {}
|
2016-12-29 20:38:47 +00:00
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
Module::Interface::~Interface() = default;
|
|
|
|
|
2018-10-11 19:48:16 +00:00
|
|
|
Module::Module(Core::System& system) {
|
2016-12-29 20:38:47 +00:00
|
|
|
tag_in_range_event =
|
2018-10-11 19:48:16 +00:00
|
|
|
system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "NFC::tag_in_range_event");
|
2017-01-14 07:42:56 +00:00
|
|
|
tag_out_of_range_event =
|
2018-10-11 19:48:16 +00:00
|
|
|
system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "NFC::tag_out_range_event");
|
2016-12-29 20:38:47 +00:00
|
|
|
}
|
|
|
|
|
2018-03-05 08:48:09 +00:00
|
|
|
Module::~Module() = default;
|
|
|
|
|
2018-10-05 14:59:43 +00:00
|
|
|
void InstallInterfaces(Core::System& system) {
|
|
|
|
auto& service_manager = system.ServiceManager();
|
2018-10-11 19:48:16 +00:00
|
|
|
auto nfc = std::make_shared<Module>(system);
|
2018-03-05 08:48:09 +00:00
|
|
|
std::make_shared<NFC_M>(nfc)->InstallAsService(service_manager);
|
|
|
|
std::make_shared<NFC_U>(nfc)->InstallAsService(service_manager);
|
2016-12-08 07:43:27 +00:00
|
|
|
}
|
|
|
|
|
2018-09-22 12:23:08 +00:00
|
|
|
} // namespace Service::NFC
|