Handle GATT client app's termination 60/224060/7
authorDoHyun Pyun <dh79.pyun@samsung.com>
Thu, 6 Feb 2020 05:01:13 +0000 (14:01 +0900)
committerDoHyun Pyun <dh79.pyun@samsung.com>
Mon, 10 Feb 2020 00:25:56 +0000 (09:25 +0900)
Change-Id: Ic209290e0b935df315d178409d12838507a0ca2f
Signed-off-by: DoHyun Pyun <dh79.pyun@samsung.com>
bt-oal/bluez_hal/src/bt-hal-gatt-client.c
bt-oal/bluez_hal/src/bt-hal-gatt-client.h
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
bt-service-adaptation/services/gatt/bt-service-gatt.c

index bf10167..17ccddb 100644 (file)
@@ -146,7 +146,12 @@ static guint pending_le_conn_timer_id = 0;
 static int bt_conn_id = 0;
 static int bt_inst_id = 0;
 
-#define BT_GATTC_CL_MAX 32
+/* Should match the range with bt-service-gatt.c's MAX_APPS_SUPPORTED */
+/* TODO: Adjust MAX Client after modifying MAX app handle logic */
+#define BT_GATTC_CL_MAX 11
+
+static int assigned_if = 0;
+static gboolean client_if_used[BT_GATTC_CL_MAX];
 
 typedef struct {
        int conn_id;
@@ -163,8 +168,6 @@ typedef struct {
 
 static GSList * hal_gattc_client_app_list = NULL;
 
-static int bt_client_if = 0;
-
 struct conn_mtu_s {
        int conn_id;
        int mtu;
@@ -185,6 +188,48 @@ static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv
 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr);
 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id);
 
+void _bt_hal_gatt_client_init(void)
+{
+       assigned_if = 0;
+       memset(client_if_used, 0x00, sizeof(client_if_used));
+}
+
+static int __bt_hal_gatt_assign_if(void)
+{
+       int index;
+
+       index = assigned_if + 1;
+
+       if (index >= BT_GATTC_CL_MAX)
+               index = 1;
+
+       while (client_if_used[index] == TRUE) {
+               if (index == assigned_if) {
+                       /* No available ID */
+                       ERR("All interface ID is used");
+                       return -1;
+               }
+
+               index++;
+
+               if (index >= BT_GATTC_CL_MAX)
+                       index = 1;
+       }
+
+       assigned_if = index;
+       client_if_used[index] = TRUE;
+
+       return assigned_if;
+}
+
+static void __bt_hal_gatt_delete_if(int client_if)
+{
+       if (client_if >= BT_GATTC_CL_MAX || client_if < 0)
+               return;
+
+       client_if_used[client_if] = FALSE;
+}
+
 
 /* To send stack event to hal-av handler */
 void _bt_hal_register_gatt_client_handler_cb(handle_stack_msg cb)
@@ -226,14 +271,10 @@ static gboolean __bt_hal_register_client_cb(gpointer user_data)
        return FALSE;
 }
 
-static int __hal_generate_client_id()
-{
-       return ++bt_client_if;
-}
-
 static hal_gatt_client_app *__hal_gattc_add_client_app(bt_uuid_t *app_uuid)
 {
        GSList *l;
+       int client_if = 0;
        hal_gatt_client_app *info = NULL;
        hal_gatt_client_app *gattc_app = NULL;
 
@@ -249,11 +290,17 @@ static hal_gatt_client_app *__hal_gattc_add_client_app(bt_uuid_t *app_uuid)
                }
        }
 
+       client_if = __bt_hal_gatt_assign_if();
+       if (client_if == -1) {
+               ERR("Fail to allocate the client if");
+               return NULL;
+       }
+
        DBG("adding the gatt client app");
 
        //add client app
        gattc_app = g_malloc0(sizeof(hal_gatt_client_app));
-       gattc_app->client_if = __hal_generate_client_id();
+       gattc_app->client_if = client_if;
        memcpy(&gattc_app->app_uuid, app_uuid, sizeof(bt_uuid_t));
 
        hal_gattc_client_app_list = g_slist_append(hal_gattc_client_app_list, gattc_app);
@@ -337,6 +384,9 @@ bt_status_t __hal_gattc_unregister_client(int client_if)
 
                if (info->client_if == client_if) {
                        DBG("gatt client app found");
+
+                       __bt_hal_gatt_delete_if(client_if);
+
                        hal_gattc_client_app_list = g_slist_remove(hal_gattc_client_app_list, info);
                        g_free(info);
                }
index 09b78ec..1d90fe8 100644 (file)
@@ -35,6 +35,8 @@
 extern "C" {
 #endif
 
+void _bt_hal_gatt_client_init(void);
+
 void _bt_hal_register_gatt_client_handler_cb(handle_stack_msg cb);
 void _bt_hal_unregister_gatt_client_handler_cb(void);
 
index 54de27a..0d7dba2 100644 (file)
@@ -195,7 +195,14 @@ struct hal_gatts_server_register_info_t {
 
 static GSList * hal_gatts_server_register_list;
 
-static int g_server_inst_id = 0;
+
+/* Should match the range with bt-service-gatt.c's MAX_APPS_SUPPORTED */
+/* TODO: Adjust MAX Server after modifying MAX app handle logic */
+#define BT_GATTS_MAX 11
+
+static int assigned_id = 0;
+
+static gboolean instance_id_used[BT_GATTS_MAX];
 
 #define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
 {\
@@ -335,6 +342,48 @@ static const gchar manager_introspection_xml[] =
 "  </interface>"
 "</node>";
 
+void _bt_hal_gatt_server_init(void)
+{
+       assigned_id = 0;
+       memset(instance_id_used, 0x00, sizeof(instance_id_used));
+}
+
+static int __bt_hal_gatt_assign_id(void)
+{
+       int index;
+
+       index = assigned_id + 1;
+
+       if (index >= BT_GATTS_MAX)
+               index = 1;
+
+       while (instance_id_used[index] == TRUE) {
+               if (index == assigned_id) {
+                       /* No available ID */
+                       ERR("All interface ID is used");
+                       return -1;
+               }
+
+               index++;
+
+               if (index >= BT_GATTS_MAX)
+                       index = 1;
+       }
+
+       assigned_id = index;
+       instance_id_used[index] = TRUE;
+
+       return assigned_id;
+}
+
+static void __bt_hal_gatt_delete_id(int instance_id)
+{
+       if (instance_id >= BT_GATTS_MAX || instance_id < 0)
+               return;
+
+       instance_id_used[instance_id] = FALSE;
+}
+
 static GSList *_bt_get_service_list_from_server(int instance)
 {
        GSList *l;
@@ -1770,11 +1819,6 @@ static int bt_hal_gatts_get_gatt_server_instance()
        return -1;
 }
 
-int bt_hal_gatts_generate_server_id()
-{
-       return ++g_server_inst_id;
-}
-
 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info_from_uuid(bt_uuid_t *app_uuid)
 {
        DBG("+");
@@ -1841,6 +1885,7 @@ static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_regist
 static struct hal_gatts_server_register_info_t * bt_hal_gatts_add_server_app(bt_uuid_t *app_uuid)
 {
        struct hal_gatts_server_register_info_t * server_register_info = NULL;
+       int instance_id = 0;
 
        server_register_info = bt_hal_gatts_find_server_register_info_from_uuid(app_uuid);
        if (server_register_info != NULL) {
@@ -1848,8 +1893,14 @@ static struct hal_gatts_server_register_info_t * bt_hal_gatts_add_server_app(bt_
                return server_register_info;
        }
 
+       instance_id = __bt_hal_gatt_assign_id();
+       if (instance_id == -1) {
+               ERR("Fail to allocate the server if");
+               return NULL;
+       }
+
        server_register_info = g_malloc0(sizeof(struct hal_gatts_server_register_info_t));
-       server_register_info->server_if = bt_hal_gatts_generate_server_id();
+       server_register_info->server_if = instance_id;
 
        DBG("Adding the gatt server app. server_if:[%d]", server_register_info->server_if);
 
@@ -1866,9 +1917,13 @@ static bt_status_t gatt_server_register_app(bt_uuid_t *uuid)
        struct hal_gatts_server_register_info_t *server_register_info = NULL;
 
        DBG("Register server instance request");
-       hal_register_server_data *user_data = g_malloc0(sizeof(hal_register_server_data));
-
        server_register_info = bt_hal_gatts_add_server_app(uuid);
+       if (server_register_info == NULL) {
+               ERR("Fail to register the server app");
+               return BT_STATUS_FAIL;
+       }
+
+       hal_register_server_data *user_data = g_malloc0(sizeof(hal_register_server_data));
        user_data->instance_data = server_register_info->server_if;
 
        /*
@@ -1936,6 +1991,8 @@ static bt_status_t gatt_server_unregister_app(int server_if)
        hal_gatts_server_register_list = g_slist_remove(hal_gatts_server_register_list, server_register_info);
        g_free(server_register_info);
 
+       __bt_hal_gatt_delete_id(server_if);
+
        /* If server_if belongs to a GATT Server, then delete the GATT server from List */
        _bt_hal_remove_gatt_server_from_list(server_if);
        return BT_STATUS_SUCCESS;
index ffae6d5..8e0093c 100644 (file)
@@ -35,6 +35,8 @@
 extern "C" {
 #endif
 
+void _bt_hal_gatt_server_init(void);
+
 void _bt_hal_register_gatt_server_handler_cb(handle_stack_msg cb);
 
 void _bt_hal_unregister_gatt_server_handler_cb(void);
index a476088..17457a4 100644 (file)
@@ -840,12 +840,16 @@ static void __bt_hal_handle_gatt_client_mtu_exchange_completed(void *buf, uint16
 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);
 
+       _bt_hal_gatt_server_init();
+       _bt_hal_gatt_client_init();
+
        return BT_STATUS_SUCCESS;
 }
 
index d59d769..d9e080b 100644 (file)
@@ -240,6 +240,9 @@ static int __bt_gatt_send_indication_to_all_connected_clients(bluetooth_gatt_att
 static void __bt_remove_all_service_handles(int instance_id);
 static void __bt_free_service_info(bt_gatt_service_info_t *service_info);
 
+static int __bt_do_unregister_gatt_instance(int instance_id);
+static void __bt_service_reset_gatt_data(void);
+
 #ifdef TIZEN_GATT_CLIENT
 static void __bt_handle_client_instance_registered(event_gattc_register_t *data);
 static void __bt_handle_client_connected(event_gattc_conn_t *event_data);
@@ -312,20 +315,31 @@ void _bt_check_adv_app_termination(const char *name)
                if (!strncasecmp(app->sender, name, strlen(name)) && app->is_initialized == TRUE) {
                        BT_DBG("Match found, name: %s", name);
 
-                       /* Unregister all service handles with stack */
-                       __bt_remove_all_service_handles(app->instance_id);
-
-                       /* If Advertising is enabled, stop it */
-                       if (app->adv_handle > 0) {
-                               BT_INFO("Stop advertising on instance ID [%d]", app->instance_id);
-                               /* Disable adv if running */
-                               BT_INFO("Disable Advertising Adv Handle [%d] sender [%s]",
-                                               app->adv_handle, name);
-                               _bt_set_advertising(app->sender, app->adv_handle, FALSE, FALSE);
-                       }
+                       /* TODO 1: If App has both GATT client / server role? */
+                       /* TODO 2: Need to manage app info as list, not array.
+                                  This loop always run for MAX count if any apps are terminated.
+                        */
 
                        /* Save instances of all apps that need to be unregistered */
-                       apps[app->instance_id] = 1;
+                       if (app->instance_id != -1) {
+                               /* GATT server */
+                               /* Unregister all service handles with stack */
+                               __bt_remove_all_service_handles(app->instance_id);
+
+                               /* If Advertising is enabled, stop it */
+                               if (app->adv_handle > 0) {
+                                       BT_INFO("Stop advertising on instance ID [%d]", app->instance_id);
+                                       /* Disable adv if running */
+                                       BT_INFO("Disable Advertising Adv Handle [%d] sender [%s]",
+                                                       app->adv_handle, name);
+                                       _bt_set_advertising(app->sender, app->adv_handle, FALSE, FALSE);
+                               }
+
+                               apps[app->instance_id] = 1;  /* App holds a GATT client Instance */
+                       } else if (app->client_id != -1) {
+                               /* GATT client */
+                               apps[app->client_id] = 1;         /* App holds a GATT server Instance */
+                       }
                }
        }
 
@@ -333,8 +347,8 @@ void _bt_check_adv_app_termination(const char *name)
        for (k = 1; k < MAX_APPS_SUPPORTED; k++) {
                if (apps[k] == 1) {
                        BT_INFO("Unregister app[%d]", k);
-                       /* Unregister server instance */
-                       __bt_unregister_gatt_server_instance(k);
+                       /* Unregister client or server instance */
+                       __bt_do_unregister_gatt_instance(k);
                }
        }
 }
@@ -425,6 +439,8 @@ static void __bt_register_default_gatt_client()
 
 int _bt_gatt_init(void)
 {
+       const char *stack_name = NULL;
+
        BT_DBG("+");
 
        if (OAL_STATUS_SUCCESS != gatt_enable()) {
@@ -434,15 +450,21 @@ int _bt_gatt_init(void)
 
        /* Register gatt event handler */
        _bt_service_register_event_handler_callback(BT_GATT_MODULE, __bt_gatt_event_handler);
-#ifdef TIZEN_GATT_CLIENT
-       /*In bluedroid product, defacult gatt client is handled differently*/
-       __bt_register_default_gatt_client();
-#endif
+
+       __bt_service_reset_gatt_data();
+
+       stack_name = oal_get_stack_name();
+
+       if (stack_name && g_strcmp0(stack_name, "bluez") == 0) {
+               /*In the platform, defacult gatt client should be registered */
+               __bt_register_default_gatt_client();
+       }
+
        BT_DBG("-");
        return BLUETOOTH_ERROR_NONE;
 }
 
-static void __bt_service_reset_gatt_data()
+static void __bt_service_reset_gatt_data(void)
 {
        int k;
 
@@ -460,6 +482,11 @@ static void __bt_service_reset_gatt_data()
                        memset(numapps[k].scan_rsp.data, 0x00, BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX);
                        numapps[k].adv_data_len = 0;
                        numapps[k].scan_rsp_len = 0;
+
+                       /* GATT client */
+                       numapps[k].client_id = -1;
+                       memset(numapps[k].address.addr, 0x00, BLUETOOTH_ADDRESS_LENGTH);
+                       numapps[k].is_watcher_enabled = FALSE;
        }
 }
 
@@ -608,6 +635,55 @@ void _bt_get_previous_scan_rsp_data(bluetooth_scan_resp_data_t *scan, int *len,
        }
 }
 
+static int __bt_do_unregister_gatt_instance(int instance_id)
+{
+       int ret = OAL_STATUS_SUCCESS;
+       int k;
+
+       BT_INFO("DeAllocate server or client instance ID [%d]", instance_id);
+
+       /* Reset data: instance_id parameter could be either for GATT Server or for GATT client  */
+       for (k = 1; k < MAX_APPS_SUPPORTED; k++) {
+               if (numapps[k].instance_id == instance_id) {
+                       BT_INFO("This is a GATT server app, unregister: Slot [%d] vacant", k);
+                       numapps[k].is_initialized = FALSE;
+                       numapps[k].instance_id = -1;
+                       numapps[k].adv_handle = 0;
+                       numapps[k].adv_instance = -1;
+                       memset(numapps[k].sender, 0x00, sizeof(numapps[k].sender));
+                       memset(numapps[k].uuid, 0x00, sizeof(numapps[k].uuid));
+                       memset(numapps[k].adv_data.data, 0x00, BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX);
+                       memset(numapps[k].scan_rsp.data, 0x00, BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX);
+                       numapps[k].adv_data_len = 0;
+                       numapps[k].scan_rsp_len = 0;
+
+                       /* Its a GATT Server Instance */
+                       ret = gatts_unregister(instance_id);
+                       if (ret != OAL_STATUS_SUCCESS) {
+                               BT_ERR("DeAllocate server instance with stack Fail ret: %d", ret);
+                               return BLUETOOTH_ERROR_INTERNAL;
+                       }
+                       break;
+               } else if (numapps[k].client_id == instance_id) {
+                       BT_INFO("This is a GATT client app, unregister: Slot [%d] vacant", k);
+                       numapps[k].client_id = -1;
+                       numapps[k].is_initialized = FALSE;
+                       memset(numapps[k].sender, 0x00, sizeof(numapps[k].sender));
+                       memset(numapps[k].uuid, 0x00, sizeof(numapps[k].uuid));
+                       memset(&numapps[k].address.addr, 0x00, sizeof(bluetooth_device_address_t));
+
+                       /* Its a GATT Client Instance */
+                       ret = gattc_deregister(instance_id);
+                       if (ret != OAL_STATUS_SUCCESS) {
+                               BT_ERR("DeAllocate GATT Client instance with stack Fail ret: %d", ret);
+                               return BLUETOOTH_ERROR_INTERNAL;
+                       }
+                       break;
+               }
+       }
+       return BLUETOOTH_ERROR_NONE;
+}
+
 static int __bt_unregister_gatt_server_instance(int server_instance)
 {
        int ret = OAL_STATUS_SUCCESS;