mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-07-01 22:08:55 -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:
@@ -63,6 +63,7 @@ typedef enum {
|
||||
NfcReadModeEMV,
|
||||
NfcReadModeNFCA,
|
||||
NfcReadModeFelica,
|
||||
NfcReadModeNFCF,
|
||||
} NfcReadMode;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -508,6 +508,10 @@ void nfc_worker_read_type(NfcWorker* nfc_worker) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if(read_mode == NfcReadModeNFCF) {
|
||||
nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown;
|
||||
event = NfcWorkerEventReadUidNfcF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
+161
-90
@@ -151,6 +151,55 @@ FelicaICType felica_get_ic_type(uint8_t* PMm) {
|
||||
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* dest,
|
||||
const FelicaReader* reader,
|
||||
@@ -212,32 +261,12 @@ uint16_t felica_parse_unencrypted_read(
|
||||
FelicaReader* reader,
|
||||
uint8_t* out,
|
||||
uint16_t out_len) {
|
||||
if(len < 12) {
|
||||
return false;
|
||||
}
|
||||
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]);
|
||||
uint8_t consumed = felica_consume_header(buf, len, reader, FELICA_UNENCRYPTED_READ_RES, false);
|
||||
if(!consumed) {
|
||||
return 0;
|
||||
}
|
||||
len -= consumed;
|
||||
buf += consumed;
|
||||
|
||||
if(len < 1) {
|
||||
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) {
|
||||
if(len < 12) {
|
||||
uint8_t consumed =
|
||||
felica_consume_header(buf, len, reader, FELICA_UNENCRYPTED_WRITE_RES, false);
|
||||
if(!consumed) {
|
||||
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--;
|
||||
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;
|
||||
}
|
||||
len--;
|
||||
buf++;
|
||||
|
||||
if(memcmp(buf, reader->current_idm, 8) != 0) {
|
||||
return false;
|
||||
}
|
||||
len -= 8;
|
||||
buf += 8;
|
||||
for(uint8_t idx = 0; idx < entries; idx++) {
|
||||
FelicaSystem* system = FelicaSystemArray_push_new(*systems);
|
||||
furi_assert(system != NULL);
|
||||
|
||||
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;
|
||||
// Set system code
|
||||
system->number = idx;
|
||||
system->code = buf[2 * idx] | (buf[2 * idx + 1] << 8);
|
||||
|
||||
FURI_LOG_D(TAG, "Found system code %04X", system->code);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
void felica_parse_system_info(FelicaSystem* system, uint8_t* IDm, uint8_t* PMm) {
|
||||
memcpy(system->idm, IDm, 8);
|
||||
memcpy(system->pmm, PMm, 8);
|
||||
for(int i = 0; i < 6; i++) {
|
||||
char MRT_byte = PMm[2 + i];
|
||||
FelicaMRTParts* mrt_data = &system->maximum_response_times[i];
|
||||
mrt_data->real_a = (MRT_byte & 7) + 1;
|
||||
MRT_byte >>= 3;
|
||||
mrt_data->real_b = (MRT_byte & 7) + 1;
|
||||
MRT_byte >>= 3;
|
||||
mrt_data->exponent = (MRT_byte & 3);
|
||||
}
|
||||
static FelicaSystem* felica_gen_monolithic_system_code(
|
||||
FelicaReader* reader,
|
||||
FelicaSystemArray_t* systems,
|
||||
uint16_t system_code) {
|
||||
FelicaSystem* system = FelicaSystemArray_push_new(*systems);
|
||||
furi_assert(reader != NULL);
|
||||
furi_assert(system != NULL);
|
||||
|
||||
memcpy(system->idm, reader->current_idm, 8);
|
||||
memcpy(system->pmm, reader->current_pmm, 8);
|
||||
system->code = system_code;
|
||||
|
||||
return system;
|
||||
}
|
||||
|
||||
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) {
|
||||
FelicaBlock* block = malloc(sizeof(FelicaBlock));
|
||||
FelicaBlock* block = FelicaBlockArray_safe_get(service->blocks, number);
|
||||
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,
|
||||
FelicaReader* reader,
|
||||
FelicaData* data,
|
||||
@@ -425,8 +487,6 @@ bool felica_read_lite_system(
|
||||
return false;
|
||||
}
|
||||
|
||||
system->code = LITE_SYSTEM_CODE;
|
||||
|
||||
FelicaLiteInfo* lite_info = &system->lite_info;
|
||||
lite_info->card_key_1 = NULL;
|
||||
lite_info->card_key_2 = NULL;
|
||||
@@ -568,6 +628,22 @@ bool felica_read_lite_system(
|
||||
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(
|
||||
FuriHalNfcTxRxContext* tx_rx,
|
||||
FelicaData* data,
|
||||
@@ -583,31 +659,24 @@ bool felica_read_card(
|
||||
memcpy(reader.current_idm, polled_idm, 8);
|
||||
memcpy(reader.current_pmm, polled_pmm, 8);
|
||||
|
||||
FelicaSystem* current_system = malloc(sizeof(FelicaSystem));
|
||||
FelicaSystemList_init(data->systems);
|
||||
FelicaSystemList_push_back(data->systems, current_system);
|
||||
|
||||
felica_parse_system_info(current_system, polled_idm, polled_pmm);
|
||||
FelicaSystemArray_init(data->systems);
|
||||
|
||||
if(data->type == FelicaICTypeLite || data->type == FelicaICTypeLiteS) {
|
||||
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;
|
||||
break;
|
||||
}
|
||||
FURI_LOG_I(TAG, "Reading Felica Standard system");
|
||||
} while(false);
|
||||
|
||||
return card_read;
|
||||
}
|
||||
|
||||
void felica_service_clear(FelicaService* service) {
|
||||
FelicaBlockList_it_t it;
|
||||
for(FelicaBlockList_it(it, service->blocks); !FelicaBlockList_end_p(it);
|
||||
FelicaBlockList_next(it)) {
|
||||
FelicaBlock* block = *FelicaBlockList_ref(it);
|
||||
free(block);
|
||||
}
|
||||
FelicaBlockList_clear(service->blocks);
|
||||
FelicaBlockArray_clear(service->blocks);
|
||||
}
|
||||
|
||||
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) {
|
||||
FelicaNodeList_it_t it;
|
||||
for(FelicaNodeList_it(it, area->nodes); !FelicaNodeList_end_p(it); FelicaNodeList_next(it)) {
|
||||
FelicaNode* node = *FelicaNodeList_ref(it);
|
||||
if(node->type == FelicaNodeTypeArea) {
|
||||
felica_area_clear(node->area);
|
||||
} else if(node->type == FelicaNodeTypeService) {
|
||||
felica_service_clear(node->service);
|
||||
for
|
||||
M_EACH(node, area->nodes, FelicaNodeArray_t) {
|
||||
felica_node_clear(node);
|
||||
}
|
||||
free(node);
|
||||
FelicaNodeArray_clear(area->nodes);
|
||||
}
|
||||
|
||||
void felica_node_clear(FelicaNode* node) {
|
||||
if(node->type == FelicaNodeTypeArea) {
|
||||
felica_area_clear(node->area);
|
||||
} else if(node->type == FelicaNodeTypeService) {
|
||||
felica_service_clear(node->service);
|
||||
}
|
||||
FelicaNodeList_clear(area->nodes);
|
||||
}
|
||||
|
||||
void felica_clear(FelicaData* data) {
|
||||
FelicaSystemList_it_t it;
|
||||
for(FelicaSystemList_it(it, data->systems); !FelicaSystemList_end_p(it);
|
||||
FelicaSystemList_next(it)) {
|
||||
FelicaSystem* system = *FelicaSystemList_ref(it);
|
||||
if(system->code == LITE_SYSTEM_CODE) {
|
||||
felica_lite_clear(&system->lite_info);
|
||||
;
|
||||
} else {
|
||||
felica_area_clear(&system->root_area);
|
||||
for
|
||||
M_EACH(system, data->systems, FelicaSystemArray_t) {
|
||||
if(system->code == LITE_SYSTEM_CODE) {
|
||||
felica_lite_clear(&system->lite_info);
|
||||
} else {
|
||||
felica_node_clear(&system->root);
|
||||
FelicaPublicServiceDict_clear(system->public_services);
|
||||
}
|
||||
}
|
||||
}
|
||||
FelicaSystemList_clear(data->systems);
|
||||
FelicaSystemArray_clear(data->systems);
|
||||
}
|
||||
+77
-24
@@ -10,6 +10,8 @@
|
||||
#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 FELICA_PMM_MRT_BASE 2
|
||||
|
||||
#define FELICA_VARIABLE_MRT 0
|
||||
#define FELICA_FIXED_MRT 1
|
||||
#define FELICA_MUTUAL_AUTH_MRT 2
|
||||
@@ -17,6 +19,13 @@
|
||||
#define FELICA_WRITE_MRT 4
|
||||
#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 CYBERNET_SYSTEM_CODE 0x0003
|
||||
@@ -55,9 +64,13 @@
|
||||
|
||||
#define FELICA_UNENCRYPTED_READ_CMD 0x06
|
||||
#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_WRITE_RES 0x09
|
||||
#define FELICA_SEARCH_SERVICE_CODE_RES 0x0b
|
||||
#define FELICA_REQUEST_SYSTEM_CODE_RES 0x0d
|
||||
|
||||
typedef enum {
|
||||
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
|
||||
} FelicaICType;
|
||||
|
||||
typedef struct {
|
||||
uint8_t exponent : 2;
|
||||
// Incremented at read
|
||||
uint8_t real_a : 4;
|
||||
uint8_t real_b : 4;
|
||||
} FelicaMRTParts;
|
||||
|
||||
typedef enum {
|
||||
FelicaServiceTypeRandom = (0b0010 << 2),
|
||||
FelicaServiceTypeCyclic = (0b0011 << 2),
|
||||
@@ -121,20 +127,22 @@ DICT_SET_DEF(
|
||||
FelicaServiceAttribute,
|
||||
M_ENUM_OPLIST(FelicaServiceAttribute, FelicaServiceAttributeAuthRW))
|
||||
|
||||
typedef FelicaMRTParts FelicaMRTParameters[6];
|
||||
|
||||
typedef struct {
|
||||
uint8_t data[FELICA_BLOCK_SIZE];
|
||||
} 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 {
|
||||
uint16_t number;
|
||||
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 {
|
||||
FelicaBlockList_t blocks;
|
||||
// TODO change this to use FelicaBlockArray_t
|
||||
FelicaBlockArray_t blocks;
|
||||
struct {
|
||||
uint16_t overlap_target;
|
||||
uint8_t block_start;
|
||||
@@ -149,23 +157,44 @@ typedef enum {
|
||||
} FelicaNodeType;
|
||||
|
||||
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;
|
||||
/** Borrowed pointer to its parent node. */
|
||||
FelicaNode* parent;
|
||||
union {
|
||||
struct _FelicaArea_t* area;
|
||||
/** (Area/dir type only) The area struct. */
|
||||
FelicaArea* area;
|
||||
/** (Service/file type only) The service struct. */
|
||||
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;
|
||||
bool can_create_subareas;
|
||||
uint16_t end_service_code;
|
||||
|
||||
FelicaNodeList_t nodes;
|
||||
} FelicaArea;
|
||||
FelicaNodeArray_t nodes;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t* S_PAD[14];
|
||||
@@ -186,24 +215,39 @@ typedef struct {
|
||||
} FelicaLiteInfo;
|
||||
|
||||
typedef struct _FelicaSystem_t {
|
||||
/** FeliCa system index. */
|
||||
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;
|
||||
/** System IDm with system index bitfield properly set. */
|
||||
uint8_t idm[8];
|
||||
/** Cached card PMm. */
|
||||
uint8_t pmm[8];
|
||||
FelicaMRTParameters maximum_response_times;
|
||||
|
||||
union {
|
||||
/** (For FeliCa Lite only) Card content. */
|
||||
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;
|
||||
|
||||
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 {
|
||||
FelicaICType type;
|
||||
uint8_t subtype;
|
||||
FelicaSystemList_t systems;
|
||||
FelicaSystemArray_t systems;
|
||||
} FelicaData;
|
||||
|
||||
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);
|
||||
|
||||
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,
|
||||
FelicaReader* reader,
|
||||
FelicaData* data,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
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 base_cost_factor = 1 + (timing & 0x7);
|
||||
uint_least32_t unit_cost_factor = 1 + ((timing >> 3) & 0x7);
|
||||
|
||||
Reference in New Issue
Block a user