2 * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
4 * Licensed under the Flora License, Version 1.1 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://floralicense.org/license/
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
27 #include "ndef-tool.h"
29 static GMainLoop *main_loop = NULL;
31 void _activation_complete_cb(net_nfc_message_e message, net_nfc_error_e result,
32 void *data, void *user_param, void *trans_data)
36 case NET_NFC_MESSAGE_INIT :
37 if (result == NET_NFC_OK)
38 fprintf(stdout, "power on success\n\n");
40 fprintf(stdout, "failed to power on (%d)\n\n", result);
42 net_nfc_unset_response_callback();
43 net_nfc_client_deinitialize();
44 g_main_loop_quit(main_loop);
47 case NET_NFC_MESSAGE_DEINIT :
48 if (result == NET_NFC_OK)
49 fprintf(stdout, "power off success\n\n");
51 fprintf(stdout, "failed to power off (%d)\n\n", result);
53 net_nfc_unset_response_callback();
54 net_nfc_client_deinitialize();
55 g_main_loop_quit(main_loop);
63 int ndef_tool_read_ndef_message_from_file(const char *file_name, ndef_message_h *msg)
68 file = fopen(file_name, "rb");
71 long int file_size = 0;
74 fseek(file, 0, SEEK_END);
75 file_size = ftell(file);
76 fseek(file, 0, SEEK_SET);
82 net_nfc_create_data(&data, NULL, file_size);
85 read = fread((void *)net_nfc_get_data_buffer(data), 1, file_size, file);
87 net_nfc_create_ndef_message_from_rawdata(msg, data);
89 net_nfc_free_data(data);
101 int ndef_tool_write_ndef_message_to_file(const char *file_name, ndef_message_h msg)
107 net_nfc_create_rawdata_from_ndef_message(msg, &data);
110 file = fopen(file_name, "wb");
113 fwrite((void *)net_nfc_get_data_buffer(data), 1, net_nfc_get_data_length(data), file);
120 net_nfc_free_data(data);
126 static void print_usage(char *file_name)
128 fprintf(stdout, "Usage : %s OPERATION [OPTION]... FILE\n", file_name);
129 fprintf(stdout, "\n");
130 fprintf(stdout, " Operation\n");
131 fprintf(stdout, " -a, --append-record Append a record to file\n");
132 fprintf(stdout, " Options\n");
133 fprintf(stdout, " -t, --tnf tnf Input TNF value\n");
134 fprintf(stdout, " (WKT : Well-known, EXT : External, \n");
135 fprintf(stdout, " MIME : MIME-type, URI : Absolute-URI)\n");
136 fprintf(stdout, " -T, --type-data data Input Type-field data\n");
137 fprintf(stdout, " -I, --id-data data Input ID-field data\n");
138 fprintf(stdout, " -P, --payload-data data Input Payload-field data. You can input hexa-style data using '%%' prefix\n");
139 fprintf(stdout, " ex) (0x20)abc : %%20abc\n");
140 fprintf(stdout, " it is possible to input '%%' by using '%%%%'\n");
141 fprintf(stdout, " ex) 120%%20 : 120%%%%20\n");
142 fprintf(stdout, " --payload-file file Input Payload-field data from binary file\n");
143 fprintf(stdout, " -E, --encoding data Input encoding method of Well-known Text type record\n");
144 fprintf(stdout, "\n");
145 fprintf(stdout, " -r, --remove-record Remove a specific record from file\n");
146 fprintf(stdout, " Options\n");
147 fprintf(stdout, " -i, --index value Input a record index\n");
148 fprintf(stdout, "\n");
149 fprintf(stdout, " -d, --display Display all records in file\n");
150 fprintf(stdout, " -s, --sign-records Sign some continuous records in file\n");
151 fprintf(stdout, " Options\n");
152 fprintf(stdout, " -b, --begin-index value Input a beginning record index\n");
153 fprintf(stdout, " -e, --end-index value Input a last record index\n");
154 fprintf(stdout, " -c, --cert-file file Input a PKCS #12 certificate file (DER file, not PEM file)\n");
155 fprintf(stdout, " -p, --password pass Input a password of PKCS #12 certificate file\n");
156 fprintf(stdout, "\n");
157 fprintf(stdout, " -v, --verify-signed-records Verify signature in file\n");
158 fprintf(stdout, " --read-tag Read a ndef from tag and store to file\n");
159 fprintf(stdout, " --write-tag Write a ndef file to tag\n");
160 fprintf(stdout, " --receive-ndef Receive a ndef from target device and store to file\n");
161 fprintf(stdout, " --send-ndef Send a ndef file to target device\n");
162 fprintf(stdout, " --handover Try to handover another carrier\n");
163 fprintf(stdout, "\n");
164 fprintf(stdout, " -h, --help Show this help messages\n");
165 fprintf(stdout, "\n");
168 static net_nfc_record_tnf_e _parse_tnf_string(const char *tnf)
170 net_nfc_record_tnf_e result = -1;
175 if (strncasecmp(tnf, "EMT", 3) == 0)
177 result = NET_NFC_RECORD_EMPTY;
179 else if (strncasecmp(tnf, "WKT", 3) == 0)
181 result = NET_NFC_RECORD_WELL_KNOWN_TYPE;
183 else if (strncasecmp(tnf, "MIME", 4) == 0)
185 result = NET_NFC_RECORD_MIME_TYPE;
187 else if (strncasecmp(tnf, "URI", 3) == 0)
189 result = NET_NFC_RECORD_URI;
191 else if (strncasecmp(tnf, "EXT", 3) == 0)
193 result = NET_NFC_RECORD_EXTERNAL_RTD;
195 else if (strncasecmp(tnf, "UNK", 3) == 0)
197 result = NET_NFC_RECORD_UNKNOWN;
199 else if (strncasecmp(tnf, "UNC", 3) == 0)
201 result = NET_NFC_RECORD_UNCHAGNED;
207 static int _append_record_to_file(const char *file_name, ndef_record_h record)
210 ndef_message_h msg = NULL;
212 if (ndef_tool_read_ndef_message_from_file(file_name, &msg) <= 0)
214 net_nfc_create_ndef_message(&msg);
217 net_nfc_append_record_to_ndef_message(msg, record);
219 ndef_tool_write_ndef_message_to_file(file_name, msg);
221 net_nfc_free_ndef_message(msg);
228 ndef_record_h _create_record(net_nfc_record_tnf_e tnf, data_h type, data_h id , data_h payload, char *encoding)
230 ndef_record_h result = NULL;
234 case NET_NFC_RECORD_WELL_KNOWN_TYPE :
235 if (net_nfc_get_data_length(type) == 1 && memcmp((void *)net_nfc_get_data_buffer(type), "T", 1) == 0)
237 if (encoding == NULL)
239 fprintf(stdout, "encoding type is not present.\n");
243 char *temp_str = calloc(1, net_nfc_get_data_length(payload) + 1);
244 memcpy(temp_str, (void *)net_nfc_get_data_buffer(payload), net_nfc_get_data_length(payload));
246 net_nfc_create_text_type_record(&result, temp_str, encoding, NET_NFC_ENCODE_UTF_8);
251 net_nfc_set_record_id(result, id);
254 else if (net_nfc_get_data_length(type) == 1 && memcmp((void *)net_nfc_get_data_buffer(type), "U", 1) == 0)
256 char *temp_str = calloc(1, net_nfc_get_data_length(payload) + 1);
257 memcpy(temp_str, (void *)net_nfc_get_data_buffer(payload), net_nfc_get_data_length(payload));
259 net_nfc_create_uri_type_record(&result, temp_str, 0);
264 net_nfc_set_record_id(result, id);
269 net_nfc_create_record(&result, tnf, type, id, payload);
274 net_nfc_create_record(&result, tnf, type, id, payload);
281 bool _remove_record_from_file(const char *file_name, int index)
284 ndef_message_h msg = NULL;
286 if (ndef_tool_read_ndef_message_from_file(file_name, &msg) > 0)
288 net_nfc_remove_record_by_index(msg, index);
290 ndef_tool_write_ndef_message_to_file(file_name, msg);
292 net_nfc_free_ndef_message(msg);
300 #define __IS_SHORT_OPTION(__dst) ((strlen(__dst) == 2) && ((__dst)[0] == '-'))
301 #define __IS_LONG_OPTION(__dst) ((strlen(__dst) > 2) && ((__dst)[0] == '-') && ((__dst)[1] == '-'))
302 #define __IS_OPTION(__dst) (__IS_SHORT_OPTION(__dst) || __IS_LONG_OPTION(__dst))
304 #define __COMPARE_OPTION(__dst, __s, __l) \
305 ((__IS_SHORT_OPTION(__dst) && ((__dst)[1] == (__s))) || \
306 (__IS_LONG_OPTION(__dst) && (strcmp((__dst) + 2, (__l)) == 0)))
308 #define __DO_NEXT_ARG \
309 if (++i >= argc || __IS_OPTION(argv[i]) == true) \
311 operation = OPERATION_ERROR; \
315 int main(int argc, char *argv[])
317 int remove_index = -1;
318 int begin_index = -1;
320 int operation = OPERATION_ERROR;
321 net_nfc_record_tnf_e tnf = -1;
324 data_h payload = NULL;
325 char *file_name = NULL;
326 char *cert_file = NULL;
327 char *password = NULL;
328 char *encoding = NULL;
329 ndef_record_h record = NULL;
334 for (i = 1; i < argc; i++)
336 if (__COMPARE_OPTION(argv[i], 'a', "append-record"))
338 operation = OPERATION_APPEND;
340 else if (__COMPARE_OPTION(argv[i], 's', "sign-records"))
342 operation = OPERATION_SIGN;
344 else if (__COMPARE_OPTION(argv[i], 'd', "display-record"))
346 operation = OPERATION_DISPLAY;
348 else if (__COMPARE_OPTION(argv[i], 'v', "verify-signed-records"))
350 operation = OPERATION_VERIFY;
352 else if (__COMPARE_OPTION(argv[i], 'r', "remove-record"))
354 operation = OPERATION_REMOVE;
356 else if (__COMPARE_OPTION(argv[i], 0, "read-tag"))
358 operation = OPERATION_READ_TAG;
360 else if (__COMPARE_OPTION(argv[i], 0, "write-tag"))
362 operation = OPERATION_WRITE_TAG;
364 else if (__COMPARE_OPTION(argv[i], 0, "receive-ndef"))
366 operation = OPERATION_RECEIVE_NDEF;
368 else if (__COMPARE_OPTION(argv[i], 0, "send-ndef"))
370 operation = OPERATION_SEND_NDEF;
372 else if (__COMPARE_OPTION(argv[i], 0, "handover"))
374 operation = OPERATION_HANDOVER;
376 else if (__COMPARE_OPTION(argv[i], 0, "off")) /* hidden operation */
378 operation = OPERATION_OFF;
380 else if (__COMPARE_OPTION(argv[i], 0, "on")) /* hidden operation */
382 operation = OPERATION_ON;
384 else if (__COMPARE_OPTION(argv[i], 0, "send-apdu")) /* hidden operation */
386 operation = OPERATION_SEND_APDU;
388 else if (__COMPARE_OPTION(argv[i], 0, "set-se")) /* hidden operation */
390 operation = OPERATION_SET_SE;
392 else if (__COMPARE_OPTION(argv[i], 'i', "record-index"))
395 remove_index = atoi(argv[i]);
397 else if (__COMPARE_OPTION(argv[i], 'c', "cert-file"))
400 cert_file = strdup(argv[i]);
402 else if (__COMPARE_OPTION(argv[i], 'p', "password"))
405 password = strdup(argv[i]);
407 else if (__COMPARE_OPTION(argv[i], 'b', "begin-index"))
410 begin_index = atoi(argv[i]);
412 else if (__COMPARE_OPTION(argv[i], 'e', "end-index"))
415 end_index = atoi(argv[i]);
417 else if (__COMPARE_OPTION(argv[i], 't', "tnf"))
420 tnf = _parse_tnf_string(argv[i]);
422 else if (__COMPARE_OPTION(argv[i], 'T', "type-data"))
425 len = strlen(argv[i]);
428 net_nfc_create_data(&type, (const uint8_t *)argv[i], len);
431 else if (__COMPARE_OPTION(argv[i], 'I', "id-data"))
434 len = strlen(argv[i]);
437 net_nfc_create_data(&id, (const uint8_t *)argv[i], len);
440 else if (__COMPARE_OPTION(argv[i], 'P', "payload-data"))
443 len = strlen(argv[i]);
446 uint8_t *buffer = NULL;
448 buffer = calloc(1, len);
453 for (j = 0; j < len; j++)
455 if (argv[i][j] == '%')
459 if (argv[i][j + 1] != '%')
461 char temp[3] = { 0, };
463 temp[0] = argv[i][j + 1];
464 temp[1] = argv[i][j + 2];
466 buffer[current++] = (uint8_t)strtol(temp, NULL, 16);
471 buffer[current++] = '%';
475 else if (j + 1 < len)
477 if (argv[i][j + 1] == '%')
479 buffer[current++] = '%';
484 buffer[current++] = argv[i][j];
489 /* invalid param. error? */
494 buffer[current++] = argv[i][j];
498 net_nfc_create_data(&payload, buffer, current);
504 else if (__COMPARE_OPTION(argv[i], 0, "payload-file"))
507 len = strlen(argv[i]);
512 file = fopen(argv[i], "rb");
515 long int file_size = 0;
518 fseek(file, 0, SEEK_END);
519 file_size = ftell(file);
520 fseek(file, 0, SEEK_SET);
524 uint8_t *buffer = NULL;
526 buffer = calloc(1, file_size);
529 read = fread(buffer, 1, file_size, file);
531 net_nfc_create_data(&payload, buffer, read);
541 else if (__COMPARE_OPTION(argv[i], 'E', "encoding"))
544 encoding = strdup(argv[i]);
546 else if (__COMPARE_OPTION(argv[i], 'h', "help"))
548 operation = OPERATION_ERROR;
553 if (file_name == NULL)
555 file_name = strdup(argv[i]);
559 operation = OPERATION_ERROR;
565 if (operation != OPERATION_ON && operation != OPERATION_OFF && file_name == NULL)
566 operation = OPERATION_ERROR;
570 case OPERATION_DISPLAY :
571 ndef_tool_display_ndef_message_from_file(file_name);
574 case OPERATION_APPEND :
575 if (tnf >= 0 && type != NULL)
577 record = _create_record(tnf, type, id, payload, encoding);
581 _append_record_to_file(file_name, record);
583 ndef_tool_display_ndef_message_from_file(file_name);
587 print_usage(argv[0]);
592 print_usage(argv[0]);
596 case OPERATION_REMOVE :
597 _remove_record_from_file(file_name, remove_index);
598 ndef_tool_display_ndef_message_from_file(file_name);
601 case OPERATION_SIGN :
602 if (begin_index < 0 || end_index < 0 || begin_index > end_index || cert_file == NULL || password == NULL)
604 print_usage(argv[0]);
608 fprintf(stdout, "file : %s\ncert file : %s\npassword : %s\nbegin index : %d\nend index : %d\n", file_name, cert_file, password, begin_index, end_index);
609 ndef_tool_sign_message_from_file(file_name, begin_index, end_index, cert_file, password);
610 ndef_tool_display_ndef_message_from_file(file_name);
614 case OPERATION_VERIFY :
615 fprintf(stdout, "verify %s\n", ndef_tool_verify_message_from_file(file_name) ? "success" : "failed");
618 case OPERATION_READ_TAG :
619 ndef_tool_read_ndef_from_tag(file_name);
622 case OPERATION_WRITE_TAG :
623 ndef_tool_write_ndef_to_tag(file_name);
626 case OPERATION_RECEIVE_NDEF :
627 ndef_tool_receive_ndef_via_p2p(file_name);
630 case OPERATION_SEND_NDEF :
631 ndef_tool_send_ndef_via_p2p(file_name);
634 case OPERATION_HANDOVER :
635 ndef_tool_connection_handover(file_name);
642 net_nfc_get_state(&state);
646 fprintf(stdout, "Power on....\n\n");
648 if(!g_thread_supported())
653 main_loop = g_main_new(true);
655 net_nfc_client_initialize();
656 net_nfc_set_response_callback(_activation_complete_cb, NULL);
657 net_nfc_set_state(true, NULL);
659 g_main_loop_run(main_loop);
663 fprintf(stdout, "Already power is on.\n\n");
672 net_nfc_get_state(&state);
676 fprintf(stdout, "Power off....\n\n");
678 if(!g_thread_supported())
683 main_loop = g_main_new(true);
685 net_nfc_client_initialize();
686 net_nfc_set_response_callback(_activation_complete_cb, NULL);
687 net_nfc_set_state(false, NULL);
689 g_main_loop_run(main_loop);
693 fprintf(stdout, "Already power is off.\n\n");
698 case OPERATION_SEND_APDU :
699 ndef_tool_send_apdu(file_name);
702 case OPERATION_SET_SE :
703 net_nfc_client_initialize();
705 if (strcmp(file_name, "SIM1") == 0) {
706 net_nfc_set_secure_element_type(NET_NFC_SE_TYPE_UICC, NULL);
707 } else if (strcmp(file_name, "eSE") == 0) {
708 net_nfc_set_secure_element_type(NET_NFC_SE_TYPE_ESE, NULL);
710 fprintf(stdout, "Unknown SE name.\n\n");
714 case OPERATION_ERROR :
716 print_usage(argv[0]);