mirror of
https://github.com/bettse/seader.git
synced 2026-03-30 20:45:51 +00:00
begin work on multi tech
This commit is contained in:
2
Makefile
2
Makefile
@@ -25,6 +25,7 @@ test-host:
|
||||
lib/host_tests/test_snmp.c \
|
||||
lib/host_tests/test_uhf_status_label.c \
|
||||
lib/host_tests/test_credential_sio_label.c \
|
||||
lib/host_tests/test_hf_read_plan.c \
|
||||
lib/host_tests/test_runtime_policy.c \
|
||||
lib/host_tests/t1_test_stubs.c \
|
||||
lib/host_tests/bit_buffer_mock.c \
|
||||
@@ -40,6 +41,7 @@ test-host:
|
||||
uhf_status_label.c \
|
||||
uhf_tag_config_view.c \
|
||||
uhf_snmp_probe.c \
|
||||
seader_hf_read_plan.c \
|
||||
runtime_policy.c \
|
||||
-o build/host_tests/seader_tests
|
||||
./build/host_tests/seader_tests
|
||||
|
||||
118
lib/host_tests/test_hf_read_plan.c
Normal file
118
lib/host_tests/test_hf_read_plan.c
Normal file
@@ -0,0 +1,118 @@
|
||||
#include "munit.h"
|
||||
|
||||
#include "seader_hf_read_plan.h"
|
||||
|
||||
static MunitResult test_selected_type_starts_immediately(
|
||||
const MunitParameter params[],
|
||||
void* fixture) {
|
||||
(void)params;
|
||||
(void)fixture;
|
||||
|
||||
const SeaderCredentialType detected_types[] = {
|
||||
SeaderCredentialType14A,
|
||||
SeaderCredentialTypeMifareClassic,
|
||||
};
|
||||
const SeaderHfReadPlan plan = seader_hf_read_plan_build(
|
||||
SeaderCredentialTypePicopass, detected_types, 2U);
|
||||
|
||||
munit_assert_int(plan.decision, ==, SeaderHfReadDecisionStartRead);
|
||||
munit_assert_int(plan.type_to_read, ==, SeaderCredentialTypePicopass);
|
||||
munit_assert_size(plan.detected_type_count, ==, 0U);
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
static MunitResult test_no_detected_types_continues_polling(
|
||||
const MunitParameter params[],
|
||||
void* fixture) {
|
||||
(void)params;
|
||||
(void)fixture;
|
||||
|
||||
const SeaderHfReadPlan plan = seader_hf_read_plan_build(SeaderCredentialTypeNone, NULL, 0U);
|
||||
|
||||
munit_assert_int(plan.decision, ==, SeaderHfReadDecisionContinuePolling);
|
||||
munit_assert_int(plan.type_to_read, ==, SeaderCredentialTypeNone);
|
||||
munit_assert_size(plan.detected_type_count, ==, 0U);
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
static MunitResult test_single_detected_type_starts_read(
|
||||
const MunitParameter params[],
|
||||
void* fixture) {
|
||||
(void)params;
|
||||
(void)fixture;
|
||||
|
||||
const SeaderCredentialType detected_types[] = {SeaderCredentialType14A};
|
||||
const SeaderHfReadPlan plan =
|
||||
seader_hf_read_plan_build(SeaderCredentialTypeNone, detected_types, 1U);
|
||||
|
||||
munit_assert_int(plan.decision, ==, SeaderHfReadDecisionStartRead);
|
||||
munit_assert_int(plan.type_to_read, ==, SeaderCredentialType14A);
|
||||
munit_assert_size(plan.detected_type_count, ==, 1U);
|
||||
munit_assert_int(plan.detected_types[0], ==, SeaderCredentialType14A);
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
static MunitResult test_multiple_detected_types_requests_selection(
|
||||
const MunitParameter params[],
|
||||
void* fixture) {
|
||||
(void)params;
|
||||
(void)fixture;
|
||||
|
||||
const SeaderCredentialType detected_types[] = {
|
||||
SeaderCredentialType14A,
|
||||
SeaderCredentialTypeMifareClassic,
|
||||
SeaderCredentialTypePicopass,
|
||||
};
|
||||
const SeaderHfReadPlan plan =
|
||||
seader_hf_read_plan_build(SeaderCredentialTypeNone, detected_types, 3U);
|
||||
|
||||
munit_assert_int(plan.decision, ==, SeaderHfReadDecisionSelectType);
|
||||
munit_assert_int(plan.type_to_read, ==, SeaderCredentialTypeNone);
|
||||
munit_assert_size(plan.detected_type_count, ==, 3U);
|
||||
munit_assert_int(plan.detected_types[0], ==, SeaderCredentialType14A);
|
||||
munit_assert_int(plan.detected_types[1], ==, SeaderCredentialTypeMifareClassic);
|
||||
munit_assert_int(plan.detected_types[2], ==, SeaderCredentialTypePicopass);
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
static MunitResult test_detected_types_are_deduped_and_clamped(
|
||||
const MunitParameter params[],
|
||||
void* fixture) {
|
||||
(void)params;
|
||||
(void)fixture;
|
||||
|
||||
const SeaderCredentialType detected_types[] = {
|
||||
SeaderCredentialType14A,
|
||||
SeaderCredentialTypeMifareClassic,
|
||||
SeaderCredentialType14A,
|
||||
SeaderCredentialTypeNone,
|
||||
SeaderCredentialTypePicopass,
|
||||
SeaderCredentialTypeConfig,
|
||||
};
|
||||
const SeaderHfReadPlan plan =
|
||||
seader_hf_read_plan_build(SeaderCredentialTypeNone, detected_types, 6U);
|
||||
|
||||
munit_assert_int(plan.decision, ==, SeaderHfReadDecisionSelectType);
|
||||
munit_assert_size(plan.detected_type_count, ==, 3U);
|
||||
munit_assert_int(plan.detected_types[0], ==, SeaderCredentialType14A);
|
||||
munit_assert_int(plan.detected_types[1], ==, SeaderCredentialTypeMifareClassic);
|
||||
munit_assert_int(plan.detected_types[2], ==, SeaderCredentialTypePicopass);
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
static MunitTest test_hf_read_plan_cases[] = {
|
||||
{(char*)"/selected-type", test_selected_type_starts_immediately, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
|
||||
{(char*)"/none-detected", test_no_detected_types_continues_polling, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
|
||||
{(char*)"/single-detected", test_single_detected_type_starts_read, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
|
||||
{(char*)"/multiple-detected", test_multiple_detected_types_requests_selection, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
|
||||
{(char*)"/dedupe-and-clamp", test_detected_types_are_deduped_and_clamped, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
|
||||
{NULL, NULL, NULL, NULL, 0, NULL},
|
||||
};
|
||||
|
||||
MunitSuite test_hf_read_plan_suite = {
|
||||
"",
|
||||
test_hf_read_plan_cases,
|
||||
NULL,
|
||||
1,
|
||||
MUNIT_SUITE_OPTION_NONE,
|
||||
};
|
||||
@@ -8,6 +8,7 @@ extern MunitSuite test_t1_protocol_suite;
|
||||
extern MunitSuite test_snmp_suite;
|
||||
extern MunitSuite test_uhf_status_label_suite;
|
||||
extern MunitSuite test_credential_sio_label_suite;
|
||||
extern MunitSuite test_hf_read_plan_suite;
|
||||
extern MunitSuite test_runtime_policy_suite;
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
@@ -20,6 +21,7 @@ int main(int argc, char* argv[]) {
|
||||
{"/snmp", test_snmp_suite.tests, NULL, 1, MUNIT_SUITE_OPTION_NONE},
|
||||
{"/uhf-status-label", test_uhf_status_label_suite.tests, NULL, 1, MUNIT_SUITE_OPTION_NONE},
|
||||
{"/credential-sio-label", test_credential_sio_label_suite.tests, NULL, 1, MUNIT_SUITE_OPTION_NONE},
|
||||
{"/hf-read-plan", test_hf_read_plan_suite.tests, NULL, 1, MUNIT_SUITE_OPTION_NONE},
|
||||
{"/runtime-policy", test_runtime_policy_suite.tests, NULL, 1, MUNIT_SUITE_OPTION_NONE},
|
||||
{NULL, NULL, NULL, 0, 0},
|
||||
};
|
||||
|
||||
49
seader_hf_read_plan.c
Normal file
49
seader_hf_read_plan.c
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "seader_hf_read_plan.h"
|
||||
|
||||
#define SEADER_HF_READ_PLAN_MAX_TYPES 3U
|
||||
|
||||
static void seader_hf_read_plan_add_type(
|
||||
SeaderHfReadPlan* plan,
|
||||
SeaderCredentialType type) {
|
||||
if(type == SeaderCredentialTypeNone) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < plan->detected_type_count; i++) {
|
||||
if(plan->detected_types[i] == type) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(plan->detected_type_count < SEADER_HF_READ_PLAN_MAX_TYPES) {
|
||||
plan->detected_types[plan->detected_type_count++] = type;
|
||||
}
|
||||
}
|
||||
|
||||
SeaderHfReadPlan seader_hf_read_plan_build(
|
||||
SeaderCredentialType selected_type,
|
||||
const SeaderCredentialType* detected_types,
|
||||
size_t detected_type_count) {
|
||||
SeaderHfReadPlan plan = {0};
|
||||
|
||||
if(selected_type != SeaderCredentialTypeNone) {
|
||||
plan.decision = SeaderHfReadDecisionStartRead;
|
||||
plan.type_to_read = selected_type;
|
||||
return plan;
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < detected_type_count; i++) {
|
||||
seader_hf_read_plan_add_type(&plan, detected_types[i]);
|
||||
}
|
||||
|
||||
if(plan.detected_type_count == 1U) {
|
||||
plan.decision = SeaderHfReadDecisionStartRead;
|
||||
plan.type_to_read = plan.detected_types[0];
|
||||
} else if(plan.detected_type_count > 1U) {
|
||||
plan.decision = SeaderHfReadDecisionSelectType;
|
||||
} else {
|
||||
plan.decision = SeaderHfReadDecisionContinuePolling;
|
||||
}
|
||||
|
||||
return plan;
|
||||
}
|
||||
23
seader_hf_read_plan.h
Normal file
23
seader_hf_read_plan.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "seader_credential_type.h"
|
||||
|
||||
typedef enum {
|
||||
SeaderHfReadDecisionContinuePolling,
|
||||
SeaderHfReadDecisionStartRead,
|
||||
SeaderHfReadDecisionSelectType,
|
||||
} SeaderHfReadDecision;
|
||||
|
||||
typedef struct {
|
||||
SeaderHfReadDecision decision;
|
||||
SeaderCredentialType type_to_read;
|
||||
SeaderCredentialType detected_types[3];
|
||||
size_t detected_type_count;
|
||||
} SeaderHfReadPlan;
|
||||
|
||||
SeaderHfReadPlan seader_hf_read_plan_build(
|
||||
SeaderCredentialType selected_type,
|
||||
const SeaderCredentialType* detected_types,
|
||||
size_t detected_type_count);
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "seader_worker_i.h"
|
||||
#include "seader_hf_read_plan.h"
|
||||
#include "trace_log.h"
|
||||
|
||||
#include <flipper_format/flipper_format.h>
|
||||
@@ -490,6 +491,7 @@ void seader_worker_reading(Seader* seader) {
|
||||
bool detected = false;
|
||||
SeaderPollerEventType result_stage = SeaderPollerEventTypeFail;
|
||||
SeaderCredentialType type_to_read = seader_hf_mode_get_selected_read_type(seader);
|
||||
SeaderHfReadPlan read_plan = {0};
|
||||
FURI_LOG_D(TAG, "HF loop selected type=%d stage=%d", type_to_read, seader_worker->stage);
|
||||
|
||||
if(type_to_read == SeaderCredentialTypeNone) {
|
||||
@@ -497,22 +499,23 @@ void seader_worker_reading(Seader* seader) {
|
||||
const size_t detected_type_count = seader->plugin_hf->detect_supported_types(
|
||||
seader->hf_plugin_ctx, detected_types, COUNT_OF(detected_types));
|
||||
FURI_LOG_I(TAG, "HF plugin detected %u type(s)", detected_type_count);
|
||||
|
||||
if(detected_type_count > 1) {
|
||||
seader_hf_mode_set_detected_types(seader, detected_types, detected_type_count);
|
||||
if(seader_worker->callback) {
|
||||
seader_worker->callback(
|
||||
SeaderWorkerEventSelectCardType, seader_worker->context);
|
||||
}
|
||||
break;
|
||||
} else if(detected_type_count == 1) {
|
||||
type_to_read = detected_types[0];
|
||||
}
|
||||
read_plan =
|
||||
seader_hf_read_plan_build(type_to_read, detected_types, detected_type_count);
|
||||
} else {
|
||||
read_plan = seader_hf_read_plan_build(type_to_read, NULL, 0U);
|
||||
}
|
||||
|
||||
if(type_to_read != SeaderCredentialTypeNone) {
|
||||
FURI_LOG_I(TAG, "HF start read for type=%d", type_to_read);
|
||||
detected = seader->plugin_hf->start_read_for_type(seader->hf_plugin_ctx, type_to_read);
|
||||
if(read_plan.decision == SeaderHfReadDecisionSelectType) {
|
||||
seader_hf_mode_set_detected_types(
|
||||
seader, read_plan.detected_types, read_plan.detected_type_count);
|
||||
if(seader_worker->callback) {
|
||||
seader_worker->callback(SeaderWorkerEventSelectCardType, seader_worker->context);
|
||||
}
|
||||
break;
|
||||
} else if(read_plan.decision == SeaderHfReadDecisionStartRead) {
|
||||
FURI_LOG_I(TAG, "HF start read for type=%d", read_plan.type_to_read);
|
||||
detected =
|
||||
seader->plugin_hf->start_read_for_type(seader->hf_plugin_ctx, read_plan.type_to_read);
|
||||
if(detected) {
|
||||
seader->hf_session_state = SeaderHfSessionStateActive;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user