mirror of
https://github.com/citra-emu/citra.git
synced 2024-12-23 22:10:05 +00:00
Merge pull request #4893 from wwylele/nfc-state
NFC: extract frontend-facing tag state
This commit is contained in:
commit
7bfd829c77
@ -53,7 +53,7 @@ void Module::Interface::Initialize(Kernel::HLERequestContext& ctx) {
|
|||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
if (nfc->nfc_tag_state != TagState::NotInitialized) {
|
if (nfc->nfc_tag_state != TagState::NotInitialized) {
|
||||||
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state.load()));
|
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state));
|
||||||
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
||||||
ErrorSummary::InvalidState, ErrorLevel::Status));
|
ErrorSummary::InvalidState, ErrorLevel::Status));
|
||||||
return;
|
return;
|
||||||
@ -99,13 +99,14 @@ void Module::Interface::StartTagScanning(Kernel::HLERequestContext& ctx) {
|
|||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
if (nfc->nfc_tag_state != TagState::NotScanning &&
|
if (nfc->nfc_tag_state != TagState::NotScanning &&
|
||||||
nfc->nfc_tag_state != TagState::TagOutOfRange) {
|
nfc->nfc_tag_state != TagState::TagOutOfRange) {
|
||||||
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state.load()));
|
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state));
|
||||||
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
||||||
ErrorSummary::InvalidState, ErrorLevel::Status));
|
ErrorSummary::InvalidState, ErrorLevel::Status));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc->nfc_tag_state = TagState::Scanning;
|
nfc->nfc_tag_state = TagState::Scanning;
|
||||||
|
nfc->SyncTagState();
|
||||||
|
|
||||||
rb.Push(RESULT_SUCCESS);
|
rb.Push(RESULT_SUCCESS);
|
||||||
LOG_WARNING(Service_NFC, "(STUBBED) called, in_val={:04x}", in_val);
|
LOG_WARNING(Service_NFC, "(STUBBED) called, in_val={:04x}", in_val);
|
||||||
@ -116,7 +117,7 @@ void Module::Interface::GetTagInfo(Kernel::HLERequestContext& ctx) {
|
|||||||
|
|
||||||
if (nfc->nfc_tag_state != TagState::TagInRange &&
|
if (nfc->nfc_tag_state != TagState::TagInRange &&
|
||||||
nfc->nfc_tag_state != TagState::TagDataLoaded && nfc->nfc_tag_state != TagState::Unknown6) {
|
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()));
|
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state));
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
||||||
ErrorSummary::InvalidState, ErrorLevel::Status));
|
ErrorSummary::InvalidState, ErrorLevel::Status));
|
||||||
@ -163,7 +164,7 @@ void Module::Interface::StopTagScanning(Kernel::HLERequestContext& ctx) {
|
|||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
if (nfc->nfc_tag_state == TagState::NotInitialized ||
|
if (nfc->nfc_tag_state == TagState::NotInitialized ||
|
||||||
nfc->nfc_tag_state == TagState::NotScanning) {
|
nfc->nfc_tag_state == TagState::NotScanning) {
|
||||||
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state.load()));
|
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state));
|
||||||
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
||||||
ErrorSummary::InvalidState, ErrorLevel::Status));
|
ErrorSummary::InvalidState, ErrorLevel::Status));
|
||||||
return;
|
return;
|
||||||
@ -192,13 +193,14 @@ void Module::Interface::ResetTagScanState(Kernel::HLERequestContext& ctx) {
|
|||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
if (nfc->nfc_tag_state != TagState::TagDataLoaded && nfc->nfc_tag_state != TagState::Unknown6) {
|
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()));
|
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state));
|
||||||
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
||||||
ErrorSummary::InvalidState, ErrorLevel::Status));
|
ErrorSummary::InvalidState, ErrorLevel::Status));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc->nfc_tag_state = TagState::TagInRange;
|
nfc->nfc_tag_state = TagState::TagInRange;
|
||||||
|
nfc->SyncTagState();
|
||||||
|
|
||||||
rb.Push(RESULT_SUCCESS);
|
rb.Push(RESULT_SUCCESS);
|
||||||
LOG_DEBUG(Service_NFC, "called");
|
LOG_DEBUG(Service_NFC, "called");
|
||||||
@ -208,7 +210,7 @@ void Module::Interface::GetTagInRangeEvent(Kernel::HLERequestContext& ctx) {
|
|||||||
IPC::RequestParser rp(ctx, 0x0B, 0, 0);
|
IPC::RequestParser rp(ctx, 0x0B, 0, 0);
|
||||||
|
|
||||||
if (nfc->nfc_tag_state != TagState::NotScanning) {
|
if (nfc->nfc_tag_state != TagState::NotScanning) {
|
||||||
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state.load()));
|
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state));
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
||||||
ErrorSummary::InvalidState, ErrorLevel::Status));
|
ErrorSummary::InvalidState, ErrorLevel::Status));
|
||||||
@ -225,7 +227,7 @@ void Module::Interface::GetTagOutOfRangeEvent(Kernel::HLERequestContext& ctx) {
|
|||||||
IPC::RequestParser rp(ctx, 0x0C, 0, 0);
|
IPC::RequestParser rp(ctx, 0x0C, 0, 0);
|
||||||
|
|
||||||
if (nfc->nfc_tag_state != TagState::NotScanning) {
|
if (nfc->nfc_tag_state != TagState::NotScanning) {
|
||||||
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state.load()));
|
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state));
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
||||||
ErrorSummary::InvalidState, ErrorLevel::Status));
|
ErrorSummary::InvalidState, ErrorLevel::Status));
|
||||||
@ -243,7 +245,7 @@ void Module::Interface::GetTagState(Kernel::HLERequestContext& ctx) {
|
|||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||||
rb.Push(RESULT_SUCCESS);
|
rb.Push(RESULT_SUCCESS);
|
||||||
rb.PushEnum(nfc->nfc_tag_state.load());
|
rb.PushEnum(nfc->nfc_tag_state);
|
||||||
LOG_DEBUG(Service_NFC, "called");
|
LOG_DEBUG(Service_NFC, "called");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,7 +263,7 @@ void Module::Interface::Unknown0x1A(Kernel::HLERequestContext& ctx) {
|
|||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
if (nfc->nfc_tag_state != TagState::TagInRange) {
|
if (nfc->nfc_tag_state != TagState::TagInRange) {
|
||||||
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state.load()));
|
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state));
|
||||||
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
||||||
ErrorSummary::InvalidState, ErrorLevel::Status));
|
ErrorSummary::InvalidState, ErrorLevel::Status));
|
||||||
return;
|
return;
|
||||||
@ -277,7 +279,7 @@ void Module::Interface::GetIdentificationBlock(Kernel::HLERequestContext& ctx) {
|
|||||||
IPC::RequestParser rp(ctx, 0x1B, 0, 0);
|
IPC::RequestParser rp(ctx, 0x1B, 0, 0);
|
||||||
|
|
||||||
if (nfc->nfc_tag_state != TagState::TagDataLoaded && nfc->nfc_tag_state != TagState::Unknown6) {
|
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()));
|
LOG_ERROR(Service_NFC, "Invalid TagState {}", static_cast<int>(nfc->nfc_tag_state));
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
rb.Push(ResultCode(ErrCodes::CommandInvalidForState, ErrorModule::NFC,
|
||||||
ErrorSummary::InvalidState, ErrorLevel::Status));
|
ErrorSummary::InvalidState, ErrorLevel::Status));
|
||||||
@ -304,15 +306,29 @@ std::shared_ptr<Module> Module::Interface::GetModule() const {
|
|||||||
void Module::Interface::LoadAmiibo(const AmiiboData& amiibo_data) {
|
void Module::Interface::LoadAmiibo(const AmiiboData& amiibo_data) {
|
||||||
std::lock_guard lock(HLE::g_hle_lock);
|
std::lock_guard lock(HLE::g_hle_lock);
|
||||||
nfc->amiibo_data = amiibo_data;
|
nfc->amiibo_data = amiibo_data;
|
||||||
nfc->nfc_tag_state = Service::NFC::TagState::TagInRange;
|
nfc->amiibo_in_range = true;
|
||||||
nfc->tag_in_range_event->Signal();
|
nfc->SyncTagState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::Interface::RemoveAmiibo() {
|
void Module::Interface::RemoveAmiibo() {
|
||||||
std::lock_guard lock(HLE::g_hle_lock);
|
std::lock_guard lock(HLE::g_hle_lock);
|
||||||
nfc->nfc_tag_state = Service::NFC::TagState::TagOutOfRange;
|
nfc->amiibo_in_range = false;
|
||||||
nfc->tag_out_of_range_event->Signal();
|
nfc->SyncTagState();
|
||||||
nfc->amiibo_data = {};
|
}
|
||||||
|
|
||||||
|
void Module::SyncTagState() {
|
||||||
|
if (amiibo_in_range &&
|
||||||
|
(nfc_tag_state == TagState::TagOutOfRange || nfc_tag_state == TagState::Scanning)) {
|
||||||
|
// TODO (wwylele): Should TagOutOfRange->TagInRange transition only happen on the same tag
|
||||||
|
// detected on Scanning->TagInRange?
|
||||||
|
nfc_tag_state = TagState::TagInRange;
|
||||||
|
tag_in_range_event->Signal();
|
||||||
|
} else if (!amiibo_in_range && nfc_tag_state == TagState::TagInRange) {
|
||||||
|
nfc_tag_state = TagState::TagOutOfRange;
|
||||||
|
// TODO (wwylele): If a tag is removed during TagDataLoaded/Unknown6, should this event
|
||||||
|
// signals early?
|
||||||
|
tag_out_of_range_event->Signal();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Module::Interface::Interface(std::shared_ptr<Module> nfc, const char* name, u32 max_session)
|
Module::Interface::Interface(std::shared_ptr<Module> nfc, const char* name, u32 max_session)
|
||||||
|
@ -231,12 +231,16 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Sync nfc_tag_state with amiibo_in_range and signal events on state change.
|
||||||
|
void SyncTagState();
|
||||||
|
|
||||||
std::shared_ptr<Kernel::Event> tag_in_range_event;
|
std::shared_ptr<Kernel::Event> tag_in_range_event;
|
||||||
std::shared_ptr<Kernel::Event> tag_out_of_range_event;
|
std::shared_ptr<Kernel::Event> tag_out_of_range_event;
|
||||||
std::atomic<TagState> nfc_tag_state = TagState::NotInitialized;
|
TagState nfc_tag_state = TagState::NotInitialized;
|
||||||
CommunicationStatus nfc_status = CommunicationStatus::NfcInitialized;
|
CommunicationStatus nfc_status = CommunicationStatus::NfcInitialized;
|
||||||
|
|
||||||
AmiiboData amiibo_data{};
|
AmiiboData amiibo_data{};
|
||||||
|
bool amiibo_in_range = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
void InstallInterfaces(Core::System& system);
|
void InstallInterfaces(Core::System& system);
|
||||||
|
Loading…
Reference in New Issue
Block a user