mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-04-29 04:09:58 -07:00
NFC: Add Felica info scenes and properly clear felica_data
This commit is contained in:
@@ -68,6 +68,87 @@ bool felica_check_ic_type(uint8_t* PMm) {
|
||||
return true;
|
||||
}
|
||||
|
||||
FelicaICType felica_get_ic_type(uint8_t* PMm) {
|
||||
uint8_t rom_type = PMm[0];
|
||||
uint8_t ic_type = PMm[1];
|
||||
|
||||
UNUSED(rom_type);
|
||||
switch(ic_type) {
|
||||
case 0xff:
|
||||
return FelicaICTypeLink;
|
||||
case 0xf2:
|
||||
return FelicaICTypeLink;
|
||||
case 0xf1:
|
||||
return FelicaICTypeLiteS;
|
||||
case 0xf0:
|
||||
return FelicaICTypeLite;
|
||||
case 0xe1:
|
||||
return FelicaICTypeLink;
|
||||
case 0xe0:
|
||||
return FelicaICTypePlug;
|
||||
case 0x48:
|
||||
return FelicaICTypeSD2_6K;
|
||||
case 0x47:
|
||||
return FelicaICTypeRC_SA24_6K;
|
||||
case 0x46:
|
||||
return FelicaICTypeSD2_4K;
|
||||
case 0x45:
|
||||
case 0x44:
|
||||
return FelicaICTypeSD2WithDES;
|
||||
case 0x3e:
|
||||
return FelicaICTypeRC_SA08;
|
||||
case 0x35:
|
||||
return FelicaICTypeSD1;
|
||||
case 0x32:
|
||||
return FelicaICTypeSD1WithDES;
|
||||
case 0x31:
|
||||
return FelicaICTypeSuica;
|
||||
case 0x20:
|
||||
return FelicaICTypeFRAM_4K;
|
||||
case 0x1f:
|
||||
case 0x1e:
|
||||
case 0x1d:
|
||||
case 0x1c:
|
||||
case 0x1b:
|
||||
case 0x1a:
|
||||
case 0x19:
|
||||
case 0x18:
|
||||
return FelicaICTypeMobileIC_V4_1;
|
||||
case 0x17:
|
||||
return FelicaICTypeMobileIC_V4;
|
||||
case 0x16:
|
||||
case 0x15:
|
||||
case 0x14:
|
||||
return FelicaICTypeMobileIC_V3;
|
||||
case 0x13:
|
||||
case 0x12:
|
||||
case 0x11:
|
||||
case 0x10:
|
||||
return FelicaICTypeMobileIC_V2;
|
||||
case 0x0d:
|
||||
return FelicaICTypeFRAM_9K;
|
||||
case 0x0c:
|
||||
return FelicaICTypeEMV_36K;
|
||||
case 0x0b: // Old Suica?
|
||||
return FelicaICTypeSuica;
|
||||
case 0x09:
|
||||
return FelicaICTypeEMV_16K;
|
||||
case 0x08:
|
||||
return FelicaICTypeEMV_32K;
|
||||
case 0x07:
|
||||
case 0x06:
|
||||
return FelicaICTypeMobileIC_V1;
|
||||
case 0x02:
|
||||
return FelicaICType576B;
|
||||
case 0x01:
|
||||
return FelicaICType4K;
|
||||
case 0x00:
|
||||
return FelicaICType2K;
|
||||
}
|
||||
|
||||
return FelicaICType2K;
|
||||
}
|
||||
|
||||
uint8_t felica_prepare_unencrypted_read(
|
||||
uint8_t* dest,
|
||||
const FelicaReader* reader,
|
||||
@@ -262,87 +343,6 @@ bool felica_parse_unencrypted_write(uint8_t* buf, uint8_t len, FelicaReader* rea
|
||||
return true;
|
||||
}
|
||||
|
||||
FelicaICType felica_get_ic_type(uint8_t* PMm) {
|
||||
uint8_t rom_type = PMm[0];
|
||||
uint8_t ic_type = PMm[1];
|
||||
|
||||
UNUSED(rom_type);
|
||||
switch(ic_type) {
|
||||
case 0xff:
|
||||
return FelicaICTypeLink;
|
||||
case 0xf2:
|
||||
return FelicaICTypeLink;
|
||||
case 0xf1:
|
||||
return FelicaICTypeLiteS;
|
||||
case 0xf0:
|
||||
return FelicaICTypeLite;
|
||||
case 0xe1:
|
||||
return FelicaICTypeLink;
|
||||
case 0xe0:
|
||||
return FelicaICTypePlug;
|
||||
case 0x48:
|
||||
return FelicaICTypeSD2_6K;
|
||||
case 0x47:
|
||||
return FelicaICTypeRC_SA24_6K;
|
||||
case 0x46:
|
||||
return FelicaICTypeSD2_4K;
|
||||
case 0x45:
|
||||
case 0x44:
|
||||
return FelicaICTypeSD2WithDES;
|
||||
case 0x3e:
|
||||
return FelicaICTypeRC_SA08;
|
||||
case 0x35:
|
||||
return FelicaICTypeSD1;
|
||||
case 0x32:
|
||||
return FelicaICTypeSD1WithDES;
|
||||
case 0x31:
|
||||
return FelicaICTypeSuica;
|
||||
case 0x20:
|
||||
return FelicaICTypeFRAM_4K;
|
||||
case 0x1f:
|
||||
case 0x1e:
|
||||
case 0x1d:
|
||||
case 0x1c:
|
||||
case 0x1b:
|
||||
case 0x1a:
|
||||
case 0x19:
|
||||
case 0x18:
|
||||
return FelicaICTypeMobileIC_V4_1;
|
||||
case 0x17:
|
||||
return FelicaICTypeMobileIC_V4;
|
||||
case 0x16:
|
||||
case 0x15:
|
||||
case 0x14:
|
||||
return FelicaICTypeMobileIC_V3;
|
||||
case 0x13:
|
||||
case 0x12:
|
||||
case 0x11:
|
||||
case 0x10:
|
||||
return FelicaICTypeMobileIC_V2;
|
||||
case 0x0d:
|
||||
return FelicaICTypeFRAM_9K;
|
||||
case 0x0c:
|
||||
return FelicaICTypeEMV_36K;
|
||||
case 0x0b: // Old Suica?
|
||||
return FelicaICTypeSuica;
|
||||
case 0x09:
|
||||
return FelicaICTypeEMV_16K;
|
||||
case 0x08:
|
||||
return FelicaICTypeEMV_32K;
|
||||
case 0x07:
|
||||
case 0x06:
|
||||
return FelicaICTypeMobileIC_V1;
|
||||
case 0x02:
|
||||
return FelicaICType576B;
|
||||
case 0x01:
|
||||
return FelicaICType4K;
|
||||
case 0x00:
|
||||
return FelicaICType2K;
|
||||
}
|
||||
|
||||
return FelicaICType2K;
|
||||
}
|
||||
|
||||
void felica_parse_system_info(FelicaSystem* system, uint8_t* IDm, uint8_t* PMm) {
|
||||
memcpy(system->idm, IDm, 8);
|
||||
memcpy(system->pmm, PMm, 8);
|
||||
@@ -369,7 +369,7 @@ void felica_define_normal_block(FelicaService* service, uint16_t number, uint8_t
|
||||
FelicaBlock* block = malloc(sizeof(FelicaBlock));
|
||||
block->type = FelicaBlockTypeNormal;
|
||||
memcpy(block->data, data, FELICA_BLOCK_SIZE);
|
||||
service->blocks[number] = block;
|
||||
FelicaBlockList_set_at(service->blocks, number, block);
|
||||
}
|
||||
|
||||
bool felica_read_lite_system(
|
||||
@@ -407,15 +407,23 @@ bool felica_read_lite_system(
|
||||
}
|
||||
system->code = LITE_SYSTEM_CODE;
|
||||
|
||||
FelicaArea* area = &system->root_area;
|
||||
FelicaService* service = malloc(sizeof(FelicaService));
|
||||
system->services = service;
|
||||
service->number = 0;
|
||||
service->block_count = CRC_CHECK_LITE_BLOCK;
|
||||
service->blocks = malloc(sizeof(FelicaBlock*) * service->block_count);
|
||||
for(int i = 0; i < service->block_count; i++) {
|
||||
service->blocks[i] = NULL;
|
||||
FelicaBlockList_init(service->blocks);
|
||||
for(int i = 0; i < CRC_CHECK_LITE_BLOCK; i++) {
|
||||
FelicaBlockList_push_back(service->blocks, NULL);
|
||||
}
|
||||
|
||||
area->number = 0;
|
||||
area->end_service_code = 0x000f;
|
||||
FelicaNodeList_init(area->nodes);
|
||||
FelicaNode* node = malloc(sizeof(node));
|
||||
node->type = FelicaNodeTypeService,
|
||||
node->ptr.service = service;
|
||||
FelicaNodeList_push_back(area->nodes, node);
|
||||
|
||||
service->number = 0;
|
||||
|
||||
felica_define_normal_block(service, SYS_CODE_LITE_BLOCK, block_data);
|
||||
|
||||
memset(block_data, 0, FELICA_BLOCK_SIZE);
|
||||
@@ -549,10 +557,10 @@ bool felica_read_card(
|
||||
memcpy(reader.current_pmm, polled_pmm, 8);
|
||||
|
||||
FelicaSystem* current_system = malloc(sizeof(FelicaSystem));
|
||||
data->systems = current_system;
|
||||
FelicaSystemList_init(data->systems);
|
||||
FelicaSystemList_push_back(data->systems, current_system);
|
||||
|
||||
felica_parse_system_info(current_system, polled_idm, polled_pmm);
|
||||
current_system->next = NULL;
|
||||
|
||||
if(data->type == FelicaICTypeLite || data->type == FelicaICTypeLiteS) {
|
||||
FURI_LOG_I(TAG, "Reading Felica Lite system");
|
||||
@@ -564,3 +572,35 @@ bool felica_read_card(
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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->ptr.area);
|
||||
} else if(node->type == FelicaNodeTypeService) {
|
||||
felica_service_clear(node->ptr.service);
|
||||
}
|
||||
free(node);
|
||||
}
|
||||
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);
|
||||
felica_area_clear(&system->root_area);
|
||||
}
|
||||
FelicaSystemList_clear(data->systems);
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi_hal_nfc.h>
|
||||
#include <m-array.h>
|
||||
|
||||
#define NFCF_F_SIG (13560000.0)
|
||||
#define MRT_T_SIG 302064.89 //ns, 256 * 16 / NFC_F_SIG * 1e9
|
||||
@@ -113,12 +114,6 @@ typedef enum {
|
||||
} FelicaMRTCommandType;
|
||||
|
||||
typedef FelicaMRTParts FelicaMRTParameters[6];
|
||||
|
||||
typedef struct {
|
||||
uint16_t number;
|
||||
uint16_t end_service_code;
|
||||
} FelicaArea;
|
||||
|
||||
typedef enum {
|
||||
FelicaBlockTypeNormal,
|
||||
FelicaBlockTypeOverlap,
|
||||
@@ -134,14 +129,37 @@ typedef struct {
|
||||
|
||||
// typedef struct {} FelicaOverlapBlock;
|
||||
|
||||
typedef struct _FelicaService_t {
|
||||
uint16_t number;
|
||||
uint16_t block_count;
|
||||
FelicaBlock** blocks;
|
||||
ARRAY_DEF(FelicaBlockList, FelicaBlock*, M_PTR_OPLIST);
|
||||
|
||||
struct _FelicaService_t* next;
|
||||
typedef struct {
|
||||
uint16_t number;
|
||||
FelicaBlockList_t blocks;
|
||||
} FelicaService;
|
||||
|
||||
typedef enum {
|
||||
FelicaNodeTypeArea,
|
||||
FelicaNodeTypeService,
|
||||
} FelicaNodeType;
|
||||
|
||||
struct _FelicaArea_t;
|
||||
typedef struct {
|
||||
FelicaNodeType type;
|
||||
union {
|
||||
struct _FelicaArea_t* area;
|
||||
FelicaService* service;
|
||||
} ptr;
|
||||
} FelicaNode;
|
||||
ARRAY_DEF(FelicaNodeList, FelicaNode*, M_PTR_OPLIST);
|
||||
|
||||
typedef struct _FelicaArea_t {
|
||||
uint16_t number;
|
||||
bool can_create_subareas;
|
||||
uint16_t end_service_code;
|
||||
|
||||
FelicaNodeList_t nodes;
|
||||
|
||||
} FelicaArea;
|
||||
|
||||
typedef struct _FelicaSystem_t {
|
||||
uint8_t number;
|
||||
uint16_t code;
|
||||
@@ -149,16 +167,18 @@ typedef struct _FelicaSystem_t {
|
||||
uint8_t pmm[8];
|
||||
FelicaMRTParameters maximum_response_times;
|
||||
|
||||
FelicaService* services;
|
||||
|
||||
struct _FelicaSystem_t* next;
|
||||
/** This struct represents area 0,
|
||||
* which always exists on a given system
|
||||
*/
|
||||
FelicaArea root_area;
|
||||
} FelicaSystem;
|
||||
|
||||
ARRAY_DEF(FelicaSystemList, FelicaSystem*, M_PTR_OPLIST);
|
||||
|
||||
typedef struct {
|
||||
FelicaICType type;
|
||||
uint8_t subtype;
|
||||
uint8_t system_count;
|
||||
FelicaSystem* systems;
|
||||
FelicaSystemList_t systems;
|
||||
} FelicaData;
|
||||
|
||||
typedef struct {
|
||||
@@ -170,8 +190,56 @@ typedef struct {
|
||||
|
||||
bool felica_check_ic_type(uint8_t* PMm);
|
||||
FelicaICType felica_get_ic_type(uint8_t* PMm);
|
||||
|
||||
uint8_t felica_prepare_unencrypted_read(
|
||||
uint8_t* dest,
|
||||
const FelicaReader* reader,
|
||||
const uint16_t* service_code_list,
|
||||
uint8_t service_count,
|
||||
const uint32_t* block_list,
|
||||
uint8_t block_count);
|
||||
uint8_t felica_lite_prepare_unencrypted_read(
|
||||
uint8_t* dest,
|
||||
const FelicaReader* reader,
|
||||
bool is_read_only,
|
||||
const uint8_t* block_list,
|
||||
uint8_t block_count);
|
||||
uint16_t felica_parse_unencrypted_read(
|
||||
uint8_t* buf,
|
||||
uint8_t len,
|
||||
FelicaReader* reader,
|
||||
uint8_t* out,
|
||||
uint16_t out_len);
|
||||
|
||||
uint8_t felica_prepare_unencrypted_write(
|
||||
uint8_t* dest,
|
||||
FelicaReader* reader,
|
||||
const uint16_t* service_code_list,
|
||||
uint8_t service_count,
|
||||
const uint32_t* block_list,
|
||||
uint8_t block_count,
|
||||
const uint8_t* block_data);
|
||||
uint8_t felica_lite_prepare_unencrypted_write(
|
||||
uint8_t* dest,
|
||||
const FelicaReader* reader,
|
||||
const uint8_t* block_list,
|
||||
uint8_t block_count,
|
||||
const uint8_t* block_data);
|
||||
bool felica_parse_unencrypted_write(uint8_t* buf, uint8_t len, FelicaReader* reader);
|
||||
|
||||
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);
|
||||
|
||||
bool felica_read_lite_system(
|
||||
FuriHalNfcTxRxContext* tx_rx,
|
||||
FelicaReader* reader,
|
||||
FelicaData* data,
|
||||
FelicaSystem* system);
|
||||
|
||||
bool felica_read_card(
|
||||
FuriHalNfcTxRxContext* tx_rx,
|
||||
FelicaData* data,
|
||||
uint8_t* polled_idm,
|
||||
uint8_t* polled_pmm);
|
||||
uint8_t* polled_pmm);
|
||||
void felica_clear(FelicaData* data);
|
||||
43
lib/nfc/protocols/felica_util.c
Normal file
43
lib/nfc/protocols/felica_util.c
Normal file
@@ -0,0 +1,43 @@
|
||||
#include "./felica.h"
|
||||
#include <furi.h>
|
||||
|
||||
FuriString* felica_get_system_name(FelicaSystem* system) {
|
||||
uint16_t code = system->code;
|
||||
|
||||
const char* prefix;
|
||||
if(code == SUICA_SYSTEM_CODE) {
|
||||
prefix = "SuiCa";
|
||||
} else if(code == NDEF_SYSTEM_CODE) {
|
||||
prefix = "NDEF";
|
||||
} else if(code == HCE_F_SYSTEM_CODE) {
|
||||
prefix = "HCE-F";
|
||||
} else if(code == OCTOPUS_SYSTEM_CODE) {
|
||||
prefix = "Octopus";
|
||||
} else if(code == EDY_SYSTEM_CODE) {
|
||||
prefix = "Edy";
|
||||
} else if(code == PASPY_SYSTEM_CODE) {
|
||||
prefix = "PASPY";
|
||||
} else if(code == BLACKBOARD_SYSTEM_CODE) {
|
||||
prefix = "Blackboard";
|
||||
} else if(code == SAPICA_SYSTEM_CODE) {
|
||||
prefix = "SAPICA";
|
||||
} else if(code == LITE_SYSTEM_CODE) {
|
||||
prefix = "FeliCa Lite";
|
||||
} else if(code == RYUTO_SYSTEM_CODE) {
|
||||
prefix = "Ryuto";
|
||||
} else if(code == OKICA_SYSTEM_CODE) {
|
||||
prefix = "OKICA";
|
||||
} else if(code == SECURE_ID_SYSTEM_CODE) {
|
||||
prefix = "FeliCa Secure ID";
|
||||
} else if(code == IRUCA_SYSTEM_CODE) {
|
||||
prefix = "IruCa";
|
||||
} else if(code == COMMON_AREA_SYSTEM_CODE) {
|
||||
prefix = "Common Area";
|
||||
} else if(code == PLUG_SYSTEM_CODE) {
|
||||
prefix = "FeliCa Plug";
|
||||
} else {
|
||||
return furi_string_alloc_printf("System %04X", code);
|
||||
}
|
||||
|
||||
return furi_string_alloc_printf("%s (%04X)", prefix, code);
|
||||
}
|
||||
4
lib/nfc/protocols/felica_util.h
Normal file
4
lib/nfc/protocols/felica_util.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#include "./felica.h"
|
||||
|
||||
FuriString* felica_get_system_name(FelicaSystem* system);
|
||||
FuriString* felica_get_service_name(FelicaService* service);
|
||||
Reference in New Issue
Block a user