diff options
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/service/am/applets/applet_cabinet.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/service/nfc/common/device.cpp | 182 | ||||
| -rw-r--r-- | src/core/hle/service/nfc/common/device.h | 10 | ||||
| -rw-r--r-- | src/core/hle/service/nfc/common/device_manager.cpp | 11 | ||||
| -rw-r--r-- | src/core/hle/service/nfc/common/device_manager.h | 2 | ||||
| -rw-r--r-- | src/core/hle/service/nfc/mifare_types.h | 11 | ||||
| -rw-r--r-- | src/core/hle/service/nfc/nfc_interface.cpp | 7 | 
7 files changed, 109 insertions, 116 deletions
| diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/applets/applet_cabinet.cpp index 8b754e9d4..19ed184e8 100644 --- a/src/core/hle/service/am/applets/applet_cabinet.cpp +++ b/src/core/hle/service/am/applets/applet_cabinet.cpp @@ -141,7 +141,7 @@ void Cabinet::DisplayCompleted(bool apply_changes, std::string_view amiibo_name)      applet_output.device_handle = applet_input_common.device_handle;      applet_output.result = CabinetResult::Cancel;      const auto reg_result = nfp_device->GetRegisterInfo(applet_output.register_info); -    const auto tag_result = nfp_device->GetTagInfo(applet_output.tag_info, false); +    const auto tag_result = nfp_device->GetTagInfo(applet_output.tag_info);      nfp_device->Finalize();      if (reg_result.IsSuccess()) { diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index f4b180b06..5bf289818 100644 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp @@ -93,7 +93,8 @@ void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) {      const auto nfc_status = npad_device->GetNfc();      switch (nfc_status.state) {      case Common::Input::NfcState::NewAmiibo: -        LoadNfcTag(nfc_status.data); +        LoadNfcTag(nfc_status.protocol, nfc_status.tag_type, nfc_status.uuid_length, +                   nfc_status.uuid);          break;      case Common::Input::NfcState::AmiiboRemoved:          if (device_state == DeviceState::Initialized || device_state == DeviceState::TagRemoved) { @@ -108,28 +109,46 @@ void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) {      }  } -bool NfcDevice::LoadNfcTag(std::span<const u8> data) { +bool NfcDevice::LoadNfcTag(u8 protocol, u8 tag_type, u8 uuid_length, UniqueSerialNumber uuid) {      if (device_state != DeviceState::SearchingForTag) {          LOG_ERROR(Service_NFC, "Game is not looking for nfc tag, current state {}", device_state);          return false;      } +    if ((protocol & static_cast<u8>(allowed_protocols)) == 0) { +        LOG_ERROR(Service_NFC, "Protocol not supported {}", protocol); +        return false; +    } + +    real_tag_info = { +        .uuid = uuid, +        .uuid_length = uuid_length, +        .protocol = static_cast<NfcProtocol>(protocol), +        .tag_type = static_cast<TagType>(tag_type), +    }; + +    device_state = DeviceState::TagFound; +    deactivate_event->GetReadableEvent().Clear(); +    activate_event->Signal(); +    return true; +} + +bool NfcDevice::LoadAmiiboData() { +    std::vector<u8> data{}; + +    if (!npad_device->ReadAmiiboData(data)) { +        return false; +    } +      if (data.size() < sizeof(NFP::EncryptedNTAG215File)) {          LOG_ERROR(Service_NFC, "Not an amiibo, size={}", data.size());          return false;      } -    mifare_data.resize(data.size()); -    memcpy(mifare_data.data(), data.data(), data.size()); -      memcpy(&tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File));      is_plain_amiibo = NFP::AmiiboCrypto::IsAmiiboValid(tag_data);      is_write_protected = false; -    device_state = DeviceState::TagFound; -    deactivate_event->GetReadableEvent().Clear(); -    activate_event->Signal(); -      // Fallback for plain amiibos      if (is_plain_amiibo) {          LOG_INFO(Service_NFP, "Using plain amiibo"); @@ -147,6 +166,7 @@ bool NfcDevice::LoadNfcTag(std::span<const u8> data) {          return true;      } +    LOG_INFO(Service_NFP, "Using encrypted amiibo");      tag_data = {};      memcpy(&encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File));      return true; @@ -162,7 +182,6 @@ void NfcDevice::CloseNfcTag() {      device_state = DeviceState::TagRemoved;      encrypted_tag_data = {};      tag_data = {}; -    mifare_data = {};      activate_event->GetReadableEvent().Clear();      deactivate_event->Signal();  } @@ -179,8 +198,12 @@ void NfcDevice::Initialize() {      device_state = npad_device->HasNfc() ? DeviceState::Initialized : DeviceState::Unavailable;      encrypted_tag_data = {};      tag_data = {}; -    mifare_data = {}; -    is_initalized = true; + +    if (device_state != DeviceState::Initialized) { +        return; +    } + +    is_initalized = npad_device->AddNfcHandle();  }  void NfcDevice::Finalize() { @@ -190,6 +213,11 @@ void NfcDevice::Finalize() {      if (device_state == DeviceState::SearchingForTag || device_state == DeviceState::TagRemoved) {          StopDetection();      } + +    if (device_state != DeviceState::Unavailable) { +        npad_device->RemoveNfcHandle(); +    } +      device_state = DeviceState::Unavailable;      is_initalized = false;  } @@ -200,10 +228,8 @@ Result NfcDevice::StartDetection(NfcProtocol allowed_protocol) {          return ResultWrongDeviceState;      } -    if (npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, -                                    Common::Input::PollingMode::NFC) != -        Common::Input::DriverResult::Success) { -        LOG_ERROR(Service_NFC, "Nfc not supported"); +    if (!npad_device->StartNfcPolling()) { +        LOG_ERROR(Service_NFC, "Nfc polling not supported");          return ResultNfcDisabled;      } @@ -213,9 +239,6 @@ Result NfcDevice::StartDetection(NfcProtocol allowed_protocol) {  }  Result NfcDevice::StopDetection() { -    npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, -                                Common::Input::PollingMode::Active); -      if (device_state == DeviceState::Initialized) {          return ResultSuccess;      } @@ -225,6 +248,7 @@ Result NfcDevice::StopDetection() {      }      if (device_state == DeviceState::SearchingForTag || device_state == DeviceState::TagRemoved) { +        npad_device->StopNfcPolling();          device_state = DeviceState::Initialized;          return ResultSuccess;      } @@ -233,7 +257,7 @@ Result NfcDevice::StopDetection() {      return ResultWrongDeviceState;  } -Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const { +Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info) const {      if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted) {          LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);          if (device_state == DeviceState::TagRemoved) { @@ -242,41 +266,15 @@ Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const {          return ResultWrongDeviceState;      } -    UniqueSerialNumber uuid{}; -    u8 uuid_length{}; -    NfcProtocol protocol{NfcProtocol::TypeA}; -    TagType tag_type{TagType::Type2}; - -    if (is_mifare) { -        tag_type = TagType::Mifare; -        uuid_length = sizeof(NFP::NtagTagUuid); -        memcpy(uuid.data(), mifare_data.data(), uuid_length); -    } else { -        tag_type = TagType::Type2; -        uuid_length = sizeof(NFP::NtagTagUuid); -        NFP::NtagTagUuid nUuid{ -            .part1 = encrypted_tag_data.uuid.part1, -            .part2 = encrypted_tag_data.uuid.part2, -            .nintendo_id = encrypted_tag_data.uuid.nintendo_id, -        }; -        memcpy(uuid.data(), &nUuid, uuid_length); +    tag_info = real_tag_info; -        // Generate random UUID to bypass amiibo load limits -        if (Settings::values.random_amiibo_id) { -            Common::TinyMT rng{}; -            rng.Initialize(static_cast<u32>(GetCurrentPosixTime())); -            rng.GenerateRandomBytes(uuid.data(), uuid_length); -        } +    // Generate random UUID to bypass amiibo load limits +    if (real_tag_info.tag_type == TagType::Type2 && Settings::values.random_amiibo_id) { +        Common::TinyMT rng{}; +        rng.Initialize(static_cast<u32>(GetCurrentPosixTime())); +        rng.GenerateRandomBytes(tag_info.uuid.data(), tag_info.uuid_length);      } -    // Protocol and tag type may change here -    tag_info = { -        .uuid = uuid, -        .uuid_length = uuid_length, -        .protocol = protocol, -        .tag_type = tag_type, -    }; -      return ResultSuccess;  } @@ -293,7 +291,7 @@ Result NfcDevice::ReadMifare(std::span<const MifareReadBlockParameter> parameter      Result result = ResultSuccess;      TagInfo tag_info{}; -    result = GetTagInfo(tag_info, true); +    result = GetTagInfo(tag_info);      if (result.IsError()) {          return result; @@ -307,6 +305,8 @@ Result NfcDevice::ReadMifare(std::span<const MifareReadBlockParameter> parameter          return ResultInvalidArgument;      } +    Common::Input::MifareRequest request{}; +    Common::Input::MifareRequest out_data{};      const auto unknown = parameters[0].sector_key.unknown;      for (std::size_t i = 0; i < parameters.size(); i++) {          if (unknown != parameters[i].sector_key.unknown) { @@ -315,25 +315,29 @@ Result NfcDevice::ReadMifare(std::span<const MifareReadBlockParameter> parameter      }      for (std::size_t i = 0; i < parameters.size(); i++) { -        result = ReadMifare(parameters[i], read_block_data[i]); -        if (result.IsError()) { -            break; +        if (parameters[i].sector_key.command == MifareCmd::None) { +            continue;          } +        request.data[i].command = static_cast<u8>(parameters[i].sector_key.command); +        request.data[i].sector = parameters[i].sector_number; +        memcpy(request.data[i].key.data(), parameters[i].sector_key.sector_key.data(), +               sizeof(KeyData));      } -    return result; -} - -Result NfcDevice::ReadMifare(const MifareReadBlockParameter& parameter, -                             MifareReadBlockData& read_block_data) const { -    const std::size_t sector_index = parameter.sector_number * sizeof(DataBlock); -    read_block_data.sector_number = parameter.sector_number; -    if (mifare_data.size() < sector_index + sizeof(DataBlock)) { +    if (!npad_device->ReadMifareData(request, out_data)) {          return ResultMifareError288;      } -    // TODO: Use parameter.sector_key to read encrypted data -    memcpy(read_block_data.data.data(), mifare_data.data() + sector_index, sizeof(DataBlock)); +    for (std::size_t i = 0; i < read_block_data.size(); i++) { +        if (static_cast<MifareCmd>(out_data.data[i].command) == MifareCmd::None) { +            continue; +        } + +        read_block_data[i] = { +            .data = out_data.data[i].data, +            .sector_number = out_data.data[i].sector, +        }; +    }      return ResultSuccess;  } @@ -342,7 +346,7 @@ Result NfcDevice::WriteMifare(std::span<const MifareWriteBlockParameter> paramet      Result result = ResultSuccess;      TagInfo tag_info{}; -    result = GetTagInfo(tag_info, true); +    result = GetTagInfo(tag_info);      if (result.IsError()) {          return result; @@ -363,42 +367,25 @@ Result NfcDevice::WriteMifare(std::span<const MifareWriteBlockParameter> paramet          }      } +    Common::Input::MifareRequest request{};      for (std::size_t i = 0; i < parameters.size(); i++) { -        result = WriteMifare(parameters[i]); -        if (result.IsError()) { -            break; +        if (parameters[i].sector_key.command == MifareCmd::None) { +            continue;          } +        request.data[i].command = static_cast<u8>(parameters[i].sector_key.command); +        request.data[i].sector = parameters[i].sector_number; +        memcpy(request.data[i].key.data(), parameters[i].sector_key.sector_key.data(), +               sizeof(KeyData)); +        memcpy(request.data[i].data.data(), parameters[i].data.data(), sizeof(KeyData));      } -    if (!npad_device->WriteNfc(mifare_data)) { -        LOG_ERROR(Service_NFP, "Error writing to file"); +    if (!npad_device->WriteMifareData(request)) {          return ResultMifareError288;      }      return result;  } -Result NfcDevice::WriteMifare(const MifareWriteBlockParameter& parameter) { -    const std::size_t sector_index = parameter.sector_number * sizeof(DataBlock); - -    if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted) { -        LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); -        if (device_state == DeviceState::TagRemoved) { -            return ResultTagRemoved; -        } -        return ResultWrongDeviceState; -    } - -    if (mifare_data.size() < sector_index + sizeof(DataBlock)) { -        return ResultMifareError288; -    } - -    // TODO: Use parameter.sector_key to encrypt the data -    memcpy(mifare_data.data() + sector_index, parameter.data.data(), sizeof(DataBlock)); - -    return ResultSuccess; -} -  Result NfcDevice::SendCommandByPassThrough(const Time::Clock::TimeSpanType& timeout,                                             std::span<const u8> command_data,                                             std::span<u8> out_data) { @@ -412,6 +399,11 @@ Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target          return ResultWrongDeviceState;      } +    if (!LoadAmiiboData()) { +        LOG_ERROR(Service_NFP, "Not an amiibo"); +        return ResultInvalidTagType; +    } +      if (!NFP::AmiiboCrypto::IsAmiiboValid(encrypted_tag_data)) {          LOG_ERROR(Service_NFP, "Not an amiibo");          return ResultInvalidTagType; @@ -562,7 +554,7 @@ Result NfcDevice::Restore() {      NFC::TagInfo tag_info{};      std::array<u8, sizeof(NFP::EncryptedNTAG215File)> data{}; -    Result result = GetTagInfo(tag_info, false); +    Result result = GetTagInfo(tag_info);      if (result.IsError()) {          return result; @@ -635,7 +627,7 @@ Result NfcDevice::GetCommonInfo(NFP::CommonInfo& common_info) const {      // TODO: Validate this data      common_info = {          .last_write_date = settings.write_date.GetWriteDate(), -        .write_counter = tag_data.write_counter, +        .write_counter = tag_data.application_write_counter,          .version = tag_data.amiibo_version,          .application_area_size = sizeof(NFP::ApplicationArea),      }; diff --git a/src/core/hle/service/nfc/common/device.h b/src/core/hle/service/nfc/common/device.h index 7560210d6..0ed1ff34c 100644 --- a/src/core/hle/service/nfc/common/device.h +++ b/src/core/hle/service/nfc/common/device.h @@ -42,15 +42,12 @@ public:      Result StartDetection(NfcProtocol allowed_protocol);      Result StopDetection(); -    Result GetTagInfo(TagInfo& tag_info, bool is_mifare) const; +    Result GetTagInfo(TagInfo& tag_info) const;      Result ReadMifare(std::span<const MifareReadBlockParameter> parameters,                        std::span<MifareReadBlockData> read_block_data) const; -    Result ReadMifare(const MifareReadBlockParameter& parameter, -                      MifareReadBlockData& read_block_data) const;      Result WriteMifare(std::span<const MifareWriteBlockParameter> parameters); -    Result WriteMifare(const MifareWriteBlockParameter& parameter);      Result SendCommandByPassThrough(const Time::Clock::TimeSpanType& timeout,                                      std::span<const u8> command_data, std::span<u8> out_data); @@ -105,7 +102,8 @@ public:  private:      void NpadUpdate(Core::HID::ControllerTriggerType type); -    bool LoadNfcTag(std::span<const u8> data); +    bool LoadNfcTag(u8 protocol, u8 tag_type, u8 uuid_length, UniqueSerialNumber uuid); +    bool LoadAmiiboData();      void CloseNfcTag();      NFP::AmiiboName GetAmiiboName(const NFP::AmiiboSettings& settings) const; @@ -140,8 +138,8 @@ private:      bool is_write_protected{};      NFP::MountTarget mount_target{NFP::MountTarget::None}; +    TagInfo real_tag_info{};      NFP::NTAG215File tag_data{}; -    std::vector<u8> mifare_data{};      NFP::EncryptedNTAG215File encrypted_tag_data{};  }; diff --git a/src/core/hle/service/nfc/common/device_manager.cpp b/src/core/hle/service/nfc/common/device_manager.cpp index b0456508e..562f3a28e 100644 --- a/src/core/hle/service/nfc/common/device_manager.cpp +++ b/src/core/hle/service/nfc/common/device_manager.cpp @@ -29,6 +29,9 @@ DeviceManager::DeviceManager(Core::System& system_, KernelHelpers::ServiceContex  }  DeviceManager ::~DeviceManager() { +    if (is_initialized) { +        Finalize(); +    }      service_context.CloseEvent(availability_change_event);  } @@ -125,14 +128,14 @@ Result DeviceManager::StopDetection(u64 device_handle) {      return result;  } -Result DeviceManager::GetTagInfo(u64 device_handle, TagInfo& tag_info, bool is_mifare) const { +Result DeviceManager::GetTagInfo(u64 device_handle, TagInfo& tag_info) const {      std::scoped_lock lock{mutex};      std::shared_ptr<NfcDevice> device = nullptr;      auto result = GetDeviceHandle(device_handle, device);      if (result.IsSuccess()) { -        result = device->GetTagInfo(tag_info, is_mifare); +        result = device->GetTagInfo(tag_info);          result = VerifyDeviceResult(device, result);      } @@ -546,7 +549,7 @@ Result DeviceManager::ReadBackupData(u64 device_handle, std::span<u8> data) cons      NFC::TagInfo tag_info{};      if (result.IsSuccess()) { -        result = device->GetTagInfo(tag_info, false); +        result = device->GetTagInfo(tag_info);      }      if (result.IsSuccess()) { @@ -565,7 +568,7 @@ Result DeviceManager::WriteBackupData(u64 device_handle, std::span<const u8> dat      NFC::TagInfo tag_info{};      if (result.IsSuccess()) { -        result = device->GetTagInfo(tag_info, false); +        result = device->GetTagInfo(tag_info);      }      if (result.IsSuccess()) { diff --git a/src/core/hle/service/nfc/common/device_manager.h b/src/core/hle/service/nfc/common/device_manager.h index 2971e280f..c61ba0cf3 100644 --- a/src/core/hle/service/nfc/common/device_manager.h +++ b/src/core/hle/service/nfc/common/device_manager.h @@ -33,7 +33,7 @@ public:      Kernel::KReadableEvent& AttachAvailabilityChangeEvent() const;      Result StartDetection(u64 device_handle, NfcProtocol tag_protocol);      Result StopDetection(u64 device_handle); -    Result GetTagInfo(u64 device_handle, NFP::TagInfo& tag_info, bool is_mifare) const; +    Result GetTagInfo(u64 device_handle, NFP::TagInfo& tag_info) const;      Kernel::KReadableEvent& AttachActivateEvent(u64 device_handle) const;      Kernel::KReadableEvent& AttachDeactivateEvent(u64 device_handle) const;      Result ReadMifare(u64 device_handle, diff --git a/src/core/hle/service/nfc/mifare_types.h b/src/core/hle/service/nfc/mifare_types.h index 75b59f021..467937399 100644 --- a/src/core/hle/service/nfc/mifare_types.h +++ b/src/core/hle/service/nfc/mifare_types.h @@ -11,9 +11,10 @@  namespace Service::NFC {  enum class MifareCmd : u8 { +    None = 0x00, +    Read = 0x30,      AuthA = 0x60,      AuthB = 0x61, -    Read = 0x30,      Write = 0xA0,      Transfer = 0xB0,      Decrement = 0xC0, @@ -35,17 +36,17 @@ static_assert(sizeof(SectorKey) == 0x10, "SectorKey is an invalid size");  // This is nn::nfc::MifareReadBlockParameter  struct MifareReadBlockParameter { -    u8 sector_number; +    u8 sector_number{};      INSERT_PADDING_BYTES(0x7); -    SectorKey sector_key; +    SectorKey sector_key{};  };  static_assert(sizeof(MifareReadBlockParameter) == 0x18,                "MifareReadBlockParameter is an invalid size");  // This is nn::nfc::MifareReadBlockData  struct MifareReadBlockData { -    DataBlock data; -    u8 sector_number; +    DataBlock data{}; +    u8 sector_number{};      INSERT_PADDING_BYTES(0x7);  };  static_assert(sizeof(MifareReadBlockData) == 0x18, "MifareReadBlockData is an invalid size"); diff --git a/src/core/hle/service/nfc/nfc_interface.cpp b/src/core/hle/service/nfc/nfc_interface.cpp index 130fb7f78..e7ca7582e 100644 --- a/src/core/hle/service/nfc/nfc_interface.cpp +++ b/src/core/hle/service/nfc/nfc_interface.cpp @@ -174,8 +174,7 @@ void NfcInterface::GetTagInfo(HLERequestContext& ctx) {      LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);      TagInfo tag_info{}; -    auto result = -        GetManager()->GetTagInfo(device_handle, tag_info, backend_type == BackendType::Mifare); +    auto result = GetManager()->GetTagInfo(device_handle, tag_info);      result = TranslateResultToServiceError(result);      if (result.IsSuccess()) { @@ -216,8 +215,8 @@ void NfcInterface::ReadMifare(HLERequestContext& ctx) {      memcpy(read_commands.data(), buffer.data(),             number_of_commands * sizeof(MifareReadBlockParameter)); -    LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, read_commands_size={}", -             device_handle, number_of_commands); +    LOG_INFO(Service_NFC, "called, device_handle={}, read_commands_size={}", device_handle, +             number_of_commands);      std::vector<MifareReadBlockData> out_data(number_of_commands);      auto result = GetManager()->ReadMifare(device_handle, read_commands, out_data); | 
