New api was added for card emulation on/off
[platform/core/connectivity/nfc-manager-neard.git] / tools / ndef-tool / ndef-tool.c
1 /*
2  * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  *     http://floralicense.org/license/
9  *
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.
15  */
16
17
18 #include <stddef.h>
19 #include <stdint.h>
20 #include <stdbool.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <glib.h>
25
26 #include "net_nfc.h"
27 #include "ndef-tool.h"
28
29 static GMainLoop *main_loop = NULL;
30
31 void _activation_complete_cb(net_nfc_message_e message, net_nfc_error_e result,
32                 void *data, void *user_param, void *trans_data)
33 {
34         switch (message)
35         {
36         case NET_NFC_MESSAGE_INIT :
37                 if (result == NET_NFC_OK)
38                         fprintf(stdout, "power on success\n\n");
39                 else
40                         fprintf(stdout, "failed to power on (%d)\n\n", result);
41
42                 net_nfc_unset_response_callback();
43                 net_nfc_client_deinitialize();
44                 g_main_loop_quit(main_loop);
45                 break;
46
47         case NET_NFC_MESSAGE_DEINIT :
48                 if (result == NET_NFC_OK)
49                         fprintf(stdout, "power off success\n\n");
50                 else
51                         fprintf(stdout, "failed to power off (%d)\n\n", result);
52
53                 net_nfc_unset_response_callback();
54                 net_nfc_client_deinitialize();
55                 g_main_loop_quit(main_loop);
56                 break;
57
58         default :
59                 break;
60         }
61 }
62
63 int ndef_tool_read_ndef_message_from_file(const char *file_name, ndef_message_h *msg)
64 {
65         int result = -1;
66         FILE *file = NULL;
67
68         file = fopen(file_name, "rb");
69         if (file != NULL)
70         {
71                 long int file_size = 0;
72                 size_t read = 0;
73
74                 fseek(file, 0, SEEK_END);
75                 file_size = ftell(file);
76                 fseek(file, 0, SEEK_SET);
77
78                 if (file_size > 0)
79                 {
80                         data_h data;
81
82                         net_nfc_create_data(&data, NULL, file_size);
83                         if (data != NULL)
84                         {
85                                 read = fread((void *)net_nfc_get_data_buffer(data), 1, file_size, file);
86
87                                 net_nfc_create_ndef_message_from_rawdata(msg, data);
88
89                                 net_nfc_free_data(data);
90
91                                 result = file_size;
92                         }
93                 }
94
95                 fclose(file);
96         }
97
98         return result;
99 }
100
101 int ndef_tool_write_ndef_message_to_file(const char *file_name, ndef_message_h msg)
102 {
103         int result = -1;
104         FILE *file = NULL;
105         data_h data = NULL;
106
107         net_nfc_create_rawdata_from_ndef_message(msg, &data);
108         if (data != NULL)
109         {
110                 file = fopen(file_name, "wb");
111                 if (file != NULL)
112                 {
113                         fwrite((void *)net_nfc_get_data_buffer(data), 1, net_nfc_get_data_length(data), file);
114                         fflush(file);
115                         fclose(file);
116
117                         result = 0;
118                 }
119
120                 net_nfc_free_data(data);
121         }
122
123         return result;
124 }
125
126 static void print_usage(char *file_name)
127 {
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");
166 }
167
168 static net_nfc_record_tnf_e _parse_tnf_string(const char *tnf)
169 {
170         net_nfc_record_tnf_e result = -1;
171
172         if (tnf == NULL)
173                 return result;
174
175         if (strncasecmp(tnf, "EMT", 3) == 0)
176         {
177                 result = NET_NFC_RECORD_EMPTY;
178         }
179         else if (strncasecmp(tnf, "WKT", 3) == 0)
180         {
181                 result = NET_NFC_RECORD_WELL_KNOWN_TYPE;
182         }
183         else if (strncasecmp(tnf, "MIME", 4) == 0)
184         {
185                 result = NET_NFC_RECORD_MIME_TYPE;
186         }
187         else if (strncasecmp(tnf, "URI", 3) == 0)
188         {
189                 result = NET_NFC_RECORD_URI;
190         }
191         else if (strncasecmp(tnf, "EXT", 3) == 0)
192         {
193                 result = NET_NFC_RECORD_EXTERNAL_RTD;
194         }
195         else if (strncasecmp(tnf, "UNK", 3) == 0)
196         {
197                 result = NET_NFC_RECORD_UNKNOWN;
198         }
199         else if (strncasecmp(tnf, "UNC", 3) == 0)
200         {
201                 result = NET_NFC_RECORD_UNCHAGNED;
202         }
203
204         return result;
205 }
206
207 static int _append_record_to_file(const char *file_name, ndef_record_h record)
208 {
209         int result = -1;
210         ndef_message_h msg = NULL;
211
212         if (ndef_tool_read_ndef_message_from_file(file_name, &msg) <= 0)
213         {
214                 net_nfc_create_ndef_message(&msg);
215         }
216
217         net_nfc_append_record_to_ndef_message(msg, record);
218
219         ndef_tool_write_ndef_message_to_file(file_name, msg);
220
221         net_nfc_free_ndef_message(msg);
222
223         result = 0;
224
225         return result;
226 }
227
228 ndef_record_h _create_record(net_nfc_record_tnf_e tnf, data_h type, data_h id , data_h payload, char *encoding)
229 {
230         ndef_record_h result = NULL;
231
232         switch (tnf)
233         {
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)
236                 {
237                         if (encoding == NULL)
238                         {
239                                 fprintf(stdout, "encoding type is not present.\n");
240                                 return result;
241                         }
242
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));
245
246                         net_nfc_create_text_type_record(&result, temp_str, encoding, NET_NFC_ENCODE_UTF_8);
247                         free(temp_str);
248
249                         if (id != NULL)
250                         {
251                                 net_nfc_set_record_id(result, id);
252                         }
253                 }
254                 else if (net_nfc_get_data_length(type) == 1 && memcmp((void *)net_nfc_get_data_buffer(type), "U", 1) == 0)
255                 {
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));
258
259                         net_nfc_create_uri_type_record(&result, temp_str, 0);
260                         free(temp_str);
261
262                         if (id != NULL)
263                         {
264                                 net_nfc_set_record_id(result, id);
265                         }
266                 }
267                 else
268                 {
269                         net_nfc_create_record(&result, tnf, type, id, payload);
270                 }
271                 break;
272
273         default :
274                 net_nfc_create_record(&result, tnf, type, id, payload);
275                 break;
276         }
277
278         return result;
279 }
280
281 bool _remove_record_from_file(const char *file_name, int index)
282 {
283         bool result = false;
284         ndef_message_h msg = NULL;
285
286         if (ndef_tool_read_ndef_message_from_file(file_name, &msg) > 0)
287         {
288                 net_nfc_remove_record_by_index(msg, index);
289
290                 ndef_tool_write_ndef_message_to_file(file_name, msg);
291
292                 net_nfc_free_ndef_message(msg);
293
294                 result = true;
295         }
296
297         return result;
298 }
299
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))
303
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)))
307
308 #define __DO_NEXT_ARG \
309         if (++i >= argc || __IS_OPTION(argv[i]) == true) \
310         { \
311                 operation = OPERATION_ERROR; \
312                 break; \
313         }
314
315 int main(int argc, char *argv[])
316 {
317         int remove_index = -1;
318         int begin_index = -1;
319         int end_index = -1;
320         int operation = OPERATION_ERROR;
321         net_nfc_record_tnf_e tnf = -1;
322         data_h type = NULL;
323         data_h id = NULL;
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;
330
331         int i = 1;
332         int len = 0;
333
334         for (i = 1; i < argc; i++)
335         {
336                 if (__COMPARE_OPTION(argv[i], 'a', "append-record"))
337                 {
338                         operation = OPERATION_APPEND;
339                 }
340                 else if (__COMPARE_OPTION(argv[i], 's', "sign-records"))
341                 {
342                         operation = OPERATION_SIGN;
343                 }
344                 else if (__COMPARE_OPTION(argv[i], 'd', "display-record"))
345                 {
346                         operation = OPERATION_DISPLAY;
347                 }
348                 else if (__COMPARE_OPTION(argv[i], 'v', "verify-signed-records"))
349                 {
350                         operation = OPERATION_VERIFY;
351                 }
352                 else if (__COMPARE_OPTION(argv[i], 'r', "remove-record"))
353                 {
354                         operation = OPERATION_REMOVE;
355                 }
356                 else if (__COMPARE_OPTION(argv[i], 0, "read-tag"))
357                 {
358                         operation = OPERATION_READ_TAG;
359                 }
360                 else if (__COMPARE_OPTION(argv[i], 0, "write-tag"))
361                 {
362                         operation = OPERATION_WRITE_TAG;
363                 }
364                 else if (__COMPARE_OPTION(argv[i], 0, "receive-ndef"))
365                 {
366                         operation = OPERATION_RECEIVE_NDEF;
367                 }
368                 else if (__COMPARE_OPTION(argv[i], 0, "send-ndef"))
369                 {
370                         operation = OPERATION_SEND_NDEF;
371                 }
372                 else if (__COMPARE_OPTION(argv[i], 0, "handover"))
373                 {
374                         operation = OPERATION_HANDOVER;
375                 }
376                 else if (__COMPARE_OPTION(argv[i], 0, "off")) /* hidden operation */
377                 {
378                         operation = OPERATION_OFF;
379                 }
380                 else if (__COMPARE_OPTION(argv[i], 0, "on")) /* hidden operation */
381                 {
382                         operation = OPERATION_ON;
383                 }
384                 else if (__COMPARE_OPTION(argv[i], 0, "send-apdu")) /* hidden operation */
385                 {
386                         operation = OPERATION_SEND_APDU;
387                 }
388                 else if (__COMPARE_OPTION(argv[i], 0, "set-se")) /* hidden operation */
389                 {
390                         operation = OPERATION_SET_SE;
391                 }
392                 else if (__COMPARE_OPTION(argv[i], 'i', "record-index"))
393                 {
394                         __DO_NEXT_ARG;
395                         remove_index = atoi(argv[i]);
396                 }
397                 else if (__COMPARE_OPTION(argv[i], 'c', "cert-file"))
398                 {
399                         __DO_NEXT_ARG;
400                         cert_file = strdup(argv[i]);
401                 }
402                 else if (__COMPARE_OPTION(argv[i], 'p', "password"))
403                 {
404                         __DO_NEXT_ARG;
405                         password = strdup(argv[i]);
406                 }
407                 else if (__COMPARE_OPTION(argv[i], 'b', "begin-index"))
408                 {
409                         __DO_NEXT_ARG;
410                         begin_index = atoi(argv[i]);
411                 }
412                 else if (__COMPARE_OPTION(argv[i], 'e', "end-index"))
413                 {
414                         __DO_NEXT_ARG;
415                         end_index = atoi(argv[i]);
416                 }
417                 else if (__COMPARE_OPTION(argv[i], 't', "tnf"))
418                 {
419                         __DO_NEXT_ARG;
420                         tnf = _parse_tnf_string(argv[i]);
421                 }
422                 else if (__COMPARE_OPTION(argv[i], 'T', "type-data"))
423                 {
424                         __DO_NEXT_ARG;
425                         len = strlen(argv[i]);
426                         if (len > 0)
427                         {
428                                 net_nfc_create_data(&type, (const uint8_t *)argv[i], len);
429                         }
430                 }
431                 else if (__COMPARE_OPTION(argv[i], 'I', "id-data"))
432                 {
433                         __DO_NEXT_ARG;
434                         len = strlen(argv[i]);
435                         if (len > 0)
436                         {
437                                 net_nfc_create_data(&id, (const uint8_t *)argv[i], len);
438                         }
439                 }
440                 else if (__COMPARE_OPTION(argv[i], 'P', "payload-data"))
441                 {
442                         __DO_NEXT_ARG;
443                         len = strlen(argv[i]);
444                         if (len > 0)
445                         {
446                                 uint8_t *buffer = NULL;
447
448                                 buffer = calloc(1, len);
449                                 if (buffer != NULL)
450                                 {
451                                         int j, current = 0;
452
453                                         for (j = 0; j < len; j++)
454                                         {
455                                                 if (argv[i][j] == '%')
456                                                 {
457                                                         if (j + 2 < len)
458                                                         {
459                                                                 if (argv[i][j + 1] != '%')
460                                                                 {
461                                                                         char temp[3] = { 0, };
462
463                                                                         temp[0] = argv[i][j + 1];
464                                                                         temp[1] = argv[i][j + 2];
465
466                                                                         buffer[current++] = (uint8_t)strtol(temp, NULL, 16);
467                                                                         j += 2;
468                                                                 }
469                                                                 else
470                                                                 {
471                                                                         buffer[current++] = '%';
472                                                                         j++;
473                                                                 }
474                                                         }
475                                                         else if (j + 1 < len)
476                                                         {
477                                                                 if (argv[i][j + 1] == '%')
478                                                                 {
479                                                                         buffer[current++] = '%';
480                                                                         j++;
481                                                                 }
482                                                                 else
483                                                                 {
484                                                                         buffer[current++] = argv[i][j];
485                                                                 }
486                                                         }
487                                                         else
488                                                         {
489                                                                 /* invalid param. error? */
490                                                         }
491                                                 }
492                                                 else
493                                                 {
494                                                         buffer[current++] = argv[i][j];
495                                                 }
496                                         }
497
498                                         net_nfc_create_data(&payload, buffer, current);
499
500                                         free(buffer);
501                                 }
502                         }
503                 }
504                 else if (__COMPARE_OPTION(argv[i], 0, "payload-file"))
505                 {
506                         __DO_NEXT_ARG;
507                         len = strlen(argv[i]);
508                         if (len > 0)
509                         {
510                                 FILE *file = NULL;
511
512                                 file = fopen(argv[i], "rb");
513                                 if (file != NULL)
514                                 {
515                                         long int file_size = 0;
516                                         size_t read = 0;
517
518                                         fseek(file, 0, SEEK_END);
519                                         file_size = ftell(file);
520                                         fseek(file, 0, SEEK_SET);
521
522                                         if (file_size > 0)
523                                         {
524                                                 uint8_t *buffer = NULL;
525
526                                                 buffer = calloc(1, file_size);
527                                                 if (buffer != NULL)
528                                                 {
529                                                         read = fread(buffer, 1, file_size, file);
530
531                                                         net_nfc_create_data(&payload, buffer, read);
532
533                                                         free(buffer);
534                                                 }
535                                         }
536
537                                         fclose(file);
538                                 }
539                         }
540                 }
541                 else if (__COMPARE_OPTION(argv[i], 'E', "encoding"))
542                 {
543                         __DO_NEXT_ARG;
544                         encoding = strdup(argv[i]);
545                 }
546                 else if (__COMPARE_OPTION(argv[i], 'h', "help"))
547                 {
548                         operation = OPERATION_ERROR;
549                         break;
550                 }
551                 else
552                 {
553                         if (file_name == NULL)
554                         {
555                                 file_name = strdup(argv[i]);
556                         }
557                         else
558                         {
559                                 operation = OPERATION_ERROR;
560                                 break;
561                         }
562                 }
563         }
564
565         if (operation != OPERATION_ON && operation != OPERATION_OFF && file_name == NULL)
566                 operation = OPERATION_ERROR;
567
568         switch (operation)
569         {
570         case OPERATION_DISPLAY :
571                 ndef_tool_display_ndef_message_from_file(file_name);
572                 break;
573
574         case OPERATION_APPEND :
575                 if (tnf >= 0 && type != NULL)
576                 {
577                         record = _create_record(tnf, type, id, payload, encoding);
578
579                         if (record != NULL)
580                         {
581                                 _append_record_to_file(file_name, record);
582
583                                 ndef_tool_display_ndef_message_from_file(file_name);
584                         }
585                         else
586                         {
587                                 print_usage(argv[0]);
588                         }
589                 }
590                 else
591                 {
592                         print_usage(argv[0]);
593                 }
594                 break;
595
596         case OPERATION_REMOVE :
597                 _remove_record_from_file(file_name, remove_index);
598                 ndef_tool_display_ndef_message_from_file(file_name);
599                 break;
600
601         case OPERATION_SIGN :
602                 if (begin_index < 0 || end_index < 0 || begin_index > end_index || cert_file == NULL || password == NULL)
603                 {
604                         print_usage(argv[0]);
605                 }
606                 else
607                 {
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);
611                 }
612                 break;
613
614         case OPERATION_VERIFY :
615                 fprintf(stdout, "verify %s\n", ndef_tool_verify_message_from_file(file_name) ? "success" : "failed");
616                 break;
617
618         case OPERATION_READ_TAG :
619                 ndef_tool_read_ndef_from_tag(file_name);
620                 break;
621
622         case OPERATION_WRITE_TAG :
623                 ndef_tool_write_ndef_to_tag(file_name);
624                 break;
625
626         case OPERATION_RECEIVE_NDEF :
627                 ndef_tool_receive_ndef_via_p2p(file_name);
628                 break;
629
630         case OPERATION_SEND_NDEF :
631                 ndef_tool_send_ndef_via_p2p(file_name);
632                 break;
633
634         case OPERATION_HANDOVER :
635                 ndef_tool_connection_handover(file_name);
636                 break;
637
638         case OPERATION_ON :
639                 {
640                         int state = 0;
641
642                         net_nfc_get_state(&state);
643
644                         if (state == 0)
645                         {
646                                 fprintf(stdout, "Power on....\n\n");
647
648                                 if(!g_thread_supported())
649                                 {
650                                         g_thread_init(NULL);
651                                 }
652
653                                 main_loop = g_main_new(true);
654
655                                 net_nfc_client_initialize();
656                                 net_nfc_set_response_callback(_activation_complete_cb, NULL);
657                                 net_nfc_set_state(true, NULL);
658
659                                 g_main_loop_run(main_loop);
660                         }
661                         else
662                         {
663                                 fprintf(stdout, "Already power is on.\n\n");
664                         }
665                 }
666                 break;
667
668         case OPERATION_OFF :
669                 {
670                         int state = 0;
671
672                         net_nfc_get_state(&state);
673
674                         if (state == 1)
675                         {
676                                 fprintf(stdout, "Power off....\n\n");
677
678                                 if(!g_thread_supported())
679                                 {
680                                         g_thread_init(NULL);
681                                 }
682
683                                 main_loop = g_main_new(true);
684
685                                 net_nfc_client_initialize();
686                                 net_nfc_set_response_callback(_activation_complete_cb, NULL);
687                                 net_nfc_set_state(false, NULL);
688
689                                 g_main_loop_run(main_loop);
690                         }
691                         else
692                         {
693                                 fprintf(stdout, "Already power is off.\n\n");
694                         }
695                 }
696                 break;
697
698         case OPERATION_SEND_APDU :
699                 ndef_tool_send_apdu(file_name);
700                 break;
701
702         case OPERATION_SET_SE :
703                 net_nfc_client_initialize();
704
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);
709                 } else {
710                         fprintf(stdout, "Unknown SE name.\n\n");
711                 }
712                 break;
713
714         case OPERATION_ERROR :
715         default :
716                 print_usage(argv[0]);
717                 break;
718         }
719
720         return 0;
721 }