71#define ST25TB_SR_BLOCK_MAX_SIZE ((uint8_t) 4)
72typedef void(*get_info_specific) (uint8_t * systemArea);
74typedef struct _st_data {
78 const char *szDatasheetUrl;
80 uint8_t nbNormalBlock;
82 get_info_specific pfnGetInfo;
85bool get_block_at(
nfc_device *pnd, uint8_t block, uint8_t *data, uint8_t cbData,
bool bPrintIt);
86bool set_block_at(
nfc_device *pnd, uint8_t block, uint8_t *data, uint8_t cbData,
bool bPrintIt);
87bool set_block_at_confirmed(
nfc_device *pnd, uint8_t block, uint8_t *data, uint8_t cbData,
bool bPrintIt);
88const st_data * get_info(
const nfc_target *pnt,
bool bPrintIt);
89void display_system_info(
nfc_device *pnd,
const st_data * stdata);
90void print_hex(
const uint8_t *pbtData,
const size_t szBytes);
92int main(
int argc,
char *argv[])
98 const st_data * stcurrent;
100 bool bIsBlock =
false, bIsRead =
false, bIsWrite =
false, bIsBadCli =
false;
101 uint8_t i, blockNumber = 0, data[ST25TB_SR_BLOCK_MAX_SIZE] = {0xff, 0xff, 0xff, 0xff};
104 while(!bIsBadCli && ((opt = getopt(argc, argv,
":hib:rw:")) != -1))
116 blockNumber = strtoul(optarg, NULL, 0);
118 else bIsBadCli =
true;
130 cbData = strlen(optarg);
131 if((cbData == (2*2)) || ((cbData == (4*2))))
136 res = sscanf(optarg,
"%02hhx%02hhx", data, data + 1);
140 res = sscanf(optarg,
"%02hhx%02hhx%02hhx%02hhx", data, data + 1, data + 2, data + 3);
143 if(res == (
int) cbData)
165 if(bIsBlock && (bIsRead || bIsWrite))
167 if(bIsRead && bIsWrite)
169 printf(
"|mode : read then write\n");
173 printf(
"|mode : read\n");
177 printf(
"|mode : write\n");
180 printf(
"|blk num: 0x%02hhx\n", blockNumber);
184 print_hex(data, cbData);
188 else if(!bIsRead && !bIsWrite && !bIsBlock)
190 printf(
"|mode : info\n");
192 else bIsBadCli =
true;
211 stcurrent = get_info(&nt,
true);
216 if(bIsBlock && (bIsRead || bIsWrite))
220 get_block_at(pnd, blockNumber, NULL, 0,
true);
225 set_block_at_confirmed(pnd, blockNumber, data, cbData,
true);
228 else if(!bIsRead && !bIsWrite && !bIsBlock)
230 for(i = 0; i < stcurrent->nbNormalBlock; i++)
232 get_block_at(pnd, i, NULL, 0,
true);
234 display_system_info(pnd, stcurrent);
238 else printf(
"ERROR - nfc_initiator_select_passive_target: %i\n", res);
240 else printf(
"ERROR - nfc_initiator_init: %i\n", res);
244 else printf(
"ERROR - nfc_open\n");
248 else printf(
"ERROR - nfc_init\n");
256 " %s -b N [-r] -w ABCD[EF01]\n %s -h\n"
258 " -i (default) information mode - will try to dump the tag content and display informations\n"
259 " -b N specify block number to operate on (tag dependent), needed for read (-r) and write (-w) modes\n"
260 " -r read mode - will try to read block (specified with -b N parameter)\n"
261 " -w ABCD[EF01] write mode - will try to write specicied data (2 or 4 bytes depending on tag) to block (specified with -b N parameter)\n"
265 " Display all tag informations\n"
267 " Read block 0x0e (14) of the tag\n"
268 " %s -b 0x0d -w 0123abcd\n"
269 " Write block 0x0d (13) of the tag with hexadecimal value '01 23 ab cd'\n"
270 " %s -b 0x0c -r -w 0123abcd\n"
271 " Read, then write block 0x0c (12) of the tag with hexadecimal value '01 23 ab cd'\n"
273 " Be careful with: system area, counters & otp, bytes order.\n"
274 , argv[0], argv[0], argv[0], argv[0], argv[0], argv[0], argv[0], argv[0]);
280bool get_block_at(
nfc_device *pnd, uint8_t block, uint8_t *data, uint8_t cbData,
bool bPrintIt)
283 uint8_t tx[2] = {0x08, block}, rx[ST25TB_SR_BLOCK_MAX_SIZE];
287 if((res == 2) || (res == 4))
293 memcpy(data, rx, res);
296 else printf(
"ERROR - We got %i bytes for a %hhu buffer size?\n", res, cbData);
302 printf(
"[0x%02hhx] ", block);
309 printf(
"ERROR - We got %i bytes?\n", res);
311 else printf(
"ERROR - nfc_initiator_transceive_bytes(get): %i\n", res);
316bool set_block_at(
nfc_device *pnd, uint8_t block, uint8_t *data, uint8_t cbData,
bool bPrintIt)
319 uint8_t tx[2 + ST25TB_SR_BLOCK_MAX_SIZE] = {0x09, block};
322 if(cbData <= ST25TB_SR_BLOCK_MAX_SIZE)
324 memcpy(tx + 2, data, cbData);
328 printf(
">0x%02hhx> ", block);
329 print_hex(data, cbData);
338 else printf(
"ERROR - nfc_initiator_transceive_bytes(set): %i\n", res);
340 else printf(
"ERROR - Wanted to write %hhu bytes, but maximum is %hhu\n", cbData, ST25TB_SR_BLOCK_MAX_SIZE);
345bool set_block_at_confirmed(
nfc_device *pnd, uint8_t block, uint8_t *data, uint8_t cbData,
bool bPrintIt)
348 uint8_t buffer[ST25TB_SR_BLOCK_MAX_SIZE];
350 if(set_block_at(pnd, block, data, cbData, bPrintIt))
352 if(get_block_at(pnd, block, buffer, cbData, bPrintIt))
354 if(memcmp(data, buffer, cbData) == 0)
360 printf(
"WARNING - not same value readed after write\n");
368void get_info_st25tb512(uint8_t * systemArea)
372 b = ((*(uint32_t *) systemArea) >> 15) & 1;
374 printf(
" | ST reserved : ");
375 for(i = 0; i < 15; i++)
377 printf(
"%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
379 printf(
"\n | b15 : %hhu - %sOTP (?)\n | OTP_Lock_Reg : ", b, b ?
"not " :
"");
380 for(i = 16; i < 32; i++)
382 printf(
"%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
385 for(i = 16; i < 32; i++)
387 if(!(((*(uint32_t *) systemArea) >> i) & 1))
389 printf(
" block 0x%02hhx is write protected\n", ((uint8_t) (i - 16)));
394void get_info_st25tb2k_4k(uint8_t * systemArea)
398 b = ((*(uint32_t *) systemArea) >> 15) & 1;
400 printf(
" | ST reserved : ");
401 for(i = 0; i < 15; i++)
403 printf(
"%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
405 printf(
"\n | b15 : %hhu - %sOTP (?)\n | OTP_Lock_RegU: ", b, b ?
"not " :
"");
406 for(i = 16; i < 24; i++)
408 printf(
"%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
410 printf(
"\n | OTP_Lock_Reg : ");
411 for(i = 24; i < 32; i++)
413 printf(
"%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
416 if(!(((*(uint32_t *) systemArea) >> 24) & 1))
418 printf(
" blocks 0x07 and 0x08 are write protected\n");
420 for(i = 25; i < 32; i++)
422 if(!(((*(uint32_t *) systemArea) >> i) & 1))
424 printf(
" block 0x%02hhx is write protected\n", ((uint8_t) (i - 16)));
429void get_info_sr176_legacy(uint8_t * systemArea)
433 printf(
" | Fixed Chip_ID: 0x%1x\n | ST reserved : ", systemArea[0] & 0x0f);
434 for(i = 4; i < 8; i++)
436 printf(
"%hhu", (uint8_t) (((*(uint16_t *) systemArea) >> i) & 1));
438 printf(
"\n | OTP_Lock_Reg : ");
439 for(i = 8; i < 16; i++)
441 printf(
"%hhu", (uint8_t) (((*(uint16_t *) systemArea) >> i) & 1));
444 for(i = 8; i < 16; i++)
446 if(((*(uint16_t *) systemArea) >> i) & 1)
448 printf(
" blocks 0x%02hhx and 0x%02hhx are write protected\n", (uint8_t) ((i - 8) * 2), (uint8_t) (((i - 8) * 2) + 1));
453void get_info_sri_srt_512_legacy(uint8_t * systemArea)
457 b = ((*(uint32_t *) systemArea) >> 15) & 1;
459 printf(
" | Fixed Chip_ID: 0x%02hhx\n | ST reserved : ", systemArea[0]);
460 for(i = 8; i < 15; i++)
462 printf(
"%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
464 printf(
"\n | b15 : %hhu - %sOTP (?)\n | OTP_Lock_Reg : ", b, b ?
"not " :
"");
465 for(i = 16; i < 32; i++)
467 printf(
"%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
470 for(i = 16; i < 32; i++)
472 if(!(((*(uint32_t *) systemArea) >> i) & 1))
474 printf(
" block 0x%02hhx is write protected\n", (uint8_t) (i - 16));
479void get_info_sri2k_4k_srix4k_srix512_legacy(uint8_t * systemArea)
483 printf(
" | Fixed Chip_ID: 0x%02hhx\n | ST reserved : ", systemArea[0]);
484 for(i = 8; i < 24; i++)
486 printf(
"%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
488 printf(
"\n | OTP_Lock_Reg : ");
489 for(i = 24; i < 32; i++)
491 printf(
"%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
494 if(!(((*(uint32_t *) systemArea) >> 24) & 1))
496 printf(
" blocks 0x07 and 0x08 are write protected\n");
498 for(i = 25; i < 32; i++)
500 if(!(((*(uint32_t *) systemArea) >> i) & 1))
502 printf(
" block 0x%02hhx is write protected\n", (uint8_t) (i - 16));
507const st_data STRefs[] = {
508 {0x1b,
false,
"ST25TB512-AC",
"https://www.st.com/resource/en/datasheet/st25tb512-ac.pdf", 4, 16, 255, get_info_st25tb512},
509 {0x33,
false,
"ST25TB512-AT",
"https://www.st.com/resource/en/datasheet/st25tb512-at.pdf", 4, 16, 255, get_info_st25tb512},
510 {0x3f,
false,
"ST25TB02K",
"https://www.st.com/resource/en/datasheet/st25tb02k.pdf", 4, 64, 255, get_info_st25tb2k_4k},
511 {0x1f,
false,
"ST25TB04K",
"https://www.st.com/resource/en/datasheet/st25tb04k.pdf", 4, 128, 255, get_info_st25tb2k_4k},
513const st_data STRefs_legacy[] = {
514 { 0,
true,
"SRI4K(s)", NULL, 4, 128, 255, NULL},
515 { 2,
true,
"SR176",
"https://www.st.com/resource/en/datasheet/sr176.pdf", 2, 15, 15, get_info_sr176_legacy},
516 { 3,
true,
"SRIX4K", NULL, 4, 128, 255, get_info_sri2k_4k_srix4k_srix512_legacy},
517 { 4,
true,
"SRIX512",
"https://www.st.com/resource/en/datasheet/srix512.pdf", 4, 16, 255, get_info_sri2k_4k_srix4k_srix512_legacy},
518 { 6,
true,
"SRI512",
"https://www.st.com/resource/en/datasheet/sri512.pdf", 4, 16, 255, get_info_sri_srt_512_legacy},
519 { 7,
true,
"SRI4K",
"https://www.st.com/resource/en/datasheet/sri4k.pdf", 4, 128, 255, get_info_sri2k_4k_srix4k_srix512_legacy},
520 {12,
true,
"SRT512",
"https://www.st.com/resource/en/datasheet/srt512.pdf", 4, 16, 255, get_info_sri_srt_512_legacy},
521 {15,
true,
"SRI2K",
"https://www.st.com/resource/en/datasheet/sri2k.pdf", 4, 64, 255, get_info_sri2k_4k_srix4k_srix512_legacy},
524const st_data * get_info(
const nfc_target *pnt,
bool bPrintIt)
526 const st_data *currentData = NULL;
530 if(pnt->nm.nmt == NMT_ISO14443B2SR)
533 print_hex(pnt->nti.nsi.abtUID,
sizeof(pnt->nti.nsi.abtUID));
536 p = pnt->nti.nsi.abtUID;
540 printf(
"Manuf : 0x%02hhx - %s\n", p[6], (p[6] == 0x02) ?
"STMicroelectronics" :
"other");
542 for(i = 0; i < (
sizeof(STRefs) /
sizeof(STRefs[0])); i++)
544 if(chipId == STRefs[i].chipId)
546 currentData = &STRefs[i];
554 for(i = 0; i < (
sizeof(STRefs_legacy) /
sizeof(STRefs_legacy[0])); i++)
556 if(chipId == STRefs_legacy[i].chipId)
558 currentData = &STRefs_legacy[i];
564 if(bPrintIt && currentData)
566 printf(
"ChipId : 0x%02hhx - %s%s\nSerial : 0x", currentData->chipId, currentData->szName, currentData->bIsLegacy ?
" (legacy)" :
"");
567 if(currentData->bIsLegacy)
569 printf(
"%1hhx", (uint8_t) (p[5] & 0x03));
571 printf(
"%02hhx%02hhx%02hhx%02hhx%02hhx\n|blk sz : %hhu bits\n|nb blks: %hhu\n|sys idx: %hhu\n", p[4], p[3], p[2], p[1], p[0], (uint8_t) (currentData->blockSize * 8), currentData->nbNormalBlock, currentData->bnSystem);
574 else printf(
"WARNI - Last byte of UID isn\'t 0xd0, but 0x%02hhx (not ST25TB / SR series?)\n", p[7]);
576 else printf(
"ERROR - not a NMT_ISO14443B2SR ?\n");
581void display_system_info(
nfc_device *pnd,
const st_data * stdata)
583 uint8_t systemArea[ST25TB_SR_BLOCK_MAX_SIZE];
585 if(get_block_at(pnd, stdata->bnSystem, systemArea, stdata->blockSize,
true))
587 if(stdata->pfnGetInfo)
589 stdata->pfnGetInfo(systemArea);
594void print_hex(
const uint8_t *pbtData,
const size_t szBytes)
597 for (szPos = 0; szPos < szBytes; szPos++)
599 printf(
"%02hhx ", pbtData[szPos]);
const char * nfc_device_get_name(nfc_device *pnd)
Returns the device name.
const char * nfc_device_get_connstring(nfc_device *pnd)
Returns the device connection string.
void nfc_close(nfc_device *pnd)
Close from a NFC device.
nfc_device * nfc_open(nfc_context *context, const nfc_connstring connstring)
Open a NFC device.
int nfc_initiator_transceive_bytes(nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, uint8_t *pbtRx, const size_t szRx, int timeout)
Send data to target then retrieve data from target.
int nfc_initiator_init(nfc_device *pnd)
Initialize NFC device as initiator (reader)
int nfc_initiator_select_passive_target(nfc_device *pnd, const nfc_modulation nm, const uint8_t *pbtInitData, const size_t szInitData, nfc_target *pnt)
Select a passive or emulated tag.
void nfc_exit(nfc_context *context)
Deinitialize libnfc. Should be called after closing all open devices and before your application term...
void nfc_init(nfc_context **context)
Initialize libnfc. This function must be called before calling any other libnfc function.
const char * str_nfc_modulation_type(const nfc_modulation_type nmt)
Convert nfc_modulation_type value to string.
const char * str_nfc_baud_rate(const nfc_baud_rate nbr)
Convert nfc_baud_rate value to string.
NFC library context Struct which contains internal options, references, pointers, etc....
NFC modulation structure.