libnfc 1.8.0
nfc-st25tb.c
Go to the documentation of this file.
1/*-
2 * Free/Libre Near Field Communication (NFC) library
3 *
4 * Libnfc historical contributors:
5 * Copyright (C) 2009 Roel Verdult
6 * Copyright (C) 2009-2013 Romuald Conty
7 * Copyright (C) 2010-2012 Romain Tartière
8 * Copyright (C) 2010-2013 Philippe Teuwen
9 * Copyright (C) 2012-2013 Ludovic Rousseau
10 * See AUTHORS file for a more comprehensive list of contributors.
11 * Additional contributors of this file:
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions are met:
15 * 1) Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 * 2 )Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Note that this license only applies on the examples, NFC library itself is under LGPL
34 *
35 */
36
41
42/* Benjamin DELPY `gentilkiwi`
43 * https://blog.gentilkiwi.com
44 * benjamin@gentilkiwi.com
45 * Licence : https://creativecommons.org/licenses/by/4.0/
46 * Rely on : libnfc - https://github.com/nfc-tools/libnfc
47 *
48 * $ gcc -Wall -lnfc -o nfc-st25tb nfc-st25tb.c
49 * $ ./nfc-st25tb -h
50 *
51 * Tested with
52 * - ST25TB512-AC - (BE/Brussels/STIB ; AliExpress ones)
53 * - ST25TB512-AT - (FR/Lille/Ilevia ; FR/Reims/Citura ; FR/Dijon/Divia ; FR/Strasbourg/CTS)
54 * - SRT512 - legacy - (FR/Bordeaux/TBM)
55 * - SRI512 - legacy - (anonymous vending machine)
56 */
57#ifdef HAVE_CONFIG_H
58# include "config.h"
59#endif // HAVE_CONFIG_H
60
61#include <unistd.h>
62#include <stdlib.h>
63#include <stdbool.h>
64#include <string.h>
65#include <nfc/nfc.h>
66
67#if defined(WIN32) /* mingw compiler */
68#include <getopt.h>
69#endif
70
71#define ST25TB_SR_BLOCK_MAX_SIZE ((uint8_t) 4) // for static arrays
72typedef void(*get_info_specific) (uint8_t * systemArea);
73
74typedef struct _st_data {
75 uint8_t chipId;
76 bool bIsLegacy;
77 const char *szName;
78 const char *szDatasheetUrl;
79 uint8_t blockSize;
80 uint8_t nbNormalBlock;
81 uint8_t bnSystem;
82 get_info_specific pfnGetInfo;
83} st_data;
84
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);
91
92int main(int argc, char *argv[])
93{
94 nfc_context *context = NULL;
95 nfc_device *pnd = NULL;
96 nfc_target nt = {0};
97 nfc_modulation nm = {NMT_ISO14443B2SR, NBR_106};
98 const st_data * stcurrent;
99 int opt, res;
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}; // just in case...
102 size_t cbData = 0;
103
104 while(!bIsBadCli && ((opt = getopt(argc, argv, ":hib:rw:")) != -1))
105 {
106 switch(opt)
107 {
108 case 'i':
109
110 break;
111
112 case 'b':
113 if(optarg)
114 {
115 bIsBlock = true;
116 blockNumber = strtoul(optarg, NULL, 0);
117 }
118 else bIsBadCli = true;
119
120 break;
121
122 case 'r':
123 bIsRead = true;
124
125 break;
126
127 case 'w':
128 if(optarg)
129 {
130 cbData = strlen(optarg);
131 if((cbData == (2*2)) || ((cbData == (4*2))))
132 {
133 cbData >>= 1;
134 if(cbData == 2) // sr176
135 {
136 res = sscanf(optarg, "%02hhx%02hhx", data, data + 1);
137 }
138 else // all others
139 {
140 res = sscanf(optarg, "%02hhx%02hhx%02hhx%02hhx", data, data + 1, data + 2, data + 3);
141 }
142
143 if(res == (int) cbData)
144 {
145 bIsWrite = true;
146 }
147 }
148
149 if(!bIsWrite)
150 {
151 bIsBadCli = true;
152 }
153 }
154
155 break;
156
157 default: // includes -h
158 bIsBadCli = true;
159
160 }
161 }
162
163 if(!bIsBadCli)
164 {
165 if(bIsBlock && (bIsRead || bIsWrite))
166 {
167 if(bIsRead && bIsWrite)
168 {
169 printf("|mode : read then write\n");
170 }
171 else if(bIsRead)
172 {
173 printf("|mode : read\n");
174 }
175 else if(bIsWrite)
176 {
177 printf("|mode : write\n");
178 }
179
180 printf("|blk num: 0x%02hhx\n", blockNumber);
181 if(bIsWrite)
182 {
183 printf("|data : ");
184 print_hex(data, cbData);
185 printf("\n");
186 }
187 }
188 else if(!bIsRead && !bIsWrite && !bIsBlock)
189 {
190 printf("|mode : info\n");
191 }
192 else bIsBadCli = true;
193 }
194
195 if(!bIsBadCli)
196 {
197 nfc_init(&context);
198 if(context)
199 {
200 pnd = nfc_open(context, NULL);
201 if(pnd)
202 {
203 res = nfc_initiator_init(pnd);
204 if(res == NFC_SUCCESS)
205 {
206 printf("Reader : %s - via %s\n ...wait for card...\n", nfc_device_get_name(pnd), nfc_device_get_connstring(pnd));
207
208 res = nfc_initiator_select_passive_target(pnd, nm, NULL, 0, &nt);
209 if (res > 0)
210 {
211 stcurrent = get_info(&nt, true);
212 if(stcurrent)
213 {
214 printf("\n");
215
216 if(bIsBlock && (bIsRead || bIsWrite))
217 {
218 if(bIsRead)
219 {
220 get_block_at(pnd, blockNumber, NULL, 0, true);
221 }
222
223 if(bIsWrite)
224 {
225 set_block_at_confirmed(pnd, blockNumber, data, cbData, true);
226 }
227 }
228 else if(!bIsRead && !bIsWrite && !bIsBlock)
229 {
230 for(i = 0; i < stcurrent->nbNormalBlock; i++)
231 {
232 get_block_at(pnd, i, NULL, 0, true);
233 }
234 display_system_info(pnd, stcurrent);
235 }
236 }
237 }
238 else printf("ERROR - nfc_initiator_select_passive_target: %i\n", res);
239 }
240 else printf("ERROR - nfc_initiator_init: %i\n", res);
241
242 nfc_close(pnd);
243 }
244 else printf("ERROR - nfc_open\n");
245
246 nfc_exit(context);
247 }
248 else printf("ERROR - nfc_init\n");
249 }
250 else
251 {
252 printf(
253 "Usage:\n"
254 " %s [-i]\n"
255 " %s -b N -r\n"
256 " %s -b N [-r] -w ABCD[EF01]\n %s -h\n"
257 "Options:\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"
262 " -h this help\n"
263 "Examples:\n"
264 " %s -i\n"
265 " Display all tag informations\n"
266 " %s -b 0x0e -r\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"
272 "Warnings:\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]);
275 }
276
277 return 0;
278}
279
280bool get_block_at(nfc_device *pnd, uint8_t block, uint8_t *data, uint8_t cbData, bool bPrintIt)
281{
282 bool bRet = false;
283 uint8_t tx[2] = {0x08, block}, rx[ST25TB_SR_BLOCK_MAX_SIZE]; // 4 is the maximum, SR176 (only 2) will fit
284 int res;
285
286 res = nfc_initiator_transceive_bytes(pnd, tx, sizeof(tx), rx, sizeof(rx), 0);
287 if((res == 2) || (res == 4))
288 {
289 if(data)
290 {
291 if(cbData == res)
292 {
293 memcpy(data, rx, res);
294 bRet = true;
295 }
296 else printf("ERROR - We got %i bytes for a %hhu buffer size?\n", res, cbData);
297 }
298 else bRet = true;
299
300 if(bPrintIt)
301 {
302 printf("[0x%02hhx] ", block);
303 print_hex(rx, res);
304 printf("\n");
305 }
306 }
307 else if(res > 0)
308 {
309 printf("ERROR - We got %i bytes?\n", res);
310 }
311 else printf("ERROR - nfc_initiator_transceive_bytes(get): %i\n", res);
312
313 return bRet;
314}
315
316bool set_block_at(nfc_device *pnd, uint8_t block, uint8_t *data, uint8_t cbData, bool bPrintIt)
317{
318 bool bRet = false;
319 uint8_t tx[2 + ST25TB_SR_BLOCK_MAX_SIZE] = {0x09, block}; // 4 is the maximum, SR176 (only 2) will fit
320 int res;
321
322 if(cbData <= ST25TB_SR_BLOCK_MAX_SIZE)
323 {
324 memcpy(tx + 2, data, cbData);
325
326 if(bPrintIt)
327 {
328 printf(">0x%02hhx> ", block);
329 print_hex(data, cbData);
330 printf("\n");
331 }
332
333 res = nfc_initiator_transceive_bytes(pnd, tx, 2 + cbData, NULL, 0, 0);
334 if(res == NFC_ERFTRANS) // ? :')
335 {
336 bRet = true;
337 }
338 else printf("ERROR - nfc_initiator_transceive_bytes(set): %i\n", res);
339 }
340 else printf("ERROR - Wanted to write %hhu bytes, but maximum is %hhu\n", cbData, ST25TB_SR_BLOCK_MAX_SIZE);
341
342 return bRet;
343}
344
345bool set_block_at_confirmed(nfc_device *pnd, uint8_t block, uint8_t *data, uint8_t cbData, bool bPrintIt)
346{
347 bool bRet = false;
348 uint8_t buffer[ST25TB_SR_BLOCK_MAX_SIZE]; // maximum size will be checked in set_block_at
349
350 if(set_block_at(pnd, block, data, cbData, bPrintIt))
351 {
352 if(get_block_at(pnd, block, buffer, cbData, bPrintIt))
353 {
354 if(memcmp(data, buffer, cbData) == 0)
355 {
356 bRet = true;
357 }
358 else if(bPrintIt)
359 {
360 printf("WARNING - not same value readed after write\n");
361 }
362 }
363 }
364
365 return bRet;
366}
367
368void get_info_st25tb512(uint8_t * systemArea)
369{
370 uint8_t b, i;
371
372 b = ((*(uint32_t *) systemArea) >> 15) & 1;
373
374 printf(" | ST reserved : ");
375 for(i = 0; i < 15; i++)
376 {
377 printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
378 }
379 printf("\n | b15 : %hhu - %sOTP (?)\n | OTP_Lock_Reg : ", b, b ? "not " : "");
380 for(i = 16; i < 32; i++)
381 {
382 printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
383 }
384 printf("\n");
385 for(i = 16; i < 32; i++)
386 {
387 if(!(((*(uint32_t *) systemArea) >> i) & 1))
388 {
389 printf(" block 0x%02hhx is write protected\n", ((uint8_t) (i - 16)));
390 }
391 }
392}
393
394void get_info_st25tb2k_4k(uint8_t * systemArea)
395{
396 uint8_t b, i;
397
398 b = ((*(uint32_t *) systemArea) >> 15) & 1;
399
400 printf(" | ST reserved : ");
401 for(i = 0; i < 15; i++)
402 {
403 printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
404 }
405 printf("\n | b15 : %hhu - %sOTP (?)\n | OTP_Lock_RegU: ", b, b ? "not " : "");
406 for(i = 16; i < 24; i++)
407 {
408 printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
409 }
410 printf("\n | OTP_Lock_Reg : ");
411 for(i = 24; i < 32; i++)
412 {
413 printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
414 }
415 printf("\n");
416 if(!(((*(uint32_t *) systemArea) >> 24) & 1))
417 {
418 printf(" blocks 0x07 and 0x08 are write protected\n");
419 }
420 for(i = 25; i < 32; i++)
421 {
422 if(!(((*(uint32_t *) systemArea) >> i) & 1))
423 {
424 printf(" block 0x%02hhx is write protected\n", ((uint8_t) (i - 16)));
425 }
426 }
427}
428
429void get_info_sr176_legacy(uint8_t * systemArea)
430{
431 uint8_t i;
432
433 printf(" | Fixed Chip_ID: 0x%1x\n | ST reserved : ", systemArea[0] & 0x0f);
434 for(i = 4; i < 8; i++)
435 {
436 printf("%hhu", (uint8_t) (((*(uint16_t *) systemArea) >> i) & 1));
437 }
438 printf("\n | OTP_Lock_Reg : ");
439 for(i = 8; i < 16; i++)
440 {
441 printf("%hhu", (uint8_t) (((*(uint16_t *) systemArea) >> i) & 1));
442 }
443 printf("\n");
444 for(i = 8; i < 16; i++)
445 {
446 if(((*(uint16_t *) systemArea) >> i) & 1)
447 {
448 printf(" blocks 0x%02hhx and 0x%02hhx are write protected\n", (uint8_t) ((i - 8) * 2), (uint8_t) (((i - 8) * 2) + 1));
449 }
450 }
451}
452
453void get_info_sri_srt_512_legacy(uint8_t * systemArea)
454{
455 uint8_t b, i;
456
457 b = ((*(uint32_t *) systemArea) >> 15) & 1;
458
459 printf(" | Fixed Chip_ID: 0x%02hhx\n | ST reserved : ", systemArea[0]);
460 for(i = 8; i < 15; i++)
461 {
462 printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
463 }
464 printf("\n | b15 : %hhu - %sOTP (?)\n | OTP_Lock_Reg : ", b, b ? "not " : "");
465 for(i = 16; i < 32; i++)
466 {
467 printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
468 }
469 printf("\n");
470 for(i = 16; i < 32; i++)
471 {
472 if(!(((*(uint32_t *) systemArea) >> i) & 1))
473 {
474 printf(" block 0x%02hhx is write protected\n", (uint8_t) (i - 16));
475 }
476 }
477}
478
479void get_info_sri2k_4k_srix4k_srix512_legacy(uint8_t * systemArea)
480{
481 uint8_t i;
482
483 printf(" | Fixed Chip_ID: 0x%02hhx\n | ST reserved : ", systemArea[0]);
484 for(i = 8; i < 24; i++)
485 {
486 printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
487 }
488 printf("\n | OTP_Lock_Reg : ");
489 for(i = 24; i < 32; i++)
490 {
491 printf("%hhu", (uint8_t) (((*(uint32_t *) systemArea) >> i) & 1));
492 }
493 printf("\n");
494 if(!(((*(uint32_t *) systemArea) >> 24) & 1))
495 {
496 printf(" blocks 0x07 and 0x08 are write protected\n");
497 }
498 for(i = 25; i < 32; i++)
499 {
500 if(!(((*(uint32_t *) systemArea) >> i) & 1))
501 {
502 printf(" block 0x%02hhx is write protected\n", (uint8_t) (i - 16));
503 }
504 }
505}
506
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},
512};
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},
522};
523
524const st_data * get_info(const nfc_target *pnt, bool bPrintIt)
525{
526 const st_data *currentData = NULL;
527 const uint8_t *p;
528 uint8_t chipId, i;
529
530 if(pnt->nm.nmt == NMT_ISO14443B2SR)
531 {
532 printf("Target : %s (%s)\nUID : ", str_nfc_modulation_type(pnt->nm.nmt), str_nfc_baud_rate(pnt->nm.nbr));
533 print_hex(pnt->nti.nsi.abtUID, sizeof(pnt->nti.nsi.abtUID));
534 printf("\n");
535
536 p = pnt->nti.nsi.abtUID;
537 if(p[7] == 0xd0) // ST25TB* / SR*
538 {
539 chipId = p[5];
540 printf("Manuf : 0x%02hhx - %s\n", p[6], (p[6] == 0x02) ? "STMicroelectronics" : "other");
541
542 for(i = 0; i < (sizeof(STRefs) / sizeof(STRefs[0])); i++)
543 {
544 if(chipId == STRefs[i].chipId)
545 {
546 currentData = &STRefs[i];
547 break;
548 }
549 }
550
551 if(!currentData)
552 {
553 chipId >>= 2;
554 for(i = 0; i < (sizeof(STRefs_legacy) / sizeof(STRefs_legacy[0])); i++)
555 {
556 if(chipId == STRefs_legacy[i].chipId)
557 {
558 currentData = &STRefs_legacy[i];
559 break;
560 }
561 }
562 }
563
564 if(bPrintIt && currentData)
565 {
566 printf("ChipId : 0x%02hhx - %s%s\nSerial : 0x", currentData->chipId, currentData->szName, currentData->bIsLegacy ? " (legacy)" : "");
567 if(currentData->bIsLegacy)
568 {
569 printf("%1hhx", (uint8_t) (p[5] & 0x03));
570 }
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);
572 }
573 }
574 else printf("WARNI - Last byte of UID isn\'t 0xd0, but 0x%02hhx (not ST25TB / SR series?)\n", p[7]);
575 }
576 else printf("ERROR - not a NMT_ISO14443B2SR ?\n");
577
578 return currentData;
579}
580
581void display_system_info(nfc_device *pnd, const st_data * stdata)
582{
583 uint8_t systemArea[ST25TB_SR_BLOCK_MAX_SIZE];
584
585 if(get_block_at(pnd, stdata->bnSystem, systemArea, stdata->blockSize, true))
586 {
587 if(stdata->pfnGetInfo)
588 {
589 stdata->pfnGetInfo(systemArea);
590 }
591 }
592}
593
594void print_hex(const uint8_t *pbtData, const size_t szBytes)
595{
596 size_t szPos;
597 for (szPos = 0; szPos < szBytes; szPos++)
598 {
599 printf("%02hhx ", pbtData[szPos]);
600 }
601}
602
const char * nfc_device_get_name(nfc_device *pnd)
Returns the device name.
Definition nfc.c:1213
const char * nfc_device_get_connstring(nfc_device *pnd)
Returns the device connection string.
Definition nfc.c:1225
void nfc_close(nfc_device *pnd)
Close from a NFC device.
Definition nfc.c:339
nfc_device * nfc_open(nfc_context *context, const nfc_connstring connstring)
Open a NFC device.
Definition nfc.c:277
#define NFC_ERFTRANS
Definition nfc.h:205
#define NFC_SUCCESS
Definition nfc.h:155
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.
Definition nfc.c:813
int nfc_initiator_init(nfc_device *pnd)
Initialize NFC device as initiator (reader)
Definition nfc.c:493
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.
Definition nfc.c:562
void nfc_exit(nfc_context *context)
Deinitialize libnfc. Should be called after closing all open devices and before your application term...
Definition nfc.c:248
void nfc_init(nfc_context **context)
Initialize libnfc. This function must be called before calling any other libnfc function.
Definition nfc.c:231
const char * str_nfc_modulation_type(const nfc_modulation_type nmt)
Convert nfc_modulation_type value to string.
Definition nfc.c:1387
const char * str_nfc_baud_rate(const nfc_baud_rate nbr)
Convert nfc_baud_rate value to string.
Definition nfc.c:1363
libnfc interface
NFC library context Struct which contains internal options, references, pointers, etc....
NFC device information.
NFC modulation structure.
Definition nfc-types.h:342
NFC target structure.
Definition nfc-types.h:351