54 #endif // HAVE_CONFIG_H
65 #if defined(WIN32) && defined(__GNUC__)
73 print_usage(
char *progname)
75 fprintf(stderr,
"usage: %s -o FILE\n", progname);
76 fprintf(stderr,
"\nOptions:\n");
77 fprintf(stderr,
" -o Extract NDEF message if available in FILE\n");
80 static void stop_select(
int sig)
92 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)
94 frame[0] = 1 + 1 + 8 + payload_len;
95 *frame_len = frame[0];
97 memcpy(frame + 2, nfi.abtId, 8);
98 memcpy(frame + 10, payload, payload_len);
103 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)
105 uint8_t payload[1024] = {
112 size_t payload_len = 1 + 2 + 1;
113 for (uint8_t b = 0; b < block_count; b++) {
115 payload[payload_len++] = 0x80;
116 payload[payload_len++] = block + b;
118 payload[payload_len++] = 0x00;
119 payload[payload_len++] = (block + b) >> 8;
120 payload[payload_len++] = (block + b) & 0xff;
125 size_t frame_len =
sizeof(frame);
126 build_felica_frame(nt.nti.nfi, CHECK, payload, payload_len, frame, &frame_len);
133 const int res_overhead = 1 + 1 + 8 + 2;
134 if (res < res_overhead) {
138 uint8_t felica_res_len = rx[0];
139 if (res != felica_res_len) {
143 if ((CHECK + 1) != rx[1]) {
147 if (0 != memcmp(&rx[2], nt.nti.nfi.abtId, 8)) {
151 const uint8_t status_flag1 = rx[10];
152 const uint8_t status_flag2 = rx[11];
153 if ((status_flag1) || (status_flag2)) {
155 fprintf(stderr,
"Status bytes: %02x, %02x\n", status_flag1, status_flag2);
159 *data_len = res - res_overhead + 1;
160 memcpy(data, &rx[res_overhead + 1], *data_len);
165 main(
int argc,
char *argv[])
171 char *ndef_output = NULL;
172 while ((ch = getopt(argc, argv,
"ho:")) != -1) {
175 print_usage(argv[0]);
179 ndef_output = optarg;
183 fprintf(stderr,
"Option -%c requires an argument.\n", optopt);
185 print_usage(argv[0]);
190 if (ndef_output == NULL) {
191 print_usage(argv[0]);
194 FILE *message_stream = NULL;
195 FILE *ndef_stream = NULL;
197 if ((strlen(ndef_output) == 1) && (ndef_output[0] ==
'-')) {
198 message_stream = stderr;
199 ndef_stream = stdout;
201 message_stream = stdout;
202 ndef_stream = fopen(ndef_output,
"wb");
204 fprintf(stderr,
"Could not open file %s.\n", ndef_output);
210 if (context == NULL) {
211 ERR(
"Unable to init libnfc (malloc)\n");
218 ERR(
"Unable to open NFC device");
231 signal(SIGINT, stop_select);
242 fprintf(message_stream,
"Place your NFC Forum Tag Type 3 in the field...\n");
245 const uint8_t *pbtSensfReq = (uint8_t *)
"\x00\xff\xff\x01\x00";
247 nfc_perror(pnd,
"nfc_initiator_select_passive_target");
255 const uint8_t abtNfcForumSysCode[] = { 0x12, 0xfc };
256 if (0 != memcmp(nt.nti.nfi.abtSysCode, abtNfcForumSysCode, 2)) {
258 const uint8_t *pbtSensfReqNfcForum = (uint8_t *)
"\x00\x12\xfc\x01\x00";
260 nfc_perror(pnd,
"nfc_initiator_select_passive_target");
267 if (0 != memcmp(nt.nti.nfi.abtSysCode, abtNfcForumSysCode, 2)) {
268 fprintf(stderr,
"Tag is not NFC Forum Tag Type 3 compliant.\n");
279 nfc_perror(pnd,
"nfc_device_set_property_bool");
287 size_t data_len =
sizeof(data);
289 if (nfc_forum_tag_type3_check(pnd, nt, 0, 1, data, &data_len) <= 0) {
297 const int ndef_major_version = (data[0] & 0xf0) >> 4;
298 const int ndef_minor_version = (data[0] & 0x0f);
299 fprintf(message_stream,
"NDEF Mapping version: %d.%d\n", ndef_major_version, ndef_minor_version);
301 const int available_block_count = (data[3] << 8) + data[4];
302 fprintf(message_stream,
"NFC Forum Tag Type 3 capacity: %d bytes\n", available_block_count * 16);
304 uint32_t ndef_data_len = (data[11] << 16) + (data[12] << 8) + data[13];
305 fprintf(message_stream,
"NDEF data length: %d bytes\n", ndef_data_len);
307 uint16_t ndef_calculated_checksum = 0;
308 for (
size_t n = 0; n < 14; n++)
309 ndef_calculated_checksum += data[n];
311 const uint16_t ndef_checksum = (data[14] << 8) + data[15];
312 if (ndef_calculated_checksum != ndef_checksum) {
313 fprintf(stderr,
"NDEF CRC does not match with calculated one\n");
320 if (!ndef_data_len) {
321 fprintf(stderr,
"Empty NFC Forum Tag Type 3\n");
328 const uint8_t block_max_per_check = data[1];
329 const uint16_t block_count_to_check = (ndef_data_len / 16) + 1;
332 for (uint16_t b = 0; b < (block_count_to_check / block_max_per_check); b += block_max_per_check) {
333 size_t size =
sizeof(data) - data_len;
334 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)) {
343 if (fwrite(data, 1, data_len, ndef_stream) != data_len) {
344 fprintf(stderr,
"Could not write to file.\n");