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