summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hid/emulated_controller.h9
-rw-r--r--src/core/hle/service/nfp/nfp.cpp74
-rw-r--r--src/core/hle/service/nfp/nfp.h37
3 files changed, 76 insertions, 44 deletions
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index 7785e6110..aa52f9572 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -299,16 +299,21 @@ public:
299 299
300 /** 300 /**
301 * Sends a specific vibration to the output device 301 * Sends a specific vibration to the output device
302 * @return returns true if vibration had no errors 302 * @return true if vibration had no errors
303 */ 303 */
304 bool SetVibration(std::size_t device_index, VibrationValue vibration); 304 bool SetVibration(std::size_t device_index, VibrationValue vibration);
305 305
306 /** 306 /**
307 * Sends a small vibration to the output device 307 * Sends a small vibration to the output device
308 * @return returns true if SetVibration was successfull 308 * @return true if SetVibration was successfull
309 */ 309 */
310 bool TestVibration(std::size_t device_index); 310 bool TestVibration(std::size_t device_index);
311 311
312 /**
313 * Sets the desired data to be polled from a controller
314 * @param polling_mode type of input desired buttons, gyro, nfc, ir, etc.
315 * @return true if SetPollingMode was successfull
316 */
312 bool SetPollingMode(Common::Input::PollingMode polling_mode); 317 bool SetPollingMode(Common::Input::PollingMode polling_mode);
313 318
314 /// Returns the led pattern corresponding to this emulated controller 319 /// Returns the led pattern corresponding to this emulated controller
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp
index 459fa798f..63e257975 100644
--- a/src/core/hle/service/nfp/nfp.cpp
+++ b/src/core/hle/service/nfp/nfp.cpp
@@ -479,7 +479,7 @@ void Module::Interface::CreateUserInterface(Kernel::HLERequestContext& ctx) {
479} 479}
480 480
481bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) { 481bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) {
482 if (buffer.size() < sizeof(AmiiboFile)) { 482 if (buffer.size() < sizeof(NTAG215File)) {
483 LOG_ERROR(Service_NFP, "Wrong file size"); 483 LOG_ERROR(Service_NFP, "Wrong file size");
484 return false; 484 return false;
485 } 485 }
@@ -490,12 +490,15 @@ bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) {
490 } 490 }
491 491
492 LOG_INFO(Service_NFP, "Amiibo detected"); 492 LOG_INFO(Service_NFP, "Amiibo detected");
493 std::memcpy(&amiibo, buffer.data(), sizeof(amiibo)); 493 std::memcpy(&tag_data, buffer.data(), sizeof(tag_data));
494 494
495 if (!IsAmiiboValid()) { 495 if (!IsAmiiboValid()) {
496 return false; 496 return false;
497 } 497 }
498 498
499 // This value can't be dumped from a tag. Generate it
500 tag_data.PWD = GetTagPassword(tag_data.uuid);
501
499 device_state = DeviceState::TagFound; 502 device_state = DeviceState::TagFound;
500 activate_event->GetWritableEvent().Signal(); 503 activate_event->GetWritableEvent().Signal();
501 return true; 504 return true;
@@ -511,42 +514,43 @@ void Module::Interface::CloseAmiibo() {
511} 514}
512 515
513bool Module::Interface::IsAmiiboValid() const { 516bool Module::Interface::IsAmiiboValid() const {
514 LOG_DEBUG(Service_NFP, "uuid_lock=0x{0:x}", amiibo.uuid_lock); 517 const auto& amiibo_data = tag_data.user_memory;
515 LOG_DEBUG(Service_NFP, "compability_container=0x{0:x}", amiibo.compability_container); 518 LOG_DEBUG(Service_NFP, "uuid_lock=0x{0:x}", tag_data.lock_bytes);
516 LOG_DEBUG(Service_NFP, "crypto_init=0x{0:x}", amiibo.crypto_init); 519 LOG_DEBUG(Service_NFP, "compability_container=0x{0:x}", tag_data.compability_container);
517 LOG_DEBUG(Service_NFP, "write_count={}", amiibo.write_count); 520 LOG_DEBUG(Service_NFP, "crypto_init=0x{0:x}", amiibo_data.crypto_init);
518 521 LOG_DEBUG(Service_NFP, "write_count={}", amiibo_data.write_count);
519 LOG_DEBUG(Service_NFP, "character_id=0x{0:x}", amiibo.model_info.character_id); 522
520 LOG_DEBUG(Service_NFP, "character_variant={}", amiibo.model_info.character_variant); 523 LOG_DEBUG(Service_NFP, "character_id=0x{0:x}", amiibo_data.model_info.character_id);
521 LOG_DEBUG(Service_NFP, "amiibo_type={}", amiibo.model_info.amiibo_type); 524 LOG_DEBUG(Service_NFP, "character_variant={}", amiibo_data.model_info.character_variant);
522 LOG_DEBUG(Service_NFP, "model_number=0x{0:x}", amiibo.model_info.model_number); 525 LOG_DEBUG(Service_NFP, "amiibo_type={}", amiibo_data.model_info.amiibo_type);
523 LOG_DEBUG(Service_NFP, "series={}", amiibo.model_info.series); 526 LOG_DEBUG(Service_NFP, "model_number=0x{0:x}", amiibo_data.model_info.model_number);
524 LOG_DEBUG(Service_NFP, "fixed_value=0x{0:x}", amiibo.model_info.fixed); 527 LOG_DEBUG(Service_NFP, "series={}", amiibo_data.model_info.series);
525 528 LOG_DEBUG(Service_NFP, "fixed_value=0x{0:x}", amiibo_data.model_info.fixed);
526 LOG_DEBUG(Service_NFP, "tag_dynamic_lock=0x{0:x}", amiibo.tag_dynamic_lock); 529
527 LOG_DEBUG(Service_NFP, "tag_CFG0=0x{0:x}", amiibo.tag_CFG0); 530 LOG_DEBUG(Service_NFP, "tag_dynamic_lock=0x{0:x}", tag_data.dynamic_lock);
528 LOG_DEBUG(Service_NFP, "tag_CFG1=0x{0:x}", amiibo.tag_CFG1); 531 LOG_DEBUG(Service_NFP, "tag_CFG0=0x{0:x}", tag_data.CFG0);
532 LOG_DEBUG(Service_NFP, "tag_CFG1=0x{0:x}", tag_data.CFG1);
529 533
530 // Check against all know constants on an amiibo binary 534 // Check against all know constants on an amiibo binary
531 if (amiibo.uuid_lock != 0xE00F) { 535 if (tag_data.lock_bytes != 0xE00F) {
532 return false; 536 return false;
533 } 537 }
534 if (amiibo.compability_container != 0xEEFF10F1UL) { 538 if (tag_data.compability_container != 0xEEFF10F1U) {
535 return false; 539 return false;
536 } 540 }
537 if ((amiibo.crypto_init & 0xFF) != 0xA5) { 541 if ((amiibo_data.crypto_init & 0xFF) != 0xA5) {
538 return false; 542 return false;
539 } 543 }
540 if (amiibo.model_info.fixed != 0x02) { 544 if (amiibo_data.model_info.fixed != 0x02) {
541 return false; 545 return false;
542 } 546 }
543 if ((amiibo.tag_dynamic_lock & 0xFFFFFF) != 0x0F0001) { 547 if ((tag_data.dynamic_lock & 0xFFFFFF) != 0x0F0001) {
544 return false; 548 return false;
545 } 549 }
546 if (amiibo.tag_CFG0 != 0x04000000UL) { 550 if (tag_data.CFG0 != 0x04000000U) {
547 return false; 551 return false;
548 } 552 }
549 if (amiibo.tag_CFG1 != 0x5F) { 553 if (tag_data.CFG1 != 0x5F) {
550 return false; 554 return false;
551 } 555 }
552 return true; 556 return true;
@@ -629,12 +633,11 @@ ResultCode Module::Interface::Unmount() {
629 633
630ResultCode Module::Interface::GetTagInfo(TagInfo& tag_info) const { 634ResultCode Module::Interface::GetTagInfo(TagInfo& tag_info) const {
631 if (device_state == DeviceState::TagFound || device_state == DeviceState::TagMounted) { 635 if (device_state == DeviceState::TagFound || device_state == DeviceState::TagMounted) {
632 // Read this data from the amiibo save file
633 tag_info = { 636 tag_info = {
634 .uuid = amiibo.uuid, 637 .uuid = tag_data.uuid,
635 .uuid_length = static_cast<u8>(amiibo.uuid.size()), 638 .uuid_length = static_cast<u8>(tag_data.uuid.size()),
636 .protocol = protocol, 639 .protocol = protocol,
637 .tag_type = static_cast<u32>(amiibo.model_info.amiibo_type), 640 .tag_type = static_cast<u32>(tag_data.user_memory.model_info.amiibo_type),
638 }; 641 };
639 return ResultSuccess; 642 return ResultSuccess;
640 } 643 }
@@ -654,7 +657,7 @@ ResultCode Module::Interface::GetCommonInfo(CommonInfo& common_info) const {
654 .last_write_year = 2022, 657 .last_write_year = 2022,
655 .last_write_month = 2, 658 .last_write_month = 2,
656 .last_write_day = 7, 659 .last_write_day = 7,
657 .write_counter = amiibo.write_count, 660 .write_counter = tag_data.user_memory.write_count,
658 .version = 1, 661 .version = 1,
659 .application_area_size = ApplicationAreaSize, 662 .application_area_size = ApplicationAreaSize,
660 }; 663 };
@@ -667,7 +670,7 @@ ResultCode Module::Interface::GetModelInfo(ModelInfo& model_info) const {
667 return ErrCodes::WrongDeviceState; 670 return ErrCodes::WrongDeviceState;
668 } 671 }
669 672
670 model_info = amiibo.model_info; 673 model_info = tag_data.user_memory.model_info;
671 return ResultSuccess; 674 return ResultSuccess;
672} 675}
673 676
@@ -757,7 +760,7 @@ bool Module::Interface::AmiiboApplicationDataExist(u32 access_id) const {
757 return false; 760 return false;
758} 761}
759 762
760const std::vector<u8> Module::Interface::LoadAmiiboApplicationData(u32 access_id) const { 763std::vector<u8> Module::Interface::LoadAmiiboApplicationData(u32 access_id) const {
761 // TODO(german77): Read file 764 // TODO(german77): Read file
762 std::vector<u8> data(ApplicationAreaSize); 765 std::vector<u8> data(ApplicationAreaSize);
763 return data; 766 return data;
@@ -781,6 +784,15 @@ Core::HID::NpadIdType Module::Interface::GetNpadId() const {
781 return npad_id; 784 return npad_id;
782} 785}
783 786
787u32 Module::Interface::GetTagPassword(const TagUuid& uuid) const {
788 // Verifiy that the generated password is correct
789 u32 password = 0xAA ^ (uuid[1] ^ uuid[3]);
790 password &= (0x55 ^ (uuid[2] ^ uuid[4])) << 8;
791 password &= (0xAA ^ (uuid[3] ^ uuid[5])) << 16;
792 password &= (0x55 ^ (uuid[4] ^ uuid[6])) << 24;
793 return password;
794}
795
784void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { 796void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
785 auto module = std::make_shared<Module>(); 797 auto module = std::make_shared<Module>();
786 std::make_shared<NFP_User>(module, system)->InstallAsService(service_manager); 798 std::make_shared<NFP_User>(module, system)->InstallAsService(service_manager);
diff --git a/src/core/hle/service/nfp/nfp.h b/src/core/hle/service/nfp/nfp.h
index 633539dcc..bc3b1967f 100644
--- a/src/core/hle/service/nfp/nfp.h
+++ b/src/core/hle/service/nfp/nfp.h
@@ -7,6 +7,7 @@
7#include <array> 7#include <array>
8#include <vector> 8#include <vector>
9 9
10#include "common/common_funcs.h"
10#include "core/hle/service/kernel_helpers.h" 11#include "core/hle/service/kernel_helpers.h"
11#include "core/hle/service/mii/mii_manager.h" 12#include "core/hle/service/mii/mii_manager.h"
12#include "core/hle/service/service.h" 13#include "core/hle/service/service.h"
@@ -85,8 +86,10 @@ enum class AmiiboSeries : u8 {
85 Diablo 86 Diablo
86}; 87};
87 88
89using TagUuid = std::array<u8, 10>;
90
88struct TagInfo { 91struct TagInfo {
89 std::array<u8, 10> uuid; 92 TagUuid uuid;
90 u8 uuid_length; 93 u8 uuid_length;
91 INSERT_PADDING_BYTES(0x15); 94 INSERT_PADDING_BYTES(0x15);
92 s32 protocol; 95 s32 protocol;
@@ -138,10 +141,7 @@ public:
138 const char* name); 141 const char* name);
139 ~Interface() override; 142 ~Interface() override;
140 143
141 struct AmiiboFile { 144 struct EncryptedAmiiboFile {
142 std::array<u8, 10> uuid;
143 u16 uuid_lock; // Must be 0F E0
144 u32 compability_container; // Must be F1 10 FF EE
145 u16 crypto_init; // Must be A5 XX 145 u16 crypto_init; // Must be A5 XX
146 u16 write_count; // Number of times the amiibo has been written? 146 u16 write_count; // Number of times the amiibo has been written?
147 INSERT_PADDING_BYTES(0x20); // System crypts 147 INSERT_PADDING_BYTES(0x20); // System crypts
@@ -150,11 +150,22 @@ public:
150 INSERT_PADDING_BYTES(0xC); // SHA256-HMAC 150 INSERT_PADDING_BYTES(0xC); // SHA256-HMAC
151 INSERT_PADDING_BYTES(0x114); // section 1 encrypted buffer 151 INSERT_PADDING_BYTES(0x114); // section 1 encrypted buffer
152 INSERT_PADDING_BYTES(0x54); // section 2 encrypted buffer 152 INSERT_PADDING_BYTES(0x54); // section 2 encrypted buffer
153 u32 tag_dynamic_lock; // Must be 01 00 0F XX
154 u32 tag_CFG0; // Must be 00 00 00 04
155 u32 tag_CFG1; // Must be 50 00 00 00
156 }; 153 };
157 static_assert(sizeof(AmiiboFile) == 0x214, "AmiiboFile is an invalid size"); 154 static_assert(sizeof(EncryptedAmiiboFile) == 0x1F8, "AmiiboFile is an invalid size");
155
156 struct NTAG215File {
157 TagUuid uuid; // Unique serial number
158 u16 lock_bytes; // Set defined pages as read only
159 u32 compability_container; // Defines available memory
160 EncryptedAmiiboFile user_memory; // Writable data
161 u32 dynamic_lock; // Dynamic lock
162 u32 CFG0; // Defines memory protected by password
163 u32 CFG1; // Defines number of verification attempts
164 u32 PWD; // Password to allow write access
165 u16 PACK; // Password acknowledge reply
166 u16 RFUI; // Reserved for future use
167 };
168 static_assert(sizeof(NTAG215File) == 0x21C, "NTAG215File is an invalid size");
158 169
159 void CreateUserInterface(Kernel::HLERequestContext& ctx); 170 void CreateUserInterface(Kernel::HLERequestContext& ctx);
160 bool LoadAmiibo(const std::vector<u8>& buffer); 171 bool LoadAmiibo(const std::vector<u8>& buffer);
@@ -191,17 +202,21 @@ public:
191 private: 202 private:
192 /// Validates that the amiibo file is not corrupted 203 /// Validates that the amiibo file is not corrupted
193 bool IsAmiiboValid() const; 204 bool IsAmiiboValid() const;
205
194 bool AmiiboApplicationDataExist(u32 access_id) const; 206 bool AmiiboApplicationDataExist(u32 access_id) const;
195 const std::vector<u8> LoadAmiiboApplicationData(u32 access_id) const; 207 std::vector<u8> LoadAmiiboApplicationData(u32 access_id) const;
196 void SaveAmiiboApplicationData(u32 access_id, const std::vector<u8>& data) const; 208 void SaveAmiiboApplicationData(u32 access_id, const std::vector<u8>& data) const;
197 209
210 /// return password needed to allow write access to protected memory
211 u32 GetTagPassword(const TagUuid& uuid) const;
212
198 const Core::HID::NpadIdType npad_id; 213 const Core::HID::NpadIdType npad_id;
199 214
200 DeviceState device_state{DeviceState::Unaviable}; 215 DeviceState device_state{DeviceState::Unaviable};
201 KernelHelpers::ServiceContext service_context; 216 KernelHelpers::ServiceContext service_context;
202 Kernel::KEvent* activate_event; 217 Kernel::KEvent* activate_event;
203 Kernel::KEvent* deactivate_event; 218 Kernel::KEvent* deactivate_event;
204 AmiiboFile amiibo{}; 219 NTAG215File tag_data{};
205 s32 protocol; 220 s32 protocol;
206 bool is_application_area_initialized{}; 221 bool is_application_area_initialized{};
207 u32 application_area_id; 222 u32 application_area_id;