#define PATHLOSS_MAX 137
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-#define check_address(address) bachk(address)
#define ADV_DATA_MAX_LENGTH 31
#define SCAN_RESPONSE_DATA_LENGTH_MAX 31
#define EIR_MANUFACTURER_DATA_LENGTH_MAX 100
-#define PRIVATE_ADDR_TIMEOUT (15 * 60)
-
-#define BT_DISC_TYPE_BREDR 1
-#define BT_DISC_TYPE_LE 2
-#define IDLE_LE_DISCOV_TIMEOUT (3)
-
-#define DISCOV_TYPE_BREDR 1
-#define DISCOV_TYPE_LE 6
#define LE_BEARER_POSTFIX " LE"
#define LE_BEARER_POSTFIX_LEN 3
bdaddr_t bdaddr; /* controller Bluetooth address */
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
bdaddr_t le_static_addr;
- bdaddr_t rpaddr; /* controller RPA */
#endif
uint32_t dev_class; /* controller class of device */
char *name; /* controller device name */
unsigned int db_id; /* Service event handler for GATT db */
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- guint private_addr_timeout;
uint8_t central_rpa_res_support;
#ifdef TIZEN_FEATURE_PLATFROM_SCAN_FILTER
bool scan_filter_support; /* platform's scan filtering support */
addr.bdaddr_type = bdaddr_type;
ba2str(dst, addr_str);
- DBG("find device %s %d", addr_str, bdaddr_type);
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
list = g_slist_find_custom(adapter->devices, &addr,
device_addr_type_strict_cmp);
if (list) {
device = list->data;
- DBG("Exact matched");
- device_print_addr(device);
exact_match = true;
} else {
#endif
device_addr_type_cmp);
if (list) {
device = list->data;
- DBG("Soft matched");
- device_print_addr(device);
}
}
}
DBG("status 0x%02x", status);
- DBG("Discovery Type 0x%02x", rp->type);
if (length < sizeof(*rp)) {
error("Wrong size of start discovery return parameters");
return;
}
+ DBG("Discovery Type 0x%02x", rp->type);
if (status == MGMT_STATUS_SUCCESS) {
adapter->discovery_type |= rp->type;
adapter->discovery_enable = 0x01;
ADAPTER_INTERFACE, "LEDiscovering");
}
-
- /*
- * In case the restart of the discovery failed, then just trigger
- * it for the next idle timeout again.
- */
-// trigger_start_discovery(adapter, IDLE_LE_DISCOV_TIMEOUT * 2);
}
#endif
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
DBG("info discov_type %d", adapter->discovery_type);
- if (ev->type == DISCOV_TYPE_BREDR) {
+ if (ev->type == SCAN_TYPE_BREDR) {
if (ev->discovering == FALSE) {
hci_clear_bit(BDADDR_BREDR, &adapter->discovery_type);
adapter->discovering = false;
g_dbus_emit_property_changed(dbus_conn, adapter->path,
ADAPTER_INTERFACE, "Discovering");
- } else if (ev->type == DISCOV_TYPE_LE) {
+ } else if (ev->type == SCAN_TYPE_LE) {
if (ev->discovering == FALSE) {
hci_clear_bit(BDADDR_LE_PUBLIC, &adapter->discovery_type);
hci_clear_bit(BDADDR_LE_RANDOM, &adapter->discovery_type);
{
adv_data[0] = 2;
adv_data[1] = EIR_FLAGS;
-#ifdef TIZEN_KITT
adv_data[2] = EIR_GEN_DISC | EIR_CONTROLLER |
EIR_SIM_HOST | EIR_BREDR_UNSUP;
-#else
- adv_data[2] = EIR_GEN_DISC | EIR_CONTROLLER | EIR_SIM_HOST;
-#endif
memcpy(adv_data + 3, data, data_len);
return data_len + 3;
DBUS_TYPE_INVALID) == FALSE)
return btd_error_invalid_args(msg);
- if (check_address(address) < 0)
+ if (bachk(address) < 0)
return btd_error_invalid_args(msg);
if (!(adapter->current_settings & MGMT_SETTING_POWERED))
DBUS_TYPE_INVALID) == FALSE)
return btd_error_invalid_args(msg);
- if (check_address(address) < 0)
+ if (bachk(address) < 0)
return btd_error_invalid_args(msg);
if (address_type == 0)
memset(&cp, 0, sizeof(struct mgmt_cp_set_enable_rssi));
memset(&cp_dis, 0, sizeof(struct mgmt_cp_disable_rssi));
- if (check_address(address) < 0)
+ if (bachk(address) < 0)
return btd_error_invalid_args(msg);
// if (!btd_adapter_find_device(adapter, address))
str2ba(address, &bt_addr);
memset(&cp, 0, sizeof(struct mgmt_cp_get_raw_rssi));
- if (check_address(address) < 0)
+ if (bachk(address) < 0)
return btd_error_invalid_args(msg);
// if (!btd_adapter_find_device(adapter, address))
DBUS_TYPE_INVALID) == FALSE)
return btd_error_invalid_args(msg);
- if (check_address(address) < 0)
+ if (bachk(address) < 0)
return btd_error_invalid_args(msg);
DBG("%s", address);
}
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- /* Get Le Privacy feature support */
- adapter->le_privacy_enabled = main_opts.le_privacy;
- if (adapter->le_privacy_enabled) {
- /* Get Local IRK */
- str = g_key_file_get_string(key_file,
- "General", "LocalIrk", &gerr);
- if (gerr || !str || strlen(str) != 34) {
- g_error_free(gerr);
- gerr = NULL;
-
- g_free(adapter->local_irk);
- adapter->local_irk = NULL;
- } else {
- if (adapter->local_irk)
- g_free(adapter->local_irk);
+ /* Get Local IRK */
+ str = g_key_file_get_string(key_file, "General", "LocalIrk", &gerr);
+ if (gerr || !str || strlen(str) != 34) {
+ g_error_free(gerr);
+ gerr = NULL;
+ g_free(adapter->local_irk);
+ adapter->local_irk = NULL;
+ } else {
+ if (!adapter->local_irk)
adapter->local_irk = g_malloc0(MGMT_IRK_SIZE);
- str2buf(&str[2], adapter->local_irk, MGMT_IRK_SIZE);
- }
+
+ str2buf(&str[2], adapter->local_irk, MGMT_IRK_SIZE);
}
#endif
#define GATT_CHARAC_UUID_STR "2803"
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-#define DEV_SIMUL_CONTROLLER 0x08 /* Simultaneous LE and BR/EDR to Same
- Device Capable (Controller) */
-#define DEV_SIMUL_HOST 0x10 /* Simultaneous LE and BR/EDR to Same
- Device Capable (Host) */
-#define DEV_MAX_MANUFACTURER_DATA_LEN 248
-
-/* Added for compilation*/
-#define BT_ADDRESS_STRING_SIZE 18
+#define DEV_MAX_MANUFACTURER_DATA_LEN 248
#endif
static DBusConnection *dbus_conn = NULL;
gboolean device_is_bredrle(struct btd_device *device)
{
- return (device->remote_feature_flags &
- (DEV_SIMUL_CONTROLLER | DEV_SIMUL_HOST));
+ return (device->remote_feature_flags & (EIR_CONTROLLER | EIR_SIM_HOST));
}
#endif
gboolean device_is_profile_trusted(struct btd_device *device,
const char *uuid)
{
- DBG("UUID %s", uuid);
if (g_strcmp0(uuid, OBEX_PSE_UUID) == 0) {
if (device->trusted_profiles.pbap == SUPPORTED_TRUSTED)
- return true;
+ return TRUE;
} else if (g_strcmp0(uuid, OBEX_MAS_UUID) == 0) {
if (device->trusted_profiles.map == SUPPORTED_TRUSTED)
- return true;
+ return TRUE;
} else if (g_strcmp0(uuid, SAP_UUID) == 0) {
if (device->trusted_profiles.sap == SUPPORTED_TRUSTED)
- return true;
+ return TRUE;
}
- return false;
+ return FALSE;
}
gboolean device_is_profile_restricted(struct btd_device *device,
const char *uuid)
{
- DBG("UUID %s", uuid);
if (g_strcmp0(uuid, HFP_HS_UUID) == 0) {
if (device->restricted_profiles.hfp_hs == CONNECTION_RESTRICTED)
- return true;
+ return TRUE;
} else if (g_strcmp0(uuid, A2DP_SINK_UUID) == 0) {
if (device->restricted_profiles.a2dp == CONNECTION_RESTRICTED)
- return true;
+ return TRUE;
}
- return false;
+ return FALSE;
}
gboolean device_is_profile_blocked(struct btd_device *device,
const char *uuid)
{
- DBG("UUID %s", uuid);
if (g_strcmp0(uuid, OBEX_PSE_UUID) == 0) {
if (device->trusted_profiles.pbap == SUPPORTED_BLOCKED)
- return true;
+ return TRUE;
} else if (g_strcmp0(uuid, OBEX_MAS_UUID) == 0) {
if (device->trusted_profiles.map == SUPPORTED_BLOCKED)
- return true;
+ return TRUE;
} else if (g_strcmp0(uuid, SAP_UUID) == 0) {
if (device->trusted_profiles.sap == SUPPORTED_BLOCKED)
- return true;
+ return TRUE;
}
- return false;
+ return FALSE;
}
#endif
dbus_uint16_t max_tx_time;
struct btd_device *device = user_data;
int status;
- char addr[BT_ADDRESS_STRING_SIZE];
+ char addr[18];
if (!dbus_message_get_args(msg, NULL,
DBUS_TYPE_UINT16, &max_tx_octets,
ba2str(&dev->bdaddr, ida);
- if (dev->rpa)
+ if (dev->rpa) {
ba2str(dev->rpa, rpa);
- DBG("IDA %s [%d] : RPA [%s], BREDR [%d], LE [%d]",
- ida, dev->bdaddr_type, dev->rpa ? rpa : "0",
- dev->bredr ? 1 : 0, dev->le ? 1 : 0);
+ DBG("IDA %s [%d] : RPA [%s], BREDR [%d], LE [%d]",
+ ida, dev->bdaddr_type, rpa,
+ dev->bredr ? 1 : 0, dev->le ? 1 : 0);
+ } else {
+ DBG("ADDR %s [%d] : BREDR [%d], LE [%d]",
+ ida, dev->bdaddr_type,
+ dev->bredr ? 1 : 0, dev->le ? 1 : 0);
+ }
}
#endif
+++ /dev/null
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2014 Instituto Nokia de Tecnologia - INdT
- *
- *
- * 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 <stdint.h>
-#include <errno.h>
-
-#include <glib.h>
-#include <dbus/dbus.h>
-#include <gdbus/gdbus.h>
-
-#include "adapter.h"
-#include "device.h"
-#include "lib/uuid.h"
-#include "dbus-common.h"
-#include "log.h"
-
-#include "error.h"
-#include "attrib/gattrib.h"
-#include "attrib/att.h"
-#include "attrib/gatt.h"
-#include "gatt.h"
-#include "gatt-dbus.h"
-
-#define GATT_MGR_IFACE "org.bluez.GattManager1"
-#define GATT_SERVICE_IFACE "org.bluez.GattService1"
-#define GATT_CHR_IFACE "org.bluez.GattCharacteristic1"
-#define GATT_DESCRIPTOR_IFACE "org.bluez.GattDescriptor1"
-
-struct external_service {
- char *owner;
- char *path;
- DBusMessage *reg;
- GDBusClient *client;
- GSList *proxies;
- struct btd_attribute *service;
-};
-
-struct proxy_write_data {
- btd_attr_write_result_t result_cb;
- void *user_data;
-};
-
-/*
- * Attribute to Proxy hash table. Used to map incoming
- * ATT operations to its external characteristic proxy.
- */
-static GHashTable *proxy_hash;
-
-static GSList *external_services;
-
-static int external_service_path_cmp(gconstpointer a, gconstpointer b)
-{
- const struct external_service *esvc = a;
- const char *path = b;
-
- return g_strcmp0(esvc->path, path);
-}
-
-static gboolean external_service_destroy(void *user_data)
-{
- struct external_service *esvc = user_data;
-
- g_dbus_client_unref(esvc->client);
-
- if (esvc->reg)
- dbus_message_unref(esvc->reg);
-
- g_free(esvc->owner);
- g_free(esvc->path);
- g_free(esvc);
-
- return FALSE;
-}
-
-static void external_service_free(void *user_data)
-{
- struct external_service *esvc = user_data;
-
- /*
- * Set callback to NULL to avoid potential race condition
- * when calling remove_service and GDBusClient unref.
- */
- g_dbus_client_set_disconnect_watch(esvc->client, NULL, NULL);
-
- external_service_destroy(user_data);
-}
-
-static void remove_service(DBusConnection *conn, void *user_data)
-{
- struct external_service *esvc = user_data;
-
- external_services = g_slist_remove(external_services, esvc);
-
- if (esvc->service)
- btd_gatt_remove_service(esvc->service);
-
- /*
- * Do not run in the same loop, this may be a disconnect
- * watch call and GDBusClient should not be destroyed.
- */
- g_idle_add(external_service_destroy, esvc);
-}
-
-static int proxy_path_cmp(gconstpointer a, gconstpointer b)
-{
- GDBusProxy *proxy1 = (GDBusProxy *) a;
- GDBusProxy *proxy2 = (GDBusProxy *) b;
- const char *path1 = g_dbus_proxy_get_path(proxy1);
- const char *path2 = g_dbus_proxy_get_path(proxy2);
-
- return g_strcmp0(path1, path2);
-}
-
-static uint8_t flags_string2int(const char *proper)
-{
- uint8_t value;
-
- /* Regular Properties: See core spec 4.1 page 2183 */
- if (!strcmp("broadcast", proper))
- value = GATT_CHR_PROP_BROADCAST;
- else if (!strcmp("read", proper))
- value = GATT_CHR_PROP_READ;
- else if (!strcmp("write-without-response", proper))
- value = GATT_CHR_PROP_WRITE_WITHOUT_RESP;
- else if (!strcmp("write", proper))
- value = GATT_CHR_PROP_WRITE;
- else if (!strcmp("notify", proper))
- value = GATT_CHR_PROP_NOTIFY;
- else if (!strcmp("indicate", proper))
- value = GATT_CHR_PROP_INDICATE;
- else if (!strcmp("authenticated-signed-writes", proper))
- value = GATT_CHR_PROP_AUTH;
- else
- value = 0;
-
- /* TODO: Extended properties. Ref core spec 4.1 page 2185 */
-
- return value;
-}
-
-static uint8_t flags_get_bitmask(DBusMessageIter *iter)
-{
- DBusMessageIter istr;
- uint8_t propmask = 0, prop;
- const char *str;
-
- if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
- goto fail;
-
- dbus_message_iter_recurse(iter, &istr);
-
- do {
- if (dbus_message_iter_get_arg_type(&istr) != DBUS_TYPE_STRING)
- goto fail;
-
- dbus_message_iter_get_basic(&istr, &str);
- prop = flags_string2int(str);
- if (!prop)
- goto fail;
-
- propmask |= prop;
- } while (dbus_message_iter_next(&istr));
-
- return propmask;
-
-fail:
- error("Characteristic Flags: Invalid argument!");
-
- return 0;
-}
-
-static void proxy_added(GDBusProxy *proxy, void *user_data)
-{
- struct external_service *esvc = user_data;
- const char *interface, *path;
-
- interface = g_dbus_proxy_get_interface(proxy);
- path = g_dbus_proxy_get_path(proxy);
-
- if (!g_str_has_prefix(path, esvc->path))
- return;
-
- if (g_strcmp0(interface, GATT_CHR_IFACE) != 0 &&
- g_strcmp0(interface, GATT_SERVICE_IFACE) != 0 &&
- g_strcmp0(interface, GATT_DESCRIPTOR_IFACE) != 0)
- return;
-
- DBG("path %s iface %s", path, interface);
-
- /*
- * Object path follows a hierarchical organization. Add the
- * proxies sorted by path helps the logic to register the
- * object path later.
- */
- esvc->proxies = g_slist_insert_sorted(esvc->proxies, proxy,
- proxy_path_cmp);
-}
-
-static void proxy_removed(GDBusProxy *proxy, void *user_data)
-{
- struct external_service *esvc = user_data;
- const char *interface, *path;
-
- interface = g_dbus_proxy_get_interface(proxy);
- path = g_dbus_proxy_get_path(proxy);
-
- DBG("path %s iface %s", path, interface);
-
- esvc->proxies = g_slist_remove(esvc->proxies, proxy);
-}
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-static void proxy_prop_changed(GDBusProxy *proxy, const char *name,
- DBusMessageIter *iter, void *user_data)
-{
- DBusMessageIter iter_uuid, array;
- const char *str;
- bt_uuid_t uuid;
- uint8_t *value;
- int len;
-
- if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
- return;
-
- dbus_message_iter_recurse(iter, &array);
- dbus_message_iter_get_fixed_array(&array, &value, &len);
-
- if (!g_dbus_proxy_get_property(proxy, "UUID", &iter_uuid))
- return;
-
- if (dbus_message_iter_get_arg_type(&iter_uuid) != DBUS_TYPE_STRING)
- return;
-
- dbus_message_iter_get_basic(&iter_uuid, &str);
-
- if (bt_string_to_uuid(&uuid, str) < 0)
- return;
-
- /* Update the charateristics in attrib database and
- * send notification or indication if CCC is set */
- btd_gatt_update_char(&uuid, value, len);
-}
-
-static DBusMessage *__bt_gatt_dbus_method_send(const char *path, const char *svc_path,
- const char *interface, const char *method, DBusError *err, int type, ...)
-{
- DBusMessage *msg;
- DBusMessage *reply;
- va_list args;
- int timeout = -1;
- struct external_service *esvc;
- GSList *list;
-
- list = g_slist_find_custom(external_services, svc_path,
- external_service_path_cmp);
- if (!list) {
- return NULL;
- }
-
- esvc = list->data;
- msg = dbus_message_new_method_call(esvc->owner,
- svc_path, interface, method);
- if (!msg) {
- DBG("Unable to allocate new D-Bus %s message \n", method);
- return NULL;
- }
-
- va_start(args, type);
-
- if (!dbus_message_append_args_valist(msg, type, args)) {
- dbus_message_unref(msg);
- va_end(args);
- return NULL;
- }
-
- va_end(args);
-
- dbus_error_init(err);
- reply = dbus_connection_send_with_reply_and_block(btd_get_dbus_connection(),
- msg, timeout, err);
- dbus_message_unref(msg);
-
- return reply;
-}
-#endif
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-static uint8_t proxy_read_cb(struct btd_attribute *attr, bdaddr_t *bdaddr,
- btd_attr_read_result_t result, void *user_data)
-#else
-static void proxy_read_cb(struct btd_attribute *attr,
- btd_attr_read_result_t result, void *user_data)
-#endif
-{
- GDBusProxy *proxy;
- uint8_t *value = NULL;
- int len = 0;
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- char dstaddr[18] = { 0 };
- char *addr_value = NULL;
- DBusMessage *reply;
- DBusError err;
- uint8_t request_id = 1;
- uint16_t offset = 0;
- const char *path = NULL;
- const char *svc_path = NULL;
-#endif
- /*
- * Remote device is trying to read the informed attribute,
- * "Value" should be read from the proxy. GDBusProxy tracks
- * properties changes automatically, it is not necessary to
- * get the value directly from the GATT server.
- */
- proxy = g_hash_table_lookup(proxy_hash, attr);
- if (!proxy) {
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- return result(-ENOENT, NULL, 0, user_data);
-#else
- result(-ENOENT, NULL, 0, user_data);
- return;
-#endif
- }
-#ifndef TIZEN_FEATURE_BLUEZ_MODIFY
- if (!g_dbus_proxy_get_property(proxy, "Value", &iter)) {
- /* Unusual situation, read property will checked earlier */
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- return result(-EPERM, NULL, 0, user_data);
-#else
- result(-EPERM, NULL, 0, user_data);
- return;
-#endif
- }
-
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
- DBG("External service inconsistent!");
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- return result(-EPERM, NULL, 0, user_data);
-#else
- result(-EPERM, NULL, 0, user_data);
- return;
-#endif
- }
-
- dbus_message_iter_recurse(&iter, &array);
- dbus_message_iter_get_fixed_array(&array, &value, &len);
-#else
- ba2str(bdaddr, dstaddr);
- addr_value = g_strdup(dstaddr);
- path = btd_get_attrib_path(attr);
- if (!path) {
- /* Fix : RESOURCE_LEAK */
- if (addr_value)
- g_free(addr_value);
- return result(-EPERM, NULL, 0, user_data);
- }
- svc_path = btd_find_service_from_attr(attr);
- if (!svc_path) {
- /* Fix : RESOURCE_LEAK */
- if (addr_value)
- g_free(addr_value);
- return result(-EPERM, NULL, 0, user_data);
- }
- reply = __bt_gatt_dbus_method_send(path, svc_path,
- DBUS_INTERFACE_PROPERTIES,
- "ReadValue", &err,
- DBUS_TYPE_STRING, &addr_value,
- DBUS_TYPE_STRING, &path,
- DBUS_TYPE_BYTE, &request_id,
- DBUS_TYPE_UINT16, &offset,
- DBUS_TYPE_INVALID);
- if (!reply) {
- DBG("Error returned in method call\n");
- if (dbus_error_is_set(&err))
- DBG("Error = %s", err.message);
- /* Fix : RESOURCE_LEAK */
- if (addr_value)
- g_free(addr_value);
- return result(-EPERM, NULL, 0, user_data);
- } else {
- DBusMessageIter iter, array;
- uint8_t *value = NULL;
- int len;
- dbus_message_iter_init(reply, &iter);
-
- if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY) {
- dbus_message_iter_recurse(&iter, &array);
- dbus_message_iter_get_fixed_array(&array, &value, &len);
- if (len > 0)
- return result(0, value, len, user_data);
- else
- return result(-ENOENT, NULL, 0, user_data);
- }
- }
-#endif
- DBG("attribute: %p read %d bytes", attr, len);
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- return result(0, value, len, user_data);
-#else
- result(0, value, len, user_data);
-#endif
-}
-
-static void proxy_write_reply(const DBusError *derr, void *user_data)
-{
- struct proxy_write_data *wdata = user_data;
- int err;
-
- /*
- * Security requirements shall be handled by the core. If external
- * applications returns an error, the reasons will be restricted to
- * invalid argument or application specific errors.
- */
-
- if (!dbus_error_is_set(derr)) {
- err = 0;
- goto done;
- }
-
- DBG("Write reply: %s", derr->message);
-
- if (dbus_error_has_name(derr, DBUS_ERROR_NO_REPLY))
- err = -ETIMEDOUT;
- else if (dbus_error_has_name(derr, ERROR_INTERFACE ".InvalidArguments"))
- err = -EINVAL;
- else
- err = -EPROTO;
-
-done:
- if (wdata && wdata->result_cb)
- wdata->result_cb(err, wdata->user_data);
-}
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-static uint8_t proxy_write_cb(struct btd_attribute *attr,
- const uint8_t *value, size_t len,
- btd_attr_write_result_t result,
- void *user_data)
-#else
-static void proxy_write_cb(struct btd_attribute *attr,
- const uint8_t *value, size_t len,
- btd_attr_write_result_t result,
- void *user_data)
-#endif
-{
- GDBusProxy *proxy;
-
- proxy = g_hash_table_lookup(proxy_hash, attr);
- if (!proxy) {
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- return result(-ENOENT, user_data);
-#else
- result(-ENOENT, user_data);
- return;
-#endif
- }
-
- /*
- * "result" callback defines if the core wants to receive the
- * operation result, allowing to select ATT Write Request or Write
- * Command. Descriptors requires Write Request operation. For
- * Characteristics, the implementation will define which operations
- * are allowed based on the properties/flags.
- * TODO: Write Long Characteristics/Descriptors.
- */
-
- if (result) {
- struct proxy_write_data *wdata;
-
- wdata = g_new0(struct proxy_write_data, 1);
- wdata->result_cb = result;
- wdata->user_data = user_data;
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- btd_gatt_set_notify_indicate_flag(attr, FALSE);
-#endif
-
- if (!g_dbus_proxy_set_property_array(proxy, "Value",
- DBUS_TYPE_BYTE, value, len,
- proxy_write_reply,
- wdata, g_free)) {
- g_free(wdata);
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- return result(-ENOENT, user_data);
-#else
- result(-ENOENT, user_data);
- return;
-#endif
- }
- } else {
- /*
- * Caller is not interested in the Set method call result.
- * This flow implements the ATT Write Command scenario, where
- * the remote doesn't receive ATT response.
- */
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- btd_gatt_set_notify_indicate_flag(attr, FALSE);
-#endif
- g_dbus_proxy_set_property_array(proxy, "Value", DBUS_TYPE_BYTE,
- value, len, proxy_write_reply,
- NULL, NULL);
- }
-
- DBG("Server: Write attribute callback %s",
- g_dbus_proxy_get_path(proxy));
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- return 0;
-#endif
-
-}
-
-static int register_external_service(struct external_service *esvc,
- GDBusProxy *proxy)
-{
- DBusMessageIter iter;
- const char *str, *path, *iface;
- bt_uuid_t uuid;
-
- path = g_dbus_proxy_get_path(proxy);
- iface = g_dbus_proxy_get_interface(proxy);
- if (g_strcmp0(esvc->path, path) != 0 ||
- g_strcmp0(iface, GATT_SERVICE_IFACE) != 0)
- return -EINVAL;
-
- if (!g_dbus_proxy_get_property(proxy, "UUID", &iter))
- return -EINVAL;
-
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
- return -EINVAL;
-
- dbus_message_iter_get_basic(&iter, &str);
-
- if (bt_string_to_uuid(&uuid, str) < 0)
- return -EINVAL;
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- esvc->service = btd_gatt_add_service(&uuid, path);
-#else
- esvc->service = btd_gatt_add_service(&uuid);
-#endif
- if (!esvc->service)
- return -EINVAL;
-
- return 0;
-}
-
-static int add_char(GDBusProxy *proxy, const bt_uuid_t *uuid)
-{
- DBusMessageIter iter;
- struct btd_attribute *attr;
- btd_attr_write_t write_cb;
- btd_attr_read_t read_cb;
- uint8_t propmask = 0;
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- const char *path;
-#endif
-
- /*
- * Optional property. If is not informed, read and write
- * procedures will be allowed. Upper-layer should handle
- * characteristic requirements.
- */
- if (g_dbus_proxy_get_property(proxy, "Flags", &iter))
- propmask = flags_get_bitmask(&iter);
- else
- propmask = GATT_CHR_PROP_WRITE_WITHOUT_RESP
- | GATT_CHR_PROP_WRITE
- | GATT_CHR_PROP_READ;
- if (!propmask)
- return -EINVAL;
-
- if (propmask & GATT_CHR_PROP_READ)
- read_cb = proxy_read_cb;
- else
- read_cb = NULL;
-
- if (propmask & (GATT_CHR_PROP_WRITE | GATT_CHR_PROP_WRITE_WITHOUT_RESP))
- write_cb = proxy_write_cb;
- else
- write_cb = NULL;
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- path = g_dbus_proxy_get_path(proxy);
- attr = btd_gatt_add_char(uuid, propmask, path, read_cb, write_cb);
-#else
- attr = btd_gatt_add_char(uuid, propmask, read_cb, write_cb);
-#endif
- if (!attr)
- return -ENOMEM;
-
- g_hash_table_insert(proxy_hash, attr, g_dbus_proxy_ref(proxy));
-
- return 0;
-}
-
-static int add_char_desc(GDBusProxy *proxy, const bt_uuid_t *uuid)
-{
- struct btd_attribute *attr;
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- const char *path;
-#endif
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- path = g_dbus_proxy_get_path(proxy);
- attr = btd_gatt_add_char_desc(uuid, path, proxy_read_cb, proxy_write_cb);
-#else
- attr = btd_gatt_add_char_desc(uuid, proxy_read_cb, proxy_write_cb);
-#endif
- if (!attr)
- return -ENOMEM;
-
- g_hash_table_insert(proxy_hash, attr, g_dbus_proxy_ref(proxy));
-
- return 0;
-}
-
-static int register_external_characteristics(GSList *proxies)
-
-{
- GSList *list;
-
- for (list = proxies; list; list = g_slist_next(list)) {
- GDBusProxy *proxy = list->data;
- DBusMessageIter iter;
- bt_uuid_t uuid;
- const char *path, *iface, *str;
- int ret;
-
- /* Mandatory property */
- if (!g_dbus_proxy_get_property(proxy, "UUID", &iter))
- return -EINVAL;
-
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
- return -EINVAL;
-
- dbus_message_iter_get_basic(&iter, &str);
-
- if (bt_string_to_uuid(&uuid, str) < 0)
- return -EINVAL;
-
- iface = g_dbus_proxy_get_interface(proxy);
- path = g_dbus_proxy_get_path(proxy);
-
- if (!strcmp(GATT_CHR_IFACE, iface))
- ret = add_char(proxy, &uuid);
- else
- ret = add_char_desc(proxy, &uuid);
-
- if (ret < 0)
- return ret;
-
- DBG("Added GATT: %s (%s)", path, str);
- }
-
- return 0;
-}
-
-static void client_ready(GDBusClient *client, void *user_data)
-{
- struct external_service *esvc = user_data;
- GDBusProxy *proxy;
- DBusConnection *conn = btd_get_dbus_connection();
- DBusMessage *reply;
-
- if (!esvc->proxies)
- goto fail;
-
- proxy = esvc->proxies->data;
- if (register_external_service(esvc, proxy) < 0)
- goto fail;
-
- if (register_external_characteristics(g_slist_next(esvc->proxies)) < 0)
- goto fail;
-
- DBG("Added GATT service %s", esvc->path);
-
- reply = dbus_message_new_method_return(esvc->reg);
- g_dbus_send_message(conn, reply);
-
- dbus_message_unref(esvc->reg);
- esvc->reg = NULL;
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- btd_gatt_update_attr_db();
-#endif
-
- return;
-
-fail:
- error("Could not register external service: %s", esvc->path);
-
- /*
- * Set callback to NULL to avoid potential race condition
- * when calling remove_service and GDBusClient unref.
- */
- g_dbus_client_set_disconnect_watch(esvc->client, NULL, NULL);
-
- remove_service(conn, esvc);
-
- reply = btd_error_invalid_args(esvc->reg);
- g_dbus_send_message(conn, reply);
-}
-
-static struct external_service *external_service_new(DBusConnection *conn,
- DBusMessage *msg, const char *path)
-{
- struct external_service *esvc;
- GDBusClient *client;
- const char *sender = dbus_message_get_sender(msg);
-
- client = g_dbus_client_new(conn, sender, "/");
- if (!client)
- return NULL;
-
- esvc = g_new0(struct external_service, 1);
- esvc->owner = g_strdup(sender);
- esvc->reg = dbus_message_ref(msg);
- esvc->client = client;
- esvc->path = g_strdup(path);
-
- g_dbus_client_set_disconnect_watch(client, remove_service, esvc);
-
- g_dbus_client_set_proxy_handlers(client, proxy_added, proxy_removed,
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- proxy_prop_changed, esvc);
-#else
- NULL, esvc);
-#endif
-
- g_dbus_client_set_ready_watch(client, client_ready, esvc);
-
- return esvc;
-}
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-static DBusMessage *get_service(DBusConnection *conn,
- DBusMessage *msg, void *user_data)
-{
- char *uuid_str = NULL;
- bt_uuid_t uuid;
- char *path = NULL;
- DBusMessage *reply = NULL;
-
- if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &uuid_str,
- DBUS_TYPE_INVALID))
- return btd_error_invalid_args(msg);
-
- if (bt_string_to_uuid(&uuid, uuid_str) < 0)
- return btd_error_invalid_args(msg);
-
- path = btd_get_service_path(uuid);
- if (path)
- reply = service_append_dict(uuid, msg);
- else
- reply = btd_error_failed(msg, "Service Not Registered");
-
- return reply;
-}
-#endif
-
-static DBusMessage *register_service(DBusConnection *conn,
- DBusMessage *msg, void *user_data)
-{
- struct external_service *esvc;
- DBusMessageIter iter;
- const char *path;
-
- if (!dbus_message_iter_init(msg, &iter))
- return btd_error_invalid_args(msg);
-
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH)
- return btd_error_invalid_args(msg);
-
- dbus_message_iter_get_basic(&iter, &path);
-
- if (g_slist_find_custom(external_services, path,
- external_service_path_cmp))
- return btd_error_already_exists(msg);
-
- esvc = external_service_new(conn, msg, path);
- if (!esvc)
- return btd_error_failed(msg, "Not enough resources");
-
- external_services = g_slist_prepend(external_services, esvc);
-
- DBG("New service %p: %s", esvc, path);
-
- return NULL;
-}
-
-static DBusMessage *unregister_service(DBusConnection *conn,
- DBusMessage *msg, void *user_data)
-{
- struct external_service *esvc;
- DBusMessageIter iter;
- const char *path;
- GSList *list;
-
- if (!dbus_message_iter_init(msg, &iter))
- return btd_error_invalid_args(msg);
-
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH)
- return btd_error_invalid_args(msg);
-
- dbus_message_iter_get_basic(&iter, &path);
-
- list = g_slist_find_custom(external_services, path,
- external_service_path_cmp);
- if (!list)
- return btd_error_does_not_exist(msg);
-
- esvc = list->data;
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- if (strcmp(dbus_message_get_sender(msg), esvc->owner))
-#else
- if (!strcmp(dbus_message_get_sender(msg), esvc->owner))
-#endif
- return btd_error_does_not_exist(msg);
-
- /*
- * Set callback to NULL to avoid potential race condition
- * when calling remove_service and GDBusClient unref.
- */
- g_dbus_client_set_disconnect_watch(esvc->client, NULL, NULL);
-
- remove_service(conn, esvc);
-
- return dbus_message_new_method_return(msg);
-}
-
-static const GDBusMethodTable methods[] = {
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- { GDBUS_ASYNC_METHOD("RegisterService",
-#else
- { GDBUS_EXPERIMENTAL_ASYNC_METHOD("RegisterService",
-#endif
- GDBUS_ARGS({ "service", "o"},
- { "options", "a{sv}"}),
- NULL, register_service) },
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- { GDBUS_METHOD("UnregisterService",
-#else
- { GDBUS_EXPERIMENTAL_METHOD("UnregisterService",
-#endif
- GDBUS_ARGS({"service", "o"}),
- NULL, unregister_service) },
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- { GDBUS_METHOD("GetService",
-#else
- { GDBUS_EXPERIMENTAL_METHOD("GetService",
-#endif
- GDBUS_ARGS({ "uuid", "s"}),
- GDBUS_ARGS({ "service", "a{sv}"})
- , get_service) },
- { }
-};
-
-gboolean gatt_dbus_manager_register(void)
-{
- if (!g_dbus_register_interface(btd_get_dbus_connection(),
- "/org/bluez", GATT_MGR_IFACE,
- methods, NULL, NULL, NULL, NULL))
- return FALSE;
-
- proxy_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
- NULL, (GDestroyNotify) g_dbus_proxy_unref);
-
- return TRUE;
-}
-
-void gatt_dbus_manager_unregister(void)
-{
- /* We might not have initialized if experimental features are
- * not enabled.
- */
- if (!proxy_hash)
- return;
-
- g_hash_table_destroy(proxy_hash);
- proxy_hash = NULL;
-
- g_slist_free_full(external_services, external_service_free);
-
- g_dbus_unregister_interface(btd_get_dbus_connection(), "/org/bluez",
- GATT_MGR_IFACE);
-}
-
-#endif
+++ /dev/null
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2014 Instituto Nokia de Tecnologia - INdT
- *
- *
- * 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
- *
- */
-
-gboolean gatt_dbus_manager_register(void);
-void gatt_dbus_manager_unregister(void);
-
-#endif
+++ /dev/null
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2014 Instituto Nokia de Tecnologia - INdT
- *
- *
- * 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 <glib.h>
-#include <stdbool.h>
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-#include <errno.h>
-#include <dbus/dbus.h>
-#include <gdbus/gdbus.h>
-#endif
-
-#include "log.h"
-#include "lib/uuid.h"
-#include "attrib/att.h"
-#include "src/shared/util.h"
-
-#include "gatt-dbus.h"
-#include "gatt.h"
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-#include "adapter.h"
-#include "attrib/gatt-service.h"
-#include "attrib/att-database.h"
-#include "attrib/gattrib.h"
-#include "attrib/gatt.h"
-#include "src/attrib-server.h"
-#include "src/device.h"
-#include "dbus-common.h"
-#endif
-
-/* Common GATT UUIDs */
-static const bt_uuid_t primary_uuid = { .type = BT_UUID16,
- .value.u16 = GATT_PRIM_SVC_UUID };
-
-static const bt_uuid_t chr_uuid = { .type = BT_UUID16,
- .value.u16 = GATT_CHARAC_UUID };
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-
-#define ATT_CHAR_READ_VALUE 0x01
-#define ATT_CHAR_RD_WRT_CB 0x02
-#define GATT_TYPE_PRIM_SVC 0x01
-#define GATT_TYPE_CHARAC_SVC 0x02
-#define GATT_TYPE_CHARAC_VALUE 0x03
-#define GATT_TYPE_DESC_CCC 0x04
-#define GATT_TYPE_DESC_USR 0x05
-#endif
-
-struct btd_attribute {
- uint16_t handle;
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- uint16_t attr_start_handle;
- uint16_t attr_end_handle;
- bool notify_indicate;
- char *path;
-#endif
- bt_uuid_t type;
- btd_attr_read_t read_cb;
- btd_attr_write_t write_cb;
- uint16_t value_len;
- uint8_t value[0];
-};
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-struct pending_hndl {
- uint16_t handle;
- uint16_t type;
- struct pending_hndl *next;
-};
-
-static struct pending_hndl *hndl_list_head = NULL;
-static struct pending_hndl *hndl_list = NULL;
-#endif
-
-static GList *local_attribute_db;
-static uint16_t next_handle = 0x0001;
-
-static inline void put_uuid_le(const bt_uuid_t *src, void *dst)
-{
- if (src->type == BT_UUID16)
- put_le16(src->value.u16, dst);
- else if (src->type == BT_UUID32)
- put_le32(src->value.u32, dst);
- else
- /* Convert from 128-bit BE to LE */
- bswap_128(&src->value.u128, dst);
-}
-
-/*
- * Helper function to create new attributes containing constant/static values.
- * eg: declaration of services/characteristics, and characteristics with
- * fixed values.
- */
-static struct btd_attribute *new_const_attribute(const bt_uuid_t *type,
- const uint8_t *value,
- uint16_t len)
-{
- struct btd_attribute *attr;
-
- attr = malloc0(sizeof(struct btd_attribute) + len);
- if (!attr)
- return NULL;
-
- attr->type = *type;
- memcpy(&attr->value, value, len);
- attr->value_len = len;
-
- return attr;
-}
-
-static struct btd_attribute *new_attribute(const bt_uuid_t *type,
- btd_attr_read_t read_cb,
- btd_attr_write_t write_cb)
-{
- struct btd_attribute *attr;
-
- attr = new0(struct btd_attribute, 1);
- if (!attr)
- return NULL;
-
- attr->type = *type;
- attr->read_cb = read_cb;
- attr->write_cb = write_cb;
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- attr->notify_indicate = TRUE;
-#endif
-
- return attr;
-}
-
-static bool is_service(const struct btd_attribute *attr)
-{
- if (attr->type.type != BT_UUID16)
- return false;
-
- if (attr->type.value.u16 == GATT_PRIM_SVC_UUID ||
- attr->type.value.u16 == GATT_SND_SVC_UUID)
- return true;
-
- return false;
-}
-
-static int local_database_add(uint16_t handle, struct btd_attribute *attr)
-{
- attr->handle = handle;
-
- local_attribute_db = g_list_append(local_attribute_db, attr);
-
- return 0;
-}
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-static int attr_uuid_cmp(gconstpointer a, gconstpointer b)
-{
- const struct btd_attribute *attrib1 = a;
- const bt_uuid_t *uuid = b;
-
- if (attrib1->type.value.u16 != GATT_PRIM_SVC_UUID) {
- return bt_uuid_cmp(&attrib1->type, uuid);
- } else {
- bt_uuid_t prim_uuid;
- prim_uuid = att_get_uuid(attrib1->value, attrib1->value_len);
-
- return bt_uuid_cmp(&prim_uuid, uuid);
- }
-}
-
-static int handle_cmp(gconstpointer a, gconstpointer b)
-{
- const struct btd_attribute *attrib = a;
- uint16_t handle = GPOINTER_TO_UINT(b);
-
- return attrib->handle - handle;
-}
-
-static int attribute_cmp(gconstpointer a1, gconstpointer a2)
-{
- const struct btd_attribute *attrib1 = a1;
- const struct btd_attribute *attrib2 = a2;
-
- return attrib1->handle - attrib2->handle;
-}
-
-static void store_start_end_handle(bt_uuid_t *uuid, uint16_t start_handle,
- uint16_t end_handle)
-{
- GList *l;
- struct btd_attribute *attrib;
-
- l = g_list_find_custom(local_attribute_db, GUINT_TO_POINTER(uuid),
- attr_uuid_cmp);
-
- if (!l)
- return;
-
- attrib = l->data;
- attrib->attr_start_handle = start_handle;
- attrib->attr_end_handle = end_handle;
-
- local_attribute_db = g_list_insert_sorted (local_attribute_db, attrib, attribute_cmp);
-
- return;
-}
-
-static void get_start_end_handle(bt_uuid_t *uuid, uint16_t *start_handle,
- uint16_t *end_handle)
-{
- GList *l;
- struct btd_attribute *attrib;
-
- l = g_list_find_custom(local_attribute_db, GUINT_TO_POINTER(uuid),
- attr_uuid_cmp);
-
-
- if (!l)
- return;
-
- attrib = l->data;
- *start_handle = attrib->attr_start_handle;
- *end_handle = attrib->attr_end_handle;
-}
-
-static struct btd_attribute *find_local_attr(bt_uuid_t *uuid)
-{
- GList *l;
-
- l = g_list_find_custom(local_attribute_db,
- GUINT_TO_POINTER(uuid),
- attr_uuid_cmp);
-
- if (!l)
- return NULL;
-
- return l->data;
-}
-
-static uint8_t read_result(int err, uint8_t *value, size_t len,
- void *user_data)
-{
- struct attribute *a = user_data;
- struct btd_adapter *adapter;
- uint8_t status = 0;
-
- adapter = btd_adapter_get_default();
- if (!adapter)
- return FALSE;
-
- if (!err)
- status = attrib_db_update(adapter, a->handle,
- NULL, value, len, NULL);
- else {
- return err;
- }
- return status;
-}
-
-static uint8_t read_desc_attr_db_value(struct attribute *a,
- struct btd_device *device,
- gpointer user_data)
-{
- struct btd_attribute *local_attr;
- uint8_t status = 0;
-
- local_attr = find_local_attr(&a->uuid);
- if (local_attr && local_attr->read_cb) {
- bdaddr_t *bdaddr = (bdaddr_t *)device_get_address(device);
- status = local_attr->read_cb(local_attr, bdaddr, read_result, a);
- } else
- return -ENOENT;
-
- return status;
-}
-
-static uint8_t read_char_attr_db_value(struct attribute *a,
- struct btd_device *device,
- gpointer user_data)
-{
- struct btd_attribute *local_attr;
- uint8_t status = 0;
-
- local_attr = find_local_attr(&a->uuid);
- if (local_attr && local_attr->read_cb) {
- bdaddr_t *bdaddr = (bdaddr_t *)device_get_address(device);
- status = local_attr->read_cb(local_attr, bdaddr, read_result, a);
- } else
- return -ENOENT;
-
- return status;
-}
-
-static uint8_t write_char_attr_db_value(struct attribute *a,
- struct btd_device *device,
- gpointer user_data)
-{
- struct btd_attribute *local_attr;
- uint8_t status = 0;
- void *ptr = (uint8_t *)a->data;
-
- local_attr = find_local_attr(&a->uuid);
- if (local_attr && local_attr->write_cb) {
- if (a->data) {
- status = local_attr->write_cb(local_attr, ptr,
- a->len, NULL, a);
- }
- } else
- return -ENOENT;
-
- return status;
-}
-
-static void free_pending_hndl_list(void)
-{
- struct pending_hndl *temp_pending_hndl_list = NULL;
-
- /* Traverse through handl list and free the list
- after atribute data base is updated */
- if (hndl_list_head) {
- hndl_list = hndl_list_head;
- temp_pending_hndl_list = hndl_list_head;
- while(temp_pending_hndl_list) {
- hndl_list = hndl_list->next;
- g_free(temp_pending_hndl_list);
- temp_pending_hndl_list = hndl_list;
- }
-
- hndl_list_head = NULL;
- }
-}
-
-static unsigned int get_attr_char_size(void)
-{
- GList *l;
- uint16_t nex_hndl = 0x0001;
- struct pending_hndl *temp_list;
- unsigned int attr_size = 0;
-
- /* Calculate the size of the char attributes to be added to attribute DB */
- for (temp_list = hndl_list_head; temp_list != NULL;
- temp_list = temp_list->next) {
- l = g_list_find_custom(local_attribute_db,
- GUINT_TO_POINTER(nex_hndl),
- handle_cmp);
- if (l) {
- if (temp_list->type == GATT_TYPE_CHARAC_SVC) {
- attr_size += 2;
- }
- }
- if (temp_list->next)
- nex_hndl = temp_list->next->handle;
- }
- return attr_size;
-}
-
-static unsigned int get_attr_desc_size(void)
-{
- GList *l;
- uint16_t nex_hndl = 0x0001;
- struct pending_hndl *temp_list;
- unsigned int attr_size = 0;
-
- for (temp_list = hndl_list_head; temp_list != NULL;
- temp_list = temp_list->next) {
- l = g_list_find_custom(local_attribute_db,
- GUINT_TO_POINTER(nex_hndl),
- handle_cmp);
- if (l) {
- if (temp_list->type == GATT_TYPE_DESC_USR)
- attr_size += 1;
- }
- if (temp_list->next)
- nex_hndl = temp_list->next->handle;
- }
- return attr_size;
-}
-
-static int is_connected(gpointer a1, gpointer a2)
-{
- const struct btd_device *dev = a1;
-
- if (device_get_gatt_connected(dev))
- return 0;
- else
- return -1;
-}
-
-bool gatt_send_service_changed_ind(struct btd_adapter *adapter, bt_uuid_t *uuid,
- uint16_t start_handle, uint16_t end_handle)
-{
- GAttrib *attrib;
- GList *l, *connections;
- size_t len;
- struct btd_device *dev;
-
- DBG("+");
- connections = (GList *)btd_adapter_get_connections(adapter);
-
- do {
- l = g_list_find_custom(connections, GUINT_TO_POINTER(NULL),
- (GCompareFunc)is_connected);
-
- if (l) {
- dev = l->data;
- if (device_is_trusted(dev)) {
- attrib = attrib_from_device(dev);
- /* Send the service changed indication */
- len = (sizeof(uint16_t) * (end_handle - start_handle));
- attrib_send_sc_ind(dev, attrib, start_handle,
- end_handle, len);
- g_attrib_unref(attrib);
- }
- connections = (GList *)g_slist_next(connections);
- } else
- break;
- } while(l);
-
- return TRUE;
-}
-
-uint16_t send_sc_indication(uint16_t start_handle, uint16_t end_handle, size_t vlen,
- uint8_t *pdu, size_t len)
-{
- const uint16_t min_len = sizeof(pdu[0]) + sizeof(uint16_t);
-
- if (pdu == NULL)
- return 0;
-
- if (len < (vlen + min_len))
- return 0;
-
- pdu[0] = ATT_OP_HANDLE_IND;
-/* API replaced by put_le16 in bluez 5.25
- att_put_u16(start_handle, &pdu[1]);
- att_put_u16(end_handle, &pdu[3]);*/
- put_le16(start_handle, &pdu[1]);
- put_le16(end_handle, &pdu[3]);
-
- return vlen + min_len;
-}
-
-bool btd_gatt_update_attr_db(void)
-{
- GList *l;
- uint16_t nex_hndl = 0x0001;
- struct pending_hndl *temp_list;
- struct btd_attribute *local_attr;
- struct btd_attribute *temp_att = NULL;
- gboolean svc_added;
- bt_uuid_t prim_uuid;
- bt_uuid_t char_uuid = {0};
- struct btd_adapter *adapter;
- uint8_t char_attr_size = 0, usr_desc_attr_size = 0, total_attr_size = 0;
- uint16_t start_handle, end_handle, next_handle;
- bool new_service_add = FALSE;
- bool new_char_desc_add = FALSE;
-
- adapter = btd_adapter_get_default();
- if (!adapter)
- return FALSE;
-
- if (!hndl_list_head)
- return FALSE;
-
- nex_hndl = hndl_list_head->handle;
- for (temp_list = hndl_list_head; temp_list != NULL;
- temp_list = temp_list->next) {
- l = g_list_find_custom(local_attribute_db,
- GUINT_TO_POINTER(nex_hndl), handle_cmp);
- if (!l)
- continue;
-
- local_attr = l->data;
- /* get the characterisitic attribute, from local DB */
- if (local_attr->type.value.u16 == GATT_PRIM_SVC_UUID &&
- temp_list->type == GATT_TYPE_PRIM_SVC) {
- new_service_add = FALSE;
- prim_uuid = att_get_uuid(local_attr->value,
- local_attr->value_len);
- char_attr_size = get_attr_char_size();
- usr_desc_attr_size = get_attr_desc_size();
- total_attr_size = char_attr_size + usr_desc_attr_size + 1;
- /* Store the primary service */
- next_handle = gatt_prim_service_add(adapter,
- GATT_PRIM_SVC_UUID, &prim_uuid,
- total_attr_size, &start_handle);
- new_char_desc_add = TRUE;
- } else if ((local_attr->type.value.u16 == GATT_CHARAC_UUID ||
- temp_list->type == GATT_TYPE_CHARAC_VALUE) &&
- new_char_desc_add) {
- /* get the characterisitic attribute, from local DB */
- if (!temp_att) {
- void *ptr = (uint8_t *)local_attr->value;
- uint8_t value[local_attr->value_len];
- memcpy(value, ptr, local_attr->value_len);
- temp_att = new_const_attribute(&local_attr->type,
- value, local_attr->value_len);
- if (!temp_att)
- return FALSE;
-
- temp_att->value_len = local_attr->value_len;
- temp_att->write_cb = local_attr->write_cb;
- temp_att->read_cb= local_attr->read_cb;
- }
- char_uuid = local_attr->type;
-
- if (temp_list->type == GATT_TYPE_CHARAC_VALUE) {
- /* Store the Characteristic attribute */
- svc_added = gatt_add_characteristic(adapter,
- &next_handle, next_handle,
- GATT_OPT_CHR_UUID, &char_uuid,
- GATT_OPT_CHR_PROPS,
- temp_att->value[0],
- GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
- read_char_attr_db_value, adapter,
- GATT_OPT_CHR_VALUE_CB, ATTRIB_WRITE,
- write_char_attr_db_value, adapter,
- GATT_OPT_INVALID);
-
- end_handle = next_handle - 1;
- if (!svc_added) {
- new_service_add = FALSE;
- new_char_desc_add = FALSE;
- /* Fix : RESOURCE_LEAK */
- if (temp_att) {
- free(temp_att);
- temp_att = NULL;
- }
- break;
- } else {
- new_service_add = TRUE;
- }
- } else if (local_attr->type.value.u16 == GATT_CHARAC_UUID) {
- continue;
- }
- /* Fix : RESOURCE_LEAK */
- if (temp_att) {
- free(temp_att);
- temp_att = NULL;
- }
- } else if (temp_list->type == GATT_TYPE_DESC_USR &&
- new_char_desc_add) {
- bt_uuid_t desc_uuid;
-
- if (local_attr->type.type == BT_UUID16) {
- get_uuid(BT_UUID16, &local_attr->type.value.u16,
- &desc_uuid);
- } else if (local_attr->type.type == BT_UUID32) {
- get_uuid(BT_UUID32, &local_attr->type.value.u32,
- &desc_uuid);
- } else {
- /* Since, get_uuid converts the 128 bit UUID
- * to LE and descriptor UUID is not converted
- * to LE while adding to local data base.
- * We can just copy the UUID directly from
- * local data base. */
-
- memcpy(&desc_uuid.value.u128,
- &local_attr->type.value.u128, 16);
- desc_uuid.type = BT_UUID128;
- }
- svc_added = gatt_add_descriptor(adapter,
- &next_handle, next_handle,
- GATT_OPT_DESC_UUID, &desc_uuid,
- GATT_OPT_DESC_VALUE_CB, ATTRIB_READ,
- read_desc_attr_db_value, adapter,
- GATT_OPT_INVALID);
- end_handle = next_handle - 1;
- if (!svc_added) {
- new_service_add = FALSE;
- break;
- } else {
- new_service_add = TRUE;
- }
- }
-
- if (temp_list->next)
- nex_hndl = temp_list->next->handle;
- }
- if (new_service_add) {
- DBG("Service Added");
- store_start_end_handle(&prim_uuid, start_handle, end_handle);
- } else {
- DBG("Failed to add service");
- start_handle = 0;
- end_handle = 0;
- /* Remove the service from attrib database */
- get_start_end_handle(&prim_uuid, &start_handle, &end_handle);
- attrib_remove_service(adapter, start_handle, end_handle);
- }
- gatt_send_service_changed_ind(adapter, &prim_uuid, start_handle,
- end_handle);
- free_pending_hndl_list();
-
- return TRUE;
-}
-
-char *btd_get_service_path(bt_uuid_t uuid)
-{
- GList *l;
- struct btd_attribute *attrib;
-
- l = g_list_find_custom(local_attribute_db, GUINT_TO_POINTER(&uuid),
- attr_uuid_cmp);
-
- if (!l)
- return NULL;
-
- attrib = l->data;
- return attrib->path;
-}
-
-const char *btd_get_attrib_path(struct btd_attribute *attrib)
-{
- if(attrib)
- return attrib->path;
- else
- return NULL;
-}
-
-const char *btd_find_service_from_attr(struct btd_attribute *attrib)
-{
- struct btd_attribute *svc_attrib = NULL;
- GList *list;
-
- for (list = local_attribute_db; list; list = g_list_next(list)) {
- struct btd_attribute *attr = list->data;
- if (attr && (attr->type.value.u16 == GATT_PRIM_SVC_UUID ||
- attr->type.value.u16 == GATT_SND_SVC_UUID)) {
- svc_attrib = attr;
- } else {
- if (attr && !attribute_cmp(attrib, attr))
- break;
- else
- continue;
- }
- }
- if (svc_attrib)
- return svc_attrib->path;
- else
- return NULL;
-}
-DBusMessage *service_append_dict(bt_uuid_t uuid, DBusMessage *msg)
-{
- GList *list;
- DBusMessage *reply = NULL;
- DBusMessageIter iter;
- DBusMessageIter dict;
- static int n_char = 1;
- bool service_found = FALSE;
-
- list = g_list_find_custom(local_attribute_db, GUINT_TO_POINTER(&uuid),
- attr_uuid_cmp);
-
- if (!list)
- return NULL;
-
- 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);
-
- for (; list; list = g_list_next(list)) {
- struct btd_attribute *attrib = list->data;
- if (attrib->type.value.u16 == GATT_PRIM_SVC_UUID && !service_found) {
-
- service_found = TRUE;
- if (attrib->path) {
-
- dict_append_entry(&dict, "Service", DBUS_TYPE_OBJECT_PATH,
- &attrib->path);
- } else
- return NULL;
- } else if (attrib->type.value.u16 == GATT_CHARAC_UUID && service_found) {
-
- if (attrib->path) {
-
- gchar *key = g_strdup_printf("Characteristic%d", n_char++);
- dict_append_entry(&dict, key, DBUS_TYPE_OBJECT_PATH,
- &attrib->path);
- g_free(key);
- }
- } else if (attrib->type.value.u16 == GATT_CHARAC_USER_DESC_UUID && service_found) {
-
- if (attrib->path) {
-
- gchar *key = g_strdup("Descriptor");
- dict_append_entry(&dict, key, DBUS_TYPE_OBJECT_PATH,
- &attrib->path);
- g_free(key);
- }
- } else if (attrib->type.value.u16 == GATT_PRIM_SVC_UUID && service_found) {
- break;
- }
- }
- dbus_message_iter_close_container(&iter, &dict);
- return reply;
-}
-
-static void remove_attr_service(struct btd_attribute *service)
-{
- uint16_t start_handle = 0, end_handle = 0;
- bt_uuid_t prim_uuid;
- struct btd_adapter *adapter;
-
- adapter = btd_adapter_get_default();
- if (!adapter)
- return;
-
- prim_uuid = att_get_uuid(service->value, service->value_len);
- get_start_end_handle(&prim_uuid, &start_handle, &end_handle);
- attrib_remove_service(adapter, start_handle, end_handle);
- gatt_send_service_changed_ind(adapter, &prim_uuid, start_handle, end_handle);
-}
-
-void btd_gatt_set_notify_indicate_flag(struct btd_attribute *attrib,
- bool notify_indicate)
-{
- attrib->notify_indicate = notify_indicate;
- local_attribute_db = g_list_insert_sorted (local_attribute_db, attrib,
- attribute_cmp);
-}
-
-#if 0
-gboolean gatt_register_internet_protocol_service(struct btd_adapter *adapter)
-{
- bt_uuid_t uuid;
-
- bt_uuid16_create(&uuid, GATT_IPSP_UUID);
-
- return gatt_service_add(adapter, GATT_PRIM_SVC_UUID, &uuid,
- GATT_OPT_INVALID);
-}
-
-gboolean gatt_unregister_internet_protocol_service(struct btd_adapter *adapter)
-{
- bt_uuid_t uuid;
- struct attribute *a;
-
- bt_uuid16_create(&uuid, GATT_IPSP_UUID);
-
- a = attribute_find(adapter, &uuid);
- if (!a) {
- error("Attribute not found for handle");
- return FALSE;
- }
-
- if (attrib_db_del(adapter, a->handle) < 0) {
- error("Can't delete handle 0x%04x", a->handle);
- return FALSE;
- }
- return TRUE;
-}
-#endif
-#endif
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid,
- const char *path)
-#else
-struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid)
-#endif
-{
- struct btd_attribute *attr;
- uint16_t len = bt_uuid_len(uuid);
- uint8_t value[len];
-
- /*
- * Service DECLARATION
- *
- * TYPE ATTRIBUTE VALUE
- * +-------+---------------------------------+
- * |0x2800 | 0xYYYY... |
- * | (1) | (2) |
- * +------+----------------------------------+
- * (1) - 2 octets: Primary/Secondary Service UUID
- * (2) - 2 or 16 octets: Service UUID
- */
-
- /* Set attribute value */
- put_uuid_le(uuid, value);
-
- attr = new_const_attribute(&primary_uuid, value, len);
- if (!attr)
- return NULL;
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- attr->path = g_strdup(path);
- /* Store the primary handle in linkedlist,
- * later this list shall be used to add the attributes to DB */
- if (!hndl_list) {
- hndl_list = g_new0(struct pending_hndl, 1);
- hndl_list_head = hndl_list;
- hndl_list->type = GATT_TYPE_PRIM_SVC;
- hndl_list->handle = next_handle;
- hndl_list->next = NULL;
- }
-#endif
-
- if (local_database_add(next_handle, attr) < 0) {
- free(attr);
- return NULL;
- }
-
- /* TODO: missing overflow checking */
- next_handle = next_handle + 1;
-
- return attr;
-}
-
-void btd_gatt_remove_service(struct btd_attribute *service)
-{
- GList *list = g_list_find(local_attribute_db, service);
- bool first_node;
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- struct btd_attribute *attrib_rmv = NULL;
-#endif
-
- if (!list)
- return;
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- attrib_rmv = list->data;
-
- /* Remove the service from Attrib database */
- remove_attr_service(attrib_rmv);
-#endif
-
- first_node = local_attribute_db == list;
-
- /* Remove service declaration attribute */
- free(list->data);
- list = g_list_delete_link(list, list);
-
- /* Remove all characteristics until next service declaration */
- while (list && !is_service(list->data)) {
-#ifndef TIZEN_FEATURE_BLUEZ_MODIFY
- free(list->data);
-#endif
- list = g_list_delete_link(list, list);
- }
-
- /*
- * When removing the first node, local attribute database head
- * needs to be updated. Node removed from middle doesn't change
- * the list head address.
- */
- if (first_node)
- local_attribute_db = list;
-}
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-bool btd_gatt_update_char(const bt_uuid_t *uuid, uint8_t *value, size_t len)
-{
- GList *l;
- struct btd_attribute *attrib;
- struct btd_adapter *adapter;
- uint8_t properties;
- bool notify_indicate;
-
- adapter = btd_adapter_get_default();
- if (!adapter)
- return FALSE;
-
- l = g_list_find_custom(local_attribute_db, GUINT_TO_POINTER(uuid),
- attr_uuid_cmp);
-
- if (!l)
- return FALSE;
-
- attrib = l->data;
- notify_indicate = attrib->notify_indicate;
- local_attribute_db = g_list_insert_sorted (local_attribute_db, attrib, attribute_cmp);
-
- l = g_list_find_custom(local_attribute_db,
- GUINT_TO_POINTER(attrib->handle - 1),
- handle_cmp);
-
- if (!l)
- return FALSE;
-
- attrib = l->data;
- properties = attrib->value[0];
-
- if (gatt_update_db(adapter, uuid, value, len)) {
- /* Attrib database is updated successfully */
-
- /* check if the characteristic properties are
- * set to send notification or indication */
- if (properties & (GATT_CHR_PROP_NOTIFY
- | GATT_CHR_PROP_INDICATE)) {
- /* Since characteristic is updated, and the
- * property is set to notify to indicate, find
- * the descreiptor UUID for notification and indication */
- if (notify_indicate == FALSE) {
- l = g_list_find_custom(local_attribute_db,
- GUINT_TO_POINTER(attrib->handle + 1),
- handle_cmp);
-
- if (!l)
- return FALSE;
- attrib = l->data;
- btd_gatt_set_notify_indicate_flag(attrib, TRUE);
- } else {
- gatt_send_noty_ind(adapter, uuid, value, len);
- }
- }
- }
- return TRUE;
-}
-#endif
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-struct btd_attribute *btd_gatt_add_char(const bt_uuid_t *uuid,
- uint8_t properties,
- const char *path,
- btd_attr_read_t read_cb,
- btd_attr_write_t write_cb)
-#else
-struct btd_attribute *btd_gatt_add_char(const bt_uuid_t *uuid,
- uint8_t properties,
- btd_attr_read_t read_cb,
- btd_attr_write_t write_cb)
-#endif
-{
- struct btd_attribute *char_decl, *char_value = NULL;
-
- /* Attribute value length */
- uint16_t len = 1 + 2 + bt_uuid_len(uuid);
- uint8_t value[len];
-
- /*
- * Characteristic DECLARATION
- *
- * TYPE ATTRIBUTE VALUE
- * +-------+---------------------------------+
- * |0x2803 | 0xXX 0xYYYY 0xZZZZ... |
- * | (1) | (2) (3) (4) |
- * +------+----------------------------------+
- * (1) - 2 octets: Characteristic declaration UUID
- * (2) - 1 octet : Properties
- * (3) - 2 octets: Handle of the characteristic Value
- * (4) - 2 or 16 octets: Characteristic UUID
- */
-
- value[0] = properties;
-
- /*
- * Since we don't know yet the characteristic value attribute
- * handle, we skip and set it later.
- */
- put_uuid_le(uuid, &value[3]);
-
- char_decl = new_const_attribute(&chr_uuid, value, len);
- if (!char_decl)
- goto fail;
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- char_decl->path = g_strdup(path);
-#endif
-
- char_value = new_attribute(uuid, read_cb, write_cb);
- if (!char_value)
- goto fail;
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- char_value->path = g_strdup(path);
-#endif
-
- if (local_database_add(next_handle, char_decl) < 0)
- goto fail;
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- /* Store the char decl handle in linkedlist,
- * later this list shall be used to add the attributes to DB */
- if (hndl_list && hndl_list->next == NULL) {
- hndl_list->next = g_new0(struct pending_hndl, 1);
- hndl_list = hndl_list->next;
- hndl_list->type = GATT_TYPE_CHARAC_SVC;
- hndl_list->handle = next_handle;
- hndl_list->next = NULL;
- }
-#endif
-
- next_handle = next_handle + 1;
-
- /*
- * Characteristic VALUE
- *
- * TYPE ATTRIBUTE VALUE
- * +----------+---------------------------------+
- * |0xZZZZ... | 0x... |
- * | (1) | (2) |
- * +----------+---------------------------------+
- * (1) - 2 or 16 octets: Characteristic UUID
- * (2) - N octets: Value is read dynamically from the service
- * implementation (external entity).
- */
-
- if (local_database_add(next_handle, char_value) < 0)
- /* TODO: remove declaration */
- goto fail;
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- /* Store the char value handle in linkedlist,
- * later this list shall be used to add the attributes to DB */
- if (hndl_list && hndl_list->next == NULL) {
- hndl_list->next = g_new0(struct pending_hndl, 1);
- hndl_list = hndl_list->next;
- hndl_list->type = GATT_TYPE_CHARAC_VALUE;
- hndl_list->handle = next_handle;
- hndl_list->next = NULL;
- }
-#endif
-
- next_handle = next_handle + 1;
-
- /*
- * Update characteristic value handle in characteristic declaration
- * attribute. For local attributes, we can assume that the handle
- * representing the characteristic value will get the next available
- * handle. However, for remote attribute this assumption is not valid.
- */
- put_le16(char_value->handle, &char_decl->value[1]);
-
- return char_value;
-
-fail:
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- /* Fix : RESOURCE_LEAK */
- if (char_decl != NULL && char_decl->path != NULL)
- g_free(char_decl->path);
- if (char_decl)
- free(char_decl);
- if (char_value)
- g_free(char_value);
-#else
- free(char_decl);
- free(char_value);
-#endif
-
- return NULL;
-}
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-struct btd_attribute *btd_gatt_add_char_desc(const bt_uuid_t *uuid,
- const char *path,
- btd_attr_read_t read_cb,
- btd_attr_write_t write_cb)
-#else
-struct btd_attribute *btd_gatt_add_char_desc(const bt_uuid_t *uuid,
- btd_attr_read_t read_cb,
- btd_attr_write_t write_cb)
-#endif
-{
- struct btd_attribute *attr;
-
- /*
- * From Core SPEC 4.1 page 2184:
- * "Characteristic descriptor declaration permissions are defined by a
- * higher layer profile or are implementation specific. A client shall
- * not assume all characteristic descriptor declarations are readable."
- *
- * The read/write callbacks presence will define the descriptor
- * permissions managed directly by the core. The upper layer can define
- * additional permissions constraints.
- */
-
- attr = new_attribute(uuid, read_cb, write_cb);
- if (!attr)
- return NULL;
-
- if (local_database_add(next_handle, attr) < 0) {
- free(attr);
- return NULL;
- }
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- attr->path = g_strdup(path);
-
- /* Store the store handle in linkedlist,
- * later this list shall be used to add the attributes to DB */
- if (hndl_list && hndl_list->next == NULL) {
- hndl_list->next = g_new0(struct pending_hndl, 1);
- hndl_list = hndl_list->next;
- hndl_list->type = GATT_TYPE_DESC_USR;
- hndl_list->handle = next_handle;;
- hndl_list->next = NULL;
- }
-#endif
-
- next_handle = next_handle + 1;
-
- return attr;
-}
-
-void gatt_init(void)
-{
- DBG("Starting GATT server");
-
- gatt_dbus_manager_register();
-}
-
-void gatt_cleanup(void)
-{
- DBG("Stopping GATT server");
-
- gatt_dbus_manager_unregister();
-}
-
-#endif
+++ /dev/null
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2014 Instituto Nokia de Tecnologia - INdT
- *
- *
- * 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
- *
- */
-
-struct btd_attribute;
-
-void gatt_init(void);
-
-void gatt_cleanup(void);
-
-/*
- * Read operation result callback. Called from the service implementation
- * informing the core (ATT layer) the result of read operation.
- * @err: error in -errno format.
- * @value: value of the attribute read.
- * @len: length of value.
- * @user_data: user_data passed in btd_attr_read_t callback.
- */
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-typedef uint8_t (*btd_attr_read_result_t) (int err, uint8_t *value, size_t len,
- void *user_data);
-#else
-typedef void (*btd_attr_read_result_t) (int err, uint8_t *value, size_t len,
- void *user_data);
-#endif
-
-/*
- * Service implementation callback passed to core (ATT layer). It manages read
- * operations received from remote devices.
- * @attr: reference of the attribute to be read.
- * @bdaddr: Remote device address, which requets read value
- * @result: callback called from the service implementation informing the
- * value of attribute read.
- * @user_data: user_data passed in btd_attr_read_result_t callback.
- */
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-typedef uint8_t (*btd_attr_read_t) (struct btd_attribute *attr, bdaddr_t *bdaddr,
- btd_attr_read_result_t result,
- void *user_data);
-#else
-typedef void (*btd_attr_read_t) (struct btd_attribute *attr,
- btd_attr_read_result_t result,
- void *user_data);
-#endif
-
-/*
- * Write operation result callback. Called from the service implementation
- * informing the core (ATT layer) the result of the write operation. It is used
- * to manage Write Request operations.
- * @err: error in -errno format.
- * @user_data: user_data passed in btd_attr_write_t callback.
- */
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-typedef uint8_t (*btd_attr_write_result_t) (int err, void *user_data);
-#else
-typedef void (*btd_attr_write_result_t) (int err, void *user_data);
-#endif
-/*
- * Service implementation callback passed to core (ATT layer). It manages write
- * operations received from remote devices.
- * @attr: reference of the attribute to be changed.
- * @value: new attribute value.
- * @len: length of value.
- * @result: callback called from the service implementation informing the
- * result of the write operation.
- * @user_data: user_data passed in btd_attr_write_result_t callback.
- */
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-typedef uint8_t (*btd_attr_write_t) (struct btd_attribute *attr,
- const uint8_t *value, size_t len,
- btd_attr_write_result_t result,
- void *user_data);
-#else
-typedef void (*btd_attr_write_t) (struct btd_attribute *attr,
- const uint8_t *value, size_t len,
- btd_attr_write_result_t result,
- void *user_data);
-#endif
-
-/* btd_gatt_add_service - Add a service declaration to local attribute database.
- * @uuid: Service UUID.
- * @path: Service object path.
- *
- * Returns a reference to service declaration attribute. In case of error,
- * NULL is returned.
- */
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid, const char *path);
-#else
-struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid);
-#endif
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-/*
- * btd_gatt_update_attr_db - updates the attribute data base.
- */
-bool btd_gatt_update_attr_db(void);
-
-/*
- * btd_get_service_path - Gets the Service object path if registerd.
- */
-char *btd_get_service_path(bt_uuid_t uuid);
-
-/*
- * btd_get_attrib_path - Gets the attribute path if registerd.
- */
-const char *btd_get_attrib_path(struct btd_attribute *attrib);
-
-/*
- * btd_find_service_from_attr - Gets the Service from attribute if registerd.
- */
-const char *btd_find_service_from_attr(struct btd_attribute *attrib);
-
-/*
- * service_append_dict - Prepare the dictionar entry for a Service
- * along with characteristics and discriptors.
- */
-DBusMessage *service_append_dict(bt_uuid_t uuid, DBusMessage *msg);
-
-/*
- * btd_gatt_set_notify_indicate_flag - Set the notification and indication flag.
- * @attrib: attribute.
- * @notify_indicate: flag to set
- */
-void btd_gatt_set_notify_indicate_flag(struct btd_attribute *attrib,
- bool notify_indicate);
-#endif
-
-/*
- * btd_gatt_remove_service - Remove a service (along with all its
- * characteristics) from the local attribute database.
- * @service: Service declaration attribute.
- */
-void btd_gatt_remove_service(struct btd_attribute *service);
-
-/*
- * btd_gatt_add_char - Add a characteristic (declaration and value attributes)
- * to local attribute database.
- * @uuid: Characteristic UUID (16-bits or 128-bits).
- * @properties: Characteristic properties. See Core SPEC 4.1 page 2183.
- * @path: Characteristic object path.
- * @read_cb: Callback used to provide the characteristic value.
- * @write_cb: Callback called to notify the implementation that a new value
- * is available.
- *
- * Returns a reference to characteristic value attribute. In case of error,
- * NULL is returned.
- */
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-struct btd_attribute *btd_gatt_add_char(const bt_uuid_t *uuid,
- uint8_t properties,
- const char *path,
- btd_attr_read_t read_cb,
- btd_attr_write_t write_cb);
-#else
-struct btd_attribute *btd_gatt_add_char(const bt_uuid_t *uuid,
- uint8_t properties,
- btd_attr_read_t read_cb,
- btd_attr_write_t write_cb);
-#endif
-
-/*
- * btd_gatt_add_char_desc - Add a characteristic descriptor to the local
- * attribute database.
- * @uuid: Characteristic Descriptor UUID (16-bits or 128-bits).
- * @path: Characteristic object path.
- * @read_cb: Callback that should be called once the characteristic
- * descriptor attribute is read.
- * @write_cb: Callback that should be called once the characteristic
- * descriptor attribute is written.
- *
- * Returns a reference to characteristic descriptor attribute. In case of
- * error, NULL is returned.
- */
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-struct btd_attribute *btd_gatt_add_char_desc(const bt_uuid_t *uuid,
- const char *path,
- btd_attr_read_t read_cb,
- btd_attr_write_t write_cb);
-#else
-struct btd_attribute *btd_gatt_add_char_desc(const bt_uuid_t *uuid,
- btd_attr_read_t read_cb,
- btd_attr_write_t write_cb);
-#endif
-
-#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
-/*
- * btd_gatt_update_char - update characteristic value to the local
- * attribute database.
- * @uuid: Characteristic UUID (16-bits or 32-bits or 128-bits).
- * @value: charateristci value to update the databas with
- * @len: length of the value.
- *
- * Returns a TRUE or FALSE.
- */
-bool btd_gatt_update_char(const bt_uuid_t *uuid, uint8_t *value, size_t len);
-#endif
-
-#endif