OSDN Git Service

LE: Add limited advertising duration capability (2/3)
authorAndre Eisenbach <eisenbach@google.com>
Thu, 7 Aug 2014 22:19:33 +0000 (15:19 -0700)
committerAndre Eisenbach <eisenbach@google.com>
Fri, 8 Aug 2014 02:26:17 +0000 (19:26 -0700)
Change-Id: Id2ebc353f1bcd94978c5c8dc55a235c92ebc7658

btif/include/btif_gatt_multi_adv_util.h
btif/src/btif_gatt_client.c
btif/src/btif_gatt_multi_adv_util.c

index a67893c..9c4a253 100644 (file)
@@ -21,6 +21,7 @@
 #define BTIF_GATT_MULTI_ADV_UTIL_H
 
 #include <hardware/bluetooth.h>
+#include "alarm.h"
 #include "bta_api.h"
 
 #define CLNT_IF_IDX 0
 #define INST_ID_IDX_MAX INST_ID_IDX + 1
 #define INVALID_ADV_INST -1
 #define STD_ADV_INSTID 0
-#define ADV_FLAGS 0x02
+
+/* Default ADV flags for general and limited discoverability */
+#define ADV_FLAGS_LIMITED 0x01
+#define ADV_FLAGS_GENERAL 0x02
 
 typedef struct
 {
@@ -56,6 +60,8 @@ typedef struct
     tBTA_BLE_AD_MASK mask;
     tBTA_BLE_ADV_DATA data;
     tBTA_BLE_ADV_PARAMS param;
+    alarm_t* limited_timer;
+    int timeout_s;
 }btgatt_multi_adv_inst_cb;
 
 typedef struct
@@ -80,10 +86,10 @@ extern BOOLEAN btif_gattc_copy_datacb(int arrindex, btif_adv_data_t *p_adv_data,
                                             BOOLEAN bInstData);
 extern void btif_gattc_adv_data_packager(int client_if, bool set_scan_rsp,
                 bool include_name, bool include_txpower, int min_interval, int max_interval,
-                int appearance, uint16_t manufacturer_len, char* manufacturer_data,
-                uint16_t service_data_len, char* service_data, uint16_t service_uuid_len,
+                int appearance, int manufacturer_len, char* manufacturer_data,
+                int service_data_len, char* service_data, int service_uuid_len,
                 char* service_uuid, btif_adv_data_t *p_multi_adv_inst);
-
+void btif_multi_adv_timer_ctrl(int client_if, alarm_callback_t cb);
 #endif
 
 
index ef53c14..f215426 100644 (file)
@@ -241,6 +241,13 @@ static uint8_t rssi_request_client_if;
 **  Static functions
 ********************************************************************************/
 
+static bt_status_t btif_gattc_multi_adv_disable(int client_if);
+static void btif_multi_adv_stop_cb(void *data)
+{
+    int client_if = (int)data;
+    btif_gattc_multi_adv_disable(client_if); // Does context switch
+}
+
 static void btapp_gattc_req_data(UINT16 event, char *p_dest, char *p_src)
 {
     tBTA_GATTC *p_dest_data = (tBTA_GATTC*) p_dest;
@@ -630,6 +637,8 @@ static void btif_gattc_upstreams_evt(uint16_t event, char* p_param)
                     , p_btif_cb->client_if
                     , p_btif_cb->status
                 );
+            btif_multi_adv_timer_ctrl(p_btif_cb->client_if,
+                    (p_btif_cb->status==0 ? btif_multi_adv_stop_cb : NULL));
             break;
         }
 
@@ -640,6 +649,8 @@ static void btif_gattc_upstreams_evt(uint16_t event, char* p_param)
                 , p_btif_cb->client_if
                 , p_btif_cb->status
             );
+            btif_multi_adv_timer_ctrl(p_btif_cb->client_if,
+                    (p_btif_cb->status==0 ? btif_multi_adv_stop_cb : NULL));
             break;
         }
 
@@ -1076,6 +1087,7 @@ static void btgattc_handle_event(uint16_t event, char* p_param)
             break;
 
         case BTIF_GATTC_UNREGISTER_APP:
+            btif_gattc_clear_clientif(p_cb->client_if);
             btif_gattc_destroy_multi_adv_cb();
             BTA_GATTC_AppDeregister(p_cb->client_if);
             break;
@@ -2060,7 +2072,7 @@ static int btif_gattc_get_device_type( const bt_bdaddr_t *bd_addr )
 }
 
 static bt_status_t btif_gattc_multi_adv_enable(int client_if, int min_interval, int max_interval,
-                                            int adv_type, int chnl_map, int tx_power)
+                                            int adv_type, int chnl_map, int tx_power, int timeout_s)
 {
     CHECK_BTGATT_INIT();
     btgatt_multi_adv_inst_cb adv_cb;
@@ -2072,12 +2084,13 @@ static bt_status_t btif_gattc_multi_adv_enable(int client_if, int min_interval,
     adv_cb.param.channel_map = chnl_map;
     adv_cb.param.adv_filter_policy = 0;
     adv_cb.param.tx_power = tx_power;
+    adv_cb.timeout_s = timeout_s;
     return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_ADV_INSTANCE_ENABLE,
                              (char*) &adv_cb, sizeof(btgatt_multi_adv_inst_cb), NULL);
 }
 
 static bt_status_t btif_gattc_multi_adv_update(int client_if, int min_interval, int max_interval,
-                                            int adv_type, int chnl_map,int tx_power)
+                                            int adv_type, int chnl_map,int tx_power, int timeout_s)
 {
     CHECK_BTGATT_INIT();
     btgatt_multi_adv_inst_cb adv_cb;
@@ -2089,17 +2102,16 @@ static bt_status_t btif_gattc_multi_adv_update(int client_if, int min_interval,
     adv_cb.param.channel_map = chnl_map;
     adv_cb.param.adv_filter_policy = 0;
     adv_cb.param.tx_power = tx_power;
+    adv_cb.timeout_s = timeout_s;
     return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_ADV_INSTANCE_UPDATE,
                          (char*) &adv_cb, sizeof(btgatt_multi_adv_inst_cb), NULL);
 }
 
 static bt_status_t btif_gattc_multi_adv_setdata(int client_if, bool set_scan_rsp,
-                                                   bool include_name, bool incl_txpower,
-                                                   int appearance, uint16_t manufacturer_len,
-                                                   char* manufacturer_data,
-                                                   uint16_t service_data_len,
-                                                   char* service_data, uint16_t service_uuid_len,
-                                                   char* service_uuid)
+                bool include_name, bool incl_txpower, int appearance,
+                int manufacturer_len, char* manufacturer_data,
+                int service_data_len, char* service_data,
+                int service_uuid_len, char* service_uuid)
 {
     CHECK_BTGATT_INIT();
 
index 8f1ca9b..0362fc4 100644 (file)
@@ -59,18 +59,25 @@ btgatt_multi_adv_common_data *btif_obtain_multi_adv_data_cb()
         p_multi_adv_com_data_cb = GKI_getbuf(sizeof(btgatt_multi_adv_common_data));
         if (NULL != p_multi_adv_com_data_cb)
         {
-           memset(p_multi_adv_com_data_cb, 0, sizeof(btgatt_multi_adv_common_data));
+            memset(p_multi_adv_com_data_cb, 0, sizeof(btgatt_multi_adv_common_data));
 
-           /* Storing both client_if and inst_id details */
-           p_multi_adv_com_data_cb->clntif_map =
+            /* Storing both client_if and inst_id details */
+            p_multi_adv_com_data_cb->clntif_map =
                   GKI_getbuf(( BTM_BleMaxMultiAdvInstanceCount() * INST_ID_IDX_MAX)* sizeof(INT8));
-           memset(p_multi_adv_com_data_cb->clntif_map, 0 ,
+            memset(p_multi_adv_com_data_cb->clntif_map, 0 ,
                   ( BTM_BleMaxMultiAdvInstanceCount() * INST_ID_IDX_MAX)* sizeof(INT8));
 
-           p_multi_adv_com_data_cb->inst_cb = GKI_getbuf(( BTM_BleMaxMultiAdvInstanceCount() + 1 )
+            p_multi_adv_com_data_cb->inst_cb = GKI_getbuf(( BTM_BleMaxMultiAdvInstanceCount() + 1 )
                                               * sizeof(btgatt_multi_adv_inst_cb));
-           memset(p_multi_adv_com_data_cb->inst_cb, 0 ,
+            memset(p_multi_adv_com_data_cb->inst_cb, 0 ,
                  ( BTM_BleMaxMultiAdvInstanceCount() + 1) * sizeof(btgatt_multi_adv_inst_cb));
+
+            for (int i=0; i <  BTM_BleMaxMultiAdvInstanceCount(); i += 2)
+            for (int i=0; i < BTM_BLE_MULTI_ADV_MAX; i++)
+            {
+                p_multi_adv_com_data_cb->clntif_map[i] = INVALID_ADV_INST;
+                p_multi_adv_com_data_cb->clntif_map[i+1] = INVALID_ADV_INST;
+            }
         }
     }
 
@@ -79,29 +86,17 @@ btgatt_multi_adv_common_data *btif_obtain_multi_adv_data_cb()
 
 void btif_gattc_init_multi_adv_cb(void)
 {
-    int i;
-    btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
-
-    if (NULL == p_multi_adv_data_cb)
-        return;
-
-    if (0 == multi_adv_enable_count)
-    {
-        for (i=0; i <  BTM_BleMaxMultiAdvInstanceCount(); i++)
-        {
-           p_multi_adv_data_cb->clntif_map[i + i] = INVALID_ADV_INST;
-           p_multi_adv_data_cb->clntif_map[i + (i + 1)] = INVALID_ADV_INST;
-        }
-    }
-    multi_adv_enable_count++;
+    // TODO: Instead of using a fragile reference counter here, one could
+    //       simply track the client_if instances that are in the map.
+    ++multi_adv_enable_count;
 }
 
-void btif_gattc_destroy_multi_adv_cb()
+void btif_gattc_destroy_multi_adv_cb(int client_if)
 {
     if (multi_adv_enable_count > 0)
         multi_adv_enable_count --;
 
-    if (0 == multi_adv_enable_count)
+    if(multi_adv_enable_count == 0 && p_multi_adv_com_data_cb != 0)
     {
         if (NULL != p_multi_adv_com_data_cb)
         {
@@ -118,7 +113,6 @@ int btif_multi_adv_add_instid_map(int client_if, int inst_id, BOOLEAN gen_temp_i
     int i=1;
 
     btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
-
     if (NULL == p_multi_adv_data_cb)
         return INVALID_ADV_INST;
 
@@ -226,8 +220,8 @@ int btif_gattc_obtain_idx_for_datacb(int value, int clnt_inst_index)
 
 void btif_gattc_adv_data_packager(int client_if, bool set_scan_rsp,
                 bool include_name, bool include_txpower, int min_interval, int max_interval,
-                int appearance, uint16_t manufacturer_len, char* manufacturer_data,
-                uint16_t service_data_len, char* service_data, uint16_t service_uuid_len,
+                int appearance, int manufacturer_len, char* manufacturer_data,
+                int service_data_len, char* service_data, int service_uuid_len,
                 char* service_uuid, btif_adv_data_t *p_multi_adv_inst)
 {
     memset(p_multi_adv_inst, 0 , sizeof(btif_adv_data_t));
@@ -276,7 +270,9 @@ BOOLEAN btif_gattc_copy_datacb(int cbindex, btif_adv_data_t *p_adv_data, BOOLEAN
     if (!p_adv_data->set_scan_rsp)
     {
          p_multi_adv_data_cb->inst_cb[cbindex].mask = BTM_BLE_AD_BIT_FLAGS;
-         p_multi_adv_data_cb->inst_cb[cbindex].data.flag = ADV_FLAGS;
+         p_multi_adv_data_cb->inst_cb[cbindex].data.flag = ADV_FLAGS_GENERAL;
+         if (p_multi_adv_data_cb->inst_cb[cbindex].timeout_s)
+             p_multi_adv_data_cb->inst_cb[cbindex].data.flag = ADV_FLAGS_LIMITED;
     }
 
     if (p_adv_data->include_name)
@@ -449,23 +445,21 @@ BOOLEAN btif_gattc_copy_datacb(int cbindex, btif_adv_data_t *p_adv_data, BOOLEAN
 
 void btif_gattc_clear_clientif(int client_if)
 {
-    int i=0;
-
     btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
-
     if (NULL == p_multi_adv_data_cb)
         return;
 
     // Clear both the inst_id and client_if values
-    for (i=0; i <  BTM_BleMaxMultiAdvInstanceCount(); i++)
+    for (i=0; i <  BTM_BleMaxMultiAdvInstanceCount(); i+=2)
     {
-       if (client_if == p_multi_adv_data_cb->clntif_map[i + i])
-       {
-          p_multi_adv_data_cb->clntif_map[i + (i + 1)] = INVALID_ADV_INST;
-          p_multi_adv_data_cb->clntif_map[i + i] = INVALID_ADV_INST;
-          BTIF_TRACE_DEBUG("Cleaning up index %d for clnt_if :%d,", i, client_if);
-          break;
-       }
+        if (client_if == p_multi_adv_data_cb->clntif_map[i])
+        {
+            btif_gattc_cleanup_inst_cb(p_multi_adv_data_cb->clntif_map[i+1]);
+            p_multi_adv_data_cb->clntif_map[i] = INVALID_ADV_INST;
+            p_multi_adv_data_cb->clntif_map[i+1] = INVALID_ADV_INST;
+            BTIF_TRACE_DEBUG("Cleaning up index %d for clnt_if :%d,", i, client_if);
+            break;
+        }
     }
 }
 
@@ -477,7 +471,6 @@ void btif_gattc_cleanup_inst_cb(int inst_id)
         return;
 
     btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
-
     if (NULL == p_multi_adv_data_cb)
         return;
 
@@ -486,17 +479,25 @@ void btif_gattc_cleanup_inst_cb(int inst_id)
         cbindex = btif_gattc_obtain_idx_for_datacb(inst_id, INST_ID_IDX);
         if (cbindex < 0)
             return;
+    } else {
+        if (STD_ADV_INSTID == inst_id)
+          cbindex = STD_ADV_INSTID;
     }
-    else
-    if (STD_ADV_INSTID == inst_id)
-       cbindex = STD_ADV_INSTID;
 
-    BTIF_TRACE_DEBUG("Cleaning up multi_inst_cb for inst_id %d, cbindex %d", inst_id, cbindex);
-    btif_gattc_cleanup_multi_inst_cb(&p_multi_adv_data_cb->inst_cb[cbindex]);
+    if (inst_id != INVALID_ADV_INST)
+    {
+        BTIF_TRACE_DEBUG("Cleaning up multi_inst_cb for inst_id %d, cbindex %d", inst_id, cbindex);
+        btif_gattc_cleanup_multi_inst_cb(&p_multi_adv_data_cb->inst_cb[cbindex]);
+        p_multi_adv_data_cb->inst_cb[cbindex].inst_id = INVALID_ADV_INST;
+    }
 }
 
 void btif_gattc_cleanup_multi_inst_cb(btgatt_multi_adv_inst_cb *p_multi_inst_cb)
 {
+    // Discoverability timer cleanup
+    alarm_free(p_multi_inst_cb->limited_timer);
+    p_multi_inst_cb->limited_timer = NULL;
+
     // Manufacturer data cleanup
     if (p_multi_inst_cb->data.p_manu != NULL)
     {
@@ -567,4 +568,40 @@ void btif_gattc_cleanup_multi_inst_cb(btgatt_multi_adv_inst_cb *p_multi_inst_cb)
         GKI_freebuf(p_multi_inst_cb->data.p_sol_service_128b);
 }
 
+void btif_multi_adv_timer_ctrl(int client_if, alarm_callback_t cb)
+{
+    int inst_id = btif_multi_adv_instid_for_clientif(client_if);
+    if (inst_id == INVALID_ADV_INST)
+        return;
+
+    int cbindex = btif_gattc_obtain_idx_for_datacb(inst_id, INST_ID_IDX);
+    if (cbindex == INVALID_ADV_INST)
+        return;
+
+    btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+    if (p_multi_adv_data_cb == NULL)
+        return;
+
+    if (cb == NULL)
+    {
+        alarm_free(p_multi_adv_data_cb->inst_cb[cbindex].limited_timer);
+        p_multi_adv_data_cb->inst_cb[cbindex].limited_timer = NULL;
+    } else {
+        if (p_multi_adv_data_cb->inst_cb[cbindex].timeout_s != 0)
+        {
+            if (p_multi_adv_data_cb->inst_cb[cbindex].limited_timer == NULL)
+                p_multi_adv_data_cb->inst_cb[cbindex].limited_timer = alarm_new();
+            else
+                alarm_cancel(p_multi_adv_data_cb->inst_cb[cbindex].limited_timer);
+
+            if (p_multi_adv_data_cb->inst_cb[cbindex].limited_timer)
+            {
+                alarm_set(p_multi_adv_data_cb->inst_cb[cbindex].limited_timer,
+                          p_multi_adv_data_cb->inst_cb[cbindex].timeout_s * 1000,
+                          cb, (void*)inst_id);
+            }
+        }
+    }
+}
+
 #endif