mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-13 06:18:35 -07:00
Array use refactor
Move all arrays to allocating actual data rather than pointers to simplify construction and destruction. Also moved to M_EACH for iterating over arrays for less boilerplate code. Also did some function renaming for extra clarity. root_area is now a node type for simplified area traversal (coming soon).
This commit is contained in:
@@ -19,10 +19,8 @@ void nfc_scene_felica_info_select_on_enter(void* context) {
|
|||||||
uint8_t i = 1;
|
uint8_t i = 1;
|
||||||
if(state->selected_system == NULL || state->selected_system->code == LITE_SYSTEM_CODE) {
|
if(state->selected_system == NULL || state->selected_system->code == LITE_SYSTEM_CODE) {
|
||||||
submenu_set_header(submenu, "Systems");
|
submenu_set_header(submenu, "Systems");
|
||||||
FelicaSystemList_it_t it;
|
for
|
||||||
for(FelicaSystemList_it(it, data->systems); !FelicaSystemList_end_p(it);
|
M_EACH(current_system, data->systems, FelicaSystemArray_t) {
|
||||||
FelicaSystemList_next(it)) {
|
|
||||||
FelicaSystem* current_system = *FelicaSystemList_ref(it);
|
|
||||||
FuriString* system_name = felica_get_system_name(current_system);
|
FuriString* system_name = felica_get_system_name(current_system);
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu,
|
submenu,
|
||||||
@@ -36,7 +34,9 @@ void nfc_scene_felica_info_select_on_enter(void* context) {
|
|||||||
FelicaSystem* system = state->selected_system;
|
FelicaSystem* system = state->selected_system;
|
||||||
FuriString* header = furi_string_alloc_printf("%04X/", system->code);
|
FuriString* header = furi_string_alloc_printf("%04X/", system->code);
|
||||||
|
|
||||||
FelicaArea* area = &system->root_area;
|
FelicaNode* root = &system->root;
|
||||||
|
furi_assert(root->type == FelicaNodeTypeArea);
|
||||||
|
FelicaArea* area = root->area;
|
||||||
if(FelicaAreaPath_size(state->selected_areas) > 0) {
|
if(FelicaAreaPath_size(state->selected_areas) > 0) {
|
||||||
FelicaAreaPath_it_t it;
|
FelicaAreaPath_it_t it;
|
||||||
for(FelicaAreaPath_it(it, state->selected_areas); !FelicaAreaPath_end_p(it);
|
for(FelicaAreaPath_it(it, state->selected_areas); !FelicaAreaPath_end_p(it);
|
||||||
@@ -51,10 +51,8 @@ void nfc_scene_felica_info_select_on_enter(void* context) {
|
|||||||
submenu_set_header(submenu, furi_string_get_cstr(header));
|
submenu_set_header(submenu, furi_string_get_cstr(header));
|
||||||
furi_string_free(header);
|
furi_string_free(header);
|
||||||
|
|
||||||
FelicaNodeList_it_t it;
|
for
|
||||||
for(FelicaNodeList_it(it, area->nodes); !FelicaNodeList_end_p(it);
|
M_EACH(node, area->nodes, FelicaNodeArray_t) {
|
||||||
FelicaNodeList_next(it)) {
|
|
||||||
FelicaNode* node = *FelicaNodeList_ref(it);
|
|
||||||
FuriString* node_name = furi_string_alloc();
|
FuriString* node_name = furi_string_alloc();
|
||||||
if(node->type == FelicaNodeTypeArea) {
|
if(node->type == FelicaNodeTypeArea) {
|
||||||
furi_string_printf(node_name, "Area %d", node->area->number);
|
furi_string_printf(node_name, "Area %d", node->area->number);
|
||||||
@@ -102,7 +100,7 @@ bool nfc_scene_felica_info_select_on_event(void* context, SceneManagerEvent even
|
|||||||
|
|
||||||
index -= 1;
|
index -= 1;
|
||||||
if(state->selected_system == NULL) {
|
if(state->selected_system == NULL) {
|
||||||
state->selected_system = *FelicaSystemList_get(data->systems, index);
|
state->selected_system = FelicaSystemArray_get(data->systems, index);
|
||||||
if(state->selected_system->code == LITE_SYSTEM_CODE) {
|
if(state->selected_system->code == LITE_SYSTEM_CODE) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaServiceData);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaServiceData);
|
||||||
} else {
|
} else {
|
||||||
@@ -111,12 +109,15 @@ bool nfc_scene_felica_info_select_on_event(void* context, SceneManagerEvent even
|
|||||||
consumed = true;
|
consumed = true;
|
||||||
} else {
|
} else {
|
||||||
FelicaNode* selected_node = NULL;
|
FelicaNode* selected_node = NULL;
|
||||||
|
|
||||||
|
FelicaNode* root = &(state->selected_system->root);
|
||||||
|
furi_assert(root->type == FelicaNodeTypeArea);
|
||||||
|
|
||||||
if(FelicaAreaPath_size(state->selected_areas) == 0) {
|
if(FelicaAreaPath_size(state->selected_areas) == 0) {
|
||||||
selected_node =
|
selected_node = FelicaNodeArray_get(root->area->nodes, index);
|
||||||
*FelicaNodeList_get(state->selected_system->root_area.nodes, index);
|
|
||||||
} else {
|
} else {
|
||||||
FelicaArea* current_area = *FelicaAreaPath_back(state->selected_areas);
|
FelicaArea* current_area = *FelicaAreaPath_back(state->selected_areas);
|
||||||
selected_node = *FelicaNodeList_get(current_area->nodes, index);
|
selected_node = FelicaNodeArray_get(current_area->nodes, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(selected_node->type == FelicaNodeTypeArea) {
|
if(selected_node->type == FelicaNodeTypeArea) {
|
||||||
|
|||||||
@@ -29,10 +29,8 @@ void nfc_scene_felica_read_success_on_enter(void* context) {
|
|||||||
} else {
|
} else {
|
||||||
temp_str = furi_string_alloc_printf("\e#%s", nfc_felica_type(felica_data->type));
|
temp_str = furi_string_alloc_printf("\e#%s", nfc_felica_type(felica_data->type));
|
||||||
|
|
||||||
FelicaSystemList_it_t it;
|
for
|
||||||
for(FelicaSystemList_it(it, felica_data->systems); !FelicaSystemList_end_p(it);
|
M_EACH(current_system, felica_data->systems, FelicaSystemArray_t) {
|
||||||
FelicaSystemList_next(it)) {
|
|
||||||
FelicaSystem* current_system = *FelicaSystemList_ref(it);
|
|
||||||
furi_string_cat_printf(
|
furi_string_cat_printf(
|
||||||
temp_str, "\nSystem %04X (#%d):", current_system->code, current_system->number);
|
temp_str, "\nSystem %04X (#%d):", current_system->code, current_system->number);
|
||||||
furi_string_cat_printf(temp_str, "\nIDm:\n ");
|
furi_string_cat_printf(temp_str, "\nIDm:\n ");
|
||||||
|
|||||||
@@ -66,35 +66,35 @@ void nfc_scene_nfc_data_info_on_enter(void* context) {
|
|||||||
nfc_data->f_data.pmm[0],
|
nfc_data->f_data.pmm[0],
|
||||||
nfc_data->f_data.pmm[1]);
|
nfc_data->f_data.pmm[1]);
|
||||||
|
|
||||||
furi_string_cat_printf(temp_str, "Timings (1 node/blk):\n");
|
furi_string_cat_printf(temp_str, "MRT (1 node/blk):\n");
|
||||||
furi_string_cat_printf(
|
furi_string_cat_printf(
|
||||||
temp_str,
|
temp_str,
|
||||||
"- ReqSvc: %" PRIuLEAST32 "us\n",
|
"- ReqSvc: %" PRIuLEAST32 "us\n",
|
||||||
felica_estimate_timing_us(nfc_data->f_data.pmm[2], 1));
|
felica_estimate_timing_us(nfc_data->f_data.pmm[FELICA_PMM_VARIABLE_MRT], 1));
|
||||||
furi_string_cat_printf(
|
furi_string_cat_printf(
|
||||||
temp_str,
|
temp_str,
|
||||||
"- Fixed: %" PRIuLEAST32 "us\n",
|
"- Fixed: %" PRIuLEAST32 "us\n",
|
||||||
felica_estimate_timing_us(nfc_data->f_data.pmm[3], 0));
|
felica_estimate_timing_us(nfc_data->f_data.pmm[FELICA_PMM_FIXED_MRT], 0));
|
||||||
furi_string_cat_printf(
|
furi_string_cat_printf(
|
||||||
temp_str,
|
temp_str,
|
||||||
"- Auth1: %" PRIuLEAST32 "us\n",
|
"- Auth1: %" PRIuLEAST32 "us\n",
|
||||||
felica_estimate_timing_us(nfc_data->f_data.pmm[4], 1));
|
felica_estimate_timing_us(nfc_data->f_data.pmm[FELICA_PMM_MUTUAL_AUTH_MRT], 1));
|
||||||
furi_string_cat_printf(
|
furi_string_cat_printf(
|
||||||
temp_str,
|
temp_str,
|
||||||
"- Auth2: %" PRIuLEAST32 "us\n",
|
"- Auth2: %" PRIuLEAST32 "us\n",
|
||||||
felica_estimate_timing_us(nfc_data->f_data.pmm[4], 0));
|
felica_estimate_timing_us(nfc_data->f_data.pmm[FELICA_PMM_MUTUAL_AUTH_MRT], 0));
|
||||||
furi_string_cat_printf(
|
furi_string_cat_printf(
|
||||||
temp_str,
|
temp_str,
|
||||||
"- Read: %" PRIuLEAST32 "us\n",
|
"- Read: %" PRIuLEAST32 "us\n",
|
||||||
felica_estimate_timing_us(nfc_data->f_data.pmm[5], 1));
|
felica_estimate_timing_us(nfc_data->f_data.pmm[FELICA_PMM_READ_MRT], 1));
|
||||||
furi_string_cat_printf(
|
furi_string_cat_printf(
|
||||||
temp_str,
|
temp_str,
|
||||||
"- Write: %" PRIuLEAST32 "us\n",
|
"- Write: %" PRIuLEAST32 "us\n",
|
||||||
felica_estimate_timing_us(nfc_data->f_data.pmm[6], 1));
|
felica_estimate_timing_us(nfc_data->f_data.pmm[FELICA_PMM_WRITE_MRT], 1));
|
||||||
furi_string_cat_printf(
|
furi_string_cat_printf(
|
||||||
temp_str,
|
temp_str,
|
||||||
"- Other: %" PRIuLEAST32 "us\n\n",
|
"- Other: %" PRIuLEAST32 "us\n\n",
|
||||||
felica_estimate_timing_us(nfc_data->f_data.pmm[7], 0));
|
felica_estimate_timing_us(nfc_data->f_data.pmm[FELICA_PMM_OTHER_MRT], 0));
|
||||||
|
|
||||||
furi_string_cat_printf(temp_str, "IDm:");
|
furi_string_cat_printf(temp_str, "IDm:");
|
||||||
for(size_t i = 0; i < nfc_data->uid_len; i++) {
|
for(size_t i = 0; i < nfc_data->uid_len; i++) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ enum SubmenuIndex {
|
|||||||
SubmenuIndexReadEMV,
|
SubmenuIndexReadEMV,
|
||||||
SubmenuIndexReadNFCA,
|
SubmenuIndexReadNFCA,
|
||||||
SubmenuIndexReadFelica,
|
SubmenuIndexReadFelica,
|
||||||
|
SubmenuIndexReadNFCF,
|
||||||
};
|
};
|
||||||
|
|
||||||
void nfc_scene_read_card_type_submenu_callback(void* context, uint32_t index) {
|
void nfc_scene_read_card_type_submenu_callback(void* context, uint32_t index) {
|
||||||
@@ -56,6 +57,12 @@ void nfc_scene_read_card_type_on_enter(void* context) {
|
|||||||
SubmenuIndexReadFelica,
|
SubmenuIndexReadFelica,
|
||||||
nfc_scene_read_card_type_submenu_callback,
|
nfc_scene_read_card_type_submenu_callback,
|
||||||
nfc);
|
nfc);
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"Read NFC-F data",
|
||||||
|
SubmenuIndexReadNFCF,
|
||||||
|
nfc_scene_read_card_type_submenu_callback,
|
||||||
|
nfc);
|
||||||
uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadCardType);
|
uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadCardType);
|
||||||
submenu_set_selected_item(submenu, state);
|
submenu_set_selected_item(submenu, state);
|
||||||
|
|
||||||
@@ -97,6 +104,11 @@ bool nfc_scene_read_card_type_on_event(void* context, SceneManagerEvent event) {
|
|||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
|
if(event.event == SubmenuIndexReadNFCF) {
|
||||||
|
nfc->dev->dev_data.read_mode = NfcReadModeNFCF;
|
||||||
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
|
||||||
|
consumed = true;
|
||||||
|
}
|
||||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneReadCardType, event.event);
|
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneReadCardType, event.event);
|
||||||
}
|
}
|
||||||
return consumed;
|
return consumed;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,+,11.13,,
|
Version,+,11.14,,
|
||||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||||
Header,+,applications/services/cli/cli.h,,
|
Header,+,applications/services/cli/cli.h,,
|
||||||
Header,+,applications/services/cli/cli_vcp.h,,
|
Header,+,applications/services/cli/cli_vcp.h,,
|
||||||
@@ -808,14 +808,15 @@ Function,-,felica_get_ic_type,FelicaICType,uint8_t*
|
|||||||
Function,-,felica_get_service_name,FuriString*,FelicaService*
|
Function,-,felica_get_service_name,FuriString*,FelicaService*
|
||||||
Function,-,felica_get_system_name,FuriString*,FelicaSystem*
|
Function,-,felica_get_system_name,FuriString*,FelicaSystem*
|
||||||
Function,-,felica_lite_can_read_without_mac,_Bool,"uint8_t*, uint8_t"
|
Function,-,felica_lite_can_read_without_mac,_Bool,"uint8_t*, uint8_t"
|
||||||
|
Function,-,felica_lite_dump_data,_Bool,"FuriHalNfcTxRxContext*, FelicaReader*, FelicaData*, FelicaSystem*"
|
||||||
Function,-,felica_lite_prepare_unencrypted_read,uint8_t,"uint8_t*, const FelicaReader*, _Bool, const uint8_t*, uint8_t"
|
Function,-,felica_lite_prepare_unencrypted_read,uint8_t,"uint8_t*, const FelicaReader*, _Bool, const uint8_t*, uint8_t"
|
||||||
Function,-,felica_lite_prepare_unencrypted_write,uint8_t,"uint8_t*, const FelicaReader*, const uint8_t*, uint8_t, const uint8_t*"
|
Function,-,felica_lite_prepare_unencrypted_write,uint8_t,"uint8_t*, const FelicaReader*, const uint8_t*, uint8_t, const uint8_t*"
|
||||||
Function,-,felica_parse_unencrypted_read,uint16_t,"uint8_t*, uint8_t, FelicaReader*, uint8_t*, uint16_t"
|
Function,-,felica_parse_unencrypted_read,uint16_t,"uint8_t*, uint8_t, FelicaReader*, uint8_t*, uint16_t"
|
||||||
Function,-,felica_parse_unencrypted_write,_Bool,"uint8_t*, uint8_t, FelicaReader*"
|
Function,-,felica_parse_unencrypted_write,_Bool,"uint8_t*, uint8_t, FelicaReader*"
|
||||||
Function,-,felica_prepare_unencrypted_read,uint8_t,"uint8_t*, const FelicaReader*, const uint16_t*, uint8_t, const uint32_t*, uint8_t"
|
Function,-,felica_prepare_unencrypted_read,uint8_t,"uint8_t*, const FelicaReader*, const uint16_t*, uint8_t, const uint32_t*, uint8_t"
|
||||||
Function,-,felica_prepare_unencrypted_write,uint8_t,"uint8_t*, FelicaReader*, const uint16_t*, uint8_t, const uint32_t*, uint8_t, const uint8_t*"
|
Function,-,felica_prepare_unencrypted_write,uint8_t,"uint8_t*, FelicaReader*, const uint16_t*, uint8_t, const uint32_t*, uint8_t, const uint8_t*"
|
||||||
|
Function,-,felica_push_normal_block,void,"FelicaService*, uint8_t*"
|
||||||
Function,-,felica_read_card,_Bool,"FuriHalNfcTxRxContext*, FelicaData*, uint8_t*, uint8_t*"
|
Function,-,felica_read_card,_Bool,"FuriHalNfcTxRxContext*, FelicaData*, uint8_t*, uint8_t*"
|
||||||
Function,-,felica_read_lite_system,_Bool,"FuriHalNfcTxRxContext*, FelicaReader*, FelicaData*, FelicaSystem*"
|
|
||||||
Function,-,feof,int,FILE*
|
Function,-,feof,int,FILE*
|
||||||
Function,-,feof_unlocked,int,FILE*
|
Function,-,feof_unlocked,int,FILE*
|
||||||
Function,-,ferror,int,FILE*
|
Function,-,ferror,int,FILE*
|
||||||
|
|||||||
|
@@ -63,6 +63,7 @@ typedef enum {
|
|||||||
NfcReadModeEMV,
|
NfcReadModeEMV,
|
||||||
NfcReadModeNFCA,
|
NfcReadModeNFCA,
|
||||||
NfcReadModeFelica,
|
NfcReadModeFelica,
|
||||||
|
NfcReadModeNFCF,
|
||||||
} NfcReadMode;
|
} NfcReadMode;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -508,6 +508,10 @@ void nfc_worker_read_type(NfcWorker* nfc_worker) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if(read_mode == NfcReadModeNFCF) {
|
||||||
|
nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown;
|
||||||
|
event = NfcWorkerEventReadUidNfcF;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -151,6 +151,55 @@ FelicaICType felica_get_ic_type(uint8_t* PMm) {
|
|||||||
return FelicaICType2K;
|
return FelicaICType2K;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Parse common FeliCa response headers.
|
||||||
|
*
|
||||||
|
* This parses and validates the most commonly occurring response header types.
|
||||||
|
*
|
||||||
|
* The header needs to match the (length, res, idm) format, and also (sf1, sf2) when always_succeed
|
||||||
|
* is set to false.
|
||||||
|
*
|
||||||
|
* @param buf RX buffer.
|
||||||
|
* @param len RX buffer length.
|
||||||
|
* @param reader The FeliCa reader context.
|
||||||
|
* @param expected_resp Expected response code. Must be an odd number.
|
||||||
|
* @param always_succeed When set to true, skip status flags (sf1 and sf2) parsing.
|
||||||
|
* @return The number of bytes parsed, or 0 when response is invalid or status flags are set.
|
||||||
|
*/
|
||||||
|
static uint8_t felica_consume_header(
|
||||||
|
uint8_t* buf,
|
||||||
|
uint8_t len,
|
||||||
|
FelicaReader* reader,
|
||||||
|
uint8_t expected_resp,
|
||||||
|
bool always_succeed) {
|
||||||
|
furi_assert(expected_resp & 1);
|
||||||
|
furi_assert(buf != NULL);
|
||||||
|
furi_assert(reader != NULL);
|
||||||
|
|
||||||
|
uint8_t header_size = always_succeed ? 10 : 12;
|
||||||
|
if(len < header_size) {
|
||||||
|
FURI_LOG_E(TAG, "Malformed header: too short.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(buf[1] != expected_resp) {
|
||||||
|
FURI_LOG_E(TAG, "Expecting %u, got %u.", expected_resp, buf[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(memcmp(&buf[2], reader->current_idm, 8) != 0) {
|
||||||
|
FURI_LOG_E(TAG, "IDm mismatch.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(always_succeed) {
|
||||||
|
reader->status_flags[0] = buf[10];
|
||||||
|
reader->status_flags[1] = buf[11];
|
||||||
|
if(reader->status_flags[0] != 0 || reader->status_flags[1] != 0) {
|
||||||
|
FURI_LOG_W(
|
||||||
|
TAG, "SF1: %02X SF2: %02X", reader->status_flags[0], reader->status_flags[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return header_size;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t felica_prepare_unencrypted_read(
|
uint8_t felica_prepare_unencrypted_read(
|
||||||
uint8_t* dest,
|
uint8_t* dest,
|
||||||
const FelicaReader* reader,
|
const FelicaReader* reader,
|
||||||
@@ -212,32 +261,12 @@ uint16_t felica_parse_unencrypted_read(
|
|||||||
FelicaReader* reader,
|
FelicaReader* reader,
|
||||||
uint8_t* out,
|
uint8_t* out,
|
||||||
uint16_t out_len) {
|
uint16_t out_len) {
|
||||||
if(len < 12) {
|
uint8_t consumed = felica_consume_header(buf, len, reader, FELICA_UNENCRYPTED_READ_RES, false);
|
||||||
return false;
|
if(!consumed) {
|
||||||
}
|
|
||||||
len--;
|
|
||||||
buf++;
|
|
||||||
|
|
||||||
if(*buf != FELICA_UNENCRYPTED_READ_RES) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
len--;
|
|
||||||
buf++;
|
|
||||||
|
|
||||||
if(memcmp(buf, reader->current_idm, 8) != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
len -= 8;
|
|
||||||
buf += 8;
|
|
||||||
|
|
||||||
reader->status_flags[0] = buf[0];
|
|
||||||
reader->status_flags[1] = buf[1];
|
|
||||||
len -= 2;
|
|
||||||
buf += 2;
|
|
||||||
if(reader->status_flags[0] != 0) {
|
|
||||||
FURI_LOG_W(TAG, "SF1: %02X SF2: %02X", reader->status_flags[0], reader->status_flags[1]);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
len -= consumed;
|
||||||
|
buf += consumed;
|
||||||
|
|
||||||
if(len < 1) {
|
if(len < 1) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -315,48 +344,77 @@ uint8_t felica_lite_prepare_unencrypted_write(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool felica_parse_unencrypted_write(uint8_t* buf, uint8_t len, FelicaReader* reader) {
|
bool felica_parse_unencrypted_write(uint8_t* buf, uint8_t len, FelicaReader* reader) {
|
||||||
if(len < 12) {
|
uint8_t consumed =
|
||||||
|
felica_consume_header(buf, len, reader, FELICA_UNENCRYPTED_WRITE_RES, false);
|
||||||
|
if(!consumed) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t felica_prepare_request_system_code(uint8_t* dest, FelicaReader* reader) {
|
||||||
|
dest[0] = FELICA_REQUEST_SYSTEM_CODE_CMD;
|
||||||
|
memcpy(&dest[1], reader->current_idm, 8);
|
||||||
|
return 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool felica_parse_request_system_code(
|
||||||
|
uint8_t* buf,
|
||||||
|
uint8_t len,
|
||||||
|
FelicaReader* reader,
|
||||||
|
FelicaSystemArray_t* systems) {
|
||||||
|
uint8_t consumed =
|
||||||
|
felica_consume_header(buf, len, reader, FELICA_REQUEST_SYSTEM_CODE_RES, true);
|
||||||
|
if(consumed == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
len -= consumed;
|
||||||
|
buf += consumed;
|
||||||
|
|
||||||
|
uint8_t entries = *buf;
|
||||||
len--;
|
len--;
|
||||||
buf++;
|
buf++;
|
||||||
|
|
||||||
if(*buf != FELICA_UNENCRYPTED_WRITE_RES) {
|
if(len < 2 * entries) {
|
||||||
|
FURI_LOG_E(TAG, "FELICA_REQUEST_SYSTEM_CODE_RES: Response too short");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
len--;
|
|
||||||
buf++;
|
|
||||||
|
|
||||||
if(memcmp(buf, reader->current_idm, 8) != 0) {
|
for(uint8_t idx = 0; idx < entries; idx++) {
|
||||||
return false;
|
FelicaSystem* system = FelicaSystemArray_push_new(*systems);
|
||||||
}
|
furi_assert(system != NULL);
|
||||||
len -= 8;
|
|
||||||
buf += 8;
|
|
||||||
|
|
||||||
reader->status_flags[0] = buf[0];
|
// Set system code
|
||||||
reader->status_flags[1] = buf[1];
|
system->number = idx;
|
||||||
len -= 2;
|
system->code = buf[2 * idx] | (buf[2 * idx + 1] << 8);
|
||||||
buf += 2;
|
|
||||||
if(reader->status_flags[0] != 0) {
|
FURI_LOG_D(TAG, "Found system code %04X", system->code);
|
||||||
FURI_LOG_W(TAG, "SF1: %02X SF2: %02X", reader->status_flags[0], reader->status_flags[1]);
|
|
||||||
return 0;
|
// Fill in IDm and PMm
|
||||||
|
memcpy(system->idm, reader->current_idm, 8);
|
||||||
|
memcpy(system->pmm, reader->current_pmm, 8);
|
||||||
|
|
||||||
|
// Set system index field in IDm
|
||||||
|
system->idm[0] &= 0x0f;
|
||||||
|
system->idm[0] |= ((idx & 0xf) << 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void felica_parse_system_info(FelicaSystem* system, uint8_t* IDm, uint8_t* PMm) {
|
static FelicaSystem* felica_gen_monolithic_system_code(
|
||||||
memcpy(system->idm, IDm, 8);
|
FelicaReader* reader,
|
||||||
memcpy(system->pmm, PMm, 8);
|
FelicaSystemArray_t* systems,
|
||||||
for(int i = 0; i < 6; i++) {
|
uint16_t system_code) {
|
||||||
char MRT_byte = PMm[2 + i];
|
FelicaSystem* system = FelicaSystemArray_push_new(*systems);
|
||||||
FelicaMRTParts* mrt_data = &system->maximum_response_times[i];
|
furi_assert(reader != NULL);
|
||||||
mrt_data->real_a = (MRT_byte & 7) + 1;
|
furi_assert(system != NULL);
|
||||||
MRT_byte >>= 3;
|
|
||||||
mrt_data->real_b = (MRT_byte & 7) + 1;
|
memcpy(system->idm, reader->current_idm, 8);
|
||||||
MRT_byte >>= 3;
|
memcpy(system->pmm, reader->current_pmm, 8);
|
||||||
mrt_data->exponent = (MRT_byte & 3);
|
system->code = system_code;
|
||||||
}
|
|
||||||
|
return system;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool felica_lite_can_read_without_mac(uint8_t* mc_r_restr, uint8_t block_number) {
|
bool felica_lite_can_read_without_mac(uint8_t* mc_r_restr, uint8_t block_number) {
|
||||||
@@ -368,12 +426,16 @@ bool felica_lite_can_read_without_mac(uint8_t* mc_r_restr, uint8_t block_number)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void felica_define_normal_block(FelicaService* service, uint16_t number, uint8_t* data) {
|
void felica_define_normal_block(FelicaService* service, uint16_t number, uint8_t* data) {
|
||||||
FelicaBlock* block = malloc(sizeof(FelicaBlock));
|
FelicaBlock* block = FelicaBlockArray_safe_get(service->blocks, number);
|
||||||
memcpy(block->data, data, FELICA_BLOCK_SIZE);
|
memcpy(block->data, data, FELICA_BLOCK_SIZE);
|
||||||
FelicaBlockList_set_at(service->blocks, number, block);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool felica_read_lite_system(
|
void felica_push_normal_block(FelicaService* service, uint8_t* data) {
|
||||||
|
FelicaBlock* block = FelicaBlockArray_push_new(service->blocks);
|
||||||
|
memcpy(block->data, data, FELICA_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool felica_lite_dump_data(
|
||||||
FuriHalNfcTxRxContext* tx_rx,
|
FuriHalNfcTxRxContext* tx_rx,
|
||||||
FelicaReader* reader,
|
FelicaReader* reader,
|
||||||
FelicaData* data,
|
FelicaData* data,
|
||||||
@@ -425,8 +487,6 @@ bool felica_read_lite_system(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
system->code = LITE_SYSTEM_CODE;
|
|
||||||
|
|
||||||
FelicaLiteInfo* lite_info = &system->lite_info;
|
FelicaLiteInfo* lite_info = &system->lite_info;
|
||||||
lite_info->card_key_1 = NULL;
|
lite_info->card_key_1 = NULL;
|
||||||
lite_info->card_key_2 = NULL;
|
lite_info->card_key_2 = NULL;
|
||||||
@@ -568,6 +628,22 @@ bool felica_read_lite_system(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool felica_std_request_system_code(
|
||||||
|
FuriHalNfcTxRxContext* tx_rx,
|
||||||
|
FelicaReader* reader,
|
||||||
|
FelicaSystemArray_t* systems) {
|
||||||
|
tx_rx->tx_bits = 8 * felica_prepare_request_system_code(tx_rx->tx_data, reader);
|
||||||
|
if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
|
||||||
|
FURI_LOG_E(TAG, "Bad exchange requesting system code");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!felica_parse_request_system_code(tx_rx->rx_data, tx_rx->rx_bits / 8, reader, systems)) {
|
||||||
|
FURI_LOG_E(TAG, "Bad response to Request System Code command");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool felica_read_card(
|
bool felica_read_card(
|
||||||
FuriHalNfcTxRxContext* tx_rx,
|
FuriHalNfcTxRxContext* tx_rx,
|
||||||
FelicaData* data,
|
FelicaData* data,
|
||||||
@@ -583,31 +659,24 @@ bool felica_read_card(
|
|||||||
memcpy(reader.current_idm, polled_idm, 8);
|
memcpy(reader.current_idm, polled_idm, 8);
|
||||||
memcpy(reader.current_pmm, polled_pmm, 8);
|
memcpy(reader.current_pmm, polled_pmm, 8);
|
||||||
|
|
||||||
FelicaSystem* current_system = malloc(sizeof(FelicaSystem));
|
FelicaSystemArray_init(data->systems);
|
||||||
FelicaSystemList_init(data->systems);
|
|
||||||
FelicaSystemList_push_back(data->systems, current_system);
|
|
||||||
|
|
||||||
felica_parse_system_info(current_system, polled_idm, polled_pmm);
|
|
||||||
|
|
||||||
if(data->type == FelicaICTypeLite || data->type == FelicaICTypeLiteS) {
|
if(data->type == FelicaICTypeLite || data->type == FelicaICTypeLiteS) {
|
||||||
FURI_LOG_I(TAG, "Reading Felica Lite system");
|
FURI_LOG_I(TAG, "Reading Felica Lite system");
|
||||||
felica_read_lite_system(tx_rx, &reader, data, current_system);
|
FelicaSystem* lite_system =
|
||||||
|
felica_gen_monolithic_system_code(&reader, &(data->systems), LITE_SYSTEM_CODE);
|
||||||
|
felica_lite_dump_data(tx_rx, &reader, data, lite_system);
|
||||||
card_read = true;
|
card_read = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
FURI_LOG_I(TAG, "Reading Felica Standard system");
|
||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
return card_read;
|
return card_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
void felica_service_clear(FelicaService* service) {
|
void felica_service_clear(FelicaService* service) {
|
||||||
FelicaBlockList_it_t it;
|
FelicaBlockArray_clear(service->blocks);
|
||||||
for(FelicaBlockList_it(it, service->blocks); !FelicaBlockList_end_p(it);
|
|
||||||
FelicaBlockList_next(it)) {
|
|
||||||
FelicaBlock* block = *FelicaBlockList_ref(it);
|
|
||||||
free(block);
|
|
||||||
}
|
|
||||||
FelicaBlockList_clear(service->blocks);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void felica_lite_clear(FelicaLiteInfo* lite_info) {
|
void felica_lite_clear(FelicaLiteInfo* lite_info) {
|
||||||
@@ -630,31 +699,33 @@ void felica_lite_clear(FelicaLiteInfo* lite_info) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void felica_node_clear(FelicaNode* node);
|
||||||
|
|
||||||
void felica_area_clear(FelicaArea* area) {
|
void felica_area_clear(FelicaArea* area) {
|
||||||
FelicaNodeList_it_t it;
|
for
|
||||||
for(FelicaNodeList_it(it, area->nodes); !FelicaNodeList_end_p(it); FelicaNodeList_next(it)) {
|
M_EACH(node, area->nodes, FelicaNodeArray_t) {
|
||||||
FelicaNode* node = *FelicaNodeList_ref(it);
|
felica_node_clear(node);
|
||||||
|
}
|
||||||
|
FelicaNodeArray_clear(area->nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void felica_node_clear(FelicaNode* node) {
|
||||||
if(node->type == FelicaNodeTypeArea) {
|
if(node->type == FelicaNodeTypeArea) {
|
||||||
felica_area_clear(node->area);
|
felica_area_clear(node->area);
|
||||||
} else if(node->type == FelicaNodeTypeService) {
|
} else if(node->type == FelicaNodeTypeService) {
|
||||||
felica_service_clear(node->service);
|
felica_service_clear(node->service);
|
||||||
}
|
}
|
||||||
free(node);
|
|
||||||
}
|
|
||||||
FelicaNodeList_clear(area->nodes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void felica_clear(FelicaData* data) {
|
void felica_clear(FelicaData* data) {
|
||||||
FelicaSystemList_it_t it;
|
for
|
||||||
for(FelicaSystemList_it(it, data->systems); !FelicaSystemList_end_p(it);
|
M_EACH(system, data->systems, FelicaSystemArray_t) {
|
||||||
FelicaSystemList_next(it)) {
|
|
||||||
FelicaSystem* system = *FelicaSystemList_ref(it);
|
|
||||||
if(system->code == LITE_SYSTEM_CODE) {
|
if(system->code == LITE_SYSTEM_CODE) {
|
||||||
felica_lite_clear(&system->lite_info);
|
felica_lite_clear(&system->lite_info);
|
||||||
;
|
|
||||||
} else {
|
} else {
|
||||||
felica_area_clear(&system->root_area);
|
felica_node_clear(&system->root);
|
||||||
|
FelicaPublicServiceDict_clear(system->public_services);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FelicaSystemList_clear(data->systems);
|
FelicaSystemArray_clear(data->systems);
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,8 @@
|
|||||||
#define MRT_T_SIG_x16 4833038.24 //ns, MRT_T_SIG * (4 ** 2)
|
#define MRT_T_SIG_x16 4833038.24 //ns, MRT_T_SIG * (4 ** 2)
|
||||||
#define MRT_T_SIG_x64 19332152.96 //ns, MRT_T_SIG * (4 ** 2)
|
#define MRT_T_SIG_x64 19332152.96 //ns, MRT_T_SIG * (4 ** 2)
|
||||||
|
|
||||||
|
#define FELICA_PMM_MRT_BASE 2
|
||||||
|
|
||||||
#define FELICA_VARIABLE_MRT 0
|
#define FELICA_VARIABLE_MRT 0
|
||||||
#define FELICA_FIXED_MRT 1
|
#define FELICA_FIXED_MRT 1
|
||||||
#define FELICA_MUTUAL_AUTH_MRT 2
|
#define FELICA_MUTUAL_AUTH_MRT 2
|
||||||
@@ -17,6 +19,13 @@
|
|||||||
#define FELICA_WRITE_MRT 4
|
#define FELICA_WRITE_MRT 4
|
||||||
#define FELICA_OTHER_MRT 5
|
#define FELICA_OTHER_MRT 5
|
||||||
|
|
||||||
|
#define FELICA_PMM_VARIABLE_MRT (FELICA_PMM_MRT_BASE + FELICA_VARIABLE_MRT)
|
||||||
|
#define FELICA_PMM_FIXED_MRT (FELICA_PMM_MRT_BASE + FELICA_FIXED_MRT)
|
||||||
|
#define FELICA_PMM_MUTUAL_AUTH_MRT (FELICA_PMM_MRT_BASE + FELICA_MUTUAL_AUTH_MRT)
|
||||||
|
#define FELICA_PMM_READ_MRT (FELICA_PMM_MRT_BASE + FELICA_READ_MRT)
|
||||||
|
#define FELICA_PMM_WRITE_MRT (FELICA_PMM_MRT_BASE + FELICA_WRITE_MRT)
|
||||||
|
#define FELICA_PMM_OTHER_MRT (FELICA_PMM_MRT_BASE + FELICA_OTHER_MRT)
|
||||||
|
|
||||||
#define FELICA_BLOCK_SIZE 16
|
#define FELICA_BLOCK_SIZE 16
|
||||||
|
|
||||||
#define CYBERNET_SYSTEM_CODE 0x0003
|
#define CYBERNET_SYSTEM_CODE 0x0003
|
||||||
@@ -55,9 +64,13 @@
|
|||||||
|
|
||||||
#define FELICA_UNENCRYPTED_READ_CMD 0x06
|
#define FELICA_UNENCRYPTED_READ_CMD 0x06
|
||||||
#define FELICA_UNENCRYPTED_WRITE_CMD 0x08
|
#define FELICA_UNENCRYPTED_WRITE_CMD 0x08
|
||||||
|
#define FELICA_SEARCH_SERVICE_CODE_CMD 0x0a
|
||||||
|
#define FELICA_REQUEST_SYSTEM_CODE_CMD 0x0c
|
||||||
|
|
||||||
#define FELICA_UNENCRYPTED_READ_RES 0x07
|
#define FELICA_UNENCRYPTED_READ_RES 0x07
|
||||||
#define FELICA_UNENCRYPTED_WRITE_RES 0x09
|
#define FELICA_UNENCRYPTED_WRITE_RES 0x09
|
||||||
|
#define FELICA_SEARCH_SERVICE_CODE_RES 0x0b
|
||||||
|
#define FELICA_REQUEST_SYSTEM_CODE_RES 0x0d
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FelicaICTypeRC_SA24_10K, // RC-SA24/1x
|
FelicaICTypeRC_SA24_10K, // RC-SA24/1x
|
||||||
@@ -88,13 +101,6 @@ typedef enum {
|
|||||||
FelicaICTypeSuica, // https://www.tuv-nederland.nl/assets/files/cerfiticaten/2019/07/cr-nscib-cc-10-30076-cr.pdf
|
FelicaICTypeSuica, // https://www.tuv-nederland.nl/assets/files/cerfiticaten/2019/07/cr-nscib-cc-10-30076-cr.pdf
|
||||||
} FelicaICType;
|
} FelicaICType;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t exponent : 2;
|
|
||||||
// Incremented at read
|
|
||||||
uint8_t real_a : 4;
|
|
||||||
uint8_t real_b : 4;
|
|
||||||
} FelicaMRTParts;
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FelicaServiceTypeRandom = (0b0010 << 2),
|
FelicaServiceTypeRandom = (0b0010 << 2),
|
||||||
FelicaServiceTypeCyclic = (0b0011 << 2),
|
FelicaServiceTypeCyclic = (0b0011 << 2),
|
||||||
@@ -121,20 +127,22 @@ DICT_SET_DEF(
|
|||||||
FelicaServiceAttribute,
|
FelicaServiceAttribute,
|
||||||
M_ENUM_OPLIST(FelicaServiceAttribute, FelicaServiceAttributeAuthRW))
|
M_ENUM_OPLIST(FelicaServiceAttribute, FelicaServiceAttributeAuthRW))
|
||||||
|
|
||||||
typedef FelicaMRTParts FelicaMRTParameters[6];
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t data[FELICA_BLOCK_SIZE];
|
uint8_t data[FELICA_BLOCK_SIZE];
|
||||||
} FelicaBlock;
|
} FelicaBlock;
|
||||||
|
|
||||||
ARRAY_DEF(FelicaBlockList, FelicaBlock*, M_PTR_OPLIST)
|
// TODO properly remove this
|
||||||
|
//ARRAY_DEF(FelicaBlockList, FelicaBlock*, M_PTR_OPLIST)
|
||||||
|
ARRAY_DEF(FelicaBlockArray, FelicaBlock, M_POD_OPLIST)
|
||||||
|
#define M_OPL_FelicaBlockArray_t() ARRAY_OPLIST(FelicaBlockArray, M_POD_OPLIST)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t number;
|
uint16_t number;
|
||||||
FelicaServiceAttributeList_t access_control_list; // accounts for overlap services
|
FelicaServiceAttributeList_t access_control_list; // accounts for overlap services
|
||||||
bool is_extended_overlap;
|
bool is_extended_overlap; // We don't know much about this currently. will always be false
|
||||||
union {
|
union {
|
||||||
FelicaBlockList_t blocks;
|
// TODO change this to use FelicaBlockArray_t
|
||||||
|
FelicaBlockArray_t blocks;
|
||||||
struct {
|
struct {
|
||||||
uint16_t overlap_target;
|
uint16_t overlap_target;
|
||||||
uint8_t block_start;
|
uint8_t block_start;
|
||||||
@@ -149,23 +157,44 @@ typedef enum {
|
|||||||
} FelicaNodeType;
|
} FelicaNodeType;
|
||||||
|
|
||||||
struct _FelicaArea_t;
|
struct _FelicaArea_t;
|
||||||
typedef struct {
|
typedef struct _FelicaArea_t FelicaArea;
|
||||||
|
|
||||||
|
struct _FelicaNode_s;
|
||||||
|
typedef struct _FelicaNode_s FelicaNode;
|
||||||
|
|
||||||
|
struct _FelicaNode_s {
|
||||||
|
/** Node type. */
|
||||||
FelicaNodeType type;
|
FelicaNodeType type;
|
||||||
|
/** Borrowed pointer to its parent node. */
|
||||||
|
FelicaNode* parent;
|
||||||
union {
|
union {
|
||||||
struct _FelicaArea_t* area;
|
/** (Area/dir type only) The area struct. */
|
||||||
|
FelicaArea* area;
|
||||||
|
/** (Service/file type only) The service struct. */
|
||||||
FelicaService* service;
|
FelicaService* service;
|
||||||
};
|
};
|
||||||
} FelicaNode;
|
};
|
||||||
|
|
||||||
ARRAY_DEF(FelicaNodeList, FelicaNode*, M_PTR_OPLIST)
|
// TODO properly remove this
|
||||||
|
//ARRAY_DEF(FelicaNodeList, FelicaNode*, M_PTR_OPLIST)
|
||||||
|
ARRAY_DEF(FelicaNodeArray, FelicaNode, M_POD_OPLIST)
|
||||||
|
#define M_OPL_FelicaNodeArray_t() ARRAY_OPLIST(FelicaNodeArray, M_POD_OPLIST)
|
||||||
|
|
||||||
typedef struct _FelicaArea_t {
|
ARRAY_DEF(FelicaNodeRefArray, FelicaNode*, M_PTR_OPLIST)
|
||||||
|
#define M_OPL_FelicaNodeRefArray_t() ARRAY_OPLIST(FelicaNodeRefArray, M_PTR_OPLIST)
|
||||||
|
|
||||||
|
// { service_number: service_ptr_in_tree }
|
||||||
|
DICT_DEF2(FelicaPublicServiceDict, uint16_t, M_DEFAULT_OPLIST, FelicaService*, M_PTR_OPLIST)
|
||||||
|
#define M_OPL_FelicaPublicServiceDict_t() \
|
||||||
|
DICT_OPLIST(FelicaPublicServiceDict, M_DEFAULT_OPLIST, M_PTR_OPLIST)
|
||||||
|
|
||||||
|
struct _FelicaArea_t {
|
||||||
uint16_t number;
|
uint16_t number;
|
||||||
bool can_create_subareas;
|
bool can_create_subareas;
|
||||||
uint16_t end_service_code;
|
uint16_t end_service_code;
|
||||||
|
|
||||||
FelicaNodeList_t nodes;
|
FelicaNodeArray_t nodes;
|
||||||
} FelicaArea;
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t* S_PAD[14];
|
uint8_t* S_PAD[14];
|
||||||
@@ -186,24 +215,39 @@ typedef struct {
|
|||||||
} FelicaLiteInfo;
|
} FelicaLiteInfo;
|
||||||
|
|
||||||
typedef struct _FelicaSystem_t {
|
typedef struct _FelicaSystem_t {
|
||||||
|
/** FeliCa system index. */
|
||||||
uint8_t number;
|
uint8_t number;
|
||||||
|
/** If the system belongs to a FeliCa Lite (and be its only system). */
|
||||||
|
bool is_lite;
|
||||||
|
/** FeliCa system code. */
|
||||||
uint16_t code;
|
uint16_t code;
|
||||||
|
/** System IDm with system index bitfield properly set. */
|
||||||
uint8_t idm[8];
|
uint8_t idm[8];
|
||||||
|
/** Cached card PMm. */
|
||||||
uint8_t pmm[8];
|
uint8_t pmm[8];
|
||||||
FelicaMRTParameters maximum_response_times;
|
|
||||||
|
|
||||||
union {
|
union {
|
||||||
|
/** (For FeliCa Lite only) Card content. */
|
||||||
FelicaLiteInfo lite_info;
|
FelicaLiteInfo lite_info;
|
||||||
FelicaArea root_area;
|
struct {
|
||||||
|
/** (For FeliCa Standard only) The root of the raw filesystem tree. */
|
||||||
|
FelicaNode root;
|
||||||
|
/** (For FeliCa Standard only) Shortcut for all publicly accessible services for quick
|
||||||
|
* access by card parsers. */
|
||||||
|
FelicaPublicServiceDict_t public_services;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
} FelicaSystem;
|
} FelicaSystem;
|
||||||
|
|
||||||
ARRAY_DEF(FelicaSystemList, FelicaSystem*, M_PTR_OPLIST)
|
// TODO properly remove this
|
||||||
|
//ARRAY_DEF(FelicaSystemList, FelicaSystem*, M_PTR_OPLIST)
|
||||||
|
ARRAY_DEF(FelicaSystemArray, FelicaSystem, M_POD_OPLIST)
|
||||||
|
#define M_OPL_FelicaSystemArray_t() ARRAY_OPLIST(FelicaSystemArray, M_POD_OPLIST)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
FelicaICType type;
|
FelicaICType type;
|
||||||
uint8_t subtype;
|
uint8_t subtype;
|
||||||
FelicaSystemList_t systems;
|
FelicaSystemArray_t systems;
|
||||||
} FelicaData;
|
} FelicaData;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -255,8 +299,17 @@ bool felica_parse_unencrypted_write(uint8_t* buf, uint8_t len, FelicaReader* rea
|
|||||||
bool felica_lite_can_read_without_mac(uint8_t* mc_r_restr, uint8_t block_number);
|
bool felica_lite_can_read_without_mac(uint8_t* mc_r_restr, uint8_t block_number);
|
||||||
|
|
||||||
void felica_define_normal_block(FelicaService* service, uint16_t number, uint8_t* data);
|
void felica_define_normal_block(FelicaService* service, uint16_t number, uint8_t* data);
|
||||||
|
void felica_push_normal_block(FelicaService* service, uint8_t* data);
|
||||||
|
|
||||||
bool felica_read_lite_system(
|
/** Dump a FeliCa Lite or Lite-S tag.
|
||||||
|
*
|
||||||
|
* @param tx_rx NFC context.
|
||||||
|
* @param reader FeliCa reader context.
|
||||||
|
* @param data Output data object.
|
||||||
|
* @param system FeliCa system description.
|
||||||
|
* @return true if successful.
|
||||||
|
*/
|
||||||
|
bool felica_lite_dump_data(
|
||||||
FuriHalNfcTxRxContext* tx_rx,
|
FuriHalNfcTxRxContext* tx_rx,
|
||||||
FelicaReader* reader,
|
FelicaReader* reader,
|
||||||
FelicaData* data,
|
FelicaData* data,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
static const uint32_t TIME_CONSTANT_US = 302;
|
static const uint32_t TIME_CONSTANT_US = 302;
|
||||||
|
|
||||||
|
// TODO move this to felica.c
|
||||||
uint_least32_t felica_estimate_timing_us(uint_least8_t timing, uint_least8_t units) {
|
uint_least32_t felica_estimate_timing_us(uint_least8_t timing, uint_least8_t units) {
|
||||||
uint_least32_t base_cost_factor = 1 + (timing & 0x7);
|
uint_least32_t base_cost_factor = 1 + (timing & 0x7);
|
||||||
uint_least32_t unit_cost_factor = 1 + ((timing >> 3) & 0x7);
|
uint_least32_t unit_cost_factor = 1 + ((timing >> 3) & 0x7);
|
||||||
|
|||||||
Reference in New Issue
Block a user