adapter: Bypass the target layer
[platform/upstream/neard.git] / src / adapter.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 <unistd.h>
29 #include <errno.h>
30 #include <string.h>
31
32 #include <glib.h>
33
34 #include <gdbus.h>
35
36 #include "near.h"
37
38 /* We check for the tag being present every 2 seconds */
39 #define CHECK_PRESENCE_PERIOD 2
40
41 static DBusConnection *connection = NULL;
42
43 static GHashTable *adapter_hash;
44
45 struct near_adapter {
46         char *path;
47
48         char *name;
49         uint32_t idx;
50         uint32_t protocols;
51
52         near_bool_t powered;
53         near_bool_t polling;
54         near_bool_t constant_poll;
55         near_bool_t dep_up;
56
57         GHashTable *tags;
58         struct near_tag *tag_link;
59         int tag_sock;
60
61         GHashTable *devices;
62         struct near_tag *device_link;
63         int device_sock;
64
65         GIOChannel *channel;
66         guint watch;
67         GList *ioreq_list;
68         GList *ndef_q;
69
70         guint presence_timeout;
71 };
72
73 struct near_adapter_ioreq {
74         uint32_t target_idx;
75         near_recv cb;
76         unsigned char buf[1024];
77         size_t len;
78         void *data;
79 };
80
81 /* HACK HACK */
82 #ifndef AF_NFC
83 #define AF_NFC 39
84 #endif
85
86 static void free_adapter(gpointer data)
87 {
88         struct near_adapter *adapter = data;
89
90         if (adapter->presence_timeout > 0)
91                 g_source_remove(adapter->presence_timeout);
92
93         g_free(adapter->name);
94         g_free(adapter->path);
95         g_free(adapter);
96 }
97
98 static void free_tag(gpointer data)
99 {
100         struct near_tag *tag = data;
101
102         __near_tag_remove(tag);
103 }
104
105 static void polling_changed(struct near_adapter *adapter)
106 {
107
108         near_dbus_property_changed_basic(adapter->path,
109                                 NFC_ADAPTER_INTERFACE, "Polling",
110                                         DBUS_TYPE_BOOLEAN, &adapter->polling);
111 }
112
113 static int adapter_start_poll(struct near_adapter *adapter)
114 {
115         int err;
116
117         if (g_hash_table_size(adapter->tags) > 0) {
118                 DBG("Clearing tags");
119
120                 g_hash_table_remove_all(adapter->tags);
121                 __near_adapter_tags_changed(adapter->idx);
122         }
123
124         err = __near_netlink_start_poll(adapter->idx, adapter->protocols);
125         if (err < 0)
126                 return err;
127
128         adapter->polling = TRUE;
129
130         polling_changed(adapter);
131
132         return 0;
133 }
134
135 static void append_path(gpointer key, gpointer value, gpointer user_data)
136 {
137         struct near_adapter *adapter = value;
138         DBusMessageIter *iter = user_data;
139
140         DBG("%s", adapter->path);
141
142         if (adapter->path == NULL)
143                 return;
144
145         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
146                                                         &adapter->path);
147
148 }
149
150 void __near_adapter_list(DBusMessageIter *iter, void *user_data)
151 {
152         g_hash_table_foreach(adapter_hash, append_path, iter);
153 }
154
155 static void append_protocols(DBusMessageIter *iter, void *user_data)
156 {
157         struct near_adapter *adapter = user_data;
158         const char *str;
159
160         DBG("protocols 0x%x", adapter->protocols);
161
162         if (adapter->protocols & NFC_PROTO_FELICA_MASK) {
163                 str = "Felica";
164
165                 dbus_message_iter_append_basic(iter,
166                                 DBUS_TYPE_STRING, &str);
167         }
168
169         if (adapter->protocols & NFC_PROTO_MIFARE_MASK) {
170                 str = "MIFARE";
171
172                 dbus_message_iter_append_basic(iter,
173                                 DBUS_TYPE_STRING, &str);
174         }
175
176         if (adapter->protocols & NFC_PROTO_JEWEL_MASK) {
177                 str = "Jewel";
178
179                 dbus_message_iter_append_basic(iter,
180                                 DBUS_TYPE_STRING, &str);
181         }
182
183         if (adapter->protocols & NFC_PROTO_ISO14443_MASK) {
184                 str = "ISO-DEP";
185
186                 dbus_message_iter_append_basic(iter,
187                                 DBUS_TYPE_STRING, &str);
188         }
189
190         if (adapter->protocols & NFC_PROTO_NFC_DEP_MASK) {
191                 str = "NFC-DEP";
192
193                 dbus_message_iter_append_basic(iter,
194                                 DBUS_TYPE_STRING, &str);
195         }
196 }
197
198 static void append_tag_path(gpointer key, gpointer value, gpointer user_data)
199 {
200         struct near_tag *tag = value;
201         DBusMessageIter *iter = user_data;
202         const char *tag_path;
203
204         tag_path = __near_tag_get_path(tag);
205         if (tag_path == NULL)
206                 return;
207
208         DBG("%s", tag_path);
209
210         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
211                                                         &tag_path);
212 }
213
214 static void append_tags(DBusMessageIter *iter, void *user_data)
215 {
216         struct near_adapter *adapter = user_data;
217
218         DBG("");
219
220         g_hash_table_foreach(adapter->tags, append_tag_path, iter);
221 }
222
223 void __near_adapter_tags_changed(uint32_t adapter_idx)
224 {
225         struct near_adapter *adapter;
226
227         DBG("");
228
229         adapter = g_hash_table_lookup(adapter_hash,
230                                 GINT_TO_POINTER(adapter_idx));
231         if (adapter == NULL)
232                 return;
233
234         near_dbus_property_changed_array(adapter->path,
235                                 NFC_ADAPTER_INTERFACE, "Tags",
236                                 DBUS_TYPE_OBJECT_PATH, append_tags,
237                                 adapter);
238 }
239 static DBusMessage *get_properties(DBusConnection *conn,
240                                         DBusMessage *msg, void *data)
241 {
242         struct near_adapter *adapter = data;
243         DBusMessage *reply;
244         DBusMessageIter array, dict;
245
246         DBG("conn %p", conn);
247
248         reply = dbus_message_new_method_return(msg);
249         if (reply == NULL)
250                 return NULL;
251
252         dbus_message_iter_init_append(reply, &array);
253
254         near_dbus_dict_open(&array, &dict);
255
256         near_dbus_dict_append_basic(&dict, "Powered",
257                                     DBUS_TYPE_BOOLEAN, &adapter->powered);
258
259         near_dbus_dict_append_basic(&dict, "Polling",
260                                     DBUS_TYPE_BOOLEAN, &adapter->polling);
261
262         near_dbus_dict_append_array(&dict, "Protocols",
263                                 DBUS_TYPE_STRING, append_protocols, adapter);
264
265         near_dbus_dict_append_array(&dict, "Tags",
266                                 DBUS_TYPE_OBJECT_PATH, append_tags, adapter);
267
268         near_dbus_dict_close(&array, &dict);
269
270         return reply;
271 }
272
273 static DBusMessage *set_property(DBusConnection *conn,
274                                         DBusMessage *msg, void *data)
275 {
276         struct near_adapter *adapter = data;
277         DBusMessageIter iter, value;
278         const char *name;
279         int type, err;
280
281         DBG("conn %p", conn);
282
283         if (dbus_message_iter_init(msg, &iter) == FALSE)
284                 return __near_error_invalid_arguments(msg);
285
286         dbus_message_iter_get_basic(&iter, &name);
287         dbus_message_iter_next(&iter);
288         dbus_message_iter_recurse(&iter, &value);
289
290         type = dbus_message_iter_get_arg_type(&value);
291
292         if (g_str_equal(name, "Powered") == TRUE) {
293                 near_bool_t powered;
294
295                 if (type != DBUS_TYPE_BOOLEAN)
296                         return __near_error_invalid_arguments(msg);
297
298                 dbus_message_iter_get_basic(&value, &powered);
299
300                 err = __near_netlink_adapter_enable(adapter->idx, powered);
301                 if (err < 0)
302                         return __near_error_failed(msg, -err);
303
304                 adapter->powered = powered;
305         } else
306                 return __near_error_invalid_property(msg);
307
308         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
309 }
310
311 static DBusMessage *start_poll(DBusConnection *conn,
312                                         DBusMessage *msg, void *data)
313 {
314         struct near_adapter *adapter = data;
315         int err;
316
317         DBG("conn %p", conn);
318
319         err = adapter_start_poll(adapter);
320         if (err < 0)
321                 return __near_error_failed(msg, -err);
322
323         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
324 }
325
326 static DBusMessage *stop_poll(DBusConnection *conn,
327                                         DBusMessage *msg, void *data)
328 {
329         struct near_adapter *adapter = data;
330         int err;
331
332         DBG("conn %p", conn);
333
334         err = __near_netlink_stop_poll(adapter->idx);
335         if (err < 0)
336                 return __near_error_failed(msg, -err);
337
338         adapter->polling = FALSE;
339
340         polling_changed(adapter);
341
342         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
343 }
344
345 static int __push_ndef_queue(struct near_adapter *adapter,
346                                         struct near_ndef_message *ndef)
347 {
348         if (adapter == NULL || ndef == NULL)
349                 return -EINVAL;
350
351         adapter->ndef_q = g_list_append(adapter->ndef_q, ndef);
352
353         return 0;
354 }
355
356 static struct near_ndef_message *
357 __pop_ndef_queue(struct near_adapter *adapter)
358 {
359         GList *list;
360         struct near_ndef_message *ndef;
361
362         if (adapter == NULL)
363                 return NULL;
364
365         list = g_list_first(adapter->ndef_q);
366         if (list == NULL)
367                 return NULL;
368
369         ndef = list->data;
370         if (ndef != NULL)
371                 adapter->ndef_q = g_list_remove(adapter->ndef_q, ndef);
372
373         return ndef;
374 }
375
376 static int __publish_text_record(DBusMessage *msg, void *data)
377 {
378         DBusMessageIter iter, arr_iter;
379         struct near_ndef_message *ndef;
380         char *cod = NULL, *lang = NULL, *rep = NULL;
381
382         DBG("");
383
384         dbus_message_iter_init(msg, &iter);
385         dbus_message_iter_recurse(&iter, &arr_iter);
386
387         while (dbus_message_iter_get_arg_type(&arr_iter) !=
388                                         DBUS_TYPE_INVALID) {
389                 const char *key;
390                 DBusMessageIter ent_iter;
391                 DBusMessageIter var_iter;
392
393                 dbus_message_iter_recurse(&arr_iter, &ent_iter);
394                 dbus_message_iter_get_basic(&ent_iter, &key);
395                 dbus_message_iter_next(&ent_iter);
396                 dbus_message_iter_recurse(&ent_iter, &var_iter);
397
398                 switch (dbus_message_iter_get_arg_type(&var_iter)) {
399                 case DBUS_TYPE_STRING:
400                         if (g_strcmp0(key, "Encoding") == 0)
401                                 dbus_message_iter_get_basic(&var_iter, &cod);
402                         else if (g_strcmp0(key, "Language") == 0)
403                                 dbus_message_iter_get_basic(&var_iter, &lang);
404                         else if (g_strcmp0(key, "Representation") == 0)
405                                 dbus_message_iter_get_basic(&var_iter, &rep);
406
407                         break;
408                 }
409
410                 dbus_message_iter_next(&arr_iter);
411         }
412
413         ndef = near_ndef_prepare_text_record(cod, lang, rep);
414         if (ndef == NULL)
415                 return -EINVAL;
416
417         return __push_ndef_queue(data, ndef);
418 }
419
420 static void tag_present_cb(uint32_t adapter_idx, uint32_t target_idx,
421                                                                 int status);
422
423 static gboolean check_presence(gpointer user_data)
424 {
425         struct near_adapter *adapter = user_data;
426         struct near_tag *tag;
427         int err;
428
429         DBG("");
430
431         if (adapter == NULL)
432                 return FALSE;
433
434         tag = adapter->tag_link;
435         if (tag == NULL)
436                 return FALSE;
437
438         err = __near_tag_check_presence(tag, tag_present_cb);
439         if (err < 0) {
440                 DBG("Could not check target presence");
441
442                 near_adapter_disconnect(adapter->idx);
443                 if (adapter->constant_poll == TRUE)
444                         adapter_start_poll(adapter);
445         }
446
447         return FALSE;
448 }
449
450 static void tag_present_cb(uint32_t adapter_idx, uint32_t target_idx,
451                                                                 int status)
452 {
453         struct near_adapter *adapter;
454
455         DBG("");
456
457         adapter = g_hash_table_lookup(adapter_hash,
458                                         GINT_TO_POINTER(adapter_idx));
459         if (adapter == NULL)
460                 return;
461
462         if (status < 0) {
463                 DBG("Tag is gone");
464
465                 near_adapter_disconnect(adapter->idx);
466                 if (adapter->constant_poll == TRUE)
467                         adapter_start_poll(adapter);
468
469                 return;
470         }
471
472         adapter->presence_timeout =
473                 g_timeout_add_seconds(CHECK_PRESENCE_PERIOD,
474                                         check_presence, adapter);
475 }
476
477 static char *get_uri_field(DBusMessage *msg)
478 {
479         DBusMessageIter iter, arr_iter;
480         char *uri = NULL;
481
482         DBG("");
483
484         dbus_message_iter_init(msg, &iter);
485         dbus_message_iter_recurse(&iter, &arr_iter);
486
487         while (dbus_message_iter_get_arg_type(&arr_iter) !=
488                                         DBUS_TYPE_INVALID) {
489                 const char *key;
490                 DBusMessageIter ent_iter;
491                 DBusMessageIter var_iter;
492
493                 dbus_message_iter_recurse(&arr_iter, &ent_iter);
494                 dbus_message_iter_get_basic(&ent_iter, &key);
495                 dbus_message_iter_next(&ent_iter);
496                 dbus_message_iter_recurse(&ent_iter, &var_iter);
497
498                 switch (dbus_message_iter_get_arg_type(&var_iter)) {
499                 case DBUS_TYPE_STRING:
500                         if (g_strcmp0(key, "URI") == 0)
501                                 dbus_message_iter_get_basic(&var_iter, &uri);
502
503                         break;
504                 }
505
506                 dbus_message_iter_next(&arr_iter);
507         }
508
509         return uri;
510 }
511
512 static int publish_uri_record(DBusMessage *msg, void *data)
513 {
514         struct near_ndef_message *ndef;
515         char *uri = NULL;
516         const char *uri_prefix = NULL;
517         uint8_t id_len, i;
518         uint32_t uri_len;
519
520         DBG("");
521
522         uri = get_uri_field(msg);
523         if (uri == NULL)
524                 return -EINVAL;
525
526         for (i = 1; i <= NFC_MAX_URI_ID; i++) {
527                 uri_prefix = __near_ndef_get_uri_prefix(i);
528
529                 if (uri_prefix != NULL &&
530                                 g_str_has_prefix(uri, uri_prefix) == TRUE)
531                         break;
532         }
533
534         /* If uri_prefix is NULL then ID will be zero */
535         if (uri_prefix == NULL) {
536                 i = 0;
537                 id_len = 0;
538         } else
539                 id_len = strlen(uri_prefix);
540
541         uri_len = strlen(uri) - id_len;
542         ndef = near_ndef_prepare_uri_record(i, uri_len,
543                                                 (uint8_t *)(uri + id_len));
544         if (ndef == NULL)
545                 return -EINVAL;
546
547         return __push_ndef_queue(data, ndef);
548 }
549
550 static int publish_sp_record(DBusMessage *msg, void *data)
551 {
552         struct near_ndef_message *ndef;
553         char *uri = NULL;
554         const char *uri_prefix;
555         uint8_t id_len, i;
556         uint32_t uri_len;
557
558         DBG("");
559
560         /* Currently this funtion supports only mandatory URI record,
561          * TODO: Other records support */
562         uri = get_uri_field(msg);
563         if (uri == NULL)
564                 return -EINVAL;
565
566         for (i = 1; i <= NFC_MAX_URI_ID; i++) {
567                 uri_prefix = __near_ndef_get_uri_prefix(i);
568
569                 if (uri_prefix != NULL &&
570                                 g_str_has_prefix(uri, uri_prefix) == TRUE)
571                         break;
572         }
573
574         if (uri_prefix == NULL) {
575                 i = 0;
576                 id_len = 0;
577         } else
578                 id_len = strlen(uri_prefix);
579
580         uri_len = strlen(uri) - id_len;
581         ndef = near_ndef_prepare_smartposter_record(i, uri_len,
582                                                 (uint8_t *)(uri + id_len));
583         if (ndef == NULL)
584                 return -EINVAL;
585
586         return __push_ndef_queue(data, ndef);
587 }
588
589 static void __add_ndef_cb(uint32_t adapter_idx, uint32_t target_idx, int status)
590 {
591         struct near_adapter *adapter;
592
593         DBG("%d", status);
594
595         adapter = g_hash_table_lookup(adapter_hash,
596                                         GINT_TO_POINTER(adapter_idx));
597         if (adapter == NULL)
598                 return;
599
600         adapter->presence_timeout =
601                 g_timeout_add_seconds(CHECK_PRESENCE_PERIOD,
602                                         check_presence, adapter);
603 }
604
605 static DBusMessage *publish(DBusConnection *conn,
606                                 DBusMessage *msg, void *data)
607 {
608         DBusMessageIter iter;
609         DBusMessageIter arr_iter;
610         struct near_adapter *adapter = data;
611
612         DBG("conn %p", conn);
613
614         dbus_message_iter_init(msg, &iter);
615         dbus_message_iter_recurse(&iter, &arr_iter);
616
617         while (dbus_message_iter_get_arg_type(&arr_iter) !=
618                                                 DBUS_TYPE_INVALID) {
619                 const char *key, *value;
620                 DBusMessageIter ent_iter;
621                 DBusMessageIter var_iter;
622
623                 dbus_message_iter_recurse(&arr_iter, &ent_iter);
624                 dbus_message_iter_get_basic(&ent_iter, &key);
625
626                 if (g_strcmp0(key, "Type") != 0) {
627                         dbus_message_iter_next(&arr_iter);
628                         continue;
629                 }
630
631                 dbus_message_iter_next(&ent_iter);
632                 dbus_message_iter_recurse(&ent_iter, &var_iter);
633
634                 switch (dbus_message_iter_get_arg_type(&var_iter)) {
635                 case DBUS_TYPE_STRING:
636                         dbus_message_iter_get_basic(&var_iter, &value);
637
638                         if (g_strcmp0(value, "Text") == 0) {
639                                 if (__publish_text_record(msg, adapter) < 0)
640                                                 goto error;
641
642                                 goto reply;
643                         } else if (g_strcmp0(value, "URI") == 0) {
644                                 if (publish_uri_record(msg, adapter)    < 0)
645                                         goto error;
646
647                                 goto reply;
648
649                         } else if (g_strcmp0(value, "SmartPoster") == 0) {
650                                 if (publish_sp_record(msg, adapter) < 0)
651                                         goto error;
652
653                                 goto reply;
654
655                         } else {
656                                 DBG(" '%s' not supported", value);
657                                 goto error;
658                         }
659
660                                 break;
661                 }
662
663                 dbus_message_iter_next(&arr_iter);
664         }
665
666 error:
667         return g_dbus_create_error(msg, "org.neard.Error.InvalidArguments",
668                                                         "Invalid arguments");
669
670 reply:
671         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
672 }
673
674 static GDBusMethodTable adapter_methods[] = {
675         { "GetProperties",     "",      "a{sv}", get_properties     },
676         { "SetProperty",       "sv",    "",      set_property       },
677         { "StartPoll",         "",      "",      start_poll         },
678         { "StopPoll",          "",      "",      stop_poll          },
679         { "Publish",         "a{sv}",   "",      publish            },
680         { },
681 };
682
683 static GDBusSignalTable adapter_signals[] = {
684         { "PropertyChanged",            "sv"    },
685         { "TagFound",                   "o"     },
686         { "TagLost",                    "o"     },
687         { }
688 };
689
690 struct near_adapter * __near_adapter_create(uint32_t idx,
691                 const char *name, uint32_t protocols, near_bool_t powered)
692 {
693         struct near_adapter *adapter;
694
695         adapter = g_try_malloc0(sizeof(struct near_adapter));
696         if (adapter == NULL)
697                 return NULL;
698
699         adapter->name = g_strdup(name);
700         if (adapter->name == NULL) {
701                 g_free(adapter);
702                 return NULL;
703         }
704         adapter->idx = idx;
705         adapter->protocols = protocols;
706         adapter->powered = powered;
707         adapter->constant_poll = near_setting_get_bool("ConstantPoll");
708         adapter->dep_up = FALSE;
709         adapter->tags = g_hash_table_new_full(g_direct_hash, g_direct_equal,
710                                                         NULL, free_tag);
711         adapter->tag_sock = -1;
712
713         adapter->path = g_strdup_printf("%s/nfc%d", NFC_PATH, idx);
714
715         return adapter;
716 }
717
718 void __near_adapter_destroy(struct near_adapter *adapter)
719 {
720         DBG("");
721
722         free_adapter(adapter);
723 }
724
725 const char *__near_adapter_get_path(struct near_adapter *adapter)
726 {
727         return adapter->path;
728 }
729
730 struct near_adapter *__near_adapter_get(uint32_t idx)
731 {
732         return g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(idx));
733 }
734
735 int near_adapter_get_dep_state(uint32_t idx)
736 {
737         struct near_adapter *adapter;
738
739         DBG("idx %d", idx);
740
741         adapter = g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(idx));
742         if (adapter == NULL)
743                 return -ENODEV;
744
745         return adapter->dep_up;
746 }
747
748 int near_adapter_set_dep_state(uint32_t idx, near_bool_t dep)
749 {
750         struct near_adapter *adapter;
751
752         DBG("idx %d", idx);
753
754         adapter = g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(idx));
755         if (adapter == NULL)
756                 return -ENODEV;
757
758         adapter->dep_up = dep;
759
760         return 0;
761 }
762
763 int __near_adapter_add(struct near_adapter *adapter)
764 {
765         uint32_t idx = adapter->idx;
766
767         DBG("%s", adapter->path);
768
769         if (g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(idx)) != NULL)
770                 return -EEXIST;
771
772         g_hash_table_insert(adapter_hash, GINT_TO_POINTER(idx), adapter);
773
774         DBG("connection %p", connection);
775
776         g_dbus_register_interface(connection, adapter->path,
777                                         NFC_ADAPTER_INTERFACE,
778                                         adapter_methods, adapter_signals,
779                                                         NULL, adapter, NULL);
780
781         return 0;
782 }
783
784 void __near_adapter_remove(struct near_adapter *adapter)
785 {
786         DBG("%s", adapter->path);
787
788         g_dbus_unregister_interface(connection, adapter->path,
789                                                 NFC_ADAPTER_INTERFACE);
790
791         g_hash_table_remove(adapter_hash, GINT_TO_POINTER(adapter->idx));
792 }
793
794 #if 0
795 static int dep_link_up(uint32_t idx, uint32_t target_idx)
796 {
797         return __near_netlink_dep_link_up(idx, target_idx,
798                                         NFC_COMM_ACTIVE, NFC_RF_INITIATOR);
799 }
800
801 static int dep_link_down(uint32_t idx)
802 {
803         return __near_netlink_dep_link_down(idx);
804 }
805 #endif
806
807 static void tag_read_cb(uint32_t adapter_idx, uint32_t target_idx, int status)
808 {
809         struct near_adapter *adapter;
810         struct near_tag *tag;
811         struct near_ndef_message *ndef, *ndef_with_header = NULL;
812         uint16_t tag_type;
813         int err;
814
815         DBG("status %d", status);
816
817         adapter = g_hash_table_lookup(adapter_hash,
818                                         GINT_TO_POINTER(adapter_idx));
819         if (adapter == NULL)
820                 goto out;
821
822         if (status < 0) {
823                 near_adapter_disconnect(adapter->idx);
824                 if (adapter->constant_poll == TRUE)
825                         adapter_start_poll(adapter);
826
827                 return;
828         }
829
830         __near_adapter_tags_changed(adapter_idx);
831
832         /* Check if adapter ndef queue has any ndef messages,
833          * then write the ndef data on tag. */
834         if (g_list_length(adapter->ndef_q) == 0)
835                 goto out;
836
837         tag = g_hash_table_lookup(adapter->tags,
838                                         GINT_TO_POINTER(target_idx));
839         if (tag == NULL)
840                 goto out;
841
842         ndef = __pop_ndef_queue(adapter);
843         if (ndef == NULL)
844                 goto out;
845
846         tag_type = __near_tag_get_type(tag);
847
848         /* Add NDEF header information depends upon tag type */
849         switch (tag_type) {
850         case NFC_PROTO_JEWEL:
851         case NFC_PROTO_MIFARE:
852                 ndef_with_header = g_try_malloc0(sizeof(
853                                         struct near_ndef_message));
854                 if (ndef_with_header == NULL)
855                         goto out;
856
857                 ndef_with_header->offset = 0;
858                 ndef_with_header->length = ndef->length + 3;
859                 ndef_with_header->data = g_try_malloc0(ndef->length + 3);
860                 if (ndef_with_header->data == NULL)
861                         goto out;
862
863                 ndef_with_header->data[0] = TLV_NDEF;
864                 ndef_with_header->data[1] = ndef->length;
865                 memcpy(ndef_with_header->data + 2, ndef->data, ndef->length);
866                 ndef_with_header->data[ndef->length + 2] = TLV_END;
867
868                 break;
869
870         case NFC_PROTO_FELICA:
871                 ndef_with_header = g_try_malloc0(sizeof(
872                                         struct near_ndef_message));
873                 if (ndef_with_header == NULL)
874                         goto out;
875
876                 ndef_with_header->offset = 0;
877                 ndef_with_header->length = ndef->length;
878                 ndef_with_header->data = g_try_malloc0(
879                                                 ndef_with_header->length);
880                 if (ndef_with_header->data == NULL)
881                         goto out;
882
883                 memcpy(ndef_with_header->data, ndef->data, ndef->length);
884
885                 break;
886
887         case NFC_PROTO_ISO14443:
888                 ndef_with_header = g_try_malloc0(sizeof(
889                                         struct near_ndef_message));
890                 if (ndef_with_header == NULL)
891                         goto out;
892
893                 ndef_with_header->offset = 0;
894                 ndef_with_header->length = ndef->length + 2;
895                 ndef_with_header->data = g_try_malloc0(ndef->length + 2);
896                 if (ndef_with_header->data == NULL)
897                         goto out;
898
899                 ndef_with_header->data[0] = (uint8_t)(ndef->length >> 8);
900                 ndef_with_header->data[1] = (uint8_t)(ndef->length);
901                 memcpy(ndef_with_header->data + 2, ndef->data, ndef->length);
902
903                 break;
904
905         default:
906                 goto out;
907         }
908
909         g_free(ndef->data);
910         g_free(ndef);
911
912         err = __near_tag_add_ndef(tag, ndef_with_header, __add_ndef_cb);
913         if (err < 0) {
914                 g_free(ndef_with_header->data);
915                 g_free(ndef_with_header);
916                 goto out;
917         }
918
919         return;
920
921 out:
922         if (ndef_with_header != NULL) {
923                 g_free(ndef_with_header->data);
924                 g_free(ndef_with_header);
925         }
926
927         if (adapter != NULL)
928                 adapter->presence_timeout =
929                         g_timeout_add_seconds(CHECK_PRESENCE_PERIOD,
930                                                 check_presence, adapter);
931 }
932
933 static int adapter_add_tag(struct near_adapter *adapter, uint32_t target_idx,
934                         uint32_t protocols,
935                         uint16_t sens_res, uint8_t sel_res,
936                         uint8_t *nfcid, uint8_t nfcid_len)
937 {
938         struct near_tag *tag;
939         uint32_t tag_type;
940         int err;
941
942         tag = __near_tag_add(adapter->idx, target_idx, protocols,
943                                 sens_res, sel_res,
944                                 nfcid, nfcid_len);
945         if (tag == NULL)
946                 return -ENODEV;
947
948         g_hash_table_insert(adapter->tags, GINT_TO_POINTER(target_idx),
949                                                                 tag);
950
951         tag_type = __near_tag_get_type(tag);
952
953         err = near_adapter_connect(adapter->idx, target_idx, tag_type);
954         if (err < 0) {
955                 near_error("Could not connect");
956                 return err;
957         }
958
959         return __near_tag_read(tag, tag_read_cb);
960 }
961
962 int __near_adapter_add_target(uint32_t idx, uint32_t target_idx,
963                         uint32_t protocols, uint16_t sens_res, uint8_t sel_res,
964                         uint8_t *nfcid, uint8_t nfcid_len)
965 {
966         struct near_adapter *adapter;
967
968         DBG("idx %d", idx);
969
970         adapter = g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(idx));
971         if (adapter == NULL)
972                 return -ENODEV;
973
974         adapter->polling = FALSE;
975         polling_changed(adapter);
976
977         if (protocols & NFC_PROTO_NFC_DEP_MASK)
978                 return -EOPNOTSUPP;
979         else
980                 return adapter_add_tag(adapter, target_idx, protocols,
981                                         sens_res, sel_res, nfcid, nfcid_len);
982
983 }
984
985 int __near_adapter_remove_target(uint32_t idx, uint32_t target_idx)
986 {
987         struct near_adapter *adapter;
988         struct near_tag *tag;
989
990         DBG("idx %d", idx);
991
992         adapter = g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(idx));
993         if (adapter == NULL)
994                 return -ENODEV;
995
996         tag = g_hash_table_lookup(adapter->tags, GINT_TO_POINTER(target_idx));
997         if (tag != NULL) {
998                 g_hash_table_remove(adapter->tags, GINT_TO_POINTER(target_idx));
999
1000                 __near_adapter_tags_changed(idx);
1001
1002                 return 0;
1003         } else {
1004                 /* TODO search for devices */
1005                 return -ENODEV;
1006         }
1007 }
1008
1009 static void adapter_flush_rx(struct near_adapter *adapter, int error)
1010 {
1011         GList *list;
1012
1013         for (list = adapter->ioreq_list; list; list = list->next) {
1014                 struct near_adapter_ioreq *req = list->data;
1015
1016                 if (req == NULL)
1017                         continue;
1018
1019                 req->cb(NULL, error, req->data);
1020                 g_free(req);
1021         }
1022
1023         g_list_free(adapter->ioreq_list);
1024         adapter->ioreq_list = NULL;
1025 }
1026
1027 static gboolean execute_recv_cb(gpointer user_data)
1028 {
1029         struct near_adapter_ioreq *req = user_data;
1030
1031         DBG("data %p", req->data);
1032
1033         req->cb(req->buf, req->len, req->data);
1034
1035         g_free(req);
1036
1037         return FALSE;
1038 }
1039
1040 static gboolean adapter_recv_event(GIOChannel *channel, GIOCondition condition,
1041                                                         gpointer user_data)
1042 {
1043         struct near_adapter *adapter = user_data;
1044         struct near_adapter_ioreq *req;
1045         GList *first;
1046         int sk;
1047
1048         DBG("condition 0x%x", condition);
1049
1050         if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
1051                 near_error("Error while reading NFC bytes");
1052
1053                 adapter_flush_rx(adapter, -EIO);
1054                 return FALSE;
1055         }
1056
1057         sk = g_io_channel_unix_get_fd(channel);
1058         first = g_list_first(adapter->ioreq_list);
1059         if (first == NULL)
1060                 return TRUE;
1061
1062         req = first->data;
1063         req->len = recv(sk, req->buf, sizeof(req->buf), 0);
1064
1065         adapter->ioreq_list = g_list_remove(adapter->ioreq_list, req);
1066
1067         g_idle_add(execute_recv_cb, req);
1068
1069         return TRUE;
1070 }
1071
1072 int near_adapter_connect(uint32_t idx, uint32_t target_idx, uint8_t protocol)
1073 {
1074         struct near_adapter *adapter;
1075         struct near_tag *tag;
1076         struct sockaddr_nfc addr;
1077         int err, sock;
1078
1079         DBG("idx %d", idx);
1080
1081         adapter = g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(idx));
1082         if (adapter == NULL)
1083                 return -ENODEV;
1084
1085         if (adapter->tag_sock != -1)
1086                 return -EALREADY;
1087
1088         tag = g_hash_table_lookup(adapter->tags,
1089                                 GINT_TO_POINTER(target_idx));
1090         if (tag == NULL)
1091                 return -ENOLINK;
1092
1093         sock = socket(AF_NFC, SOCK_SEQPACKET, NFC_SOCKPROTO_RAW);
1094         if (sock == -1)
1095                 return sock;
1096
1097         addr.sa_family = AF_NFC;
1098         addr.dev_idx = idx;
1099         addr.target_idx = target_idx;
1100         addr.nfc_protocol = protocol;
1101
1102         err = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
1103         if (err) {
1104                 close(sock);
1105                 return err;
1106         }
1107
1108         adapter->tag_sock = sock;
1109         adapter->tag_link = tag;
1110
1111         if (adapter->channel == NULL)
1112                 adapter->channel = g_io_channel_unix_new(adapter->tag_sock);
1113
1114         g_io_channel_set_flags(adapter->channel, G_IO_FLAG_NONBLOCK, NULL);
1115         g_io_channel_set_close_on_unref(adapter->channel, TRUE);
1116
1117         if (adapter->watch == 0)
1118                 adapter->watch = g_io_add_watch(adapter->channel,
1119                                 G_IO_IN | G_IO_NVAL | G_IO_ERR | G_IO_HUP,
1120                                                 adapter_recv_event, adapter);
1121
1122         return 0;
1123 }
1124
1125 int near_adapter_disconnect(uint32_t idx)
1126 {
1127         struct near_adapter *adapter;
1128         uint32_t target_idx;
1129         uint16_t tag_type;
1130
1131         DBG("idx %d", idx);
1132
1133         adapter = g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(idx));
1134         if (adapter == NULL)
1135                 return -ENODEV;
1136
1137         DBG("link %p", adapter->tag_link);
1138
1139         if (adapter->tag_link == NULL)
1140                 return -ENOLINK;
1141
1142         tag_type = __near_tag_get_type(adapter->tag_link);
1143         target_idx = __near_tag_get_idx(adapter->tag_link);
1144
1145         DBG("tag type %d", tag_type);
1146
1147         __near_adapter_remove_target(adapter->idx, target_idx);
1148
1149         if (adapter->tag_sock == -1)
1150                 return -ENOLINK;
1151
1152         if (adapter->watch > 0) {
1153                 g_source_remove(adapter->watch);
1154                 adapter->watch = 0;
1155         }
1156
1157         adapter->channel = NULL;
1158         close(adapter->tag_sock);
1159         adapter->tag_sock = -1;
1160         adapter->tag_link = NULL;
1161
1162         return 0;
1163 }
1164
1165 int near_adapter_send(uint32_t idx, uint8_t *buf, size_t length,
1166                         near_recv cb, void *data)
1167 {
1168         struct near_adapter *adapter;
1169         struct near_adapter_ioreq *req = NULL;
1170         int err;
1171
1172         DBG("idx %d", idx);
1173
1174         adapter = g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(idx));
1175         if (adapter == NULL)
1176                 return -ENODEV;
1177
1178         if (adapter->tag_sock == -1 || adapter->tag_link == NULL)
1179                 return -ENOLINK;
1180
1181         if (cb != NULL && adapter->watch != 0) {
1182                 req = g_try_malloc0(sizeof(*req));
1183                 if (req == NULL)
1184                         return -ENOMEM;
1185
1186                 DBG("req %p cb %p data %p", req, cb, data);
1187
1188                 req->target_idx = __near_tag_get_idx(adapter->tag_link);
1189                 req->cb = cb;
1190                 req->data = data;
1191
1192                 adapter->ioreq_list =
1193                         g_list_append(adapter->ioreq_list, req);
1194         }
1195
1196         err = send(adapter->tag_sock, buf, length, 0);
1197         if (err < 0)
1198                 goto out_err;
1199
1200         return err;
1201
1202 out_err:
1203         if (req != NULL) {
1204                 GList *last = g_list_last(adapter->ioreq_list);
1205
1206                 g_free(req);
1207                 adapter->ioreq_list =
1208                                 g_list_delete_link(adapter->ioreq_list, last);
1209         }
1210
1211         return err;
1212 }
1213
1214 int __near_adapter_init(void)
1215 {
1216         DBG("");
1217
1218         connection = near_dbus_get_connection();
1219
1220         adapter_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1221                                                         NULL, free_adapter);
1222
1223         return 0;
1224 }
1225
1226 void __near_adapter_cleanup(void)
1227 {
1228         DBG("");
1229
1230         g_hash_table_destroy(adapter_hash);
1231         adapter_hash = NULL;
1232 }