4 * Copyright (c) 2015 -2016 Samsung Electronics Co., Ltd All Rights Reserved.
6 * Contact: Anupam Roy <anupam.r@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
24 #include <hardware/bluetooth.h>
25 #include <hardware/bt_gatt.h>
34 #include <vconf-keys.h>
35 #include <vconf-internal-radio-keys.h>
42 #include "bt-hal-log.h"
43 #include "bt-hal-msg.h"
44 #include "bt-hal-utils.h"
46 #include <bt-hal-adapter-dbus-handler.h>
47 #include <bt-hal-dbus-common-utils.h>
49 #include "bt-hal-gatt-server.h"
57 } bt_adapter_le_feature_info_t;
61 gboolean is_multi_adv; /* To be removed once we complete descope Legacy Adv */
63 gboolean is_advertising;
66 } bt_adapter_le_adv_slot_t;
68 static bt_adapter_le_feature_info_t le_feature_info = { 1, 0, 0 };
69 static bt_adapter_le_adv_slot_t *le_adv_slot = NULL;
76 } bt_hal_adv_event_data_t;
79 #define BT_HAL_ADV_CONNECTABLE 0x00 /* ADV_IND */
80 #define BT_HAL_ADV_CONNECTABLE_DIRECT_HIGH 0x01 /* ADV_DIRECT_IND, high duty cycle */
81 #define BT_HAL_ADV_SCANNABLE 0x02 /* ADV_SCAN_IND */
82 #define BT_HAL_ADV_NON_CONNECTABLE 0x03 /* ADV_NONCOND_IND */
83 #define BT_HAL_ADV_CONNECTABLE_DIRECT_LOW 0x04 /* ADV_DIRECT_IND, low duty cycle */
85 #define BT_HAL_ADV_INTERVAL_MIN 20 /* msec */
86 #define BT_HAL_ADV_INTERVAL_MAX 10240
87 #define BT_HAL_ADV_INTERVAL_SPLIT 0.625
88 #define BT_HAL_DEFAULT_ADV_MIN_INTERVAL 500
89 #define BT_HAL_DEFAULT_ADV_MAX_INTERVAL 500
90 #define BT_HAL_ADV_FILTER_POLICY_DEFAULT 0x00
91 #define BT_HAL_ADV_TYPE_DEFAULT 0x00
92 #define BT_HAL_ADV_FILTER_POLICY_ALLOW_SCAN_CONN_WL_ONLY 0x03
94 /* Multi Advertisement callback event */
95 #define BT_HAL_MULTI_ADV_ENB_EVT 1
96 #define BT_HAL_MULTI_ADV_DISABLE_EVT 2
97 #define BT_HAL_MULTI_ADV_PARAM_EVT 3
98 #define BT_HAL_MULTI_ADV_DATA_EVT 4
99 #define BT_HAL_MULTI_ADV_UPDATE_EVT 5
100 #define BT_HAL_LEGACY_ADV_STATUS 6
102 handle_stack_msg gatt_le_event_cb;
104 /* Forward declarations */
105 static gboolean __bt_hal_is_factory_test_mode(void);
106 static void __bt_hal_free_le_adv_slot(void);
107 static gboolean __bt_hal_adv_event_cb(gpointer param);
110 /* Enable LE Adapter */
111 int _bt_hal_le_enable(void)
113 return _bt_hal_dbus_enable_le();
116 /* Disable LE Adapter */
117 int _bt_hal_le_disable(void)
119 return _bt_hal_dbus_disable_le();
123 static void __bt_hal_free_le_adv_slot(void)
127 if (le_adv_slot == NULL)
130 for (i = 0; i < le_feature_info.adv_inst_max; i++)
131 memset(&le_adv_slot[i], 0x00, sizeof(bt_adapter_le_adv_slot_t));
137 void _bt_hal_unregister_adv_slot_owner(int slot_id)
139 if (le_adv_slot == NULL)
141 INFO("Unregister Adv Slot [%d]", slot_id);
142 memset(&le_adv_slot[slot_id], 0x00, sizeof(bt_adapter_le_adv_slot_t));
145 int _bt_hal_get_adv_slot_adv_handle(int slot_id)
147 if (le_adv_slot == NULL)
150 return le_adv_slot[slot_id].adv_handle;
153 gboolean _bt_hal_is_advertising_in_slot(int slot)
155 return le_adv_slot[slot].is_advertising;
158 void _bt_hal_set_advertising_status(int slot_id, gboolean mode)
161 DBG("Advertising enabled [%s] slot [%d]", mode ? "TRUE" : "FALSE", slot_id);
162 bt_hal_adv_event_data_t *event;
164 if (le_adv_slot == NULL)
167 le_adv_slot[slot_id].is_advertising = mode;
169 event = g_malloc0(sizeof(bt_hal_adv_event_data_t));
170 event->event = mode ? BT_HAL_MULTI_ADV_ENB_EVT : BT_HAL_MULTI_ADV_DISABLE_EVT;
171 event->server_if = slot_id;
172 event->status = BT_STATUS_SUCCESS;
173 /* To be removed later when we completely descope Legacy Adv concept */
174 DBG("Is multi ? [%d]", le_adv_slot[slot_id].is_multi_adv);
175 if (le_adv_slot[slot_id].is_multi_adv == FALSE)
176 event->event = BT_HAL_LEGACY_ADV_STATUS;
178 __bt_hal_adv_event_cb((gpointer)event);
181 gboolean _bt_hal_is_advertising(void)
185 for (i = 0; i < le_feature_info.adv_inst_max; i++) {
186 if (le_adv_slot[i].is_advertising == TRUE)
193 int _bt_hal_le_init(void)
195 le_adv_slot = g_malloc0(sizeof(bt_adapter_le_adv_slot_t) * le_feature_info.adv_inst_max);
196 return BT_STATUS_SUCCESS;
198 void _bt_hal_le_deinit(void)
200 __bt_hal_free_le_adv_slot();
203 gboolean _bt_hal_update_le_feature_support(const char *item, const char *value,
204 bt_local_le_features_t *le_features)
206 if (item == NULL || value == NULL)
211 if (g_strcmp0(item, "adv_inst_max") == 0) {
214 slot_num = atoi(value);
216 ERR("ERR:Advertising MAX instance [%d]", slot_num);
220 if (slot_num != le_feature_info.adv_inst_max) {
221 __bt_hal_free_le_adv_slot();
222 le_feature_info.adv_inst_max = slot_num;
223 INFO("Advertising instance max : %d", le_feature_info.adv_inst_max);
224 le_adv_slot = g_malloc0(sizeof(bt_adapter_le_adv_slot_t) * le_feature_info.adv_inst_max);
226 /* Fill LE feature bytes */
227 le_features->max_adv_instance = atoi(value);
229 } else if (g_strcmp0(item, "rpa_offloading") == 0) {
230 le_feature_info.rpa_offloading = atoi(value);
231 INFO("RPA offloading : %d", le_feature_info.rpa_offloading);
233 /* Fill LE feature bytes */
234 le_features->rpa_offload_supported = atoi(value);
236 } else if (g_strcmp0(item, "max_filter") == 0) {
237 le_feature_info.max_filter = atoi(value);
238 INFO("BLE Scan max filter : %d", le_feature_info.max_filter);
240 /* Fill LE feature bytes */
241 le_features->max_adv_filter_supported = atoi(value);
243 } else if (g_strcmp0(item, "2m_phy") == 0) {
244 if (g_strcmp0(value, "true") == 0) {
245 le_feature_info.le_2m_phy = TRUE;
246 /* Fill LE feature bytes */
247 le_features->le_2m_phy_supported = 0x1;
249 le_feature_info.le_2m_phy = FALSE;
250 /* Fill LE feature bytes */
251 le_features->le_2m_phy_supported = 0x0;
253 INFO("2M PHY Supported [%s]", le_feature_info.le_2m_phy ? "TRUE" : "FALSE");
254 } else if (g_strcmp0(item, "coded_phy") == 0) {
255 if (g_strcmp0(value, "true") == 0) {
256 le_feature_info.le_coded_phy = TRUE;
257 /* Fill LE feature bytes */
258 le_features->le_coded_phy_supported = 0x1;
260 le_feature_info.le_coded_phy = FALSE;
261 /* Fill LE feature bytes */
262 le_features->le_coded_phy_supported = 0x0;
264 INFO("CODED PHY Supported [%s]", le_feature_info.le_coded_phy ? "TRUE" : "FALSE");
266 DBG("No registered item");
273 void _bt_hal_free_server_slot(int slot_id)
275 if (le_adv_slot == NULL)
277 memset(&le_adv_slot[slot_id], 0x00, sizeof(bt_adapter_le_adv_slot_t));
280 int _bt_hal_get_available_adv_slot_id(bt_uuid_t *uuid, gboolean use_reserved_slot)
284 if (le_adv_slot == NULL) {
285 ERR("le_adv_slot is NULL");
289 DBG("adv_inst_max : %d", le_feature_info.adv_inst_max);
291 for (i = 0; i < le_feature_info.adv_inst_max; i++) {
292 if (le_adv_slot[i].initialized == 0)
294 if (memcmp(uuid->uu, le_adv_slot[i].app_uuid.uu, sizeof(bt_uuid_t)) == 0) {
295 DBG("UUID [%s] matched, return slot [%d]", btuuid2str(uuid->uu), i);
300 /* We should consider 'use_reverved_slot' in later */
301 if (le_feature_info.adv_inst_max <= 1)
303 else if (use_reserved_slot == TRUE)
308 for (i = 0; i < le_feature_info.adv_inst_max; i++) {
309 if (le_adv_slot[i].initialized == 0) {
310 DBG("Slot to be allocated [%d] UUID to be registered [%s]",
311 i, btuuid2str(uuid->uu));
312 le_adv_slot[i].initialized = 1;
313 memcpy(&le_adv_slot[i].app_uuid.uu, &uuid->uu, sizeof(bt_uuid_t));
321 void _bt_hal_get_gatt_server_instance_initialized(int *instance)
324 if (le_adv_slot == NULL) {
325 ERR("le_adv_slot is NULL");
329 DBG("adv_inst_max : %d", le_feature_info.adv_inst_max);
331 for (i = 0; i < le_feature_info.adv_inst_max; i++) {
332 if (le_adv_slot[i].initialized == 0)
334 DBG("Initialized Slot found: UUID [%s] slot [%d]", le_adv_slot[i].app_uuid.uu, i);
340 gboolean _bt_is_advertising(void)
345 int _bt_set_advertising(const char *sender, int adv_handle,
346 gboolean enable, gboolean use_reserved_slot)
349 return BT_STATUS_UNSUPPORTED;
352 static int __bt_hal_uuid_type(uint8_t* p_uuid)
358 for (i = 0; i != 16; ++i) {
359 if (i == 12 || i == 13)
362 if (p_uuid[i] == BASE_UUID_CONVERTED[i])
371 return BT_HAL_UUID_32;
373 return BT_HAL_UUID_16;
374 return BT_HAL_UUID_128;
377 static void __bt_hal_parse_uuid(int len, char *src, uint8_t *dest, int *length, int is_solicit)
380 int prev_byte_len = 0;
381 /* dest[index] will contain the length followed by AD Type
382 Move length only when different byte_len is found Ex) 2->4, 2->16, 4->16 etc */
387 /* Create Local buffer & copy source 16 bytes in sequence */
390 memset(&uuid, 0, sizeof(bt_uuid_t));
391 memcpy(&uuid.uu, src, 16);
393 /* Compute current UUID's byte length */
394 byte_len = __bt_hal_uuid_type(uuid.uu);
398 if (prev_byte_len == byte_len) {
399 memcpy(&(dest[dest[index] + 1]), &src[12], byte_len);
403 if (dest[index] != 0)
404 index = dest[index] +1;
405 dest[index] = byte_len + 1;
407 dest[index+1] = 0x14; /* AD Type */
409 dest[index+1] = 0x02; /* AD Type */
410 memcpy(&(dest[index + 2]), &src[12], byte_len);
414 /* Update current type */
415 prev_byte_len = byte_len;
419 if (prev_byte_len == byte_len) {
420 memcpy(&(dest[dest[index] + 1]), &src[12], byte_len);;
424 if (dest[index] != 0)
425 index = dest[index] +1;
426 dest[index] = byte_len + 1;
428 dest[index+1] = 0x1F; /* AD Type */
430 dest[index+1] = 0x04; /* AD Type */
431 memcpy(&(dest[index + 2]), &src[12], byte_len);
434 /* Update current type */
435 prev_byte_len = byte_len;
439 if (dest[index] != 0)
440 index = dest[index] +1;
441 dest[index] = byte_len + 1;
443 dest[index+1] = 0x15; /* AD Type */
445 dest[index+1] = 0x06; /* AD Type */
446 memcpy(&(dest[index + 2]), &src[12], byte_len);
447 /* Update current type */
448 prev_byte_len = byte_len;
453 ERR("Abnormal Byte len [%d]", byte_len);
458 /* Process Next 16 bytes of MW UUID */
465 static gboolean __bt_hal_is_factory_test_mode(void)
469 if (vconf_get_bool(VCONFKEY_BT_DUT_MODE, &mode)) {
470 ERR("Get the DUT Mode fail");
475 INFO("DUT Test Mode !!");
482 static gboolean __bt_hal_adv_event_cb(gpointer param)
484 bt_hal_adv_event_data_t *event = (bt_hal_adv_event_data_t*)param;
490 if (!gatt_le_event_cb) {
491 ERR("GATT event callback not registered!!!");
495 switch (event->event) {
496 case BT_HAL_MULTI_ADV_ENB_EVT: {
497 INFO("BLE Advertising enabled slot [%d]", event->server_if);
498 struct hal_ev_multi_adv_enable ev;
499 memset(&ev, 0, sizeof(struct hal_ev_multi_adv_enable));
500 ev.status = event->status;
501 ev.server_instance = event->server_if;
502 gatt_le_event_cb(HAL_EV_MULTI_ADV_ENABLE, (void *)&ev, sizeof(ev));
505 case BT_HAL_MULTI_ADV_DISABLE_EVT: {
506 INFO("BLE Advertising disabled slot [%d]", event->server_if);
507 struct hal_ev_multi_adv_disable ev;
508 memset(&ev, 0, sizeof(struct hal_ev_multi_adv_disable));
509 ev.status = event->status;
510 ev.server_instance = event->server_if;
511 gatt_le_event_cb(HAL_EV_MULTI_ADV_DISABLE, (void *)&ev, sizeof(ev));
514 case BT_HAL_MULTI_ADV_PARAM_EVT: {
515 INFO("Unhandled event slot [%d]", event->server_if);
518 case BT_HAL_MULTI_ADV_UPDATE_EVT: {
519 INFO("BLE Advertising Param update slot [%d]", event->server_if);
520 struct hal_ev_multi_adv_update ev;
521 memset(&ev, 0, sizeof(struct hal_ev_multi_adv_update));
522 ev.status = event->status;
523 ev.server_instance = event->server_if;
524 gatt_le_event_cb(HAL_EV_MULTI_ADV_UPDATE, (void *)&ev, sizeof(ev));
527 case BT_HAL_MULTI_ADV_DATA_EVT: {
528 INFO("BLE Advertising data set slot [%d]", event->server_if);
529 struct hal_ev_multi_adv_data_set ev_data_set;
531 memset(&ev_data_set, 0, sizeof(struct hal_ev_multi_adv_data_set));
532 ev_data_set.status = event->status;
533 ev_data_set.server_instance = event->server_if;
534 gatt_le_event_cb(HAL_EV_MULTI_ADV_DATA_SET, (void *)&ev_data_set, sizeof(ev_data_set));
537 case BT_HAL_LEGACY_ADV_STATUS: {
538 INFO("BLE Legacy Advertising [%d]", event->server_if);
539 struct hal_ev_legacy_adv_status ev;
541 memset(&ev, 0, sizeof(struct hal_ev_legacy_adv_status));
542 ev.status = event->status;
543 ev.server_instance = event->server_if;
544 gatt_le_event_cb(HAL_EV_LEGACY_ADV_ENABLE, (void *)&ev, sizeof(ev));
548 ERR("Unknown event");
558 int _bt_hal_enable_advertising(int server_if, bool enable, bool is_multi_adv)
561 GError *error = NULL;
565 proxy = _bt_hal_get_adapter_proxy();
567 return BT_STATUS_FAIL;
569 if (le_adv_slot[server_if].is_advertising == TRUE && enable == TRUE)
570 return BT_STATUS_BUSY;
572 if (le_adv_slot[server_if].initialized == TRUE &&
573 le_adv_slot[server_if].is_advertising == FALSE &&
575 return BT_STATUS_DONE;
577 if (le_adv_slot[server_if].hold_timer_id > 0) {
578 g_source_remove(le_adv_slot[server_if].hold_timer_id);
579 le_adv_slot[server_if].hold_timer_id = 0;
582 ret = g_dbus_proxy_call_sync(proxy, "SetAdvertising",
583 g_variant_new("(bi)", enable, server_if),
584 G_DBUS_CALL_FLAGS_NONE,
590 ERR("SetAdvertising Fail: %s", error->message);
591 g_clear_error(&error);
592 return BT_STATUS_FAIL;
595 INFO("Enable advertising [%d] SLot Id [%d] Is Multi? [%d]", enable, server_if, is_multi_adv);
597 g_variant_unref(ret);
599 le_adv_slot[server_if].is_multi_adv = is_multi_adv;
600 le_adv_slot[server_if].is_advertising = enable;
601 return BT_STATUS_SUCCESS;
604 int _bt_hal_set_advertising_params(int server_if, int min_interval,
605 int max_interval, int adv_type,
606 int chnl_map, int tx_power, int timeout_s)
611 GError *error = NULL;
614 bt_hal_adv_event_data_t *event;
617 proxy = _bt_hal_get_adapter_proxy();
619 return BT_STATUS_FAIL;
621 if (min_interval > max_interval ||
622 min_interval < BT_HAL_ADV_INTERVAL_MIN ||
623 max_interval > BT_HAL_ADV_INTERVAL_MAX)
624 return BT_STATUS_PARM_INVALID;
627 if (adv_type == BT_HAL_ADV_CONNECTABLE_DIRECT_HIGH ||
628 adv_type == BT_HAL_ADV_CONNECTABLE_DIRECT_LOW ||
629 adv_type == BT_HAL_ADV_NON_CONNECTABLE)
630 return BT_STATUS_UNSUPPORTED;
633 min = min_interval / BT_HAL_ADV_INTERVAL_SPLIT;
634 max = max_interval / BT_HAL_ADV_INTERVAL_SPLIT;
636 ret = g_dbus_proxy_call_sync(proxy, "SetAdvertisingParameters",
637 g_variant_new("(uuuuii)", min, max,
638 BT_HAL_ADV_FILTER_POLICY_DEFAULT, adv_type,
639 server_if), G_DBUS_CALL_FLAGS_NONE,
642 ERR("SetAdvertisingParameters Fail: %s", error->message);
643 g_clear_error(&error);
644 return BT_STATUS_FAIL;
647 INFO("Set advertising data");
649 g_variant_unref(ret);
652 * As we need to provide async callback to user from HAL, simply schedule a
653 * callback method which will carry actual result
655 event = g_malloc0(sizeof(bt_hal_adv_event_data_t));
656 event->event = BT_HAL_MULTI_ADV_UPDATE_EVT;
657 event->server_if = server_if;
658 event->status = BT_STATUS_SUCCESS;
659 g_idle_add(__bt_hal_adv_event_cb, (gpointer)event);
661 return BT_STATUS_SUCCESS;
664 /* Takes care of both Scan Response and Advertising data */
665 int _bt_hal_set_advertising_data(btgatt_adv_param_setup_t adv_param_setup)
668 uint8_t adv_data[31];
671 GError *error = NULL;
672 GVariant *ret = NULL;
673 GVariant *temp = NULL;
674 GVariantBuilder *builder;
675 bt_hal_adv_event_data_t *event;
679 /* Parse data according to Bluez Interface */
680 if (__bt_hal_is_factory_test_mode()) {
681 ERR("Unable to set advertising data in factory binary !!");
682 return BT_STATUS_UNSUPPORTED;
685 /* TODO: Check adapter and LE adapter status */
686 proxy = _bt_hal_get_adapter_proxy();
688 return BT_STATUS_FAIL;
690 memset(&adv_data, 0, 31);
693 DBG("Service UUID length [%d]", adv_param_setup.service_uuid_len);
694 if (adv_param_setup.service_uuid_len > 0) {
695 __bt_hal_parse_uuid(adv_param_setup.service_uuid_len,
696 adv_param_setup.service_uuid, &adv_data[index], &length, FALSE);
698 DBG("After Service UUID:Index [%d]", index);
702 DBG("Solicit UUID length [%d]", adv_param_setup.solicit_uuid_len);
703 if (adv_param_setup.solicit_uuid_len > 0) {
704 __bt_hal_parse_uuid(adv_param_setup.solicit_uuid_len,
705 adv_param_setup.solicit_uuid, &adv_data[index], &length, TRUE);
707 DBG("After Solicit UUID: Index [%d]", index);
710 /* Service Data UUID*/
711 DBG("Service Data length [%d]", adv_param_setup.service_data_len);
712 if (adv_param_setup.service_data_len > 0) {
713 adv_data[index] = 1 + adv_param_setup.service_data_len;
714 adv_data[index+1] = 0x16; /* Fixed */
715 memcpy(&adv_data[index+2], adv_param_setup.service_data, adv_param_setup.service_data_len);
716 index += (2 + adv_param_setup.service_data_len);
717 length += (2 + adv_param_setup.service_data_len);
718 DBG("After Service data: Index [%d]", index);
722 if (adv_param_setup.appearance > 0) {
723 adv_data[index] = 0x03;
724 adv_data[index+1] = 0x19;
725 adv_data[index+2] = (uint8_t) (adv_param_setup.appearance & 0xFF);
726 adv_data[index+3] = (uint8_t) ((adv_param_setup.appearance >> 8) & 0xFF);
729 DBG("After Apperance: Index [%d]", index);
733 if (adv_param_setup.include_txpower != 0) {
734 adv_data[index] = 0x01;
735 adv_data[index+1] = 0x0A;
738 DBG("After TX Power: Index [%d]", index);
742 if (adv_param_setup.include_name != 0) {
743 adv_data[index] = 0x01;
744 adv_data[index+1] = 0x09;
747 DBG("After Name: Index [%d]", index);
750 /* Manufacturer data */
751 if (adv_param_setup.manufacturer_data_len > 0) {
752 adv_data[index] = 1 + adv_param_setup.manufacturer_data_len;
753 adv_data[index+1] = 0xFF;
754 memcpy(&adv_data[index+2], adv_param_setup.manufacturer_data, adv_param_setup.manufacturer_data_len);
755 index += (2 + adv_param_setup.manufacturer_data_len);
756 length += (2 + adv_param_setup.manufacturer_data_len);
757 DBG("After Manuf Data: Index [%d]", index);
761 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
762 for (i = 0; i < length; i++)
763 g_variant_builder_add(builder, "y", adv_data[i]);
765 temp = g_variant_new("ay", builder);
766 g_variant_builder_unref(builder);
768 DBG("####Adv data length [%d] Index [%d]", length, index);
769 for (i = 0; i < length; i++)
770 DBG("##Data[%d] [0x%x]", i, adv_data[i]);
772 if (adv_param_setup.set_scan_rsp == 0) {
773 /* Set Advertising data to stack */
774 ret = g_dbus_proxy_call_sync(proxy, "SetAdvertisingData",
775 g_variant_new("(@ayi)", temp, adv_param_setup.server_if),
776 G_DBUS_CALL_FLAGS_NONE,
779 /* Set Scan response data to stack */
780 ret = g_dbus_proxy_call_sync(proxy, "SetScanRespData",
781 g_variant_new("(@ayi)", temp, adv_param_setup.server_if),
782 G_DBUS_CALL_FLAGS_NONE,
787 ERR("SetAdvertisingData Fail: %s", error->message);
788 g_clear_error(&error);
789 return BT_STATUS_FAIL;
792 INFO("Set advertising data");
794 g_variant_unref(ret);
797 * As we need to provide async callback to user from HAL, simply schedule a
798 * callback method which will carry actual result
800 event = g_malloc0(sizeof(bt_hal_adv_event_data_t));
801 event->event = BT_HAL_MULTI_ADV_DATA_EVT;
802 event->server_if = adv_param_setup.server_if;
803 event->status = BT_STATUS_SUCCESS;
804 memcpy(&event->data, adv_data, 31);
805 g_idle_add(__bt_hal_adv_event_cb, (gpointer)event);
807 return BT_STATUS_SUCCESS;
810 int _bt_hal_adapter_le_start_scan(void)
813 GError *error = NULL;
818 /* TODO: Check adapter and LE adapter status */
819 proxy = _bt_hal_get_adapter_proxy();
821 return BT_STATUS_FAIL;
823 ret = g_dbus_proxy_call_sync(proxy, "StartLEDiscovery",
824 NULL, G_DBUS_CALL_FLAGS_NONE,
828 ERR("StartLEDiscovery Fail: %s", error->message);
829 g_clear_error(&error);
832 return BT_STATUS_FAIL;
835 g_variant_unref(ret);
838 return BT_STATUS_SUCCESS;
841 int _bt_hal_adapter_le_stop_scan(void)
844 GError *error = NULL;
849 /* TODO: Check adapter and LE adapter status */
850 proxy = _bt_hal_get_adapter_proxy();
852 return BT_STATUS_FAIL;
854 ret = g_dbus_proxy_call_sync(proxy, "StopLEDiscovery",
855 NULL, G_DBUS_CALL_FLAGS_NONE,
859 g_dbus_error_strip_remote_error(error);
860 ERR("StopLEDiscovery Fail: %s", error->message);
862 /* Abnormal case for ARTIK530 */
863 if (g_strrstr(error->message, "No discovery started") ||
864 g_strrstr(error->message, "Operation already in progress")) {
865 g_clear_error(&error);
866 return BT_STATUS_SUCCESS;
869 g_clear_error(&error);
870 return BT_STATUS_FAIL;
874 g_variant_unref(ret);
877 return BT_STATUS_SUCCESS;
881 int _bt_hal_adapter_le_set_scan_parameters(
882 int scan_type, int scan_interval, int scan_window)
885 GError *error = NULL;
890 /* TODO: Check adapter and LE adapter status */
891 proxy = _bt_hal_get_adapter_proxy();
893 return BT_STATUS_FAIL;
895 ret = g_dbus_proxy_call_sync(proxy, "SetScanParameters",
896 g_variant_new("(uuu)", scan_type, scan_interval, scan_window),
897 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
900 ERR("SetScanParameters Fail: %s", error->message);
901 g_clear_error(&error);
904 return BT_STATUS_FAIL;
907 g_variant_unref(ret);
910 return BT_STATUS_SUCCESS;
913 /* To send stack event to hal-av handler */
914 void _bt_hal_register_gatt_le_dbus_handler_cb(handle_stack_msg cb)
916 gatt_le_event_cb = cb;
919 void _bt_hal_unregister_gatt_le_dbus_handler_cb(void)
921 gatt_le_event_cb = NULL;