4450b92bbf3826a46f181ed03aa1e87aad83eb60
[profile/ivi/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         near_bool_t blank;
61
62         /* Tag specific structures */
63         struct {
64                 uint8_t IDm[TYPE3_IDM_LEN];
65                 uint8_t attr[TYPE3_ATTR_BLOCK_SIZE];
66                 uint8_t ic_type;
67         } t3;
68
69         struct {
70                 uint16_t max_ndef_size;
71                 uint16_t c_apdu_max_size;
72         } t4;
73
74         DBusMessage *write_msg; /* Pending write message */
75         struct near_ndef_message *write_ndef;
76 };
77
78 static DBusConnection *connection = NULL;
79
80 static GHashTable *tag_hash;
81
82 static GSList *driver_list = NULL;
83
84 struct near_tag *near_tag_get_tag(uint32_t adapter_idx, uint32_t target_idx)
85 {
86         struct near_tag *tag;
87         char *path;
88
89         path = g_strdup_printf("%s/nfc%d/tag%d", NFC_PATH,
90                                         adapter_idx, target_idx);
91         if (path == NULL)
92                 return NULL;
93
94         tag = g_hash_table_lookup(tag_hash, path);
95         g_free(path);
96
97         /* TODO refcount */
98         return tag;
99 }
100
101 static void append_records(DBusMessageIter *iter, void *user_data)
102 {
103         struct near_tag *tag = user_data;
104         GList *list;
105
106         DBG("");
107
108         for (list = tag->records; list; list = list->next) {
109                 struct near_ndef_record *record = list->data;
110                 char *path;
111
112                 path = __near_ndef_record_get_path(record);
113                 if (path == NULL)
114                         continue;
115
116                 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
117                                                         &path);
118         }
119 }
120
121 static const char *type_string(struct near_tag *tag)
122 {
123         const char *type;
124
125         DBG("type 0x%x", tag->type);
126
127         switch (tag->type) {
128         case NFC_PROTO_JEWEL:
129                 type = "Type 1";
130                 break;
131
132         case NFC_PROTO_MIFARE:
133                 type = "Type 2";
134                 break;
135
136         case NFC_PROTO_FELICA:
137                 type = "Type 3";
138                 break;
139
140         case NFC_PROTO_ISO14443:
141                 type = "Type 4";
142                 break;
143
144         default:
145                 type = NULL;
146                 near_error("Unknown tag type 0x%x", tag->type);
147                 break;
148         }
149
150         return type;
151 }
152
153 static const char *protocol_string(struct near_tag *tag)
154 {
155         const char *protocol;
156
157         DBG("protocol 0x%x", tag->protocol);
158
159         switch (tag->protocol) {
160         case NFC_PROTO_FELICA_MASK:
161                 protocol = "Felica";
162                 break;
163
164         case NFC_PROTO_MIFARE_MASK:
165                 protocol = "MIFARE";
166                 break;
167
168         case NFC_PROTO_JEWEL_MASK:
169                 protocol = "Jewel";
170                 break;
171
172         case NFC_PROTO_ISO14443_MASK:
173                 protocol = "ISO-DEP";
174                 break;
175
176         default:
177                 near_error("Unknown tag protocol 0x%x", tag->protocol);
178                 protocol = NULL;
179         }
180
181         return protocol;
182 }
183
184 static DBusMessage *get_properties(DBusConnection *conn,
185                                         DBusMessage *msg, void *data)
186 {
187         struct near_tag *tag = data;
188         const char *protocol, *type;
189         DBusMessage *reply;
190         DBusMessageIter array, dict;
191
192         DBG("conn %p", conn);
193
194         reply = dbus_message_new_method_return(msg);
195         if (reply == NULL)
196                 return NULL;
197
198         dbus_message_iter_init_append(reply, &array);
199
200         near_dbus_dict_open(&array, &dict);
201
202         type = type_string(tag);
203         if (type != NULL)
204                 near_dbus_dict_append_basic(&dict, "Type",
205                                         DBUS_TYPE_STRING, &type);
206
207         protocol = protocol_string(tag);
208         if (protocol != NULL)
209                 near_dbus_dict_append_basic(&dict, "Protocol",
210                                         DBUS_TYPE_STRING, &protocol);
211
212         near_dbus_dict_append_basic(&dict, "ReadOnly",
213                                         DBUS_TYPE_BOOLEAN, &tag->readonly);
214
215         near_dbus_dict_append_array(&dict, "Records",
216                                 DBUS_TYPE_OBJECT_PATH, append_records, tag);
217
218         near_dbus_dict_close(&array, &dict);
219
220         return reply;
221 }
222
223 static DBusMessage *set_property(DBusConnection *conn,
224                                         DBusMessage *msg, void *data)
225 {
226         DBG("conn %p", conn);
227
228         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
229 }
230
231 static void tag_read_cb(uint32_t adapter_idx, uint32_t target_idx, int status)
232 {
233         __near_adapter_tags_changed(adapter_idx);
234 }
235
236 static void write_cb(uint32_t adapter_idx, uint32_t target_idx, int status)
237 {
238         struct near_tag *tag;
239         DBusConnection *conn;
240         DBusMessage *reply;
241
242         DBG("Write status %d", status);
243
244         conn = near_dbus_get_connection();
245         tag = near_tag_get_tag(adapter_idx, target_idx);
246
247         if (conn == NULL || tag == NULL)
248                 return;
249
250         if (status != 0) {
251                 reply = __near_error_failed(tag->write_msg, EINVAL);
252                 if (reply != NULL)
253                         g_dbus_send_message(conn, reply);
254         } else {
255                 g_dbus_send_reply(conn, tag->write_msg, DBUS_TYPE_INVALID);
256         }
257
258         dbus_message_unref(tag->write_msg);
259         tag->write_msg = NULL;
260
261         near_ndef_records_free(tag->records);
262         tag->n_records = 0;
263         tag->records = NULL;
264         g_free(tag->data);
265
266         if (status == 0)
267                 __near_tag_read(tag, tag_read_cb);
268 }
269
270 static void format_cb(uint32_t adapter_idx, uint32_t target_idx, int status)
271 {
272         struct near_tag *tag;
273         int err;
274
275         DBG("format status %d", status);
276
277         tag = near_tag_get_tag(adapter_idx, target_idx);
278         if (tag == NULL)
279                 return;
280
281         if (tag->write_msg == NULL)
282                 return;
283
284         if (status == 0) {
285                 err = __near_tag_write(tag, tag->write_ndef,
286                                                 write_cb);
287                 if (err < 0)
288                         goto error;
289         } else {
290                 err = status;
291                 goto error;
292         }
293
294         return;
295
296 error:
297         write_cb(tag->adapter_idx, tag->target_idx, err);
298 }
299
300 static DBusMessage *write_ndef(DBusConnection *conn,
301                                 DBusMessage *msg, void *data)
302 {
303         struct near_tag *tag = data;
304         struct near_ndef_message *ndef, *ndef_with_header = NULL;
305         int err;
306
307         DBG("conn %p", conn);
308
309         if (tag->readonly == TRUE) {
310                 DBG("Read only tag");
311                 return __near_error_permission_denied(msg);
312         }
313
314         if (tag->write_msg)
315                 return __near_error_in_progress(msg);
316
317         ndef = __ndef_build_from_message(msg);
318         if (ndef == NULL)
319                 return __near_error_failed(msg, EINVAL);
320
321         tag->write_msg = dbus_message_ref(msg);
322
323         /* Add NDEF header information depends upon tag type */
324         switch (tag->type) {
325         case NFC_PROTO_JEWEL:
326         case NFC_PROTO_MIFARE:
327                 ndef_with_header = g_try_malloc0(sizeof(
328                                         struct near_ndef_message));
329                 if (ndef_with_header == NULL)
330                         goto fail;
331
332                 ndef_with_header->offset = 0;
333                 ndef_with_header->length = ndef->length + 3;
334                 ndef_with_header->data = g_try_malloc0(ndef->length + 3);
335                 if (ndef_with_header->data == NULL)
336                         goto fail;
337
338                 ndef_with_header->data[0] = TLV_NDEF;
339                 ndef_with_header->data[1] = ndef->length;
340                 memcpy(ndef_with_header->data + 2, ndef->data, ndef->length);
341                 ndef_with_header->data[ndef->length + 2] = TLV_END;
342
343                 break;
344
345         case NFC_PROTO_FELICA:
346                 ndef_with_header = g_try_malloc0(sizeof(
347                                         struct near_ndef_message));
348                 if (ndef_with_header == NULL)
349                         goto fail;
350
351                 ndef_with_header->offset = 0;
352                 ndef_with_header->length = ndef->length;
353                 ndef_with_header->data = g_try_malloc0(
354                                                 ndef_with_header->length);
355                 if (ndef_with_header->data == NULL)
356                         goto fail;
357
358                 memcpy(ndef_with_header->data, ndef->data, ndef->length);
359
360                 break;
361
362         case NFC_PROTO_ISO14443:
363                 ndef_with_header = g_try_malloc0(sizeof(
364                                         struct near_ndef_message));
365                 if (ndef_with_header == NULL)
366                         goto fail;
367
368                 ndef_with_header->offset = 0;
369                 ndef_with_header->length = ndef->length + 2;
370                 ndef_with_header->data = g_try_malloc0(ndef->length + 2);
371                 if (ndef_with_header->data == NULL)
372                         goto fail;
373
374                 ndef_with_header->data[0] = (uint8_t)(ndef->length >> 8);
375                 ndef_with_header->data[1] = (uint8_t)(ndef->length);
376                 memcpy(ndef_with_header->data + 2, ndef->data, ndef->length);
377
378                 break;
379
380         default:
381                 g_free(ndef->data);
382                 g_free(ndef);
383
384                 return __near_error_failed(msg, EOPNOTSUPP);
385         }
386
387         g_free(ndef->data);
388         g_free(ndef);
389
390         tag->write_ndef = ndef_with_header;
391         err = __near_tag_write(tag, ndef_with_header, write_cb);
392         if (err < 0) {
393                 g_free(ndef_with_header->data);
394                 g_free(ndef_with_header);
395
396                 return __near_error_failed(msg, -err);
397         }
398
399         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
400
401 fail:
402         dbus_message_unref(tag->write_msg);
403         tag->write_msg = NULL;
404
405         return __near_error_failed(msg, ENOMEM);
406 }
407
408 static const GDBusMethodTable tag_methods[] = {
409         { GDBUS_METHOD("GetProperties",
410                                 NULL, GDBUS_ARGS({"properties", "a{sv}"}),
411                                 get_properties) },
412         { GDBUS_METHOD("SetProperty",
413                                 GDBUS_ARGS({"name", "s"}, {"value", "v"}),
414                                 NULL, set_property) },
415         { GDBUS_ASYNC_METHOD("Write", GDBUS_ARGS({"attributes", "a{sv}"}),
416                                                         NULL, write_ndef) },
417         { },
418 };
419
420 static const GDBusSignalTable tag_signals[] = {
421         { GDBUS_SIGNAL("PropertyChanged",
422                                 GDBUS_ARGS({"name", "s"}, {"value", "v"})) },
423         { }
424 };
425
426
427 void __near_tag_append_records(struct near_tag *tag, DBusMessageIter *iter)
428 {
429         GList *list;
430
431         for (list = tag->records; list; list = list->next) {
432                 struct near_ndef_record *record = list->data;
433                 char *path;
434
435                 path = __near_ndef_record_get_path(record);
436                 if (path == NULL)
437                         continue;
438
439                 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
440                                                         &path);
441         }
442 }
443
444 #define NFC_TAG_A (NFC_PROTO_ISO14443_MASK | NFC_PROTO_NFC_DEP_MASK | \
445                                 NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK)
446 #define NFC_TAG_A_TYPE2      0x00
447 #define NFC_TAG_A_TYPE4      0x01
448 #define NFC_TAG_A_NFC_DEP    0x02
449 #define NFC_TAG_A_TYPE4_DEP  0x03
450
451 #define NFC_TAG_A_SENS_RES_SSD_JEWEL      0x00
452 #define NFC_TAG_A_SENS_RES_PLATCONF_JEWEL 0x0c
453
454 #define NFC_TAG_A_SEL_PROT(sel_res) (((sel_res) & 0x60) >> 5)
455 #define NFC_TAG_A_SEL_CASCADE(sel_res) (((sel_res) & 0x04) >> 2)
456 #define NFC_TAG_A_SENS_RES_SSD(sens_res) ((sens_res) & 0x001f)
457 #define NFC_TAG_A_SENS_RES_PLATCONF(sens_res) (((sens_res) & 0x0f00) >> 8)
458
459 static enum near_tag_sub_type get_tag_type2_sub_type(uint8_t sel_res)
460 {
461         switch(sel_res) {
462         case 0x00 :
463                 return NEAR_TAG_NFC_T2_MIFARE_ULTRALIGHT;
464         case 0x08:
465                 return NEAR_TAG_NFC_T2_MIFARE_CLASSIC_1K;
466         case 0x09:
467                 return NEAR_TAG_NFC_T2_MIFARE_MINI;
468         case 0x18:
469                 return NEAR_TAG_NFC_T2_MIFARE_CLASSIC_4K;
470         case 0x20:
471                 return NEAR_TAG_NFC_T2_MIFARE_DESFIRE;
472         case 0x28 :
473                 return NEAR_TAG_NFC_T2_JCOP30;
474         case 0x38:
475                 return NEAR_TAG_NFC_T2_MIFARE_4K_EMUL;
476         case 0x88:
477                 return NEAR_TAG_NFC_T2_MIFARE_1K_INFINEON;
478         case 0x98:
479                 return NEAR_TAG_NFC_T2_MPCOS;
480         }
481
482         return NEAR_TAG_NFC_SUBTYPE_UNKNOWN;
483 }
484
485 static void set_tag_type(struct near_tag *tag,
486                                 uint16_t sens_res, uint8_t sel_res)
487 {
488         uint8_t platconf, ssd, proto;
489
490         DBG("protocol 0x%x sens_res 0x%x sel_res 0x%x", tag->protocol,
491                                                         sens_res, sel_res);
492
493         switch (tag->protocol) {
494         case NFC_PROTO_JEWEL_MASK:
495                 platconf = NFC_TAG_A_SENS_RES_PLATCONF(sens_res);
496                 ssd = NFC_TAG_A_SENS_RES_SSD(sens_res);
497
498                 DBG("Jewel");
499
500                 if ((ssd == NFC_TAG_A_SENS_RES_SSD_JEWEL) &&
501                                 (platconf == NFC_TAG_A_SENS_RES_PLATCONF_JEWEL))
502                         tag->type = NFC_PROTO_JEWEL;
503                 break;
504
505         case NFC_PROTO_MIFARE_MASK:
506         case NFC_PROTO_ISO14443_MASK:
507                 proto = NFC_TAG_A_SEL_PROT(sel_res);
508
509                 DBG("proto 0x%x", proto);
510
511                 switch(proto) {
512                 case NFC_TAG_A_TYPE2:
513                         tag->type = NFC_PROTO_MIFARE;
514                         tag->sub_type = get_tag_type2_sub_type(sel_res);
515                         break;
516                 case NFC_TAG_A_TYPE4:
517                         tag->type = NFC_PROTO_ISO14443;
518                         break;
519                 case NFC_TAG_A_TYPE4_DEP:
520                         tag->type = NFC_PROTO_NFC_DEP;
521                         break;
522                 }
523                 break;
524
525         case NFC_PROTO_FELICA_MASK:
526                 tag->type = NFC_PROTO_FELICA;
527                 break;
528
529         default:
530                 tag->type = NFC_PROTO_MAX;
531                 break;
532         }
533
534         DBG("tag type 0x%x", tag->type);
535 }
536
537 static int tag_initialize(struct near_tag *tag,
538                         uint32_t adapter_idx, uint32_t target_idx,
539                         uint32_t protocols,
540                         uint16_t sens_res, uint8_t sel_res,
541                         uint8_t *nfcid, uint8_t nfcid_len)
542 {
543         DBG("");
544
545         tag->path = g_strdup_printf("%s/nfc%d/tag%d", NFC_PATH,
546                                         adapter_idx, target_idx);
547         if (tag->path == NULL)
548                 return -ENOMEM;
549         tag->adapter_idx = adapter_idx;
550         tag->target_idx = target_idx;
551         tag->protocol = protocols;
552         tag->n_records = 0;
553         tag->readonly = FALSE;
554
555         if (nfcid_len <= NFC_MAX_NFCID1_LEN) {
556                 tag->nfcid_len = nfcid_len;
557                 memcpy(tag->nfcid, nfcid, nfcid_len);
558         }
559
560         set_tag_type(tag, sens_res, sel_res);
561
562         return 0;
563 }
564
565 struct near_tag *__near_tag_add(uint32_t adapter_idx, uint32_t target_idx,
566                                 uint32_t protocols,
567                                 uint16_t sens_res, uint8_t sel_res,
568                                 uint8_t *nfcid, uint8_t nfcid_len)
569 {
570         struct near_tag *tag;
571         char *path;
572
573         tag = near_tag_get_tag(adapter_idx, target_idx);
574         if (tag != NULL)
575                 return NULL;
576
577         tag = g_try_malloc0(sizeof(struct near_tag));
578         if (tag == NULL)
579                 return NULL;
580
581         if (tag_initialize(tag, adapter_idx, target_idx,
582                                 protocols,
583                                 sens_res, sel_res,
584                                 nfcid, nfcid_len) < 0) {
585                 g_free(tag);
586                 return NULL;
587         }
588
589         path = g_strdup(tag->path);
590         if (path == NULL) {
591                 g_free(tag);
592                 return NULL;
593         }
594
595         g_hash_table_insert(tag_hash, path, tag);
596
597         DBG("connection %p", connection);
598
599         g_dbus_register_interface(connection, tag->path,
600                                         NFC_TAG_INTERFACE,
601                                         tag_methods, tag_signals,
602                                                         NULL, tag, NULL);
603
604         return tag;
605 }
606
607 void __near_tag_remove(struct near_tag *tag)
608 {
609         char *path = tag->path;
610
611         DBG("path %s", tag->path);
612
613         if (g_hash_table_lookup(tag_hash, tag->path) == NULL)
614                 return;
615
616         g_dbus_unregister_interface(connection, tag->path,
617                                                 NFC_TAG_INTERFACE);
618
619         g_hash_table_remove(tag_hash, path);
620 }
621
622 const char *__near_tag_get_path(struct near_tag *tag)
623 {
624         return tag->path;
625 }
626
627
628 uint32_t __near_tag_get_idx(struct near_tag *tag)
629 {
630         return tag->target_idx;
631 }
632
633 uint32_t __near_tag_get_type(struct near_tag *tag)
634 {
635         return tag->type;
636 }
637
638 enum near_tag_sub_type near_tag_get_subtype(uint32_t adapter_idx,
639                                 uint32_t target_idx)
640
641 {
642         struct near_tag *tag;
643
644         tag = near_tag_get_tag(adapter_idx, target_idx);
645         if (tag == NULL)
646                 return NEAR_TAG_NFC_SUBTYPE_UNKNOWN;
647
648         return tag->sub_type;
649 }
650
651 uint8_t *near_tag_get_nfcid(uint32_t adapter_idx, uint32_t target_idx,
652                                 uint8_t *nfcid_len)
653 {
654         struct near_tag *tag;
655         uint8_t *nfcid;
656
657         tag = near_tag_get_tag(adapter_idx, target_idx);
658         if (tag == NULL)
659                 goto fail;
660
661         nfcid = g_try_malloc0(tag->nfcid_len);
662         if (nfcid == NULL)
663                 goto fail;
664
665         memcpy(nfcid, tag->nfcid, tag->nfcid_len);
666         *nfcid_len = tag->nfcid_len;
667
668         return nfcid;
669
670 fail:
671         *nfcid_len = 0;
672         return NULL;
673 }
674
675 int near_tag_set_nfcid(uint32_t adapter_idx, uint32_t target_idx,
676                                         uint8_t *nfcid, size_t nfcid_len)
677 {
678         struct near_tag *tag;
679
680         DBG("NFCID len %zd", nfcid_len);
681
682         tag = near_tag_get_tag(adapter_idx, target_idx);
683         if (tag == NULL)
684                 return -ENODEV;
685
686         if (tag->nfcid_len > 0)
687                 return -EALREADY;
688
689         if (nfcid_len > NFC_MAX_NFCID1_LEN)
690                 return -EINVAL;
691
692         memcpy(tag->nfcid, nfcid, nfcid_len);
693         tag->nfcid_len = nfcid_len;
694
695         return 0;
696 }
697
698 int near_tag_add_data(uint32_t adapter_idx, uint32_t target_idx,
699                         uint8_t *data, size_t data_length)
700 {
701         struct near_tag *tag;
702
703         tag = near_tag_get_tag(adapter_idx, target_idx);
704         if (tag == NULL)
705                 return -ENODEV;
706
707         tag->data_length = data_length;
708         tag->data = g_try_malloc0(data_length);
709         if (tag->data == NULL)
710                 return -ENOMEM;
711
712         if (data != NULL)
713                 memcpy(tag->data, data, data_length);
714
715         return 0;
716 }
717
718 int near_tag_add_records(struct near_tag *tag, GList *records,
719                                 near_tag_io_cb cb, int status)
720 {
721         GList *list;
722         struct near_ndef_record *record;
723         char *path;
724
725         DBG("records %p", records);
726
727         for (list = records; list; list = list->next) {
728                 record = list->data;
729
730                 path = g_strdup_printf("%s/nfc%d/tag%d/record%d",
731                                         NFC_PATH, tag->adapter_idx,
732                                         tag->target_idx, tag->n_records);
733
734                 if (path == NULL)
735                         continue;
736
737                 __near_ndef_record_register(record, path);
738
739                 tag->n_records++;
740                 tag->records = g_list_append(tag->records, record);
741         }
742
743         __near_agent_ndef_parse_records(tag->records);
744
745         if (cb != NULL)
746                 cb(tag->adapter_idx, tag->target_idx, status);
747
748         g_list_free(records);
749
750         return 0;
751 }
752
753 void near_tag_set_ro(struct near_tag *tag, near_bool_t readonly)
754 {
755         tag->readonly = readonly;
756 }
757
758 void near_tag_set_blank(struct near_tag *tag, near_bool_t blank)
759 {
760         tag->blank = blank;
761 }
762
763 uint8_t *near_tag_get_data(struct near_tag *tag, size_t *data_length)
764 {
765         if (data_length == NULL)
766                 return NULL;
767
768         *data_length = tag->data_length;
769
770         return tag->data;
771 }
772
773 uint32_t near_tag_get_adapter_idx(struct near_tag *tag)
774 {
775         return tag->adapter_idx;
776 }
777
778 uint32_t near_tag_get_target_idx(struct near_tag *tag)
779 {
780         return tag->target_idx;
781 }
782
783 enum near_tag_memory_layout near_tag_get_memory_layout(struct near_tag *tag)
784 {
785         if (tag == NULL)
786                 return NEAR_TAG_MEMORY_UNKNOWN;
787
788         return tag->layout;
789 }
790
791 void near_tag_set_memory_layout(struct near_tag *tag,
792                                         enum near_tag_memory_layout layout)
793 {
794         if (tag == NULL)
795                 return;
796
797         tag->layout = layout;
798 }
799
800 void near_tag_set_max_ndef_size(struct near_tag *tag, uint16_t size)
801 {
802         if (tag == NULL)
803                 return;
804
805         tag->t4.max_ndef_size = size;
806 }
807
808 uint16_t near_tag_get_max_ndef_size(struct near_tag *tag)
809 {
810         if (tag == NULL)
811                 return 0;
812
813         return tag->t4.max_ndef_size;
814 }
815
816 void near_tag_set_c_apdu_max_size(struct near_tag *tag, uint16_t size)
817 {
818         if (tag == NULL)
819                 return;
820
821         tag->t4.c_apdu_max_size = size;
822 }
823
824 uint16_t near_tag_get_c_apdu_max_size(struct near_tag *tag)
825 {
826         if (tag == NULL)
827                 return 0;
828
829         return tag->t4.c_apdu_max_size;
830 }
831
832 void near_tag_set_idm(struct near_tag *tag, uint8_t *idm, uint8_t len)
833 {
834         if (tag == NULL || len > TYPE3_IDM_LEN)
835                 return;
836
837         memset(tag->t3.IDm, 0, TYPE3_IDM_LEN);
838         memcpy(tag->t3.IDm, idm, len);
839 }
840
841 uint8_t *near_tag_get_idm(struct near_tag *tag, uint8_t *len)
842 {
843         if (tag == NULL || len == NULL)
844                 return NULL;
845
846         *len = TYPE3_IDM_LEN;
847         return tag->t3.IDm;
848 }
849
850 void near_tag_set_attr_block(struct near_tag *tag, uint8_t *attr, uint8_t len)
851 {
852         if (tag == NULL || len > TYPE3_ATTR_BLOCK_SIZE)
853                 return;
854
855         memset(tag->t3.attr, 0, TYPE3_ATTR_BLOCK_SIZE);
856         memcpy(tag->t3.attr, attr, len);
857 }
858
859 uint8_t *near_tag_get_attr_block(struct near_tag *tag, uint8_t *len)
860 {
861         if (tag == NULL || len == NULL)
862                 return NULL;
863
864         *len = TYPE3_ATTR_BLOCK_SIZE;
865         return tag->t3.attr;
866 }
867
868 void near_tag_set_ic_type(struct near_tag *tag, uint8_t ic_type)
869 {
870         if (tag == NULL)
871                 return;
872
873         tag->t3.ic_type = ic_type;
874 }
875
876 uint8_t near_tag_get_ic_type(struct near_tag *tag)
877 {
878         if (tag == NULL)
879                 return 0;
880
881         return tag->t3.ic_type;
882 }
883
884 static gint cmp_prio(gconstpointer a, gconstpointer b)
885 {
886         const struct near_tag_driver *driver1 = a;
887         const struct near_tag_driver *driver2 = b;
888
889         return driver2->priority - driver1->priority;
890 }
891
892 int near_tag_driver_register(struct near_tag_driver *driver)
893 {
894         DBG("");
895
896         if (driver->read == NULL)
897                 return -EINVAL;
898
899         driver_list = g_slist_insert_sorted(driver_list, driver, cmp_prio);
900
901         return 0;
902 }
903
904 void near_tag_driver_unregister(struct near_tag_driver *driver)
905 {
906         DBG("");
907
908         driver_list = g_slist_remove(driver_list, driver);
909 }
910
911 int __near_tag_read(struct near_tag *tag, near_tag_io_cb cb)
912 {
913         GSList *list;
914
915         DBG("type 0x%x", tag->type);
916
917         for (list = driver_list; list; list = list->next) {
918                 struct near_tag_driver *driver = list->data;
919
920                 DBG("driver type 0x%x", driver->type);
921
922                 if (driver->type == tag->type)
923                         return driver->read(tag->adapter_idx, tag->target_idx,
924                                                                         cb);
925         }
926
927         return 0;
928 }
929
930 int __near_tag_write(struct near_tag *tag,
931                                 struct near_ndef_message *ndef,
932                                 near_tag_io_cb cb)
933 {
934         GSList *list;
935         int err;
936
937         DBG("type 0x%x", tag->type);
938
939         for (list = driver_list; list; list = list->next) {
940                 struct near_tag_driver *driver = list->data;
941
942                 DBG("driver type 0x%x", driver->type);
943
944                 if (driver->type == tag->type) {
945                         if (tag->blank == TRUE && driver->format != NULL) {
946                                 DBG("Blank tag detected, formatting");
947                                 err = driver->format(tag->adapter_idx,
948                                                 tag->target_idx, format_cb);
949                                 if (err < 0)
950                                         return err;
951                         } else {
952                                 return driver->write(tag->adapter_idx,
953                                                 tag->target_idx, ndef,
954                                                 cb);
955                         }
956                 }
957         }
958
959         return 0;
960 }
961
962 int __near_tag_check_presence(struct near_tag *tag, near_tag_io_cb cb)
963 {
964         GSList *list;
965
966         DBG("type 0x%x", tag->type);
967
968         for (list = driver_list; list; list = list->next) {
969                 struct near_tag_driver *driver = list->data;
970
971                 DBG("driver type 0x%x", driver->type);
972
973                 if (driver->type == tag->type) {
974                         if (driver->check_presence == NULL)
975                                 continue;
976
977                         return driver->check_presence(tag->adapter_idx, tag->target_idx, cb);
978                 }
979         }
980
981         return -EOPNOTSUPP;
982 }
983
984 static void free_tag(gpointer data)
985 {
986         struct near_tag *tag = data;
987
988         DBG("tag %p", tag);
989
990         near_ndef_records_free(tag->records);
991
992         g_free(tag->path);
993         g_free(tag->data);
994         g_free(tag);
995 }
996
997 int __near_tag_init(void)
998 {
999         DBG("");
1000
1001         connection = near_dbus_get_connection();
1002
1003         tag_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
1004                                                 g_free, free_tag);
1005
1006         return 0;
1007 }
1008
1009 void __near_tag_cleanup(void)
1010 {
1011         DBG("");
1012
1013         g_hash_table_destroy(tag_hash);
1014         tag_hash = NULL;
1015 }