diff --git a/Makefile.am b/Makefile.am
index 97ab08e..ab6f8b7 100644
--- a/Makefile.am
+++ b/Makefile.am
attrib_sources = attrib/att.h attrib/att-database.h attrib/att.c \
attrib/gatt.h attrib/gatt.c \
- attrib/gattrib.h attrib/gattrib.c attrib/client.h \
- attrib/client.c attrib/gatt-service.h attrib/gatt-service.c
+ attrib/gattrib.h attrib/gattrib.c \
+ attrib/gatt-service.h attrib/gatt-service.c
gdbus_sources = gdbus/gdbus.h gdbus/mainloop.c gdbus/watch.c \
gdbus/object.c gdbus/client.c gdbus/polkit.c
diff --git a/attrib/client.c b/attrib/client.c
deleted file mode 100644
index 138c0ef..0000000
--- a/attrib/client.c
+++ /dev/null
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2010 Nokia Corporation
- * Copyright (C) 2010 Marcel Holtmann <marcel@holtmann.org>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <glib.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/uuid.h>
-
-#include <gdbus/gdbus.h>
-#include <btio/btio.h>
-#include "adapter.h"
-#include "device.h"
-#include "log.h"
-#include "error.h"
-#include "dbus-common.h"
-#include "storage.h"
-
-#include "att.h"
-#include "gattrib.h"
-#include "attio.h"
-#include "gatt.h"
-#include "client.h"
-
-#define CHAR_INTERFACE "org.bluez.Characteristic"
-
-struct format {
- guint8 format;
- guint8 exponent;
- guint16 unit;
- guint8 namespace;
- guint16 desc;
-} __attribute__ ((packed));
-
-struct query {
- DBusMessage *msg;
- GSList *list;
-};
-
-struct gatt_service {
- struct btd_device *dev;
- struct gatt_primary *prim;
- GAttrib *attrib;
- guint attioid;
- int psm;
- char *path;
- GSList *chars;
- GSList *offline_chars;
- GSList *watchers;
- struct query *query;
-};
-
-struct characteristic {
- struct gatt_service *gatt;
- char *path;
- uint16_t handle;
- uint16_t end;
- uint8_t perm;
- char type[MAX_LEN_UUID_STR + 1];
- char *name;
- char *desc;
- struct format *format;
- uint8_t *value;
- size_t vlen;
-};
-
-struct query_data {
- struct gatt_service *gatt;
- struct characteristic *chr;
- uint16_t handle;
-};
-
-struct watcher {
- guint id;
- char *name;
- char *path;
- struct gatt_service *gatt;
-};
-
-static const struct {
- const char *uuid;
- const char *name;
-} char_names[] = {
- { "00002a43-0000-1000-8000-00805f9b34fb", "Alert Category ID" },
- { "00002a42-0000-1000-8000-00805f9b34fb", "Alert Category ID Bit Mask" },
- { "00002a06-0000-1000-8000-00805f9b34fb", "Alert Level" },
- { "00002a44-0000-1000-8000-00805f9b34fb", "Alert Notification Control Point" },
- { "00002a3f-0000-1000-8000-00805f9b34fb", "Alert Status" },
- { "00002a01-0000-1000-8000-00805f9b34fb", "Appearance" },
- { "00002a19-0000-1000-8000-00805f9b34fb", "Battery Level" },
- { "00002a1b-0000-1000-8000-00805f9b34fb", "Battery Level State" },
- { "00002a49-0000-1000-8000-00805f9b34fb", "Blood Pressure Feature" },
- { "00002a35-0000-1000-8000-00805f9b34fb", "Blood Pressure Measurement" },
- { "00002a38-0000-1000-8000-00805f9b34fb", "Body Sensor Location" },
- { "00002a22-0000-1000-8000-00805f9b34fb", "Boot Keyboard Input Report" },
- { "00002a32-0000-1000-8000-00805f9b34fb", "Boot Keyboard Output Report" },
- { "00002a33-0000-1000-8000-00805f9b34fb", "Boot Mouse Input Report" },
- { "00002a5c-0000-1000-8000-00805f9b34fb", "CSC Feature" },
- { "00002a5b-0000-1000-8000-00805f9b34fb", "CSC Measurement" },
- { "00002a2b-0000-1000-8000-00805f9b34fb", "Current Time" },
- { "00002a08-0000-1000-8000-00805f9b34fb", "Date Time" },
- { "00002a0a-0000-1000-8000-00805f9b34fb", "Day Date Time" },
- { "00002a09-0000-1000-8000-00805f9b34fb", "Day of Week" },
- { "00002a00-0000-1000-8000-00805f9b34fb", "Device Name" },
- { "00002a0d-0000-1000-8000-00805f9b34fb", "DST Offset" },
- { "00002a0c-0000-1000-8000-00805f9b34fb", "Exact Time 256" },
- { "00002a26-0000-1000-8000-00805f9b34fb", "Firmware Revision String" },
- { "00002a51-0000-1000-8000-00805f9b34fb", "Glucose Feature" },
- { "00002a18-0000-1000-8000-00805f9b34fb", "Glucose Measurement" },
- { "00002a34-0000-1000-8000-00805f9b34fb", "Glucose Measurement Context" },
- { "00002a27-0000-1000-8000-00805f9b34fb", "Hardware Revision String" },
- { "00002a39-0000-1000-8000-00805f9b34fb", "Heart Rate Control Point" },
- { "00002a37-0000-1000-8000-00805f9b34fb", "Heart Rate Measurement" },
- { "00002a4c-0000-1000-8000-00805f9b34fb", "HID Control Point" },
- { "00002a4a-0000-1000-8000-00805f9b34fb", "HID Information" },
- { "00002a2a-0000-1000-8000-00805f9b34fb", "IEEE 11073-20601 Regulatory" },
- { "00002a36-0000-1000-8000-00805f9b34fb", "Intermediate Cuff Pressure" },
- { "00002a1e-0000-1000-8000-00805f9b34fb", "Intermediate Temperature" },
- { "00002a0f-0000-1000-8000-00805f9b34fb", "Local Time Information" },
- { "00002a29-0000-1000-8000-00805f9b34fb", "Manufacturer Name String" },
- { "00002a21-0000-1000-8000-00805f9b34fb", "Measurement Interval" },
- { "00002a24-0000-1000-8000-00805f9b34fb", "Model Number String" },
- { "00002a46-0000-1000-8000-00805f9b34fb", "New Alert" },
- { "00002a04-0000-1000-8000-00805f9b34fb", "Peripheral Preferred Connection Parameters" },
- { "00002a02-0000-1000-8000-00805f9b34fb", "Peripheral Privacy Flag" },
- { "00002a50-0000-1000-8000-00805f9b34fb", "PnP ID" },
- { "00002a4e-0000-1000-8000-00805f9b34fb", "Protocol Mode" },
- { "00002a03-0000-1000-8000-00805f9b34fb", "Reconnection Address" },
- { "00002a52-0000-1000-8000-00805f9b34fb", "Record Access Control Point" },
- { "00002a14-0000-1000-8000-00805f9b34fb", "Reference Time Information" },
- { "00002a4d-0000-1000-8000-00805f9b34fb", "Report" },
- { "00002a4b-0000-1000-8000-00805f9b34fb", "Report Map" },
- { "00002a40-0000-1000-8000-00805f9b34fb", "Ringer Control Point" },
- { "00002a41-0000-1000-8000-00805f9b34fb", "Ringer Setting" },
- { "00002a54-0000-1000-8000-00805f9b34fb", "RSC Feature" },
- { "00002a53-0000-1000-8000-00805f9b34fb", "RSC Measurement" },
- { "00002a55-0000-1000-8000-00805f9b34fb", "SC Control Point" },
- { "00002a4f-0000-1000-8000-00805f9b34fb", "Scan Interval Window" },
- { "00002a31-0000-1000-8000-00805f9b34fb", "Scan Refresh" },
- { "00002a5d-0000-1000-8000-00805f9b34fb", "Sensor Location" },
- { "00002a25-0000-1000-8000-00805f9b34fb", "Serial Number String" },
- { "00002a05-0000-1000-8000-00805f9b34fb", "Service Changed" },
- { "00002a28-0000-1000-8000-00805f9b34fb", "Software Revision String" },
- { "00002a47-0000-1000-8000-00805f9b34fb", "Supported New Alert Category" },
- { "00002a48-0000-1000-8000-00805f9b34fb", "Supported Unread Alert Category" },
- { "00002a23-0000-1000-8000-00805f9b34fb", "System ID" },
- { "00002a1c-0000-1000-8000-00805f9b34fb", "Temperature Measurement" },
- { "00002a1d-0000-1000-8000-00805f9b34fb", "Temperature Type" },
- { "00002a12-0000-1000-8000-00805f9b34fb", "Time Accuracy" },
- { "00002a13-0000-1000-8000-00805f9b34fb", "Time Source" },
- { "00002a16-0000-1000-8000-00805f9b34fb", "Time Update Control Point" },
- { "00002a17-0000-1000-8000-00805f9b34fb", "Time Update State" },
- { "00002a11-0000-1000-8000-00805f9b34fb", "Time with DST" },
- { "00002a0e-0000-1000-8000-00805f9b34fb", "Time Zone" },
- { "00002a07-0000-1000-8000-00805f9b34fb", "Tx Power Level" },
- { "00002a45-0000-1000-8000-00805f9b34fb", "Unread Alert Status" },
-};
-
-static GSList *gatt_services = NULL;
-
-static const char *get_char_name(const char *uuid)
-{
- unsigned int i;
-
- for (i = 0; i < G_N_ELEMENTS(char_names); i++) {
- if (bt_uuid_strcmp(char_names[i].uuid, uuid) == 0)
- return char_names[i].name;
- }
-
- return NULL;
-}
-
-static void characteristic_free(void *user_data)
-{
- struct characteristic *chr = user_data;
-
- g_free(chr->path);
- g_free(chr->desc);
- g_free(chr->format);
- g_free(chr->value);
- g_free(chr->name);
- g_free(chr);
-}
-
-static void watcher_free(void *user_data)
-{
- struct watcher *watcher = user_data;
-
- g_free(watcher->path);
- g_free(watcher->name);
- g_free(watcher);
-}
-
-static void gatt_service_free(struct gatt_service *gatt)
-{
- g_slist_free_full(gatt->watchers, watcher_free);
- g_slist_free_full(gatt->chars, characteristic_free);
- g_slist_free(gatt->offline_chars);
- g_free(gatt->path);
- btd_device_unref(gatt->dev);
- g_free(gatt);
-}
-
-static void remove_attio(struct gatt_service *gatt)
-{
- if (gatt->offline_chars || gatt->watchers || gatt->query)
- return;
-
- if (gatt->attioid) {
- btd_device_remove_attio_callback(gatt->dev, gatt->attioid);
- gatt->attioid = 0;
- }
-
- if (gatt->attrib) {
- g_attrib_unref(gatt->attrib);
- gatt->attrib = NULL;
- }
-}
-
-static int characteristic_handle_cmp(gconstpointer a, gconstpointer b)
-{
- const struct characteristic *chr = a;
- uint16_t handle = GPOINTER_TO_UINT(b);
-
- return chr->handle - handle;
-}
-
-static int watcher_cmp(gconstpointer a, gconstpointer b)
-{
- const struct watcher *watcher = a;
- const struct watcher *match = b;
- int ret;
-
- ret = g_strcmp0(watcher->name, match->name);
- if (ret != 0)
- return ret;
-
- return g_strcmp0(watcher->path, match->path);
-}
-
-static void append_char_dict(DBusMessageIter *iter, struct characteristic *chr)
-{
- DBusMessageIter dict;
- const char *name;
- char *uuid;
-
- dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
- DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
- DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
- DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
-
- uuid = g_strdup(chr->type);
- dict_append_entry(&dict, "UUID", DBUS_TYPE_STRING, &uuid);
- g_free(uuid);
-
- name = get_char_name(chr->type);
- if (name)
- dict_append_entry(&dict, "Name", DBUS_TYPE_STRING, &name);
-
- if (chr->desc)
- dict_append_entry(&dict, "Description", DBUS_TYPE_STRING,
- &chr->desc);
-
- if (chr->value)
- dict_append_array(&dict, "Value", DBUS_TYPE_BYTE, &chr->value,
- chr->vlen);
-
- /* FIXME: Missing Format, Value and Representation */
-
- dbus_message_iter_close_container(iter, &dict);
-}
-
-static void watcher_exit(DBusConnection *conn, void *user_data)
-{
- struct watcher *watcher = user_data;
- struct gatt_service *gatt = watcher->gatt;
-
- DBG("%s watcher %s exited", gatt->path, watcher->name);
-
- gatt->watchers = g_slist_remove(gatt->watchers, watcher);
- g_dbus_remove_watch(btd_get_dbus_connection(), watcher->id);
- remove_attio(gatt);
-}
-
-static int characteristic_set_value(struct characteristic *chr,
- const uint8_t *value, size_t vlen)
-{
- chr->value = g_try_realloc(chr->value, vlen);
- if (chr->value == NULL)
- return -ENOMEM;
-
- memcpy(chr->value, value, vlen);
- chr->vlen = vlen;
-
- return 0;
-}
-
-static void update_watchers(gpointer data, gpointer user_data)
-{
- struct watcher *w = data;
- struct characteristic *chr = user_data;
- DBusMessage *msg;
-
- msg = dbus_message_new_method_call(w->name, w->path,
- "org.bluez.Watcher", "ValueChanged");
- if (msg == NULL)
- return;
-
- dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &chr->path,
- DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
- &chr->value, chr->vlen, DBUS_TYPE_INVALID);
-
- dbus_message_set_no_reply(msg, TRUE);
- g_dbus_send_message(btd_get_dbus_connection(), msg);
-}
-
-static void events_handler(const uint8_t *pdu, uint16_t len,
- gpointer user_data)
-{
- struct gatt_service *gatt = user_data;
- struct characteristic *chr;
- GSList *l;
- uint8_t *opdu;
- guint handle;
- uint16_t olen;
- size_t plen;
-
- if (len < 3) {
- DBG("Malformed notification/indication packet (opcode 0x%02x)",
- pdu[0]);
- return;
- }
-
- handle = att_get_u16(&pdu[1]);
-
- l = g_slist_find_custom(gatt->chars, GUINT_TO_POINTER(handle),
- characteristic_handle_cmp);
- if (!l)
- return;
-
- chr = l->data;
-
- if (chr == NULL) {
- DBG("Attribute handle 0x%02x not found", handle);
- return;
- }
-
- switch (pdu[0]) {
- case ATT_OP_HANDLE_IND:
- opdu = g_attrib_get_buffer(gatt->attrib, &plen);
- olen = enc_confirmation(opdu, plen);
- g_attrib_send(gatt->attrib, 0, opdu, olen, NULL, NULL, NULL);
- case ATT_OP_HANDLE_NOTIFY:
- if (characteristic_set_value(chr, &pdu[3], len - 3) < 0)
- DBG("Can't change Characteristic 0x%02x", handle);
-
- g_slist_foreach(gatt->watchers, update_watchers, chr);
- break;
- }
-}
-
-static void offline_char_written(gpointer user_data)
-{
- struct characteristic *chr = user_data;
- struct gatt_service *gatt = chr->gatt;
-
- gatt->offline_chars = g_slist_remove(gatt->offline_chars, chr);
-
- remove_attio(gatt);
-}
-
-static void offline_char_write(gpointer data, gpointer user_data)
-{
- struct characteristic *chr = data;
- GAttrib *attrib = user_data;
-
- gatt_write_cmd(attrib, chr->handle, chr->value, chr->vlen,
- offline_char_written, chr);
-}
-
-static void char_discovered_cb(GSList *characteristics, guint8 status,
- gpointer user_data);
-
-static void attio_connected(GAttrib *attrib, gpointer user_data)
-{
- struct gatt_service *gatt = user_data;
-
- gatt->attrib = g_attrib_ref(attrib);
-
- g_attrib_register(gatt->attrib, ATT_OP_HANDLE_NOTIFY,
- GATTRIB_ALL_HANDLES, events_handler, gatt, NULL);
- g_attrib_register(gatt->attrib, ATT_OP_HANDLE_IND,
- GATTRIB_ALL_HANDLES, events_handler, gatt, NULL);
-
- g_slist_foreach(gatt->offline_chars, offline_char_write, attrib);
-
- if (gatt->query) {
- struct gatt_primary *prim = gatt->prim;
- struct query_data *qchr;
-
- qchr = g_slist_nth_data(gatt->query->list, 0);
- gatt_discover_char(gatt->attrib, prim->range.start,
- prim->range.end, NULL,
- char_discovered_cb, qchr);
- }
-}
-
-static void attio_disconnected(gpointer user_data)
-{
- struct gatt_service *gatt = user_data;
-
- if (gatt->query && gatt->query->msg) {
- DBusMessage *reply;
-
- reply = btd_error_failed(gatt->query->msg,
- "ATT IO channel was disconnected");
- g_dbus_send_message(btd_get_dbus_connection(), reply);
- dbus_message_unref(gatt->query->msg);
- }
-
- if (gatt->query) {
- g_slist_free_full(gatt->query->list, g_free);
- gatt->query = NULL;
- }
-
- if (gatt->attrib) {
- g_attrib_unref(gatt->attrib);
- gatt->attrib = NULL;
- }
-}
-
-static DBusMessage *register_watcher(DBusConnection *conn,
- DBusMessage *msg, void *data)
-{
- const char *sender = dbus_message_get_sender(msg);
- struct gatt_service *gatt = data;
- struct watcher *watcher;
- char *path;
-
- if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID))
- return btd_error_invalid_args(msg);
-
- watcher = g_new0(struct watcher, 1);
- watcher->name = g_strdup(sender);
- watcher->gatt = gatt;
- watcher->path = g_strdup(path);
- watcher->id = g_dbus_add_disconnect_watch(btd_get_dbus_connection(),
- sender, watcher_exit,
- watcher, watcher_free);
-
- if (gatt->attioid == 0)
- gatt->attioid = btd_device_add_attio_callback(gatt->dev,
- attio_connected,
- attio_disconnected,
- gatt);
-
- gatt->watchers = g_slist_append(gatt->watchers, watcher);
-
- return dbus_message_new_method_return(msg);
-}
-
-static DBusMessage *unregister_watcher(DBusConnection *conn,
- DBusMessage *msg, void *data)
-{
- const char *sender = dbus_message_get_sender(msg);
- struct gatt_service *gatt = data;
- struct watcher *watcher, *match;
- GSList *l;
- char *path;
-
- if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID))
- return btd_error_invalid_args(msg);
-
- match = g_new0(struct watcher, 1);
- match->name = g_strdup(sender);
- match->path = g_strdup(path);
- l = g_slist_find_custom(gatt->watchers, match, watcher_cmp);
- watcher_free(match);
- if (!l)
- return btd_error_not_authorized(msg);
-
- watcher = l->data;
- gatt->watchers = g_slist_remove(gatt->watchers, watcher);
- g_dbus_remove_watch(btd_get_dbus_connection(), watcher->id);
- remove_attio(gatt);
-
- return dbus_message_new_method_return(msg);
-}
-
-static DBusMessage *set_value(DBusMessage *msg,
- DBusMessageIter *iter, struct characteristic *chr)
-{
- struct gatt_service *gatt = chr->gatt;
- DBusMessageIter sub;
- uint8_t *value;
- int len;
-
- if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(iter) != DBUS_TYPE_BYTE)
- return btd_error_invalid_args(msg);
-
- dbus_message_iter_recurse(iter, &sub);
-
- dbus_message_iter_get_fixed_array(&sub, &value, &len);
-
- characteristic_set_value(chr, value, len);
-
- if (gatt->attioid == 0)
- gatt->attioid = btd_device_add_attio_callback(gatt->dev,
- attio_connected,
- attio_disconnected,
- gatt);
-
- if (gatt->attrib)
- gatt_write_cmd(gatt->attrib, chr->handle, value, len,
- NULL, NULL);
- else
- gatt->offline_chars = g_slist_append(gatt->offline_chars, chr);
-
- return dbus_message_new_method_return(msg);
-}
-
-static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg,
- void *data)
-{
- struct characteristic *chr = data;
- DBusMessage *reply;
- DBusMessageIter iter;
-
- reply = dbus_message_new_method_return(msg);
- if (!reply)
- return NULL;
-
- dbus_message_iter_init_append(reply, &iter);
-
- append_char_dict(&iter, chr);
-
- return reply;
-}
-
-static DBusMessage *set_property(DBusConnection *conn,
- DBusMessage *msg, void *data)
-{
- struct characteristic *chr = data;
- DBusMessageIter iter;
- DBusMessageIter sub;
- const char *property;
-
- if (!dbus_message_iter_init(msg, &iter))
- return btd_error_invalid_args(msg);
-
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
- return btd_error_invalid_args(msg);
-
- dbus_message_iter_get_basic(&iter, &property);
- dbus_message_iter_next(&iter);
-
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
- return btd_error_invalid_args(msg);
-
- dbus_message_iter_recurse(&iter, &sub);
-
- if (g_str_equal("Value", property))
- return set_value(msg, &sub, chr);
-
- return btd_error_invalid_args(msg);
-}
-
-static const GDBusMethodTable char_methods[] = {
- { GDBUS_METHOD("GetProperties",
- NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
- get_properties) },
- { GDBUS_ASYNC_METHOD("SetProperty",
- GDBUS_ARGS({ "name", "s" }, { "value", "v" }), NULL,
- set_property) },
- { }
-};
-
-static char *characteristic_list_to_string(GSList *chars)
-{
- GString *characteristics;
- GSList *l;
-
- characteristics = g_string_new(NULL);
-
- for (l = chars; l; l = l->next) {
- struct characteristic *chr = l->data;
- char chr_str[64];
-
- memset(chr_str, 0, sizeof(chr_str));
-
- snprintf(chr_str, sizeof(chr_str), "%04X#%02X#%04X#%s ",
- chr->handle, chr->perm, chr->end, chr->type);
-
- characteristics = g_string_append(characteristics, chr_str);
- }
-
- return g_string_free(characteristics, FALSE);
-}
-
-static void store_characteristics(const bdaddr_t *sba, const bdaddr_t *dba,
- uint8_t bdaddr_type, uint16_t start,
- GSList *chars)
-{
- char *characteristics;
-
- characteristics = characteristic_list_to_string(chars);
-
- write_device_characteristics(sba, dba, bdaddr_type, start,
- characteristics);
-
- g_free(characteristics);
-}
-
-static void register_characteristic(gpointer data, gpointer user_data)
-{
- struct characteristic *chr = data;
- const char *gatt_path = user_data;
-
- chr->path = g_strdup_printf("%s/characteristic%04x", gatt_path,
- chr->handle);
-
- g_dbus_register_interface(btd_get_dbus_connection(),
- chr->path, CHAR_INTERFACE,
- char_methods, NULL, NULL, chr, NULL);
-
- DBG("Registered: %s", chr->path);
-}
-
-static GSList *string_to_characteristic_list(struct gatt_service *gatt,
- const char *str)
-{
- GSList *l = NULL;
- char **chars;
- int i;
-
- if (str == NULL)
- return NULL;
-
- chars = g_strsplit(str, " ", 0);
- if (chars == NULL)
- return NULL;
-
- for (i = 0; chars[i]; i++) {
- struct characteristic *chr;
- int ret;
-
- chr = g_new0(struct characteristic, 1);
-
- ret = sscanf(chars[i], "%04hX#%02hhX#%04hX#%s", &chr->handle,
- &chr->perm, &chr->end, chr->type);
- if (ret < 4) {
- g_free(chr);
- continue;
- }
-
- chr->gatt = gatt;
- l = g_slist_append(l, chr);
- }
-
- g_strfreev(chars);
-
- return l;
-}
-
-static GSList *load_characteristics(struct gatt_service *gatt, uint16_t start)
-{
- struct btd_device *device = gatt->dev;
- struct btd_adapter *adapter = device_get_adapter(device);
- GSList *chrs_list;
- char *str;
-
- str = read_device_characteristics(adapter_get_address(adapter),
- device_get_address(device),
- device_get_addr_type(device),
- start);
- if (str == NULL)
- return NULL;
-
- chrs_list = string_to_characteristic_list(gatt, str);
-
- free(str);
-
- return chrs_list;
-}
-
-static void store_attribute(struct gatt_service *gatt, uint16_t handle,
- uint16_t type, uint8_t *value, gsize len)
-{
- struct btd_device *device = gatt->dev;
- bt_uuid_t uuid;
- char *str, *tmp;
- guint i;
-
- str = g_malloc0(MAX_LEN_UUID_STR + len * 2 + 1);
-
- bt_uuid16_create(&uuid, type);
- bt_uuid_to_string(&uuid, str, MAX_LEN_UUID_STR);
-
- str[MAX_LEN_UUID_STR - 1] = '#';
-
- for (i = 0, tmp = str + MAX_LEN_UUID_STR; i < len; i++, tmp += 2)
- sprintf(tmp, "%02X", value[i]);
-
- write_device_attribute(adapter_get_address(device_get_adapter(device)),
- device_get_address(device),
- device_get_addr_type(device), handle, str);
-
- g_free(str);
-}
-
-static void query_list_append(struct gatt_service *gatt, struct query_data *data)
-{
- struct query *query = gatt->query;
-
- query->list = g_slist_append(query->list, data);
-}
-
-static void query_list_remove(struct gatt_service *gatt, struct query_data *data)
-{
- struct query *query = gatt->query;
-
- query->list = g_slist_remove(query->list, data);
- if (query->list != NULL)
- return;
-
- g_free(query);
- gatt->query = NULL;
-
- remove_attio(gatt);
-}
-
-static void update_char_desc(guint8 status, const guint8 *pdu, guint16 len,
- gpointer user_data)
-{
- struct query_data *current = user_data;
- struct gatt_service *gatt = current->gatt;
- struct characteristic *chr = current->chr;
-
- if (status == 0) {
-
- g_free(chr->desc);
-
- chr->desc = g_malloc(len);
- memcpy(chr->desc, pdu + 1, len - 1);
- chr->desc[len - 1] = '\0';
-
- store_attribute(gatt, current->handle,
- GATT_CHARAC_USER_DESC_UUID,
- (void *) chr->desc, len);
- } else if (status == ATT_ECODE_INSUFF_ENC) {
- GIOChannel *io = g_attrib_get_channel(gatt->attrib);
- BtIOSecLevel level = BT_IO_SEC_HIGH;
-
- bt_io_get(io, NULL, BT_IO_OPT_SEC_LEVEL, &level,
- BT_IO_OPT_INVALID);
- if (level < BT_IO_SEC_HIGH)
- level++;
-
- if (bt_io_set(io, NULL,
- BT_IO_OPT_SEC_LEVEL, level,
- BT_IO_OPT_INVALID)) {
- gatt_read_char(gatt->attrib, current->handle,
- update_char_desc, current);
- return;
- }
- }
-
- query_list_remove(gatt, current);
- g_free(current);
-}
-
-static void update_char_format(guint8 status, const guint8 *pdu, guint16 len,
- gpointer user_data)
-{
- struct query_data *current = user_data;
- struct gatt_service *gatt = current->gatt;
- struct characteristic *chr = current->chr;
-
- if (status != 0)
- goto done;
-
- if (len < 8)
- goto done;
-
- g_free(chr->format);
-
- chr->format = g_new0(struct format, 1);
- memcpy(chr->format, pdu + 1, 7);
-
- store_attribute(gatt, current->handle, GATT_CHARAC_FMT_UUID,
- (void *) chr->format, sizeof(*chr->format));
-
-done:
- query_list_remove(gatt, current);
- g_free(current);
-}
-
-static void update_char_value(guint8 status, const guint8 *pdu,
- guint16 len, gpointer user_data)
-{
- struct query_data *current = user_data;
- struct gatt_service *gatt = current->gatt;
- struct characteristic *chr = current->chr;
-
- if (status == 0)
- characteristic_set_value(chr, pdu + 1, len - 1);
- else if (status == ATT_ECODE_INSUFF_ENC) {
- GIOChannel *io = g_attrib_get_channel(gatt->attrib);
-
- if (bt_io_set(io, NULL,
- BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_HIGH,
- BT_IO_OPT_INVALID)) {
- gatt_read_char(gatt->attrib, chr->handle,
- update_char_value, current);
- return;
- }
- }
-
- query_list_remove(gatt, current);
- g_free(current);
-}
-
-static int uuid_desc16_cmp(bt_uuid_t *uuid, guint16 desc)
-{
- bt_uuid_t u16;
-
- bt_uuid16_create(&u16, desc);
-
- return bt_uuid_cmp(uuid, &u16);
-}
-
-static void descriptor_cb(guint8 status, const guint8 *pdu, guint16 plen,
- gpointer user_data)
-{
- struct query_data *current = user_data;
- struct gatt_service *gatt = current->gatt;
- struct att_data_list *list;
- guint8 format;
- int i;
-
- if (status != 0)
- goto done;
-
- DBG("Find Information Response received");
-
- list = dec_find_info_resp(pdu, plen, &format);
- if (list == NULL)
- goto done;
-
- for (i = 0; i < list->num; i++) {
- guint16 handle;
- bt_uuid_t uuid;
- uint8_t *info = list->data[i];
- struct query_data *qfmt;
-
- handle = att_get_u16(info);
-
- if (format == 0x01) {
- uuid = att_get_uuid16(&info[2]);
- } else {
- /* Currently, only "user description" and "presentation
- * format" descriptors are used, and both have 16-bit
- * UUIDs. Therefore there is no need to support format
- * 0x02 yet. */
- continue;
- }
- qfmt = g_new0(struct query_data, 1);
- qfmt->gatt = current->gatt;
- qfmt->chr = current->chr;
- qfmt->handle = handle;
-
- if (uuid_desc16_cmp(&uuid, GATT_CHARAC_USER_DESC_UUID) == 0) {
- query_list_append(gatt, qfmt);
- gatt_read_char(gatt->attrib, handle, update_char_desc,
- qfmt);
- } else if (uuid_desc16_cmp(&uuid, GATT_CHARAC_FMT_UUID) == 0) {
- query_list_append(gatt, qfmt);
- gatt_read_char(gatt->attrib, handle, update_char_format,
- qfmt);
- } else
- g_free(qfmt);
- }
-
- att_data_list_free(list);
-done:
- query_list_remove(gatt, current);
- g_free(current);
-}
-
-static void update_all_chars(gpointer data, gpointer user_data)
-{
- struct query_data *qdesc, *qvalue;
- struct characteristic *chr = data;
- struct gatt_service *gatt = user_data;
-
- qdesc = g_new0(struct query_data, 1);
- qdesc->gatt = gatt;
- qdesc->chr = chr;
-
- query_list_append(gatt, qdesc);
-
- gatt_find_info(gatt->attrib, chr->handle + 1, chr->end, descriptor_cb,
- qdesc);
-
- qvalue = g_new0(struct query_data, 1);
- qvalue->gatt = gatt;
- qvalue->chr = chr;
-
- query_list_append(gatt, qvalue);
-
- gatt_read_char(gatt->attrib, chr->handle, update_char_value, qvalue);
-}
-
-static DBusMessage *create_discover_char_reply(DBusMessage *msg, GSList *chars)
-{
- DBusMessage *reply;
- DBusMessageIter iter, array_iter;
- GSList *l;
-
- reply = dbus_message_new_method_return(msg);
-
- dbus_message_iter_init_append(reply, &iter);
-
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
- DBUS_TYPE_OBJECT_PATH_AS_STRING, &array_iter);
-
- for (l = chars; l; l = l->next) {
- struct characteristic *chr = l->data;
-
- dbus_message_iter_append_basic(&array_iter,
- DBUS_TYPE_OBJECT_PATH, &chr->path);
- }
-
- dbus_message_iter_close_container(&iter, &array_iter);
-
- return reply;
-}
-
-static void char_discovered_cb(GSList *characteristics, guint8 status,
- gpointer user_data)
-{
- DBusMessage *reply;
- struct query_data *current = user_data;
- struct gatt_service *gatt = current->gatt;
- struct gatt_primary *prim = gatt->prim;
- uint16_t *previous_end = NULL;
- struct btd_device *device = gatt->dev;
- struct btd_adapter *adapter = device_get_adapter(device);
- GSList *l;
-
- if (status != 0) {
- const char *str = att_ecode2str(status);
-
- DBG("Discover all characteristics failed: %s", str);
- reply = btd_error_failed(gatt->query->msg, str);
- goto fail;
- }
-
- for (l = characteristics; l; l = l->next) {
- struct gatt_char *current_chr = l->data;
- struct characteristic *chr;
- guint handle = current_chr->value_handle;
- GSList *lchr;
-
- lchr = g_slist_find_custom(gatt->chars,
- GUINT_TO_POINTER(handle), characteristic_handle_cmp);
- if (lchr)
- continue;
-
- chr = g_new0(struct characteristic, 1);
- chr->gatt = gatt;
- chr->perm = current_chr->properties;
- chr->handle = current_chr->value_handle;
- strncpy(chr->type, current_chr->uuid, sizeof(chr->type));
-
- if (previous_end)
- *previous_end = current_chr->handle;
-
- previous_end = &chr->end;
-
- gatt->chars = g_slist_append(gatt->chars, chr);
- register_characteristic(chr, gatt->path);
- }
-
- if (previous_end)
- *previous_end = prim->range.end;
-
- store_characteristics(adapter_get_address(adapter),
- device_get_address(device),
- device_get_addr_type(device),
- prim->range.start, gatt->chars);
-
- g_slist_foreach(gatt->chars, update_all_chars, gatt);
-
- reply = create_discover_char_reply(gatt->query->msg, gatt->chars);
-
-fail:
- dbus_message_unref(gatt->query->msg);
- gatt->query->msg = NULL;
-
- g_dbus_send_message(btd_get_dbus_connection(), reply);
- query_list_remove(gatt, current);
- g_free(current);
-}
-
-static DBusMessage *discover_char(DBusConnection *conn, DBusMessage *msg,
- void *data)
-{
- struct gatt_service *gatt = data;
- struct query *query;
- struct query_data *qchr;
-
- if (gatt->query)
- return btd_error_busy(msg);
-
- query = g_new0(struct query, 1);
-
- qchr = g_new0(struct query_data, 1);
- qchr->gatt = gatt;
-
- query->msg = dbus_message_ref(msg);
-
- if (gatt->attioid == 0) {
- gatt->attioid = btd_device_add_attio_callback(gatt->dev,
- attio_connected,
- attio_disconnected,
- gatt);
- } else if (gatt->attrib) {
- struct gatt_primary *prim = gatt->prim;
- gatt_discover_char(gatt->attrib, prim->range.start,
- prim->range.end, NULL,
- char_discovered_cb, qchr);
- }
-
- gatt->query = query;
-
- query_list_append(gatt, qchr);
-
- return NULL;
-}
-
-static DBusMessage *prim_get_properties(DBusConnection *conn, DBusMessage *msg,
- void *data)
-{
- struct gatt_service *gatt = data;
- DBusMessage *reply;
- DBusMessageIter iter;
- DBusMessageIter dict;
- GSList *l;
- char **chars;
- const char *uuid;
- int i;
-
- reply = dbus_message_new_method_return(msg);
- if (!reply)
- return NULL;
-
- dbus_message_iter_init_append(reply, &iter);
-
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
- DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
- DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
- DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
-
- chars = g_new0(char *, g_slist_length(gatt->chars) + 1);
-
- for (i = 0, l = gatt->chars; l; l = l->next, i++) {
- struct characteristic *chr = l->data;
- chars[i] = chr->path;
- }
-
- dict_append_array(&dict, "Characteristics", DBUS_TYPE_OBJECT_PATH,
- &chars, i);
- uuid = gatt->prim->uuid;
- dict_append_entry(&dict, "UUID", DBUS_TYPE_STRING, &uuid);
-
- g_free(chars);
-
- dbus_message_iter_close_container(&iter, &dict);
-
- return reply;
-}
-
-static const GDBusMethodTable prim_methods[] = {
- { GDBUS_ASYNC_METHOD("DiscoverCharacteristics",
- NULL, GDBUS_ARGS({ "characteristics", "ao" }),
- discover_char) },
- { GDBUS_METHOD("RegisterCharacteristicsWatcher",
- GDBUS_ARGS({ "agent", "o" }), NULL,
- register_watcher) },
- { GDBUS_METHOD("UnregisterCharacteristicsWatcher",
- GDBUS_ARGS({ "agent", "o" }), NULL,
- unregister_watcher) },
- { GDBUS_METHOD("GetProperties",
- NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
- prim_get_properties) },
- { }
-};
-
-static struct gatt_service *primary_register(struct btd_device *device,
- struct gatt_primary *prim,
- int psm)
-{
- struct gatt_service *gatt;
- const char *device_path;
-
- device_path = device_get_path(device);
-
- gatt = g_new0(struct gatt_service, 1);
- gatt->dev = btd_device_ref(device);
- gatt->prim = prim;
- gatt->psm = psm;
- gatt->path = g_strdup_printf("%s/service%04x", device_path,
- prim->range.start);
-
- g_dbus_register_interface(btd_get_dbus_connection(), gatt->path,
- CHAR_INTERFACE, prim_methods,
- NULL, NULL, gatt, NULL);
- gatt->chars = load_characteristics(gatt, prim->range.start);
- g_slist_foreach(gatt->chars, register_characteristic, gatt->path);
-
- return gatt;
-}
-
-GSList *attrib_client_register(struct btd_device *device, int psm,
- GAttrib *attrib, GSList *primaries)
-{
- GSList *l, *services;
-
- for (l = primaries, services = NULL; l; l = l->next) {
- struct gatt_primary *prim = l->data;
- struct gatt_service *gatt;
-
- gatt = primary_register(device, prim, psm);
-
- DBG("Registered: %s", gatt->path);
-
- services = g_slist_append(services, g_strdup(gatt->path));
- gatt_services = g_slist_append(gatt_services, gatt);
-
- }
-
- return services;
-}
-
-static void primary_unregister(struct gatt_service *gatt)
-{
- DBusConnection *conn = btd_get_dbus_connection();
- GSList *l;
-
- for (l = gatt->chars; l; l = l->next) {
- struct characteristic *chr = l->data;
- g_dbus_unregister_interface(conn, chr->path, CHAR_INTERFACE);
- }
-
- g_dbus_unregister_interface(conn, gatt->path, CHAR_INTERFACE);
-
- remove_attio(gatt);
-}
-
-static int path_cmp(gconstpointer data, gconstpointer user_data)
-{
- const char *path = data;
- const char *gatt_path = user_data;
-
- return g_strcmp0(path, gatt_path);
-}
-
-void attrib_client_unregister(GSList *services)
-{
- GSList *l, *left;
-
- for (l = gatt_services, left = NULL; l; l = l->next) {
- struct gatt_service *gatt = l->data;
-
- if (!g_slist_find_custom(services, gatt->path, path_cmp)) {
- left = g_slist_append(left, gatt);
- continue;
- }
-
- primary_unregister(gatt);
- gatt_service_free(gatt);
- }
-
- g_slist_free(gatt_services);
- gatt_services = left;
-}
diff --git a/attrib/client.h b/attrib/client.h
deleted file mode 100644
index 89f4f24..0000000
--- a/attrib/client.h
+++ /dev/null
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2010 Nokia Corporation
- * Copyright (C) 2010 Marcel Holtmann <marcel@holtmann.org>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-GSList *attrib_client_register(struct btd_device *device, int psm,
- GAttrib *attrib, GSList *primaries);
-void attrib_client_unregister(GSList *services);
diff --git a/doc/attribute-api.txt b/doc/attribute-api.txt
deleted file mode 100644
index 4b392b9..0000000
--- a/doc/attribute-api.txt
+++ /dev/null
-BlueZ D-Bus Attribute API description
-*************************************
-
-Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
-
-Service details
----------------
-
-All characteristics are presented as object paths in a single, flat list. Each
-object has a "ServiceUUID" property which contains the 128-bit UUID of the
-service that contains it, so clients can identify the correct characteristic if
-multiple services contain the same characteristic.
-
-This API is used for both local (added to the BlueZ GATT server) and remote
-(found by GATT discovery) services.
-
-Device Characteristic hierarchy
-===============================
-
-Service org.bluez
-Interface org.bluez.Characteristic
-Object path freely definable
-
-For local characteristics, it is recommended (for readability and debugging
-purposes) to have the object path prefix as "[freely definable]/[busid]" where
-"[busid]" is the application's D-Bus address. For remote characteristics, the
-device address is added to the prefix. E.g.:
-
-[freely definable]/[busid]/characteristic_1803_2A06 (local)
-[freely definable]/dev_XX_XX_XX_XX_XX_XX/characteristic_1803_2A06 (remote)
-
-Methods void SetValue(array{byte} value)
-
- Update characteristic value.
-
- For a remote characteristic, this method triggers a
- GATT characteristic value write procedure setting a new
- value for this characteristic. The GATT sub-procedure
- is automatically selected based on the characteristic
- properties and value length.
-
- dict GetValue()
-
- Read characteristic value and descriptors. The returned
- dictionary has the following format:
-
- {
- "value": array{byte},
- "formatted value": string,
- // Optional descriptors
- "client configuration": uint16,
- "server configuration": uint16,
- "extended properties": uint16,
- "user description": string,
- // For unknown descriptors, use 128-bit UUID
- // as key
- "uuid": array{byte},
- }
-
-Properties string UUID [readonly]
-
- 128-bit UUID of this characteristic.
-
- string ServiceUUID [readonly]
-
- 128-bit UUID of the service which includes this
- characteristic.
-
- boolean Read [readonly]
-
- Characteristic value can be read.
-
- boolean WriteWithoutResponse [readonly]
-
- Characteristic value can be written using GATT Write
- Without Response sub-procedure.
-
- boolean Write [readonly]
-
- Characteristic value can be written using GATT Write
- Characteristic Value sub-procedures.
-
- boolean Notify [readonly]
-
- Characteristic value can be notified.
-
- boolean Indicate [readonly]
-
- Characteristic value can be indicated.
-
- boolean AuthenticatedSignedWrites [readonly]
-
- Characteristic value can be written using GATT Signed
- Write Without Response sub-procedure.
-
- boolean ExtendedProperties [readonly]
-
- Characteristic contains additional properties defined
- on the Extended Properties descriptor.
-
-Characteristic Watcher hierarchy
-===============================
-
-Service unique name
-Interface org.bluez.Watcher
-Object path freely definable
-
-Methods void ValueChanged(object characteristic, dict value)
-
- The value dictionary contains the new value for the
- Characteristic. The format is the same returned by
- Characteristic.GetValue().
-
- This method is only called when the "raw" setting is
- disabled on Adapter.RegisterCharacteristicsWatcher().
-
- void RawValueChanged(object characteristic, array{byte} value)
-
- New raw Characteristic value.
-
- This method is only called when the "raw" setting is
- enabled on Adapter.RegisterCharacteristicsWatcher().
diff --git a/src/adapter.c b/src/adapter.c
index 34af063..0a3297e 100644
--- a/src/adapter.c
+++ b/src/adapter.c
list = device_services_from_record(device, uuids);
if (list)
- device_register_services(device, list, ATT_PSM);
+ device_register_primaries(device, list, ATT_PSM);
device_probe_profiles(device, uuids);
uuids = g_slist_append(uuids, prim->uuid);
}
- device_register_services(device, services, -1);
+ device_register_primaries(device, services, -1);
device_probe_profiles(device, uuids);
diff --git a/src/device.c b/src/device.c
index e6afe64..0e66f79 100644
--- a/src/device.c
+++ b/src/device.c
#include "sdp-xml.h"
#include "storage.h"
#include "attrib-server.h"
-#include "attrib/client.h"
#define IO_CAPABILITY_DISPLAYONLY 0x00
#define IO_CAPABILITY_DISPLAYYESNO 0x01
uint16_t version;
struct btd_adapter *adapter;
GSList *uuids;
- GSList *services; /* Primary services path */
GSList *primaries; /* List of primary services */
GSList *profiles; /* Probed profiles */
GSList *pending; /* Pending profiles */
agent_is_busy(agent, device->authr)))
agent_cancel(agent);
- g_slist_free_full(device->services, g_free);
g_slist_free_full(device->uuids, g_free);
g_slist_free_full(device->primaries, g_free);
g_slist_free_full(device->attios, g_free);
return dev->eir_uuids ? TRUE : FALSE;
}
-static gboolean dev_property_get_services(const GDBusPropertyTable *property,
- DBusMessageIter *iter, void *data)
-{
- struct btd_device *device = data;
- DBusMessageIter entry;
- GSList *l;
-
- dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
- DBUS_TYPE_OBJECT_PATH_AS_STRING, &entry);
-
- for (l = device->services; l != NULL; l = l->next)
- dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
- &l->data);
-
- dbus_message_iter_close_container(iter, &entry);
-
- return TRUE;
-}
-
-static gboolean dev_property_exists_services(const GDBusPropertyTable *prop,
- void *data)
-{
- struct btd_device *dev = data;
-
- return dev->services ? TRUE : FALSE;
-}
-
static gboolean dev_property_get_adapter(const GDBusPropertyTable *property,
DBusMessageIter *iter, void *data)
{
{ "Connected", "b", dev_property_get_connected },
{ "UUIDs", "as", dev_property_get_uuids, NULL,
dev_property_exists_uuids },
- { "Services", "ao", dev_property_get_services, NULL,
- dev_property_exists_services },
{ "Adapter", "o", dev_property_get_adapter },
{ }
};
g_slist_free(device->profiles);
device->profiles = NULL;
- attrib_client_unregister(device->services);
-
btd_device_unref(device);
}
list = device_services_from_record(device, req->profiles_added);
if (list)
- device_register_services(device, list, ATT_PSM);
+ device_register_primaries(device, list, ATT_PSM);
device_probe_profiles(device, req->profiles_added);
}
return FALSE;
}
-static void device_unregister_services(struct btd_device *device)
-{
- attrib_client_unregister(device->services);
- g_slist_free_full(device->services, g_free);
- device->services = NULL;
-}
-
static void register_all_services(struct browse_req *req, GSList *services)
{
struct btd_device *device = req->device;
device_set_temporary(device, FALSE);
- if (device->services)
- device_unregister_services(device);
-
update_gatt_services(req, device->primaries, services);
g_slist_free_full(device->primaries, g_free);
device->primaries = NULL;
- device_register_services(device, g_slist_copy(services), -1);
+ device_register_primaries(device, g_slist_copy(services), -1);
if (req->profiles_removed)
device_remove_profiles(device, req->profiles_removed);
return (device->authr != NULL);
}
-void device_register_services(struct btd_device *device,
+void device_register_primaries(struct btd_device *device,
GSList *prim_list, int psm)
{
device->primaries = g_slist_concat(device->primaries, prim_list);
- device->services = attrib_client_register(device, psm, NULL, prim_list);
}
GSList *btd_device_get_primaries(struct btd_device *device)
diff --git a/src/device.h b/src/device.h
index 1987a80..b569a71 100644
--- a/src/device.h
+++ b/src/device.h
GSList *btd_device_get_primaries(struct btd_device *device);
void btd_device_gatt_set_service_changed(struct btd_device *device,
uint16_t start, uint16_t end);
-void device_register_services(struct btd_device *device,
+void device_register_primaries(struct btd_device *device,
GSList *prim_list, int psm);
GSList *device_services_from_record(struct btd_device *device,
GSList *profiles);
diff --git a/test/test-attrib b/test/test-attrib
deleted file mode 100755
index aadffaa..0000000
--- a/test/test-attrib
+++ /dev/null
-#!/usr/bin/python
-
-from __future__ import absolute_import, print_function, unicode_literals
-# Script for testing the Attribute D-Bus API
-
-import sys
-from optparse import OptionParser, OptionValueError
-from binascii import hexlify, unhexlify
-
-import gobject
-
-import sys
-import dbus
-import dbus.mainloop.glib
-from optparse import OptionParser, make_option
-import bluezutils
-
-dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
-bus = dbus.SystemBus()
-mainloop = gobject.MainLoop()
-
-option_list = [
- make_option("-i", "--device", action="store",
- type="string", dest="dev_id"),
- ]
-parser = OptionParser(option_list=option_list)
-
-(options, args) = parser.parse_args()
-
-if (len(args) < 1):
- print("Usage: %s <command>" % (sys.argv[0]))
- print("")
- print(" list")
- print(" services <address>")
- print(" discover <service path>")
- print(" chars <service path>")
- sys.exit(1)
-
-if (args[0] == "list"):
- adapter = bluezutils.find_adapter(options.dev_id)
- for path in adapter.GetProperties()["Devices"]:
- device = dbus.Interface(bus.get_object("org.bluez", path),
- "org.bluez.Device1")
- devprop = device.GetProperties()
- print("[ %s ]" % devprop["Address"])
- for path in devprop["Services"]:
-
- service = dbus.Interface(bus.get_object("org.bluez", path),
- "org.bluez.Characteristic")
- srvprop = service.GetProperties()
- print(" * %s" % (path))
- print(" UUID: %s" % srvprop["UUID"])
- print(" Chars: ",)
- for char in srvprop["Characteristics"]:
- print("%s " % char,)
- print()
- print()
- print()
- sys.exit(0)
-
-if (args[0] == "services"):
- if (len(args) < 2):
- print("Need address parameter")
- else:
- device = bluezutils.find_device(args[1], options.dev_id)
- properties = device.GetProperties()
- for path in properties["Services"]:
- print(path)
- sys.exit(0)
-
-if (args[0] == "discover"):
- if (len(args) < 2):
- print("Need service path parameter")
- else:
- service = dbus.Interface(bus.get_object("org.bluez", args[1]),
- "org.bluez.Characteristic")
- for path in service.DiscoverCharacteristics():
- print(path)
- sys.exit(0)
-
-if (args[0] == "chars"):
- if (len(args) < 2):
- print("Need service path parameter")
- else:
- service = dbus.Interface(bus.get_object("org.bluez", args[1]),
- "org.bluez.Characteristic")
- srvprop = service.GetProperties()
- for path in srvprop["Characteristics"]:
- print("[ %s ]" % (path))
- char = dbus.Interface(bus.get_object("org.bluez", path),
- "org.bluez.Characteristic")
- charprop = char.GetProperties()
- print(" Name: %s" % charprop["Name"])
- print(" UUID: %s" % charprop["UUID"])
- print()
- print()
- sys.exit(0)
-
-print("Unknown command")
-sys.exit(1)