diff options
| author | 2023-06-16 21:57:21 -0600 | |
|---|---|---|
| committer | 2023-06-21 17:54:58 -0600 | |
| commit | 84d43489c5df9f450efb0293cc58161d08e3b882 (patch) | |
| tree | c4d45b021c78392956dc58d409a34632fe135d2b /src/input_common/helpers/joycon_protocol/nfc.cpp | |
| parent | Merge pull request #10783 from liamwhite/memory (diff) | |
| download | yuzu-84d43489c5df9f450efb0293cc58161d08e3b882.tar.gz yuzu-84d43489c5df9f450efb0293cc58161d08e3b882.tar.xz yuzu-84d43489c5df9f450efb0293cc58161d08e3b882.zip | |
input_common: Implement native mifare support
Diffstat (limited to 'src/input_common/helpers/joycon_protocol/nfc.cpp')
| -rw-r--r-- | src/input_common/helpers/joycon_protocol/nfc.cpp | 390 |
1 files changed, 383 insertions, 7 deletions
diff --git a/src/input_common/helpers/joycon_protocol/nfc.cpp b/src/input_common/helpers/joycon_protocol/nfc.cpp index f7058c4a7..261f46255 100644 --- a/src/input_common/helpers/joycon_protocol/nfc.cpp +++ b/src/input_common/helpers/joycon_protocol/nfc.cpp | |||
| @@ -40,6 +40,16 @@ DriverResult NfcProtocol::EnableNfc() { | |||
| 40 | if (result == DriverResult::Success) { | 40 | if (result == DriverResult::Success) { |
| 41 | result = WaitUntilNfcIs(NFCStatus::Ready); | 41 | result = WaitUntilNfcIs(NFCStatus::Ready); |
| 42 | } | 42 | } |
| 43 | if (result == DriverResult::Success) { | ||
| 44 | MCUCommandResponse output{}; | ||
| 45 | result = SendStopPollingRequest(output); | ||
| 46 | } | ||
| 47 | if (result == DriverResult::Success) { | ||
| 48 | result = WaitUntilNfcIs(NFCStatus::Ready); | ||
| 49 | } | ||
| 50 | if (result == DriverResult::Success) { | ||
| 51 | is_enabled = true; | ||
| 52 | } | ||
| 43 | 53 | ||
| 44 | return result; | 54 | return result; |
| 45 | } | 55 | } |
| @@ -54,37 +64,50 @@ DriverResult NfcProtocol::DisableNfc() { | |||
| 54 | } | 64 | } |
| 55 | 65 | ||
| 56 | is_enabled = false; | 66 | is_enabled = false; |
| 67 | is_polling = false; | ||
| 57 | 68 | ||
| 58 | return result; | 69 | return result; |
| 59 | } | 70 | } |
| 60 | 71 | ||
| 61 | DriverResult NfcProtocol::StartNFCPollingMode() { | 72 | DriverResult NfcProtocol::StartNFCPollingMode() { |
| 62 | LOG_DEBUG(Input, "Start NFC pooling Mode"); | 73 | LOG_DEBUG(Input, "Start NFC polling Mode"); |
| 63 | ScopedSetBlocking sb(this); | 74 | ScopedSetBlocking sb(this); |
| 64 | DriverResult result{DriverResult::Success}; | 75 | DriverResult result{DriverResult::Success}; |
| 65 | 76 | ||
| 66 | if (result == DriverResult::Success) { | 77 | if (result == DriverResult::Success) { |
| 67 | MCUCommandResponse output{}; | 78 | MCUCommandResponse output{}; |
| 68 | result = SendStopPollingRequest(output); | 79 | result = SendStartPollingRequest(output); |
| 69 | } | 80 | } |
| 70 | if (result == DriverResult::Success) { | 81 | if (result == DriverResult::Success) { |
| 71 | result = WaitUntilNfcIs(NFCStatus::Ready); | 82 | result = WaitUntilNfcIs(NFCStatus::Polling); |
| 72 | } | 83 | } |
| 73 | if (result == DriverResult::Success) { | 84 | if (result == DriverResult::Success) { |
| 85 | is_polling = true; | ||
| 86 | } | ||
| 87 | |||
| 88 | return result; | ||
| 89 | } | ||
| 90 | |||
| 91 | DriverResult NfcProtocol::StopNFCPollingMode() { | ||
| 92 | LOG_DEBUG(Input, "Stop NFC polling Mode"); | ||
| 93 | ScopedSetBlocking sb(this); | ||
| 94 | DriverResult result{DriverResult::Success}; | ||
| 95 | |||
| 96 | if (result == DriverResult::Success) { | ||
| 74 | MCUCommandResponse output{}; | 97 | MCUCommandResponse output{}; |
| 75 | result = SendStartPollingRequest(output); | 98 | result = SendStopPollingRequest(output); |
| 76 | } | 99 | } |
| 77 | if (result == DriverResult::Success) { | 100 | if (result == DriverResult::Success) { |
| 78 | result = WaitUntilNfcIs(NFCStatus::Polling); | 101 | result = WaitUntilNfcIs(NFCStatus::WriteReady); |
| 79 | } | 102 | } |
| 80 | if (result == DriverResult::Success) { | 103 | if (result == DriverResult::Success) { |
| 81 | is_enabled = true; | 104 | is_polling = false; |
| 82 | } | 105 | } |
| 83 | 106 | ||
| 84 | return result; | 107 | return result; |
| 85 | } | 108 | } |
| 86 | 109 | ||
| 87 | DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) { | 110 | DriverResult NfcProtocol::GetTagInfo(Joycon::TagInfo& tag_info) { |
| 88 | if (update_counter++ < AMIIBO_UPDATE_DELAY) { | 111 | if (update_counter++ < AMIIBO_UPDATE_DELAY) { |
| 89 | return DriverResult::Delayed; | 112 | return DriverResult::Delayed; |
| 90 | } | 113 | } |
| @@ -100,11 +123,41 @@ DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) { | |||
| 100 | } | 123 | } |
| 101 | 124 | ||
| 102 | if (result == DriverResult::Success) { | 125 | if (result == DriverResult::Success) { |
| 126 | tag_info = { | ||
| 127 | .uuid_length = tag_data.uuid_size, | ||
| 128 | .protocol = 1, | ||
| 129 | .tag_type = tag_data.type, | ||
| 130 | .uuid = {}, | ||
| 131 | }; | ||
| 132 | |||
| 133 | memcpy(tag_info.uuid.data(), tag_data.uuid.data(), tag_data.uuid_size); | ||
| 134 | |||
| 135 | // Investigate why mifare type is not correct | ||
| 136 | if (tag_info.tag_type == 144) { | ||
| 137 | tag_info.tag_type = 1U << 6; | ||
| 138 | } | ||
| 139 | |||
| 103 | std::string uuid_string; | 140 | std::string uuid_string; |
| 104 | for (auto& content : tag_data.uuid) { | 141 | for (auto& content : tag_data.uuid) { |
| 105 | uuid_string += fmt::format(" {:02x}", content); | 142 | uuid_string += fmt::format(" {:02x}", content); |
| 106 | } | 143 | } |
| 107 | LOG_INFO(Input, "Tag detected, type={}, uuid={}", tag_data.type, uuid_string); | 144 | LOG_INFO(Input, "Tag detected, type={}, uuid={}", tag_data.type, uuid_string); |
| 145 | } | ||
| 146 | |||
| 147 | return result; | ||
| 148 | } | ||
| 149 | |||
| 150 | DriverResult NfcProtocol::ReadAmiibo(std::vector<u8>& data) { | ||
| 151 | LOG_DEBUG(Input, "Scan for amiibos"); | ||
| 152 | ScopedSetBlocking sb(this); | ||
| 153 | DriverResult result{DriverResult::Success}; | ||
| 154 | TagFoundData tag_data{}; | ||
| 155 | |||
| 156 | if (result == DriverResult::Success) { | ||
| 157 | result = IsTagInRange(tag_data, 7); | ||
| 158 | } | ||
| 159 | |||
| 160 | if (result == DriverResult::Success) { | ||
| 108 | result = GetAmiiboData(data); | 161 | result = GetAmiiboData(data); |
| 109 | } | 162 | } |
| 110 | 163 | ||
| @@ -154,6 +207,69 @@ DriverResult NfcProtocol::WriteAmiibo(std::span<const u8> data) { | |||
| 154 | return result; | 207 | return result; |
| 155 | } | 208 | } |
| 156 | 209 | ||
| 210 | DriverResult NfcProtocol::ReadMifare(std::span<const MifareReadChunk> read_request, | ||
| 211 | std::span<MifareReadData> out_data) { | ||
| 212 | LOG_DEBUG(Input, "Read mifare"); | ||
| 213 | ScopedSetBlocking sb(this); | ||
| 214 | DriverResult result{DriverResult::Success}; | ||
| 215 | TagFoundData tag_data{}; | ||
| 216 | MifareUUID tag_uuid{}; | ||
| 217 | |||
| 218 | if (result == DriverResult::Success) { | ||
| 219 | result = IsTagInRange(tag_data, 7); | ||
| 220 | } | ||
| 221 | if (result == DriverResult::Success) { | ||
| 222 | memcpy(tag_uuid.data(), tag_data.uuid.data(), sizeof(MifareUUID)); | ||
| 223 | result = GetMifareData(tag_uuid, read_request, out_data); | ||
| 224 | } | ||
| 225 | if (result == DriverResult::Success) { | ||
| 226 | MCUCommandResponse output{}; | ||
| 227 | result = SendStopPollingRequest(output); | ||
| 228 | } | ||
| 229 | if (result == DriverResult::Success) { | ||
| 230 | result = WaitUntilNfcIs(NFCStatus::Ready); | ||
| 231 | } | ||
| 232 | if (result == DriverResult::Success) { | ||
| 233 | MCUCommandResponse output{}; | ||
| 234 | result = SendStartPollingRequest(output, true); | ||
| 235 | } | ||
| 236 | if (result == DriverResult::Success) { | ||
| 237 | result = WaitUntilNfcIs(NFCStatus::WriteReady); | ||
| 238 | } | ||
| 239 | return result; | ||
| 240 | } | ||
| 241 | |||
| 242 | DriverResult NfcProtocol::WriteMifare(std::span<const MifareWriteChunk> write_request) { | ||
| 243 | LOG_DEBUG(Input, "Write mifare"); | ||
| 244 | ScopedSetBlocking sb(this); | ||
| 245 | DriverResult result{DriverResult::Success}; | ||
| 246 | TagFoundData tag_data{}; | ||
| 247 | MifareUUID tag_uuid{}; | ||
| 248 | |||
| 249 | if (result == DriverResult::Success) { | ||
| 250 | result = IsTagInRange(tag_data, 7); | ||
| 251 | } | ||
| 252 | if (result == DriverResult::Success) { | ||
| 253 | memcpy(tag_uuid.data(), tag_data.uuid.data(), sizeof(MifareUUID)); | ||
| 254 | result = WriteMifareData(tag_uuid, write_request); | ||
| 255 | } | ||
| 256 | if (result == DriverResult::Success) { | ||
| 257 | MCUCommandResponse output{}; | ||
| 258 | result = SendStopPollingRequest(output); | ||
| 259 | } | ||
| 260 | if (result == DriverResult::Success) { | ||
| 261 | result = WaitUntilNfcIs(NFCStatus::Ready); | ||
| 262 | } | ||
| 263 | if (result == DriverResult::Success) { | ||
| 264 | MCUCommandResponse output{}; | ||
| 265 | result = SendStartPollingRequest(output, true); | ||
| 266 | } | ||
| 267 | if (result == DriverResult::Success) { | ||
| 268 | result = WaitUntilNfcIs(NFCStatus::WriteReady); | ||
| 269 | } | ||
| 270 | return result; | ||
| 271 | } | ||
| 272 | |||
| 157 | bool NfcProtocol::HasAmiibo() { | 273 | bool NfcProtocol::HasAmiibo() { |
| 158 | if (update_counter++ < AMIIBO_UPDATE_DELAY) { | 274 | if (update_counter++ < AMIIBO_UPDATE_DELAY) { |
| 159 | return true; | 275 | return true; |
| @@ -341,6 +457,158 @@ DriverResult NfcProtocol::WriteAmiiboData(const TagUUID& tag_uuid, std::span<con | |||
| 341 | return result; | 457 | return result; |
| 342 | } | 458 | } |
| 343 | 459 | ||
| 460 | DriverResult NfcProtocol::GetMifareData(const MifareUUID& tag_uuid, | ||
| 461 | std::span<const MifareReadChunk> read_request, | ||
| 462 | std::span<MifareReadData> out_data) { | ||
| 463 | constexpr std::size_t timeout_limit = 60; | ||
| 464 | const auto nfc_data = MakeMifareReadPackage(tag_uuid, read_request); | ||
| 465 | const std::vector<u8> nfc_buffer_data = SerializeMifareReadPackage(nfc_data); | ||
| 466 | std::span<const u8> buffer(nfc_buffer_data); | ||
| 467 | DriverResult result = DriverResult::Success; | ||
| 468 | MCUCommandResponse output{}; | ||
| 469 | u8 block_id = 1; | ||
| 470 | u8 package_index = 0; | ||
| 471 | std::size_t tries = 0; | ||
| 472 | std::size_t current_position = 0; | ||
| 473 | |||
| 474 | LOG_INFO(Input, "Reading Mifare data"); | ||
| 475 | |||
| 476 | // Send data request. Nfc buffer size is 31, Send the data in smaller packages | ||
| 477 | while (current_position < buffer.size() && tries++ < timeout_limit) { | ||
| 478 | const std::size_t next_position = | ||
| 479 | std::min(current_position + sizeof(NFCRequestState::raw_data), buffer.size()); | ||
| 480 | const std::size_t block_size = next_position - current_position; | ||
| 481 | const bool is_last_packet = block_size < sizeof(NFCRequestState::raw_data); | ||
| 482 | |||
| 483 | SendReadDataMifareRequest(output, block_id, is_last_packet, | ||
| 484 | buffer.subspan(current_position, block_size)); | ||
| 485 | |||
| 486 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); | ||
| 487 | |||
| 488 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::TagLost) { | ||
| 489 | return DriverResult::ErrorReadingData; | ||
| 490 | } | ||
| 491 | |||
| 492 | // Increase position when data is confirmed by the joycon | ||
| 493 | if (output.mcu_report == MCUReport::NFCState && | ||
| 494 | (output.mcu_data[1] << 8) + output.mcu_data[0] == 0x0500 && | ||
| 495 | output.mcu_data[3] == block_id) { | ||
| 496 | block_id++; | ||
| 497 | current_position = next_position; | ||
| 498 | } | ||
| 499 | } | ||
| 500 | |||
| 501 | if (result != DriverResult::Success) { | ||
| 502 | return result; | ||
| 503 | } | ||
| 504 | |||
| 505 | // Wait for reply and save the output data | ||
| 506 | while (tries++ < timeout_limit) { | ||
| 507 | result = SendNextPackageRequest(output, package_index); | ||
| 508 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); | ||
| 509 | |||
| 510 | if (result != DriverResult::Success) { | ||
| 511 | return result; | ||
| 512 | } | ||
| 513 | |||
| 514 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::TagLost) { | ||
| 515 | return DriverResult::ErrorReadingData; | ||
| 516 | } | ||
| 517 | |||
| 518 | if (output.mcu_report == MCUReport::NFCState && output.mcu_data[1] == 0x10) { | ||
| 519 | constexpr std::size_t DATA_LENGHT = 0x10 + 1; | ||
| 520 | constexpr std::size_t DATA_START = 11; | ||
| 521 | const u8 number_of_elements = output.mcu_data[10]; | ||
| 522 | for (std::size_t i = 0; i < number_of_elements; i++) { | ||
| 523 | out_data[i].sector = output.mcu_data[DATA_START + (i * DATA_LENGHT)]; | ||
| 524 | memcpy(out_data[i].data.data(), | ||
| 525 | output.mcu_data.data() + DATA_START + 1 + (i * DATA_LENGHT), | ||
| 526 | sizeof(MifareReadData::data)); | ||
| 527 | } | ||
| 528 | package_index++; | ||
| 529 | continue; | ||
| 530 | } | ||
| 531 | |||
| 532 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::MifareDone) { | ||
| 533 | LOG_INFO(Input, "Finished reading mifare"); | ||
| 534 | break; | ||
| 535 | } | ||
| 536 | } | ||
| 537 | |||
| 538 | return result; | ||
| 539 | } | ||
| 540 | |||
| 541 | DriverResult NfcProtocol::WriteMifareData(const MifareUUID& tag_uuid, | ||
| 542 | std::span<const MifareWriteChunk> write_request) { | ||
| 543 | constexpr std::size_t timeout_limit = 60; | ||
| 544 | const auto nfc_data = MakeMifareWritePackage(tag_uuid, write_request); | ||
| 545 | const std::vector<u8> nfc_buffer_data = SerializeMifareWritePackage(nfc_data); | ||
| 546 | std::span<const u8> buffer(nfc_buffer_data); | ||
| 547 | DriverResult result = DriverResult::Success; | ||
| 548 | MCUCommandResponse output{}; | ||
| 549 | u8 block_id = 1; | ||
| 550 | u8 package_index = 0; | ||
| 551 | std::size_t tries = 0; | ||
| 552 | std::size_t current_position = 0; | ||
| 553 | |||
| 554 | LOG_INFO(Input, "Writing Mifare data"); | ||
| 555 | |||
| 556 | // Send data request. Nfc buffer size is 31, Send the data in smaller packages | ||
| 557 | while (current_position < buffer.size() && tries++ < timeout_limit) { | ||
| 558 | const std::size_t next_position = | ||
| 559 | std::min(current_position + sizeof(NFCRequestState::raw_data), buffer.size()); | ||
| 560 | const std::size_t block_size = next_position - current_position; | ||
| 561 | const bool is_last_packet = block_size < sizeof(NFCRequestState::raw_data); | ||
| 562 | |||
| 563 | SendReadDataMifareRequest(output, block_id, is_last_packet, | ||
| 564 | buffer.subspan(current_position, block_size)); | ||
| 565 | |||
| 566 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); | ||
| 567 | |||
| 568 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::TagLost) { | ||
| 569 | return DriverResult::ErrorReadingData; | ||
| 570 | } | ||
| 571 | |||
| 572 | // Increase position when data is confirmed by the joycon | ||
| 573 | if (output.mcu_report == MCUReport::NFCState && | ||
| 574 | (output.mcu_data[1] << 8) + output.mcu_data[0] == 0x0500 && | ||
| 575 | output.mcu_data[3] == block_id) { | ||
| 576 | block_id++; | ||
| 577 | current_position = next_position; | ||
| 578 | } | ||
| 579 | } | ||
| 580 | |||
| 581 | if (result != DriverResult::Success) { | ||
| 582 | return result; | ||
| 583 | } | ||
| 584 | |||
| 585 | // Wait for reply and ignore the output data | ||
| 586 | while (tries++ < timeout_limit) { | ||
| 587 | result = SendNextPackageRequest(output, package_index); | ||
| 588 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); | ||
| 589 | |||
| 590 | if (result != DriverResult::Success) { | ||
| 591 | return result; | ||
| 592 | } | ||
| 593 | |||
| 594 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::TagLost) { | ||
| 595 | return DriverResult::ErrorReadingData; | ||
| 596 | } | ||
| 597 | |||
| 598 | if (output.mcu_report == MCUReport::NFCState && output.mcu_data[1] == 0x10) { | ||
| 599 | package_index++; | ||
| 600 | continue; | ||
| 601 | } | ||
| 602 | |||
| 603 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::MifareDone) { | ||
| 604 | LOG_INFO(Input, "Finished writing mifare"); | ||
| 605 | break; | ||
| 606 | } | ||
| 607 | } | ||
| 608 | |||
| 609 | return result; | ||
| 610 | } | ||
| 611 | |||
| 344 | DriverResult NfcProtocol::SendStartPollingRequest(MCUCommandResponse& output, | 612 | DriverResult NfcProtocol::SendStartPollingRequest(MCUCommandResponse& output, |
| 345 | bool is_second_attempt) { | 613 | bool is_second_attempt) { |
| 346 | NFCRequestState request{ | 614 | NFCRequestState request{ |
| @@ -477,6 +745,28 @@ DriverResult NfcProtocol::SendWriteDataAmiiboRequest(MCUCommandResponse& output, | |||
| 477 | output); | 745 | output); |
| 478 | } | 746 | } |
| 479 | 747 | ||
| 748 | DriverResult NfcProtocol::SendReadDataMifareRequest(MCUCommandResponse& output, u8 block_id, | ||
| 749 | bool is_last_packet, std::span<const u8> data) { | ||
| 750 | const auto data_size = std::min(data.size(), sizeof(NFCRequestState::raw_data)); | ||
| 751 | NFCRequestState request{ | ||
| 752 | .command_argument = NFCCommand::Mifare, | ||
| 753 | .block_id = block_id, | ||
| 754 | .packet_id = {}, | ||
| 755 | .packet_flag = | ||
| 756 | is_last_packet ? MCUPacketFlag::LastCommandPacket : MCUPacketFlag::MorePacketsRemaining, | ||
| 757 | .data_length = static_cast<u8>(data_size), | ||
| 758 | .raw_data = {}, | ||
| 759 | .crc = {}, | ||
| 760 | }; | ||
| 761 | memcpy(request.raw_data.data(), data.data(), data_size); | ||
| 762 | |||
| 763 | std::array<u8, sizeof(NFCRequestState)> request_data{}; | ||
| 764 | memcpy(request_data.data(), &request, sizeof(NFCRequestState)); | ||
| 765 | request_data[36] = CalculateMCU_CRC8(request_data.data(), 36); | ||
| 766 | return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, MCUSubCommand::ReadDeviceMode, request_data, | ||
| 767 | output); | ||
| 768 | } | ||
| 769 | |||
| 480 | std::vector<u8> NfcProtocol::SerializeWritePackage(const NFCWritePackage& package) const { | 770 | std::vector<u8> NfcProtocol::SerializeWritePackage(const NFCWritePackage& package) const { |
| 481 | const std::size_t header_size = | 771 | const std::size_t header_size = |
| 482 | sizeof(NFCWriteCommandData) + sizeof(NFCWritePackage::number_of_chunks); | 772 | sizeof(NFCWriteCommandData) + sizeof(NFCWritePackage::number_of_chunks); |
| @@ -498,6 +788,48 @@ std::vector<u8> NfcProtocol::SerializeWritePackage(const NFCWritePackage& packag | |||
| 498 | return serialized_data; | 788 | return serialized_data; |
| 499 | } | 789 | } |
| 500 | 790 | ||
| 791 | std::vector<u8> NfcProtocol::SerializeMifareReadPackage(const MifareReadPackage& package) const { | ||
| 792 | const std::size_t header_size = sizeof(MifareCommandData); | ||
| 793 | std::vector<u8> serialized_data(header_size); | ||
| 794 | std::size_t start_index = 0; | ||
| 795 | |||
| 796 | memcpy(serialized_data.data(), &package, header_size); | ||
| 797 | start_index += header_size; | ||
| 798 | |||
| 799 | for (const auto& data_chunk : package.data_chunks) { | ||
| 800 | const std::size_t chunk_size = sizeof(MifareReadChunk); | ||
| 801 | if (data_chunk.command == MifareCmd::None) { | ||
| 802 | continue; | ||
| 803 | } | ||
| 804 | serialized_data.resize(start_index + chunk_size); | ||
| 805 | memcpy(serialized_data.data() + start_index, &data_chunk, chunk_size); | ||
| 806 | start_index += chunk_size; | ||
| 807 | } | ||
| 808 | |||
| 809 | return serialized_data; | ||
| 810 | } | ||
| 811 | |||
| 812 | std::vector<u8> NfcProtocol::SerializeMifareWritePackage(const MifareWritePackage& package) const { | ||
| 813 | const std::size_t header_size = sizeof(MifareCommandData); | ||
| 814 | std::vector<u8> serialized_data(header_size); | ||
| 815 | std::size_t start_index = 0; | ||
| 816 | |||
| 817 | memcpy(serialized_data.data(), &package, header_size); | ||
| 818 | start_index += header_size; | ||
| 819 | |||
| 820 | for (const auto& data_chunk : package.data_chunks) { | ||
| 821 | const std::size_t chunk_size = sizeof(MifareWriteChunk); | ||
| 822 | if (data_chunk.command == MifareCmd::None) { | ||
| 823 | continue; | ||
| 824 | } | ||
| 825 | serialized_data.resize(start_index + chunk_size); | ||
| 826 | memcpy(serialized_data.data() + start_index, &data_chunk, chunk_size); | ||
| 827 | start_index += chunk_size; | ||
| 828 | } | ||
| 829 | |||
| 830 | return serialized_data; | ||
| 831 | } | ||
| 832 | |||
| 501 | NFCWritePackage NfcProtocol::MakeAmiiboWritePackage(const TagUUID& tag_uuid, | 833 | NFCWritePackage NfcProtocol::MakeAmiiboWritePackage(const TagUUID& tag_uuid, |
| 502 | std::span<const u8> data) const { | 834 | std::span<const u8> data) const { |
| 503 | return { | 835 | return { |
| @@ -527,6 +859,46 @@ NFCWritePackage NfcProtocol::MakeAmiiboWritePackage(const TagUUID& tag_uuid, | |||
| 527 | }; | 859 | }; |
| 528 | } | 860 | } |
| 529 | 861 | ||
| 862 | MifareReadPackage NfcProtocol::MakeMifareReadPackage( | ||
| 863 | const MifareUUID& tag_uuid, std::span<const MifareReadChunk> read_request) const { | ||
| 864 | MifareReadPackage package{ | ||
| 865 | .command_data{ | ||
| 866 | .unknown1 = 0xd0, | ||
| 867 | .unknown2 = 0x07, | ||
| 868 | .number_of_short_bytes = static_cast<u8>( | ||
| 869 | ((read_request.size() * sizeof(MifareReadChunk)) + sizeof(MifareUUID)) / 2), | ||
| 870 | .uid = tag_uuid, | ||
| 871 | }, | ||
| 872 | .data_chunks = {}, | ||
| 873 | }; | ||
| 874 | |||
| 875 | for (std::size_t i = 0; i < read_request.size() && i < package.data_chunks.size(); ++i) { | ||
| 876 | package.data_chunks[i] = read_request[i]; | ||
| 877 | } | ||
| 878 | |||
| 879 | return package; | ||
| 880 | } | ||
| 881 | |||
| 882 | MifareWritePackage NfcProtocol::MakeMifareWritePackage( | ||
| 883 | const MifareUUID& tag_uuid, std::span<const MifareWriteChunk> read_request) const { | ||
| 884 | MifareWritePackage package{ | ||
| 885 | .command_data{ | ||
| 886 | .unknown1 = 0xd0, | ||
| 887 | .unknown2 = 0x07, | ||
| 888 | .number_of_short_bytes = static_cast<u8>( | ||
| 889 | ((read_request.size() * sizeof(MifareReadChunk)) + sizeof(MifareUUID) + 2) / 2), | ||
| 890 | .uid = tag_uuid, | ||
| 891 | }, | ||
| 892 | .data_chunks = {}, | ||
| 893 | }; | ||
| 894 | |||
| 895 | for (std::size_t i = 0; i < read_request.size() && i < package.data_chunks.size(); ++i) { | ||
| 896 | package.data_chunks[i] = read_request[i]; | ||
| 897 | } | ||
| 898 | |||
| 899 | return package; | ||
| 900 | } | ||
| 901 | |||
| 530 | NFCDataChunk NfcProtocol::MakeAmiiboChunk(u8 page, u8 size, std::span<const u8> data) const { | 902 | NFCDataChunk NfcProtocol::MakeAmiiboChunk(u8 page, u8 size, std::span<const u8> data) const { |
| 531 | constexpr u8 NFC_PAGE_SIZE = 4; | 903 | constexpr u8 NFC_PAGE_SIZE = 4; |
| 532 | 904 | ||
| @@ -606,4 +978,8 @@ bool NfcProtocol::IsEnabled() const { | |||
| 606 | return is_enabled; | 978 | return is_enabled; |
| 607 | } | 979 | } |
| 608 | 980 | ||
| 981 | bool NfcProtocol::IsPolling() const { | ||
| 982 | return is_polling; | ||
| 983 | } | ||
| 984 | |||
| 609 | } // namespace InputCommon::Joycon | 985 | } // namespace InputCommon::Joycon |