ofw pr 4293 NFC FeliCa Improvement: Dump All Systems

by zinongli
This commit is contained in:
MX
2025-10-12 03:39:38 +03:00
parent fc34205f97
commit eed1d3367a
14 changed files with 569 additions and 325 deletions

View File

@@ -12,6 +12,7 @@
ARRAY_DEF(felica_service_array, FelicaService, M_POD_OPLIST); // -V658
ARRAY_DEF(felica_area_array, FelicaArea, M_POD_OPLIST); // -V658
ARRAY_DEF(felica_public_block_array, FelicaPublicBlock, M_POD_OPLIST); // -V658
ARRAY_DEF(felica_system_array, FelicaSystem, M_POD_OPLIST); // -V658
typedef NfcCommand (*FelicaPollerReadHandler)(FelicaPoller* instance);
@@ -43,6 +44,9 @@ static FelicaPoller* felica_poller_alloc(Nfc* nfc) {
instance->general_event.event_data = &instance->felica_event;
instance->general_event.instance = instance;
instance->systems_read = 0;
instance->systems_total = 0;
return instance;
}
@@ -94,7 +98,7 @@ NfcCommand felica_poller_state_handler_activate(FelicaPoller* instance) {
switch(instance->data->workflow_type) {
case FelicaStandard:
instance->state = FelicaPollerStateTraverseStandardSystem;
instance->state = FelicaPollerStateListSystem;
break;
case FelicaLite:
instance->state = FelicaPollerStateReadLiteBlocks;
@@ -117,6 +121,44 @@ NfcCommand felica_poller_state_handler_activate(FelicaPoller* instance) {
return command;
}
NfcCommand felica_poller_state_handler_list_system(FelicaPoller* instance) {
FURI_LOG_D(TAG, "List System");
NfcCommand command = NfcCommandContinue;
FelicaListSystemCodeCommandResponse* response_system_code;
FelicaError error = felica_poller_list_system_code(instance, &response_system_code);
instance->systems_total = response_system_code->system_count;
simple_array_init(instance->data->systems, instance->systems_total);
uint8_t* system_codes = response_system_code->system_code;
for(uint8_t i = 0; i < instance->systems_total; i++) {
FelicaSystem* system = simple_array_get(instance->data->systems, i);
system->system_code = system_codes[i * 2] << 8 | system_codes[i * 2 + 1];
system->system_code_idx = i;
}
if(error == FelicaErrorNone) {
instance->state = FelicaPollerStateSelectSystemIndex;
} else if(error != FelicaErrorTimeout) {
instance->felica_event.type = FelicaPollerEventTypeError;
instance->felica_event_data.error = error;
instance->state = FelicaPollerStateReadFailed;
}
return command;
}
NfcCommand felica_poller_state_handler_select_system_idx(FelicaPoller* instance) {
FURI_LOG_D(TAG, "Select System Index %d", instance->systems_read);
uint8_t system_index_mask = instance->systems_read << 4;
instance->data->idm.data[0] &= 0x0F;
instance->data->idm.data[0] |= system_index_mask;
instance->state = FelicaPollerStateTraverseStandardSystem;
return NfcCommandContinue;
}
NfcCommand felica_poller_state_handler_auth_internal(FelicaPoller* instance) {
FURI_LOG_D(TAG, "Auth Internal");
@@ -274,6 +316,8 @@ NfcCommand felica_poller_state_handler_traverse_standard_system(FelicaPoller* in
service->code = code_begin;
service->attr = (uint8_t)(code_begin & 0x3F);
FURI_LOG_D(TAG, "Service %04X", service->code);
if(felica_area_array_size(area_buffer)) {
FelicaArea* current_area = felica_area_array_back(area_buffer);
current_area->last_idx = (uint16_t)(felica_service_array_size(service_buffer) - 1);
@@ -284,31 +328,30 @@ NfcCommand felica_poller_state_handler_traverse_standard_system(FelicaPoller* in
const size_t service_num = felica_service_array_size(service_buffer);
const size_t area_num = felica_area_array_size(area_buffer);
FelicaSystem* system = simple_array_get(instance->data->systems, instance->systems_read);
if(service_num) {
simple_array_init(instance->data->services, (uint32_t)service_num);
simple_array_init(system->services, (uint32_t)service_num);
memcpy(
simple_array_get(instance->data->services, 0),
simple_array_get(system->services, 0),
service_buffer->ptr,
service_num * sizeof(FelicaService));
} else {
simple_array_reset(instance->data->services);
simple_array_reset(system->services);
}
if(area_num) {
simple_array_init(instance->data->areas, (uint32_t)area_num);
simple_array_init(system->areas, (uint32_t)area_num);
memcpy(
simple_array_get(instance->data->areas, 0),
area_buffer->ptr,
area_num * sizeof(FelicaArea));
simple_array_get(system->areas, 0), area_buffer->ptr, area_num * sizeof(FelicaArea));
} else {
simple_array_reset(instance->data->areas);
simple_array_reset(system->areas);
}
FURI_LOG_I(
TAG,
"Services found: %lu, Areas found: %lu",
simple_array_get_count(instance->data->services),
simple_array_get_count(instance->data->areas));
simple_array_get_count(system->services),
simple_array_get_count(system->areas));
felica_service_array_clear(service_buffer);
felica_area_array_clear(area_buffer);
@@ -320,22 +363,22 @@ NfcCommand felica_poller_state_handler_traverse_standard_system(FelicaPoller* in
NfcCommand felica_poller_state_handler_read_standard_blocks(FelicaPoller* instance) {
FURI_LOG_D(TAG, "Read Standard Blocks");
const uint32_t service_count = simple_array_get_count(instance->data->services);
FelicaSystem* system = simple_array_get(instance->data->systems, instance->systems_read);
const uint32_t service_count = simple_array_get_count(system->services);
felica_public_block_array_t public_block_buffer;
felica_public_block_array_init(public_block_buffer);
instance->state = FelicaPollerStateReadSuccess;
bool have_read_anything = false;
FelicaError error = FelicaErrorNone;
for(uint32_t i = 0; i < service_count; i++) {
const FelicaService* service = simple_array_get(instance->data->services, i);
const FelicaService* service = simple_array_get(system->services, i);
if((service->attr & FELICA_SERVICE_ATTRIBUTE_UNAUTH_READ) == 0) continue;
uint8_t block_count = 1;
uint8_t block_list[1] = {0};
FelicaError error = FelicaErrorNone;
FelicaPollerReadCommandResponse* response;
do {
error = felica_poller_read_blocks(
@@ -369,11 +412,20 @@ NfcCommand felica_poller_state_handler_read_standard_blocks(FelicaPoller* instan
}
}
if(error == FelicaErrorNone) {
instance->systems_read++;
if(instance->systems_read == instance->systems_total) {
instance->state = FelicaPollerStateReadSuccess;
} else {
instance->state = FelicaPollerStateSelectSystemIndex;
}
}
if(have_read_anything) {
const size_t n = felica_public_block_array_size(public_block_buffer);
simple_array_init(instance->data->public_blocks, (uint32_t)n);
simple_array_init(system->public_blocks, (uint32_t)n);
memcpy(
simple_array_get(instance->data->public_blocks, 0),
simple_array_get(system->public_blocks, 0),
public_block_buffer->ptr,
n * sizeof(FelicaPublicBlock));
}
@@ -446,6 +498,8 @@ NfcCommand felica_poller_state_handler_read_success(FelicaPoller* instance) {
instance->felica_event.type = FelicaPollerEventTypeReady;
}
instance->data->idm.data[0] &= 0x0F;
instance->felica_event_data.error = FelicaErrorNone;
return instance->callback(instance->general_event, instance->context);
}
@@ -453,6 +507,7 @@ NfcCommand felica_poller_state_handler_read_success(FelicaPoller* instance) {
NfcCommand felica_poller_state_handler_read_failed(FelicaPoller* instance) {
FURI_LOG_D(TAG, "Read Fail");
instance->callback(instance->general_event, instance->context);
instance->data->idm.data[0] &= 0x0F;
return NfcCommandStop;
}
@@ -460,6 +515,8 @@ NfcCommand felica_poller_state_handler_read_failed(FelicaPoller* instance) {
static const FelicaPollerReadHandler felica_poller_handler[FelicaPollerStateNum] = {
[FelicaPollerStateIdle] = felica_poller_state_handler_idle,
[FelicaPollerStateActivated] = felica_poller_state_handler_activate,
[FelicaPollerStateListSystem] = felica_poller_state_handler_list_system,
[FelicaPollerStateSelectSystemIndex] = felica_poller_state_handler_select_system_idx,
[FelicaPollerStateAuthenticateInternal] = felica_poller_state_handler_auth_internal,
[FelicaPollerStateAuthenticateExternal] = felica_poller_state_handler_auth_external,
[FelicaPollerStateTraverseStandardSystem] =