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"
55 } bt_adapter_le_feature_info_t;
59 gboolean is_multi_adv; /* To be removed once we complete descope Legacy Adv */
61 gboolean is_advertising;
64 } bt_adapter_le_adv_slot_t;
66 static bt_adapter_le_feature_info_t le_feature_info = { 1, 0, 0 };
67 static bt_adapter_le_adv_slot_t *le_adv_slot = NULL;
74 } bt_hal_adv_event_data_t;
77 #define BT_HAL_ADV_CONNECTABLE 0x00 /* ADV_IND */
78 #define BT_HAL_ADV_CONNECTABLE_DIRECT_HIGH 0x01 /* ADV_DIRECT_IND, high duty cycle */
79 #define BT_HAL_ADV_SCANNABLE 0x02 /* ADV_SCAN_IND */
80 #define BT_HAL_ADV_NON_CONNECTABLE 0x03 /* ADV_NONCOND_IND */
81 #define BT_HAL_ADV_CONNECTABLE_DIRECT_LOW 0x04 /* ADV_DIRECT_IND, low duty cycle */
83 #define BT_HAL_ADV_INTERVAL_MIN 20 /* msec */
84 #define BT_HAL_ADV_INTERVAL_MAX 10240
85 #define BT_HAL_ADV_INTERVAL_SPLIT 0.625
86 #define BT_HAL_DEFAULT_ADV_MIN_INTERVAL 500
87 #define BT_HAL_DEFAULT_ADV_MAX_INTERVAL 500
88 #define BT_HAL_ADV_FILTER_POLICY_DEFAULT 0x00
89 #define BT_HAL_ADV_TYPE_DEFAULT 0x00
90 #define BT_HAL_ADV_FILTER_POLICY_ALLOW_SCAN_CONN_WL_ONLY 0x03
92 /* Multi Advertisement callback event */
93 #define BT_HAL_MULTI_ADV_ENB_EVT 1
94 #define BT_HAL_MULTI_ADV_DISABLE_EVT 2
95 #define BT_HAL_MULTI_ADV_PARAM_EVT 3
96 #define BT_HAL_MULTI_ADV_DATA_EVT 4
97 #define BT_HAL_MULTI_ADV_UPDATE_EVT 5
98 #define BT_HAL_LEGACY_ADV_STATUS 6
100 handle_stack_msg gatt_le_event_cb;
102 /* Forward declarations */
103 static gboolean __bt_hal_is_factory_test_mode(void);
104 static void __bt_hal_free_le_adv_slot(void);
105 static gboolean __bt_hal_adv_event_cb(gpointer param);
108 /* Enable LE Adapter */
109 int _bt_hal_le_enable(void)
111 return _bt_hal_dbus_enable_le();
114 /* Disable LE Adapter */
115 int _bt_hal_le_disable(void)
117 return _bt_hal_dbus_disable_le();
121 static void __bt_hal_free_le_adv_slot(void)
125 if (le_adv_slot == NULL)
128 for (i = 0; i < le_feature_info.adv_inst_max; i++)
129 memset(&le_adv_slot[i], 0x00, sizeof(bt_adapter_le_adv_slot_t));
135 void _bt_hal_unregister_adv_slot_owner(int slot_id)
137 if (le_adv_slot == NULL)
139 INFO("Unregister Adv Slot [%d]", slot_id);
140 memset(&le_adv_slot[slot_id], 0x00, sizeof(bt_adapter_le_adv_slot_t));
143 int _bt_hal_get_adv_slot_adv_handle(int slot_id)
145 if (le_adv_slot == NULL)
148 return le_adv_slot[slot_id].adv_handle;
151 gboolean _bt_hal_is_advertising_in_slot(int slot)
153 return le_adv_slot[slot].is_advertising;
156 void _bt_hal_set_advertising_status(int slot_id, gboolean mode)
159 DBG("Advertising enabled [%s] slot [%d]", mode ? "TRUE" : "FALSE", slot_id);
160 bt_hal_adv_event_data_t *event;
162 if (le_adv_slot == NULL)
165 le_adv_slot[slot_id].is_advertising = mode;
167 event = g_malloc0(sizeof(bt_hal_adv_event_data_t));
168 event->event = mode ? BT_HAL_MULTI_ADV_ENB_EVT : BT_HAL_MULTI_ADV_DISABLE_EVT;
169 event->server_if = slot_id;
170 event->status = BT_STATUS_SUCCESS;
171 /* To be removed later when we completely descope Legacy Adv concept */
172 DBG("Is multi ? [%d]", le_adv_slot[slot_id].is_multi_adv);
173 if (le_adv_slot[slot_id].is_multi_adv == FALSE)
174 event->event = BT_HAL_LEGACY_ADV_STATUS;
176 __bt_hal_adv_event_cb((gpointer)event);
179 gboolean _bt_hal_is_advertising(void)
183 for (i = 0; i < le_feature_info.adv_inst_max; i++) {
184 if (le_adv_slot[i].is_advertising == TRUE)
191 int _bt_hal_le_init(void)
193 le_adv_slot = g_malloc0(sizeof(bt_adapter_le_adv_slot_t) * le_feature_info.adv_inst_max);
194 return BT_STATUS_SUCCESS;
196 void _bt_hal_le_deinit(void)
198 __bt_hal_free_le_adv_slot();
200 gboolean _bt_hal_update_le_feature_support(const char *item, const char *value)
202 if (item == NULL || value == NULL)
207 if (g_strcmp0(item, "adv_inst_max") == 0) {
210 slot_num = atoi(value);
212 ERR("ERR:Advertising MAX instance [%d]", slot_num);
216 if (slot_num != le_feature_info.adv_inst_max) {
217 __bt_hal_free_le_adv_slot();
218 le_feature_info.adv_inst_max = slot_num;
219 INFO("Advertising instance max : %d", le_feature_info.adv_inst_max);
220 le_adv_slot = g_malloc0(sizeof(bt_adapter_le_adv_slot_t) * le_feature_info.adv_inst_max);
222 } else if (g_strcmp0(item, "rpa_offloading") == 0) {
223 le_feature_info.rpa_offloading = atoi(value);
224 INFO("RPA offloading : %d", le_feature_info.rpa_offloading);
225 } else if (g_strcmp0(item, "max_filter") == 0) {
226 le_feature_info.max_filter = atoi(value);
227 INFO("BLE Scan max filter : %d", le_feature_info.max_filter);
229 DBG("No registered item");
236 void _bt_hal_free_server_slot(int slot_id)
238 if (le_adv_slot == NULL)
240 memset(&le_adv_slot[slot_id], 0x00, sizeof(bt_adapter_le_adv_slot_t));
243 int _bt_hal_get_available_adv_slot_id(bt_uuid_t *uuid)
247 if (le_adv_slot == NULL) {
248 ERR("le_adv_slot is NULL");
252 DBG("adv_inst_max : %d", le_feature_info.adv_inst_max);
254 for (i = 0; i < le_feature_info.adv_inst_max; i++) {
255 if (le_adv_slot[i].initialized == 0)
257 if (memcmp(uuid->uu, le_adv_slot[i].app_uuid.uu, sizeof(bt_uuid_t)) == 0) {
258 DBG("UUID [%s] matched, return slot [%d]", btuuid2str(uuid->uu), i);
263 for (i = 0; i < le_feature_info.adv_inst_max; i++) {
264 if (le_adv_slot[i].initialized == 0) {
265 DBG("Slot to be allocated [%d] UUID to be registered [%s]",
266 i, btuuid2str(uuid->uu));
267 le_adv_slot[i].initialized = 1;
268 memcpy(&le_adv_slot[i].app_uuid.uu, &uuid->uu, sizeof(bt_uuid_t));
276 void _bt_hal_get_gatt_server_instance_initialized(int *instance)
279 if (le_adv_slot == NULL) {
280 ERR("le_adv_slot is NULL");
284 DBG("adv_inst_max : %d", le_feature_info.adv_inst_max);
286 for (i = 0; i < le_feature_info.adv_inst_max; i++) {
287 if (le_adv_slot[i].initialized == 0)
289 DBG("Initialized Slot found: UUID [%s] slot [%d]", le_adv_slot[i].app_uuid.uu, i);
295 gboolean _bt_is_advertising(void)
300 int _bt_set_advertising(const char *sender, int adv_handle,
301 gboolean enable, gboolean use_reserved_slot)
304 return BT_STATUS_UNSUPPORTED;
307 static int __bt_hal_uuid_type(uint8_t* p_uuid)
313 for (i = 0; i != 16; ++i) {
314 if (i == 12 || i == 13)
317 if (p_uuid[i] == BASE_UUID_CONVERTED[i])
326 return BT_HAL_UUID_32;
328 return BT_HAL_UUID_16;
329 return BT_HAL_UUID_128;
332 static void __bt_hal_parse_uuid(int len, char *src, uint8_t *dest, int *length, int is_solicit)
335 int prev_byte_len = 0;
336 /* dest[index] will contain the length followed by AD Type
337 Move length only when different byte_len is found Ex) 2->4, 2->16, 4->16 etc */
342 /* Create Local buffer & copy source 16 bytes in sequence */
345 memset(&uuid, 0, sizeof(bt_uuid_t));
346 memcpy(&uuid.uu, src, 16);
348 /* Compute current UUID's byte length */
349 byte_len = __bt_hal_uuid_type(uuid.uu);
353 if (prev_byte_len == byte_len) {
354 memcpy(&(dest[dest[index] + 1]), &src[12], byte_len);
358 if (dest[index] != 0)
359 index = dest[index] +1;
360 dest[index] = byte_len + 1;
362 dest[index+1] = 0x14; /* AD Type */
364 dest[index+1] = 0x02; /* AD Type */
365 memcpy(&(dest[index + 2]), &src[12], byte_len);
369 /* Update current type */
370 prev_byte_len = byte_len;
374 if (prev_byte_len == byte_len) {
375 memcpy(&(dest[dest[index] + 1]), &src[12], byte_len);;
379 if (dest[index] != 0)
380 index = dest[index] +1;
381 dest[index] = byte_len + 1;
383 dest[index+1] = 0x1F; /* AD Type */
385 dest[index+1] = 0x04; /* AD Type */
386 memcpy(&(dest[index + 2]), &src[12], byte_len);
389 /* Update current type */
390 prev_byte_len = byte_len;
394 if (dest[index] != 0)
395 index = dest[index] +1;
396 dest[index] = byte_len + 1;
398 dest[index+1] = 0x15; /* AD Type */
400 dest[index+1] = 0x06; /* AD Type */
401 memcpy(&(dest[index + 2]), &src[12], byte_len);
402 /* Update current type */
403 prev_byte_len = byte_len;
408 ERR("Abnormal Byte len [%d]", byte_len);
413 /* Process Next 16 bytes of MW UUID */
420 static gboolean __bt_hal_is_factory_test_mode(void)
424 if (vconf_get_bool(VCONFKEY_BT_DUT_MODE, &mode)) {
425 ERR("Get the DUT Mode fail");
430 INFO("DUT Test Mode !!");
437 static gboolean __bt_hal_adv_event_cb(gpointer param)
439 bt_hal_adv_event_data_t *event = (bt_hal_adv_event_data_t*)param;
445 if (!gatt_le_event_cb) {
446 ERR("GATT event callback not registered!!!");
450 switch (event->event) {
451 case BT_HAL_MULTI_ADV_ENB_EVT: {
452 INFO("BLE Advertising enabled slot [%d]", event->server_if);
453 struct hal_ev_multi_adv_enable ev;
454 memset(&ev, 0, sizeof(struct hal_ev_multi_adv_enable));
455 ev.status = event->status;
456 ev.server_instance = event->server_if;
457 gatt_le_event_cb(HAL_EV_MULTI_ADV_ENABLE, (void *)&ev, sizeof(ev));
460 case BT_HAL_MULTI_ADV_DISABLE_EVT: {
461 INFO("BLE Advertising disabled slot [%d]", event->server_if);
462 struct hal_ev_multi_adv_disable ev;
463 memset(&ev, 0, sizeof(struct hal_ev_multi_adv_disable));
464 ev.status = event->status;
465 ev.server_instance = event->server_if;
466 gatt_le_event_cb(HAL_EV_MULTI_ADV_DISABLE, (void *)&ev, sizeof(ev));
469 case BT_HAL_MULTI_ADV_PARAM_EVT: {
470 INFO("Unhandled event slot [%d]", event->server_if);
473 case BT_HAL_MULTI_ADV_UPDATE_EVT: {
474 INFO("BLE Advertising Param update slot [%d]", event->server_if);
475 struct hal_ev_multi_adv_update ev;
476 memset(&ev, 0, sizeof(struct hal_ev_multi_adv_update));
477 ev.status = event->status;
478 ev.server_instance = event->server_if;
479 gatt_le_event_cb(HAL_EV_MULTI_ADV_UPDATE, (void *)&ev, sizeof(ev));
482 case BT_HAL_MULTI_ADV_DATA_EVT: {
483 INFO("BLE Advertising data set slot [%d]", event->server_if);
484 struct hal_ev_multi_adv_data_set ev_data_set;
486 memset(&ev_data_set, 0, sizeof(struct hal_ev_multi_adv_data_set));
487 ev_data_set.status = event->status;
488 ev_data_set.server_instance = event->server_if;
489 gatt_le_event_cb(HAL_EV_MULTI_ADV_DATA_SET, (void *)&ev_data_set, sizeof(ev_data_set));
492 case BT_HAL_LEGACY_ADV_STATUS: {
493 INFO("BLE Legacy Advertising [%d]", event->server_if);
494 struct hal_ev_legacy_adv_status ev;
496 memset(&ev, 0, sizeof(struct hal_ev_legacy_adv_status));
497 ev.status = event->status;
498 ev.server_instance = event->server_if;
499 gatt_le_event_cb(HAL_EV_LEGACY_ADV_ENABLE, (void *)&ev, sizeof(ev));
503 ERR("Unknown event");
513 int _bt_hal_enable_advertising(int server_if, bool enable, bool is_multi_adv)
516 GError *error = NULL;
520 proxy = _bt_hal_get_adapter_proxy();
522 return BT_STATUS_FAIL;
524 if (le_adv_slot[server_if].is_advertising == TRUE && enable == TRUE)
525 return BT_STATUS_BUSY;
527 if (le_adv_slot[server_if].initialized == TRUE &&
528 le_adv_slot[server_if].is_advertising == FALSE &&
530 return BT_STATUS_DONE;
532 if (le_adv_slot[server_if].hold_timer_id > 0) {
533 g_source_remove(le_adv_slot[server_if].hold_timer_id);
534 le_adv_slot[server_if].hold_timer_id = 0;
537 ret = g_dbus_proxy_call_sync(proxy, "SetAdvertising",
538 g_variant_new("(bi)", enable, server_if),
539 G_DBUS_CALL_FLAGS_NONE,
545 ERR("SetAdvertising Fail: %s", error->message);
546 g_clear_error(&error);
547 return BT_STATUS_FAIL;
550 INFO("Enable advertising [%d] SLot Id [%d] Is Multi? [%d]", enable, server_if, is_multi_adv);
552 g_variant_unref(ret);
554 le_adv_slot[server_if].is_multi_adv = is_multi_adv;
555 le_adv_slot[server_if].is_advertising = enable;
556 return BT_STATUS_SUCCESS;
559 int _bt_hal_set_advertising_params(int server_if, int min_interval,
560 int max_interval, int adv_type,
561 int chnl_map, int tx_power, int timeout_s)
566 GError *error = NULL;
569 bt_hal_adv_event_data_t *event;
572 proxy = _bt_hal_get_adapter_proxy();
574 return BT_STATUS_FAIL;
576 if (min_interval > max_interval ||
577 min_interval < BT_HAL_ADV_INTERVAL_MIN ||
578 max_interval > BT_HAL_ADV_INTERVAL_MAX)
579 return BT_STATUS_PARM_INVALID;
582 if (adv_type == BT_HAL_ADV_CONNECTABLE_DIRECT_HIGH ||
583 adv_type == BT_HAL_ADV_CONNECTABLE_DIRECT_LOW ||
584 adv_type == BT_HAL_ADV_NON_CONNECTABLE)
585 return BT_STATUS_UNSUPPORTED;
588 min = min_interval / BT_HAL_ADV_INTERVAL_SPLIT;
589 max = max_interval / BT_HAL_ADV_INTERVAL_SPLIT;
591 ret = g_dbus_proxy_call_sync(proxy, "SetAdvertisingParameters",
592 g_variant_new("(uuuui)", min, max,
593 BT_HAL_ADV_FILTER_POLICY_DEFAULT, adv_type,
594 server_if), G_DBUS_CALL_FLAGS_NONE,
597 ERR("SetAdvertisingParameters Fail: %s", error->message);
598 g_clear_error(&error);
599 return BT_STATUS_FAIL;
602 INFO("Set advertising data");
604 g_variant_unref(ret);
607 * As we need to provide async callback to user from HAL, simply schedule a
608 * callback method which will carry actual result
610 event = g_malloc0(sizeof(bt_hal_adv_event_data_t));
611 event->event = BT_HAL_MULTI_ADV_UPDATE_EVT;
612 event->server_if = server_if;
613 event->status = BT_STATUS_SUCCESS;
614 g_idle_add(__bt_hal_adv_event_cb, (gpointer)event);
616 return BT_STATUS_SUCCESS;
619 /* Takes care of both Scan Response and Advertising data */
620 int _bt_hal_set_advertising_data(btgatt_adv_param_setup_t adv_param_setup)
623 uint8_t adv_data[31];
626 GError *error = NULL;
627 GVariant *ret = NULL;
628 GVariant *temp = NULL;
629 GVariantBuilder *builder;
630 bt_hal_adv_event_data_t *event;
634 /* Parse data according to Bluez Interface */
635 if (__bt_hal_is_factory_test_mode()) {
636 ERR("Unable to set advertising data in factory binary !!");
637 return BT_STATUS_UNSUPPORTED;
640 /* TODO: Check adapter and LE adapter status */
641 proxy = _bt_hal_get_adapter_proxy();
643 return BT_STATUS_FAIL;
645 memset(&adv_data, 0, 31);
648 DBG("Service UUID length [%d]", adv_param_setup.service_uuid_len);
649 if (adv_param_setup.service_uuid_len > 0) {
650 __bt_hal_parse_uuid(adv_param_setup.service_uuid_len,
651 adv_param_setup.service_uuid, &adv_data[index], &length, FALSE);
653 DBG("After Service UUID:Index [%d]", index);
657 DBG("Solicit UUID length [%d]", adv_param_setup.solicit_uuid_len);
658 if (adv_param_setup.solicit_uuid_len > 0) {
659 __bt_hal_parse_uuid(adv_param_setup.solicit_uuid_len,
660 adv_param_setup.solicit_uuid, &adv_data[index], &length, TRUE);
662 DBG("After Solicit UUID: Index [%d]", index);
665 /* Service Data UUID*/
666 DBG("Service Data length [%d]", adv_param_setup.service_data_len);
667 if (adv_param_setup.service_data_len > 0) {
668 adv_data[index] = 1 + adv_param_setup.service_data_len;
669 adv_data[index+1] = 0x16; /* Fixed */
670 memcpy(&adv_data[index+2], adv_param_setup.service_data, adv_param_setup.service_data_len);
671 index += (2 + adv_param_setup.service_data_len);
672 length += (2 + adv_param_setup.service_data_len);
673 DBG("After Service data: Index [%d]", index);
677 if (adv_param_setup.appearance > 0) {
678 adv_data[index] = 0x03;
679 adv_data[index+1] = 0x19;
680 adv_data[index+2] = (uint8_t) (adv_param_setup.appearance & 0xFF);
681 adv_data[index+3] = (uint8_t) ((adv_param_setup.appearance >> 8) & 0xFF);
684 DBG("After Apperance: Index [%d]", index);
688 if (adv_param_setup.include_txpower != 0) {
689 adv_data[index] = 0x01;
690 adv_data[index+1] = 0x0A;
693 DBG("After TX Power: Index [%d]", index);
697 if (adv_param_setup.include_name != 0) {
698 adv_data[index] = 0x01;
699 adv_data[index+1] = 0x09;
702 DBG("After Name: Index [%d]", index);
705 /* Manufacturer data */
706 if (adv_param_setup.manufacturer_data_len > 0) {
707 adv_data[index] = 1 + adv_param_setup.manufacturer_data_len;
708 adv_data[index+1] = 0xFF;
709 memcpy(&adv_data[index+2], adv_param_setup.manufacturer_data, adv_param_setup.manufacturer_data_len);
710 index += (2 + adv_param_setup.manufacturer_data_len);
711 length += (2 + adv_param_setup.manufacturer_data_len);
712 DBG("After Manuf Data: Index [%d]", index);
716 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
717 for (i = 0; i < length; i++)
718 g_variant_builder_add(builder, "y", adv_data[i]);
720 temp = g_variant_new("ay", builder);
721 g_variant_builder_unref(builder);
723 DBG("####Adv data length [%d] Index [%d]", length, index);
724 for (i = 0; i < length; i++)
725 DBG("##Data[%d] [0x%x]", i, adv_data[i]);
727 if (adv_param_setup.set_scan_rsp == 0) {
728 /* Set Advertising data to stack */
729 ret = g_dbus_proxy_call_sync(proxy, "SetAdvertisingData",
730 g_variant_new("(@ayi)", temp, adv_param_setup.server_if),
731 G_DBUS_CALL_FLAGS_NONE,
734 /* Set Scan response data to stack */
735 ret = g_dbus_proxy_call_sync(proxy, "SetScanRespData",
736 g_variant_new("(@ayi)", temp, adv_param_setup.server_if),
737 G_DBUS_CALL_FLAGS_NONE,
742 ERR("SetAdvertisingData Fail: %s", error->message);
743 g_clear_error(&error);
744 return BT_STATUS_FAIL;
747 INFO("Set advertising data");
749 g_variant_unref(ret);
752 * As we need to provide async callback to user from HAL, simply schedule a
753 * callback method which will carry actual result
755 event = g_malloc0(sizeof(bt_hal_adv_event_data_t));
756 event->event = BT_HAL_MULTI_ADV_DATA_EVT;
757 event->server_if = adv_param_setup.server_if;
758 event->status = BT_STATUS_SUCCESS;
759 memcpy(&event->data, adv_data, 31);
760 g_idle_add(__bt_hal_adv_event_cb, (gpointer)event);
762 return BT_STATUS_SUCCESS;
765 int _bt_hal_adapter_le_start_scan(void)
768 GError *error = NULL;
773 /* TODO: Check adapter and LE adapter status */
774 proxy = _bt_hal_get_adapter_proxy();
776 return BT_STATUS_FAIL;
778 ret = g_dbus_proxy_call_sync(proxy, "StartLEDiscovery",
779 NULL, G_DBUS_CALL_FLAGS_NONE,
783 ERR("StartLEDiscovery Fail: %s", error->message);
784 g_clear_error(&error);
787 return BT_STATUS_FAIL;
790 g_variant_unref(ret);
793 return BT_STATUS_SUCCESS;
796 int _bt_hal_adapter_le_stop_scan(void)
799 GError *error = NULL;
804 /* TODO: Check adapter and LE adapter status */
805 proxy = _bt_hal_get_adapter_proxy();
807 return BT_STATUS_FAIL;
809 ret = g_dbus_proxy_call_sync(proxy, "StopLEDiscovery",
810 NULL, G_DBUS_CALL_FLAGS_NONE,
814 g_dbus_error_strip_remote_error(error);
815 ERR("StopLEDiscovery Fail: %s", error->message);
817 /* Abnormal case for ARTIK530 */
818 if (g_strrstr(error->message, "No discovery started") ||
819 g_strrstr(error->message, "Operation already in progress")) {
820 g_clear_error(&error);
821 return BT_STATUS_SUCCESS;
824 g_clear_error(&error);
825 return BT_STATUS_FAIL;
829 g_variant_unref(ret);
832 return BT_STATUS_SUCCESS;
836 int _bt_hal_adapter_le_set_scan_parameters(
837 int scan_type, int scan_interval, int scan_window)
840 GError *error = NULL;
845 /* TODO: Check adapter and LE adapter status */
846 proxy = _bt_hal_get_adapter_proxy();
848 return BT_STATUS_FAIL;
850 ret = g_dbus_proxy_call_sync(proxy, "SetScanParameters",
851 g_variant_new("(uuu)", scan_type, scan_interval, scan_window),
852 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
855 ERR("SetScanParameters Fail: %s", error->message);
856 g_clear_error(&error);
859 return BT_STATUS_FAIL;
862 g_variant_unref(ret);
865 return BT_STATUS_SUCCESS;
868 /* To send stack event to hal-av handler */
869 void _bt_hal_register_gatt_le_dbus_handler_cb(handle_stack_msg cb)
871 gatt_le_event_cb = cb;
874 void _bt_hal_unregister_gatt_le_dbus_handler_cb(void)
876 gatt_le_event_cb = NULL;