3 * neard - Near Field Communication manager
5 * Copyright (C) 2011 Intel Corporation. All rights reserved.
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.
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.
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
43 uint8_t nfcid[NFC_MAX_NFCID1_LEN];
52 DBusMessage *push_msg; /* Push pending message */
55 static DBusConnection *connection = NULL;
57 static GHashTable *device_hash;
59 static GSList *driver_list = NULL;
61 static void free_device(gpointer data)
63 struct near_device *device = data;
66 DBG("device %p", device);
68 for (list = device->records; list; list = list->next) {
69 struct near_ndef_record *record = list->data;
71 __near_ndef_record_free(record);
74 g_list_free(device->records);
80 struct near_device *near_device_get_device(uint32_t adapter_idx,
83 struct near_device *device;
88 path = g_strdup_printf("%s/nfc%d/device%d", NFC_PATH,
89 adapter_idx, target_idx);
93 device = g_hash_table_lookup(device_hash, path);
100 void __near_device_remove(struct near_device *device)
102 char *path = device->path;
104 DBG("path %s", device->path);
106 if (g_hash_table_lookup(device_hash, device->path) == NULL)
109 g_dbus_unregister_interface(connection, device->path,
110 NFC_DEVICE_INTERFACE);
112 g_hash_table_remove(device_hash, path);
115 const char *__near_device_get_path(struct near_device *device)
120 uint32_t __neard_device_get_idx(struct near_device *device)
122 return device->target_idx;
125 static void append_records(DBusMessageIter *iter, void *user_data)
127 struct near_device *device = user_data;
132 for (list = device->records; list; list = list->next) {
133 struct near_ndef_record *record = list->data;
136 path = __near_ndef_record_get_path(record);
140 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
145 static DBusMessage *get_properties(DBusConnection *conn,
146 DBusMessage *msg, void *data)
148 struct near_device *device = data;
150 DBusMessageIter array, dict;
152 DBG("conn %p", conn);
154 reply = dbus_message_new_method_return(msg);
158 dbus_message_iter_init_append(reply, &array);
160 near_dbus_dict_open(&array, &dict);
162 near_dbus_dict_append_array(&dict, "Records",
163 DBUS_TYPE_OBJECT_PATH, append_records, device);
165 near_dbus_dict_close(&array, &dict);
170 static DBusMessage *set_property(DBusConnection *conn,
171 DBusMessage *msg, void *data)
173 DBG("conn %p", conn);
175 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
178 static void push_cb(uint32_t adapter_idx, uint32_t target_idx, int status)
180 struct near_device *device;
181 DBusConnection *conn;
184 DBG("Push status %d", status);
186 conn = near_dbus_get_connection();
187 device = near_device_get_device(adapter_idx, target_idx);
189 if (conn == NULL || device == NULL)
193 reply = __near_error_failed(device->push_msg, EINVAL);
195 g_dbus_send_message(conn, reply);
197 g_dbus_send_reply(conn, device->push_msg, DBUS_TYPE_INVALID);
200 dbus_message_unref(device->push_msg);
201 device->push_msg = NULL;
204 static char *sn_from_message(DBusMessage *msg)
206 DBusMessageIter iter;
207 DBusMessageIter arr_iter;
211 dbus_message_iter_init(msg, &iter);
212 dbus_message_iter_recurse(&iter, &arr_iter);
214 while (dbus_message_iter_get_arg_type(&arr_iter) !=
216 const char *key, *value;
217 DBusMessageIter ent_iter;
218 DBusMessageIter var_iter;
220 dbus_message_iter_recurse(&arr_iter, &ent_iter);
221 dbus_message_iter_get_basic(&ent_iter, &key);
223 if (g_strcmp0(key, "Type") != 0) {
224 dbus_message_iter_next(&arr_iter);
228 dbus_message_iter_next(&ent_iter);
229 dbus_message_iter_recurse(&ent_iter, &var_iter);
231 switch (dbus_message_iter_get_arg_type(&var_iter)) {
232 case DBUS_TYPE_STRING:
233 dbus_message_iter_get_basic(&var_iter, &value);
235 if (g_strcmp0(value, "Text") == 0)
236 return NEAR_DEVICE_SN_SNEP;
237 else if (g_strcmp0(value, "URI") == 0)
238 return NEAR_DEVICE_SN_SNEP;
239 else if (g_strcmp0(value, "SmartPoster") == 0)
240 return NEAR_DEVICE_SN_SNEP;
241 else if (g_strcmp0(value, "Handover") == 0)
242 return NEAR_DEVICE_SN_HANDOVER;
249 dbus_message_iter_next(&arr_iter);
255 static DBusMessage *push_ndef(DBusConnection *conn,
256 DBusMessage *msg, void *data)
258 struct near_device *device = data;
259 struct near_ndef_message *ndef;
263 DBG("conn %p", conn);
265 if (device->push_msg)
266 return __near_error_in_progress(msg);
268 device->push_msg = dbus_message_ref(msg);
270 service_name = sn_from_message(msg);
271 if (service_name == NULL) {
276 ndef = __ndef_build_from_message(msg);
282 err = __near_device_push(device, ndef, service_name, push_cb);
292 dbus_message_unref(device->push_msg);
293 device->push_msg = NULL;
295 return __near_error_failed(msg, -err);
298 static const GDBusMethodTable device_methods[] = {
299 { GDBUS_METHOD("GetProperties",
300 NULL, GDBUS_ARGS({"properties", "a{sv}"}),
302 { GDBUS_METHOD("SetProperty",
303 GDBUS_ARGS({"name", "s"}, {"value", "v"}),
304 NULL, set_property) },
305 { GDBUS_ASYNC_METHOD("Push", GDBUS_ARGS({"attributes", "a{sv}"}),
310 static const GDBusSignalTable device_signals[] = {
311 { GDBUS_SIGNAL("PropertyChanged",
312 GDBUS_ARGS({"name", "s"}, {"value", "v"})) },
316 int near_device_add_data(uint32_t adapter_idx, uint32_t target_idx,
317 uint8_t *data, size_t data_length)
319 struct near_device *device;
321 device = near_device_get_device(adapter_idx, target_idx);
325 device->data_length = data_length;
326 device->data = g_try_malloc0(data_length);
327 if (device->data == NULL)
331 memcpy(device->data, data, data_length);
336 int near_device_add_records(struct near_device *device, GList *records,
337 near_device_io_cb cb, int status)
340 struct near_ndef_record *record;
343 DBG("records %p", records);
345 for (list = records; list; list = list->next) {
348 path = g_strdup_printf("%s/nfc%d/device%d/record%d",
349 NFC_PATH, device->adapter_idx,
350 device->target_idx, device->n_records);
355 __near_ndef_record_register(record, path);
358 device->records = g_list_append(device->records, record);
361 __near_agent_ndef_parse_records(device->records);
364 cb(device->adapter_idx, device->target_idx, status);
366 g_list_free(records);
371 struct near_device *__near_device_add(uint32_t adapter_idx, uint32_t target_idx,
372 uint8_t *nfcid, uint8_t nfcid_len)
374 struct near_device *device;
377 device = near_device_get_device(adapter_idx, target_idx);
381 device = g_try_malloc0(sizeof(struct near_device));
385 device->path = g_strdup_printf("%s/nfc%d/device%d", NFC_PATH,
386 adapter_idx, target_idx);
387 if (device->path == NULL) {
391 device->adapter_idx = adapter_idx;
392 device->target_idx = target_idx;
393 device->n_records = 0;
395 if (nfcid_len <= NFC_MAX_NFCID1_LEN && nfcid_len > 0) {
396 device->nfcid_len = nfcid_len;
397 memcpy(device->nfcid, nfcid, nfcid_len);
400 path = g_strdup(device->path);
406 g_hash_table_insert(device_hash, path, device);
408 DBG("connection %p", connection);
410 g_dbus_register_interface(connection, device->path,
411 NFC_DEVICE_INTERFACE,
412 device_methods, device_signals,
418 int __near_device_listen(struct near_device *device, near_device_io_cb cb)
424 for (list = driver_list; list; list = list->next) {
425 struct near_device_driver *driver = list->data;
427 return driver->listen(device->adapter_idx, cb);
433 int __near_device_push(struct near_device *device,
434 struct near_ndef_message *ndef, char *service_name,
435 near_device_io_cb cb)
441 if (__near_adapter_get_dep_state(device->adapter_idx) == FALSE) {
442 near_error("DEP link is not established");
446 for (list = driver_list; list; list = list->next) {
447 struct near_device_driver *driver = list->data;
449 return driver->push(device->adapter_idx, device->target_idx,
450 ndef, service_name, cb);
456 static gint cmp_prio(gconstpointer a, gconstpointer b)
458 const struct near_tag_driver *driver1 = a;
459 const struct near_tag_driver *driver2 = b;
461 return driver2->priority - driver1->priority;
464 int near_device_driver_register(struct near_device_driver *driver)
468 if (driver->listen == NULL)
471 driver_list = g_slist_insert_sorted(driver_list, driver, cmp_prio);
473 __near_adapter_listen(driver);
478 void near_device_driver_unregister(struct near_device_driver *driver)
482 driver_list = g_slist_remove(driver_list, driver);
485 int __near_device_init(void)
489 connection = near_dbus_get_connection();
491 device_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
492 g_free, free_device);
497 void __near_device_cleanup(void)
501 g_hash_table_destroy(device_hash);