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 | |
| 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')
| -rw-r--r-- | src/input_common/helpers/joycon_driver.cpp | 118 | ||||
| -rw-r--r-- | src/input_common/helpers/joycon_driver.h | 6 | ||||
| -rw-r--r-- | src/input_common/helpers/joycon_protocol/joycon_types.h | 59 | ||||
| -rw-r--r-- | src/input_common/helpers/joycon_protocol/nfc.cpp | 390 | ||||
| -rw-r--r-- | src/input_common/helpers/joycon_protocol/nfc.h | 34 | ||||
| -rw-r--r-- | src/input_common/helpers/joycon_protocol/poller.cpp | 4 | ||||
| -rw-r--r-- | src/input_common/helpers/joycon_protocol/poller.h | 4 |
7 files changed, 588 insertions, 27 deletions
diff --git a/src/input_common/helpers/joycon_driver.cpp b/src/input_common/helpers/joycon_driver.cpp index 95106f16d..2c8c66951 100644 --- a/src/input_common/helpers/joycon_driver.cpp +++ b/src/input_common/helpers/joycon_driver.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "common/logging/log.h" | 4 | #include "common/logging/log.h" |
| 5 | #include "common/scope_exit.h" | ||
| 5 | #include "common/swap.h" | 6 | #include "common/swap.h" |
| 6 | #include "common/thread.h" | 7 | #include "common/thread.h" |
| 7 | #include "input_common/helpers/joycon_driver.h" | 8 | #include "input_common/helpers/joycon_driver.h" |
| @@ -112,7 +113,7 @@ DriverResult JoyconDriver::InitializeDevice() { | |||
| 112 | joycon_poller = std::make_unique<JoyconPoller>(device_type, left_stick_calibration, | 113 | joycon_poller = std::make_unique<JoyconPoller>(device_type, left_stick_calibration, |
| 113 | right_stick_calibration, motion_calibration); | 114 | right_stick_calibration, motion_calibration); |
| 114 | 115 | ||
| 115 | // Start pooling for data | 116 | // Start polling for data |
| 116 | is_connected = true; | 117 | is_connected = true; |
| 117 | if (!input_thread_running) { | 118 | if (!input_thread_running) { |
| 118 | input_thread = | 119 | input_thread = |
| @@ -208,7 +209,7 @@ void JoyconDriver::OnNewData(std::span<u8> buffer) { | |||
| 208 | joycon_poller->UpdateCamera(irs_protocol->GetImage(), irs_protocol->GetIrsFormat()); | 209 | joycon_poller->UpdateCamera(irs_protocol->GetImage(), irs_protocol->GetIrsFormat()); |
| 209 | } | 210 | } |
| 210 | 211 | ||
| 211 | if (nfc_protocol->IsEnabled()) { | 212 | if (nfc_protocol->IsPolling()) { |
| 212 | if (amiibo_detected) { | 213 | if (amiibo_detected) { |
| 213 | if (!nfc_protocol->HasAmiibo()) { | 214 | if (!nfc_protocol->HasAmiibo()) { |
| 214 | joycon_poller->UpdateAmiibo({}); | 215 | joycon_poller->UpdateAmiibo({}); |
| @@ -218,10 +219,10 @@ void JoyconDriver::OnNewData(std::span<u8> buffer) { | |||
| 218 | } | 219 | } |
| 219 | 220 | ||
| 220 | if (!amiibo_detected) { | 221 | if (!amiibo_detected) { |
| 221 | std::vector<u8> data(0x21C); | 222 | Joycon::TagInfo tag_info; |
| 222 | const auto result = nfc_protocol->ScanAmiibo(data); | 223 | const auto result = nfc_protocol->GetTagInfo(tag_info); |
| 223 | if (result == DriverResult::Success) { | 224 | if (result == DriverResult::Success) { |
| 224 | joycon_poller->UpdateAmiibo(data); | 225 | joycon_poller->UpdateAmiibo(tag_info); |
| 225 | amiibo_detected = true; | 226 | amiibo_detected = true; |
| 226 | } | 227 | } |
| 227 | } | 228 | } |
| @@ -247,6 +248,7 @@ void JoyconDriver::OnNewData(std::span<u8> buffer) { | |||
| 247 | } | 248 | } |
| 248 | 249 | ||
| 249 | DriverResult JoyconDriver::SetPollingMode() { | 250 | DriverResult JoyconDriver::SetPollingMode() { |
| 251 | SCOPE_EXIT({ disable_input_thread = false; }); | ||
| 250 | disable_input_thread = true; | 252 | disable_input_thread = true; |
| 251 | 253 | ||
| 252 | rumble_protocol->EnableRumble(vibration_enabled && supported_features.vibration); | 254 | rumble_protocol->EnableRumble(vibration_enabled && supported_features.vibration); |
| @@ -276,7 +278,6 @@ DriverResult JoyconDriver::SetPollingMode() { | |||
| 276 | if (irs_enabled && supported_features.irs) { | 278 | if (irs_enabled && supported_features.irs) { |
| 277 | auto result = irs_protocol->EnableIrs(); | 279 | auto result = irs_protocol->EnableIrs(); |
| 278 | if (result == DriverResult::Success) { | 280 | if (result == DriverResult::Success) { |
| 279 | disable_input_thread = false; | ||
| 280 | return result; | 281 | return result; |
| 281 | } | 282 | } |
| 282 | irs_protocol->DisableIrs(); | 283 | irs_protocol->DisableIrs(); |
| @@ -286,10 +287,6 @@ DriverResult JoyconDriver::SetPollingMode() { | |||
| 286 | if (nfc_enabled && supported_features.nfc) { | 287 | if (nfc_enabled && supported_features.nfc) { |
| 287 | auto result = nfc_protocol->EnableNfc(); | 288 | auto result = nfc_protocol->EnableNfc(); |
| 288 | if (result == DriverResult::Success) { | 289 | if (result == DriverResult::Success) { |
| 289 | result = nfc_protocol->StartNFCPollingMode(); | ||
| 290 | } | ||
| 291 | if (result == DriverResult::Success) { | ||
| 292 | disable_input_thread = false; | ||
| 293 | return result; | 290 | return result; |
| 294 | } | 291 | } |
| 295 | nfc_protocol->DisableNfc(); | 292 | nfc_protocol->DisableNfc(); |
| @@ -303,7 +300,6 @@ DriverResult JoyconDriver::SetPollingMode() { | |||
| 303 | } | 300 | } |
| 304 | if (result == DriverResult::Success) { | 301 | if (result == DriverResult::Success) { |
| 305 | ring_connected = true; | 302 | ring_connected = true; |
| 306 | disable_input_thread = false; | ||
| 307 | return result; | 303 | return result; |
| 308 | } | 304 | } |
| 309 | ring_connected = false; | 305 | ring_connected = false; |
| @@ -314,7 +310,6 @@ DriverResult JoyconDriver::SetPollingMode() { | |||
| 314 | if (passive_enabled && supported_features.passive) { | 310 | if (passive_enabled && supported_features.passive) { |
| 315 | const auto result = generic_protocol->EnablePassiveMode(); | 311 | const auto result = generic_protocol->EnablePassiveMode(); |
| 316 | if (result == DriverResult::Success) { | 312 | if (result == DriverResult::Success) { |
| 317 | disable_input_thread = false; | ||
| 318 | return result; | 313 | return result; |
| 319 | } | 314 | } |
| 320 | LOG_ERROR(Input, "Error enabling passive mode"); | 315 | LOG_ERROR(Input, "Error enabling passive mode"); |
| @@ -328,7 +323,6 @@ DriverResult JoyconDriver::SetPollingMode() { | |||
| 328 | // Switch calls this function after enabling active mode | 323 | // Switch calls this function after enabling active mode |
| 329 | generic_protocol->TriggersElapsed(); | 324 | generic_protocol->TriggersElapsed(); |
| 330 | 325 | ||
| 331 | disable_input_thread = false; | ||
| 332 | return result; | 326 | return result; |
| 333 | } | 327 | } |
| 334 | 328 | ||
| @@ -492,9 +486,63 @@ DriverResult JoyconDriver::SetRingConMode() { | |||
| 492 | return result; | 486 | return result; |
| 493 | } | 487 | } |
| 494 | 488 | ||
| 495 | DriverResult JoyconDriver::WriteNfcData(std::span<const u8> data) { | 489 | DriverResult JoyconDriver::StartNfcPolling() { |
| 496 | std::scoped_lock lock{mutex}; | 490 | std::scoped_lock lock{mutex}; |
| 491 | |||
| 492 | if (!supported_features.nfc) { | ||
| 493 | return DriverResult::NotSupported; | ||
| 494 | } | ||
| 495 | if (!nfc_protocol->IsEnabled()) { | ||
| 496 | return DriverResult::Disabled; | ||
| 497 | } | ||
| 498 | |||
| 499 | disable_input_thread = true; | ||
| 500 | const auto result = nfc_protocol->StartNFCPollingMode(); | ||
| 501 | disable_input_thread = false; | ||
| 502 | |||
| 503 | return result; | ||
| 504 | } | ||
| 505 | |||
| 506 | DriverResult JoyconDriver::StopNfcPolling() { | ||
| 507 | std::scoped_lock lock{mutex}; | ||
| 508 | |||
| 509 | if (!supported_features.nfc) { | ||
| 510 | return DriverResult::NotSupported; | ||
| 511 | } | ||
| 512 | if (!nfc_protocol->IsEnabled()) { | ||
| 513 | return DriverResult::Disabled; | ||
| 514 | } | ||
| 515 | |||
| 516 | disable_input_thread = true; | ||
| 517 | const auto result = nfc_protocol->StopNFCPollingMode(); | ||
| 518 | disable_input_thread = false; | ||
| 519 | |||
| 520 | return result; | ||
| 521 | } | ||
| 522 | |||
| 523 | DriverResult JoyconDriver::ReadAmiiboData(std::vector<u8>& out_data) { | ||
| 524 | std::scoped_lock lock{mutex}; | ||
| 525 | |||
| 526 | if (!supported_features.nfc) { | ||
| 527 | return DriverResult::NotSupported; | ||
| 528 | } | ||
| 529 | if (!nfc_protocol->IsEnabled()) { | ||
| 530 | return DriverResult::Disabled; | ||
| 531 | } | ||
| 532 | if (!amiibo_detected) { | ||
| 533 | return DriverResult::ErrorWritingData; | ||
| 534 | } | ||
| 535 | |||
| 536 | out_data.resize(0x21C); | ||
| 497 | disable_input_thread = true; | 537 | disable_input_thread = true; |
| 538 | const auto result = nfc_protocol->ReadAmiibo(out_data); | ||
| 539 | disable_input_thread = false; | ||
| 540 | |||
| 541 | return result; | ||
| 542 | } | ||
| 543 | |||
| 544 | DriverResult JoyconDriver::WriteNfcData(std::span<const u8> data) { | ||
| 545 | std::scoped_lock lock{mutex}; | ||
| 498 | 546 | ||
| 499 | if (!supported_features.nfc) { | 547 | if (!supported_features.nfc) { |
| 500 | return DriverResult::NotSupported; | 548 | return DriverResult::NotSupported; |
| @@ -506,9 +554,51 @@ DriverResult JoyconDriver::WriteNfcData(std::span<const u8> data) { | |||
| 506 | return DriverResult::ErrorWritingData; | 554 | return DriverResult::ErrorWritingData; |
| 507 | } | 555 | } |
| 508 | 556 | ||
| 557 | disable_input_thread = true; | ||
| 509 | const auto result = nfc_protocol->WriteAmiibo(data); | 558 | const auto result = nfc_protocol->WriteAmiibo(data); |
| 559 | disable_input_thread = false; | ||
| 510 | 560 | ||
| 561 | return result; | ||
| 562 | } | ||
| 563 | |||
| 564 | DriverResult JoyconDriver::ReadMifareData(std::span<const MifareReadChunk> data, | ||
| 565 | std::span<MifareReadData> out_data) { | ||
| 566 | std::scoped_lock lock{mutex}; | ||
| 567 | |||
| 568 | if (!supported_features.nfc) { | ||
| 569 | return DriverResult::NotSupported; | ||
| 570 | } | ||
| 571 | if (!nfc_protocol->IsEnabled()) { | ||
| 572 | return DriverResult::Disabled; | ||
| 573 | } | ||
| 574 | if (!amiibo_detected) { | ||
| 575 | return DriverResult::ErrorWritingData; | ||
| 576 | } | ||
| 577 | |||
| 578 | disable_input_thread = true; | ||
| 579 | const auto result = nfc_protocol->ReadMifare(data, out_data); | ||
| 580 | disable_input_thread = false; | ||
| 581 | |||
| 582 | return result; | ||
| 583 | } | ||
| 584 | |||
| 585 | DriverResult JoyconDriver::WriteMifareData(std::span<const MifareWriteChunk> data) { | ||
| 586 | std::scoped_lock lock{mutex}; | ||
| 587 | |||
| 588 | if (!supported_features.nfc) { | ||
| 589 | return DriverResult::NotSupported; | ||
| 590 | } | ||
| 591 | if (!nfc_protocol->IsEnabled()) { | ||
| 592 | return DriverResult::Disabled; | ||
| 593 | } | ||
| 594 | if (!amiibo_detected) { | ||
| 595 | return DriverResult::ErrorWritingData; | ||
| 596 | } | ||
| 597 | |||
| 598 | disable_input_thread = true; | ||
| 599 | const auto result = nfc_protocol->WriteMifare(data); | ||
| 511 | disable_input_thread = false; | 600 | disable_input_thread = false; |
| 601 | |||
| 512 | return result; | 602 | return result; |
| 513 | } | 603 | } |
| 514 | 604 | ||
diff --git a/src/input_common/helpers/joycon_driver.h b/src/input_common/helpers/joycon_driver.h index e9b2fccbb..bc7025a21 100644 --- a/src/input_common/helpers/joycon_driver.h +++ b/src/input_common/helpers/joycon_driver.h | |||
| @@ -49,7 +49,13 @@ public: | |||
| 49 | DriverResult SetIrMode(); | 49 | DriverResult SetIrMode(); |
| 50 | DriverResult SetNfcMode(); | 50 | DriverResult SetNfcMode(); |
| 51 | DriverResult SetRingConMode(); | 51 | DriverResult SetRingConMode(); |
| 52 | DriverResult StartNfcPolling(); | ||
| 53 | DriverResult StopNfcPolling(); | ||
| 54 | DriverResult ReadAmiiboData(std::vector<u8>& out_data); | ||
| 52 | DriverResult WriteNfcData(std::span<const u8> data); | 55 | DriverResult WriteNfcData(std::span<const u8> data); |
| 56 | DriverResult ReadMifareData(std::span<const MifareReadChunk> request, | ||
| 57 | std::span<MifareReadData> out_data); | ||
| 58 | DriverResult WriteMifareData(std::span<const MifareWriteChunk> request); | ||
| 53 | 59 | ||
| 54 | void SetCallbacks(const JoyconCallbacks& callbacks); | 60 | void SetCallbacks(const JoyconCallbacks& callbacks); |
| 55 | 61 | ||
diff --git a/src/input_common/helpers/joycon_protocol/joycon_types.h b/src/input_common/helpers/joycon_protocol/joycon_types.h index 5007b0e18..e0e431156 100644 --- a/src/input_common/helpers/joycon_protocol/joycon_types.h +++ b/src/input_common/helpers/joycon_protocol/joycon_types.h | |||
| @@ -24,6 +24,7 @@ constexpr std::array<u8, 8> DefaultVibrationBuffer{0x0, 0x1, 0x40, 0x40, 0x0, 0x | |||
| 24 | using MacAddress = std::array<u8, 6>; | 24 | using MacAddress = std::array<u8, 6>; |
| 25 | using SerialNumber = std::array<u8, 15>; | 25 | using SerialNumber = std::array<u8, 15>; |
| 26 | using TagUUID = std::array<u8, 7>; | 26 | using TagUUID = std::array<u8, 7>; |
| 27 | using MifareUUID = std::array<u8, 4>; | ||
| 27 | 28 | ||
| 28 | enum class ControllerType : u8 { | 29 | enum class ControllerType : u8 { |
| 29 | None = 0x00, | 30 | None = 0x00, |
| @@ -307,6 +308,19 @@ enum class NFCStatus : u8 { | |||
| 307 | WriteDone = 0x05, | 308 | WriteDone = 0x05, |
| 308 | TagLost = 0x07, | 309 | TagLost = 0x07, |
| 309 | WriteReady = 0x09, | 310 | WriteReady = 0x09, |
| 311 | MifareDone = 0x10, | ||
| 312 | }; | ||
| 313 | |||
| 314 | enum class MifareCmd : u8 { | ||
| 315 | None = 0x00, | ||
| 316 | Read = 0x30, | ||
| 317 | AuthA = 0x60, | ||
| 318 | AuthB = 0x61, | ||
| 319 | Write = 0xA0, | ||
| 320 | Transfer = 0xB0, | ||
| 321 | Decrement = 0xC0, | ||
| 322 | Increment = 0xC1, | ||
| 323 | Store = 0xC2 | ||
| 310 | }; | 324 | }; |
| 311 | 325 | ||
| 312 | enum class IrsMode : u8 { | 326 | enum class IrsMode : u8 { |
| @@ -592,6 +606,14 @@ struct NFCWriteCommandData { | |||
| 592 | static_assert(sizeof(NFCWriteCommandData) == 0x15, "NFCWriteCommandData is an invalid size"); | 606 | static_assert(sizeof(NFCWriteCommandData) == 0x15, "NFCWriteCommandData is an invalid size"); |
| 593 | #pragma pack(pop) | 607 | #pragma pack(pop) |
| 594 | 608 | ||
| 609 | struct MifareCommandData { | ||
| 610 | u8 unknown1; | ||
| 611 | u8 unknown2; | ||
| 612 | u8 number_of_short_bytes; | ||
| 613 | MifareUUID uid; | ||
| 614 | }; | ||
| 615 | static_assert(sizeof(MifareCommandData) == 0x7, "MifareCommandData is an invalid size"); | ||
| 616 | |||
| 595 | struct NFCPollingCommandData { | 617 | struct NFCPollingCommandData { |
| 596 | u8 enable_mifare; | 618 | u8 enable_mifare; |
| 597 | u8 unknown_1; | 619 | u8 unknown_1; |
| @@ -629,6 +651,41 @@ struct NFCWritePackage { | |||
| 629 | std::array<NFCDataChunk, 4> data_chunks; | 651 | std::array<NFCDataChunk, 4> data_chunks; |
| 630 | }; | 652 | }; |
| 631 | 653 | ||
| 654 | struct MifareReadChunk { | ||
| 655 | MifareCmd command; | ||
| 656 | std::array<u8, 0x6> sector_key; | ||
| 657 | u8 sector; | ||
| 658 | }; | ||
| 659 | |||
| 660 | struct MifareWriteChunk { | ||
| 661 | MifareCmd command; | ||
| 662 | std::array<u8, 0x6> sector_key; | ||
| 663 | u8 sector; | ||
| 664 | std::array<u8, 0x10> data; | ||
| 665 | }; | ||
| 666 | |||
| 667 | struct MifareReadData { | ||
| 668 | u8 sector; | ||
| 669 | std::array<u8, 0x10> data; | ||
| 670 | }; | ||
| 671 | |||
| 672 | struct MifareReadPackage { | ||
| 673 | MifareCommandData command_data; | ||
| 674 | std::array<MifareReadChunk, 0x10> data_chunks; | ||
| 675 | }; | ||
| 676 | |||
| 677 | struct MifareWritePackage { | ||
| 678 | MifareCommandData command_data; | ||
| 679 | std::array<MifareWriteChunk, 0x10> data_chunks; | ||
| 680 | }; | ||
| 681 | |||
| 682 | struct TagInfo { | ||
| 683 | u8 uuid_length; | ||
| 684 | u8 protocol; | ||
| 685 | u8 tag_type; | ||
| 686 | std::array<u8, 10> uuid; | ||
| 687 | }; | ||
| 688 | |||
| 632 | struct IrsConfigure { | 689 | struct IrsConfigure { |
| 633 | MCUCommand command; | 690 | MCUCommand command; |
| 634 | MCUSubCommand sub_command; | 691 | MCUSubCommand sub_command; |
| @@ -744,7 +801,7 @@ struct JoyconCallbacks { | |||
| 744 | std::function<void(int, f32)> on_stick_data; | 801 | std::function<void(int, f32)> on_stick_data; |
| 745 | std::function<void(int, const MotionData&)> on_motion_data; | 802 | std::function<void(int, const MotionData&)> on_motion_data; |
| 746 | std::function<void(f32)> on_ring_data; | 803 | std::function<void(f32)> on_ring_data; |
| 747 | std::function<void(const std::vector<u8>&)> on_amiibo_data; | 804 | std::function<void(const Joycon::TagInfo&)> on_amiibo_data; |
| 748 | std::function<void(const std::vector<u8>&, IrsResolution)> on_camera_data; | 805 | std::function<void(const std::vector<u8>&, IrsResolution)> on_camera_data; |
| 749 | }; | 806 | }; |
| 750 | 807 | ||
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 |
diff --git a/src/input_common/helpers/joycon_protocol/nfc.h b/src/input_common/helpers/joycon_protocol/nfc.h index eb58c427d..0be95e40e 100644 --- a/src/input_common/helpers/joycon_protocol/nfc.h +++ b/src/input_common/helpers/joycon_protocol/nfc.h | |||
| @@ -25,14 +25,25 @@ public: | |||
| 25 | 25 | ||
| 26 | DriverResult StartNFCPollingMode(); | 26 | DriverResult StartNFCPollingMode(); |
| 27 | 27 | ||
| 28 | DriverResult ScanAmiibo(std::vector<u8>& data); | 28 | DriverResult StopNFCPollingMode(); |
| 29 | |||
| 30 | DriverResult GetTagInfo(Joycon::TagInfo& tag_info); | ||
| 31 | |||
| 32 | DriverResult ReadAmiibo(std::vector<u8>& data); | ||
| 29 | 33 | ||
| 30 | DriverResult WriteAmiibo(std::span<const u8> data); | 34 | DriverResult WriteAmiibo(std::span<const u8> data); |
| 31 | 35 | ||
| 36 | DriverResult ReadMifare(std::span<const MifareReadChunk> read_request, | ||
| 37 | std::span<MifareReadData> out_data); | ||
| 38 | |||
| 39 | DriverResult WriteMifare(std::span<const MifareWriteChunk> write_request); | ||
| 40 | |||
| 32 | bool HasAmiibo(); | 41 | bool HasAmiibo(); |
| 33 | 42 | ||
| 34 | bool IsEnabled() const; | 43 | bool IsEnabled() const; |
| 35 | 44 | ||
| 45 | bool IsPolling() const; | ||
| 46 | |||
| 36 | private: | 47 | private: |
| 37 | // Number of times the function will be delayed until it outputs valid data | 48 | // Number of times the function will be delayed until it outputs valid data |
| 38 | static constexpr std::size_t AMIIBO_UPDATE_DELAY = 15; | 49 | static constexpr std::size_t AMIIBO_UPDATE_DELAY = 15; |
| @@ -51,6 +62,13 @@ private: | |||
| 51 | 62 | ||
| 52 | DriverResult WriteAmiiboData(const TagUUID& tag_uuid, std::span<const u8> data); | 63 | DriverResult WriteAmiiboData(const TagUUID& tag_uuid, std::span<const u8> data); |
| 53 | 64 | ||
| 65 | DriverResult GetMifareData(const MifareUUID& tag_uuid, | ||
| 66 | std::span<const MifareReadChunk> read_request, | ||
| 67 | std::span<MifareReadData> out_data); | ||
| 68 | |||
| 69 | DriverResult WriteMifareData(const MifareUUID& tag_uuid, | ||
| 70 | std::span<const MifareWriteChunk> write_request); | ||
| 71 | |||
| 54 | DriverResult SendStartPollingRequest(MCUCommandResponse& output, | 72 | DriverResult SendStartPollingRequest(MCUCommandResponse& output, |
| 55 | bool is_second_attempt = false); | 73 | bool is_second_attempt = false); |
| 56 | 74 | ||
| @@ -65,17 +83,31 @@ private: | |||
| 65 | DriverResult SendWriteDataAmiiboRequest(MCUCommandResponse& output, u8 block_id, | 83 | DriverResult SendWriteDataAmiiboRequest(MCUCommandResponse& output, u8 block_id, |
| 66 | bool is_last_packet, std::span<const u8> data); | 84 | bool is_last_packet, std::span<const u8> data); |
| 67 | 85 | ||
| 86 | DriverResult SendReadDataMifareRequest(MCUCommandResponse& output, u8 block_id, | ||
| 87 | bool is_last_packet, std::span<const u8> data); | ||
| 88 | |||
| 68 | std::vector<u8> SerializeWritePackage(const NFCWritePackage& package) const; | 89 | std::vector<u8> SerializeWritePackage(const NFCWritePackage& package) const; |
| 69 | 90 | ||
| 91 | std::vector<u8> SerializeMifareReadPackage(const MifareReadPackage& package) const; | ||
| 92 | |||
| 93 | std::vector<u8> SerializeMifareWritePackage(const MifareWritePackage& package) const; | ||
| 94 | |||
| 70 | NFCWritePackage MakeAmiiboWritePackage(const TagUUID& tag_uuid, std::span<const u8> data) const; | 95 | NFCWritePackage MakeAmiiboWritePackage(const TagUUID& tag_uuid, std::span<const u8> data) const; |
| 71 | 96 | ||
| 72 | NFCDataChunk MakeAmiiboChunk(u8 page, u8 size, std::span<const u8> data) const; | 97 | NFCDataChunk MakeAmiiboChunk(u8 page, u8 size, std::span<const u8> data) const; |
| 73 | 98 | ||
| 99 | MifareReadPackage MakeMifareReadPackage(const MifareUUID& tag_uuid, | ||
| 100 | std::span<const MifareReadChunk> read_request) const; | ||
| 101 | |||
| 102 | MifareWritePackage MakeMifareWritePackage(const MifareUUID& tag_uuid, | ||
| 103 | std::span<const MifareWriteChunk> read_request) const; | ||
| 104 | |||
| 74 | NFCReadBlockCommand GetReadBlockCommand(NFCPages pages) const; | 105 | NFCReadBlockCommand GetReadBlockCommand(NFCPages pages) const; |
| 75 | 106 | ||
| 76 | TagUUID GetTagUUID(std::span<const u8> data) const; | 107 | TagUUID GetTagUUID(std::span<const u8> data) const; |
| 77 | 108 | ||
| 78 | bool is_enabled{}; | 109 | bool is_enabled{}; |
| 110 | bool is_polling{}; | ||
| 79 | std::size_t update_counter{}; | 111 | std::size_t update_counter{}; |
| 80 | }; | 112 | }; |
| 81 | 113 | ||
diff --git a/src/input_common/helpers/joycon_protocol/poller.cpp b/src/input_common/helpers/joycon_protocol/poller.cpp index dca797f7a..1aab9e12a 100644 --- a/src/input_common/helpers/joycon_protocol/poller.cpp +++ b/src/input_common/helpers/joycon_protocol/poller.cpp | |||
| @@ -70,8 +70,8 @@ void JoyconPoller::UpdateColor(const Color& color) { | |||
| 70 | callbacks.on_color_data(color); | 70 | callbacks.on_color_data(color); |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | void JoyconPoller::UpdateAmiibo(const std::vector<u8>& amiibo_data) { | 73 | void JoyconPoller::UpdateAmiibo(const Joycon::TagInfo& tag_info) { |
| 74 | callbacks.on_amiibo_data(amiibo_data); | 74 | callbacks.on_amiibo_data(tag_info); |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | void JoyconPoller::UpdateCamera(const std::vector<u8>& camera_data, IrsResolution format) { | 77 | void JoyconPoller::UpdateCamera(const std::vector<u8>& camera_data, IrsResolution format) { |
diff --git a/src/input_common/helpers/joycon_protocol/poller.h b/src/input_common/helpers/joycon_protocol/poller.h index 0fa72c6db..3746abe5d 100644 --- a/src/input_common/helpers/joycon_protocol/poller.h +++ b/src/input_common/helpers/joycon_protocol/poller.h | |||
| @@ -36,8 +36,8 @@ public: | |||
| 36 | 36 | ||
| 37 | void UpdateColor(const Color& color); | 37 | void UpdateColor(const Color& color); |
| 38 | void UpdateRing(s16 value, const RingStatus& ring_status); | 38 | void UpdateRing(s16 value, const RingStatus& ring_status); |
| 39 | void UpdateAmiibo(const std::vector<u8>& amiibo_data); | 39 | void UpdateAmiibo(const Joycon::TagInfo& tag_info); |
| 40 | void UpdateCamera(const std::vector<u8>& amiibo_data, IrsResolution format); | 40 | void UpdateCamera(const std::vector<u8>& camera_data, IrsResolution format); |
| 41 | 41 | ||
| 42 | private: | 42 | private: |
| 43 | void UpdateActiveLeftPadInput(const InputReportActive& input, | 43 | void UpdateActiveLeftPadInput(const InputReportActive& input, |