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