Merge branch 'fix/mfc-ndef' into mntm-dev --nobuild

This commit is contained in:
Willy-JL
2025-03-26 11:39:25 +00:00
4 changed files with 30 additions and 47 deletions

View File

@@ -65,9 +65,10 @@
- Also added `BLE_ID` command, same as `BT_ID` - Also added `BLE_ID` command, same as `BT_ID`
- Main Menu: Refined CoverFlow menu style (#379 by @956MB) - Main Menu: Refined CoverFlow menu style (#379 by @956MB)
- NFC: - NFC:
- Support MIFARE DESFire Transaction MAC file type, fixes reading some EV2+ cards (by @Willy-JL)
- Improvements and fixes for NDEF parsing on MIFARE Classic (by @Willy-JL)
- OFW: Added naming for DESFire cards + fix MF3ICD40 cards unable to be read (by @Demae) - OFW: Added naming for DESFire cards + fix MF3ICD40 cards unable to be read (by @Demae)
- OFW: FeliCa Protocol Expose Read Block API and Allow Specifying Service (by @zinongli) - OFW: FeliCa Protocol Expose Read Block API and Allow Specifying Service (by @zinongli)
- OFW: Support DESFire Transaction MAC file type, fixes reading some EV2+ cards (by @Willy-JL)
- OFW: Enable MFUL sync poller to be provided with passwords (by @GMMan) - OFW: Enable MFUL sync poller to be provided with passwords (by @GMMan)
- UL: Power: Moved Charge Cap to Power Settings as Charge Limit option (by @Dmitry422) - UL: Power: Moved Charge Cap to Power Settings as Charge Limit option (by @Dmitry422)
- Infrared: - Infrared:
@@ -84,13 +85,13 @@
### Fixed: ### Fixed:
- Asset Packs: Fix level-up animations not being themed (by @Willy-JL) - Asset Packs: Fix level-up animations not being themed (by @Willy-JL)
- About: Fix missing Prev. button when invoked from Device Info keybind (by @Willy-JL) - About: Fix missing Prev. button when invoked from Device Info keybind (by @Willy-JL)
- GUI: Fix widget text scroll with 256+ lines (by @Willy-JL)
- Sub-GHz: - Sub-GHz:
- UL: Fix Hollarm protocol with more verification (by @xMasterX) - UL: Fix Hollarm protocol with more verification (by @xMasterX)
- UL: Fix GangQi protocol (by @DoberBit and @mishamyte) - UL: Fix GangQi protocol (by @DoberBit and @mishamyte)
- UL: Came Atomo button hold simulation with full cycle to allow proper pairing with receiver (by @xMasterX) - UL: Came Atomo button hold simulation with full cycle to allow proper pairing with receiver (by @xMasterX)
- OFW: NFC: ST25TB poller mode check (by @RebornedBrain) - OFW: NFC: ST25TB poller mode check (by @RebornedBrain)
- OFW: RFID: Fix Detection Conflict Between Securakey and Noralsy Format (by @zinongli) - OFW: RFID: Fix Detection Conflict Between Securakey and Noralsy Format (by @zinongli)
- OFW: GUI: Fix widget text scroll with 256+ lines (by @Willy-JL)
- Furi: - Furi:
- OFW: EventLoop unsubscribe fix (by @gsurkov & @portasynthinca3) - OFW: EventLoop unsubscribe fix (by @gsurkov & @portasynthinca3)
- OFW: Various bug fixes and improvements (by @skotopes) - OFW: Various bug fixes and improvements (by @skotopes)

View File

@@ -181,30 +181,34 @@ static bool ndef_get(Ndef* ndef, size_t pos, size_t len, void* buf) {
// So the first 93 (31*3) data blocks correspond to 128 real blocks. // So the first 93 (31*3) data blocks correspond to 128 real blocks.
// Last 128 blocks are 8 sectors: 15 data blocks, 1 sector trailer. // Last 128 blocks are 8 sectors: 15 data blocks, 1 sector trailer.
// So the last 120 (8*15) data blocks correspond to 128 real blocks. // So the last 120 (8*15) data blocks correspond to 128 real blocks.
div_t small_sector_data_blocks = div(pos, MF_CLASSIC_BLOCK_SIZE); const size_t real_block_data_offset = pos % MF_CLASSIC_BLOCK_SIZE;
size_t small_sector_data_blocks = pos / MF_CLASSIC_BLOCK_SIZE;
size_t large_sector_data_blocks = 0; size_t large_sector_data_blocks = 0;
if(small_sector_data_blocks.quot > 93) { if(small_sector_data_blocks > 93) {
large_sector_data_blocks = small_sector_data_blocks.quot - 93; large_sector_data_blocks = small_sector_data_blocks - 93;
small_sector_data_blocks.quot = 93; small_sector_data_blocks = 93;
} }
div_t small_sectors = div(small_sector_data_blocks.quot, 3); const size_t small_sector_block_offset = small_sector_data_blocks % 3;
size_t real_block = small_sectors.quot * 4 + small_sectors.rem; const size_t small_sectors = small_sector_data_blocks / 3;
if(small_sectors.quot >= 16) { size_t real_block = small_sectors * 4 + small_sector_block_offset;
if(small_sectors >= 16) {
real_block += 4; // Skip MAD2 real_block += 4; // Skip MAD2
} }
if(large_sector_data_blocks) { if(large_sector_data_blocks) {
div_t large_sectors = div(large_sector_data_blocks, 15); const size_t large_sector_block_offset = large_sector_data_blocks % 15;
real_block += large_sectors.quot * 16 + large_sectors.rem; const size_t large_sectors = large_sector_data_blocks / 15;
real_block += large_sectors * 16 + large_sector_block_offset;
} }
const uint8_t* cur = &ndef->mfc.blocks[real_block].data[small_sector_data_blocks.rem]; const uint8_t* cur = &ndef->mfc.blocks[real_block].data[real_block_data_offset];
while(len) { while(len) {
size_t sector_trailer = mf_classic_get_sector_trailer_num_by_block(real_block); size_t sector_trailer = mf_classic_get_sector_trailer_num_by_block(real_block);
const uint8_t* end = &ndef->mfc.blocks[sector_trailer].data[0]; const uint8_t* end = &ndef->mfc.blocks[sector_trailer].data[0];
size_t chunk_len = MIN((size_t)(end - cur), len); const size_t chunk_len = MIN((size_t)(end - cur), len);
memcpy(buf, cur, chunk_len); memcpy(buf, cur, chunk_len);
buf += chunk_len;
len -= chunk_len; len -= chunk_len;
if(len) { if(len) {
@@ -582,7 +586,7 @@ bool ndef_parse_record(
NdefTnf tnf, NdefTnf tnf,
const char* type, const char* type,
uint8_t type_len) { uint8_t type_len) {
FURI_LOG_D(TAG, "payload type: %.*s len: %hu", type_len, type, len); FURI_LOG_D(TAG, "payload type: %.*s len: %hu pos: %zu", type_len, type, len, pos);
if(!len) { if(!len) {
furi_string_cat(ndef->output, "Empty\n"); furi_string_cat(ndef->output, "Empty\n");
return true; return true;
@@ -887,13 +891,13 @@ static bool ndef_mfc_parse(const NfcDevice* device, FuriString* parsed_data) {
for(uint8_t mad = 0; mad < COUNT_OF(mads); mad++) { for(uint8_t mad = 0; mad < COUNT_OF(mads); mad++) {
const size_t block = mads[mad].block; const size_t block = mads[mad].block;
const size_t sector = mf_classic_get_sector_by_block(block); const size_t sector = mf_classic_get_sector_by_block(block);
if(sector_count <= sector) break; // Skip this MAD if not present if(sector_count <= sector) continue; // Skip this MAD if not present
// Check MAD key // Check MAD key
const MfClassicSectorTrailer* sector_trailer = const MfClassicSectorTrailer* sector_trailer =
mf_classic_get_sector_trailer_by_sector(data, sector); mf_classic_get_sector_trailer_by_sector(data, sector);
const uint64_t sector_key_a = bit_lib_bytes_to_num_be( const uint64_t sector_key_a = bit_lib_bytes_to_num_be(
sector_trailer->key_a.data, COUNT_OF(sector_trailer->key_a.data)); sector_trailer->key_a.data, COUNT_OF(sector_trailer->key_a.data));
if(sector_key_a != mad_key) return false; if(sector_key_a != mad_key) continue;
// Find NDEF AIDs // Find NDEF AIDs
for(uint8_t aid_index = 0; aid_index < mads[mad].aid_count; aid_index++) { for(uint8_t aid_index = 0; aid_index < mads[mad].aid_count; aid_index++) {
const uint8_t* aid = &data->block[block].data[2 + aid_index * AID_SIZE]; const uint8_t* aid = &data->block[block].data[2 + aid_index * AID_SIZE];
@@ -917,7 +921,7 @@ static bool ndef_mfc_parse(const NfcDevice* device, FuriString* parsed_data) {
data_size = 93 + (sector_count - 32) * 15; data_size = 93 + (sector_count - 32) * 15;
} else { } else {
data_size = sector_count * 3; data_size = sector_count * 3;
if(sector_count >= 16) { if(sector_count > 16) {
data_size -= 3; // Skip MAD2 data_size -= 3; // Skip MAD2
} }
} }

View File

@@ -392,37 +392,15 @@ static void nfc_generate_mf_classic(NfcDevice* nfc_device, uint8_t uid_len, MfCl
mf_classic_set_block_read(mfc_data, 0, &mfc_data->block[0]); mf_classic_set_block_read(mfc_data, 0, &mfc_data->block[0]);
// Set every block to 0x00
uint16_t block_num = mf_classic_get_total_block_num(type); uint16_t block_num = mf_classic_get_total_block_num(type);
if(type == MfClassicType4k) { for(uint16_t i = 1; i < block_num; i++) {
// Set every block to 0x00 if(mf_classic_is_sector_trailer(i)) {
for(uint16_t i = 1; i < block_num; i++) { nfc_generate_mf_classic_sector_trailer(mfc_data, i);
if(mf_classic_is_sector_trailer(i)) { } else {
nfc_generate_mf_classic_sector_trailer(mfc_data, i); memset(&mfc_data->block[i].data, 0x00, MF_CLASSIC_BLOCK_SIZE);
} else {
memset(&mfc_data->block[i].data, 0x00, 16);
}
mf_classic_set_block_read(mfc_data, i, &mfc_data->block[i]);
}
} else if(type == MfClassicType1k) {
// Set every block to 0x00
for(uint16_t i = 1; i < block_num; i++) {
if(mf_classic_is_sector_trailer(i)) {
nfc_generate_mf_classic_sector_trailer(mfc_data, i);
} else {
memset(&mfc_data->block[i].data, 0x00, 16);
}
mf_classic_set_block_read(mfc_data, i, &mfc_data->block[i]);
}
} else if(type == MfClassicTypeMini) {
// Set every block to 0x00
for(uint16_t i = 1; i < block_num; i++) {
if(mf_classic_is_sector_trailer(i)) {
nfc_generate_mf_classic_sector_trailer(mfc_data, i);
} else {
memset(&mfc_data->block[i].data, 0x00, 16);
}
mf_classic_set_block_read(mfc_data, i, &mfc_data->block[i]);
} }
mf_classic_set_block_read(mfc_data, i, &mfc_data->block[i]);
} }
nfc_generate_mf_classic_block_0( nfc_generate_mf_classic_block_0(

View File

@@ -983,7 +983,7 @@ Function,+,dir_walk_read,DirWalkResult,"DirWalk*, FuriString*, FileInfo*"
Function,+,dir_walk_set_filter_cb,void,"DirWalk*, DirWalkFilterCb, void*" Function,+,dir_walk_set_filter_cb,void,"DirWalk*, DirWalkFilterCb, void*"
Function,+,dir_walk_set_recurse_filter,void,"DirWalk*, const char**, size_t" Function,+,dir_walk_set_recurse_filter,void,"DirWalk*, const char**, size_t"
Function,+,dir_walk_set_recursive,void,"DirWalk*, _Bool" Function,+,dir_walk_set_recursive,void,"DirWalk*, _Bool"
Function,+,div,div_t,"int, int" Function,-,div,div_t,"int, int"
Function,+,dolphin_deed,void,DolphinDeed Function,+,dolphin_deed,void,DolphinDeed
Function,+,dolphin_deed_get_app,DolphinApp,DolphinDeed Function,+,dolphin_deed_get_app,DolphinApp,DolphinDeed
Function,+,dolphin_deed_get_app_limit,uint8_t,DolphinApp Function,+,dolphin_deed_get_app_limit,uint8_t,DolphinApp
1 entry status name type params
983 Function + dir_walk_set_filter_cb void DirWalk*, DirWalkFilterCb, void*
984 Function + dir_walk_set_recurse_filter void DirWalk*, const char**, size_t
985 Function + dir_walk_set_recursive void DirWalk*, _Bool
986 Function + - div div_t int, int
987 Function + dolphin_deed void DolphinDeed
988 Function + dolphin_deed_get_app DolphinApp DolphinDeed
989 Function + dolphin_deed_get_app_limit uint8_t DolphinApp