adapter: Bypass the target layer
[platform/upstream/neard.git] / src / tag.c
1 /*
2  *
3  *  neard - Near Field Communication manager
4  *
5  *  Copyright (C) 2011  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <string.h>
30
31 #include <glib.h>
32
33 #include <gdbus.h>
34
35 #include "near.h"
36
37 #define TYPE3_IDM_LEN 8
38 #define TYPE3_ATTR_BLOCK_SIZE 16
39
40 struct near_tag {
41         char *path;
42
43         uint32_t adapter_idx;
44         uint32_t target_idx;
45
46         uint32_t protocol;
47         uint32_t type;
48         enum near_tag_sub_type sub_type;
49         enum near_tag_memory_layout layout;
50         near_bool_t readonly;
51
52         uint8_t nfcid[NFC_MAX_NFCID1_LEN];
53         uint8_t nfcid_len;
54
55         size_t data_length;
56         uint8_t *data;
57
58         uint32_t n_records;
59         GList *records;
60
61         /* Tag specific structures */
62         struct {
63                 uint8_t IDm[TYPE3_IDM_LEN];
64                 uint8_t attr[TYPE3_ATTR_BLOCK_SIZE];
65         } t3;
66
67         struct {
68                 uint16_t max_ndef_size;
69                 uint16_t c_apdu_max_size;
70         } t4;
71 };
72
73 static DBusConnection *connection = NULL;
74
75 static GHashTable *tag_hash;
76
77 static GSList *driver_list = NULL;
78
79 struct near_tag *near_tag_get_tag(uint32_t adapter_idx, uint32_t target_idx)
80 {
81         struct near_tag *tag;
82         char *path;
83
84         path = g_strdup_printf("%s/nfc%d/tag%d", NFC_PATH,
85                                         adapter_idx, target_idx);
86         if (path == NULL)
87                 return NULL;
88
89         tag = g_hash_table_lookup(tag_hash, path);
90         g_free(path);
91
92         /* TODO refcount */
93         return tag;
94 }
95
96 static void append_records(DBusMessageIter *iter, void *user_data)
97 {
98         struct near_tag *tag = user_data;
99         GList *list;
100
101         DBG("");
102
103         for (list = tag->records; list; list = list->next) {
104                 struct near_ndef_record *record = list->data;
105                 char *path;
106
107                 path = __near_ndef_record_get_path(record);
108                 if (path == NULL)
109                         continue;
110
111                 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
112                                                         &path);
113         }
114 }
115
116 static const char *type_string(struct near_tag *tag)
117 {
118         const char *type;
119
120         DBG("type 0x%x", tag->type);
121
122         switch (tag->type) {
123         case NFC_PROTO_JEWEL:
124                 type = "Type 1";
125                 break;
126
127         case NFC_PROTO_MIFARE:
128                 type = "Type 2";
129                 break;
130
131         case NFC_PROTO_FELICA:
132                 type = "Type 3";
133                 break;
134
135         case NFC_PROTO_ISO14443:
136                 type = "Type 4";
137                 break;
138
139         default:
140                 type = NULL;
141                 near_error("Unknown tag type 0x%x", tag->type);
142                 break;
143         }
144
145         return type;
146 }
147
148 static const char *protocol_string(struct near_tag *tag)
149 {
150         const char *protocol;
151
152         DBG("protocol 0x%x", tag->protocol);
153
154         switch (tag->protocol) {
155         case NFC_PROTO_FELICA_MASK:
156                 protocol = "Felica";
157                 break;
158
159         case NFC_PROTO_MIFARE_MASK:
160                 protocol = "MIFARE";
161                 break;
162
163         case NFC_PROTO_JEWEL_MASK:
164                 protocol = "Jewel";
165                 break;
166
167         case NFC_PROTO_ISO14443_MASK:
168                 protocol = "ISO-DEP";
169                 break;
170
171         default:
172                 near_error("Unknown tag protocol 0x%x", tag->protocol);
173                 protocol = NULL;
174         }
175
176         return protocol;
177 }
178
179 static DBusMessage *get_properties(DBusConnection *conn,
180                                         DBusMessage *msg, void *data)
181 {
182         struct near_tag *tag = data;
183         const char *protocol, *type;
184         DBusMessage *reply;
185         DBusMessageIter array, dict;
186
187         DBG("conn %p", conn);
188
189         reply = dbus_message_new_method_return(msg);
190         if (reply == NULL)
191                 return NULL;
192
193         dbus_message_iter_init_append(reply, &array);
194
195         near_dbus_dict_open(&array, &dict);
196
197         type = type_string(tag);
198         if (type != NULL)
199                 near_dbus_dict_append_basic(&dict, "Type",
200                                         DBUS_TYPE_STRING, &type);
201
202         protocol = protocol_string(tag);
203         if (protocol != NULL)
204                 near_dbus_dict_append_basic(&dict, "Protocol",
205                                         DBUS_TYPE_STRING, &protocol);
206
207         near_dbus_dict_append_basic(&dict, "ReadOnly",
208                                         DBUS_TYPE_BOOLEAN, &tag->readonly);
209
210         near_dbus_dict_append_array(&dict, "Records",
211                                 DBUS_TYPE_OBJECT_PATH, append_records, tag);
212
213         near_dbus_dict_close(&array, &dict);
214
215         return reply;
216 }
217
218 static DBusMessage *set_property(DBusConnection *conn,
219                                         DBusMessage *msg, void *data)
220 {
221         DBG("conn %p", conn);
222
223         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
224 }
225
226 static GDBusMethodTable tag_methods[] = {
227         { "GetProperties",     "",      "a{sv}", get_properties     },
228         { "SetProperty",       "sv",    "",      set_property       },
229         { },
230 };
231
232 static GDBusSignalTable tag_signals[] = {
233         { "PropertyChanged",            "sv"    },
234         { }
235 };
236
237
238 void __near_tag_append_records(struct near_tag *tag, DBusMessageIter *iter)
239 {
240         GList *list;
241
242         for (list = tag->records; list; list = list->next) {
243                 struct near_ndef_record *record = list->data;
244                 char *path;
245
246                 path = __near_ndef_record_get_path(record);
247                 if (path == NULL)
248                         continue;
249
250                 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
251                                                         &path);
252         }
253 }
254
255 #define NFC_TAG_A (NFC_PROTO_ISO14443_MASK | NFC_PROTO_NFC_DEP_MASK | \
256                                 NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK)
257 #define NFC_TAG_A_TYPE2      0x00
258 #define NFC_TAG_A_TYPE4      0x01
259 #define NFC_TAG_A_NFC_DEP    0x02
260 #define NFC_TAG_A_TYPE4_DEP  0x03
261
262 #define NFC_TAG_A_SENS_RES_SSD_JEWEL      0x00
263 #define NFC_TAG_A_SENS_RES_PLATCONF_JEWEL 0x0c
264
265 #define NFC_TAG_A_SEL_PROT(sel_res) (((sel_res) & 0x60) >> 5)
266 #define NFC_TAG_A_SEL_CASCADE(sel_res) (((sel_res) & 0x04) >> 2)
267 #define NFC_TAG_A_SENS_RES_SSD(sens_res) ((sens_res) & 0x001f)
268 #define NFC_TAG_A_SENS_RES_PLATCONF(sens_res) (((sens_res) & 0x0f00) >> 8)
269
270 static enum near_tag_sub_type get_tag_type2_sub_type(uint8_t sel_res)
271 {
272         switch(sel_res) {
273         case 0x00 :
274                 return NEAR_TAG_NFC_T2_MIFARE_ULTRALIGHT;
275         case 0x08:
276                 return NEAR_TAG_NFC_T2_MIFARE_CLASSIC_1K;
277         case 0x09:
278                 return NEAR_TAG_NFC_T2_MIFARE_MINI;
279         case 0x18:
280                 return NEAR_TAG_NFC_T2_MIFARE_CLASSIC_4K;
281         case 0x20:
282                 return NEAR_TAG_NFC_T2_MIFARE_DESFIRE;
283         case 0x28 :
284                 return NEAR_TAG_NFC_T2_JCOP30;
285         case 0x38:
286                 return NEAR_TAG_NFC_T2_MIFARE_4K_EMUL;
287         case 0x88:
288                 return NEAR_TAG_NFC_T2_MIFARE_1K_INFINEON;
289         case 0x98:
290                 return NEAR_TAG_NFC_T2_MPCOS;
291         }
292
293         return NEAR_TAG_NFC_SUBTYPE_UNKNOWN;
294 }
295
296 static void set_tag_type(struct near_tag *tag,
297                                 uint16_t sens_res, uint8_t sel_res)
298 {
299         uint8_t platconf, ssd, proto;
300
301         DBG("protocol 0x%x sens_res 0x%x sel_res 0x%x", tag->protocol,
302                                                         sens_res, sel_res);
303
304         switch (tag->protocol) {
305         case NFC_PROTO_JEWEL_MASK:
306                 platconf = NFC_TAG_A_SENS_RES_PLATCONF(sens_res);
307                 ssd = NFC_TAG_A_SENS_RES_SSD(sens_res);
308
309                 DBG("Jewel");
310
311                 if ((ssd == NFC_TAG_A_SENS_RES_SSD_JEWEL) &&
312                                 (platconf == NFC_TAG_A_SENS_RES_PLATCONF_JEWEL))
313                         tag->type = NFC_PROTO_JEWEL;
314                 break;
315
316         case NFC_PROTO_MIFARE_MASK:
317         case NFC_PROTO_ISO14443_MASK:
318                 proto = NFC_TAG_A_SEL_PROT(sel_res);
319
320                 DBG("proto 0x%x", proto);
321
322                 switch(proto) {
323                 case NFC_TAG_A_TYPE2:
324                         tag->type = NFC_PROTO_MIFARE;
325                         tag->sub_type = get_tag_type2_sub_type(sel_res);
326                         break;
327                 case NFC_TAG_A_TYPE4:
328                         tag->type = NFC_PROTO_ISO14443;
329                         break;
330                 case NFC_TAG_A_TYPE4_DEP:
331                         tag->type = NFC_PROTO_NFC_DEP;
332                         break;
333                 }
334                 break;
335
336         case NFC_PROTO_FELICA_MASK:
337                 tag->type = NFC_PROTO_FELICA;
338                 break;
339
340         default:
341                 tag->type = NFC_PROTO_MAX;
342                 break;
343         }
344
345         DBG("tag type 0x%x", tag->type);
346 }
347
348 static int tag_initialize(struct near_tag *tag,
349                         uint32_t adapter_idx, uint32_t target_idx,
350                         uint32_t protocols,
351                         uint16_t sens_res, uint8_t sel_res,
352                         uint8_t *nfcid, uint8_t nfcid_len)
353 {
354         DBG("");
355
356         tag->path = g_strdup_printf("%s/nfc%d/tag%d", NFC_PATH,
357                                         adapter_idx, target_idx);
358         if (tag->path == NULL)
359                 return -ENOMEM;
360         tag->adapter_idx = adapter_idx;
361         tag->target_idx = target_idx;
362         tag->protocol = protocols;
363         tag->n_records = 0;
364         tag->readonly = 0;
365
366         if (nfcid_len <= NFC_MAX_NFCID1_LEN) {
367                 tag->nfcid_len = nfcid_len;
368                 memcpy(tag->nfcid, nfcid, nfcid_len);
369         }
370
371         set_tag_type(tag, sens_res, sel_res);
372
373         return 0;
374 }
375
376 struct near_tag *__near_tag_add(uint32_t adapter_idx, uint32_t target_idx,
377                                 uint32_t protocols,
378                                 uint16_t sens_res, uint8_t sel_res,
379                                 uint8_t *nfcid, uint8_t nfcid_len)
380 {
381         struct near_tag *tag;
382         char *path;
383
384         tag = near_tag_get_tag(adapter_idx, target_idx);
385         if (tag != NULL)
386                 return NULL;
387
388         tag = g_try_malloc0(sizeof(struct near_tag));
389         if (tag == NULL)
390                 return NULL;
391
392         if (tag_initialize(tag, adapter_idx, target_idx,
393                                 protocols,
394                                 sens_res, sel_res,
395                                 nfcid, nfcid_len) < 0) {
396                 g_free(tag);
397                 return NULL;
398         }
399
400         path = g_strdup(tag->path);
401         if (path == NULL) {
402                 g_free(tag);
403                 return NULL;
404         }
405
406         g_hash_table_insert(tag_hash, path, tag);
407
408         DBG("connection %p", connection);
409
410         g_dbus_register_interface(connection, tag->path,
411                                         NFC_TAG_INTERFACE,
412                                         tag_methods, tag_signals,
413                                                         NULL, tag, NULL);
414
415         return tag;
416 }
417
418 void __near_tag_remove(struct near_tag *tag)
419 {
420         char *path = tag->path;
421
422         DBG("path %s", tag->path);
423
424         if (g_hash_table_lookup(tag_hash, tag->path) == NULL)
425                 return;
426
427         g_dbus_unregister_interface(connection, tag->path,
428                                                 NFC_TAG_INTERFACE);
429
430         g_hash_table_remove(tag_hash, path);
431 }
432
433 const char *__near_tag_get_path(struct near_tag *tag)
434 {
435         return tag->path;
436 }
437
438
439 uint32_t __near_tag_get_idx(struct near_tag *tag)
440 {
441         return tag->target_idx;
442 }
443
444 uint32_t __near_tag_get_type(struct near_tag *tag)
445 {
446         return tag->type;
447 }
448
449 enum near_tag_sub_type near_tag_get_subtype(uint32_t adapter_idx,
450                                 uint32_t target_idx)
451
452 {
453         struct near_tag *tag;
454
455         tag = near_tag_get_tag(adapter_idx, target_idx);
456         if (tag == NULL)
457                 return NEAR_TAG_NFC_SUBTYPE_UNKNOWN;
458
459         return tag->sub_type;
460 }
461
462 uint8_t *near_tag_get_nfcid(uint32_t adapter_idx, uint32_t target_idx,
463                                 uint8_t *nfcid_len)
464 {
465         struct near_tag *tag;
466         uint8_t *nfcid;
467
468         tag = near_tag_get_tag(adapter_idx, target_idx);
469         if (tag == NULL)
470                 goto fail;
471
472         nfcid = g_try_malloc0(tag->nfcid_len);
473         if (nfcid == NULL)
474                 goto fail;
475
476         memcpy(nfcid, tag->nfcid, tag->nfcid_len);
477         *nfcid_len = tag->nfcid_len;
478
479         return nfcid;
480
481 fail:
482         *nfcid_len = 0;
483         return NULL;
484 }
485
486 int near_tag_add_data(uint32_t adapter_idx, uint32_t target_idx,
487                         uint8_t *data, size_t data_length)
488 {
489         struct near_tag *tag;
490
491         tag = near_tag_get_tag(adapter_idx, target_idx);
492         if (tag == NULL)
493                 return -ENODEV;
494
495         tag->data_length = data_length;
496         tag->data = g_try_malloc0(data_length);
497         if (tag->data == NULL)
498                 return -ENOMEM;
499
500         if (data != NULL)
501                 memcpy(tag->data, data, data_length);
502
503         return 0;
504 }
505
506 struct near_tag *__near_tag_new(uint32_t adapter_idx, uint32_t target_idx,
507                                 uint8_t *data, size_t data_length)
508 {
509         struct near_tag *tag;
510         char *path;
511
512         path = g_strdup_printf("%s/nfc%d/tag%d", NFC_PATH,
513                                         adapter_idx, target_idx);
514
515         if (path == NULL)
516                 return NULL;
517
518         if (g_hash_table_lookup(tag_hash, path) != NULL)
519                 return NULL;
520         g_free(path);
521
522         tag = g_try_malloc0(sizeof(struct near_tag));
523         if (tag == NULL)
524                 return NULL;
525
526         g_hash_table_insert(tag_hash, path, tag);
527
528         DBG("connection %p", connection);
529
530         g_dbus_register_interface(connection, tag->path,
531                                         NFC_TAG_INTERFACE,
532                                         tag_methods, tag_signals,
533                                                         NULL, tag, NULL);
534
535         return tag;
536 }
537
538 void __near_tag_free(struct near_tag *tag)
539 {
540         GList *list;
541
542         DBG("");
543
544         for (list = tag->records; list; list = list->next) {
545                 struct near_ndef_record *record = list->data;
546
547                 __near_ndef_record_free(record);
548         }
549
550         g_list_free(tag->records);
551         g_free(tag->path);
552         g_free(tag->data);
553         g_free(tag);
554 }
555
556 uint32_t __near_tag_n_records(struct near_tag *tag)
557 {
558         return tag->n_records;
559 }
560
561 int __near_tag_add_record(struct near_tag *tag,
562                                 struct near_ndef_record *record)
563 {
564         DBG("");
565
566         tag->n_records++;
567         tag->records = g_list_append(tag->records, record);
568
569         return 0;
570 }
571
572 int near_tag_set_ro(struct near_tag *tag, near_bool_t readonly)
573 {
574         tag->readonly = readonly;
575
576         return 0;
577 }
578
579 near_bool_t near_tag_get_ro(struct near_tag *tag)
580 {
581         return tag->readonly;
582 }
583
584 uint8_t *near_tag_get_data(struct near_tag *tag, size_t *data_length)
585 {
586         if (data_length == NULL)
587                 return NULL;
588
589         *data_length = tag->data_length;
590
591         return tag->data;
592 }
593
594 uint32_t near_tag_get_adapter_idx(struct near_tag *tag)
595 {
596         return tag->adapter_idx;
597 }
598
599 uint32_t near_tag_get_target_idx(struct near_tag *tag)
600 {
601         return tag->target_idx;
602 }
603
604 enum near_tag_memory_layout near_tag_get_memory_layout(struct near_tag *tag)
605 {
606         if (tag == NULL)
607                 return NEAR_TAG_MEMORY_UNKNOWN;
608
609         return tag->layout;
610 }
611
612 void near_tag_set_memory_layout(struct near_tag *tag,
613                                         enum near_tag_memory_layout layout)
614 {
615         if (tag == NULL)
616                 return;
617
618         tag->layout = layout;
619 }
620
621 void near_tag_set_max_ndef_size(struct near_tag *tag, uint16_t size)
622 {
623         if (tag == NULL)
624                 return;
625
626         tag->t4.max_ndef_size = size;
627 }
628
629 uint16_t near_tag_get_max_ndef_size(struct near_tag *tag)
630 {
631         if (tag == NULL)
632                 return 0;
633
634         return tag->t4.max_ndef_size;
635 }
636
637 void near_tag_set_c_apdu_max_size(struct near_tag *tag, uint16_t size)
638 {
639         if (tag == NULL)
640                 return;
641
642         tag->t4.c_apdu_max_size = size;
643 }
644
645 uint16_t near_tag_get_c_apdu_max_size(struct near_tag *tag)
646 {
647         if (tag == NULL)
648                 return 0;
649
650         return tag->t4.c_apdu_max_size;
651 }
652
653 void near_tag_set_idm(struct near_tag *tag, uint8_t *idm, uint8_t len)
654 {
655         if (tag == NULL || len > TYPE3_IDM_LEN)
656                 return;
657
658         memset(tag->t3.IDm, 0, TYPE3_IDM_LEN);
659         memcpy(tag->t3.IDm, idm, len);
660 }
661
662 uint8_t *near_tag_get_idm(struct near_tag *tag, uint8_t *len)
663 {
664         if (tag == NULL || len == NULL)
665                 return NULL;
666
667         *len = TYPE3_IDM_LEN;
668         return tag->t3.IDm;
669 }
670
671 void near_tag_set_attr_block(struct near_tag *tag, uint8_t *attr, uint8_t len)
672 {
673         if (tag == NULL || len > TYPE3_ATTR_BLOCK_SIZE)
674                 return;
675
676         memset(tag->t3.attr, 0, TYPE3_ATTR_BLOCK_SIZE);
677         memcpy(tag->t3.attr, attr, len);
678 }
679
680 uint8_t *near_tag_get_attr_block(struct near_tag *tag, uint8_t *len)
681 {
682         if (tag == NULL || len == NULL)
683                 return NULL;
684
685         *len = TYPE3_ATTR_BLOCK_SIZE;
686         return tag->t3.attr;
687 }
688
689 static gint cmp_prio(gconstpointer a, gconstpointer b)
690 {
691         const struct near_tag_driver *driver1 = a;
692         const struct near_tag_driver *driver2 = b;
693
694         return driver2->priority - driver1->priority;
695 }
696
697 int near_tag_driver_register(struct near_tag_driver *driver)
698 {
699         DBG("");
700
701         if (driver->read_tag == NULL)
702                 return -EINVAL;
703
704         driver_list = g_slist_insert_sorted(driver_list, driver, cmp_prio);
705
706         return 0;
707 }
708
709 void near_tag_driver_unregister(struct near_tag_driver *driver)
710 {
711         DBG("");
712
713         driver_list = g_slist_remove(driver_list, driver);
714 }
715
716 int __near_tag_read(struct near_tag *tag, near_tag_io_cb cb)
717 {
718         GSList *list;
719
720         DBG("type 0x%x", tag->type);
721
722         for (list = driver_list; list; list = list->next) {
723                 struct near_tag_driver *driver = list->data;
724
725                 DBG("driver type 0x%x", driver->type);
726
727                 if (driver->type == tag->type)
728                         return driver->read_tag(tag->adapter_idx, tag->target_idx, cb);
729         }
730
731         return 0;
732 }
733
734 int __near_tag_add_ndef(struct near_tag *tag,
735                                 struct near_ndef_message *ndef,
736                                 near_tag_io_cb cb)
737 {
738         GSList *list;
739
740         DBG("type 0x%x", tag->type);
741
742         for (list = driver_list; list; list = list->next) {
743                 struct near_tag_driver *driver = list->data;
744
745                 DBG("driver type 0x%x", driver->type);
746
747                 if (driver->type == tag->type)
748                         return driver->add_ndef(tag->adapter_idx, tag->target_idx,
749                                                                 ndef, cb);
750         }
751
752         return 0;
753 }
754
755 int __near_tag_check_presence(struct near_tag *tag, near_tag_io_cb cb)
756 {
757         GSList *list;
758
759         DBG("type 0x%x", tag->type);
760
761         for (list = driver_list; list; list = list->next) {
762                 struct near_tag_driver *driver = list->data;
763
764                 DBG("driver type 0x%x", driver->type);
765
766                 if (driver->type == tag->type) {
767                         if (driver->check_presence == NULL)
768                                 continue;
769
770                         return driver->check_presence(tag->adapter_idx, tag->target_idx, cb);
771                 }
772         }
773
774         return -EOPNOTSUPP;
775 }
776
777 static void free_tag(gpointer data)
778 {
779         struct near_tag *tag = data;
780         GList *list;
781
782         DBG("tag %p", tag);
783
784         for (list = tag->records; list; list = list->next) {
785                 struct near_ndef_record *record = list->data;
786
787                 __near_ndef_record_free(record);
788         }
789
790         DBG("record freed");
791
792         g_list_free(tag->records);
793         g_free(tag->path);
794         g_free(tag->data);
795         g_free(tag);
796
797         DBG("Done");
798 }
799
800 int __near_tag_init(void)
801 {
802         DBG("");
803
804         connection = near_dbus_get_connection();
805
806         tag_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
807                                                 g_free, free_tag);
808
809         return 0;
810 }
811
812 void __near_tag_cleanup(void)
813 {
814         DBG("");
815
816         g_hash_table_destroy(tag_hash);
817         tag_hash = NULL;
818 }