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