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