#include "bt-hal-gatt-server.h"
typedef struct {
- int adv_inst_max;
- int rpa_offloading;
- int max_filter;
+ int adv_inst_max;
+ int rpa_offloading;
+ int max_filter;
+ int le_2m_phy;
+ int le_coded_phy;
} bt_adapter_le_feature_info_t;
typedef struct {
int initialized;
gboolean is_multi_adv; /* To be removed once we complete descope Legacy Adv */
- int adv_handle;
- gboolean is_advertising;
- guint hold_timer_id;
+ int adv_handle;
+ gboolean is_advertising;
+ guint hold_timer_id;
bt_uuid_t app_uuid;
} bt_adapter_le_adv_slot_t;
typedef struct {
uint8_t event;
- int server_if;
- uint8_t status;
- uint8_t data[31];
+ int server_if;
+ uint8_t status;
+ uint8_t data[31];
} bt_hal_adv_event_data_t;
/* Macros */
{
return _bt_hal_dbus_disable_le();
}
+
+int _bt_hal_set_le_static_random_address(uint8_t enable)
+{
+ DBG("+");
+ GError *error = NULL;
+ GVariant *ret;
+ GDBusProxy *proxy;
+
+ proxy = _bt_hal_get_adapter_proxy();
+ if (proxy == NULL)
+ return BT_STATUS_FAIL;
+
+ ret = g_dbus_proxy_call_sync(proxy, "SetLeStaticRandomAddress",
+ g_variant_new("(b)", (enable ? TRUE : FALSE)),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (error) {
+ ERR("Set static address Fail: %s", error->message);
+ g_clear_error(&error);
+ return BT_STATUS_FAIL;
+ }
+
+ INFO("Set le static address [%d]", enable);
+ if (ret)
+ g_variant_unref(ret);
+
+ return BT_STATUS_SUCCESS;
+}
#endif
static void __bt_hal_free_le_adv_slot(void)
if (le_adv_slot == NULL)
return;
- for (i = 0; i < le_feature_info.adv_inst_max; i++) {
+ for (i = 0; i < le_feature_info.adv_inst_max; i++)
memset(&le_adv_slot[i], 0x00, sizeof(bt_adapter_le_adv_slot_t));
- }
+
g_free(le_adv_slot);
le_adv_slot = NULL;
}
void _bt_hal_set_advertising_status(int slot_id, gboolean mode)
{
-
- DBG("Advertising enabled [%s] slot [%d]", mode? "TRUE": "FALSE", slot_id);
bt_hal_adv_event_data_t *event;
+ int adv_slot_id = slot_id;
+ int server_if = 0;
+
+ server_if = bt_hal_gatts_get_server_if(slot_id);
+
+ DBG("Advertising enabled [%s] server_slot [%d] server_if[%d]", mode ? "TRUE" : "FALSE", slot_id, server_if);
if (le_adv_slot == NULL)
return;
- le_adv_slot[slot_id].is_advertising = mode;
+ le_adv_slot[adv_slot_id].is_advertising = mode;
event = g_malloc0(sizeof(bt_hal_adv_event_data_t));
- event->event = mode? BT_HAL_MULTI_ADV_ENB_EVT: BT_HAL_MULTI_ADV_DISABLE_EVT;
- event->server_if = slot_id;
+ event->event = mode ? BT_HAL_MULTI_ADV_ENB_EVT : BT_HAL_MULTI_ADV_DISABLE_EVT;
+
+ event->server_if = server_if;
event->status = BT_STATUS_SUCCESS;
/* To be removed later when we completely descope Legacy Adv concept */
- DBG("Is multi ? [%d]", le_adv_slot[slot_id].is_multi_adv);
- if (le_adv_slot[slot_id].is_multi_adv == FALSE)
+
+ DBG("adv_slot_id[%d] Is multi ? [%d]", adv_slot_id, le_adv_slot[adv_slot_id].is_multi_adv);
+ if (le_adv_slot[adv_slot_id].is_multi_adv == FALSE)
event->event = BT_HAL_LEGACY_ADV_STATUS;
+ if (mode == false ) {
+ DBG("release the adv_slot");
+ bt_hal_gatts_release_adv_slot(server_if);
+ }
+
__bt_hal_adv_event_cb((gpointer)event);
}
gboolean _bt_hal_is_advertising(void)
{
- gboolean status = FALSE;
int i;
+ if (le_adv_slot == NULL)
+ return FALSE;
+
for (i = 0; i < le_feature_info.adv_inst_max; i++) {
if (le_adv_slot[i].is_advertising == TRUE)
- status = TRUE;
+ return TRUE;
}
- return status;
+ return FALSE;
}
int _bt_hal_le_init(void)
{
__bt_hal_free_le_adv_slot();
}
-gboolean _bt_hal_update_le_feature_support(const char *item, const char *value)
+
+gboolean _bt_hal_update_le_feature_support(const char *item, const char *value,
+ bt_local_le_features_t *le_features)
{
if (item == NULL || value == NULL)
return FALSE;
int slot_num;
slot_num = atoi(value);
+ INFO("slot_num:[%d]", slot_num);
if (slot_num < 0) {
ERR("ERR:Advertising MAX instance [%d]", slot_num);
return FALSE;
INFO("Advertising instance max : %d", le_feature_info.adv_inst_max);
le_adv_slot = g_malloc0(sizeof(bt_adapter_le_adv_slot_t) * le_feature_info.adv_inst_max);
}
+
+ INFO("Advertising instance max: [%d]", le_feature_info.adv_inst_max);
+ /* Fill LE feature bytes */
+ le_features->max_adv_instance = atoi(value);
+
} else if (g_strcmp0(item, "rpa_offloading") == 0) {
le_feature_info.rpa_offloading = atoi(value);
INFO("RPA offloading : %d", le_feature_info.rpa_offloading);
+
+ /* Fill LE feature bytes */
+ le_features->rpa_offload_supported = atoi(value);
+
} else if (g_strcmp0(item, "max_filter") == 0) {
le_feature_info.max_filter = atoi(value);
INFO("BLE Scan max filter : %d", le_feature_info.max_filter);
+
+ /* Fill LE feature bytes */
+ le_features->max_adv_filter_supported = atoi(value);
+
+ } else if (g_strcmp0(item, "2m_phy") == 0) {
+ if (g_strcmp0(value, "true") == 0) {
+ le_feature_info.le_2m_phy = TRUE;
+ /* Fill LE feature bytes */
+ le_features->le_2m_phy_supported = 0x1;
+ } else {
+ le_feature_info.le_2m_phy = FALSE;
+ /* Fill LE feature bytes */
+ le_features->le_2m_phy_supported = 0x0;
+ }
+ INFO("2M PHY Supported [%s]", le_feature_info.le_2m_phy ? "TRUE" : "FALSE");
+ } else if (g_strcmp0(item, "coded_phy") == 0) {
+ if (g_strcmp0(value, "true") == 0) {
+ le_feature_info.le_coded_phy = TRUE;
+ /* Fill LE feature bytes */
+ le_features->le_coded_phy_supported = 0x1;
+ } else {
+ le_feature_info.le_coded_phy = FALSE;
+ /* Fill LE feature bytes */
+ le_features->le_coded_phy_supported = 0x0;
+ }
+ INFO("CODED PHY Supported [%s]", le_feature_info.le_coded_phy ? "TRUE" : "FALSE");
} else {
DBG("No registered item");
return FALSE;
memset(&le_adv_slot[slot_id], 0x00, sizeof(bt_adapter_le_adv_slot_t));
}
-int _bt_hal_get_available_adv_slot_id(bt_uuid_t *uuid)
+int _bt_hal_get_available_adv_slot_id(bt_uuid_t *uuid, gboolean use_reserved_slot)
{
int i;
}
}
+ /* We should consider 'use_reverved_slot' in later */
+ if (le_feature_info.adv_inst_max <= 1)
+ i = 0;
+ else if (use_reserved_slot == TRUE)
+ i = 1;
+ else
+ i = 2;
+
for (i = 0; i < le_feature_info.adv_inst_max; i++) {
if (le_adv_slot[i].initialized == 0) {
DBG("Slot to be allocated [%d] UUID to be registered [%s]",
dest[index+1] = 0x06; /* AD Type */
memcpy(&(dest[index + 2]), &src[12], byte_len);
/* Update current type */
- prev_byte_len = byte_len;
+ prev_byte_len = byte_len;
*length += 18;
break;
}
static gboolean __bt_hal_is_factory_test_mode(void)
{
- int mode = 0;
+ int mode = 0;
- if (vconf_get_bool(VCONFKEY_BT_DUT_MODE, &mode)) {
- ERR("Get the DUT Mode fail");
- return TRUE;
- }
+ if (vconf_get_bool(VCONFKEY_BT_DUT_MODE, &mode)) {
+ ERR("Get the DUT Mode fail");
+ return TRUE;
+ }
- if (mode != FALSE) {
- INFO("DUT Test Mode !!");
- return TRUE;
- }
+ if (mode != FALSE) {
+ INFO("DUT Test Mode !!");
+ return TRUE;
+ }
- return FALSE;
+ return FALSE;
}
static gboolean __bt_hal_adv_event_cb(gpointer param)
return FALSE;
}
- switch(event->event) {
+ switch (event->event) {
case BT_HAL_MULTI_ADV_ENB_EVT: {
INFO("BLE Advertising enabled slot [%d]", event->server_if);
struct hal_ev_multi_adv_enable ev;
return FALSE;
}
-int _bt_hal_enable_advertising(int server_if, bool enable, bool is_multi_adv)
+int _bt_hal_enable_advertising(int server_if, int adv_slot_id, bool enable, bool is_multi_adv)
{
DBG("+");
GError *error = NULL;
if (proxy == NULL)
return BT_STATUS_FAIL;
- if (le_adv_slot[server_if].is_advertising == TRUE && enable == TRUE)
+ if (le_adv_slot[adv_slot_id].is_advertising == TRUE && enable == TRUE)
return BT_STATUS_BUSY;
- if (le_adv_slot[server_if].initialized == TRUE &&
- le_adv_slot[server_if].is_advertising == FALSE &&
+ if (le_adv_slot[adv_slot_id].initialized == TRUE &&
+ le_adv_slot[adv_slot_id].is_advertising == FALSE &&
enable == FALSE)
return BT_STATUS_DONE;
- if (le_adv_slot[server_if].hold_timer_id > 0) {
- g_source_remove(le_adv_slot[server_if].hold_timer_id);
- le_adv_slot[server_if].hold_timer_id = 0;
+ if (le_adv_slot[adv_slot_id].hold_timer_id > 0) {
+ g_source_remove(le_adv_slot[adv_slot_id].hold_timer_id);
+ le_adv_slot[adv_slot_id].hold_timer_id = 0;
}
ret = g_dbus_proxy_call_sync(proxy, "SetAdvertising",
- g_variant_new("(bi)", enable, server_if),
+ g_variant_new("(bi)", enable, adv_slot_id),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
return BT_STATUS_FAIL;
}
- INFO("Enable advertising [%d] SLot Id [%d] Is Multi? [%d]", enable, server_if, is_multi_adv);
+ INFO("Enable advertising [%d] SLot Id [%d] gatt_server [%d] Is Multi? [%d]",
+ enable, adv_slot_id, server_if, is_multi_adv);
if (ret)
g_variant_unref(ret);
- le_adv_slot[server_if].is_multi_adv = is_multi_adv;
- le_adv_slot[server_if].is_advertising = enable;
+ le_adv_slot[adv_slot_id].is_multi_adv = is_multi_adv;
+ le_adv_slot[adv_slot_id].is_advertising = enable;
return BT_STATUS_SUCCESS;
}
int _bt_hal_set_advertising_params(int server_if, int min_interval,
- int max_interval,int adv_type,
- int chnl_map, int tx_power, int timeout_s)
+ int max_interval, int adv_type,
+ int chnl_map, int tx_power, int timeout_s)
{
DBG("+");
GDBusProxy *proxy;
- GVariant *ret;
- GError *error = NULL;
- guint32 min = 0;
- guint32 max = 0;
+ GVariant *ret;
+ GError *error = NULL;
+ guint32 min = 0;
+ guint32 max = 0;
bt_hal_adv_event_data_t *event;
+ int slot_id = 0;
proxy = _bt_hal_get_adapter_proxy();
- if (proxy == NULL)
+ if (proxy == NULL)
return BT_STATUS_FAIL;
if (min_interval > max_interval ||
- min_interval < BT_HAL_ADV_INTERVAL_MIN ||
- max_interval > BT_HAL_ADV_INTERVAL_MAX)
+ min_interval < BT_HAL_ADV_INTERVAL_MIN ||
+ max_interval > BT_HAL_ADV_INTERVAL_MAX)
return BT_STATUS_PARM_INVALID;
if (adv_type == BT_HAL_ADV_CONNECTABLE_DIRECT_HIGH ||
- adv_type == BT_HAL_ADV_CONNECTABLE_DIRECT_LOW ||
- adv_type == BT_HAL_ADV_NON_CONNECTABLE)
- return BT_STATUS_UNSUPPORTED;
+ adv_type == BT_HAL_ADV_CONNECTABLE_DIRECT_LOW ||
+ adv_type == BT_HAL_ADV_NON_CONNECTABLE)
+ return BT_STATUS_UNSUPPORTED;
min = min_interval / BT_HAL_ADV_INTERVAL_SPLIT;
- max = max_interval / BT_HAL_ADV_INTERVAL_SPLIT;
+ max = max_interval / BT_HAL_ADV_INTERVAL_SPLIT;
+
+ slot_id = bt_hal_gatts_allocate_adv_slot_by_server_if(server_if);
ret = g_dbus_proxy_call_sync(proxy, "SetAdvertisingParameters",
- g_variant_new("(uuuui)", min, max,
- BT_HAL_ADV_FILTER_POLICY_DEFAULT, adv_type,
- server_if), G_DBUS_CALL_FLAGS_NONE,
- -1, NULL, &error);
+ g_variant_new("(uuuuii)", min, max,
+ BT_HAL_ADV_FILTER_POLICY_DEFAULT, adv_type,
+ tx_power, slot_id), G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &error);
if (error) {
- ERR("SetAdvertisingParameters Fail: %s", error->message);
- g_clear_error(&error);
+ ERR("SetAdvertisingParameters Fail: %s", error->message);
+ g_clear_error(&error);
return BT_STATUS_FAIL;
- }
+ }
INFO("Set advertising data");
- if (ret)
- g_variant_unref(ret);
+ if (ret)
+ g_variant_unref(ret);
/*
- * As we need to provide async callback to user from HAL, simply schedule a
- * callback method which will carry actual result
- */
+ * As we need to provide async callback to user from HAL, simply schedule a
+ * callback method which will carry actual result
+ */
event = g_malloc0(sizeof(bt_hal_adv_event_data_t));
event->event = BT_HAL_MULTI_ADV_UPDATE_EVT;
event->server_if = server_if;
event->status = BT_STATUS_SUCCESS;
- g_idle_add(__bt_hal_adv_event_cb, (gpointer)event);
+ g_idle_add(__bt_hal_adv_event_cb, (gpointer)event);
return BT_STATUS_SUCCESS;
}
uint8_t adv_data[31];
int index = 0;
GDBusProxy *proxy;
- GError *error = NULL;
- GVariant *ret = NULL;
- GVariant *temp = NULL;
- GVariantBuilder *builder;
+ GError *error = NULL;
+ GVariant *ret = NULL;
+ GVariant *temp = NULL;
+ GVariantBuilder *builder;
bt_hal_adv_event_data_t *event;
int length = 0;
- int i;
+ int i;
+ int slot_id = 0;
/* Parse data according to Bluez Interface */
if (__bt_hal_is_factory_test_mode()) {
- ERR("Unable to set advertising data in factory binary !!");
- return BT_STATUS_UNSUPPORTED;
- }
+ ERR("Unable to set advertising data in factory binary !!");
+ return BT_STATUS_UNSUPPORTED;
+ }
/* TODO: Check adapter and LE adapter status */
proxy = _bt_hal_get_adapter_proxy();
- if (proxy == NULL)
+ if (proxy == NULL)
return BT_STATUS_FAIL;
+ slot_id = bt_hal_gatts_allocate_adv_slot_by_server_if(adv_param_setup.server_if);
+
memset(&adv_data, 0, 31);
/* Service UUID */
/* Create Builder */
builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
- for (i = 0; i < length; i++)
- g_variant_builder_add(builder, "y", adv_data[i]);
+ for (i = 0; i < length; i++)
+ g_variant_builder_add(builder, "y", adv_data[i]);
- temp = g_variant_new("ay", builder);
- g_variant_builder_unref(builder);
+ temp = g_variant_new("ay", builder);
+ g_variant_builder_unref(builder);
- DBG("####Adv data length [%d] Index [%d]", length, index);
- for (i = 0; i < length; i++)
- DBG("##Data[%d] [0x%x]", i, adv_data[i]);
+ DBG("####Adv data length [%d] Index [%d]", length, index);
+ for (i = 0; i < length; i++)
+ DBG("##Data[%d] [0x%x]", i, adv_data[i]);
if (adv_param_setup.set_scan_rsp == 0) {
/* Set Advertising data to stack */
ret = g_dbus_proxy_call_sync(proxy, "SetAdvertisingData",
- g_variant_new("(@ayi)", temp, adv_param_setup.server_if),
+ g_variant_new("(@ayi)", temp, slot_id),
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, &error);
} else {
/* Set Scan response data to stack */
ret = g_dbus_proxy_call_sync(proxy, "SetScanRespData",
- g_variant_new("(@ayi)", temp, adv_param_setup.server_if),
+ g_variant_new("(@ayi)", temp, slot_id),
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, &error);
}
- if (error) {
- ERR("SetAdvertisingData Fail: %s", error->message);
- g_clear_error(&error);
- return BT_STATUS_FAIL;
- }
+ if (error) {
+ ERR("SetAdvertisingData Fail: %s", error->message);
+ g_clear_error(&error);
+ return BT_STATUS_FAIL;
+ }
INFO("Set advertising data");
- if (ret)
- g_variant_unref(ret);
+ if (ret)
+ g_variant_unref(ret);
/*
- * As we need to provide async callback to user from HAL, simply schedule a
- * callback method which will carry actual result
- */
+ * As we need to provide async callback to user from HAL, simply schedule a
+ * callback method which will carry actual result
+ */
event = g_malloc0(sizeof(bt_hal_adv_event_data_t));
event->event = BT_HAL_MULTI_ADV_DATA_EVT;
event->server_if = adv_param_setup.server_if;
event->status = BT_STATUS_SUCCESS;
memcpy(&event->data, adv_data, 31);
- g_idle_add(__bt_hal_adv_event_cb, (gpointer)event);
+ g_idle_add(__bt_hal_adv_event_cb, (gpointer)event);
- return BT_STATUS_SUCCESS;
+ return BT_STATUS_SUCCESS;
}
int _bt_hal_adapter_le_start_scan(void)
-1, NULL, &error);
if (ret == NULL) {
if (error) {
+ g_dbus_error_strip_remote_error(error);
ERR("StopLEDiscovery Fail: %s", error->message);
+
+ /* Abnormal case for ARTIK530 */
+ if (g_strrstr(error->message, "No discovery started") ||
+ g_strrstr(error->message, "Operation already in progress")) {
+ g_clear_error(&error);
+ return BT_STATUS_SUCCESS;
+ }
+
g_clear_error(&error);
+ return BT_STATUS_FAIL;
}
-
- return BT_STATUS_FAIL;
}
-
g_variant_unref(ret);
DBG("-");
return BT_STATUS_SUCCESS;
}
+/*sets the privacy functionality of the adapter*/
+int _bt_hal_adapter_le_set_privacy(uint8_t set_privacy)
+{
+ GDBusProxy *proxy;
+ GError *error = NULL;
+ GVariant *result = NULL;
+ proxy = _bt_hal_get_adapter_proxy();
+ if (proxy == NULL)
+ return BT_STATUS_FAIL;
+
+ result = g_dbus_proxy_call_sync(proxy,
+ "SetLePrivacy",
+ g_variant_new("(b)", set_privacy),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (!result) {
+ if (error != NULL) {
+ ERR("Failed to SetLePrivacy (Error: %s)", error->message);
+ g_clear_error(&error);
+ } else
+ ERR("Failed to SetLePrivacy");
+ return BT_STATUS_FAIL;
+ }
+
+ g_variant_unref(result);
+ INFO("SetLePrivacy as %d", set_privacy);
+ return BT_STATUS_SUCCESS;
+}
int _bt_hal_adapter_le_set_scan_parameters(
int scan_type, int scan_interval, int scan_window)
{
gatt_le_event_cb = NULL;
}
+
+int _bt_hal_adapter_le_set_manufacturer_data(bt_manufacturer_data_t *m_data)
+{
+ GDBusProxy *proxy;
+ GError *error = NULL;
+ int i;
+ GVariant *val;
+ GVariant *ret;
+ GVariantBuilder *builder;
+
+ proxy = _bt_hal_get_adapter_proxy();
+ if (proxy == NULL)
+ return BT_STATUS_FAIL;
+
+ builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
+
+ if (m_data->data_len + 2 >= BT_MANUFACTURER_DATA_LENGTH_MAX)
+ return BT_STATUS_PARM_INVALID;
+ for (i = 0; i < (m_data->data_len) + 2; i++)
+ g_variant_builder_add(builder, "y", m_data->data[i]);
+
+ val = g_variant_new("(ay)", builder);
+
+ ret = g_dbus_proxy_call_sync(proxy,
+ "SetManufacturerData",
+ val,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+ g_variant_builder_unref(builder);
+ if (!ret) {
+ if (error != NULL) {
+ ERR("Failed to SetManufacturerData (Error: %s)", error->message);
+ g_clear_error(&error);
+ } else {
+ ERR("Failed to SetManufacturerData");
+ }
+ return BT_STATUS_FAIL;
+ }
+
+ INFO("Set manufacturer data");
+ g_variant_unref(ret);
+
+ return BT_STATUS_SUCCESS;
+}
+
+
+
+/*add/remove remote device address from white list*/
+int _bt_hal_adapter_le_set_white_list(bt_bdaddr_t *device_address, bt_dev_addr_type_t address_type, bool is_add)
+{
+ GDBusProxy *proxy;
+ char address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
+ GError *error = NULL;
+ GVariant *ret;
+
+ if (address_type != BLUETOOTH_HAL_DEVICE_PUBLIC_ADDRESS &&
+ address_type != BLUETOOTH_HAL_DEVICE_RANDOM_ADDRESS)
+ return BT_STATUS_PARM_INVALID;
+
+ _bt_hal_convert_addr_type_to_string(address, device_address->address);
+
+ proxy = _bt_hal_get_adapter_proxy();
+ if (proxy == NULL)
+ return BT_STATUS_FAIL;
+ if (is_add)
+ ret = g_dbus_proxy_call_sync(proxy, "AddDeviceWhiteList",
+ g_variant_new("(su)", address, address_type),
+ G_DBUS_CALL_FLAGS_NONE, -1,
+ NULL, &error);
+ else
+ ret = g_dbus_proxy_call_sync(proxy, "RemoveDeviceWhiteList",
+ g_variant_new("(su)", address, address_type),
+ G_DBUS_CALL_FLAGS_NONE, -1,
+ NULL, &error);
+
+ if (error) {
+ if (is_add)
+ ERR("RemoveDeviceWhiteList Fail: %s", error->message);
+ else
+ ERR("AddDeviceWhiteList Fail: %s", error->message);
+ g_clear_error(&error);
+ return BT_STATUS_FAIL;
+ }
+
+ if (ret)
+ g_variant_unref(ret);
+ if (is_add)
+ INFO("Device Added to white list");
+ else
+ INFO("Device Removed from white list");
+ return BT_STATUS_SUCCESS;
+}