[BluezHAL] Added LE Scan API support 40/123240/1
authorAtul Rai <a.rai@samsung.com>
Thu, 30 Mar 2017 11:48:22 +0000 (17:18 +0530)
committerAtul Rai <a.rai@samsung.com>
Thu, 30 Mar 2017 11:48:22 +0000 (17:18 +0530)
This patch implements following HAL APIs and corresponding
event handling to enable LE scan functionality:
1/ GATT Client register
2/ GATT Client LE scan
3/ GATT Client set scan parameters

Change-Id: I5919f81a3ad230b481b04adfb237f26636730e20
Signed-off-by: Atul Rai <a.rai@samsung.com>
bt-oal/bluez_hal/hardware/bt_gatt_client.h
bt-oal/bluez_hal/inc/bt-hal-msg.h
bt-oal/bluez_hal/src/bt-hal-adapter-le.c
bt-oal/bluez_hal/src/bt-hal-adapter-le.h
bt-oal/bluez_hal/src/bt-hal-event-receiver.c
bt-oal/bluez_hal/src/bt-hal-gatt-client.c
bt-oal/bluez_hal/src/bt-hal-gatt-client.h [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-gatt-server.c
bt-oal/bluez_hal/src/bt-hal-gatt-server.h
bt-oal/bluez_hal/src/bt-hal-gatt.c

index 31ec30d..21bde80 100644 (file)
 
 __BEGIN_DECLS
 
+#ifdef TIZEN_BT_HAL
+#define BT_GATTC_LE_SCAN_TYPE_PASSIVE  0x00
+#define BT_GATTC_LE_SCAN_TYPE_ACTIVE   0x01
+#endif
+
 /** Buffer type for unformatted reads/writes */
 typedef struct
 {
@@ -341,7 +346,11 @@ typedef struct {
     bt_status_t (*scan_filter_enable)(int client_if, bool enable);
 
     /** Sets the LE scan interval and window in units of N*0.625 msec */
+#ifdef TIZEN_BT_HAL
+    bt_status_t (*set_scan_parameters)(int scan_type, int scan_interval, int scan_window);
+#else
     bt_status_t (*set_scan_parameters)(int scan_interval, int scan_window);
+#endif
 
     /* Configure the batchscan storage */
     bt_status_t (*batchscan_cfg_storage)(int client_if, int batch_scan_full_max,
index 81c44c0..b0ac5ee 100644 (file)
@@ -476,4 +476,21 @@ struct hal_ev_legacy_adv_status {
         uint32_t server_instance;
 } __attribute__((packed));
 
+#define HAL_EV_GATT_CLIENT_REGISTERED  0xAA
+struct hal_ev_gatt_client_registered {
+        uint32_t status;
+        uint32_t client_if;
+        uint8_t app_uuid[16];
+} __attribute__((packed));
+
+#define HAL_EV_GATT_CLIENT_SCAN_RESULT  0xAC
+struct hal_ev_gatt_client_scan_result {
+       uint8_t  bd_addr[6];
+       uint8_t  addr_type;
+       uint8_t  adv_type;
+       int32_t  rssi;
+       uint16_t len;
+       uint8_t  adv_data[0];
+} __attribute__((packed));
+
 #endif //_BT_HAL_MSG_H_
index ec820e4..c5cad7e 100644 (file)
@@ -97,6 +97,8 @@ typedef struct {
 #define BT_HAL_MULTI_ADV_UPDATE_EVT        5
 #define BT_HAL_LEGACY_ADV_STATUS           6
 
+handle_stack_msg gatt_le_event_cb;
+
 /* Forward declarations */
 static gboolean __bt_hal_is_factory_test_mode(void);
 static void __bt_hal_free_le_adv_slot(void);
@@ -378,15 +380,13 @@ static gboolean __bt_hal_is_factory_test_mode(void)
 
 static gboolean __bt_hal_adv_event_cb(gpointer param)
 {
-       handle_stack_msg event_cb;
        bt_hal_adv_event_data_t *event = (bt_hal_adv_event_data_t*)param;
        DBG("+");
 
        if (!event)
                return FALSE;
 
-       event_cb = _bt_hal_get_gatt_event();
-       if (!event_cb) {
+       if (!gatt_le_event_cb) {
                ERR("GATT event callback not registered!!!");
                return FALSE;
        }
@@ -397,7 +397,7 @@ static gboolean __bt_hal_adv_event_cb(gpointer param)
                memset(&ev, 0, sizeof(struct hal_ev_multi_adv_enable));
                ev.status = event->status;
                ev.server_instance = event->server_if;
-               event_cb(HAL_EV_MULTI_ADV_ENABLE, (void *)&ev, sizeof(ev));
+               gatt_le_event_cb(HAL_EV_MULTI_ADV_ENABLE, (void *)&ev, sizeof(ev));
                INFO("BLE Advertising enabled slot [%d]", event->server_if);
                break;
        }
@@ -406,7 +406,7 @@ static gboolean __bt_hal_adv_event_cb(gpointer param)
                memset(&ev, 0, sizeof(struct hal_ev_multi_adv_disable));
                ev.status = event->status;
                ev.server_instance = event->server_if;
-               event_cb(HAL_EV_MULTI_ADV_DISABLE, (void *)&ev, sizeof(ev));
+               gatt_le_event_cb(HAL_EV_MULTI_ADV_DISABLE, (void *)&ev, sizeof(ev));
                INFO("BLE Advertising disabled slot [%d]", event->server_if);
                break;
        }
@@ -419,7 +419,7 @@ static gboolean __bt_hal_adv_event_cb(gpointer param)
                memset(&ev, 0, sizeof(struct hal_ev_multi_adv_update));
                ev.status = event->status;
                ev.server_instance = event->server_if;
-               event_cb(HAL_EV_MULTI_ADV_UPDATE, (void *)&ev, sizeof(ev));
+               gatt_le_event_cb(HAL_EV_MULTI_ADV_UPDATE, (void *)&ev, sizeof(ev));
                INFO("BLE Advertising Param update slot [%d]", event->server_if);
                break;
        }
@@ -430,7 +430,7 @@ static gboolean __bt_hal_adv_event_cb(gpointer param)
                memset(&ev_data_set, 0, sizeof(struct hal_ev_multi_adv_data_set));
                ev_data_set.status = event->status;
                ev_data_set.server_instance = event->server_if;
-               event_cb(HAL_EV_MULTI_ADV_DATA_SET, (void *)&ev_data_set, sizeof(ev_data_set));
+               gatt_le_event_cb(HAL_EV_MULTI_ADV_DATA_SET, (void *)&ev_data_set, sizeof(ev_data_set));
                break;
        }
        case BT_HAL_LEGACY_ADV_STATUS: {
@@ -440,7 +440,7 @@ static gboolean __bt_hal_adv_event_cb(gpointer param)
                memset(&ev, 0, sizeof(struct hal_ev_legacy_adv_status));
                ev.status = event->status;
                ev.server_instance = event->server_if;
-               event_cb(HAL_EV_LEGACY_ADV_ENABLE, (void *)&ev, sizeof(ev));
+               gatt_le_event_cb(HAL_EV_LEGACY_ADV_ENABLE, (void *)&ev, sizeof(ev));
                break;
        }
        default:
@@ -704,3 +704,110 @@ int _bt_hal_set_advertising_data(btgatt_adv_param_setup_t adv_param_setup)
 
         return BT_STATUS_SUCCESS;
 }
+
+int _bt_hal_adapter_le_start_scan(void)
+{
+       GDBusProxy *proxy;
+       GError *error = NULL;
+       GVariant *ret;
+
+       DBG("+");
+
+       /* TODO: Check adapter and LE adapter status */
+       proxy = _bt_get_adapter_proxy();
+       if (proxy == NULL)
+               return BT_STATUS_FAIL;
+
+       ret = g_dbus_proxy_call_sync(proxy, "StartLEDiscovery",
+                       NULL, G_DBUS_CALL_FLAGS_NONE,
+                       -1, NULL, &error);
+       if (ret == NULL) {
+               if (error) {
+                       ERR("StartLEDiscovery Fail: %s", error->message);
+                       g_clear_error(&error);
+               }
+
+               return BT_STATUS_FAIL;
+       }
+
+       g_variant_unref(ret);
+
+       DBG("-");
+       return BT_STATUS_SUCCESS;
+}
+
+int _bt_hal_adapter_le_stop_scan(void)
+{
+       GDBusProxy *proxy;
+       GError *error = NULL;
+       GVariant *ret;
+
+       DBG("+");
+
+       /* TODO: Check adapter and LE adapter status */
+       proxy = _bt_get_adapter_proxy();
+       if (proxy == NULL)
+               return BT_STATUS_FAIL;
+
+       ret = g_dbus_proxy_call_sync(proxy, "StopLEDiscovery",
+                       NULL, G_DBUS_CALL_FLAGS_NONE,
+                       -1, NULL, &error);
+       if (ret == NULL) {
+               if (error) {
+                       ERR("StopLEDiscovery Fail: %s", error->message);
+                       g_clear_error(&error);
+               }
+
+               return BT_STATUS_FAIL;
+       }
+
+
+       g_variant_unref(ret);
+
+       DBG("-");
+       return BT_STATUS_SUCCESS;
+}
+
+
+int _bt_hal_adapter_le_set_scan_parameters(
+               int scan_type, int scan_interval, int scan_window)
+{
+       GDBusProxy *proxy;
+       GError *error = NULL;
+       GVariant *ret;
+
+       DBG("+");
+
+       /* TODO: Check adapter and LE adapter status */
+       proxy = _bt_get_adapter_proxy();
+       if (proxy == NULL)
+               return BT_STATUS_FAIL;
+
+       ret = g_dbus_proxy_call_sync(proxy, "SetScanParameters",
+                       g_variant_new("(uuu)", scan_type, scan_interval, scan_window),
+                       G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+       if (ret == NULL) {
+               if (error) {
+                       ERR("SetScanParameters Fail: %s", error->message);
+                       g_clear_error(&error);
+               }
+
+               return BT_STATUS_FAIL;
+       }
+
+       g_variant_unref(ret);
+
+       DBG("-");
+       return BT_STATUS_SUCCESS;
+}
+
+/* To send stack event to hal-av handler */
+void _bt_hal_register_gatt_le_dbus_handler_cb(handle_stack_msg cb)
+{
+       gatt_le_event_cb = cb;
+}
+
+void _bt_hal_unregister_gatt_le_dbus_handler_cb(void)
+{
+       gatt_le_event_cb = NULL;
+}
index 6430abc..697bd64 100644 (file)
 
 #include <hardware/bt_gatt_server.h>
 
+#include "bt-hal-event-receiver.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+void _bt_hal_register_gatt_le_dbus_handler_cb(handle_stack_msg cb);
+
+void _bt_hal_unregister_gatt_le_dbus_handler_cb();
+
 gboolean _bt_hal_update_le_feature_support(const char *item, const char *value);
 
 int _bt_hal_get_available_adv_slot_id(bt_uuid_t *uuid);
@@ -51,6 +57,13 @@ int _bt_hal_set_advertising_params(int server_if, int min_interval,
 
 int _bt_hal_enable_advertising(int server_if, bool enable, bool is_multi_adv);
 
+int _bt_hal_adapter_le_start_scan(void);
+
+int _bt_hal_adapter_le_stop_scan(void);
+
+int _bt_hal_adapter_le_set_scan_parameters(
+               int scan_type, int scan_interval, int scan_window);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index 4fd7711..10b28ec 100644 (file)
@@ -103,6 +103,8 @@ static int __bt_hal_register_audio_subscribe_signal(GDBusConnection *conn, int s
 static void __bt_hal_handle_headset_events(GVariant *msg, const char *member,const char *path);
 static void __bt_hal_send_hf_audio_connection_state_event(gboolean connected, const char *address);
 
+static void __bt_hal_handle_adv_report(GVariant *msg, const char *path);
+
 static gboolean __bt_hal_discovery_finished_cb(gpointer user_data)
 {
        event_id = 0;
@@ -373,8 +375,33 @@ static void __bt_hal_adapter_property_changed_event(GVariant *msg)
                        }
 
                } else if (!g_strcmp0(key, "LEDiscovering")) {
+                       GVariant *result;
+
                        is_le_discovering = g_variant_get_boolean(value);
                        DBG("##LE Discovering = [%d]", is_le_discovering);
+
+                       if (is_le_discovering)
+                               continue;
+
+                       adapter_proxy = _bt_get_adapter_proxy();
+                       if (adapter_proxy == NULL) {
+                               ERR("adapter_proxy == NULL");
+                               continue;
+                       }
+
+                       /* Need to stop searching */
+                       result = g_dbus_proxy_call_sync(adapter_proxy, "StopLEDiscovery",
+                                       NULL, G_DBUS_CALL_FLAGS_NONE,
+                                       DBUS_TIMEOUT, NULL, &err);
+                       if (!result) {
+                               ERR("Error occured in Proxy call");
+                               if (err) {
+                                       ERR("(Error: %s)", err->message);
+                                       g_clear_error(&err);
+                               }
+                               continue;
+                       }
+                       g_variant_unref(result);
                } else if (!g_strcmp0(key, "Modalias")) {
                        char *modalias = NULL;
                        g_variant_get(value, "s", &modalias);
@@ -1679,9 +1706,58 @@ static void __bt_hal_handle_device_specific_events(GVariant *msg, const char *me
                g_free(address);
                g_free(profile_uuid);
        } else if (strcasecmp(member, "AdvReport") == 0) {
-               /* TODO */
                DBG("Member: [%s]", member);
+               __bt_hal_handle_adv_report(msg, path);
+       }
+}
+
+static void __bt_hal_handle_adv_report(GVariant *msg, const char *path)
+{
+       uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
+       struct hal_ev_gatt_client_scan_result *ev = (void *)buf;
+       size_t size = 0;
+       char *address = NULL;
+       GVariant *value = NULL;
+       char *buffer = NULL;
+       int data_len = 0;
+       int buffer_len = 0;
+       uint8_t addr_type = 0;
+       uint8_t adv_type = 0;
+       int rssi = 0;
+
+       if (!gatt_event_cb)
+               return;
+
+       memset(buf, 0, sizeof(buf));
+       size = sizeof(*ev);
+
+       g_variant_get(msg, "(&syyii@ay)", &address, &addr_type,
+                       &adv_type, &rssi, &data_len, &value);
+
+       buffer_len = g_variant_get_size(value);
+       if (buffer_len > 0)
+               buffer = (char *)g_variant_get_data(value);
+
+       if (data_len != buffer_len) {
+               ERR("Unexpected: buffer_len: %d, data_len: %d",
+                               buffer_len, data_len);
+               data_len = buffer_len;
        }
+
+       DBG("Address: %s, len: %d, rssi: %d, addr_type: 0x%02X, adv_type: 0x%02X",
+                       address, data_len, rssi, addr_type, adv_type);
+
+       _bt_convert_addr_string_to_type(ev->bd_addr, address);
+       ev->addr_type = addr_type;
+       ev->adv_type = adv_type;
+       ev->rssi = rssi;
+       ev->len = data_len;
+       memcpy(ev->adv_data, buffer, data_len);
+       size += data_len;
+
+       DBG("Send le scan result event to HAL, size: [%d]", size);
+       gatt_event_cb(HAL_EV_GATT_CLIENT_SCAN_RESULT, buf, size);
+       g_variant_unref(value);
 }
 
 /* AVRCP Controller Role(Remote:AVRCP Target) Events */
index c625c39..b87a352 100644 (file)
 #include <stdlib.h>
 #include <errno.h>
 #include <string.h>
+#include <dlog.h>
+
+#include "bt-hal-log.h"
+#include "bt-hal-msg.h"
+#include "bt-hal-event-receiver.h"
+#include "bt-hal-adapter-le.h"
+
+#include "bt-hal-gatt-client.h"
+
+/************************************************************************************
+ **  Static variables
+ ************************************************************************************/
+extern const btgatt_callbacks_t *bt_gatt_callbacks;
+#define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
+{\
+       ERR("%s: BTGATT not initialized", __FUNCTION__);\
+       return BT_STATUS_NOT_READY;\
+} else {\
+       DBG("%s", __FUNCTION__);\
+}
+
+typedef struct {
+       uint32_t client_if;
+       bt_uuid_t uuid;
+} hal_registered_client_t;
+
+#ifdef TIZEN_BT_HAL
+int le_scan_type = BT_GATTC_LE_SCAN_TYPE_PASSIVE;
+#endif
+
+static handle_stack_msg event_cb = NULL;
+
+/* To send stack event to hal-av handler */
+void _bt_hal_register_gatt_client_handler_cb(handle_stack_msg cb)
+{
+       event_cb = cb;
+}
+
+void _bt_hal_unregister_gatt_client_handler_cb(void)
+{
+       event_cb = NULL;
+}
+
+#ifdef TIZEN_BT_HAL
+int _bt_hal_gatt_client_get_le_scan_type(void)
+{
+       return le_scan_type;
+}
+#endif
+
+static gboolean __bt_hal_register_client_cb(gpointer user_data)
+{
+       struct hal_ev_gatt_client_registered ev;
+       hal_registered_client_t *client_info = user_data;
+
+       /* Prepare to send AV connecting event */
+       memset(&ev, 0, sizeof(ev));
+       ev.status = BT_STATUS_SUCCESS;
+       ev.client_if = client_info->client_if;
+       memcpy(ev.app_uuid, client_info->uuid.uu, sizeof(ev.app_uuid));
+
+       if (!event_cb)
+               ERR("GATT Callback not registered");
+       else {
+               DBG("GATT client registered, client_if: [%d]", client_info->client_if);
+               event_cb(HAL_EV_GATT_CLIENT_REGISTERED, (void *)&ev, sizeof(ev));
+       }
+
+       g_free(user_data);
+       return FALSE;
+}
+
+/** Registers a GATT client application with the stack */
+bt_status_t register_client(bt_uuid_t *uuid)
+{
+       hal_registered_client_t *client_info = NULL;
+
+       client_info = g_malloc0(sizeof(hal_registered_client_t));
+       /*
+        * TODO: Actual client_if will be used here later when GATT register_client
+        * is implemented compeltely. For now return 1 as client_if.
+        */
+       client_info->client_if = 1;
+       memcpy(client_info->uuid.uu, uuid->uu, sizeof(bt_uuid_t));
+
+       /*
+        * As we need to provide async callback to user from HAL, simply schedule a
+        * callback method which will carry actual result
+        */
+       g_idle_add(__bt_hal_register_client_cb, (gpointer)client_info);
+
+       /* If available, then return success, else return error */
+       return BT_STATUS_SUCCESS;
+}
+
+/* TODO: APIs will be implemented in subsequent patches whenever required */
+/** Unregister a client application from the stack */
+bt_status_t unregister_client(int client_if)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/** Start or stop LE device scanning */
+bt_status_t scan(int client_if, bool start)
+{
+       int ret;
+
+       CHECK_BTGATT_INIT();
+
+       if (start)
+               ret = _bt_hal_adapter_le_start_scan();
+       else
+               ret = _bt_hal_adapter_le_stop_scan();
+
+       return ret;
+}
+
+/** Create a connection to a remote LE or dual-mode device */
+bt_status_t connect(int client_if, const bt_bdaddr_t *bd_addr,
+               bool is_direct)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/** Disconnect a remote device or cancel a pending connection */
+bt_status_t disconnect(int client_if, const bt_bdaddr_t *bd_addr,
+               int conn_id)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/** Clear the attribute cache for a given device */
+bt_status_t refresh(int client_if, const bt_bdaddr_t *bd_addr)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/**
+ * Enumerate all GATT services on a connected device.
+ * Optionally, the results can be filtered for a given UUID.
+ */
+bt_status_t search_service(int conn_id, bt_uuid_t *filter_uuid)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/**
+ * Enumerate included services for a given service.
+ * Set start_incl_srvc_id to NULL to get the first included service.
+ */
+bt_status_t get_included_service(int conn_id, btgatt_srvc_id_t *srvc_id,
+               btgatt_srvc_id_t *start_incl_srvc_id)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/**
+ * Enumerate characteristics for a given service.
+ * Set start_char_id to NULL to get the first characteristic.
+ */
+bt_status_t get_characteristic(int conn_id,
+               btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/**
+ * Enumerate descriptors for a given characteristic.
+ * Set start_descr_id to NULL to get the first descriptor.
+ */
+bt_status_t get_descriptor(int conn_id,
+               btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
+               btgatt_gatt_id_t *start_descr_id)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/** Read a characteristic on a remote device */
+bt_status_t read_characteristic(int conn_id,
+               btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
+               int auth_req)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/** Write a remote characteristic */
+bt_status_t write_characteristic(int conn_id,
+               btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
+               int write_type, int len, int auth_req,
+               char* p_value)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/** Read the descriptor for a given characteristic */
+bt_status_t read_descriptor(int conn_id,
+               btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
+               btgatt_gatt_id_t *descr_id, int auth_req)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+/** Write a remote descriptor for a given characteristic */
+bt_status_t write_descriptor(int conn_id,
+               btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
+               btgatt_gatt_id_t *descr_id, int write_type, int len,
+               int auth_req, char* p_value)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/** Execute a prepared write operation */
+bt_status_t execute_write(int conn_id, int execute)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/**
+ * Register to receive notifications or indications for a given
+ * characteristic
+ */
+bt_status_t register_for_notification(int client_if,
+               const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
+               btgatt_gatt_id_t *char_id)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/** Deregister a previous request for notifications/indications */
+bt_status_t deregister_for_notification(int client_if,
+               const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
+               btgatt_gatt_id_t *char_id)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/** Request RSSI for a given remote device */
+bt_status_t read_remote_rssi(int client_if, const bt_bdaddr_t *bd_addr)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/** OTA firmware download */
+bt_status_t ota_fw_update(int client_if, int conn_id, const bt_bdaddr_t *bd_addr, char* path)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
+int get_device_type(const bt_bdaddr_t *bd_addr)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/** Request a connection parameter update */
+bt_status_t conn_parameter_update(bt_bdaddr_t *bd, int min_int, int max_int, int latency, int timeout)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/** Test mode interface */
+bt_status_t test_command(int command, btgatt_test_params_t* params)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/** MTU Exchange request from client */
+bt_status_t configure_mtu(int conn_id, int mtu)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/** Setup scan filter params */
+bt_status_t scan_filter_param_setup(int client_if, int action, int filt_index, int feat_seln,
+               int list_logic_type, int filt_logic_type, int rssi_high_thres,
+               int rssi_low_thres, int dely_mode, int found_timeout,
+               int lost_timeout, int found_timeout_cnt)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+
+/** Configure a scan filter condition */
+bt_status_t scan_filter_add_remove(int client_if, int action, int filt_type,
+               int filt_index, int company_id,
+               int company_id_mask, const bt_uuid_t *p_uuid,
+               const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
+               char addr_type, int data_len, char* p_data, int mask_len,
+               char* p_mask)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/** Clear all scan filter conditions for specific filter index*/
+bt_status_t scan_filter_clear(int client_if, int filt_index)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/** Enable / disable scan filter feature*/
+bt_status_t scan_filter_enable(int client_if, bool enable)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/** Sets the LE scan interval and window in units of N*0.625 msec */
+#ifdef TIZEN_BT_HAL
+bt_status_t set_scan_parameters(int scan_type, int scan_interval, int scan_window)
+{
+       int ret;
+
+       CHECK_BTGATT_INIT();
+
+       le_scan_type = scan_type;
+       ret = _bt_hal_adapter_le_set_scan_parameters(
+                       scan_type, scan_interval, scan_window);
+       return ret;
+}
+#else
+bt_status_t set_scan_parameters(int scan_interval, int scan_window)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+#endif
+
+/* Configure the batchscan storage */
+bt_status_t batchscan_cfg_storage(int client_if, int batch_scan_full_max,
+               int batch_scan_trunc_max, int batch_scan_notify_threshold)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/* Enable batchscan */
+bt_status_t batchscan_enb_batch_scan(int client_if, int scan_mode,
+               int scan_interval, int scan_window, int addr_type, int discard_rule)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/* Disable batchscan */
+bt_status_t batchscan_dis_batch_scan(int client_if)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
+
+/* Read out batchscan reports */
+bt_status_t batchscan_read_reports(int client_if, int scan_mode)
+{
+       CHECK_BTGATT_INIT();
+       return BT_STATUS_UNSUPPORTED;
+}
 
-/*TODO*/
 const btgatt_client_interface_t btgatt_client_interface = {
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
+       register_client,
+       unregister_client,
+       scan,
+       connect,
+       disconnect,
+       refresh,
+       search_service,
+       get_included_service,
+       get_characteristic,
+       get_descriptor,
+       read_characteristic,
+       write_characteristic,
+       read_descriptor,
+       write_descriptor,
+       execute_write,
+       register_for_notification,
+       deregister_for_notification,
+       read_remote_rssi,
+       ota_fw_update,
+       get_device_type,
+       conn_parameter_update,
+       test_command,
+       configure_mtu,
+       scan_filter_param_setup,
+       scan_filter_add_remove,
+       scan_filter_clear,
+       scan_filter_enable,
+       set_scan_parameters,
+       batchscan_cfg_storage,
+       batchscan_enb_batch_scan,
+       batchscan_dis_batch_scan,
+       batchscan_read_reports
 };
diff --git a/bt-oal/bluez_hal/src/bt-hal-gatt-client.h b/bt-oal/bluez_hal/src/bt-hal-gatt-client.h
new file mode 100644 (file)
index 0000000..cb7f2f2
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * BLUETOOOTH HAL
+ *
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:  Atul Rai <a.rai@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *              http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _BT_HAL_GATT_CLIENT_H_
+#define _BT_HAL_GATT_CLIENT_H_
+
+#include <glib.h>
+#include <sys/types.h>
+
+#include "bt-hal.h"
+#include "bt-hal-log.h"
+#include "bt-hal-msg.h"
+
+#include "bt-hal-event-receiver.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void _bt_hal_register_gatt_client_handler_cb(handle_stack_msg cb);
+void _bt_hal_unregister_gatt_client_handler_cb(void);
+
+#ifdef TIZEN_BT_HAL
+int _bt_hal_gatt_client_get_le_scan_type(void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /*_BT_HAL_GATT_CLIENT_H_*/
index fa5cfb4..077d1ba 100644 (file)
@@ -64,12 +64,12 @@ typedef struct {
 /* To send stack event to hal-av handler */
 void _bt_hal_register_gatt_server_handler_cb(handle_stack_msg cb)
 {
-        event_cb = cb;
+       event_cb = cb;
 }
 
-handle_stack_msg _bt_hal_get_gatt_event(void)
+void _bt_hal_unregister_gatt_server_handler_cb(void)
 {
-       return event_cb;
+       event_cb = NULL;
 }
 
 static gboolean __bt_hal_register_slot_id_cb(gpointer user_data)
@@ -116,11 +116,11 @@ static bt_status_t gatt_server_register_app(bt_uuid_t *uuid)
        }
 
        /*
-         * 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
+        */
        memcpy(user_data->uuid.uu, uuid->uu, sizeof(bt_uuid_t));
-        g_idle_add(__bt_hal_register_slot_id_cb, (gpointer)user_data);
+       g_idle_add(__bt_hal_register_slot_id_cb, (gpointer)user_data);
 
        /* If available, then return success, else return error */
        return BT_STATUS_SUCCESS;
@@ -239,7 +239,7 @@ static bt_status_t gatt_server_multi_adv_update(int server_if, int min_interval,
        DBG("+");
        /* Send Advertising parameters to LE Module */
        return _bt_hal_set_advertising_params(server_if, min_interval, max_interval, adv_type,
-                chnl_map, tx_power, timeout_s);
+                       chnl_map, tx_power, timeout_s);
 }
 
 static bt_status_t gatt_server_multi_adv_set_inst_data(btgatt_adv_param_setup_t adv_param_setup)
index 03a27d0..dc6f526 100644 (file)
@@ -37,7 +37,7 @@ extern "C" {
 
 void _bt_hal_register_gatt_server_handler_cb(handle_stack_msg cb);
 
-handle_stack_msg _bt_hal_get_gatt_event(void);
+void _bt_hal_unregister_gatt_server_handler_cb(void);
 
 #ifdef __cplusplus
 }
index 440d374..f0cba77 100644 (file)
@@ -3,28 +3,28 @@
  *
  * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
  *
- * Contact:  Anupam Roy <anupam.r@samsung.com>
+ * Contact: Anupam Roy <anupam.r@samsung.com>
  *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at:
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
  *
- *  http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  *
  */
 
 
 /*******************************************************************************
  *
- *  Filename:      btif_gatt.c
+ * Filename:   btif_gatt.c
  *
- *  Description:   GATT Profile Bluetooth Interface
+ * Description:        GATT Profile Bluetooth Interface
  *
  *******************************************************************************/
 
 #include "bt-hal-msg.h"
 #include "bt-hal-utils.h"
 
+#include "bt-hal-adapter-le.h"
 #include "bt-hal-gatt-server.h"
+#include "bt-hal-gatt-client.h"
 
+/* Advertising report event types */
+#define BT_LE_ADV_IND  0x00
+#define BT_LE_ADV_DIRECT_IND   0x01
+#define BT_LE_ADV_SCAN_IND     0x02
+#define BT_LE_ADV_NONCONN_IND  0x03
+#define BT_LE_ADV_SCAN_RSP     0x04
+
+#define BT_HAL_ADV_DATA_MAX_SIZE       31
+typedef struct {
+       char addr[18];
+       uint8_t addr_type;
+       uint8_t adv_type;
+       int rssi;
+       int data_len;
+       uint8_t data[BT_HAL_ADV_DATA_MAX_SIZE * 2];
+       guint timer_id;
+} bt_hal_le_adv_info_t;
+
+/****************************************** Global Variables ******************************************/
 const btgatt_callbacks_t *bt_gatt_callbacks = NULL;
 
 extern btgatt_client_interface_t btgatt_client_interface;
 extern btgatt_server_interface_t btgatt_server_interface;
 
+static GSList *adv_ind_list = NULL;
+/****************************************** Forward Declarations *************************************/
+static void __bt_handle_gatt_client_registered(void *buf, uint16_t len);
+static void __bt_hal_handle_gatt_client_scan_result(void *buf, uint16_t len);
+/*****************************************************************************************************/
+
 static bool interface_ready(void)
 {
-        return bt_gatt_callbacks != NULL;
+       return bt_gatt_callbacks != NULL;
 }
 
 static void __bt_hal_handle_server_instance_initialized(void *buf, uint16_t len)
@@ -134,6 +161,14 @@ static void __bt_hal_gatt_events(int message, void *buf, uint16_t len)
                __bt_hal_handle_legacy_adv_status(buf, len);
                break;
        }
+       case HAL_EV_GATT_CLIENT_REGISTERED: {
+               __bt_handle_gatt_client_registered(buf, len);
+               break;
+       }
+       case HAL_EV_GATT_CLIENT_SCAN_RESULT: {
+               __bt_hal_handle_gatt_client_scan_result(buf, len);
+               break;
+       }
        default:
                DBG("Event Currently not handled!!");
                break;
@@ -141,59 +176,189 @@ static void __bt_hal_gatt_events(int message, void *buf, uint16_t len)
        DBG("-");
 }
 
+/************************************* GATT CLIENT EVENTS ****************************************/
+static void __bt_handle_gatt_client_registered(void *buf, uint16_t len)
+{
+       struct hal_ev_gatt_client_registered *ev = buf;
+       bt_uuid_t uuid;
+
+       memcpy(uuid.uu, ev->app_uuid, 16);
+       if (bt_gatt_callbacks->client->register_client_cb)
+               bt_gatt_callbacks->client->register_client_cb(
+                               ev->status, ev->client_if, &uuid);
+}
+
+static void __bt_hal_send_le_scan_result_event(bt_hal_le_adv_info_t *adv_info)
+{
+       bt_bdaddr_t bd_addr;
+
+       str2bt_bdaddr_t(adv_info->addr, &bd_addr);
+       if (bt_gatt_callbacks->client->scan_result_cb)
+               bt_gatt_callbacks->client->scan_result_cb(
+                               &bd_addr, adv_info->rssi, adv_info->data);
+}
+
+static bt_hal_le_adv_info_t *__bt_hal_get_adv_ind_info(char *addr)
+{
+       GSList *l;
+
+       if (!addr)
+               return NULL;
+
+       for (l = adv_ind_list; NULL != l; l = g_slist_next(l)) {
+               bt_hal_le_adv_info_t *adv_info = l->data;
+
+               if (!adv_info)
+                       continue;
+
+               if (!g_strcmp0(adv_info->addr, addr))
+                       return adv_info;
+       }
+
+       return NULL;
+}
+
+static int __bt_hal_add_adv_ind_info(bt_hal_le_adv_info_t *adv_info)
+{
+       if (!adv_info)
+               return -1;
+
+       if (__bt_hal_get_adv_ind_info(adv_info->addr) != NULL) {
+               DBG("Adv info already present");
+               return -1;
+       }
+
+       adv_ind_list = g_slist_append(adv_ind_list, adv_info);
+       return 0;
+}
+
+static gboolean __bt_hal_adv_scan_req_timeout_cb(gpointer user_data)
+{
+       bt_hal_le_adv_info_t *adv_info = user_data;
+
+       __bt_hal_send_le_scan_result_event(adv_info);
+       adv_ind_list = g_slist_remove(adv_ind_list, adv_info);
+       g_free(adv_info);
+       return FALSE;
+}
+
+static void __bt_hal_handle_gatt_client_scan_result(void *buf, uint16_t len)
+{
+       bt_bdaddr_t bd_addr;
+       char address[18];
+       struct hal_ev_gatt_client_scan_result *ev = buf;
+       bt_hal_le_adv_info_t *adv_info;
+       int data_len = 0;
+
+       memcpy(bd_addr.address, ev->bd_addr, 6);
+       bt_bdaddr_t2str(&bd_addr, address);
+       data_len = (ev->len < BT_HAL_ADV_DATA_MAX_SIZE) ? ev->len : BT_HAL_ADV_DATA_MAX_SIZE;
+       if (data_len == 0 && ev->adv_type != BT_LE_ADV_SCAN_RSP) {
+               ERR("Unexpected: Data len is 0");
+               return;
+       }
+
+       if (ev->adv_type == BT_LE_ADV_SCAN_RSP) { /* SCAN_RSP */
+               adv_info = __bt_hal_get_adv_ind_info(address);
+               if (adv_info) {
+                       /* Copy scan response data in data field and send event */
+                       memcpy(&(adv_info->data[adv_info->data_len]), ev->adv_data, data_len);
+                       __bt_hal_send_le_scan_result_event(adv_info);
+                       adv_ind_list = g_slist_remove(adv_ind_list, adv_info);
+                       if (adv_info->timer_id)
+                               g_source_remove(adv_info->timer_id);
+                       g_free(adv_info);
+               }
+               return;
+       }
+
+       /* ADV_IND */
+       adv_info = g_malloc0(sizeof(bt_hal_le_adv_info_t));
+       if (!adv_info) {
+               ERR("Not enough memory");
+               return;
+       }
+
+       g_strlcpy(adv_info->addr, address, 18);
+       adv_info->addr_type = ev->addr_type;
+       adv_info->adv_type = ev->adv_type;
+       adv_info->rssi = ev->rssi;
+       adv_info->data_len = data_len;
+       memcpy(adv_info->data, ev->adv_data, data_len);
+
+#ifdef TIZEN_BT_HAL
+       if (_bt_hal_gatt_client_get_le_scan_type() == BT_GATTC_LE_SCAN_TYPE_PASSIVE) {
+               __bt_hal_send_le_scan_result_event(adv_info);
+               g_free(adv_info);
+               return;
+       }
+#endif
+       if (__bt_hal_add_adv_ind_info(adv_info))
+               adv_info->timer_id = g_timeout_add(1000,
+                               __bt_hal_adv_scan_req_timeout_cb,
+                               (void *)adv_info);
+}
+
 /*******************************************************************************
-**
-** Function         gatt_init
-**
-** Description      Initializes the GATT interface
-**
-** Returns          bt_status_t
-**
-*******************************************************************************/
+ **
+ ** Function           gatt_init
+ **
+ ** Description                Initializes the GATT interface
+ **
+ ** Returns            bt_status_t
+ **
+ *******************************************************************************/
 static bt_status_t gatt_init(const btgatt_callbacks_t* callbacks )
 {
        bt_gatt_callbacks = callbacks;
        DBG("Register A2DP Src events callback function");
+       _bt_hal_register_gatt_le_dbus_handler_cb(__bt_hal_gatt_events);
        _bt_hal_register_gatt_server_handler_cb(__bt_hal_gatt_events);
+       _bt_hal_register_gatt_client_handler_cb(__bt_hal_gatt_events);
+       _bt_hal_register_event_handler_cb(HAL_GATT, __bt_hal_gatt_events);
 
        return BT_STATUS_SUCCESS;
 }
 
 /*******************************************************************************
-**
-** Function         gatt_cleanup
-**
-** Description      Closes the GATT interface
-**
-** Returns          void
-**
-*******************************************************************************/
-static void  gatt_cleanup(void)
+ **
+ ** Function   gatt_cleanup
+ **
+ ** Description        Closes the GATT interface
+ **
+ ** Returns    void
+ **
+ *******************************************************************************/
+static void gatt_cleanup(void)
 {
-    if (bt_gatt_callbacks)
-        bt_gatt_callbacks = NULL;
+       _bt_hal_unregister_gatt_le_dbus_handler_cb();
+       _bt_hal_unregister_gatt_client_handler_cb();
+       _bt_hal_unregister_event_handler_cb(HAL_GATT);
+
+       if (bt_gatt_callbacks)
+               bt_gatt_callbacks = NULL;
 }
 
 static const btgatt_interface_t btgatt_interface = {
-    sizeof(btgatt_interface),
+       sizeof(btgatt_interface),
 
-    gatt_init,
-    gatt_cleanup,
+       gatt_init,
+       gatt_cleanup,
 
-    &btgatt_client_interface,
-    &btgatt_server_interface,
+       &btgatt_client_interface,
+       &btgatt_server_interface,
 };
 
 /*******************************************************************************
-**
-** Function         bt_get_gatt_interface
-**
-** Description      Get the gatt callback interface
-**
-** Returns          btgatt_interface_t
-**
-*******************************************************************************/
+ **
+ ** Function           bt_get_gatt_interface
+ **
+ ** Description                Get the gatt callback interface
+ **
+ ** Returns            btgatt_interface_t
+ **
+ *******************************************************************************/
 const btgatt_interface_t *bt_get_gatt_interface()
 {
-    return &btgatt_interface;
+       return &btgatt_interface;
 }