|
|
@ -98,11 +98,6 @@ bool NfpDevice::LoadAmiibo(std::span<const u8> data) {
|
|
|
|
|
|
|
|
|
|
|
|
memcpy(&encrypted_tag_data, data.data(), sizeof(EncryptedNTAG215File));
|
|
|
|
memcpy(&encrypted_tag_data, data.data(), sizeof(EncryptedNTAG215File));
|
|
|
|
|
|
|
|
|
|
|
|
if (!AmiiboCrypto::IsAmiiboValid(encrypted_tag_data)) {
|
|
|
|
|
|
|
|
LOG_INFO(Service_NFP, "Invalid amiibo");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
device_state = DeviceState::TagFound;
|
|
|
|
device_state = DeviceState::TagFound;
|
|
|
|
deactivate_event->GetReadableEvent().Clear();
|
|
|
|
deactivate_event->GetReadableEvent().Clear();
|
|
|
|
activate_event->GetWritableEvent().Signal();
|
|
|
|
activate_event->GetWritableEvent().Signal();
|
|
|
@ -148,20 +143,28 @@ void NfpDevice::Finalize() {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Result NfpDevice::StartDetection(s32 protocol_) {
|
|
|
|
Result NfpDevice::StartDetection(s32 protocol_) {
|
|
|
|
if (device_state == DeviceState::Initialized || device_state == DeviceState::TagRemoved) {
|
|
|
|
if (device_state != DeviceState::Initialized && device_state != DeviceState::TagRemoved) {
|
|
|
|
npad_device->SetPollingMode(Common::Input::PollingMode::NFC);
|
|
|
|
LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
|
|
|
|
device_state = DeviceState::SearchingForTag;
|
|
|
|
return WrongDeviceState;
|
|
|
|
protocol = protocol_;
|
|
|
|
|
|
|
|
return ResultSuccess;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
|
|
|
|
if (!npad_device->SetPollingMode(Common::Input::PollingMode::NFC)) {
|
|
|
|
return WrongDeviceState;
|
|
|
|
LOG_ERROR(Service_NFP, "Nfc not supported");
|
|
|
|
|
|
|
|
return NfcDisabled;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
device_state = DeviceState::SearchingForTag;
|
|
|
|
|
|
|
|
protocol = protocol_;
|
|
|
|
|
|
|
|
return ResultSuccess;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Result NfpDevice::StopDetection() {
|
|
|
|
Result NfpDevice::StopDetection() {
|
|
|
|
npad_device->SetPollingMode(Common::Input::PollingMode::Active);
|
|
|
|
npad_device->SetPollingMode(Common::Input::PollingMode::Active);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (device_state == DeviceState::Initialized) {
|
|
|
|
|
|
|
|
return ResultSuccess;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (device_state == DeviceState::TagFound || device_state == DeviceState::TagMounted) {
|
|
|
|
if (device_state == DeviceState::TagFound || device_state == DeviceState::TagMounted) {
|
|
|
|
CloseAmiibo();
|
|
|
|
CloseAmiibo();
|
|
|
|
return ResultSuccess;
|
|
|
|
return ResultSuccess;
|
|
|
@ -225,6 +228,11 @@ Result NfpDevice::Mount(MountTarget mount_target_) {
|
|
|
|
return WrongDeviceState;
|
|
|
|
return WrongDeviceState;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!AmiiboCrypto::IsAmiiboValid(encrypted_tag_data)) {
|
|
|
|
|
|
|
|
LOG_ERROR(Service_NFP, "Not an amiibo");
|
|
|
|
|
|
|
|
return NotAnAmiibo;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) {
|
|
|
|
if (!AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) {
|
|
|
|
LOG_ERROR(Service_NFP, "Can't decode amiibo {}", device_state);
|
|
|
|
LOG_ERROR(Service_NFP, "Can't decode amiibo {}", device_state);
|
|
|
|
return CorruptedData;
|
|
|
|
return CorruptedData;
|
|
|
@ -238,6 +246,9 @@ Result NfpDevice::Mount(MountTarget mount_target_) {
|
|
|
|
Result NfpDevice::Unmount() {
|
|
|
|
Result NfpDevice::Unmount() {
|
|
|
|
if (device_state != DeviceState::TagMounted) {
|
|
|
|
if (device_state != DeviceState::TagMounted) {
|
|
|
|
LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
|
|
|
|
LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
|
|
|
|
|
|
|
|
if (device_state == DeviceState::TagRemoved) {
|
|
|
|
|
|
|
|
return TagRemoved;
|
|
|
|
|
|
|
|
}
|
|
|
|
return WrongDeviceState;
|
|
|
|
return WrongDeviceState;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -256,6 +267,9 @@ Result NfpDevice::Unmount() {
|
|
|
|
Result NfpDevice::GetTagInfo(TagInfo& tag_info) const {
|
|
|
|
Result NfpDevice::GetTagInfo(TagInfo& tag_info) const {
|
|
|
|
if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted) {
|
|
|
|
if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted) {
|
|
|
|
LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
|
|
|
|
LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
|
|
|
|
|
|
|
|
if (device_state == DeviceState::TagRemoved) {
|
|
|
|
|
|
|
|
return TagRemoved;
|
|
|
|
|
|
|
|
}
|
|
|
|
return WrongDeviceState;
|
|
|
|
return WrongDeviceState;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -287,12 +301,7 @@ Result NfpDevice::GetCommonInfo(CommonInfo& common_info) const {
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: Validate this data
|
|
|
|
// TODO: Validate this data
|
|
|
|
common_info = {
|
|
|
|
common_info = {
|
|
|
|
.last_write_date =
|
|
|
|
.last_write_date = settings.write_date.GetWriteDate(),
|
|
|
|
{
|
|
|
|
|
|
|
|
settings.write_date.GetYear(),
|
|
|
|
|
|
|
|
settings.write_date.GetMonth(),
|
|
|
|
|
|
|
|
settings.write_date.GetDay(),
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
.write_counter = tag_data.write_counter,
|
|
|
|
.write_counter = tag_data.write_counter,
|
|
|
|
.version = 0,
|
|
|
|
.version = 0,
|
|
|
|
.application_area_size = sizeof(ApplicationArea),
|
|
|
|
.application_area_size = sizeof(ApplicationArea),
|
|
|
@ -303,6 +312,9 @@ Result NfpDevice::GetCommonInfo(CommonInfo& common_info) const {
|
|
|
|
Result NfpDevice::GetModelInfo(ModelInfo& model_info) const {
|
|
|
|
Result NfpDevice::GetModelInfo(ModelInfo& model_info) const {
|
|
|
|
if (device_state != DeviceState::TagMounted) {
|
|
|
|
if (device_state != DeviceState::TagMounted) {
|
|
|
|
LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
|
|
|
|
LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
|
|
|
|
|
|
|
|
if (device_state == DeviceState::TagRemoved) {
|
|
|
|
|
|
|
|
return TagRemoved;
|
|
|
|
|
|
|
|
}
|
|
|
|
return WrongDeviceState;
|
|
|
|
return WrongDeviceState;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -341,12 +353,7 @@ Result NfpDevice::GetRegisterInfo(RegisterInfo& register_info) const {
|
|
|
|
// TODO: Validate this data
|
|
|
|
// TODO: Validate this data
|
|
|
|
register_info = {
|
|
|
|
register_info = {
|
|
|
|
.mii_char_info = manager.ConvertV3ToCharInfo(tag_data.owner_mii),
|
|
|
|
.mii_char_info = manager.ConvertV3ToCharInfo(tag_data.owner_mii),
|
|
|
|
.creation_date =
|
|
|
|
.creation_date = settings.init_date.GetWriteDate(),
|
|
|
|
{
|
|
|
|
|
|
|
|
settings.init_date.GetYear(),
|
|
|
|
|
|
|
|
settings.init_date.GetMonth(),
|
|
|
|
|
|
|
|
settings.init_date.GetDay(),
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
.amiibo_name = GetAmiiboName(settings),
|
|
|
|
.amiibo_name = GetAmiiboName(settings),
|
|
|
|
.font_region = {},
|
|
|
|
.font_region = {},
|
|
|
|
};
|
|
|
|
};
|
|
|
@ -478,8 +485,7 @@ Result NfpDevice::GetApplicationArea(std::vector<u8>& data) const {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (data.size() > sizeof(ApplicationArea)) {
|
|
|
|
if (data.size() > sizeof(ApplicationArea)) {
|
|
|
|
LOG_ERROR(Service_NFP, "Wrong data size {}", data.size());
|
|
|
|
data.resize(sizeof(ApplicationArea));
|
|
|
|
return ResultUnknown;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
memcpy(data.data(), tag_data.application_area.data(), data.size());
|
|
|
|
memcpy(data.data(), tag_data.application_area.data(), data.size());
|
|
|
@ -518,7 +524,7 @@ Result NfpDevice::SetApplicationArea(std::span<const u8> data) {
|
|
|
|
|
|
|
|
|
|
|
|
Common::TinyMT rng{};
|
|
|
|
Common::TinyMT rng{};
|
|
|
|
std::memcpy(tag_data.application_area.data(), data.data(), data.size());
|
|
|
|
std::memcpy(tag_data.application_area.data(), data.data(), data.size());
|
|
|
|
// HW seems to fill excess data with garbage
|
|
|
|
// Fill remaining data with random numbers
|
|
|
|
rng.GenerateRandomBytes(tag_data.application_area.data() + data.size(),
|
|
|
|
rng.GenerateRandomBytes(tag_data.application_area.data() + data.size(),
|
|
|
|
sizeof(ApplicationArea) - data.size());
|
|
|
|
sizeof(ApplicationArea) - data.size());
|
|
|
|
|
|
|
|
|
|
|
@ -561,12 +567,12 @@ Result NfpDevice::RecreateApplicationArea(u32 access_id, std::span<const u8> dat
|
|
|
|
|
|
|
|
|
|
|
|
if (data.size() > sizeof(ApplicationArea)) {
|
|
|
|
if (data.size() > sizeof(ApplicationArea)) {
|
|
|
|
LOG_ERROR(Service_NFP, "Wrong data size {}", data.size());
|
|
|
|
LOG_ERROR(Service_NFP, "Wrong data size {}", data.size());
|
|
|
|
return ResultUnknown;
|
|
|
|
return WrongApplicationAreaSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Common::TinyMT rng{};
|
|
|
|
Common::TinyMT rng{};
|
|
|
|
std::memcpy(tag_data.application_area.data(), data.data(), data.size());
|
|
|
|
std::memcpy(tag_data.application_area.data(), data.data(), data.size());
|
|
|
|
// HW seems to fill excess data with garbage
|
|
|
|
// Fill remaining data with random numbers
|
|
|
|
rng.GenerateRandomBytes(tag_data.application_area.data() + data.size(),
|
|
|
|
rng.GenerateRandomBytes(tag_data.application_area.data() + data.size(),
|
|
|
|
sizeof(ApplicationArea) - data.size());
|
|
|
|
sizeof(ApplicationArea) - data.size());
|
|
|
|
|
|
|
|
|
|
|
@ -612,7 +618,6 @@ u64 NfpDevice::GetHandle() const {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
u32 NfpDevice::GetApplicationAreaSize() const {
|
|
|
|
u32 NfpDevice::GetApplicationAreaSize() const {
|
|
|
|
// Investigate if this value is really constant
|
|
|
|
|
|
|
|
return sizeof(ApplicationArea);
|
|
|
|
return sizeof(ApplicationArea);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|