mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-04-30 04:19:59 -07:00
NFC: add Slix capabilities (#3652)
* iso15693 listener: fix inventory cmd and buffer overflow * iso15 listener: fix read multiple blocks command * slix: print password * slix: add capabilities field * slix listener: skip password validation for special capability * slix: fix capability name * slix: add capabilities handler to verify and reset * nfc test: introduce slix tests * fbt: change toolchain back to 33 version * slix: fix saving capablities comment * unit tests: add slix files to resources * slix: fix set passwrd signature * nfc tests: add set correct password test * nfc test: complete slix password tests * nfc test: add slix file test * nfc test: handle errors in worker callback * iso15693_3: code clean up * iso15693_listener: fix incorrect afi handling * slix: chage capabilities format to one word camel case * unit tests: update nfc files with new slix format Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
@@ -13,6 +13,12 @@
|
||||
#include <nfc/protocols/mf_ultralight/mf_ultralight_poller_sync.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller.h>
|
||||
#include <nfc/protocols/iso15693_3/iso15693_3_poller.h>
|
||||
#include <nfc/protocols/slix/slix.h>
|
||||
#include <nfc/protocols/slix/slix_i.h>
|
||||
#include <nfc/protocols/slix/slix_poller.h>
|
||||
#include <nfc/protocols/slix/slix_poller_i.h>
|
||||
|
||||
#include <nfc/nfc_poller.h>
|
||||
|
||||
#include <toolbox/keys_dict.h>
|
||||
@@ -42,6 +48,19 @@ typedef struct {
|
||||
FuriThreadId thread_id;
|
||||
} NfcTestMfClassicSendFrameTest;
|
||||
|
||||
typedef enum {
|
||||
NfcTestSlixPollerSetPasswordStateGetRandomNumber,
|
||||
NfcTestSlixPollerSetPasswordStateSetPassword,
|
||||
} NfcTestSlixPollerSetPasswordState;
|
||||
|
||||
typedef struct {
|
||||
FuriThreadId thread_id;
|
||||
NfcTestSlixPollerSetPasswordState state;
|
||||
SlixRandomNumber random_number;
|
||||
SlixPassword password;
|
||||
SlixError error;
|
||||
} NfcTestSlixPollerSetPasswordContext;
|
||||
|
||||
typedef struct {
|
||||
Storage* storage;
|
||||
} NfcTest;
|
||||
@@ -627,6 +646,127 @@ MU_TEST(mf_classic_dict_test) {
|
||||
"Remove test dict failed");
|
||||
}
|
||||
|
||||
MU_TEST(slix_file_with_capabilities_test) {
|
||||
NfcDevice* nfc_device_missed_cap = nfc_device_alloc();
|
||||
mu_assert(
|
||||
nfc_device_load(nfc_device_missed_cap, EXT_PATH("unit_tests/nfc/Slix_cap_missed.nfc")),
|
||||
"nfc_device_load() failed\r\n");
|
||||
|
||||
NfcDevice* nfc_device_default_cap = nfc_device_alloc();
|
||||
mu_assert(
|
||||
nfc_device_load(nfc_device_default_cap, EXT_PATH("unit_tests/nfc/Slix_cap_default.nfc")),
|
||||
"nfc_device_load() failed\r\n");
|
||||
|
||||
mu_assert(
|
||||
nfc_device_is_equal(nfc_device_missed_cap, nfc_device_default_cap),
|
||||
"nfc_device_is_equal() failed\r\n");
|
||||
|
||||
nfc_device_free(nfc_device_default_cap);
|
||||
nfc_device_free(nfc_device_missed_cap);
|
||||
}
|
||||
|
||||
NfcCommand slix_poller_set_password_callback(NfcGenericEventEx event, void* context) {
|
||||
furi_check(event.poller);
|
||||
furi_check(event.parent_event_data);
|
||||
furi_check(context);
|
||||
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
Iso15693_3PollerEvent* iso15_event = event.parent_event_data;
|
||||
SlixPoller* poller = event.poller;
|
||||
NfcTestSlixPollerSetPasswordContext* slix_ctx = context;
|
||||
|
||||
if(iso15_event->type == Iso15693_3PollerEventTypeReady) {
|
||||
iso15693_3_copy(
|
||||
poller->data->iso15693_3_data, iso15693_3_poller_get_data(poller->iso15693_3_poller));
|
||||
|
||||
if(slix_ctx->state == NfcTestSlixPollerSetPasswordStateGetRandomNumber) {
|
||||
slix_ctx->error = slix_poller_get_random_number(poller, &slix_ctx->random_number);
|
||||
if(slix_ctx->error != SlixErrorNone) {
|
||||
furi_thread_flags_set(slix_ctx->thread_id, NFC_TEST_FLAG_WORKER_DONE);
|
||||
command = NfcCommandStop;
|
||||
} else {
|
||||
slix_ctx->state = NfcTestSlixPollerSetPasswordStateSetPassword;
|
||||
}
|
||||
} else if(slix_ctx->state == NfcTestSlixPollerSetPasswordStateSetPassword) {
|
||||
slix_ctx->error = slix_poller_set_password(
|
||||
poller, SlixPasswordTypeRead, slix_ctx->password, slix_ctx->random_number);
|
||||
furi_thread_flags_set(slix_ctx->thread_id, NFC_TEST_FLAG_WORKER_DONE);
|
||||
command = NfcCommandStop;
|
||||
}
|
||||
} else {
|
||||
slix_ctx->error = slix_process_iso15693_3_error(iso15_event->data->error);
|
||||
furi_thread_flags_set(slix_ctx->thread_id, NFC_TEST_FLAG_WORKER_DONE);
|
||||
command = NfcCommandStop;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
static void slix_set_password_test(const char* file_path, SlixPassword pass, bool correct_pass) {
|
||||
FURI_LOG_I(TAG, "Testing file: %s", file_path);
|
||||
|
||||
Nfc* poller = nfc_alloc();
|
||||
Nfc* listener = nfc_alloc();
|
||||
|
||||
NfcDevice* nfc_device = nfc_device_alloc();
|
||||
mu_assert(nfc_device_load(nfc_device, file_path), "nfc_device_load() failed\r\n");
|
||||
|
||||
const SlixData* slix_data = nfc_device_get_data(nfc_device, NfcProtocolSlix);
|
||||
NfcListener* slix_listener = nfc_listener_alloc(listener, NfcProtocolSlix, slix_data);
|
||||
nfc_listener_start(slix_listener, NULL, NULL);
|
||||
|
||||
SlixCapabilities slix_capabilities = slix_data->capabilities;
|
||||
|
||||
NfcPoller* slix_poller = nfc_poller_alloc(poller, NfcProtocolSlix);
|
||||
|
||||
NfcTestSlixPollerSetPasswordContext slix_poller_context = {
|
||||
.thread_id = furi_thread_get_current_id(),
|
||||
.state = NfcTestSlixPollerSetPasswordStateGetRandomNumber,
|
||||
.password = pass,
|
||||
.error = SlixErrorNone,
|
||||
};
|
||||
|
||||
nfc_poller_start_ex(slix_poller, slix_poller_set_password_callback, &slix_poller_context);
|
||||
|
||||
uint32_t flag =
|
||||
furi_thread_flags_wait(NFC_TEST_FLAG_WORKER_DONE, FuriFlagWaitAny, FuriWaitForever);
|
||||
mu_assert(flag == NFC_TEST_FLAG_WORKER_DONE, "Wrong thread flag\r\n");
|
||||
|
||||
nfc_poller_stop(slix_poller);
|
||||
nfc_poller_free(slix_poller);
|
||||
nfc_listener_stop(slix_listener);
|
||||
nfc_listener_free(slix_listener);
|
||||
|
||||
mu_assert(
|
||||
slix_poller_context.state == NfcTestSlixPollerSetPasswordStateSetPassword,
|
||||
"Poller failed before setting password\r\n");
|
||||
|
||||
if((slix_capabilities == SlixCapabilitiesAcceptAllPasswords) || (correct_pass)) {
|
||||
mu_assert(slix_poller_context.error == SlixErrorNone, "Failed to set password\r\n");
|
||||
} else {
|
||||
mu_assert(
|
||||
slix_poller_context.error == SlixErrorTimeout,
|
||||
"Must have received SlixErrorTimeout\r\n");
|
||||
}
|
||||
|
||||
nfc_device_free(nfc_device);
|
||||
nfc_free(listener);
|
||||
nfc_free(poller);
|
||||
}
|
||||
|
||||
MU_TEST(slix_set_password_default_cap_correct_pass) {
|
||||
slix_set_password_test(EXT_PATH("unit_tests/nfc/Slix_cap_default.nfc"), 0x00000000, true);
|
||||
}
|
||||
|
||||
MU_TEST(slix_set_password_default_cap_incorrect_pass) {
|
||||
slix_set_password_test(EXT_PATH("unit_tests/nfc/Slix_cap_default.nfc"), 0x12341234, false);
|
||||
}
|
||||
|
||||
MU_TEST(slix_set_password_access_all_passwords_cap) {
|
||||
slix_set_password_test(
|
||||
EXT_PATH("unit_tests/nfc/Slix_cap_accept_all_pass.nfc"), 0x12341234, false);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(nfc) {
|
||||
nfc_test_alloc();
|
||||
|
||||
@@ -668,6 +808,11 @@ MU_TEST_SUITE(nfc) {
|
||||
MU_RUN_TEST(mf_classic_send_frame_test);
|
||||
MU_RUN_TEST(mf_classic_dict_test);
|
||||
|
||||
MU_RUN_TEST(slix_file_with_capabilities_test);
|
||||
MU_RUN_TEST(slix_set_password_default_cap_correct_pass);
|
||||
MU_RUN_TEST(slix_set_password_default_cap_incorrect_pass);
|
||||
MU_RUN_TEST(slix_set_password_access_all_passwords_cap);
|
||||
|
||||
nfc_test_free();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user