a641e3a8f267d0874820e6d5f6d47eb30cf7820b
[platform/upstream/neard.git] / src / target.c
1 /*
2  *
3  *  neard - Near Field Communication manager
4  *
5  *  Copyright (C) 2011  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <errno.h>
29
30 #include <glib.h>
31
32 #include <gdbus.h>
33
34 #include "near.h"
35
36 struct near_target {
37         char *path;
38
39         uint32_t idx;
40         uint32_t adapter_idx;
41         uint32_t protocols;
42         enum near_target_type type;
43
44         uint16_t tag_type;
45         struct near_tag *tag;
46 };
47
48 static DBusConnection *connection = NULL;
49
50 static GHashTable *target_hash;
51
52 static void free_target(gpointer data)
53 {
54         struct near_target *target = data;
55
56         if (target->tag != NULL)
57                 __near_tag_free(target->tag);
58         g_free(target->path);
59         g_free(target);
60 }
61
62 const char *__near_target_get_path(struct near_target *target)
63
64 {
65         DBG("");
66
67         if (target == NULL)
68                 return NULL;
69
70         return target->path;
71 }
72
73 uint16_t __near_target_get_tag_type(struct near_target *target)
74 {
75         return target->tag_type;
76 }
77
78 uint32_t __near_target_get_idx(struct near_target *target)
79 {
80         return target->idx;
81 }
82
83 uint32_t __near_target_get_adapter_idx(struct near_target *target)
84 {
85         return target->adapter_idx;
86 }
87
88 uint32_t __near_target_get_protocols(struct near_target *target)
89 {
90         return target->protocols;
91 }
92
93 static void append_protocols(DBusMessageIter *iter, void *user_data)
94 {
95         struct near_target *target = user_data;
96         const char *str;
97
98         DBG("protocols 0x%x", target->protocols);
99
100         if (target->protocols & NFC_PROTO_FELICA_MASK) {
101                 str = "Felica";
102
103                 dbus_message_iter_append_basic(iter,
104                                 DBUS_TYPE_STRING, &str);
105         }
106
107         if (target->protocols & NFC_PROTO_MIFARE_MASK) {
108                 str = "MIFARE";
109
110                 dbus_message_iter_append_basic(iter,
111                                 DBUS_TYPE_STRING, &str);
112         }
113
114         if (target->protocols & NFC_PROTO_JEWEL_MASK) {
115                 str = "Jewel";
116
117                 dbus_message_iter_append_basic(iter,
118                                 DBUS_TYPE_STRING, &str);
119         }
120
121         if (target->protocols & NFC_PROTO_ISO14443_MASK) {
122                 str = "ISO-DEP";
123
124                 dbus_message_iter_append_basic(iter,
125                                 DBUS_TYPE_STRING, &str);
126         }
127
128         if (target->protocols & NFC_PROTO_NFC_DEP_MASK) {
129                 str = "NFC-DEP";
130
131                 dbus_message_iter_append_basic(iter,
132                                 DBUS_TYPE_STRING, &str);
133         }
134 }
135
136 static void append_tag_type(DBusMessageIter *iter, void *user_data)
137 {
138         struct near_target *target = user_data;
139         const char *str;
140
141         DBG("tag 0x%x", target->tag_type);
142
143         if (target->tag_type & NEAR_TAG_NFC_TYPE1) {
144                 str = "Type 1";
145
146                 dbus_message_iter_append_basic(iter,
147                                 DBUS_TYPE_STRING, &str);
148         }
149
150         if (target->tag_type & NEAR_TAG_NFC_TYPE2) {
151                 str = "Type 2";
152
153                 dbus_message_iter_append_basic(iter,
154                                 DBUS_TYPE_STRING, &str);
155         }
156
157         if (target->tag_type & NEAR_TAG_NFC_TYPE3) {
158                 str = "Type 3";
159
160                 dbus_message_iter_append_basic(iter,
161                                 DBUS_TYPE_STRING, &str);
162         }
163
164         if (target->tag_type & NEAR_TAG_NFC_TYPE4) {
165                 str = "Type 4";
166
167                 dbus_message_iter_append_basic(iter,
168                                 DBUS_TYPE_STRING, &str);
169         }
170
171         if (target->tag_type & NEAR_TAG_NFC_DEP) {
172                 str = "NFC-DEP";
173
174                 dbus_message_iter_append_basic(iter,
175                                 DBUS_TYPE_STRING, &str);
176         }
177 }
178
179 static const char *type2string(enum near_target_type type)
180 {
181         DBG("");
182
183         switch (type) {
184         case NEAR_TARGET_TYPE_TAG:
185                 return "Tag";
186         case NEAR_TARGET_TYPE_DEVICE:
187                 return "Device";
188         }
189
190         return NULL;
191 }
192
193 static DBusMessage *get_properties(DBusConnection *conn,
194                                         DBusMessage *msg, void *data)
195 {
196         struct near_target *target = data;
197         DBusMessage *reply;
198         DBusMessageIter array, dict;
199         const char *type;
200
201         DBG("conn %p", conn);
202
203         reply = dbus_message_new_method_return(msg);
204         if (reply == NULL)
205                 return NULL;
206
207         type = type2string(target->type);
208
209         dbus_message_iter_init_append(reply, &array);
210
211         near_dbus_dict_open(&array, &dict);
212
213         near_dbus_dict_append_basic(&dict, "Type",
214                                     DBUS_TYPE_STRING, &type);
215
216         if (target->type == NEAR_TARGET_TYPE_DEVICE)
217                 near_dbus_dict_append_array(&dict, "Protocols",
218                                 DBUS_TYPE_STRING, append_protocols, target);
219
220         if (target->type == NEAR_TARGET_TYPE_TAG)
221                 near_dbus_dict_append_array(&dict, "TagType",
222                                 DBUS_TYPE_STRING, append_tag_type, target);
223
224         near_dbus_dict_close(&array, &dict);
225
226         return reply;
227 }
228
229 static DBusMessage *set_property(DBusConnection *conn,
230                                         DBusMessage *msg, void *data)
231 {
232         DBG("conn %p", conn);
233
234         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
235 }
236
237 static GDBusMethodTable target_methods[] = {
238         { "GetProperties",     "",      "a{sv}", get_properties     },
239         { "SetProperty",       "sv",    "",      set_property       },
240         { },
241 };
242
243 static GDBusSignalTable target_signals[] = {
244         { "PropertyChanged",            "sv"    },
245         { }
246 };
247
248 #define NFC_TAG_A (NFC_PROTO_ISO14443_MASK | NFC_PROTO_NFC_DEP_MASK | \
249                                                 NFC_PROTO_MIFARE_MASK)
250 #define NFC_TAG_A_TYPE2      0x00
251 #define NFC_TAG_A_TYPE4      0x01
252 #define NFC_TAG_A_NFC_DEP    0x02
253 #define NFC_TAG_A_TYPE4_DEP  0x03
254
255 #define NFC_TAG_A_SEL_PROT(sel_res) (((sel_res) & 0x60) >> 5)
256
257 static void find_tag_type(struct near_target *target,
258                                 uint16_t sens_res, uint8_t sel_res)
259 {
260         DBG("protocols 0x%x sens_res 0x%x sel_res 0x%x", target->protocols,
261                                                         sens_res, sel_res);
262
263         if (target->type != NEAR_TARGET_TYPE_TAG) {
264                 target->tag_type = NEAR_TAG_NFC_UNKNOWN;
265                 return;
266         }
267
268         if (target->protocols & NFC_TAG_A) {
269                 uint8_t proto = NFC_TAG_A_SEL_PROT(sel_res);
270
271                 DBG("proto 0x%x", proto);
272
273                 switch(proto) {
274                 case NFC_TAG_A_TYPE2:
275                         target->tag_type = NEAR_TAG_NFC_TYPE2;
276                         break;
277                 case NFC_TAG_A_TYPE4:
278                         target->tag_type = NEAR_TAG_NFC_TYPE4;
279                         break;
280                 case NFC_TAG_A_NFC_DEP:
281                         target->tag_type = NEAR_TAG_NFC_DEP;
282                         break;
283                 case NFC_TAG_A_TYPE4_DEP:
284                         target->tag_type = NEAR_TAG_NFC_TYPE4 |
285                                                 NEAR_TAG_NFC_DEP;
286                         break;
287                 }
288
289         } else {
290                 target->tag_type = NEAR_TAG_NFC_UNKNOWN;
291         }
292
293         DBG("tag type 0x%x", target->tag_type);
294 }
295
296 int __near_target_add(uint32_t adapter_idx, uint32_t target_idx,
297                         uint32_t protocols, enum near_target_type type,
298                         uint16_t sens_res, uint8_t sel_res)
299 {
300         struct near_target *target;
301
302         if (g_hash_table_lookup(target_hash,
303                         GINT_TO_POINTER(target_idx)) != NULL)
304                 return -EEXIST;
305
306         target = g_try_malloc0(sizeof(struct near_target));
307         if (target == NULL)
308                 return -ENOMEM;
309
310         target->path = g_strdup_printf("%s/nfc%d/target%d", NFC_PATH,
311                                         adapter_idx, target_idx);
312         if (target->path == NULL) {
313                 g_free(target);
314                 return -ENOMEM;
315         }
316
317         target->idx = target_idx;
318         target->adapter_idx = adapter_idx;
319         target->protocols = protocols;
320         target->type = type;
321         find_tag_type(target, sens_res, sel_res);
322
323         g_hash_table_insert(target_hash, GINT_TO_POINTER(target_idx), target);
324
325         DBG("connection %p", connection);
326
327         g_dbus_register_interface(connection, target->path,
328                                         NFC_TARGET_INTERFACE,
329                                         target_methods, target_signals,
330                                                         NULL, target, NULL);
331
332         return __near_adapter_add_target(adapter_idx, target);
333 }
334
335 void __near_target_remove(uint32_t target_idx)
336 {
337         struct near_target *target;
338
339         target = g_hash_table_lookup(target_hash, GINT_TO_POINTER(target_idx));
340         if (target == NULL)
341                 return;
342
343         __near_adapter_remove_target(target->adapter_idx, target);
344
345         g_dbus_unregister_interface(connection, target->path,
346                                                 NFC_TARGET_INTERFACE);
347
348         g_hash_table_remove(target_hash, GINT_TO_POINTER(target_idx));
349 }
350
351 struct near_tag *near_target_get_tag(uint32_t target_idx, size_t data_length)
352 {
353         struct near_target *target;
354
355         target = g_hash_table_lookup(target_hash, GINT_TO_POINTER(target_idx));
356         if (target == NULL)
357                 return NULL;
358
359         if (target->tag != NULL)
360                 return target->tag;
361
362         target->tag = __near_tag_new(target->adapter_idx, target_idx, data_length);
363         if (target->tag == NULL)
364                 return NULL;
365
366         /* TODO reference the tag, or add tag reference count API */
367         return target->tag;
368 }
369
370 int __near_target_init(void)
371 {
372         DBG("");
373
374         connection = near_dbus_get_connection();
375
376         target_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
377                                                         NULL, free_target);
378
379         return 0;
380 }
381
382 void __near_target_cleanup(void)
383 {
384         DBG("");
385
386         g_hash_table_destroy(target_hash);
387         target_hash = NULL;
388 }