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;
65 DBG("device %p", device);
67 near_ndef_records_free(device->records);
74 struct near_device *near_device_get_device(uint32_t adapter_idx,
77 struct near_device *device;
82 path = g_strdup_printf("%s/nfc%d/device%d", NFC_PATH,
83 adapter_idx, target_idx);
87 device = g_hash_table_lookup(device_hash, path);
94 void __near_device_remove(struct near_device *device)
96 char *path = device->path;
98 DBG("path %s", device->path);
100 if (g_hash_table_lookup(device_hash, device->path) == NULL)
103 g_dbus_unregister_interface(connection, device->path,
104 NFC_DEVICE_INTERFACE);
106 g_hash_table_remove(device_hash, path);
109 const char *__near_device_get_path(struct near_device *device)
114 uint32_t __neard_device_get_idx(struct near_device *device)
116 return device->target_idx;
119 static void append_records(DBusMessageIter *iter, void *user_data)
121 struct near_device *device = user_data;
126 for (list = device->records; list; list = list->next) {
127 struct near_ndef_record *record = list->data;
130 path = __near_ndef_record_get_path(record);
134 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
139 static DBusMessage *get_properties(DBusConnection *conn,
140 DBusMessage *msg, void *data)
142 struct near_device *device = data;
144 DBusMessageIter array, dict;
146 DBG("conn %p", conn);
148 reply = dbus_message_new_method_return(msg);
152 dbus_message_iter_init_append(reply, &array);
154 near_dbus_dict_open(&array, &dict);
156 near_dbus_dict_append_array(&dict, "Records",
157 DBUS_TYPE_OBJECT_PATH, append_records, device);
159 near_dbus_dict_close(&array, &dict);
164 static DBusMessage *set_property(DBusConnection *conn,
165 DBusMessage *msg, void *data)
167 DBG("conn %p", conn);
169 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
172 static void push_cb(uint32_t adapter_idx, uint32_t target_idx, int status)
174 struct near_device *device;
175 DBusConnection *conn;
178 DBG("Push status %d", status);
180 conn = near_dbus_get_connection();
181 device = near_device_get_device(adapter_idx, target_idx);
183 if (conn == NULL || device == NULL)
187 reply = __near_error_failed(device->push_msg, EINVAL);
189 g_dbus_send_message(conn, reply);
191 g_dbus_send_reply(conn, device->push_msg, DBUS_TYPE_INVALID);
194 dbus_message_unref(device->push_msg);
195 device->push_msg = NULL;
198 static char *sn_from_message(DBusMessage *msg)
200 DBusMessageIter iter;
201 DBusMessageIter arr_iter;
205 dbus_message_iter_init(msg, &iter);
206 dbus_message_iter_recurse(&iter, &arr_iter);
208 while (dbus_message_iter_get_arg_type(&arr_iter) !=
210 const char *key, *value;
211 DBusMessageIter ent_iter;
212 DBusMessageIter var_iter;
214 dbus_message_iter_recurse(&arr_iter, &ent_iter);
215 dbus_message_iter_get_basic(&ent_iter, &key);
217 if (g_strcmp0(key, "Type") != 0) {
218 dbus_message_iter_next(&arr_iter);
222 dbus_message_iter_next(&ent_iter);
223 dbus_message_iter_recurse(&ent_iter, &var_iter);
225 switch (dbus_message_iter_get_arg_type(&var_iter)) {
226 case DBUS_TYPE_STRING:
227 dbus_message_iter_get_basic(&var_iter, &value);
229 if (g_strcmp0(value, "Text") == 0)
230 return NEAR_DEVICE_SN_SNEP;
231 else if (g_strcmp0(value, "URI") == 0)
232 return NEAR_DEVICE_SN_SNEP;
233 else if (g_strcmp0(value, "SmartPoster") == 0)
234 return NEAR_DEVICE_SN_SNEP;
235 else if (g_strcmp0(value, "Handover") == 0)
236 return NEAR_DEVICE_SN_HANDOVER;
243 dbus_message_iter_next(&arr_iter);
249 static DBusMessage *push_ndef(DBusConnection *conn,
250 DBusMessage *msg, void *data)
252 struct near_device *device = data;
253 struct near_ndef_message *ndef;
257 DBG("conn %p", conn);
259 if (device->push_msg)
260 return __near_error_in_progress(msg);
262 device->push_msg = dbus_message_ref(msg);
264 service_name = sn_from_message(msg);
265 if (service_name == NULL) {
270 ndef = __ndef_build_from_message(msg);
276 err = __near_device_push(device, ndef, service_name, push_cb);
286 dbus_message_unref(device->push_msg);
287 device->push_msg = NULL;
289 return __near_error_failed(msg, -err);
292 static const GDBusMethodTable device_methods[] = {
293 { GDBUS_METHOD("GetProperties",
294 NULL, GDBUS_ARGS({"properties", "a{sv}"}),
296 { GDBUS_METHOD("SetProperty",
297 GDBUS_ARGS({"name", "s"}, {"value", "v"}),
298 NULL, set_property) },
299 { GDBUS_ASYNC_METHOD("Push", GDBUS_ARGS({"attributes", "a{sv}"}),
304 static const GDBusSignalTable device_signals[] = {
305 { GDBUS_SIGNAL("PropertyChanged",
306 GDBUS_ARGS({"name", "s"}, {"value", "v"})) },
310 int near_device_add_data(uint32_t adapter_idx, uint32_t target_idx,
311 uint8_t *data, size_t data_length)
313 struct near_device *device;
315 device = near_device_get_device(adapter_idx, target_idx);
319 device->data_length = data_length;
320 device->data = g_try_malloc0(data_length);
321 if (device->data == NULL)
325 memcpy(device->data, data, data_length);
330 int near_device_add_records(struct near_device *device, GList *records,
331 near_device_io_cb cb, int status)
334 struct near_ndef_record *record;
337 DBG("records %p", records);
339 near_ndef_records_free(device->records);
340 device->records = NULL;
342 for (list = records; list; list = list->next) {
345 path = g_strdup_printf("%s/nfc%d/device%d/record%d",
346 NFC_PATH, device->adapter_idx,
347 device->target_idx, device->n_records);
352 __near_ndef_record_register(record, path);
355 device->records = g_list_append(device->records, record);
358 __near_agent_ndef_parse_records(device->records);
360 near_dbus_property_changed_array(device->path,
361 NFC_DEVICE_INTERFACE, "Records",
362 DBUS_TYPE_OBJECT_PATH, append_records,
366 cb(device->adapter_idx, device->target_idx, status);
368 g_list_free(records);
373 struct near_device *__near_device_add(uint32_t adapter_idx, uint32_t target_idx,
374 uint8_t *nfcid, uint8_t nfcid_len)
376 struct near_device *device;
379 device = near_device_get_device(adapter_idx, target_idx);
383 device = g_try_malloc0(sizeof(struct near_device));
387 device->path = g_strdup_printf("%s/nfc%d/device%d", NFC_PATH,
388 adapter_idx, target_idx);
389 if (device->path == NULL) {
393 device->adapter_idx = adapter_idx;
394 device->target_idx = target_idx;
395 device->n_records = 0;
397 if (nfcid_len <= NFC_MAX_NFCID1_LEN && nfcid_len > 0) {
398 device->nfcid_len = nfcid_len;
399 memcpy(device->nfcid, nfcid, nfcid_len);
402 path = g_strdup(device->path);
408 g_hash_table_insert(device_hash, path, device);
410 DBG("connection %p", connection);
412 g_dbus_register_interface(connection, device->path,
413 NFC_DEVICE_INTERFACE,
414 device_methods, device_signals,
420 int __near_device_listen(struct near_device *device, near_device_io_cb cb)
426 for (list = driver_list; list; list = list->next) {
427 struct near_device_driver *driver = list->data;
429 return driver->listen(device->adapter_idx, cb);
435 int __near_device_push(struct near_device *device,
436 struct near_ndef_message *ndef, char *service_name,
437 near_device_io_cb cb)
443 if (__near_adapter_get_dep_state(device->adapter_idx) == FALSE) {
444 near_error("DEP link is not established");
448 for (list = driver_list; list; list = list->next) {
449 struct near_device_driver *driver = list->data;
451 return driver->push(device->adapter_idx, device->target_idx,
452 ndef, service_name, cb);
458 static gint cmp_prio(gconstpointer a, gconstpointer b)
460 const struct near_tag_driver *driver1 = a;
461 const struct near_tag_driver *driver2 = b;
463 return driver2->priority - driver1->priority;
466 int near_device_driver_register(struct near_device_driver *driver)
470 if (driver->listen == NULL)
473 driver_list = g_slist_insert_sorted(driver_list, driver, cmp_prio);
475 __near_adapter_listen(driver);
480 void near_device_driver_unregister(struct near_device_driver *driver)
484 driver_list = g_slist_remove(driver_list, driver);
487 int __near_device_init(void)
491 connection = near_dbus_get_connection();
493 device_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
494 g_free, free_device);
499 void __near_device_cleanup(void)
503 g_hash_table_destroy(device_hash);