65 #if defined(WIN32) && defined(__GNUC__)
73 print_usage(
char *progname)
75 fprintf(stderr,
"usage: %s [-q] -o FILE\n", progname);
76 fprintf(stderr,
"\nOptions:\n");
77 fprintf(stderr,
" -o FILE Extract NDEF message if available in FILE\n");
78 fprintf(stderr,
" -o - Extract NDEF message if available to stdout\n");
79 fprintf(stderr,
" -q Be quiet, don't display Attribute Block parsing info\n");
82 static void stop_select(
int sig)
94 build_felica_frame(
const nfc_felica_info nfi,
const uint8_t command,
const uint8_t *payload,
const size_t payload_len, uint8_t *frame,
size_t *frame_len)
96 frame[0] = 1 + 1 + 8 + payload_len;
97 *frame_len = frame[0];
99 memcpy(frame + 2, nfi.abtId, 8);
100 memcpy(frame + 10, payload, payload_len);
105 nfc_forum_tag_type3_check(
nfc_device *dev,
const nfc_target *nt,
const uint16_t block,
const uint8_t block_count, uint8_t *data,
size_t *data_len)
107 uint8_t payload[1024] = {
114 size_t payload_len = 1 + 2 + 1;
115 for (uint8_t b = 0; b < block_count; b++) {
117 payload[payload_len++] = 0x80;
118 payload[payload_len++] = block + b;
120 payload[payload_len++] = 0x00;
121 payload[payload_len++] = (block + b) >> 8;
122 payload[payload_len++] = (block + b) & 0xff;
127 size_t frame_len =
sizeof(frame);
128 build_felica_frame(nt->nti.nfi, CHECK, payload, payload_len, frame, &frame_len);
136 const int res_overhead = 1 + 1 + 8 + 2;
137 if (res < res_overhead) {
141 uint8_t felica_res_len = rx[0];
142 if (res != felica_res_len) {
146 if ((CHECK + 1) != rx[1]) {
150 if (0 != memcmp(&rx[2], nt->nti.nfi.abtId, 8)) {
154 const uint8_t status_flag1 = rx[10];
155 const uint8_t status_flag2 = rx[11];
156 if ((status_flag1) || (status_flag2)) {
158 fprintf(stderr,
"Status bytes: %02x, %02x\n", status_flag1, status_flag2);
162 *data_len = res - res_overhead + 1;
163 memcpy(data, &rx[res_overhead + 1], *data_len);
168 main(
int argc,
char *argv[])
175 char *ndef_output = NULL;
176 while ((ch = getopt(argc, argv,
"hqo:")) != -1) {
179 print_usage(argv[0]);
185 ndef_output = optarg;
188 print_usage(argv[0]);
193 if (ndef_output == NULL) {
194 print_usage(argv[0]);
197 FILE *message_stream = NULL;
198 FILE *ndef_stream = NULL;
200 if ((strlen(ndef_output) == 1) && (ndef_output[0] ==
'-')) {
201 message_stream = stderr;
202 ndef_stream = stdout;
204 message_stream = stdout;
205 ndef_stream = fopen(ndef_output,
"wb");
207 fprintf(stderr,
"Could not open file %s.\n", ndef_output);
213 if (context == NULL) {
214 ERR(
"Unable to init libnfc (malloc)\n");
221 ERR(
"Unable to open NFC device");
236 signal(SIGINT, stop_select);
249 fprintf(message_stream,
"Place your NFC Forum Tag Type 3 in the field...\n");
253 const uint8_t *pbtSensfReq = (uint8_t *)
"\x00\xff\xff\x01\x00";
255 nfc_perror(pnd,
"nfc_initiator_select_passive_target");
263 const uint8_t abtNfcForumSysCode[] = { 0x12, 0xfc };
264 if (0 != memcmp(nt.nti.nfi.abtSysCode, abtNfcForumSysCode, 2)) {
266 const uint8_t *pbtSensfReqNfcForum = (uint8_t *)
"\x00\x12\xfc\x01\x00";
268 nfc_perror(pnd,
"nfc_initiator_select_passive_target");
275 if (0 != memcmp(nt.nti.nfi.abtSysCode, abtNfcForumSysCode, 2)) {
276 fprintf(stderr,
"Tag is not NFC Forum Tag Type 3 compliant.\n");
287 nfc_perror(pnd,
"nfc_device_set_property_bool");
295 size_t data_len =
sizeof(data);
297 if (nfc_forum_tag_type3_check(pnd, &nt, 0, 1, data, &data_len) <= 0) {
305 const int ndef_major_version = (data[0] & 0xf0) >> 4;
306 const int ndef_minor_version = (data[0] & 0x0f);
307 const int ndef_nbr = data[1];
308 const int ndef_nbw = data[2];
309 const int ndef_nmaxb = (data[3] << 8) + data[4];
310 const int ndef_writeflag = data[9];
311 const int ndef_rwflag = data[10];
312 uint32_t ndef_data_len = (data[11] << 16) + (data[12] << 8) + data[13];
313 uint16_t ndef_calculated_checksum = 0;
314 for (
size_t n = 0; n < 14; n++)
315 ndef_calculated_checksum += data[n];
316 const uint16_t ndef_checksum = (data[14] << 8) + data[15];
319 fprintf(message_stream,
"NDEF Attribute Block:\n");
320 fprintf(message_stream,
"* Mapping version: %d.%d\n", ndef_major_version, ndef_minor_version);
321 fprintf(message_stream,
"* Maximum nr of blocks to read by Check Command: %3d block%s\n", ndef_nbr, ndef_nbr > 1 ?
"s" :
"");
322 fprintf(message_stream,
"* Maximum nr of blocks to write by Update Command: %3d block%s\n", ndef_nbw, ndef_nbw > 1 ?
"s" :
"");
323 fprintf(message_stream,
"* Maximum nr of blocks available for NDEF data: %3d block%s (%d bytes)\n", ndef_nmaxb, ndef_nmaxb > 1 ?
"s" :
"", ndef_nmaxb * 16);
324 fprintf(message_stream,
"* NDEF writing state: ");
325 switch (ndef_writeflag) {
327 fprintf(message_stream,
"finished (0x00)\n");
330 fprintf(message_stream,
"in progress (0x0F)\n");
333 fprintf(message_stream,
"invalid (0x%02X)\n", ndef_writeflag);
336 fprintf(message_stream,
"* NDEF Access Attribute: ");
337 switch (ndef_rwflag) {
339 fprintf(message_stream,
"Read only (0x00)\n");
342 fprintf(message_stream,
"Read/Write (0x01)\n");
345 fprintf(message_stream,
"invalid (0x%02X)\n", ndef_rwflag);
348 fprintf(message_stream,
"* NDEF message length: %d bytes\n", ndef_data_len);
349 if (ndef_calculated_checksum != ndef_checksum) {
350 fprintf(message_stream,
"* Checksum: fail (0x%04X != 0x%04X)\n", ndef_calculated_checksum, ndef_checksum);
352 fprintf(message_stream,
"* Checksum: ok (0x%04X)\n", ndef_checksum);
356 if (ndef_calculated_checksum != ndef_checksum) {
357 fprintf(stderr,
"Error: Checksum failed! Exiting now.\n");
364 if (!ndef_data_len) {
365 fprintf(stderr,
"Error: empty NFC Forum Tag Type 3, nothing to read!\n");
372 const uint8_t block_max_per_check = data[1];
373 const uint16_t block_count_to_check = (ndef_data_len / 16) + 1;
376 for (uint16_t b = 0; b < ((block_count_to_check - 1) / block_max_per_check + 1); b += block_max_per_check) {
377 size_t size =
sizeof(data) - data_len;
378 if (!nfc_forum_tag_type3_check(pnd, &nt, 1 + b, MIN(block_max_per_check, (block_count_to_check - (b * block_max_per_check))), data + data_len, &size)) {
388 if (fwrite(data, 1, ndef_data_len, ndef_stream) != ndef_data_len) {
389 fprintf(stderr,
"Error: could not write to file.\n");
396 fprintf(stderr,
"%i bytes written to %s\n", ndef_data_len, ndef_output);
const char * nfc_device_get_name(nfc_device *pnd)
Returns the device name.
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_abort_command(nfc_device *pnd)
Abort current running command.
void nfc_perror(const nfc_device *pnd, const char *pcString)
Display the last error occured on 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.
int nfc_device_set_property_bool(nfc_device *pnd, const nfc_property property, const bool bEnable)
Set a device's boolean-property value.
Provide some examples shared functions like print, parity calculation, options parsing.
#define ERR(...)
Print a error message.
NFC library context Struct which contains internal options, references, pointers, etc....
NFC FeLiCa tag information.
NFC modulation structure.