Integrate neard post 0.6 changes - handover code
[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 static const GDBusMethodTable adapter_methods[] = {
503         { GDBUS_METHOD("GetProperties",
504                                 NULL, GDBUS_ARGS({"properties", "a{sv}"}),
505                                 get_properties) },
506         { GDBUS_METHOD("SetProperty",
507                                 GDBUS_ARGS({"name", "s"}, {"value", "v"}),
508                                 NULL, set_property) },
509         { GDBUS_METHOD("StartPollLoop", GDBUS_ARGS({"name", "s"}), NULL,
510                                                         start_poll_loop) },
511         { GDBUS_METHOD("StopPollLoop", NULL, NULL, stop_poll_loop) },
512         { },
513 };
514
515 static const GDBusSignalTable adapter_signals[] = {
516         { GDBUS_SIGNAL("PropertyChanged",
517                                 GDBUS_ARGS({"name", "s"}, {"value", "v"})) },
518         { GDBUS_SIGNAL("TagFound", GDBUS_ARGS({"address", "o"})) },
519         { GDBUS_SIGNAL("TagLost", GDBUS_ARGS({"address", "o"})) },
520         { }
521 };
522
523 struct near_adapter * __near_adapter_create(uint32_t idx,
524                 const char *name, uint32_t protocols, near_bool_t powered)
525 {
526         struct near_adapter *adapter;
527
528         adapter = g_try_malloc0(sizeof(struct near_adapter));
529         if (adapter == NULL)
530                 return NULL;
531
532         adapter->name = g_strdup(name);
533         if (adapter->name == NULL) {
534                 g_free(adapter);
535                 return NULL;
536         }
537         adapter->idx = idx;
538         adapter->protocols = protocols;
539         adapter->powered = powered;
540         adapter->constant_poll = near_setting_get_bool("ConstantPoll");
541         adapter->dep_up = FALSE;
542         adapter->tags = g_hash_table_new_full(g_direct_hash, g_direct_equal,
543                                                         NULL, free_tag);
544         adapter->tag_sock = -1;
545
546         adapter->devices = g_hash_table_new_full(g_direct_hash, g_direct_equal,
547                                                         NULL, free_device);
548         adapter->device_sock = -1;
549
550         adapter->path = g_strdup_printf("%s/nfc%d", NFC_PATH, idx);
551
552         return adapter;
553 }
554
555 void __near_adapter_destroy(struct near_adapter *adapter)
556 {
557         DBG("");
558
559         free_adapter(adapter);
560 }
561
562 const char *__near_adapter_get_path(struct near_adapter *adapter)
563 {
564         return adapter->path;
565 }
566
567 struct near_adapter *__near_adapter_get(uint32_t idx)
568 {
569         return g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(idx));
570 }
571
572 int __near_adapter_set_dep_state(uint32_t idx, near_bool_t dep)
573 {
574         struct near_adapter *adapter;
575
576         DBG("idx %d", idx);
577
578         adapter = g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(idx));
579         if (adapter == NULL)
580                 return -ENODEV;
581
582         adapter->dep_up = dep;
583
584         if (dep == FALSE && adapter->constant_poll == TRUE)
585                 adapter_start_poll(adapter);
586
587         if (dep == FALSE) {
588                 uint32_t target_idx;
589
590                 target_idx =  __neard_device_get_idx(adapter->device_link);
591                 __near_adapter_remove_target(idx, target_idx);
592         } else {
593                 __near_adapter_devices_changed(idx);
594         }
595
596         return 0;
597 }
598
599 near_bool_t __near_adapter_get_dep_state(uint32_t idx)
600 {
601         struct near_adapter *adapter;
602
603         DBG("idx %d", idx);
604
605         adapter = g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(idx));
606         if (adapter == NULL)
607                 return FALSE;
608
609         return adapter->dep_up;
610 }
611
612 int __near_adapter_add(struct near_adapter *adapter)
613 {
614         uint32_t idx = adapter->idx;
615
616         DBG("%s", adapter->path);
617
618         if (g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(idx)) != NULL)
619                 return -EEXIST;
620
621         g_hash_table_insert(adapter_hash, GINT_TO_POINTER(idx), adapter);
622
623         DBG("connection %p", connection);
624
625         g_dbus_register_interface(connection, adapter->path,
626                                         NFC_ADAPTER_INTERFACE,
627                                         adapter_methods, adapter_signals,
628                                         NULL, adapter, NULL);
629
630         return 0;
631 }
632
633 void __near_adapter_remove(struct near_adapter *adapter)
634 {
635         DBG("%s", adapter->path);
636
637         g_dbus_unregister_interface(connection, adapter->path,
638                                                 NFC_ADAPTER_INTERFACE);
639
640         g_hash_table_remove(adapter_hash, GINT_TO_POINTER(adapter->idx));
641 }
642
643 static void tag_read_cb(uint32_t adapter_idx, uint32_t target_idx, int status)
644 {
645         struct near_adapter *adapter;
646
647         DBG("status %d", status);
648
649         adapter = g_hash_table_lookup(adapter_hash,
650                                         GINT_TO_POINTER(adapter_idx));
651         if (adapter == NULL)
652                 return;
653
654         if (status < 0) {
655                 near_adapter_disconnect(adapter->idx);
656                 if (adapter->constant_poll == TRUE)
657                         adapter_start_poll(adapter);
658
659                 return;
660         }
661
662         __near_adapter_tags_changed(adapter_idx);
663
664         adapter->presence_timeout =
665                 g_timeout_add_seconds(CHECK_PRESENCE_PERIOD,
666                                         check_presence, adapter);
667 }
668
669 static void device_read_cb(uint32_t adapter_idx, uint32_t target_idx,
670                                                                 int status)
671 {
672         struct near_adapter *adapter;
673
674         DBG("status %d", status);
675
676         adapter = g_hash_table_lookup(adapter_hash,
677                                         GINT_TO_POINTER(adapter_idx));
678         if (adapter == NULL)
679                 return;
680
681         if (status < 0) {
682                 if (adapter->device_link != NULL) {
683                         __near_netlink_dep_link_down(adapter->idx);
684                         adapter->device_link = NULL;
685                 }
686
687                 if (adapter->constant_poll == TRUE)
688                         adapter_start_poll(adapter);
689
690                 return;
691         }
692 }
693
694 static int adapter_add_tag(struct near_adapter *adapter, uint32_t target_idx,
695                         uint32_t protocols,
696                         uint16_t sens_res, uint8_t sel_res,
697                         uint8_t *nfcid, uint8_t nfcid_len)
698 {
699         struct near_tag *tag;
700         uint32_t tag_type;
701         int err;
702
703         tag = __near_tag_add(adapter->idx, target_idx, protocols,
704                                 sens_res, sel_res,
705                                 nfcid, nfcid_len);
706         if (tag == NULL)
707                 return -ENODEV;
708
709         g_hash_table_insert(adapter->tags, GINT_TO_POINTER(target_idx), tag);
710
711         tag_type = __near_tag_get_type(tag);
712
713         err = near_adapter_connect(adapter->idx, target_idx, tag_type);
714         if (err < 0) {
715                 near_error("Could not connect");
716                 return err;
717         }
718
719         return __near_tag_read(tag, tag_read_cb);
720 }
721
722 static int adapter_add_device(struct near_adapter *adapter,
723                                 uint32_t target_idx,
724                                 uint8_t *nfcid, uint8_t nfcid_len)
725 {
726         struct near_device *device;
727         int err;
728
729         device = __near_device_add(adapter->idx, target_idx, nfcid, nfcid_len);
730         if (device == NULL)
731                 return -ENODEV;
732
733         g_hash_table_insert(adapter->devices, GINT_TO_POINTER(target_idx),
734                                                                 device);
735
736         /* For p2p, reading is listening for an incoming connection */
737         err = __near_device_listen(device, device_read_cb);
738         if (err < 0) {
739                 near_error("Could not read device");
740                 return err;
741         }
742
743         adapter->device_link = device;
744
745         if (adapter->dep_up == TRUE)
746                 return 0;
747
748         err = __near_netlink_dep_link_up(adapter->idx, target_idx,
749                                         NFC_COMM_ACTIVE, NFC_RF_INITIATOR);
750
751         if (err < 0)
752                 adapter->device_link = NULL;
753
754         return err;
755 }
756
757 int __near_adapter_add_target(uint32_t idx, uint32_t target_idx,
758                         uint32_t protocols, uint16_t sens_res, uint8_t sel_res,
759                         uint8_t *nfcid, uint8_t nfcid_len)
760 {
761         struct near_adapter *adapter;
762
763         DBG("idx %d", idx);
764
765         adapter = g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(idx));
766         if (adapter == NULL)
767                 return -ENODEV;
768
769         adapter->polling = FALSE;
770         polling_changed(adapter);
771
772         if (protocols & NFC_PROTO_NFC_DEP_MASK)
773                 return adapter_add_device(adapter, target_idx,
774                                                 nfcid, nfcid_len);
775         else
776                 return adapter_add_tag(adapter, target_idx, protocols,
777                                         sens_res, sel_res, nfcid, nfcid_len);
778 }
779
780 int __near_adapter_remove_target(uint32_t idx, uint32_t target_idx)
781 {
782         struct near_adapter *adapter;
783
784         DBG("idx %d", idx);
785
786         adapter = g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(idx));
787         if (adapter == NULL)
788                 return -ENODEV;
789
790         if (g_hash_table_remove(adapter->tags,
791                         GINT_TO_POINTER(target_idx)) == TRUE) {
792                 __near_adapter_tags_changed(idx);
793
794                 return 0;
795         }
796
797         if (g_hash_table_remove(adapter->devices,
798                         GINT_TO_POINTER(target_idx)) == TRUE) {
799                 __near_adapter_devices_changed(idx);
800
801                 return 0;
802         }
803
804         return 0;
805 }
806
807 int __near_adapter_add_device(uint32_t idx, uint8_t *nfcid, uint8_t nfcid_len)
808 {
809         struct near_adapter *adapter;
810
811         DBG("idx %d", idx);
812
813         adapter = g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(idx));
814         if (adapter == NULL)
815                 return -ENODEV;
816
817         adapter->polling = FALSE;
818         adapter->dep_up = TRUE;
819         polling_changed(adapter);
820
821         __near_adapter_devices_changed(idx);
822
823         return adapter_add_device(adapter, 0, nfcid, nfcid_len);
824 }
825
826 int __near_adapter_remove_device(uint32_t idx)
827 {
828         struct near_adapter *adapter;
829         uint32_t device_idx = 0;
830
831         DBG("idx %d", idx);
832
833         adapter = g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(idx));
834         if (adapter == NULL)
835                 return -ENODEV;
836
837         if (g_hash_table_remove(adapter->devices,
838                         GINT_TO_POINTER(device_idx)) == FALSE)
839                 return 0;
840
841         __near_adapter_devices_changed(idx);
842
843         adapter->dep_up = FALSE;
844
845         if (adapter->constant_poll == TRUE)
846                 adapter_start_poll(adapter);
847
848         return 0;
849 }
850
851 static void adapter_flush_rx(struct near_adapter *adapter, int error)
852 {
853         GList *list;
854
855         for (list = adapter->ioreq_list; list; list = list->next) {
856                 struct near_adapter_ioreq *req = list->data;
857
858                 if (req == NULL)
859                         continue;
860
861                 req->cb(NULL, error, req->data);
862                 g_free(req);
863         }
864
865         g_list_free(adapter->ioreq_list);
866         adapter->ioreq_list = NULL;
867 }
868
869 static gboolean execute_recv_cb(gpointer user_data)
870 {
871         struct near_adapter_ioreq *req = user_data;
872
873         DBG("data %p", req->data);
874
875         req->cb(req->buf, req->len, req->data);
876
877         g_free(req);
878
879         return FALSE;
880 }
881
882 static gboolean adapter_recv_event(GIOChannel *channel, GIOCondition condition,
883                                                         gpointer user_data)
884 {
885         struct near_adapter *adapter = user_data;
886         struct near_adapter_ioreq *req;
887         GList *first;
888         int sk;
889
890         DBG("condition 0x%x", condition);
891
892         if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
893                 near_error("Error while reading NFC bytes");
894
895                 adapter_flush_rx(adapter, -EIO);
896
897                 near_adapter_disconnect(adapter->idx);
898
899                 adapter->presence_timeout =
900                         g_timeout_add_seconds(2 * CHECK_PRESENCE_PERIOD,
901                                               check_presence, adapter);
902                 return FALSE;
903         }
904
905         sk = g_io_channel_unix_get_fd(channel);
906         first = g_list_first(adapter->ioreq_list);
907         if (first == NULL)
908                 return TRUE;
909
910         req = first->data;
911         req->len = recv(sk, req->buf, sizeof(req->buf), 0);
912
913         adapter->ioreq_list = g_list_remove(adapter->ioreq_list, req);
914
915         g_idle_add(execute_recv_cb, req);
916
917         return TRUE;
918 }
919
920 int near_adapter_connect(uint32_t idx, uint32_t target_idx, uint8_t protocol)
921 {
922         struct near_adapter *adapter;
923         struct near_tag *tag;
924         struct sockaddr_nfc addr;
925         int err, sock;
926
927         DBG("idx %d", idx);
928
929         adapter = g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(idx));
930         if (adapter == NULL)
931                 return -ENODEV;
932
933         if (adapter->tag_sock != -1)
934                 return -EALREADY;
935
936         tag = g_hash_table_lookup(adapter->tags,
937                                 GINT_TO_POINTER(target_idx));
938         if (tag == NULL)
939                 return -ENOLINK;
940
941         sock = socket(AF_NFC, SOCK_SEQPACKET, NFC_SOCKPROTO_RAW);
942         if (sock == -1)
943                 return sock;
944
945         addr.sa_family = AF_NFC;
946         addr.dev_idx = idx;
947         addr.target_idx = target_idx;
948         addr.nfc_protocol = protocol;
949
950         err = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
951         if (err) {
952                 close(sock);
953                 return err;
954         }
955
956         adapter->tag_sock = sock;
957         adapter->tag_link = tag;
958
959         if (adapter->channel == NULL)
960                 adapter->channel = g_io_channel_unix_new(adapter->tag_sock);
961
962         g_io_channel_set_flags(adapter->channel, G_IO_FLAG_NONBLOCK, NULL);
963         g_io_channel_set_close_on_unref(adapter->channel, TRUE);
964
965         if (adapter->watch == 0)
966                 adapter->watch = g_io_add_watch(adapter->channel,
967                                 G_IO_IN | G_IO_NVAL | G_IO_ERR | G_IO_HUP,
968                                                 adapter_recv_event, adapter);
969
970         return 0;
971 }
972
973 int near_adapter_disconnect(uint32_t idx)
974 {
975         struct near_adapter *adapter;
976         uint32_t target_idx;
977         uint16_t tag_type;
978
979         DBG("idx %d", idx);
980
981         adapter = g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(idx));
982         if (adapter == NULL)
983                 return -ENODEV;
984
985         DBG("link %p", adapter->tag_link);
986
987         if (adapter->tag_link == NULL)
988                 return -ENOLINK;
989
990         tag_type = __near_tag_get_type(adapter->tag_link);
991         target_idx = near_tag_get_target_idx(adapter->tag_link);
992
993         DBG("tag type %d", tag_type);
994
995         __near_adapter_remove_target(adapter->idx, target_idx);
996
997         if (adapter->tag_sock == -1)
998                 return -ENOLINK;
999
1000         if (adapter->watch > 0) {
1001                 g_source_remove(adapter->watch);
1002                 adapter->watch = 0;
1003         }
1004
1005         g_io_channel_unref(adapter->channel);
1006         adapter->channel = NULL;
1007         adapter->tag_sock = -1;
1008         adapter->tag_link = NULL;
1009
1010         return 0;
1011 }
1012
1013 int near_adapter_send(uint32_t idx, uint8_t *buf, size_t length,
1014                         near_recv cb, void *data)
1015 {
1016         struct near_adapter *adapter;
1017         struct near_adapter_ioreq *req = NULL;
1018         int err;
1019
1020         DBG("idx %d", idx);
1021
1022         adapter = g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(idx));
1023         if (adapter == NULL)
1024                 return -ENODEV;
1025
1026         if (adapter->tag_sock == -1 || adapter->tag_link == NULL)
1027                 return -ENOLINK;
1028
1029         if (cb != NULL && adapter->watch != 0) {
1030                 req = g_try_malloc0(sizeof(*req));
1031                 if (req == NULL)
1032                         return -ENOMEM;
1033
1034                 DBG("req %p cb %p data %p", req, cb, data);
1035
1036                 req->target_idx = near_tag_get_target_idx(adapter->tag_link);
1037                 req->cb = cb;
1038                 req->data = data;
1039
1040                 adapter->ioreq_list =
1041                         g_list_append(adapter->ioreq_list, req);
1042         }
1043
1044         err = send(adapter->tag_sock, buf, length, 0);
1045         if (err < 0)
1046                 goto out_err;
1047
1048         return err;
1049
1050 out_err:
1051         if (req != NULL) {
1052                 GList *last = g_list_last(adapter->ioreq_list);
1053
1054                 g_free(req);
1055                 adapter->ioreq_list =
1056                                 g_list_delete_link(adapter->ioreq_list, last);
1057         }
1058
1059         return err;
1060 }
1061
1062 static void adapter_listen(gpointer key, gpointer value, gpointer user_data)
1063 {
1064         struct near_adapter *adapter = value;
1065         struct near_device_driver *driver = user_data;
1066
1067         DBG("%s", adapter->path);
1068
1069         if (adapter->path == NULL)
1070                 return;
1071
1072         driver->listen(adapter->idx, device_read_cb);
1073 }
1074
1075 void __near_adapter_listen(struct near_device_driver *driver)
1076 {
1077         g_hash_table_foreach(adapter_hash, adapter_listen, driver);
1078 }
1079
1080 int __near_adapter_init(void)
1081 {
1082         DBG("");
1083
1084         connection = near_dbus_get_connection();
1085
1086         adapter_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1087                                                         NULL, free_adapter);
1088
1089         return 0;
1090 }
1091
1092 void __near_adapter_cleanup(void)
1093 {
1094         DBG("");
1095
1096         g_hash_table_destroy(adapter_hash);
1097         adapter_hash = NULL;
1098 }