Просмотр исходного кода

component/bt: add bluedroid 1st version

1. add bluedroid 1st version
2. alarm adapter
3. task semaphore lock
4. other bugs resolved
Tian Hao 9 лет назад
Родитель
Сommit
b80325604d
100 измененных файлов с 46854 добавлено и 0 удалено
  1. 185 0
      components/bt/bluedroid/app/app_client_profiles/battery_c/battery_c.c
  2. 186 0
      components/bt/bluedroid/app/app_core/bt_app.c
  3. 384 0
      components/bt/bluedroid/app/app_core/bt_app_core.c
  4. 225 0
      components/bt/bluedroid/app/app_profiles/app_sample_button/app_button.c
  5. 247 0
      components/bt/bluedroid/app/app_project/SamleServerProject.c
  6. 381 0
      components/bt/bluedroid/app/app_project/SampleClientProject.c
  7. 62 0
      components/bt/bluedroid/app/include/app_button.h
  8. 46 0
      components/bt/bluedroid/app/include/bt_app_common.h
  9. 23 0
      components/bt/bluedroid/app/include/bt_app_defs.h
  10. 46 0
      components/bt/bluedroid/app/include/gattc_profile.h
  11. 5797 0
      components/bt/bluedroid/bta/dm/bta_dm_act.c
  12. 2165 0
      components/bt/bluedroid/bta/dm/bta_dm_api.c
  13. 587 0
      components/bt/bluedroid/bta/dm/bta_dm_cfg.c
  14. 117 0
      components/bt/bluedroid/bta/dm/bta_dm_ci.c
  15. 1199 0
      components/bt/bluedroid/bta/dm/bta_dm_int.h
  16. 376 0
      components/bt/bluedroid/bta/dm/bta_dm_main.c
  17. 1242 0
      components/bt/bluedroid/bta/dm/bta_dm_pm.c
  18. 695 0
      components/bt/bluedroid/bta/dm/bta_dm_sco.c
  19. 2379 0
      components/bt/bluedroid/bta/gatt/bta_gattc_act.c
  20. 1106 0
      components/bt/bluedroid/bta/gatt/bta_gattc_api.c
  21. 1637 0
      components/bt/bluedroid/bta/gatt/bta_gattc_cache.c
  22. 140 0
      components/bt/bluedroid/bta/gatt/bta_gattc_ci.c
  23. 542 0
      components/bt/bluedroid/bta/gatt/bta_gattc_main.c
  24. 973 0
      components/bt/bluedroid/bta/gatt/bta_gattc_utils.c
  25. 992 0
      components/bt/bluedroid/bta/gatt/bta_gatts_act.c
  26. 581 0
      components/bt/bluedroid/bta/gatt/bta_gatts_api.c
  27. 144 0
      components/bt/bluedroid/bta/gatt/bta_gatts_main.c
  28. 234 0
      components/bt/bluedroid/bta/gatt/bta_gatts_utils.c
  29. 1329 0
      components/bt/bluedroid/bta/hh/bta_hh_act.c
  30. 496 0
      components/bt/bluedroid/bta/hh/bta_hh_api.c
  31. 62 0
      components/bt/bluedroid/bta/hh/bta_hh_cfg.c
  32. 415 0
      components/bt/bluedroid/bta/hh/bta_hh_int.h
  33. 3168 0
      components/bt/bluedroid/bta/hh/bta_hh_le.c
  34. 593 0
      components/bt/bluedroid/bta/hh/bta_hh_main.c
  35. 539 0
      components/bt/bluedroid/bta/hh/bta_hh_utils.c
  36. 2389 0
      components/bt/bluedroid/bta/include/bta_api.h
  37. 80 0
      components/bt/bluedroid/bta/include/bta_dm_ci.h
  38. 274 0
      components/bt/bluedroid/bta/include/bta_dm_co.h
  39. 1411 0
      components/bt/bluedroid/bta/include/bta_gatt_api.h
  40. 119 0
      components/bt/bluedroid/bta/include/bta_gattc_ci.h
  41. 114 0
      components/bt/bluedroid/bta/include/bta_gattc_co.h
  42. 554 0
      components/bt/bluedroid/bta/include/bta_gattc_int.h
  43. 81 0
      components/bt/bluedroid/bta/include/bta_gatts_co.h
  44. 260 0
      components/bt/bluedroid/bta/include/bta_gatts_int.h
  45. 558 0
      components/bt/bluedroid/bta/include/bta_hh_api.h
  46. 133 0
      components/bt/bluedroid/bta/include/bta_hh_co.h
  47. 287 0
      components/bt/bluedroid/bta/include/bta_sys.h
  48. 170 0
      components/bt/bluedroid/bta/include/utl.h
  49. 598 0
      components/bt/bluedroid/bta/sys/bta_sys_conn.c
  50. 754 0
      components/bt/bluedroid/bta/sys/bta_sys_main.c
  51. 104 0
      components/bt/bluedroid/bta/sys/include/bta_sys_int.h
  52. 299 0
      components/bt/bluedroid/bta/sys/utl.c
  53. 107 0
      components/bt/bluedroid/btcore/bdaddr.c
  54. 63 0
      components/bt/bluedroid/btcore/include/bdaddr.h
  55. 29 0
      components/bt/bluedroid/btcore/include/device_features.h
  56. 30 0
      components/bt/bluedroid/btcore/include/event_mask.h
  57. 31 0
      components/bt/bluedroid/btcore/include/version.h
  58. 464 0
      components/bt/bluedroid/btif/bta_dm_co.c
  59. 217 0
      components/bt/bluedroid/btif/bta_gattc_co.c
  60. 170 0
      components/bt/bluedroid/btif/bta_gatts_co.c
  61. 589 0
      components/bt/bluedroid/device/controller.c
  62. 87 0
      components/bt/bluedroid/device/include/controller.h
  63. 44 0
      components/bt/bluedroid/device/include/interop.h
  64. 50 0
      components/bt/bluedroid/device/include/interop_database.h
  65. 56 0
      components/bt/bluedroid/device/interop.c
  66. 563 0
      components/bt/bluedroid/gki/gki_buffer.c
  67. 62 0
      components/bt/bluedroid/gki/gki_ulinux.c
  68. 101 0
      components/bt/bluedroid/gki/include/gki.h
  69. 68 0
      components/bt/bluedroid/gki/include/gki_common.h
  70. 35 0
      components/bt/bluedroid/gki/include/gki_int.h
  71. 33 0
      components/bt/bluedroid/hci/buffer_allocator.c
  72. 288 0
      components/bt/bluedroid/hci/hci_hal_h4.c
  73. 574 0
      components/bt/bluedroid/hci/hci_layer.c
  74. 202 0
      components/bt/bluedroid/hci/hci_packet_factory.c
  75. 243 0
      components/bt/bluedroid/hci/hci_packet_parser.c
  76. 362 0
      components/bt/bluedroid/hci/include/bt_vendor_lib.h
  77. 25 0
      components/bt/bluedroid/hci/include/buffer_allocator.h
  78. 85 0
      components/bt/bluedroid/hci/include/hci_hal.h
  79. 31 0
      components/bt/bluedroid/hci/include/hci_internals.h
  80. 101 0
      components/bt/bluedroid/hci/include/hci_layer.h
  81. 48 0
      components/bt/bluedroid/hci/include/hci_packet_factory.h
  82. 99 0
      components/bt/bluedroid/hci/include/hci_packet_parser.h
  83. 62 0
      components/bt/bluedroid/hci/include/packet_fragmenter.h
  84. 225 0
      components/bt/bluedroid/hci/packet_fragmenter.c
  85. 31 0
      components/bt/bluedroid/include/bt_common_types.h
  86. 90 0
      components/bt/bluedroid/include/bt_defs.h
  87. 1769 0
      components/bt/bluedroid/include/bt_target.h
  88. 462 0
      components/bt/bluedroid/include/bt_trace.h
  89. 362 0
      components/bt/bluedroid/include/bt_vendor_lib.h
  90. 118 0
      components/bt/bluedroid/include/bte.h
  91. 37 0
      components/bt/bluedroid/include/bte_appl.h
  92. 244 0
      components/bt/bluedroid/include/gki_target.h
  93. 216 0
      components/bt/bluedroid/main/bte_init.c
  94. 324 0
      components/bt/bluedroid/main/bte_main.c
  95. 12 0
      components/bt/bluedroid/mk.sh
  96. 184 0
      components/bt/bluedroid/osi/alarm.c
  97. 58 0
      components/bt/bluedroid/osi/allocator.c
  98. 96 0
      components/bt/bluedroid/osi/buffer.c
  99. 187 0
      components/bt/bluedroid/osi/fixed_queue.c
  100. 42 0
      components/bt/bluedroid/osi/hash_functions.c

+ 185 - 0
components/bt/bluedroid/app/app_client_profiles/battery_c/battery_c.c

@@ -0,0 +1,185 @@
+/***************************************************************
+* *
+* * This file is for client to execute battery-related operation
+* *
+***************************************************************/
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#include "bta_api.h"
+#include "bta_gatt_api.h"
+#include "controller.h"
+     
+#include "gatt_int.h"
+#include "bt_trace.h"
+#include "btm_api.h"
+#include "bt_types.h"
+#include "gattc_profile.h"
+
+#define BT_BD_ADDR_STR         "%02x:%02x:%02x:%02x:%02x:%02x"
+#define BT_BD_ADDR_HEX(addr)   addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]
+tBTA_GATTC_IF client_if;
+
+tBT_UUID            bas_uuid = {LEN_UUID_16, {UUID_SERVCLASS_BATTERY}};
+
+uint16_t get_uuid16(tBT_UUID* p_uuid)
+{
+    if(p_uuid->len == LEN_UUID_16)
+    {
+        return p_uuid->uu.uuid16;
+    }
+    else if(p_uuid->len == LEN_UUID_128)
+    {
+        UINT16 u16;
+        UINT8 *p = &p_uuid->uu.uuid128[LEN_UUID_128 - 4];
+        STREAM_TO_UINT16(u16, p);
+        return u16;
+    }
+    else
+    {
+        return (UINT16)p_uuid->uu.uuid32;
+    }
+}
+
+/*fill a GATT ID structure*/
+void bta_le_fill_16bits_gatt_id(UINT8 inst_id, UINT16 uuid, tBTA_GATT_ID* p_output)
+{
+    p_output->inst_id = inst_id;
+    p_output->uuid.len = LEN_UUID_16;
+    p_output->uuid.uu.uuid16 = uuid;
+}
+
+/*fill a service ID structure with a 16 bits service UUID*/
+void bta_le_fill_16bits_srvc_id(bool is_pri, UINT8 inst_id, UINT16 srvc_uuid, tBTA_GATT_SRVC_ID* p_output)
+{
+    memset((void *)p_output, 0, sizeof(tBTA_GATT_SRVC_ID));
+    p_output->is_primary = is_pri;
+    bta_le_fill_16bits_gatt_id(inst_id, srvc_uuid, &p_output->id);
+}
+
+/*fill a char ID structure with a 16 bits char UUID*/
+void bta_le_fill_16bits_char_id(UINT8 inst_id, UINT16 char_uuid, tBTA_GATT_ID* p_output)
+{
+    memset((void *)p_output, 0, sizeof(tBTA_GATT_ID));
+    bta_le_fill_16bits_gatt_id(inst_id, char_uuid, p_output);
+}
+
+/******************************************************************************
+** Function      bas_gattc_callback
+**
+** Description   battery service register callback function
+*******************************************************************************/
+static void bas_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data)
+{
+    switch (event)
+    {   
+        case BTA_GATTC_REG_EVT:
+        {  
+            tBTA_GATT_STATUS  status = p_data->reg_oper.status;
+            client_if = p_data->reg_oper.client_if;
+            LOG_ERROR("BAS register completed: event=%d, status=%d, client_if=%d\n", 
+                event, status, client_if);
+
+        }
+        break;
+
+        /*connect callback*/
+        case BTA_GATTC_OPEN_EVT:
+        {
+            
+            LOG_ERROR("\n%s:device is connected "BT_BD_ADDR_STR", client_if=%d, status=%d, connect_id=%d\n", 
+                             __FUNCTION__, BT_BD_ADDR_HEX(p_data->open.remote_bda), p_data->open.client_if,
+                             p_data->open.status, p_data->open.conn_id);
+            /*return whether the remote device is currently connected*/
+            int is_connected = BTA_DmGetConnectionState(p_data->open.remote_bda);
+            LOG_ERROR("is_connected=%d\n",is_connected);
+            /*get the energy info of the controller*/
+
+            /*read battery level*/
+            int conn_id = p_data->open.conn_id;
+
+            /*discover service*/
+            BTA_GATTC_ServiceSearchRequest(conn_id, NULL);
+
+        }
+        break;
+
+        case BTA_GATTC_SEARCH_RES_EVT:
+        {
+           // tBTA_GATTC_SRVC_RES service_result;
+            LOG_ERROR("find the service,uuid=0x%x, is_primary=%d\n",
+                get_uuid16(&p_data->srvc_res.service_uuid.id.uuid), 
+                p_data->srvc_res.service_uuid.is_primary);
+        }
+        break;
+
+        case BTA_GATTC_SEARCH_CMPL_EVT:
+        {
+            LOG_ERROR("search service complete, conn_id=%d,status=%d\n", p_data->search_cmpl.conn_id,
+                p_data->search_cmpl.status);
+
+            /*get first characteristic of battey service*/
+            LOG_ERROR("get first characteristic of battery service\n");
+            tBTA_GATT_STATUS    status;
+            tBTA_GATT_SRVC_ID   battery_srvc_id;
+            tBTA_GATTC_CHAR_ID  out_char_id;
+            tGATT_CHAR_PROP     out_char_prop;
+            bta_le_fill_16bits_srvc_id(TRUE, 0, UUID_SERVCLASS_BATTERY, &battery_srvc_id);
+            status = BTA_GATTC_GetFirstChar(p_data->search_cmpl.conn_id, &battery_srvc_id, NULL, 
+                &out_char_id, &out_char_prop);
+            if(status == 0)
+            {
+                LOG_ERROR("the first char:srvc_id=0x%x,char_id=0x%x, property = %d\n", 
+                    get_uuid16(&out_char_id.srvc_id.id.uuid), get_uuid16(&out_char_id.char_id.uuid),
+                    out_char_prop);
+                /*read battery level*/
+                tBTA_GATTC_CHAR_ID battery_char_id;
+                bta_le_fill_16bits_srvc_id(TRUE, 0, UUID_SERVCLASS_BATTERY, &battery_char_id.srvc_id);
+                bta_le_fill_16bits_char_id(0, GATT_UUID_BATTERY_LEVEL, &battery_char_id.char_id);
+            
+                BTA_GATTC_ReadCharacteristic(p_data->search_cmpl.conn_id, &battery_char_id, 
+                    BTA_GATT_AUTH_REQ_NONE); 
+            }
+        }
+        break;
+
+        case BTA_GATTC_READ_CHAR_EVT:
+        {
+            
+            LOG_ERROR("\nread characteristic:connect_id=%d, status=%d\n", 
+                p_data->read.conn_id, p_data->read.status);
+            LOG_ERROR("srvc_id=0x%x,char_id=0x%x,descr_type=0x%x\n", 
+                get_uuid16(&p_data->read.srvc_id.id.uuid), 
+                get_uuid16(&p_data->read.char_id.uuid), 
+                get_uuid16(&p_data->read.descr_type.uuid));
+            if(get_uuid16(&p_data->read.descr_type.uuid) != GATT_UUID_CHAR_AGG_FORMAT
+                && p_data->read.p_value->unformat.len > 0
+                && p_data->read.p_value->unformat.p_value != NULL)
+            {
+                LOG_ERROR("read the value: len=%d, value=%d\n", p_data->read.p_value->unformat.len,
+                    *(p_data->read.p_value->unformat.p_value));
+            }
+        }
+        break;
+
+        default:
+        LOG_ERROR("unsettled event: %d\n", event);
+    }
+
+}
+
+/***************************************************************
+**
+** Function     bac_register
+**
+** Description  register app for battery service
+**
+****************************************************************/
+void bac_register(void)
+{
+    BTA_GATTC_AppRegister(&bas_uuid, bas_gattc_callback);    
+    
+}
+

+ 186 - 0
components/bt/bluedroid/app/app_core/bt_app.c

@@ -0,0 +1,186 @@
+/**
+ ****************************************************************************************
+ *
+ * @file bt_app.c
+ *
+ * @brief Application entry point
+ *
+ * Copyright (C) Espressif 2016
+ * Created by Yulong at 2016/9/9
+ *
+ *
+ ****************************************************************************************
+ */
+
+#include "bt_app_defs.h"
+
+
+ /*******************************************************************************
+ **
+ ** Function		 ESP_AppConfigadvData
+ **
+ ** Description 	 This function is called to override the BTA default ADV parameters.
+ **
+ ** 				 adv_data: Pointer to User defined ADV data structure. This
+ ** 							memory space can not be freed until p_adv_data_cback
+ ** 							is received.
+ ** 				 p_adv_data_cback: set adv data complete callback.
+ **
+ ** Returns 		 None
+ **
+ *******************************************************************************/
+ void ESP_AppBleConfigadvData(tESP_BLE_ADV_DATA *adv_data,
+												tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback)
+{
+	tBTA_BLE_AD_MASK data_mask = 0;
+	if(adv_data->adv_name != NULL)
+	{
+		 data_mask |= BTM_BLE_AD_BIT_DEV_NAME;
+		 BTA_DmSetDeviceName(adv_data->adv_name);
+	}
+	if(adv_data->ble_adv_data.int_range.low != 0 ||
+	   adv_data->ble_adv_data.int_range.hi != 0)
+		data_mask |= BTM_BLE_AD_BIT_INT_RANGE;
+	
+	if(adv_data->ble_adv_data.p_manu != NULL)
+	{
+		data_mask |= BTM_BLE_AD_BIT_MANU;
+	}
+
+	if(adv_data->ble_adv_data.p_services != NULL)
+	{
+		data_mask |= BTM_BLE_AD_BIT_SERVICE;
+	}
+
+	if(adv_data->ble_adv_data.p_service_32b != NULL)
+	{
+		data_mask |= BTM_BLE_AD_BIT_SERVICE_32;
+	}
+
+	if(adv_data->ble_adv_data.p_services_128b != NULL)
+	{
+		data_mask |= BTM_BLE_AD_BIT_SERVICE_128;
+	}
+
+	if(adv_data->ble_adv_data.p_sol_services != NULL)
+	{
+		data_mask |= BTM_BLE_AD_BIT_SERVICE_SOL;
+	}
+
+	if(adv_data->ble_adv_data.p_sol_service_32b != NULL)
+	{
+		data_mask |= BTM_BLE_AD_BIT_SERVICE_32SOL;
+	}
+
+	if(adv_data->ble_adv_data.p_sol_service_128b != NULL)
+	{
+		data_mask |= BTM_BLE_AD_BIT_SERVICE_128SOL;
+	}
+	
+	if(adv_data->ble_adv_data.p_service_data != NULL)
+	{
+		data_mask |= BTM_BLE_AD_BIT_SERVICE_DATA;
+	}
+	
+	if(adv_data->ble_adv_data.appearance != 0)
+	{
+		data_mask |= BTM_BLE_AD_BIT_APPEARANCE;
+	}
+
+	if(adv_data->ble_adv_data.p_proprietary != NULL)
+	{
+		data_mask |= BTM_BLE_AD_BIT_PROPRIETARY;
+	}
+
+	if(adv_data->ble_adv_data.tx_power != 0)
+	{
+		data_mask |= BTM_BLE_AD_BIT_TX_PWR;
+	}
+
+	BTA_DmBleSetAdvConfig(data_mask, &(adv_data->ble_adv_data), p_adv_data_cback);
+}
+
+
+/*******************************************************************************
+**
+** Function         ESP_BleSetScanRsp
+**
+** Description      This function is called to override the app scan response.
+**
+** Parameters       Pointer to User defined ADV data structure
+**
+** Returns          None
+**
+*******************************************************************************/
+void ESP_AppBleSetScanRsp(tESP_BLE_ADV_DATA *scan_rsp_data,
+												tBTA_SET_ADV_DATA_CMPL_CBACK *p_scan_rsp_data_cback)
+{
+	tBTA_BLE_AD_MASK data_mask = 0;
+	if(scan_rsp_data->adv_name != NULL)
+	{
+		 data_mask |= BTM_BLE_AD_BIT_DEV_NAME;
+		 BTA_DmSetDeviceName(scan_rsp_data->adv_name);
+	}
+	if(scan_rsp_data->ble_adv_data.int_range.low != 0 || 
+	   scan_rsp_data->ble_adv_data.int_range.hi != 0)
+		data_mask |= BTM_BLE_AD_BIT_INT_RANGE;
+	
+	if(scan_rsp_data->ble_adv_data.p_manu != NULL)
+	{
+		data_mask |= BTM_BLE_AD_BIT_MANU;
+	}
+
+	if(scan_rsp_data->ble_adv_data.p_services != NULL)
+	{
+		data_mask |= BTM_BLE_AD_BIT_SERVICE;
+	}
+
+	if(scan_rsp_data->ble_adv_data.p_service_32b != NULL)
+	{
+		data_mask |= BTM_BLE_AD_BIT_SERVICE_32;
+	}
+
+	if(scan_rsp_data->ble_adv_data.p_services_128b != NULL)
+	{
+		data_mask |= BTM_BLE_AD_BIT_SERVICE_128;
+	}
+
+	if(scan_rsp_data->ble_adv_data.p_sol_services != NULL)
+	{
+		data_mask |= BTM_BLE_AD_BIT_SERVICE_SOL;
+	}
+
+	if(scan_rsp_data->ble_adv_data.p_sol_service_32b != NULL)
+	{
+		data_mask |= BTM_BLE_AD_BIT_SERVICE_32SOL;
+	}
+
+	if(scan_rsp_data->ble_adv_data.p_sol_service_128b != NULL)
+	{
+		data_mask |= BTM_BLE_AD_BIT_SERVICE_128SOL;
+	}
+	
+	if(scan_rsp_data->ble_adv_data.p_service_data != NULL)
+	{
+		data_mask |= BTM_BLE_AD_BIT_SERVICE_DATA;
+	}
+	
+	if(scan_rsp_data->ble_adv_data.appearance != 0)
+	{
+		data_mask |= BTM_BLE_AD_BIT_APPEARANCE;
+	}
+
+	if(scan_rsp_data->ble_adv_data.p_proprietary != NULL)
+	{
+		data_mask |= BTM_BLE_AD_BIT_PROPRIETARY;
+	}
+
+	if(scan_rsp_data->ble_adv_data.tx_power != 0)
+	{
+		data_mask |= BTM_BLE_AD_BIT_TX_PWR;
+	}
+
+	BTA_DmBleSetScanRsp(data_mask, &(scan_rsp_data->ble_adv_data), p_scan_rsp_data_cback);
+}
+
+

+ 384 - 0
components/bt/bluedroid/app/app_core/bt_app_core.c

@@ -0,0 +1,384 @@
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "fixed_queue.h"
+#include "gki.h"
+#include "bt_defs.h"
+#include "bt_trace.h"
+#include "bt_types.h"
+#include "allocator.h"
+
+#include "bta_api.h"
+#include "bta_gatt_api.h"
+#include "bt_app_common.h"
+
+#include "controller.h"
+
+#include "hash_map.h"
+#include "hash_functions.h"
+#include "alarm.h"
+#include "app_button.h"
+#include "button_pro.h"
+#include "thread.h"
+#include "bt_app_common.h"
+#include "gatt_profile.h"
+#include "gattc_profile.h"
+#include "smp_int.h"
+#include "smp_api.h"
+
+static fixed_queue_t *bta_app1_msg_queue;
+fixed_queue_t *bt_app1_general_alarm_queue;
+hash_map_t *bt_app1_general_alarm_hash_map;
+pthread_mutex_t bt_app1_general_alarm_lock;
+static const size_t BT_APP1_GENERAL_ALARM_HASH_MAP_SIZE = 10;
+
+xQueueHandle xBtaApp1Queue;
+xTaskHandle xBtaApp1TaskHandle;
+
+#define BT_APP1_TTYPE_MAIN_ENTRY   (1)
+static TIMER_LIST_ENT main_boot_tle;
+
+tSMP_CB smp_cmd;
+
+static void bt_app1_context_switched(void *p_msg);
+static void bt_app1_send_msg(void *p_msg);
+static void bt_app1_task_handler(void *arg);
+static void bta_app1_msg_ready(fixed_queue_t *queue);
+static void bt_app1_task_shut_down(void);
+
+static void bt_app1_general_alarm_ready(fixed_queue_t *queue);
+static void bt_app1_general_alarm_process(TIMER_LIST_ENT *p_tle);
+void bt_app1_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_sec);
+
+//extern void ble_test_conn(void);
+//extern void bt_test_start_inquiry(void);
+extern void ble_server_test(void);
+
+static void bt_app1_task_handler(void *arg)
+{
+    TaskEvt_t *e;
+    UINT8 button_msg[2] = {0x01,0x00};
+    for (;;) {
+        if (pdTRUE == xQueueReceive(xBtaApp1Queue, &e, (portTickType)portMAX_DELAY)) {
+            if (e->sig == 0xff) {
+                fixed_queue_process(bta_app1_msg_queue);
+                fixed_queue_process(bt_app1_general_alarm_queue);
+            }else if(e->sig == BUTTON_PRESS_EVT){
+			LOG_ERROR("button_press_event come in,button_value=%x\n",e->par);
+		  button_msg[1] = e->par;
+          button_msg_notify(2,button_msg);		
+}
+        }
+        osi_free(e);
+    }
+}
+
+static void bt_app1_task_post(void)
+{
+
+     TaskEvt_t *evt = (TaskEvt_t *)osi_malloc(sizeof(TaskEvt_t));
+     if (evt == NULL)
+        return;
+
+     evt->sig = 0xff;
+     evt->par = 0;
+
+     if (xQueueSend(xBtaApp1Queue, &evt, 10/portTICK_RATE_MS) != pdTRUE) {
+         ets_printf("btdm_post failed\n");
+     }
+
+}
+
+
+static void bta_app1_msg_ready(fixed_queue_t *queue) {
+    BT_HDR *p_msg;
+    while (!fixed_queue_is_empty(queue)) {
+        p_msg = (BT_HDR *)fixed_queue_dequeue(queue);
+        LOG_ERROR("bta_app1_msg_ready, evt: %d\n", p_msg->event);
+        switch (p_msg->event) {
+        case BT_EVT_APP1_CONTEXT_SWITCH:
+            bt_app1_context_switched(p_msg);
+            break;
+        default:
+            LOG_ERROR("unhandled BT_APP1 event (%d)\n", p_msg->event & BT_EVT_MASK);
+            break;
+        }
+        GKI_freebuf(p_msg);
+    }
+}
+
+static void bt_app1_context_switched(void *p_msg)
+{
+    tBTAPP1_CONTEXT_SWITCH_CBACK *p = (tBTAPP1_CONTEXT_SWITCH_CBACK *) p_msg;
+    
+    if (p->p_cb)
+        p->p_cb(p->event, p->p_param);
+}
+
+static void bt_app1_send_msg(void *p_msg)
+{
+    if (bta_app1_msg_queue) {
+        fixed_queue_enqueue(bta_app1_msg_queue, p_msg);
+        //ke_event_set(KE_EVENT_BT_APP1_TASK);
+        bt_app1_task_post();
+    }
+}
+
+bt_status_t bt_app1_transfer_context (tBTAPP1_CBACK *p_cback, UINT16 event, char* p_params, int param_len, tBTAPP1_COPY_CBACK *p_copy_cback)
+{
+    tBTAPP1_CONTEXT_SWITCH_CBACK *p_msg;
+
+    LOG_ERROR("btapp1_transfer_context evt %d, len %d", event, param_len);
+
+    /* allocate and send message that will be executed in btif context */
+    if ((p_msg = (tBTAPP1_CONTEXT_SWITCH_CBACK *) GKI_getbuf(sizeof(tBTAPP1_CONTEXT_SWITCH_CBACK) + param_len)) != NULL)
+    {
+        p_msg->hdr.event = BT_EVT_APP1_CONTEXT_SWITCH; /* internal event */
+        p_msg->p_cb = p_cback;
+
+        p_msg->event = event;                         /* callback event */
+
+        /* check if caller has provided a copy callback to do the deep copy */
+        if (p_copy_cback)
+        {
+            p_copy_cback(event, p_msg->p_param, p_params);
+        }
+        else if (p_params)
+        {
+            memcpy(p_msg->p_param, p_params, param_len);  /* callback parameter data */
+        }
+
+        bt_app1_send_msg(p_msg);
+        return BT_STATUS_SUCCESS;
+    }
+    else
+    {
+        /* let caller deal with a failed allocation */
+        return BT_STATUS_NOMEM;
+    }
+}
+
+void bt_app1_task_start_up(void)
+{
+    bta_app1_msg_queue = fixed_queue_new(SIZE_MAX);
+    if (bta_app1_msg_queue == NULL)
+        goto error_exit;
+    //ke_event_callback_set(KE_EVENT_BT_APP1_TASK, &bt_app1_task_handler);
+
+    xBtaApp1Queue = xQueueCreate(3, sizeof(void *));
+    xTaskCreate(bt_app1_task_handler, "BtaApp1T", 8192, NULL, configMAX_PRIORITIES - 3, xBtaApp1TaskHandle);
+
+    fixed_queue_register_dequeue(bta_app1_msg_queue, bta_app1_msg_ready);
+
+    bt_app1_general_alarm_hash_map = hash_map_new(BT_APP1_GENERAL_ALARM_HASH_MAP_SIZE,
+            hash_function_pointer, NULL, (data_free_fn)osi_alarm_free, NULL);
+    if (bt_app1_general_alarm_hash_map == NULL)
+        goto error_exit;
+
+    pthread_mutex_init(&bt_app1_general_alarm_lock, NULL);
+
+    bt_app1_general_alarm_queue = fixed_queue_new(SIZE_MAX);
+    if (bt_app1_general_alarm_queue == NULL)
+        goto error_exit;
+    fixed_queue_register_dequeue(bt_app1_general_alarm_queue, bt_app1_general_alarm_ready);
+
+    memset(&main_boot_tle, 0, sizeof(TIMER_LIST_ENT));
+    return;
+
+error_exit:
+    LOG_ERROR("%s Unable to allocate resources for bt_app1", __func__);
+    bt_app1_task_shut_down();
+}
+
+static void bt_app1_task_shut_down(void)
+{
+    fixed_queue_unregister_dequeue(bta_app1_msg_queue);
+    fixed_queue_free(bta_app1_msg_queue, NULL);
+    bta_app1_msg_queue = NULL;
+
+    // todo: hash map, pthread_mutex...
+    fixed_queue_unregister_dequeue(bt_app1_general_alarm_queue);
+
+    vTaskDelete(xBtaApp1TaskHandle);
+    vTaskDelete(xBtaApp1Queue);
+}
+
+
+static void bt_app1_dm_data_copy(uint16_t event, char *dst, char *src)
+{
+    tBTA_DM_SEC *dst_dm_sec = (tBTA_DM_SEC*)dst;
+    tBTA_DM_SEC *src_dm_sec = (tBTA_DM_SEC*)src;
+
+    if (!src_dm_sec)
+        return;
+
+    assert(dst_dm_sec);
+    memcpy(dst_dm_sec, src_dm_sec, sizeof(tBTA_DM_SEC));
+
+    if (event == BTA_DM_BLE_KEY_EVT)
+    {
+        dst_dm_sec->ble_key.p_key_value = osi_malloc(sizeof(tBTM_LE_KEY_VALUE));
+        assert(src_dm_sec->ble_key.p_key_value);
+        assert(dst_dm_sec->ble_key.p_key_value);
+        memcpy(dst_dm_sec->ble_key.p_key_value, src_dm_sec->ble_key.p_key_value, sizeof(tBTM_LE_KEY_VALUE));
+    }
+}
+
+static void bt_app1_dm_data_free(uint16_t event, tBTA_DM_SEC *dm_sec)
+{
+    if (event == BTA_DM_BLE_KEY_EVT)
+        osi_free(dm_sec->ble_key.p_key_value);
+}
+
+static void bt_app1_dm_upstreams_evt(UINT16 event, char *p_param)
+{
+    tBTA_DM_SEC *p_data = (tBTA_DM_SEC*)p_param;
+    switch (event) {
+    case BTA_DM_ENABLE_EVT: {
+
+//        BTA_DmSetDeviceName("ijiazu");
+
+  
+
+
+        /*set connectable,discoverable, pairable and paired only modes of local device*/
+        tBTA_DM_DISC disc_mode = BTA_DM_GENERAL_DISC | BTA_DM_BLE_GENERAL_DISCOVERABLE;
+        tBTA_DM_CONN conn_mode = BTA_DM_CONN | BTA_DM_BLE_CONNECTABLE;
+        BTA_DmSetVisibility(disc_mode, conn_mode, BTA_DM_IGNORE, BTA_DM_IGNORE);
+
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+        /* Enable local privacy */
+        BTA_DmBleConfigLocalPrivacy(BLE_LOCAL_PRIVACY_ENABLED);
+        do {
+            const controller_t *controller = controller_get_interface();
+            char bdstr[18];
+            bdaddr_to_string(controller->get_address(), bdstr, sizeof(bdstr));
+            LOG_ERROR("BDA is: %s\n", bdstr);
+        } while (0);
+#endif        
+    }
+	break;
+	case BTA_DM_BLE_SEC_REQ_EVT:
+		
+		smp_cmd.local_io_capability = 0x03;		//no input no output
+		smp_cmd.loc_oob_flag = 0x00;		//oob data not present
+		smp_cmd.loc_auth_req = 0x05;
+		smp_cmd.loc_enc_size = 0x10;
+		smp_cmd.local_i_key = 0x07;
+		smp_cmd.local_r_key = 0x07;
+		memcpy(smp_cmd.pairing_bda,p_data->ble_req.bd_addr,0x06);
+		smp_send_cmd(SMP_OPCODE_PAIRING_RSP,&smp_cmd);
+		smp_set_state(SMP_STATE_WAIT_CONFIRM);
+		//BTA_DmConfirm(p_data->ble_req.bd_addr,true);
+			break;
+	default:
+		break;
+    }
+
+    bt_app1_dm_data_free(event, p_data);
+}
+
+static void bte_dm_evt(tBTA_DM_SEC_EVT event, tBTA_DM_SEC* p_data)
+{
+    LOG_ERROR("bte_dm_evt: %d\n", (uint16_t)event);
+    bt_app1_transfer_context(bt_app1_dm_upstreams_evt, (uint16_t)event, 
+           (void *)p_data, sizeof(tBTA_DM_SEC), bt_app1_dm_data_copy);
+}
+
+void bt_app1_init_ok(UNUSED_ATTR uint16_t event, UNUSED_ATTR char *p_param)
+{
+    BTA_EnableBluetooth(bte_dm_evt);
+    vTaskDelay(1000 / portTICK_PERIOD_MS);
+    bt_app1_start_timer(&main_boot_tle, BT_APP1_TTYPE_MAIN_ENTRY, 8);
+}
+
+/* Alarm timer */
+static void bt_app1_general_alarm_cb(void *data) {
+    assert(data != NULL);
+    TIMER_LIST_ENT *p_tle = (TIMER_LIST_ENT *)data;
+
+    fixed_queue_enqueue(bt_app1_general_alarm_queue, p_tle);
+    //ke_event_set(KE_EVENT_BT_APP1_TASK);
+    bt_app1_task_post();
+}
+
+void bt_app1_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_sec) {
+   osi_alarm_t *alarm = NULL;
+
+    assert(p_tle != NULL);
+
+    // Get the alarm for the timer list entry.
+    pthread_mutex_lock(&bt_app1_general_alarm_lock);
+    if (!hash_map_has_key(bt_app1_general_alarm_hash_map, p_tle)) {
+        alarm = osi_alarm_new("bt_app1", bt_app1_general_alarm_cb, (void *)p_tle, 0);
+        hash_map_set(bt_app1_general_alarm_hash_map, p_tle, alarm);
+    }
+    pthread_mutex_unlock(&bt_app1_general_alarm_lock);
+    
+	pthread_mutex_lock(&bt_app1_general_alarm_lock);
+    alarm = hash_map_get(bt_app1_general_alarm_hash_map, p_tle);
+    pthread_mutex_unlock(&bt_app1_general_alarm_lock);
+    if (alarm == NULL) {
+        LOG_ERROR("%s Unable to create alarm", __func__);
+
+        return;
+    }
+
+    osi_alarm_cancel(alarm);
+
+    p_tle->event = type;
+    // NOTE: This value is in seconds but stored in a ticks field.
+    p_tle->ticks = timeout_sec;
+    p_tle->in_use = TRUE;
+    osi_alarm_set(alarm, (period_ms_t)(timeout_sec * 1000));
+}
+
+void bt_app1_stop_timer(TIMER_LIST_ENT *p_tle)
+{
+    assert(p_tle != NULL);
+
+    if (p_tle->in_use == FALSE)
+        return;
+    p_tle->in_use = FALSE;
+
+    // Get the alarm for the timer list entry.
+   osi_alarm_t *alarm = hash_map_get(bt_app1_general_alarm_hash_map, p_tle);
+    if (alarm == NULL) {
+        LOG_WARN("%s Unable to find expected alarm in hashmap", __func__);
+        return;
+    }
+    osi_alarm_cancel(alarm);
+}
+
+static void bt_app1_general_alarm_process(TIMER_LIST_ENT *p_tle)
+{
+    assert(p_tle != NULL);
+    LOG_ERROR("general_alarm_process\n");
+    switch (p_tle->event) {
+    case BT_APP1_TTYPE_MAIN_ENTRY:
+        LOG_ERROR("BT_APP1 main boot**********\n");
+
+      //  ble_test_conn();
+  //      ble_server_test();
+ 
+
+  //     bt_test_start_inquiry();
+
+       gatts_server_test();
+       //gattc_client_test();
+        break;
+    }
+
+}
+
+static void bt_app1_general_alarm_ready(fixed_queue_t *queue)
+{
+    TIMER_LIST_ENT *p_tle;
+
+    while (!fixed_queue_is_empty(queue)) {
+        p_tle = (TIMER_LIST_ENT *)fixed_queue_dequeue(queue);
+        bt_app1_general_alarm_process(p_tle);
+    }
+}
+

+ 225 - 0
components/bt/bluedroid/app/app_profiles/app_sample_button/app_button.c

@@ -0,0 +1,225 @@
+/**
+ 
+*******************************************************************************
+*********
+ *
+ * @file app_button.c
+ *
+ * @brief button Service Application entry point
+ *
+ * Copyright (C) ESPRESSSIF 2016
+ * Created by Yulong at 2016/08/24
+ *
+ *
+ 
+*******************************************************************************
+*********
+*/
+#if 0
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+
+#include "rom/gpio.h"
+#include "app_button.h"
+#include "bt_trace.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/timers.h"
+#include "freertos/task.h"
+#include "freertos/xtensa_api.h"
+#include "thread.h"
+
+#include "allocator.h"
+#include "button_pro.h"
+#define GPIO_INUM 8
+#define TABLE_ELEMENT_CNT(table) ((sizeof(table))/(sizeof(table[0])));
+app_key_env key_press;
+
+uint8_t gpio_test_table[]={0,2,4,5,12,13,14,15,16,17,18,19,20,21,22,23,25,26,27,33,34,35,36,37,38,39};
+
+struct gpio_test_info{
+	uint8_t *gpio_test_table;
+	uint8_t gpio_test_num;
+	void *time_s;
+};
+
+static void gpio_irq_init(uint64_t gpio_num);
+
+void gpio_check_register(enum_gpio_num_t gpio_num)
+{
+    if(gpio_num>=GPIO_PIN_COUNT||0==GPIO_PIN_MUX_REG[gpio_num]){
+        ets_printf("io_num=%d not exits\n",gpio_num);
+		return;
+	}
+    LOG_ERROR("---------gpio_num %d reg----------\n",gpio_num);
+LOG_ERROR("GPIO_IOMUX_%d=0x%08x\n",gpio_num,READ_PERI_REG(GPIO_PIN_MUX_REG[gpio_num]));
+   LOG_ERROR("GPIO_PIN%d_ADDR=0x%08x\n",gpio_num,READ_PERI_REG(GPIO_PIN_ADDR(gpio_num)));
+	LOG_ERROR("GPIO_OUT_REG=0x%08x\n",READ_PERI_REG(GPIO_OUT_REG));
+	LOG_ERROR("GPIO_OUT1_REG=0x%08x\n",READ_PERI_REG(GPIO_OUT1_REG));
+	LOG_ERROR("GPIO_ENABLE_REG=0x%08x\n",READ_PERI_REG(GPIO_ENABLE_REG));
+	LOG_ERROR("GPIO_ENABLE1_REG=0x%08x\n",READ_PERI_REG(GPIO_ENABLE1_REG));
+	LOG_ERROR("GPIO_IN_REG=0x%08x\n",READ_PERI_REG(GPIO_IN_REG));
+	LOG_ERROR("GPIO_IN1_REG=0x%08x\n",READ_PERI_REG(GPIO_IN1_REG));
+	LOG_ERROR("GPIO_STATUS_REG=0x%08x\n",READ_PERI_REG(GPIO_STATUS_REG));
+	LOG_ERROR("GPIO_STATUS1_REG=0x%08x\n",READ_PERI_REG(GPIO_STATUS1_REG));
+}
+
+void t1_callback(void *arg)
+{
+	 static uint8_t level=0;
+	static uint8_t cnt=0;
+	uint8_t err_flag=0;
+	struct gpio_test_info *gpio_test=(struct gpio_test_info*)(arg);
+	uint8_t i=0;
+	while(1){
+	gpio_check_register(35);
+	vTaskDelay(2*1000);	
+	/*
+        level=~level;
+        LOG_ERROR("Test cnt %u, level %u\n",cnt+1,level&0x01);
+        for(i=0;i<gpio_test->gpio_test_num;i++){
+            gpio_set_output_level(gpio_test->gpio_test_table[i],level&0x01);
+        	if(gpio_get_input_level(gpio_test->gpio_test_table[i])!=(level&0x01))
+        	{
+        	    err_flag=1;
+                LOG_ERROR("[ERR] GPIO%u set_level %u get_level %u\n",gpio_test->gpio_test_table[i],level&0x01,gpio_get_input_level(gpio_test->gpio_test_table[i]));
+        	}
+			else{
+               LOG_ERROR("GPIO%u OK\n",gpio_test->gpio_test_table[i]);
+			}
+        }
+        cnt++;
+		if(err_flag==0){
+          LOG_ERROR("cnt %u test ok\n",cnt);  
+		}
+		err_flag=0;
+        if(cnt>=10){
+           LOG_ERROR("Gpio input and output test end\n");
+           vTaskDelete(NULL);*/
+       // }
+		
+		//vTaskDelay(2*1000);
+		
+	}
+}
+
+ void app_button_init(void)
+{
+	uint64_t gpio_num = GPIO_Pin_27|GPIO_Pin_35|GPIO_Pin_34|GPIO_Pin_36|GPIO_Pin_39;
+	// Reset environment
+    memset(&key_press, 0, sizeof(key_press));	
+	gpio_irq_init(gpio_num);
+	static struct gpio_test_info gpio_test_infor; 
+        LOG_ERROR("app_button_init.");
+/*	TimerHandle_t t1=NULL;
+   t1=xTimerCreate("t1_time",(1000/portTICK_PERIOD_MS),pdTRUE,&gpio_test_infor,t1_callback);
+   	do{
+        gpio_test_infor.gpio_test_table=gpio_test_table;
+		gpio_test_infor.gpio_test_num=TABLE_ELEMENT_CNT(gpio_test_table);
+		gpio_test_infor.time_s=t1;
+	}while(0);*/
+
+   // xTaskCreate(t1_callback,"t1_callback",1024,&gpio_test_infor,30,NULL);
+	LOG_ERROR("gpio_input_output_demo\n");
+    return;
+}
+
+static void gpio_irq_init(uint64_t gpio_num)
+{
+	 gpio_config_t gpio_config_prot;
+	memset(&gpio_config_prot,0,sizeof(gpio_config_prot));
+    gpio_config_prot.GPIO_Pin= gpio_num;
+	
+	gpio_config_prot.GPIO_Mode=GPIO_Mode_Input;
+	gpio_config_prot.GPIO_IntrType=GPIO_PIN_INTR_NEGEDGE;
+	gpio_config_prot.GPIO_Pullup=GPIO_PullUp_EN;
+	gpio_config_prot.GPIO_Pulldown=GPIO_PullDown_DIS;
+    gpio_config(&gpio_config_prot);
+	//Register gpio handler
+	gpio_intr_handler_register(GPIO_isr_callback,NULL);
+	//Enable gpio intr
+	xt_ints_on(1<<GPIO_INUM);
+	//ETS_GPIO_INTR_ENABLE(); //Enable intr
+}
+
+
+void GPIO_isr_callback(void* arg)
+{
+	/*GPIO interrupt process*/
+	uint32_t gpio_intr_status = 0;
+	uint32_t gpio_intr_status_h = 0;
+	uint32_t gpio_num =0;
+	//disable the pending interrupt
+	xt_ints_off(1<<GPIO_INUM);
+	gpio_intr_status = READ_PERI_REG(GPIO_STATUS_REG);
+	gpio_intr_status_h = READ_PERI_REG(GPIO_STATUS1_REG);
+	LOG_ERROR("the interrupt come in,gpio_intr_staus = %d,gpio_intr_status_h=%d\n",gpio_intr_status,gpio_intr_status_h);
+	//clear intr for gpio0-gpio31
+	WRITE_PERI_REG((GPIO_STATUS_W1TC_REG),(READ_PERI_REG(GPIO_STATUS_W1TC_REG)|(gpio_intr_status)));
+	//clear intr for gpio32-39
+	WRITE_PERI_REG((GPIO_STATUS1_W1TC_REG),(READ_PERI_REG(GPIO_STATUS1_W1TC_REG)|(gpio_intr_status_h)));
+	do{
+		if(gpio_num < 32){
+			if(gpio_intr_status&BIT(gpio_num))
+			{
+				LOG_ERROR("Intr GPIO= %d\n",gpio_num);
+				break;
+			}
+		}
+		else{
+			if(gpio_intr_status_h&BIT(gpio_num - 32)){
+				LOG_ERROR("Intr GPIO = %d\n",gpio_num);
+				break;
+			}
+		}
+		
+	}while(++gpio_num<GPIO_PIN_COUNT);
+	TaskEvt_t *evt = (TaskEvt_t *)osi_malloc(sizeof(TaskEvt_t));
+	if(evt == NULL)
+	{
+		return;
+	}
+	
+	switch(gpio_num)
+	{
+		case GPIO_NUM_35:
+			evt->par = Button_Voice;
+		break;
+		case GPIO_NUM_34:
+			evt->par = Button_OK;
+			break;
+		case GPIO_NUM_39:
+			evt->par = Button_Down;
+			break;
+		case GPIO_NUM_36:
+			evt->par = Button_Up;
+			break;
+		default:
+			evt->par = Button_Back;
+		break;
+	}
+	evt->sig = BUTTON_PRESS_EVT;
+	if(xQueueSend(xBtaApp1Queue,&evt,10/portTICK_RATE_MS)!=pdTRUE){
+		LOG_ERROR("btdm_post_failed\n");
+	}
+	//enable the interrupt
+	xt_ints_on(1<<GPIO_INUM);
+	LOG_ERROR("the interrupt come in arg = %s\n",arg);
+}
+
+
+uint8_t check_sum(uint8_t *check_array,uint8_t len)
+{
+	uint8_t i,sum = 0;
+	for(i = 0;i < len; i++)
+	{
+		sum ^= check_array[i];
+	}
+	sum += 1;
+
+	return sum;
+}
+
+#endif

+ 247 - 0
components/bt/bluedroid/app/app_project/SamleServerProject.c

@@ -0,0 +1,247 @@
+/***************************************************************
+*
+* This file is for gatt server device. It instantiates BATTERY
+* sevice. It can be scanned and connected by central device,
+* and the client will get the BAS value. It calls the API bta 
+* layer provides.
+*
+****************************************************************/
+
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#include "bta_api.h"
+#include "bta_gatt_api.h"
+#include "controller.h"
+
+#include "gatt_int.h"
+#include "bt_trace.h"
+#include "btm_api.h"
+#include "bt_types.h"
+#include "gatt_profile.h"
+#include "bt_app_common.h"
+
+//#include "app_button.h"
+//#include "button_pro.h"
+#include "hid_le_prf.h"
+#include "prf_defs.h"
+#include "hcimsgs.h"
+#include "bt_app_defs.h"
+
+
+#define BT_BD_ADDR_STR         "%02x:%02x:%02x:%02x:%02x:%02x"
+#define BT_BD_ADDR_HEX(addr)   addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]
+tBTA_GATTS_IF server_if;
+
+static unsigned char DIS_UUID[16] = {
+    0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
+    0x00, 0x10, 0x00, 0x00, 0x0a, 0x18, 0x00, 0x00
+    };
+static unsigned char BASE_UUID[16] = {
+    0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
+    0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+    };
+
+UINT16 ijiazu_uuid = 0xffff;
+tBTA_BLE_SERVICE ijiazu_service = {
+							0x01,		//only one service in the ijiazu button profile
+							false,
+							&ijiazu_uuid
+							};        /* 16 bits services */
+
+
+UINT8 beacon_manu[25] = {0x4c, 0x00,0x02, 0x15, 0xfd, 0xa5, 0x06, 0x93, 0xa4, 0xe2, 
+                  0x4f, 0xb1, 0xaf, 0xcf, 0xc6, 0xeb, 0x07, 0x64, 0x78, 0x25,
+                  0x27, 0x32, 0xe6, 0x08, 0xc5};
+
+//UINT8 ijiazu_manu[17] = {0xff,0x20,0x14,0x07,0x22,0x00,0x02,0x5B,0x00,0x33,0x49,0x31,0x30,0x4a,0x30,0x30,0x31};
+UINT8 ijiazu_manu[17] = {0xff,0x20,0x14,0x07,0x22,0x00,0x02,0x5B,0x00,0x33,0x49,0x31,0x30,0x4a,0x30,0x30,0x31};
+tBTA_BLE_MANU	p_ijiazu_manu = {sizeof(ijiazu_manu),ijiazu_manu};			/* manufacturer data */
+
+
+BD_ADDR rand_ijiazu_addr = {0x00,0x02,0x5B,0x00,0x32,0x55};
+
+tESP_BLE_ADV_DATA ijiazu_adv_data[ADV_SCAN_IDX_MAX] = 
+{
+	[BLE_ADV_DATA_IDX] 		= {
+										.adv_name = "esp_server",
+										{
+										{0,0},
+										NULL,			//no manufature data to be setting in the ijiazu adervetisiing datas
+										&ijiazu_service,
+										NULL,					//the  128 bits service uuid set to null(not used)
+										NULL,					//the 32 bits Service UUID set to null(not used)
+										NULL,					//16 bits services Solicitation UUIDs set to null(not used)
+										NULL,					//List of 32 bit Service Solicitation UUIDs set to null(not used)
+										NULL,					//List of 128 bit Service Solicitation UUIDs set to null(not used)
+										NULL,					//proprietary data set to null(not used)
+										NULL,					//service data set not null(no service data to be sent)
+										0x0200,         		//device type : generic display
+										BTA_DM_GENERAL_DISC,	// General discoverable. 
+										0xFE					//the tx power value,defult value is 0
+										},
+									
+								},
+	[BLE_SCAN_RSP_DATA_IDX] = {
+										.adv_name = NULL,	
+										{
+										{0,0},
+										&p_ijiazu_manu,
+										NULL,
+										NULL,					//the  128 bits service uuid set to null(not used)
+										NULL,					//the 32 bits Service UUID set to null(not used)
+										NULL,					//16 bits services Solicitation UUIDs set to null(not used)
+										NULL,					//List of 32 bit Service Solicitation UUIDs set to null(not used)
+										NULL,					//List of 128 bit Service Solicitation UUIDs set to null(not used)
+										NULL,					//proprietary data set to null(not used)
+										NULL,					//service data set not null(no service data to be sent)
+										0x0000,         		//device type : generic display
+										0x00,					// General discoverable. 
+										0x00},					//the tx power value,defult value is 0
+									
+								}
+};
+
+                  
+typedef struct {
+    uint8_t uu[16];
+} bt_uuid_t;
+
+int uuidType(unsigned char* p_uuid)
+{
+    int i = 0;
+    int match = 0;
+    int all_zero = 1;
+                
+    for(i = 0; i != 16; ++i)
+    {
+        if (i == 12 || i == 13)
+            continue;
+                              
+        if (p_uuid[i] == BASE_UUID[i])
+            ++match;
+                                        
+        if (p_uuid[i] != 0)
+            all_zero = 0;
+    }
+    if (all_zero)
+        return 0;
+    if (match == 12)
+        return LEN_UUID_32;
+    if (match == 14)
+        return LEN_UUID_16;
+    return LEN_UUID_128;
+}
+
+/*16-bits uuid to the structure of holding any type of UUID*/
+void btif_to_bta_uuid(tBT_UUID *p_dest, bt_uuid_t *p_src)
+{
+    char *p_byte = (char*)p_src;
+   
+    int i = 0;
+            
+    p_dest->len = uuidType(p_src->uu);
+                  
+    switch (p_dest->len)
+    {
+        case LEN_UUID_16:
+            p_dest->uu.uuid16 = (p_src->uu[13] << 8) + p_src->uu[12];
+            break;
+                                    
+        case LEN_UUID_32:
+            p_dest->uu.uuid32  = (p_src->uu[13] <<  8) + p_src->uu[12];
+            p_dest->uu.uuid32 += (p_src->uu[15] << 24) + (p_src->uu[14] << 16);
+            break;
+                                                   
+        case LEN_UUID_128:
+            for(i = 0; i != 16; ++i)
+                p_dest->uu.uuid128[i] = p_byte[i];
+                break;
+                                                            
+        default:         
+        LOG_ERROR("%s: Unknown UUID length %d!", __FUNCTION__, p_dest->len);
+        break;
+    }
+}
+/*set advertising config callback*/
+static void bta_gatts_set_adv_data_cback(tBTA_STATUS call_status)
+{
+    LOG_ERROR("set advertising config:status=%d\n", call_status);
+    /*dis init*/
+/*    tDIS_ATTR_MASK dis_attr_mask;
+    dis_attr_mask = DIS_ATTR_SYS_ID_BIT | DIS_ATTR_MODEL_NUM_BIT | DIS_ATTR_SERIAL_NUM_BIT | 
+        DIS_ATTR_FW_NUM_BIT | DIS_ATTR_HW_NUM_BIT | DIS_ATTR_SW_NUM_BIT | DIS_ATTR_MANU_NAME_BIT |
+        DIS_ATTR_IEEE_DATA_BIT | DIS_ATTR_PNP_ID_BIT;
+    DIS_SrInit(dis_attr_mask);
+*/
+    /*instantiate a battery service*/
+    bas_register();  
+	/*instantiate the driver for button profile*/
+	//app_button_init();
+	/*instantiate a button service*/
+	//button_init();
+	/*instantiate a hid device service*/
+	hidd_le_init();
+    /*start advetising*/
+//    BTA_GATTS_Listen(server_if, true, NULL);
+}
+
+/*register callback*/
+void bta_gatts_callback(tBTA_GATTS_EVT event, tBTA_GATTS* p_data)
+{
+    switch (event)
+    {   
+        case BTA_GATTS_REG_EVT:
+        {  
+            tBTA_GATT_STATUS  status = p_data->reg_oper.status;
+            server_if = p_data->reg_oper.server_if;
+            LOG_ERROR("register complete: event=%d, status=%d, server_if=%d\n", 
+                event, status, server_if);
+            
+            LOG_ERROR("set advertising parameters\n");
+			//set the advertising data to the btm layer
+			ESP_AppBleConfigadvData(&ijiazu_adv_data[BLE_ADV_DATA_IDX],
+								bta_gatts_set_adv_data_cback);
+			//set the adversting data to the btm layer
+			ESP_AppBleSetScanRsp(&ijiazu_adv_data[BLE_SCAN_RSP_DATA_IDX],NULL);
+           	
+        }
+        break;
+        /*connect callback*/
+        case BTA_GATTS_CONNECT_EVT:
+        {
+            LOG_ERROR("\ndevice is connected "BT_BD_ADDR_STR", server_if=%d,reason=0x%x,connect_id=%d\n", 
+                             BT_BD_ADDR_HEX(p_data->conn.remote_bda), p_data->conn.server_if,
+                             p_data->conn.reason, p_data->conn.conn_id);
+            /*return whether the remote device is currently connected*/
+            int is_connected = BTA_DmGetConnectionState(p_data->conn.remote_bda);
+            LOG_ERROR("is_connected=%d\n",is_connected);
+        }
+        break;
+        
+        default:
+        LOG_ERROR("unsettled event: %d\n", event);
+    }
+
+}
+
+static void ble_server_appRegister(void)
+{    
+    bt_uuid_t uuid;
+    tBT_UUID t_uuid;
+    memcpy(&uuid, BASE_UUID, sizeof(bt_uuid_t));
+    //memcpy(&uuid, DIS_UUID, sizeof(bt_uuid_t));
+    btif_to_bta_uuid(&t_uuid, &uuid);
+
+    LOG_ERROR("register gatts application\n");
+    BTA_GATTS_AppRegister(&t_uuid, bta_gatts_callback);
+}
+
+void gatts_server_test(void)
+{
+    BTM_SetTraceLevel(BT_TRACE_LEVEL_DEBUG);
+
+    ble_server_appRegister();
+}

+ 381 - 0
components/bt/bluedroid/app/app_project/SampleClientProject.c

@@ -0,0 +1,381 @@
+/****************************************************************************
+*
+* This file is for gatt client. It can scan ble device, connect one device, 
+*
+****************************************************************************/
+
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#include "bta_api.h"
+#include "bta_gatt_api.h"
+#include "controller.h"
+               
+#include "bt_trace.h"
+#include "btm_api.h"
+#include "bt_types.h"
+#include "gattc_profile.h"
+
+#define BT_BD_ADDR_STR         "%02x:%02x:%02x:%02x:%02x:%02x"
+#define BT_BD_ADDR_HEX(addr)   addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]
+
+tBTA_GATTC_IF client_if;
+BD_ADDR obj_addr;
+static unsigned char BASE_UUID[16] = {
+    0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
+    0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+    };
+                  
+typedef struct {
+    uint8_t uu[16];
+} bt_uuid_t;
+
+int uuidType(unsigned char* p_uuid)
+{
+    int i = 0;
+    int match = 0;
+    int all_zero = 1;
+                
+    for(i = 0; i != 16; ++i)
+    {
+        if (i == 12 || i == 13)
+            continue;
+                              
+        if (p_uuid[i] == BASE_UUID[i])
+            ++match;
+                                        
+        if (p_uuid[i] != 0)
+            all_zero = 0;
+    }
+    if (all_zero)
+        return 0;
+    if (match == 12)
+        return LEN_UUID_32;
+    if (match == 14)
+        return LEN_UUID_16;
+    return LEN_UUID_128;
+}
+
+static void btif_to_bta_uuid(tBT_UUID *p_dest, bt_uuid_t *p_src)
+{
+    char *p_byte = (char*)p_src;
+   
+    int i = 0;
+            
+    p_dest->len = uuidType(p_src->uu);
+                  
+    switch (p_dest->len)
+    {
+        case LEN_UUID_16:
+            p_dest->uu.uuid16 = (p_src->uu[13] << 8) + p_src->uu[12];
+            break;
+                                    
+        case LEN_UUID_32:
+            p_dest->uu.uuid32  = (p_src->uu[13] <<  8) + p_src->uu[12];
+            p_dest->uu.uuid32 += (p_src->uu[15] << 24) + (p_src->uu[14] << 16);
+            break;
+                                                   
+        case LEN_UUID_128:
+            for(i = 0; i != 16; ++i)
+                p_dest->uu.uuid128[i] = p_byte[i];
+                break;
+                                                            
+        default:         
+        LOG_ERROR("%s: Unknown UUID length %d!", __FUNCTION__, p_dest->len);
+        break;
+    }
+}
+/*
+uint16_t get_uuid16(tBT_UUID* p_uuid)
+{
+    if(p_uuid->len == LEN_UUID_16)
+    {
+        return p_uuid->uu.uuid16;
+    }
+    else if(p_uuid->len == LEN_UUID_128)
+    {
+        UINT16 u16;
+        UINT8 *p = &p_uuid->uu.uuid128[LEN_UUID_128 - 4];
+        STREAM_TO_UINT16(u16, p);
+        return u16;
+    }
+    else
+    {
+        return (UINT16)p_uuid->uu.uuid32;
+    }
+}
+
+//fill a GATT ID structure
+void bta_le_fill_16bits_gatt_id(UINT8 inst_id, UINT16 uuid, tBTA_GATT_ID* p_output)
+{
+    p_output->inst_id = inst_id;
+    p_output->uuid.len = LEN_UUID_16;
+    p_output->uuid.uu.uuid16 = uuid;
+}
+
+//fill a service ID structure with a 16 bits service UUID
+void bta_le_fill_16bits_srvc_id(bool is_pri, UINT8 inst_id, UINT16 srvc_uuid, tBTA_GATT_SRVC_ID* p_output)
+{
+    memset((void *)p_output, 0, sizeof(tBTA_GATT_SRVC_ID));
+    p_output->is_primary = is_pri;
+    bta_le_fill_16bits_gatt_id(inst_id, srvc_uuid, &p_output->id);
+}
+
+//fill a char ID structure with a 16 bits char UUID
+void bta_le_fill_16bits_char_id(UINT8 inst_id, UINT16 char_uuid, tBTA_GATT_ID* p_output)
+{
+    memset((void *)p_output, 0, sizeof(tBTA_GATT_ID));
+    bta_le_fill_16bits_gatt_id(inst_id, char_uuid, p_output);
+}
+*/
+/*get remote name*/
+static bool check_remote_name(tBTA_DM_INQ_RES* result, uint8_t* rmt_name, uint8_t* rmt_name_len)
+{
+    uint8_t *p_rmt_name = NULL;
+    uint8_t remote_name_len = 0;
+    
+    if (result->p_eir) {
+        p_rmt_name = BTM_CheckEirData(result->p_eir,
+            BTM_EIR_COMPLETE_LOCAL_NAME_TYPE,
+            &remote_name_len);
+        if (!p_rmt_name)
+            p_rmt_name = BTM_CheckEirData(result->p_eir,
+                BTM_EIR_SHORTENED_LOCAL_NAME_TYPE,
+                &remote_name_len);
+        if (p_rmt_name) {
+            if (remote_name_len > BD_NAME_LEN)
+                remote_name_len = BD_NAME_LEN;
+            if (rmt_name && rmt_name_len) {
+                memcpy(rmt_name, p_rmt_name, remote_name_len);
+                *(rmt_name + remote_name_len) = 0;
+                *rmt_name_len = remote_name_len;
+                }
+            return true;
+        }
+    }
+    return false;
+}
+
+/************************************************************************************
+* * Function        bta_scan_recult_callback
+* *
+* * Description     scan result.it will be called when device scaned a peer device
+* *
+* * Return          NULL
+**************************************************************************************/
+static void bta_scan_result_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH* p_data)
+{
+    uint8_t len;
+    BD_ADDR bd_addr;
+    char dev_name[32];
+    tBTA_GATT_TRANSPORT transport = BTA_GATT_TRANSPORT_LE;
+    //char obj_name[] = "Find Me";
+    char obj_name[] = "SimpleBLEPeripheral";
+    uint8_t dev_name_len;
+
+    switch (event)
+    {
+        case BTA_DM_INQ_RES_EVT:
+        {
+            LOG_ERROR("scan result: event=%d, "BT_BD_ADDR_STR", device_type=%d\n",
+                event, BT_BD_ADDR_HEX(p_data->inq_res.bd_addr), p_data->inq_res.device_type); 
+            
+            bdcpy(bd_addr, p_data->inq_res.bd_addr);
+            if (p_data->inq_res.p_eir)
+            {
+                if (BTM_CheckEirData(p_data->inq_res.p_eir, BTM_EIR_COMPLETE_LOCAL_NAME_TYPE, &len))
+                {
+                    p_data->inq_res.remt_name_not_required = TRUE;
+                }
+            }
+
+            if(check_remote_name(&(p_data->inq_res), dev_name, &dev_name_len))
+            {
+                LOG_ERROR("scan device name len=%d, name = %s\n", dev_name_len, dev_name);
+            }
+
+            if(strcmp(dev_name, obj_name) == 0)
+            {
+                bdcpy(obj_addr, bd_addr);
+                LOG_ERROR("find the device, obj_addr="BT_BD_ADDR_STR"\n", BT_BD_ADDR_HEX(obj_addr));
+//                BTA_GATTC_Open(client_if, obj_addr, true, transport);
+            }
+        }
+        break;
+
+        case BTA_DM_INQ_CMPL_EVT:
+        {
+            LOG_ERROR("%s-BLE observe complete. Num Resp %d\n", __FUNCTION__, p_data->inq_cmpl.num_resps);
+
+            LOG_ERROR("connect the device "BT_BD_ADDR_STR", client_if=%d\n", 
+                BT_BD_ADDR_HEX(obj_addr), client_if); 
+
+/* scan complete, start connect*/
+            BTA_GATTC_Open(client_if, obj_addr, true, transport); 
+        }
+        break;
+
+        default:
+        LOG_ERROR("%s : unknown event 0x%x", __FUNCTION__, event);
+    }
+}
+
+/************************************************************************************
+* * Function        bta_scan_param_setup_cback
+* *
+* * Description     set scan param callback.it will be called after setting scan parameter
+* *
+* * Return          NULL
+**************************************************************************************/
+static void bta_scan_param_setup_cback(tGATT_IF c_client_if, tBTM_STATUS status)
+{
+    client_if = c_client_if;
+    LOG_ERROR("\nset scan params complete: status=%d, client_if=%d\n", status, client_if);
+    /*start scan*/
+    BTA_DmBleObserve(true, 8, bta_scan_result_callback);
+}
+
+/************************************************************************************
+* * Function        bta_gattc_callback
+* *
+* * Description     app register callback
+* *
+* * Return          NULL
+**************************************************************************************/
+static void bta_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data)
+{
+    switch (event)
+    {   
+        case BTA_GATTC_REG_EVT:
+        {  
+            tBTA_GATT_STATUS  status = p_data->reg_oper.status;
+            client_if = p_data->reg_oper.client_if;
+            LOG_ERROR("%s:register complete: event=%d, status=%d, client_if=%d\n", __FUNCTION__, event, status, client_if);
+            UINT8 scan_interval = 0x50;
+            UINT8 scan_window = 0x30;
+            tBLE_SCAN_MODE scan_mode = BTM_BLE_SCAN_MODE_ACTI;
+            
+            bac_register();
+            /*register complete,set scan parameter*/
+            BTA_DmSetBleScanParams(client_if, scan_interval, scan_window, scan_mode,
+                bta_scan_param_setup_cback);
+  
+        }
+        break;
+        
+        /*connect callback*/
+        case BTA_GATTC_OPEN_EVT:
+        {
+            
+            LOG_ERROR("\n%s:device is connected "BT_BD_ADDR_STR", client_if=%d, status=%d, connect_id=%d\n", 
+                            __FUNCTION__, BT_BD_ADDR_HEX(p_data->open.remote_bda), p_data->open.client_if,
+                             p_data->open.status, p_data->open.conn_id);
+            /*return whether the remote device is currently connected*/
+            int is_connected = BTA_DmGetConnectionState(p_data->open.remote_bda);
+            LOG_ERROR("is_connected=%d\n",is_connected);
+            /*get the energy info of the controller*/
+
+            /*read battery level*/
+            int conn_id = p_data->open.conn_id;
+
+            /*discover service*/
+      //      BTA_GATTC_ServiceSearchRequest(conn_id, NULL);
+
+        }
+        break;
+/*
+        case BTA_GATTC_SEARCH_RES_EVT:
+        {
+           // tBTA_GATTC_SRVC_RES service_result;
+            LOG_ERROR("find the service,uuid=0x%x, is_primary=%d\n",
+                get_uuid16(&p_data->srvc_res.service_uuid.id.uuid), 
+                p_data->srvc_res.service_uuid.is_primary);
+        }
+        break;
+
+        case BTA_GATTC_SEARCH_CMPL_EVT:
+        {
+            LOG_ERROR("search service complete, conn_id=%d,status=%d\n", p_data->search_cmpl.conn_id,
+                p_data->search_cmpl.status);
+
+            //get first characteristic of battey service
+            LOG_ERROR("get first characteristic of battery service\n");
+            tBTA_GATT_STATUS    status;
+            tBTA_GATT_SRVC_ID   battery_srvc_id;
+            tBTA_GATTC_CHAR_ID  out_char_id;
+            tGATT_CHAR_PROP     out_char_prop;
+            bta_le_fill_16bits_srvc_id(TRUE, 0, UUID_SERVCLASS_BATTERY, &battery_srvc_id);
+            status = BTA_GATTC_GetFirstChar(p_data->search_cmpl.conn_id, &battery_srvc_id, NULL, 
+                &out_char_id, &out_char_prop);
+            if(status == 0)
+            {
+                LOG_ERROR("the first char:srvc_id=0x%x,char_id=0x%x, property = %d\n", 
+                    get_uuid16(&out_char_id.srvc_id.id.uuid), get_uuid16(&out_char_id.char_id.uuid),
+                    out_char_prop);
+                //read battery level
+                tBTA_GATTC_CHAR_ID battery_char_id;
+                bta_le_fill_16bits_srvc_id(TRUE, 0, UUID_SERVCLASS_BATTERY, &battery_char_id.srvc_id);
+                bta_le_fill_16bits_char_id(0, GATT_UUID_BATTERY_LEVEL, &battery_char_id.char_id);
+            
+                BTA_GATTC_ReadCharacteristic(p_data->search_cmpl.conn_id, &battery_char_id, 
+                    BTA_GATT_AUTH_REQ_NONE); 
+            }
+        }
+        break;
+
+        case BTA_GATTC_READ_CHAR_EVT:
+        {
+            
+            LOG_ERROR("\nread characteristic:connect_id=%d, status=%d\n", 
+                p_data->read.conn_id, p_data->read.status);
+            LOG_ERROR("srvc_id=0x%x,char_id=0x%x,descr_type=0x%x\n", 
+                get_uuid16(&p_data->read.srvc_id.id.uuid), 
+                get_uuid16(&p_data->read.char_id.uuid), 
+                get_uuid16(&p_data->read.descr_type.uuid));
+            if(get_uuid16(&p_data->read.descr_type.uuid) != GATT_UUID_CHAR_AGG_FORMAT
+                && p_data->read.p_value->unformat.len > 0
+                && p_data->read.p_value->unformat.p_value != NULL)
+            {
+                LOG_ERROR("read the value: len=%d, value=%d\n", p_data->read.p_value->unformat.len,
+                    *(p_data->read.p_value->unformat.p_value));
+            }
+        }
+        break;
+*/
+        default:
+        LOG_ERROR("%s:unknown event: %d\n", __FUNCTION__, event);
+    }
+
+}
+
+/************************************************************************************
+* * Function        ble_client_appRegister
+* *
+* * Description     app register function
+* *
+* * Return          NULL
+**************************************************************************************/
+void ble_client_appRegister(void)
+{
+    
+    bt_uuid_t uuid;
+    tBT_UUID t_uuid;
+    memcpy(&uuid, BASE_UUID, sizeof(bt_uuid_t));
+    btif_to_bta_uuid(&t_uuid, &uuid);
+
+    LOG_ERROR("register application\n");
+    BTA_GATTC_AppRegister(&t_uuid, bta_gattc_callback);
+
+    /*battery service register*/
+//    bac_register();
+
+}
+
+void gattc_client_test(void)
+{
+    BTM_SetTraceLevel(BT_TRACE_LEVEL_DEBUG);
+
+    ble_client_appRegister();
+}

+ 62 - 0
components/bt/bluedroid/app/include/app_button.h

@@ -0,0 +1,62 @@
+/**
+ ****************************************************************************************
+ *
+ * @file app_button.h
+ *
+ * @brief button Service Application entry point
+ *
+ * Copyright (C) ESPRESSIF 2016
+ * Created by Yulong at 2016/02/24
+ *
+ *
+ ****************************************************************************************
+ */
+
+ /*
+ * DEFINES
+ ****************************************************************************************
+ */
+#define BUTTON_HEAD		(0x01)
+#define BUTTON_PRESS_EVT (0x10)
+
+//the key value enum
+enum 
+{
+	Button_Up = 0x01,
+	Button_Voice = 0x02,
+	Button_OK = 0x04,
+	Button_Down = 0x08,
+	Button_Back = 0x10,
+};
+
+
+typedef struct {
+	uint8_t  key_val;	//button val
+	uint8_t head;		//the head of the frame
+}key_frame;
+
+
+typedef struct 
+{
+	bool button_press;
+	key_frame key_msg;
+}app_key_env;
+
+
+
+extern app_key_env key_press;
+
+/*
+ * FUNCTIONS DECLARATION
+ ****************************************************************************************
+ */
+
+ void app_button_init(void);
+
+ void GPIO_isr_callback(void* arg);
+
+ uint8_t check_sum(uint8_t *check_array,uint8_t len);
+
+
+
+

+ 46 - 0
components/bt/bluedroid/app/include/bt_app_common.h

@@ -0,0 +1,46 @@
+#ifndef __BT_APP_COMMON_H__
+#define __BT_APP_COMMON_H__
+
+#include <stdint.h>
+#include "osi.h"
+
+/** Bluetooth Error Status */
+/** originally defined in bluetooth.h */
+typedef enum {
+    BT_STATUS_SUCCESS,
+    BT_STATUS_FAIL,
+    BT_STATUS_NOT_READY,
+    BT_STATUS_NOMEM,
+    BT_STATUS_BUSY,
+    BT_STATUS_DONE,
+    BT_STATUS_UNSUPPORTED,
+    BT_STATUS_PARAM_INVALID,
+    BT_STATUS_UNHANDLED,
+    BT_STATUS_AUTH_FAILURE,
+    BT_STATUS_RMT_DEV_DOWN
+
+} bt_status_t;
+    
+/* BT APP1 Events */
+#define BT_EVT_APP1                     (0xB000)
+#define BT_EVT_APP1_CONTEXT_SWITCH      (0x0001 | BT_EVT_APP1)
+
+typedef void (tBTAPP1_CBACK) (UINT16 event, char *p_param);
+typedef void (tBTAPP1_COPY_CBACK) (UINT16 event, char *p_dest, char *p_src);
+
+typedef struct
+{
+    BT_HDR               hdr;
+    tBTAPP1_CBACK*       p_cb;    /* context switch callback */
+
+    /* parameters passed to callback */
+    UINT16               event;   /* message event id */
+    char                 p_param[0]; /* parameter area needs to be last */
+} tBTAPP1_CONTEXT_SWITCH_CBACK;
+
+bt_status_t bt_app1_transfer_context (tBTAPP1_CBACK *p_cback, UINT16 event, char* p_params, int param_len, tBTAPP1_COPY_CBACK *p_copy_cback);
+
+void bt_app1_init_ok(UNUSED_ATTR uint16_t event, UNUSED_ATTR char *p_param);
+
+void bt_app1_task_start_up(void);
+#endif /* __BT_APP_COMMON_H__ */

+ 23 - 0
components/bt/bluedroid/app/include/bt_app_defs.h

@@ -0,0 +1,23 @@
+#include "bta_api.h"
+#include "btm_ble_api.h"
+
+enum
+{
+	BLE_ADV_DATA_IDX,
+	BLE_SCAN_RSP_DATA_IDX,
+	ADV_SCAN_IDX_MAX
+};
+
+typedef struct
+{
+	char	*adv_name;				//set the device name to be sent on the advertising
+	tBTA_BLE_ADV_DATA ble_adv_data;
+}tESP_BLE_ADV_DATA;
+
+extern void ESP_AppBleConfigadvData(tESP_BLE_ADV_DATA *adv_data,
+												tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback);
+
+extern void ESP_AppBleSetScanRsp(tESP_BLE_ADV_DATA *scan_rsp_data,
+							  tBTA_SET_ADV_DATA_CMPL_CBACK *p_scan_rsp_data_cback);
+
+

+ 46 - 0
components/bt/bluedroid/app/include/gattc_profile.h

@@ -0,0 +1,46 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 1999-2013 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/*******************************************************************************
+**
+** Header file for gatt client.
+**
+********************************************************************************/
+
+#include "bt_target.h"
+#include "gatt_api.h"
+#include "gattdefs.h"
+
+/*******************************************************************************
+**      BATTERY CLIENT API
+*******************************************************************************/
+/***************************************************************
+**
+** Function     bac_register
+**
+** Description  register app for battery service
+**
+****************************************************************/
+extern void bac_register(void);
+
+extern void gattc_client_test(void);
+#ifdef __cplusplus
+
+}
+#endif
+

+ 5797 - 0
components/bt/bluedroid/bta/dm/bta_dm_act.c

@@ -0,0 +1,5797 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2014 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This file contains the action functions for device manager state
+ *  machine.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#include "bt_types.h"
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_dm_int.h"
+#include "bta_dm_co.h"
+#include "btm_api.h"
+#include "btm_int.h"
+#include "btu.h"
+#include "sdp_api.h"
+#include "l2c_api.h"
+#include "utl.h"
+#include "gap_api.h"    /* For GAP_BleReadPeerPrefConnParams */
+#include <string.h>
+
+#define LOG_TAG "bt_bta_dm"
+// #include "osi/include/log.h"
+
+#if (GAP_INCLUDED == TRUE)
+#include "gap_api.h"
+#endif
+
+static void bta_dm_inq_results_cb (tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir);
+static void bta_dm_inq_cmpl_cb (void * p_result);
+static void bta_dm_service_search_remname_cback (BD_ADDR bd_addr, DEV_CLASS dc, BD_NAME bd_name);
+static void bta_dm_remname_cback (tBTM_REMOTE_DEV_NAME *p_remote_name);
+static void bta_dm_find_services ( BD_ADDR bd_addr);
+static void bta_dm_discover_next_device(void);
+static void bta_dm_sdp_callback (UINT16 sdp_status);
+static UINT8 bta_dm_authorize_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, UINT8 *service_name, UINT8 service_id, BOOLEAN is_originator);
+static UINT8 bta_dm_pin_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, BOOLEAN min_16_digit);
+static UINT8 bta_dm_new_link_key_cback(BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, LINK_KEY key, UINT8 key_type);
+static UINT8 bta_dm_authentication_complete_cback(BD_ADDR bd_addr, DEV_CLASS dev_class,BD_NAME bd_name, int result);
+static void bta_dm_local_name_cback(BD_ADDR bd_addr);
+static BOOLEAN bta_dm_check_av(UINT16 event);
+static void bta_dm_bl_change_cback (tBTM_BL_EVENT_DATA *p_data);
+
+
+#if BLE_INCLUDED == TRUE
+static void bta_dm_acl_change_cback(BD_ADDR p_bda, DEV_CLASS p_dc,
+                                    BD_NAME p_bdn, UINT8 *features,
+                                    BOOLEAN is_new, UINT16 handle,
+                                    tBT_TRANSPORT transport);
+#else
+static void bta_dm_acl_change_cback(BD_ADDR p_bda, DEV_CLASS p_dc,
+                                    BD_NAME p_bdn, UINT8 *features,
+                                    BOOLEAN is_new);
+#endif
+
+
+static void bta_dm_policy_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+
+/* Extended Inquiry Response */
+static UINT8 bta_dm_sp_cback (tBTM_SP_EVT event, tBTM_SP_EVT_DATA *p_data);
+
+static void bta_dm_set_eir (char *local_name);
+
+static void bta_dm_eir_search_services( tBTM_INQ_RESULTS  *p_result,
+                                        tBTA_SERVICE_MASK *p_services_to_search,
+                                        tBTA_SERVICE_MASK *p_services_found);
+
+static void bta_dm_search_timer_cback (TIMER_LIST_ENT *p_tle);
+static void bta_dm_disable_conn_down_timer_cback (TIMER_LIST_ENT *p_tle);
+static void bta_dm_rm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+static void bta_dm_adjust_roles(BOOLEAN delay_role_switch);
+static char *bta_dm_get_remname(void);
+static void bta_dm_bond_cancel_complete_cback(tBTM_STATUS result);
+
+static BOOLEAN bta_dm_read_remote_device_name (BD_ADDR bd_addr,tBT_TRANSPORT transport);
+static void bta_dm_discover_device(BD_ADDR remote_bd_addr);
+
+static void bta_dm_sys_hw_cback( tBTA_SYS_HW_EVT status );
+static void bta_dm_disable_search_and_disc(void);
+
+#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+    #if ((defined SMP_INCLUDED) && (SMP_INCLUDED == TRUE))
+static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_DATA *p_data);
+    #endif
+static void bta_dm_ble_id_key_cback (UINT8 key_type, tBTM_BLE_LOCAL_KEYS *p_key);
+    #if ((defined BTA_GATT_INCLUDED) &&  (BTA_GATT_INCLUDED == TRUE))
+static void bta_dm_gattc_register(void);
+static void btm_dm_start_gatt_discovery(BD_ADDR bd_addr);
+static void bta_dm_cancel_gatt_discovery(BD_ADDR bd_addr);
+static void bta_dm_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data);
+extern tBTA_DM_CONTRL_STATE bta_dm_pm_obtain_controller_state(void);
+    #endif
+
+#if BLE_VND_INCLUDED == TRUE
+static void bta_dm_ctrl_features_rd_cmpl_cback(tBTM_STATUS result);
+#endif
+
+#ifndef BTA_DM_BLE_ADV_CHNL_MAP
+#define BTA_DM_BLE_ADV_CHNL_MAP (BTM_BLE_ADV_CHNL_37|BTM_BLE_ADV_CHNL_38|BTM_BLE_ADV_CHNL_39)
+#endif
+#endif
+
+static void bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr);
+static void bta_dm_observe_results_cb(tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir);
+static void bta_dm_observe_cmpl_cb(void * p_result);
+static void bta_dm_delay_role_switch_cback(TIMER_LIST_ENT *p_tle);
+extern void sdpu_uuid16_to_uuid128(UINT16 uuid16, UINT8* p_uuid128);
+static void bta_dm_disable_timer_cback(TIMER_LIST_ENT *p_tle);
+
+
+const UINT16 bta_service_id_to_uuid_lkup_tbl [BTA_MAX_SERVICE_ID] =
+{
+    UUID_SERVCLASS_PNP_INFORMATION,         /* Reserved */
+    UUID_SERVCLASS_SERIAL_PORT,             /* BTA_SPP_SERVICE_ID */
+    UUID_SERVCLASS_DIALUP_NETWORKING,       /* BTA_DUN_SERVICE_ID */
+    UUID_SERVCLASS_AUDIO_SOURCE,            /* BTA_A2DP_SOURCE_SERVICE_ID */
+    UUID_SERVCLASS_LAN_ACCESS_USING_PPP,    /* BTA_LAP_SERVICE_ID */
+    UUID_SERVCLASS_HEADSET,                 /* BTA_HSP_HS_SERVICE_ID */
+    UUID_SERVCLASS_HF_HANDSFREE,            /* BTA_HFP_HS_SERVICE_ID */
+    UUID_SERVCLASS_OBEX_OBJECT_PUSH,        /* BTA_OPP_SERVICE_ID */
+    UUID_SERVCLASS_OBEX_FILE_TRANSFER,      /* BTA_FTP_SERVICE_ID */
+    UUID_SERVCLASS_CORDLESS_TELEPHONY,      /* BTA_CTP_SERVICE_ID */
+    UUID_SERVCLASS_INTERCOM,                /* BTA_ICP_SERVICE_ID */
+    UUID_SERVCLASS_IRMC_SYNC,               /* BTA_SYNC_SERVICE_ID */
+    UUID_SERVCLASS_DIRECT_PRINTING,         /* BTA_BPP_SERVICE_ID */
+    UUID_SERVCLASS_IMAGING_RESPONDER,       /* BTA_BIP_SERVICE_ID */
+    UUID_SERVCLASS_PANU,                    /* BTA_PANU_SERVICE_ID */
+    UUID_SERVCLASS_NAP,                     /* BTA_NAP_SERVICE_ID */
+    UUID_SERVCLASS_GN,                      /* BTA_GN_SERVICE_ID */
+    UUID_SERVCLASS_SAP,                     /* BTA_SAP_SERVICE_ID */
+    UUID_SERVCLASS_AUDIO_SINK,              /* BTA_A2DP_SERVICE_ID */
+    UUID_SERVCLASS_AV_REMOTE_CONTROL,       /* BTA_AVRCP_SERVICE_ID */
+    UUID_SERVCLASS_HUMAN_INTERFACE,         /* BTA_HID_SERVICE_ID */
+    UUID_SERVCLASS_VIDEO_SINK,              /* BTA_VDP_SERVICE_ID */
+    UUID_SERVCLASS_PBAP_PSE,                /* BTA_PBAP_SERVICE_ID */
+    UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY,   /* BTA_HSP_SERVICE_ID */
+    UUID_SERVCLASS_AG_HANDSFREE,            /* BTA_HFP_SERVICE_ID */
+    UUID_SERVCLASS_MESSAGE_ACCESS,          /* BTA_MAP_SERVICE_ID */
+    UUID_SERVCLASS_MESSAGE_NOTIFICATION,    /* BTA_MN_SERVICE_ID */
+    UUID_SERVCLASS_HDP_PROFILE,             /* BTA_HDP_SERVICE_ID */
+    UUID_SERVCLASS_PBAP_PCE                 /* BTA_PCE_SERVICE_ID */
+#if BLE_INCLUDED && BTA_GATT_INCLUDED
+    ,UUID_PROTOCOL_ATT                       /* BTA_GATT_SERVICE_ID */
+#endif
+};
+
+/*
+ * NOTE : The number of element in bta_service_id_to_btm_srv_id_lkup_tbl should be matching with
+ *        the value BTA_MAX_SERVICE_ID in bta_api.h
+ *
+ *        i.e., If you add new Service ID for BTA, the correct security ID of the new service
+ *              from Security service definitions (btm_api.h) should be added to this lookup table.
+ */
+const UINT32 bta_service_id_to_btm_srv_id_lkup_tbl [BTA_MAX_SERVICE_ID] =
+{
+    0,                                      /* Reserved */
+    BTM_SEC_SERVICE_SERIAL_PORT,            /* BTA_SPP_SERVICE_ID */
+    BTM_SEC_SERVICE_DUN,                    /* BTA_DUN_SERVICE_ID */
+    BTM_SEC_SERVICE_AVDTP,                  /* BTA_AUDIO_SOURCE_SERVICE_ID */
+    BTM_SEC_SERVICE_LAN_ACCESS,             /* BTA_LAP_SERVICE_ID */
+    BTM_SEC_SERVICE_HEADSET_AG,             /* BTA_HSP_SERVICE_ID */
+    BTM_SEC_SERVICE_AG_HANDSFREE,           /* BTA_HFP_SERVICE_ID */
+    BTM_SEC_SERVICE_OBEX,                   /* BTA_OPP_SERVICE_ID */
+    BTM_SEC_SERVICE_OBEX_FTP,               /* BTA_FTP_SERVICE_ID */
+    BTM_SEC_SERVICE_CORDLESS,               /* BTA_CTP_SERVICE_ID */
+    BTM_SEC_SERVICE_INTERCOM,               /* BTA_ICP_SERVICE_ID */
+    BTM_SEC_SERVICE_IRMC_SYNC,              /* BTA_SYNC_SERVICE_ID */
+    BTM_SEC_SERVICE_BPP_JOB,                /* BTA_BPP_SERVICE_ID */
+    BTM_SEC_SERVICE_BIP,                    /* BTA_BIP_SERVICE_ID */
+    BTM_SEC_SERVICE_BNEP_PANU,              /* BTA_PANU_SERVICE_ID */
+    BTM_SEC_SERVICE_BNEP_NAP,               /* BTA_NAP_SERVICE_ID */
+    BTM_SEC_SERVICE_BNEP_GN,                /* BTA_GN_SERVICE_ID */
+    BTM_SEC_SERVICE_SAP,                    /* BTA_SAP_SERVICE_ID */
+    BTM_SEC_SERVICE_AVDTP,                  /* BTA_A2DP_SERVICE_ID */
+    BTM_SEC_SERVICE_AVCTP,                  /* BTA_AVRCP_SERVICE_ID */
+    BTM_SEC_SERVICE_HIDH_SEC_CTRL,          /* BTA_HID_SERVICE_ID */
+    BTM_SEC_SERVICE_AVDTP,                  /* BTA_VDP_SERVICE_ID */
+    BTM_SEC_SERVICE_PBAP,                   /* BTA_PBAP_SERVICE_ID */
+    BTM_SEC_SERVICE_HEADSET,                /* BTA_HSP_HS_SERVICE_ID */
+    BTM_SEC_SERVICE_HF_HANDSFREE,           /* BTA_HFP_HS_SERVICE_ID */
+    BTM_SEC_SERVICE_MAP,                    /* BTA_MAP_SERVICE_ID */
+    BTM_SEC_SERVICE_MAP,                    /* BTA_MN_SERVICE_ID */
+    BTM_SEC_SERVICE_HDP_SNK,                /* BTA_HDP_SERVICE_ID */
+    BTM_SEC_SERVICE_PBAP                    /* BTA_PCE_SERVICE_ID */
+#if BLE_INCLUDED && BTA_GATT_INCLUDED
+    ,BTM_SEC_SERVICE_ATT                    /* BTA_GATT_SERVICE_ID */
+#endif
+
+};
+
+/* bta security callback */
+const tBTM_APPL_INFO bta_security =
+{
+    &bta_dm_authorize_cback,
+    &bta_dm_pin_cback,
+    &bta_dm_new_link_key_cback,
+    &bta_dm_authentication_complete_cback,
+    &bta_dm_bond_cancel_complete_cback,
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+    &bta_dm_sp_cback
+#else
+    NULL
+#endif
+#if BLE_INCLUDED == TRUE
+#if SMP_INCLUDED == TRUE
+    ,&bta_dm_ble_smp_cback
+#endif
+    ,&bta_dm_ble_id_key_cback
+#endif
+
+};
+
+#define MAX_DISC_RAW_DATA_BUF       (4096)
+UINT8 g_disc_raw_data_buf[MAX_DISC_RAW_DATA_BUF];
+
+extern DEV_CLASS local_device_default_class;
+
+/*******************************************************************************
+**
+** Function         bta_dm_enable
+**
+** Description      Initialises the BT device manager
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_enable(tBTA_DM_MSG *p_data)
+{
+    tBTA_SYS_HW_MSG *sys_enable_event;
+    tBTA_DM_ENABLE enable_event;
+
+    /* if already in use, return an error */
+    if( bta_dm_cb.is_bta_dm_active == TRUE  )
+    {
+        APPL_TRACE_WARNING("%s Device already started by another application", __func__);
+        memset(&enable_event, 0, sizeof(tBTA_DM_ENABLE));
+        enable_event.status = BTA_FAILURE;
+        if (p_data->enable.p_sec_cback != NULL)
+            p_data->enable.p_sec_cback(BTA_DM_ENABLE_EVT, (tBTA_DM_SEC *)&enable_event);
+        return;
+    }
+
+    /* first, register our callback to SYS HW manager */
+    bta_sys_hw_register( BTA_SYS_HW_BLUETOOTH, bta_dm_sys_hw_cback );
+
+    /* make sure security callback is saved - if no callback, do not erase the previous one,
+    it could be an error recovery mechanism */
+    if( p_data->enable.p_sec_cback != NULL  )
+    bta_dm_cb.p_sec_cback = p_data->enable.p_sec_cback;
+    /* notify BTA DM is now active */
+    bta_dm_cb.is_bta_dm_active = TRUE;
+
+    /* send a message to BTA SYS */
+    if ((sys_enable_event = (tBTA_SYS_HW_MSG *) GKI_getbuf(sizeof(tBTA_SYS_HW_MSG))) != NULL)
+    {
+        sys_enable_event->hdr.event = BTA_SYS_API_ENABLE_EVT;
+        sys_enable_event->hw_module = BTA_SYS_HW_BLUETOOTH;
+
+        bta_sys_sendmsg(sys_enable_event);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_sys_hw_cback
+**
+** Description     callback register to SYS to get HW status updates
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_sys_hw_cback( tBTA_SYS_HW_EVT status )
+{
+    DEV_CLASS   dev_class;
+    tBTA_DM_SEC_CBACK           *temp_cback;
+#if BLE_INCLUDED == TRUE
+    UINT8                   key_mask = 0;
+    BT_OCTET16              er;
+    tBTA_BLE_LOCAL_ID_KEYS  id_key;
+#endif
+
+    APPL_TRACE_DEBUG("%s with event: %i", __func__, status);
+
+    /* On H/W error evt, report to the registered DM application callback */
+    if (status == BTA_SYS_HW_ERROR_EVT) {
+          if( bta_dm_cb.p_sec_cback != NULL )
+                bta_dm_cb.p_sec_cback(BTA_DM_HW_ERROR_EVT, NULL);
+          return;
+    }
+
+    if( status == BTA_SYS_HW_OFF_EVT )
+    {
+        if( bta_dm_cb.p_sec_cback != NULL )
+            bta_dm_cb.p_sec_cback(BTA_DM_DISABLE_EVT, NULL);
+
+        /* reinitialize the control block */
+        memset(&bta_dm_cb, 0, sizeof(bta_dm_cb));
+
+        /* unregister from SYS */
+        bta_sys_hw_unregister( BTA_SYS_HW_BLUETOOTH );
+        /* notify BTA DM is now unactive */
+        bta_dm_cb.is_bta_dm_active = FALSE;
+    }
+    else
+    if( status == BTA_SYS_HW_ON_EVT )
+    {
+        /* FIXME: We should not unregister as the SYS shall invoke this callback on a H/W error.
+        * We need to revisit when this platform has more than one BLuetooth H/W chip */
+        //bta_sys_hw_unregister( BTA_SYS_HW_BLUETOOTH);
+
+        /* save security callback */
+        temp_cback = bta_dm_cb.p_sec_cback;
+        /* make sure the control block is properly initialized */
+        memset(&bta_dm_cb, 0, sizeof(bta_dm_cb));
+        /* and retrieve the callback */
+        bta_dm_cb.p_sec_cback=temp_cback;
+        bta_dm_cb.is_bta_dm_active = TRUE;
+
+        /* hw is ready, go on with BTA DM initialization */
+        memset(&bta_dm_search_cb, 0x00, sizeof(bta_dm_search_cb));
+        memset(&bta_dm_conn_srvcs, 0x00, sizeof(bta_dm_conn_srvcs));
+        memset(&bta_dm_di_cb, 0, sizeof(tBTA_DM_DI_CB));
+
+        memcpy(dev_class, p_bta_dm_cfg->dev_class, sizeof(dev_class));
+        BTM_SetDeviceClass (dev_class);
+
+#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
+        /* load BLE local information: ID keys, ER if available */
+        bta_dm_co_ble_load_local_keys(&key_mask, er, &id_key);
+
+        if (key_mask & BTA_BLE_LOCAL_KEY_TYPE_ER)
+        {
+            BTM_BleLoadLocalKeys(BTA_BLE_LOCAL_KEY_TYPE_ER, (tBTM_BLE_LOCAL_KEYS *)&er);
+        }
+        if (key_mask & BTA_BLE_LOCAL_KEY_TYPE_ID)
+        {
+            BTM_BleLoadLocalKeys(BTA_BLE_LOCAL_KEY_TYPE_ID, (tBTM_BLE_LOCAL_KEYS *)&id_key);
+        }
+#if ((defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+        bta_dm_search_cb.conn_id = BTA_GATT_INVALID_CONN_ID;
+#endif
+#endif
+
+        BTM_SecRegister((tBTM_APPL_INFO*)&bta_security);
+        BTM_SetDefaultLinkSuperTout(p_bta_dm_cfg->link_timeout);
+        BTM_WritePageTimeout(p_bta_dm_cfg->page_timeout);
+        bta_dm_cb.cur_policy = p_bta_dm_cfg->policy_settings;
+        BTM_SetDefaultLinkPolicy(bta_dm_cb.cur_policy);
+        BTM_RegBusyLevelNotif (bta_dm_bl_change_cback, NULL, BTM_BL_UPDATE_MASK|BTM_BL_ROLE_CHG_MASK);
+
+#if BLE_VND_INCLUDED == TRUE
+        BTM_BleReadControllerFeatures (bta_dm_ctrl_features_rd_cmpl_cback);
+#endif
+
+        /* Earlier, we used to invoke BTM_ReadLocalAddr which was just copying the bd_addr
+           from the control block and invoking the callback which was sending the DM_ENABLE_EVT.
+           But then we have a few HCI commands being invoked above which were still in progress
+           when the ENABLE_EVT was sent. So modified this to fetch the local name which forces
+           the DM_ENABLE_EVT to be sent only after all the init steps are complete */
+        BTM_ReadLocalDeviceNameFromController((tBTM_CMPL_CB *)bta_dm_local_name_cback);
+
+        bta_sys_rm_register((tBTA_SYS_CONN_CBACK*)bta_dm_rm_cback);
+
+        /* initialize bluetooth low power manager */
+        bta_dm_init_pm();
+
+        bta_sys_policy_register((tBTA_SYS_CONN_CBACK*)bta_dm_policy_cback);
+
+#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
+        bta_dm_gattc_register();
+#endif
+
+    }
+    else
+        APPL_TRACE_DEBUG(" --- ignored event");
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_disable
+**
+** Description      Disables the BT device manager
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_disable (tBTA_DM_MSG *p_data)
+{
+    UNUSED(p_data);
+
+    /* Set l2cap idle timeout to 0 (so BTE immediately disconnects ACL link after last channel is closed) */
+    L2CA_SetIdleTimeoutByBdAddr((UINT8 *)BT_BD_ANY, 0, BT_TRANSPORT_BR_EDR);
+    L2CA_SetIdleTimeoutByBdAddr((UINT8 *)BT_BD_ANY, 0, BT_TRANSPORT_LE);
+
+    /* disable all active subsystems */
+    bta_sys_disable(BTA_SYS_HW_BLUETOOTH);
+
+    BTM_SetDiscoverability(BTM_NON_DISCOVERABLE, 0, 0);
+    BTM_SetConnectability(BTM_NON_CONNECTABLE, 0, 0);
+
+    bta_dm_disable_pm();
+    bta_dm_disable_search_and_disc();
+    bta_dm_cb.disabling = TRUE;
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    BTM_BleClearBgConnDev();
+#endif
+
+    if(BTM_GetNumAclLinks()==0)
+    {
+#if (defined(BTA_DISABLE_DELAY) && BTA_DISABLE_DELAY > 0)
+        /* If BTA_DISABLE_DELAY is defined and greater than zero, then delay the shutdown by
+         * BTA_DISABLE_DELAY milliseconds
+         */
+        APPL_TRACE_WARNING("%s BTA_DISABLE_DELAY set to %d ms",
+                            __FUNCTION__, BTA_DISABLE_DELAY);
+        bta_sys_stop_timer(&bta_dm_cb.disable_timer);
+        bta_dm_cb.disable_timer.p_cback = (TIMER_CBACK*)&bta_dm_disable_conn_down_timer_cback;
+        bta_sys_start_timer(&bta_dm_cb.disable_timer, 0, BTA_DISABLE_DELAY);
+#else
+        bta_dm_disable_conn_down_timer_cback(NULL);
+#endif
+    }
+    else
+    {
+        bta_dm_cb.disable_timer.p_cback = (TIMER_CBACK*)&bta_dm_disable_timer_cback;
+        bta_dm_cb.disable_timer.param = 0;
+        bta_sys_start_timer(&bta_dm_cb.disable_timer, 0, 5000);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_disable_timer_cback
+**
+** Description      Called if the disable timer expires
+**                  Used to close ACL connections which are still active
+**
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_disable_timer_cback (TIMER_LIST_ENT *p_tle)
+{
+    UNUSED(p_tle);
+    UINT8 i;
+    tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
+    BOOLEAN trigger_disc = FALSE;
+
+
+    APPL_TRACE_EVENT(" bta_dm_disable_timer_cback trial %d ", p_tle->param);
+
+    if(BTM_GetNumAclLinks() && p_tle->param == 0)
+    {
+        for(i=0; i<bta_dm_cb.device_list.count; i++)
+        {
+#if (BLE_INCLUDED == TRUE)
+            transport = bta_dm_cb.device_list.peer_device[i].transport;
+#endif
+            btm_remove_acl(bta_dm_cb.device_list.peer_device[i].peer_bdaddr, transport);
+            trigger_disc = TRUE;
+        }
+
+        /* Retrigger disable timer in case ACL disconnect failed, DISABLE_EVT still need
+            to be sent out to avoid jave layer disable timeout */
+        if (trigger_disc)
+        {
+            bta_dm_cb.disable_timer.p_cback = (TIMER_CBACK*)&bta_dm_disable_timer_cback;
+            bta_dm_cb.disable_timer.param = 1;
+            bta_sys_start_timer(&bta_dm_cb.disable_timer, 0, 1500);
+        }
+    }
+    else
+    {
+        bta_dm_cb.disabling = FALSE;
+
+        bta_sys_remove_uuid(UUID_SERVCLASS_PNP_INFORMATION);
+        bta_dm_cb.p_sec_cback(BTA_DM_DISABLE_EVT, NULL);
+    }
+}
+
+
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_set_dev_name
+**
+** Description      Sets local device name
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_set_dev_name (tBTA_DM_MSG *p_data)
+{
+
+    BTM_SetLocalDeviceName((char*)p_data->set_name.name);
+    bta_dm_set_eir ((char*)p_data->set_name.name);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_set_visibility
+**
+** Description      Sets discoverability, connectability and pairability
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_set_visibility(tBTA_DM_MSG *p_data)
+{
+    UINT16 window, interval;
+    UINT16 le_disc_mode = BTM_BleReadDiscoverability();
+    UINT16 disc_mode = BTM_ReadDiscoverability(&window, &interval);
+    UINT16 le_conn_mode = BTM_BleReadConnectability();
+    UINT16 conn_mode = BTM_ReadConnectability(&window, &interval);
+
+    /* set modes for Discoverability and connectability if not ignore */
+    if (p_data->set_visibility.disc_mode != (BTA_DM_IGNORE | BTA_DM_LE_IGNORE))
+    {
+        if ((p_data->set_visibility.disc_mode & BTA_DM_LE_IGNORE) == BTA_DM_LE_IGNORE)
+            p_data->set_visibility.disc_mode =
+                ((p_data->set_visibility.disc_mode & ~BTA_DM_LE_IGNORE) | le_disc_mode);
+
+        if ((p_data->set_visibility.disc_mode & BTA_DM_IGNORE) == BTA_DM_IGNORE)
+            p_data->set_visibility.disc_mode =
+                ((p_data->set_visibility.disc_mode & ~BTA_DM_IGNORE) | disc_mode);
+
+        BTM_SetDiscoverability(p_data->set_visibility.disc_mode,
+                                bta_dm_cb.inquiry_scan_window,
+                                bta_dm_cb.inquiry_scan_interval);
+    }
+
+    if (p_data->set_visibility.conn_mode != (BTA_DM_IGNORE | BTA_DM_LE_IGNORE))
+    {
+        if ((p_data->set_visibility.conn_mode & BTA_DM_LE_IGNORE) == BTA_DM_LE_IGNORE)
+            p_data->set_visibility.conn_mode =
+                ((p_data->set_visibility.conn_mode & ~BTA_DM_LE_IGNORE) | le_conn_mode);
+
+        if ((p_data->set_visibility.conn_mode & BTA_DM_IGNORE) == BTA_DM_IGNORE)
+            p_data->set_visibility.conn_mode =
+                ((p_data->set_visibility.conn_mode & ~BTA_DM_IGNORE) | conn_mode);
+
+        BTM_SetConnectability(p_data->set_visibility.conn_mode,
+                                bta_dm_cb.page_scan_window,
+                                bta_dm_cb.page_scan_interval);
+    }
+
+    /* Send False or True if not ignore */
+    if (p_data->set_visibility.pair_mode != BTA_DM_IGNORE )
+    {
+
+        if (p_data->set_visibility.pair_mode == BTA_DM_NON_PAIRABLE)
+            bta_dm_cb.disable_pair_mode = TRUE;
+        else
+            bta_dm_cb.disable_pair_mode = FALSE;
+
+    }
+
+    /* Send False or True if not ignore */
+    if (p_data->set_visibility.conn_paired_only != BTA_DM_IGNORE)
+    {
+
+        if (p_data->set_visibility.conn_paired_only == BTA_DM_CONN_ALL)
+            bta_dm_cb.conn_paired_only = FALSE;
+        else
+            bta_dm_cb.conn_paired_only = TRUE;
+
+    }
+
+    /* Change mode if either mode is not ignore */
+    if (p_data->set_visibility.pair_mode != BTA_DM_IGNORE || p_data->set_visibility.conn_paired_only != BTA_DM_IGNORE)
+        BTM_SetPairableMode((BOOLEAN)(!(bta_dm_cb.disable_pair_mode)),bta_dm_cb.conn_paired_only);
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_process_remove_device
+**
+** Description      Removes device, Disconnects ACL link if required.
+****
+*******************************************************************************/
+void bta_dm_process_remove_device(BD_ADDR bd_addr)
+{
+#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
+     /* need to remove all pending background connection before unpair */
+     BTA_GATTC_CancelOpen(0, bd_addr, FALSE);
+#endif
+
+     BTM_SecDeleteDevice(bd_addr);
+
+#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
+      /* remove all cached GATT information */
+      BTA_GATTC_Refresh(bd_addr);
+#endif
+
+      if (bta_dm_cb.p_sec_cback)
+      {
+         tBTA_DM_SEC sec_event;
+         bdcpy(sec_event.link_down.bd_addr, bd_addr);
+         /* No connection, set status to success (acl disc code not valid) */
+         sec_event.link_down.status = HCI_SUCCESS;
+         bta_dm_cb.p_sec_cback(BTA_DM_DEV_UNPAIRED_EVT, &sec_event);
+      }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_remove_device
+**
+** Description      Removes device, disconnects ACL link if required.
+****
+*******************************************************************************/
+void bta_dm_remove_device(tBTA_DM_MSG *p_data)
+{
+    tBTA_DM_API_REMOVE_DEVICE *p_dev = &p_data->remove_dev;
+    if (p_dev == NULL)
+        return;
+
+    BD_ADDR other_address;
+    bdcpy(other_address, p_dev->bd_addr);
+
+    /* If ACL exists for the device in the remove_bond message*/
+    BOOLEAN continue_delete_dev = FALSE;
+    UINT8 other_transport = BT_TRANSPORT_INVALID;
+
+    if (BTM_IsAclConnectionUp(p_dev->bd_addr, BT_TRANSPORT_LE) ||
+        BTM_IsAclConnectionUp(p_dev->bd_addr, BT_TRANSPORT_BR_EDR))
+    {
+        APPL_TRACE_DEBUG("%s: ACL Up count  %d", __func__, bta_dm_cb.device_list.count);
+        continue_delete_dev = FALSE;
+
+        /* Take the link down first, and mark the device for removal when disconnected */
+        for(int i=0; i < bta_dm_cb.device_list.count; i++)
+        {
+            if (!bdcmp(bta_dm_cb.device_list.peer_device[i].peer_bdaddr, p_dev->bd_addr))
+            {
+                bta_dm_cb.device_list.peer_device[i].conn_state = BTA_DM_UNPAIRING;
+                btm_remove_acl( p_dev->bd_addr, bta_dm_cb.device_list.peer_device[i].transport);
+                APPL_TRACE_DEBUG("%s:transport = %d", __func__,
+                                  bta_dm_cb.device_list.peer_device[i].transport);
+
+                /* save the other transport to check if device is connected on other_transport */
+                if(bta_dm_cb.device_list.peer_device[i].transport == BT_TRANSPORT_LE)
+                   other_transport = BT_TRANSPORT_BR_EDR;
+                else
+                   other_transport = BT_TRANSPORT_LE;
+                break;
+            }
+        }
+    }
+    else
+    {
+        continue_delete_dev = TRUE;
+    }
+
+    // If it is DUMO device and device is paired as different address, unpair that device
+    // if different address
+    BOOLEAN continue_delete_other_dev = FALSE;
+    if ((other_transport && (BTM_ReadConnectedTransportAddress(other_address, other_transport))) ||
+      (!other_transport && (BTM_ReadConnectedTransportAddress(other_address, BT_TRANSPORT_BR_EDR) ||
+       BTM_ReadConnectedTransportAddress(other_address, BT_TRANSPORT_LE))))
+    {
+        continue_delete_other_dev = FALSE;
+        /* Take the link down first, and mark the device for removal when disconnected */
+        for(int i=0; i < bta_dm_cb.device_list.count; i++)
+        {
+            if (!bdcmp(bta_dm_cb.device_list.peer_device[i].peer_bdaddr, other_address))
+            {
+                bta_dm_cb.device_list.peer_device[i].conn_state = BTA_DM_UNPAIRING;
+                btm_remove_acl(other_address,bta_dm_cb.device_list.peer_device[i].transport);
+                break;
+            }
+        }
+    }
+    else
+    {
+        APPL_TRACE_DEBUG("%s: continue to delete the other dev ", __func__);
+        continue_delete_other_dev = TRUE;
+    }
+
+    /* Delete the device mentioned in the msg */
+    if (continue_delete_dev)
+        bta_dm_process_remove_device(p_dev->bd_addr);
+
+    /* Delete the other paired device too */
+    BD_ADDR dummy_bda = {0};
+    if (continue_delete_other_dev && (bdcmp(other_address, dummy_bda) != 0))
+        bta_dm_process_remove_device(other_address);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_add_device
+**
+** Description      This function adds a Link Key to an security database entry.
+**                  It is normally called during host startup to restore all required information
+**                  stored in the NVRAM.
+****
+*******************************************************************************/
+void bta_dm_add_device (tBTA_DM_MSG *p_data)
+{
+    tBTA_DM_API_ADD_DEVICE *p_dev = &p_data->add_dev;
+    UINT8   *p_dc = NULL;
+    UINT8   *p_lc = NULL;
+    UINT32  trusted_services_mask[BTM_SEC_SERVICE_ARRAY_SIZE];
+    UINT8   index = 0;
+    UINT8   btm_mask_index = 0;
+
+    memset (trusted_services_mask, 0, sizeof(trusted_services_mask));
+
+    /* If not all zeros, the device class has been specified */
+    if (p_dev->dc_known)
+        p_dc = (UINT8 *)p_dev->dc;
+
+    if (p_dev->link_key_known)
+        p_lc = (UINT8 *)p_dev->link_key;
+
+    if (p_dev->is_trusted)
+    {
+        /* covert BTA service mask to BTM mask */
+        while (p_dev->tm && (index < BTA_MAX_SERVICE_ID))
+        {
+            if (p_dev->tm & (UINT32)(1<<index))
+            {
+
+                btm_mask_index =  bta_service_id_to_btm_srv_id_lkup_tbl[index] / BTM_SEC_ARRAY_BITS;
+                trusted_services_mask[btm_mask_index] |= (UINT32)(1 << (bta_service_id_to_btm_srv_id_lkup_tbl[index] - (UINT32)(btm_mask_index * 32)));
+
+                p_dev->tm &= (UINT32)(~(1<<index));
+
+            }
+            index++;
+        }
+    }
+
+    if (!BTM_SecAddDevice (p_dev->bd_addr, p_dc, p_dev->bd_name, p_dev->features,
+                           trusted_services_mask, p_lc, p_dev->key_type, p_dev->io_cap,
+                           p_dev->pin_length))
+    {
+        APPL_TRACE_ERROR ("BTA_DM: Error adding device %08x%04x",
+                (p_dev->bd_addr[0]<<24)+(p_dev->bd_addr[1]<<16)+(p_dev->bd_addr[2]<<8)+p_dev->bd_addr[3],
+                (p_dev->bd_addr[4]<<8)+p_dev->bd_addr[5]);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_close_acl
+**
+** Description      This function forces to close the connection to a remote device
+**                  and optionaly remove the device from security database if
+**                  required.
+****
+*******************************************************************************/
+void bta_dm_close_acl(tBTA_DM_MSG *p_data)
+{
+    tBTA_DM_API_REMOVE_ACL *p_remove_acl = &p_data->remove_acl;
+    UINT8   index;
+
+    APPL_TRACE_DEBUG("bta_dm_close_acl");
+
+    if (BTM_IsAclConnectionUp(p_remove_acl->bd_addr, p_remove_acl->transport))
+    {
+        for (index = 0; index < bta_dm_cb.device_list.count; index ++)
+        {
+            if (!bdcmp( bta_dm_cb.device_list.peer_device[index].peer_bdaddr, p_remove_acl->bd_addr))
+                break;
+            }
+        if (index != bta_dm_cb.device_list.count)
+        {
+            if (p_remove_acl->remove_dev)
+                bta_dm_cb.device_list.peer_device[index].remove_dev_pending = TRUE;
+        }
+        else
+        {
+            APPL_TRACE_ERROR("unknown device, remove ACL failed");
+        }
+        /* Disconnect the ACL link */
+        btm_remove_acl(p_remove_acl->bd_addr, p_remove_acl->transport);
+    }
+    /* if to remove the device from security database ? do it now */
+    else if (p_remove_acl->remove_dev)
+    {
+        if (!BTM_SecDeleteDevice(p_remove_acl->bd_addr))
+        {
+            APPL_TRACE_ERROR("delete device from security database failed.");
+        }
+#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
+        /* need to remove all pending background connection if any */
+        BTA_GATTC_CancelOpen(0, p_remove_acl->bd_addr, FALSE);
+        /* remove all cached GATT information */
+        BTA_GATTC_Refresh(p_remove_acl->bd_addr);
+#endif
+    }
+    /* otherwise, no action needed */
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_remove_all_acl
+**
+** Description      This function forces to close all the ACL links specified by link type
+****
+*******************************************************************************/
+void bta_dm_remove_all_acl(tBTA_DM_MSG *p_data)
+{
+    const tBTA_DM_LINK_TYPE link_type = p_data->remove_all_acl.link_type;
+    tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
+
+    APPL_TRACE_DEBUG("%s link type = %d", __func__, link_type);
+
+    for (UINT8 i=0; i < bta_dm_cb.device_list.count; i++)
+    {
+        BD_ADDR addr = {0};
+        bdcpy(addr, bta_dm_cb.device_list.peer_device[i].peer_bdaddr);
+#if defined (BLE_INCLUDED) && (BLE_INCLUDED == TRUE)
+        transport = bta_dm_cb.device_list.peer_device[i].transport;
+#endif
+        if ((link_type == BTA_DM_LINK_TYPE_ALL) ||
+            ((link_type == BTA_DM_LINK_TYPE_LE) && (transport == BT_TRANSPORT_LE)) ||
+            ((link_type == BTA_DM_LINK_TYPE_BR_EDR) && (transport == BT_TRANSPORT_BR_EDR)))
+        {
+            /* Disconnect the ACL link */
+            btm_remove_acl(addr, transport);
+        }
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_bond
+**
+** Description      Bonds with peer device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_bond (tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS status;
+    tBTA_DM_SEC sec_event;
+    char        *p_name;
+
+    if (p_data->bond.transport == BTA_TRANSPORT_UNKNOWN)
+        status = BTM_SecBond ( p_data->bond.bd_addr, 0, NULL, 0 );
+    else
+        status = BTM_SecBondByTransport ( p_data->bond.bd_addr, p_data->bond.transport, 0, NULL, 0 );
+
+
+    if (bta_dm_cb.p_sec_cback && (status != BTM_CMD_STARTED))
+    {
+
+        memset(&sec_event, 0, sizeof(tBTA_DM_SEC));
+        bdcpy(sec_event.auth_cmpl.bd_addr, p_data->bond.bd_addr);
+        p_name = BTM_SecReadDevName(p_data->bond.bd_addr);
+        if (p_name != NULL)
+        {
+            memcpy(sec_event.auth_cmpl.bd_name, p_name, (BD_NAME_LEN-1));
+            sec_event.auth_cmpl.bd_name[BD_NAME_LEN-1] = 0;
+        }
+
+/*      taken care of by memset [above]
+        sec_event.auth_cmpl.key_present = FALSE;
+        sec_event.auth_cmpl.success = FALSE;
+*/
+        sec_event.auth_cmpl.fail_reason = HCI_ERR_ILLEGAL_COMMAND;
+        if (status == BTM_SUCCESS)
+        {
+            sec_event.auth_cmpl.success = TRUE;
+        }
+        else
+        {
+            /* delete this device entry from Sec Dev DB */
+            bta_dm_remove_sec_dev_entry(p_data->bond.bd_addr);
+        }
+        bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_bond_cancel
+**
+** Description      Cancels bonding with a peer device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_bond_cancel (tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS status;
+    tBTA_DM_SEC sec_event;
+
+    APPL_TRACE_EVENT(" bta_dm_bond_cancel ");
+    status = BTM_SecBondCancel ( p_data->bond_cancel.bd_addr );
+
+    if (bta_dm_cb.p_sec_cback && (status != BTM_CMD_STARTED && status != BTM_SUCCESS))
+    {
+        sec_event.bond_cancel_cmpl.result = BTA_FAILURE;
+
+        bta_dm_cb.p_sec_cback(BTA_DM_BOND_CANCEL_CMPL_EVT, &sec_event);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_pin_reply
+**
+** Description      Send the pin_reply to a request from BTM
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_pin_reply (tBTA_DM_MSG *p_data)
+{
+    UINT32  trusted_mask[BTM_SEC_SERVICE_ARRAY_SIZE];
+    UINT32  * current_trusted_mask;
+
+    current_trusted_mask = BTM_ReadTrustedMask(p_data->pin_reply.bd_addr);
+
+    if(current_trusted_mask)
+    {
+        memcpy(trusted_mask, current_trusted_mask, sizeof(trusted_mask));
+    }
+    else
+    {
+        memset(trusted_mask, 0, sizeof(trusted_mask));
+    }
+
+    if(p_data->pin_reply.accept)
+    {
+
+        BTM_PINCodeReply(p_data->pin_reply.bd_addr, BTM_SUCCESS, p_data->pin_reply.pin_len, p_data->pin_reply.p_pin, trusted_mask );
+    }
+    else
+    {
+        BTM_PINCodeReply(p_data->pin_reply.bd_addr, BTM_NOT_AUTHORIZED, 0, NULL, trusted_mask );
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_policy_cback
+**
+** Description      process the link policy changes
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_policy_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+    tBTA_DM_PEER_DEVICE *p_dev = NULL;
+    UINT16  policy = app_id;
+    UINT32  mask = (UINT32)(1 << id);
+
+    if(peer_addr)
+        p_dev = bta_dm_find_peer_device(peer_addr);
+
+    APPL_TRACE_DEBUG(" bta_dm_policy_cback cmd:%d, policy:0x%x",
+        status, policy);
+    switch(status)
+    {
+    case BTA_SYS_PLCY_SET:
+        if(!p_dev)
+            return;
+        /* restore the default link policy */
+        p_dev->link_policy |= policy;
+        BTM_SetLinkPolicy(p_dev->peer_bdaddr, &(p_dev->link_policy));
+        break;
+
+    case BTA_SYS_PLCY_CLR:
+        if(!p_dev)
+            return;
+        /* clear the policy from the default link policy */
+        p_dev->link_policy &= (~policy);
+        BTM_SetLinkPolicy(p_dev->peer_bdaddr, &(p_dev->link_policy));
+
+        if(policy & (HCI_ENABLE_SNIFF_MODE | HCI_ENABLE_PARK_MODE))
+        {
+            /* if clearing sniff/park, wake the link */
+            bta_dm_pm_active(p_dev->peer_bdaddr);
+        }
+        break;
+
+    case BTA_SYS_PLCY_DEF_SET:
+        /* want to restore/set the role switch policy */
+        bta_dm_cb.role_policy_mask &= ~mask;
+        if(0 == bta_dm_cb.role_policy_mask)
+        {
+            /* if nobody wants to insist on the role */
+            bta_dm_cb.cur_policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
+            BTM_SetDefaultLinkPolicy(bta_dm_cb.cur_policy);
+        }
+        break;
+
+    case BTA_SYS_PLCY_DEF_CLR:
+        /* want to remove the role switch policy */
+        bta_dm_cb.role_policy_mask |= mask;
+        bta_dm_cb.cur_policy &= ~HCI_ENABLE_MASTER_SLAVE_SWITCH;
+        BTM_SetDefaultLinkPolicy(bta_dm_cb.cur_policy);
+        break;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_confirm
+**
+** Description      Send the user confirm request reply in response to a
+**                  request from BTM
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_confirm(tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS res = BTM_NOT_AUTHORIZED;
+
+    if(p_data->confirm.accept == TRUE)
+        res = BTM_SUCCESS;
+    BTM_ConfirmReqReply(res, p_data->confirm.bd_addr);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_loc_oob
+**
+** Description      Retrieve the OOB data from the local LM
+**
+** Returns          void
+**
+*******************************************************************************/
+#if (BTM_OOB_INCLUDED == TRUE)
+void bta_dm_loc_oob(tBTA_DM_MSG *p_data)
+{
+    UNUSED(p_data);
+    BTM_ReadLocalOobData();
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ci_io_req_act
+**
+** Description      respond to the IO capabilities request from BTM
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_ci_io_req_act(tBTA_DM_MSG *p_data)
+{
+    tBTM_AUTH_REQ   auth_req = BTM_AUTH_AP_NO;
+    if(p_data->ci_io_req.auth_req)
+        auth_req = BTM_AUTH_AP_YES;
+    BTM_IoCapRsp(p_data->ci_io_req.bd_addr, p_data->ci_io_req.io_cap,
+        p_data->ci_io_req.oob_data, auth_req);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ci_rmt_oob_act
+**
+** Description      respond to the OOB data request for the remote device from BTM
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_ci_rmt_oob_act(tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS res = BTM_NOT_AUTHORIZED;
+
+    if(p_data->ci_rmt_oob.accept == TRUE)
+        res = BTM_SUCCESS;
+    BTM_RemoteOobDataReply(res, p_data->ci_rmt_oob.bd_addr,
+        p_data->ci_rmt_oob.c, p_data->ci_rmt_oob.r );
+}
+#endif /* BTM_OOB_INCLUDED */
+
+/*******************************************************************************
+**
+** Function         bta_dm_search_start
+**
+** Description      Starts an inquiry
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_search_start (tBTA_DM_MSG *p_data)
+{
+    tBTM_INQUIRY_CMPL result;
+
+#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
+    UINT16 len = (UINT16)(sizeof(tBT_UUID) * p_data->search.num_uuid);
+    bta_dm_gattc_register();
+#endif
+
+    APPL_TRACE_DEBUG("%s avoid_scatter=%d", __func__, p_bta_dm_cfg->avoid_scatter);
+
+    if (p_bta_dm_cfg->avoid_scatter &&
+        (p_data->search.rs_res == BTA_DM_RS_NONE) && bta_dm_check_av(BTA_DM_API_SEARCH_EVT))
+    {
+        memcpy(&bta_dm_cb.search_msg, &p_data->search, sizeof(tBTA_DM_API_SEARCH));
+        return;
+    }
+
+    BTM_ClearInqDb(NULL);
+    /* save search params */
+    bta_dm_search_cb.p_search_cback = p_data->search.p_cback;
+    bta_dm_search_cb.services = p_data->search.services;
+
+#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
+    utl_freebuf((void **)&bta_dm_search_cb.p_srvc_uuid);
+
+    if ((bta_dm_search_cb.num_uuid = p_data->search.num_uuid) != 0 &&
+         p_data->search.p_uuid != NULL)
+    {
+        if ((bta_dm_search_cb.p_srvc_uuid = (tBT_UUID *)GKI_getbuf(len)) == NULL)
+        {
+            APPL_TRACE_ERROR("%s no resources", __func__);
+
+            result.status = BTA_FAILURE;
+            result.num_resp = 0;
+            bta_dm_inq_cmpl_cb ((void *)&result);
+            return;
+        }
+
+        memcpy(bta_dm_search_cb.p_srvc_uuid, p_data->search.p_uuid, len);
+    }
+#endif
+    result.status = BTM_StartInquiry(   (tBTM_INQ_PARMS*)&p_data->search.inq_params,
+                        bta_dm_inq_results_cb,
+                        (tBTM_CMPL_CB*) bta_dm_inq_cmpl_cb);
+
+    APPL_TRACE_EVENT("%s status=%d", __func__, result.status);
+    if (result.status != BTM_CMD_STARTED)
+    {
+        result.num_resp = 0;
+        bta_dm_inq_cmpl_cb ((void *)&result);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_search_cancel
+**
+** Description      Cancels an ongoing search for devices
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_search_cancel (tBTA_DM_MSG *p_data)
+{
+    UNUSED(p_data);
+    tBTA_DM_MSG * p_msg;
+
+    if (BTM_IsInquiryActive())
+    {
+        if (BTM_CancelInquiry() != BTM_CMD_STARTED)
+        {
+            bta_dm_search_cancel_notify(NULL);
+            p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG));
+            if (p_msg != NULL)
+            {
+                p_msg->hdr.event = BTA_DM_SEARCH_CMPL_EVT;
+                p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;
+                bta_sys_sendmsg(p_msg);
+            }
+        } else {
+            /* flag a search cancel is pending */
+            bta_dm_search_cb.cancel_pending = TRUE;
+        }
+    }
+    /* If no Service Search going on then issue cancel remote name in case it is active */
+    else if (!bta_dm_search_cb.name_discover_done)
+    {
+        BTM_CancelRemoteDeviceName();
+
+        if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+        {
+            p_msg->hdr.event = BTA_DM_SEARCH_CMPL_EVT;
+            p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;
+            bta_sys_sendmsg(p_msg);
+        }
+
+    }
+    else {
+        if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+        {
+            p_msg->hdr.event = BTA_DM_INQUIRY_CMPL_EVT;
+            p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;
+            bta_sys_sendmsg(p_msg);
+        }
+    }
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    if (bta_dm_search_cb.gatt_disc_active)
+    {
+        bta_dm_cancel_gatt_discovery(bta_dm_search_cb.peer_bdaddr);
+    }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_discover
+**
+** Description      Discovers services on a remote device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_discover (tBTA_DM_MSG *p_data)
+{
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    UINT16 len = (UINT16)(sizeof(tBT_UUID) * p_data->discover.num_uuid);
+#endif
+    APPL_TRACE_EVENT("%s services_to_search=0x%04X, sdp_search=%d", __func__,
+                      p_data->discover.services, p_data->discover.sdp_search);
+
+    /* save the search condition */
+    bta_dm_search_cb.services = p_data->discover.services;
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    bta_dm_gattc_register();
+    utl_freebuf((void **)&bta_dm_search_cb.p_srvc_uuid);
+    if ((bta_dm_search_cb.num_uuid = p_data->discover.num_uuid) != 0 &&
+        p_data->discover.p_uuid != NULL)
+    {
+        if ((bta_dm_search_cb.p_srvc_uuid = (tBT_UUID *)GKI_getbuf(len)) == NULL)
+        {
+            p_data->discover.p_cback(BTA_DM_DISC_CMPL_EVT, NULL);
+            return;
+        }
+        memcpy(bta_dm_search_cb.p_srvc_uuid, p_data->discover.p_uuid, len);
+    }
+    bta_dm_search_cb.uuid_to_search = bta_dm_search_cb.num_uuid;
+#endif
+
+    bta_dm_search_cb.p_search_cback = p_data->discover.p_cback;
+    bta_dm_search_cb.sdp_search = p_data->discover.sdp_search;
+    bta_dm_search_cb.services_to_search = bta_dm_search_cb.services;
+    bta_dm_search_cb.service_index = 0;
+    bta_dm_search_cb.services_found = 0;
+    bta_dm_search_cb.peer_name[0] = 0;
+    bta_dm_search_cb.sdp_search = p_data->discover.sdp_search;
+    bta_dm_search_cb.p_btm_inq_info = BTM_InqDbRead (p_data->discover.bd_addr);
+    bta_dm_search_cb.transport = p_data->discover.transport;
+
+    bta_dm_search_cb.name_discover_done = FALSE;
+    memcpy(&bta_dm_search_cb.uuid, &p_data->discover.uuid, sizeof(tSDP_UUID));
+    bta_dm_discover_device(p_data->discover.bd_addr);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_di_disc_cmpl
+**
+** Description      Sends event to application when DI discovery complete
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_di_disc_cmpl(tBTA_DM_MSG *p_data)
+{
+    tBTA_DM_DI_DISC_CMPL    di_disc;
+
+    memset(&di_disc, 0, sizeof(tBTA_DM_DI_DISC_CMPL));
+    bdcpy(di_disc.bd_addr, bta_dm_search_cb.peer_bdaddr);
+
+    if((p_data->hdr.offset == SDP_SUCCESS)
+        || (p_data->hdr.offset == SDP_DB_FULL))
+    {
+        di_disc.num_record  = SDP_GetNumDiRecords(bta_dm_di_cb.p_di_db);
+    }
+    else
+        di_disc.result      = BTA_FAILURE;
+
+    bta_dm_di_cb.p_di_db = NULL;
+    bta_dm_search_cb.p_search_cback(BTA_DM_DI_DISC_CMPL_EVT, (tBTA_DM_SEARCH *) &di_disc);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_di_disc_callback
+**
+** Description      This function queries a remote device for DI information.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_di_disc_callback(UINT16 result)
+{
+    tBTA_DM_MSG * p_msg;
+
+    if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+    {
+        p_msg->hdr.event            = BTA_DM_SEARCH_CMPL_EVT;
+        p_msg->hdr.layer_specific   = BTA_DM_API_DI_DISCOVER_EVT;
+        p_msg->hdr.offset           = result;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_disable_search_and_disc
+**
+** Description      Cancels an ongoing search or discovery for devices in case of
+**                  a Bluetooth disable
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_disable_search_and_disc (void)
+{
+    tBTA_DM_DI_DISC_CMPL    di_disc;
+
+    if (bta_dm_search_cb.state != BTA_DM_SEARCH_IDLE)
+        bta_dm_search_cancel(NULL);
+
+    if (bta_dm_di_cb.p_di_db != NULL)
+    {
+        memset(&di_disc, 0, sizeof(tBTA_DM_DI_DISC_CMPL));
+        bdcpy(di_disc.bd_addr, bta_dm_search_cb.peer_bdaddr);
+        di_disc.result      = BTA_FAILURE;
+
+        bta_dm_di_cb.p_di_db = NULL;
+        bta_dm_search_cb.p_search_cback(BTA_DM_DI_DISC_CMPL_EVT, NULL);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_di_disc
+**
+** Description      This function queries a remote device for DI information.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_di_disc (tBTA_DM_MSG *p_data)
+{
+    UINT16  result = BTA_FAILURE;
+    tBTA_DM_MSG *p_msg;
+
+    bta_dm_search_cb.p_search_cback = p_data->di_disc.p_cback;
+    bdcpy(bta_dm_search_cb.peer_bdaddr, p_data->di_disc.bd_addr);
+    bta_dm_di_cb.p_di_db = p_data->di_disc.p_sdp_db;
+
+    if((bta_dm_search_cb.p_sdp_db = (tSDP_DISCOVERY_DB *)GKI_getbuf(BTA_DM_SDP_DB_SIZE)) != NULL)
+    {
+        if ( SDP_DiDiscover(bta_dm_search_cb.peer_bdaddr, p_data->di_disc.p_sdp_db,
+                    p_data->di_disc.len, bta_dm_di_disc_callback) == SDP_SUCCESS)
+        {
+            result = BTA_SUCCESS;
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR("No buffer to start DI discovery");
+    }
+
+    if ( result == BTA_FAILURE &&
+        (p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+    {
+        p_msg->hdr.event            = BTA_DM_SEARCH_CMPL_EVT;
+        p_msg->hdr.layer_specific   = BTA_DM_API_DI_DISCOVER_EVT;
+        p_data->hdr.offset          = result;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_read_remote_device_name
+**
+** Description      Initiate to get remote device name
+**
+** Returns          TRUE if started to get remote name
+**
+*******************************************************************************/
+static BOOLEAN bta_dm_read_remote_device_name (BD_ADDR bd_addr,tBT_TRANSPORT transport)
+{
+    tBTM_STATUS  btm_status;
+
+    APPL_TRACE_DEBUG("bta_dm_read_remote_device_name");
+
+    bdcpy(bta_dm_search_cb.peer_bdaddr, bd_addr);
+    bta_dm_search_cb.peer_name[0] = 0;
+
+    btm_status = BTM_ReadRemoteDeviceName (bta_dm_search_cb.peer_bdaddr,
+                                           (tBTM_CMPL_CB *) bta_dm_remname_cback,
+                                           transport);
+
+    if ( btm_status == BTM_CMD_STARTED )
+    {
+        APPL_TRACE_DEBUG("bta_dm_read_remote_device_name: BTM_ReadRemoteDeviceName is started");
+
+        return (TRUE);
+    }
+    else if ( btm_status == BTM_BUSY )
+    {
+        APPL_TRACE_DEBUG("bta_dm_read_remote_device_name: BTM_ReadRemoteDeviceName is busy");
+
+        /* Remote name discovery is on going now so BTM cannot notify through "bta_dm_remname_cback" */
+        /* adding callback to get notified that current reading remore name done */
+        BTM_SecAddRmtNameNotifyCallback(&bta_dm_service_search_remname_cback);
+
+        return (TRUE);
+    }
+    else
+    {
+        APPL_TRACE_WARNING("bta_dm_read_remote_device_name: BTM_ReadRemoteDeviceName returns 0x%02X", btm_status);
+
+        return (FALSE);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_inq_cmpl
+**
+** Description      Process the inquiry complete event from BTM
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_inq_cmpl (tBTA_DM_MSG *p_data)
+{
+    tBTA_DM_MSG * p_msg;
+    tBTA_DM_SEARCH  data;
+
+    APPL_TRACE_DEBUG("bta_dm_inq_cmpl");
+
+    data.inq_cmpl.num_resps = p_data->inq_cmpl.num;
+    bta_dm_search_cb.p_search_cback(BTA_DM_INQ_CMPL_EVT, &data);
+
+    if((bta_dm_search_cb.p_btm_inq_info = BTM_InqDbFirst()) != NULL)
+    {
+        /* start name and service discovery from the first device on inquiry result */
+        bta_dm_search_cb.name_discover_done = FALSE;
+        bta_dm_search_cb.peer_name[0]       = 0;
+        bta_dm_discover_device(bta_dm_search_cb.p_btm_inq_info->results.remote_bd_addr);
+    }
+    else
+    {
+        /* no devices, search complete */
+        bta_dm_search_cb.services = 0;
+
+        if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+        {
+            p_msg->hdr.event          = BTA_DM_SEARCH_CMPL_EVT;
+            p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;
+            bta_sys_sendmsg(p_msg);
+        }
+        }
+    }
+
+/*******************************************************************************
+**
+** Function         bta_dm_rmt_name
+**
+** Description      Process the remote name result from BTM
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_rmt_name (tBTA_DM_MSG *p_data)
+{
+    APPL_TRACE_DEBUG("bta_dm_rmt_name");
+
+    if( p_data->rem_name.result.disc_res.bd_name[0] && bta_dm_search_cb.p_btm_inq_info)
+    {
+        bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name = TRUE;
+    }
+
+    bta_dm_discover_device(bta_dm_search_cb.peer_bdaddr);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_disc_rmt_name
+**
+** Description      Process the remote name result from BTM when application
+**                  wants to find the name for a bdaddr
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_disc_rmt_name (tBTA_DM_MSG *p_data)
+{
+    tBTM_INQ_INFO *p_btm_inq_info;
+
+    APPL_TRACE_DEBUG("bta_dm_disc_rmt_name");
+
+    p_btm_inq_info = BTM_InqDbRead (p_data->rem_name.result.disc_res.bd_addr);
+    if( p_btm_inq_info )
+    {
+        if( p_data->rem_name.result.disc_res.bd_name[0] )
+        {
+            p_btm_inq_info->appl_knows_rem_name = TRUE;
+        }
+    }
+
+    bta_dm_discover_device(p_data->rem_name.result.disc_res.bd_addr);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_sdp_result
+**
+** Description      Process the discovery result from sdp
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_sdp_result (tBTA_DM_MSG *p_data)
+{
+
+    tSDP_DISC_REC   *p_sdp_rec = NULL;
+    tBTA_DM_MSG     *p_msg;
+    BOOLEAN          scn_found = FALSE;
+    UINT16           service = 0xFFFF;
+    tSDP_PROTOCOL_ELEM  pe;
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    tBT_UUID           *p_uuid = bta_dm_search_cb.p_srvc_uuid;
+    tBTA_DM_SEARCH      result;
+    tBT_UUID            service_uuid;
+#endif
+
+    UINT32 num_uuids = 0;
+    UINT8  uuid_list[32][MAX_UUID_SIZE]; // assuming a max of 32 services
+
+    if((p_data->sdp_event.sdp_result == SDP_SUCCESS)
+        || (p_data->sdp_event.sdp_result == SDP_NO_RECS_MATCH)
+        || (p_data->sdp_event.sdp_result == SDP_DB_FULL))
+    {
+        APPL_TRACE_DEBUG("sdp_result::0x%x", p_data->sdp_event.sdp_result);
+        do
+        {
+
+            p_sdp_rec = NULL;
+            if( bta_dm_search_cb.service_index == (BTA_USER_SERVICE_ID+1) )
+            {
+                p_sdp_rec = SDP_FindServiceUUIDInDb(bta_dm_search_cb.p_sdp_db, &bta_dm_search_cb.uuid, p_sdp_rec);
+
+                if (p_sdp_rec && SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_RFCOMM, &pe))
+                {
+                    bta_dm_search_cb.peer_scn = (UINT8) pe.params[0];
+                    scn_found = TRUE;
+                }
+            }
+            else
+            {
+                service = bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index-1];
+                p_sdp_rec = SDP_FindServiceInDb(bta_dm_search_cb.p_sdp_db, service, p_sdp_rec);
+            }
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+            /* finished with BR/EDR services, now we check the result for GATT based service UUID */
+            if (bta_dm_search_cb.service_index == BTA_MAX_SERVICE_ID)
+            {
+                if (bta_dm_search_cb.uuid_to_search != 0 && p_uuid != NULL)
+                {
+                    p_uuid +=  (bta_dm_search_cb.num_uuid - bta_dm_search_cb.uuid_to_search);
+                    /* only support 16 bits UUID for now */
+                    service = p_uuid->uu.uuid16;
+
+                }
+                /* all GATT based services */
+                do
+                {
+                    /* find a service record, report it */
+                    p_sdp_rec = SDP_FindServiceInDb(bta_dm_search_cb.p_sdp_db,
+                                                0, p_sdp_rec);
+                    if (p_sdp_rec)
+                    {
+                        if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid))
+                        {
+                            /* send result back to app now, one by one */
+                            bdcpy (result.disc_ble_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+                            BCM_STRNCPY_S((char*)result.disc_ble_res.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN));
+                            result.disc_ble_res.bd_name[BD_NAME_LEN] = 0;
+                            result.disc_ble_res.service.len = service_uuid.len;
+                            result.disc_ble_res.service.uu.uuid16 = service_uuid.uu.uuid16;
+
+                            bta_dm_search_cb.p_search_cback(BTA_DM_DISC_BLE_RES_EVT, &result);
+                        }
+                    }
+
+                    if (bta_dm_search_cb.uuid_to_search > 0)
+                        break;
+
+                } while (p_sdp_rec);
+            }
+            else
+#endif
+            {
+                /* SDP_DB_FULL means some records with the
+                   required attributes were received */
+                if (((p_data->sdp_event.sdp_result == SDP_DB_FULL) &&
+                        bta_dm_search_cb.services != BTA_ALL_SERVICE_MASK) ||
+                        (p_sdp_rec != NULL))
+                {
+                    if (service != UUID_SERVCLASS_PNP_INFORMATION)
+                    {
+                        UINT16 tmp_svc = 0xFFFF;
+                        bta_dm_search_cb.services_found |=
+                            (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(bta_dm_search_cb.service_index-1));
+                        tmp_svc = bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index-1];
+                        /* Add to the list of UUIDs */
+                        sdpu_uuid16_to_uuid128(tmp_svc, uuid_list[num_uuids]);
+                        num_uuids++;
+                    }
+                }
+            }
+
+            if(bta_dm_search_cb.services == BTA_ALL_SERVICE_MASK &&
+                bta_dm_search_cb.services_to_search == 0)
+            {
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+                if ( bta_dm_search_cb.service_index == BTA_BLE_SERVICE_ID &&
+                    bta_dm_search_cb.uuid_to_search > 0)
+                    bta_dm_search_cb.uuid_to_search --;
+
+                if (bta_dm_search_cb.uuid_to_search == 0 ||
+                    bta_dm_search_cb.service_index != BTA_BLE_SERVICE_ID)
+#endif
+                    bta_dm_search_cb.service_index++;
+            }
+            else /* regular one service per search or PNP search */
+                break;
+
+        }
+        while(bta_dm_search_cb.service_index <= BTA_MAX_SERVICE_ID);
+
+//        GKI_freebuf(bta_dm_search_cb.p_sdp_db);
+//        bta_dm_search_cb.p_sdp_db = NULL;
+        APPL_TRACE_DEBUG("%s services_found = %04x", __FUNCTION__,
+                         bta_dm_search_cb.services_found);
+
+        /* Collect the 128-bit services here and put them into the list */
+        if(bta_dm_search_cb.services == BTA_ALL_SERVICE_MASK)
+        {
+            p_sdp_rec = NULL;
+            do
+            {
+                tBT_UUID temp_uuid;
+                /* find a service record, report it */
+                p_sdp_rec = SDP_FindServiceInDb_128bit(bta_dm_search_cb.p_sdp_db, p_sdp_rec);
+                if (p_sdp_rec)
+                {
+                    if (SDP_FindServiceUUIDInRec_128bit(p_sdp_rec, &temp_uuid))
+                    {
+                        memcpy(uuid_list[num_uuids], temp_uuid.uu.uuid128, MAX_UUID_SIZE);
+                        num_uuids++;
+                    }
+                }
+            } while (p_sdp_rec);
+        }
+        /* if there are more services to search for */
+        if(bta_dm_search_cb.services_to_search)
+        {
+            /* Free up the p_sdp_db before checking the next one */
+            bta_dm_free_sdp_db(NULL);
+            bta_dm_find_services(bta_dm_search_cb.peer_bdaddr);
+        }
+        else
+        {
+            /* callbacks */
+            /* start next bd_addr if necessary */
+
+            BTM_SecDeleteRmtNameNotifyCallback(&bta_dm_service_search_remname_cback);
+
+
+            if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+            {
+                p_msg->hdr.event = BTA_DM_DISCOVERY_RESULT_EVT;
+                p_msg->disc_result.result.disc_res.result = BTA_SUCCESS;
+                p_msg->disc_result.result.disc_res.p_raw_data = NULL;
+                p_msg->disc_result.result.disc_res.raw_data_size = 0;
+                p_msg->disc_result.result.disc_res.num_uuids = num_uuids;
+                p_msg->disc_result.result.disc_res.p_uuid_list = NULL;
+                if (num_uuids > 0) {
+                    p_msg->disc_result.result.disc_res.p_uuid_list = (UINT8*)GKI_getbuf(num_uuids*MAX_UUID_SIZE);
+                    if (p_msg->disc_result.result.disc_res.p_uuid_list) {
+                        memcpy(p_msg->disc_result.result.disc_res.p_uuid_list, uuid_list,
+                               num_uuids*MAX_UUID_SIZE);
+                    } else {
+                       p_msg->disc_result.result.disc_res.num_uuids = 0;
+                       APPL_TRACE_ERROR("%s: Unable to allocate memory for uuid_list", __func__);
+                    }
+                }
+                //copy the raw_data to the discovery result  structure
+                //
+
+                if (  bta_dm_search_cb.p_sdp_db != NULL && bta_dm_search_cb.p_sdp_db->raw_used != 0   &&
+                    bta_dm_search_cb.p_sdp_db->raw_data != NULL) {
+                    APPL_TRACE_DEBUG(
+                        "%s raw_data used = 0x%x raw_data_ptr = 0x%x", __func__,
+                        bta_dm_search_cb.p_sdp_db->raw_used,
+                        bta_dm_search_cb.p_sdp_db->raw_data);
+
+                    p_msg->disc_result.result.disc_res.p_raw_data = GKI_getbuf(bta_dm_search_cb.p_sdp_db->raw_used);
+                    if ( NULL != p_msg->disc_result.result.disc_res.p_raw_data  ) {
+                        memcpy(     p_msg->disc_result.result.disc_res.p_raw_data,
+                                    bta_dm_search_cb.p_sdp_db->raw_data,
+                                    bta_dm_search_cb.p_sdp_db->raw_used );
+
+                        p_msg->disc_result.result.disc_res.raw_data_size =
+                            bta_dm_search_cb.p_sdp_db->raw_used;
+
+                    } else {
+                        APPL_TRACE_DEBUG("%s GKI Alloc failed to allocate %d bytes !!", __func__,
+                            bta_dm_search_cb.p_sdp_db->raw_used);
+                    }
+
+                    bta_dm_search_cb.p_sdp_db->raw_data = NULL;     //no need to free this - it is a global assigned.
+                    bta_dm_search_cb.p_sdp_db->raw_used = 0;
+                    bta_dm_search_cb.p_sdp_db->raw_size = 0;
+                }
+                else {
+                    APPL_TRACE_DEBUG("%s raw data size is 0 or raw_data is null!!", __func__);
+                }
+                /* Done with p_sdp_db. Free it */
+                bta_dm_free_sdp_db(NULL);
+                p_msg->disc_result.result.disc_res.services = bta_dm_search_cb.services_found;
+
+                //Piggy back the SCN over result field
+                if( scn_found )
+                {
+                  p_msg->disc_result.result.disc_res.result = (3 + bta_dm_search_cb.peer_scn);
+                  p_msg->disc_result.result.disc_res.services |= BTA_USER_SERVICE_MASK;
+
+                  APPL_TRACE_EVENT(" Piggy back the SCN over result field  SCN=%d", bta_dm_search_cb.peer_scn);
+
+                }
+                bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+                BCM_STRNCPY_S((char*)p_msg->disc_result.result.disc_res.bd_name, sizeof(BD_NAME),
+                        bta_dm_get_remname(), (BD_NAME_LEN-1));
+
+                /* make sure the string is null terminated */
+                p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN-1] = 0;
+
+                bta_sys_sendmsg(p_msg);
+            }
+        }
+    } else {
+        /* conn failed. No need for timer */
+        if(p_data->sdp_event.sdp_result == SDP_CONN_FAILED || p_data->sdp_event.sdp_result == SDP_CONN_REJECTED
+           || p_data->sdp_event.sdp_result == SDP_SECURITY_ERR)
+            bta_dm_search_cb.wait_disc = FALSE;
+
+        /* not able to connect go to next device */
+        GKI_freebuf(bta_dm_search_cb.p_sdp_db);
+        bta_dm_search_cb.p_sdp_db = NULL;
+
+        BTM_SecDeleteRmtNameNotifyCallback(&bta_dm_service_search_remname_cback);
+
+        if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+        {
+            p_msg->hdr.event = BTA_DM_DISCOVERY_RESULT_EVT;
+            p_msg->disc_result.result.disc_res.result = BTA_FAILURE;
+            p_msg->disc_result.result.disc_res.services = bta_dm_search_cb.services_found;
+            bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+            BCM_STRNCPY_S((char*)p_msg->disc_result.result.disc_res.bd_name, sizeof(BD_NAME),
+                    bta_dm_get_remname(), (BD_NAME_LEN-1));
+
+            /* make sure the string is null terminated */
+            p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN-1] = 0;
+
+            bta_sys_sendmsg(p_msg);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_search_cmpl
+**
+** Description      Sends event to application
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_search_cmpl (tBTA_DM_MSG *p_data)
+{
+    APPL_TRACE_EVENT("%s", __func__);
+
+#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
+    utl_freebuf((void **)&bta_dm_search_cb.p_srvc_uuid);
+#endif
+
+    if (p_data->hdr.layer_specific == BTA_DM_API_DI_DISCOVER_EVT)
+        bta_dm_di_disc_cmpl(p_data);
+    else
+        bta_dm_search_cb.p_search_cback(BTA_DM_DISC_CMPL_EVT, NULL);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_disc_result
+**
+** Description      Service discovery result when discovering services on a device
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_disc_result (tBTA_DM_MSG *p_data)
+{
+    APPL_TRACE_EVENT("%s", __func__);
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    /* if any BR/EDR service discovery has been done, report the event */
+    if ((bta_dm_search_cb.services & ((BTA_ALL_SERVICE_MASK | BTA_USER_SERVICE_MASK ) & ~BTA_BLE_SERVICE_MASK)))
+#endif
+    bta_dm_search_cb.p_search_cback(BTA_DM_DISC_RES_EVT, &p_data->disc_result.result);
+
+    tBTA_DM_MSG *p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG));
+
+    /* send a message to change state */
+    if (p_msg != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_SEARCH_CMPL_EVT;
+        p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_search_result
+**
+** Description      Service discovery result while searching for devices
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_search_result (tBTA_DM_MSG *p_data)
+{
+    APPL_TRACE_DEBUG("%s searching:0x%04x, result:0x%04x", __func__,
+                       bta_dm_search_cb.services,
+                       p_data->disc_result.result.disc_res.services);
+
+    /* call back if application wants name discovery or found services that application is searching */
+    if (( !bta_dm_search_cb.services )
+      ||(( bta_dm_search_cb.services ) && ( p_data->disc_result.result.disc_res.services )))
+    {
+        bta_dm_search_cb.p_search_cback(BTA_DM_DISC_RES_EVT, &p_data->disc_result.result);
+    }
+
+    /* if searching did not initiate to create link */
+    if(!bta_dm_search_cb.wait_disc )
+    {
+        /* if service searching is done with EIR, don't search next device */
+        if( bta_dm_search_cb.p_btm_inq_info )
+        bta_dm_discover_next_device();
+    }
+    else
+    {
+        /* wait until link is disconnected or timeout */
+        bta_dm_search_cb.sdp_results = TRUE;
+        bta_dm_search_cb.search_timer.p_cback = (TIMER_CBACK*)&bta_dm_search_timer_cback;
+        bta_sys_start_timer(&bta_dm_search_cb.search_timer, 0, 1000*(L2CAP_LINK_INACTIVITY_TOUT+1) );
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_search_timer_cback
+**
+** Description      Called when ACL disconnect time is over
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_search_timer_cback (TIMER_LIST_ENT *p_tle)
+{
+    UNUSED(p_tle);
+
+    APPL_TRACE_EVENT("%s", __func__);
+    bta_dm_search_cb.wait_disc = FALSE;
+
+    /* proceed with next device */
+    bta_dm_discover_next_device();
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_free_sdp_db
+**
+** Description      Frees SDP data base
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_free_sdp_db (tBTA_DM_MSG *p_data)
+{
+    UNUSED(p_data);
+    if(bta_dm_search_cb.p_sdp_db)
+    {
+        GKI_freebuf(bta_dm_search_cb.p_sdp_db);
+        bta_dm_search_cb.p_sdp_db = NULL;
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_queue_search
+**
+** Description      Queues search command while search is being cancelled
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_queue_search (tBTA_DM_MSG *p_data)
+{
+    if(bta_dm_search_cb.p_search_queue)
+    {
+        GKI_freebuf(bta_dm_search_cb.p_search_queue);
+    }
+
+    bta_dm_search_cb.p_search_queue = (tBTA_DM_MSG *)GKI_getbuf(sizeof(tBTA_DM_API_SEARCH));
+    memcpy(bta_dm_search_cb.p_search_queue, p_data, sizeof(tBTA_DM_API_SEARCH));
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_queue_disc
+**
+** Description      Queues discovery command while search is being cancelled
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_queue_disc (tBTA_DM_MSG *p_data)
+{
+    if(bta_dm_search_cb.p_search_queue)
+    {
+        GKI_freebuf(bta_dm_search_cb.p_search_queue);
+    }
+
+    bta_dm_search_cb.p_search_queue = (tBTA_DM_MSG *)GKI_getbuf(sizeof(tBTA_DM_API_DISCOVER));
+    memcpy(bta_dm_search_cb.p_search_queue, p_data, sizeof(tBTA_DM_API_DISCOVER));
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_search_clear_queue
+**
+** Description      Clears the queue if API search cancel is called
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_search_clear_queue (tBTA_DM_MSG *p_data)
+{
+    UNUSED(p_data);
+    if(bta_dm_search_cb.p_search_queue)
+    {
+        GKI_freebuf(bta_dm_search_cb.p_search_queue);
+        bta_dm_search_cb.p_search_queue = NULL;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_search_cancel_cmpl
+**
+** Description      Search cancel is complete
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_search_cancel_cmpl (tBTA_DM_MSG *p_data)
+{
+    UNUSED(p_data);
+    if(bta_dm_search_cb.p_search_queue)
+    {
+        bta_sys_sendmsg(bta_dm_search_cb.p_search_queue);
+        bta_dm_search_cb.p_search_queue = NULL;
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_search_cancel_transac_cmpl
+**
+** Description      Current Service Discovery or remote name procedure is
+**                  completed after search cancellation
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_search_cancel_transac_cmpl(tBTA_DM_MSG *p_data)
+{
+    UNUSED(p_data);
+    if(bta_dm_search_cb.p_sdp_db)
+    {
+        GKI_freebuf(bta_dm_search_cb.p_sdp_db);
+        bta_dm_search_cb.p_sdp_db = NULL;
+    }
+
+    bta_dm_search_cancel_notify(NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_search_cancel_notify
+**
+** Description      Notify application that search has been cancelled
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_search_cancel_notify (tBTA_DM_MSG *p_data)
+{
+    UNUSED(p_data);
+    if (bta_dm_search_cb.p_search_cback)
+    {
+        bta_dm_search_cb.p_search_cback(BTA_DM_SEARCH_CANCEL_CMPL_EVT, NULL);
+    }
+    if (!bta_dm_search_cb.name_discover_done)
+    {
+        BTM_CancelRemoteDeviceName();
+    }
+#if (BLE_INCLUDED == TRUE) && (BTA_GATT_INCLUDED == TRUE)
+    if (bta_dm_search_cb.gatt_disc_active)
+    {
+        bta_dm_cancel_gatt_discovery(bta_dm_search_cb.peer_bdaddr);
+    }
+#endif
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_find_services
+**
+** Description      Starts discovery on a device
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_find_services ( BD_ADDR bd_addr)
+{
+
+    tSDP_UUID    uuid;
+    UINT16       num_attrs = 1;
+    tBTA_DM_MSG *p_msg;
+
+    memset (&uuid, 0, sizeof(tSDP_UUID));
+
+    while(bta_dm_search_cb.service_index < BTA_MAX_SERVICE_ID)
+    {
+        if( bta_dm_search_cb.services_to_search
+            & (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(bta_dm_search_cb.service_index)))
+        {
+            if((bta_dm_search_cb.p_sdp_db = (tSDP_DISCOVERY_DB *)GKI_getbuf(BTA_DM_SDP_DB_SIZE)) != NULL)
+            {
+                APPL_TRACE_DEBUG("bta_dm_search_cb.services = %04x***********", bta_dm_search_cb.services);
+                /* try to search all services by search based on L2CAP UUID */
+                if(bta_dm_search_cb.services == BTA_ALL_SERVICE_MASK )
+                {
+                    LOG_INFO("%s services_to_search=%08x", __func__, bta_dm_search_cb.services_to_search);
+                    if (bta_dm_search_cb.services_to_search & BTA_RES_SERVICE_MASK)
+                    {
+                        uuid.uu.uuid16 = bta_service_id_to_uuid_lkup_tbl[0];
+                        bta_dm_search_cb.services_to_search &= ~BTA_RES_SERVICE_MASK;
+                    }
+                    else
+                    {
+                        uuid.uu.uuid16 = UUID_PROTOCOL_L2CAP;
+                        bta_dm_search_cb.services_to_search = 0;
+                    }
+                }
+                else
+                {
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+                    /* for LE only profile */
+                    if (bta_dm_search_cb.service_index == BTA_BLE_SERVICE_ID)
+                    {
+                        if (bta_dm_search_cb.uuid_to_search > 0 && bta_dm_search_cb.p_srvc_uuid)
+                        {
+                            memcpy(&uuid,
+                                   (const void *)(bta_dm_search_cb.p_srvc_uuid + \
+                                                  bta_dm_search_cb.num_uuid - bta_dm_search_cb.uuid_to_search),
+                                   sizeof(tBT_UUID));
+
+                            bta_dm_search_cb.uuid_to_search -- ;
+                        }
+                        else
+                            uuid.uu.uuid16 = bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index];
+
+                        /* last one? clear the BLE service bit if all discovery has been done */
+                        if (bta_dm_search_cb.uuid_to_search == 0)
+                            bta_dm_search_cb.services_to_search &=
+                            (tBTA_SERVICE_MASK)(~(BTA_SERVICE_ID_TO_SERVICE_MASK(bta_dm_search_cb.service_index)));
+
+                    }
+                    else
+#endif
+                    {
+                        /* remove the service from services to be searched  */
+                        bta_dm_search_cb.services_to_search &=
+                        (tBTA_SERVICE_MASK)(~(BTA_SERVICE_ID_TO_SERVICE_MASK(bta_dm_search_cb.service_index)));
+                        uuid.uu.uuid16 = bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index];
+                    }
+                }
+
+                if (uuid.len == 0)
+                    uuid.len = LEN_UUID_16;
+
+                if (bta_dm_search_cb.service_index == BTA_USER_SERVICE_ID)
+                {
+                    memcpy(&uuid, &bta_dm_search_cb.uuid, sizeof(tSDP_UUID));
+                }
+
+                LOG_INFO("%s search UUID = %04x", __func__, uuid.uu.uuid16);
+                SDP_InitDiscoveryDb (bta_dm_search_cb.p_sdp_db, BTA_DM_SDP_DB_SIZE, 1, &uuid, 0, NULL);
+
+                memset(g_disc_raw_data_buf, 0, sizeof(g_disc_raw_data_buf));
+                bta_dm_search_cb.p_sdp_db->raw_data = g_disc_raw_data_buf;
+
+                bta_dm_search_cb.p_sdp_db->raw_size = MAX_DISC_RAW_DATA_BUF;
+
+                if (!SDP_ServiceSearchAttributeRequest (bd_addr, bta_dm_search_cb.p_sdp_db, &bta_dm_sdp_callback))
+                {
+                    /* if discovery not successful with this device
+                    proceed to next one */
+                    GKI_freebuf(bta_dm_search_cb.p_sdp_db);
+                    bta_dm_search_cb.p_sdp_db = NULL;
+                    bta_dm_search_cb.service_index = BTA_MAX_SERVICE_ID;
+
+                }
+                else
+                {
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+                    if ((bta_dm_search_cb.service_index == BTA_BLE_SERVICE_ID &&
+                         bta_dm_search_cb.uuid_to_search == 0) ||
+                         bta_dm_search_cb.service_index != BTA_BLE_SERVICE_ID)
+#endif
+                    bta_dm_search_cb.service_index++;
+                    return;
+                }
+            }
+            else
+            {
+                APPL_TRACE_ERROR("#### Failed to allocate SDP DB buffer! ####");
+            }
+        }
+
+        bta_dm_search_cb.service_index++;
+    }
+
+    /* no more services to be discovered */
+    if(bta_dm_search_cb.service_index >= BTA_MAX_SERVICE_ID)
+    {
+        if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+        {
+            p_msg->hdr.event = BTA_DM_DISCOVERY_RESULT_EVT;
+            p_msg->disc_result.result.disc_res.services = bta_dm_search_cb.services_found;
+            bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+            BCM_STRNCPY_S((char*)p_msg->disc_result.result.disc_res.bd_name, sizeof(BD_NAME),
+                    bta_dm_get_remname(), (BD_NAME_LEN-1));
+
+            /* make sure the string is terminated */
+            p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN-1] = 0;
+
+            bta_sys_sendmsg(p_msg);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_discover_next_device
+**
+** Description      Starts discovery on the next device in Inquiry data base
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_discover_next_device(void)
+{
+
+    tBTA_DM_MSG * p_msg;
+
+    APPL_TRACE_DEBUG("bta_dm_discover_next_device");
+
+    /* searching next device on inquiry result */
+    if((bta_dm_search_cb.p_btm_inq_info = BTM_InqDbNext(bta_dm_search_cb.p_btm_inq_info)) != NULL)
+    {
+        bta_dm_search_cb.name_discover_done = FALSE;
+        bta_dm_search_cb.peer_name[0]       = 0;
+        bta_dm_discover_device(bta_dm_search_cb.p_btm_inq_info->results.remote_bd_addr);
+    }
+    else
+    {
+        /* no devices, search complete */
+        bta_dm_search_cb.services = 0;
+
+        if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+        {
+            p_msg->hdr.event          = BTA_DM_SEARCH_CMPL_EVT;
+            p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;
+            bta_sys_sendmsg(p_msg);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_discover_device
+**
+** Description      Starts name and service discovery on the device
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_discover_device(BD_ADDR remote_bd_addr)
+{
+    tBTA_DM_MSG * p_msg;
+    tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
+
+#if BLE_INCLUDED == TRUE
+    if (bta_dm_search_cb.transport == BTA_TRANSPORT_UNKNOWN)
+    {
+        tBT_DEVICE_TYPE dev_type;
+        tBLE_ADDR_TYPE  addr_type;
+
+        BTM_ReadDevInfo(remote_bd_addr, &dev_type, &addr_type);
+        if (dev_type == BT_DEVICE_TYPE_BLE || addr_type == BLE_ADDR_RANDOM)
+            transport = BT_TRANSPORT_LE;
+    } else {
+        transport = bta_dm_search_cb.transport;
+    }
+#endif
+
+    /* Reset transport state for next discovery */
+    bta_dm_search_cb.transport = BTA_TRANSPORT_UNKNOWN;
+
+    APPL_TRACE_DEBUG("%s BDA:0x%02X%02X%02X%02X%02X%02X", __func__,
+                        remote_bd_addr[0],remote_bd_addr[1],
+                        remote_bd_addr[2],remote_bd_addr[3],
+                        remote_bd_addr[4],remote_bd_addr[5]);
+
+    bdcpy(bta_dm_search_cb.peer_bdaddr, remote_bd_addr);
+
+    APPL_TRACE_DEBUG("%s name_discover_done = %d p_btm_inq_info 0x%x state = %d, transport=%d",
+                        __func__,
+                        bta_dm_search_cb.name_discover_done,
+                        bta_dm_search_cb.p_btm_inq_info,
+                        bta_dm_search_cb.state,
+                        transport);
+
+    if (bta_dm_search_cb.p_btm_inq_info)
+    {
+        APPL_TRACE_DEBUG("%s appl_knows_rem_name %d", __func__,
+                            bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name);
+    }
+
+    if((bta_dm_search_cb.p_btm_inq_info)
+       && (bta_dm_search_cb.p_btm_inq_info->results.device_type == BT_DEVICE_TYPE_BLE)
+       && (bta_dm_search_cb.state == BTA_DM_SEARCH_ACTIVE))
+    {
+        /* Do not perform RNR for LE devices at inquiry complete*/
+        bta_dm_search_cb.name_discover_done = TRUE;
+    }
+
+    /* if name discovery is not done and application needs remote name */
+    if ((!bta_dm_search_cb.name_discover_done)
+       && (( bta_dm_search_cb.p_btm_inq_info == NULL )
+            ||(bta_dm_search_cb.p_btm_inq_info && (!bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name))))
+    {
+        if (bta_dm_read_remote_device_name(bta_dm_search_cb.peer_bdaddr, transport) == TRUE)
+            return;
+
+        /* starting name discovery failed */
+        bta_dm_search_cb.name_discover_done = TRUE;
+    }
+
+    /* if application wants to discover service */
+    if ( bta_dm_search_cb.services )
+    {
+        /* initialize variables */
+        bta_dm_search_cb.service_index      = 0;
+        bta_dm_search_cb.services_found     = 0;
+        bta_dm_search_cb.services_to_search = bta_dm_search_cb.services;
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+        bta_dm_search_cb.uuid_to_search     = bta_dm_search_cb.num_uuid;
+#endif
+        if ((bta_dm_search_cb.p_btm_inq_info != NULL) &&
+            bta_dm_search_cb.services != BTA_USER_SERVICE_MASK
+            &&(bta_dm_search_cb.sdp_search == FALSE))
+        {
+            /* check if EIR provides the information of supported services */
+            bta_dm_eir_search_services( &bta_dm_search_cb.p_btm_inq_info->results,
+                                        &bta_dm_search_cb.services_to_search,
+                                        &bta_dm_search_cb.services_found );
+        }
+
+        /* if seaching with EIR is not completed */
+        if(bta_dm_search_cb.services_to_search)
+        {
+            /* check whether connection already exists to the device
+               if connection exists, we don't have to wait for ACL
+               link to go down to start search on next device */
+            if (BTM_IsAclConnectionUp(bta_dm_search_cb.peer_bdaddr, BT_TRANSPORT_BR_EDR))
+                bta_dm_search_cb.wait_disc = FALSE;
+            else
+                bta_dm_search_cb.wait_disc = TRUE;
+
+#if (BLE_INCLUDED == TRUE && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+            if ( bta_dm_search_cb.p_btm_inq_info )
+            {
+                APPL_TRACE_DEBUG("%s p_btm_inq_info 0x%x results.device_type 0x%x services_to_search 0x%x",
+                                    __func__,
+                                    bta_dm_search_cb.p_btm_inq_info,
+                                    bta_dm_search_cb.p_btm_inq_info->results.device_type,
+                                    bta_dm_search_cb.services_to_search);
+            }
+
+            if (transport == BT_TRANSPORT_LE)
+            {
+                if (bta_dm_search_cb.services_to_search & BTA_BLE_SERVICE_MASK)
+                {
+                    //set the raw data buffer here
+                    memset(g_disc_raw_data_buf, 0, sizeof(g_disc_raw_data_buf));
+                    bta_dm_search_cb.p_ble_rawdata = g_disc_raw_data_buf;
+
+                    bta_dm_search_cb.ble_raw_size = MAX_DISC_RAW_DATA_BUF;
+                    bta_dm_search_cb.ble_raw_used = 0;
+
+                    /* start GATT for service discovery */
+                    btm_dm_start_gatt_discovery(bta_dm_search_cb.peer_bdaddr);
+                    return;
+                }
+            }
+            else
+#endif
+            {
+                bta_dm_search_cb.sdp_results = FALSE;
+                bta_dm_find_services(bta_dm_search_cb.peer_bdaddr);
+                return;
+            }
+        }
+    }
+
+    /* name discovery and service discovery are done for this device */
+    if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_DISCOVERY_RESULT_EVT;
+        /* initialize the data structure - includes p_raw_data and raw_data_size */
+        memset(&(p_msg->disc_result.result), 0, sizeof(tBTA_DM_DISC_RES));
+        p_msg->disc_result.result.disc_res.result = BTA_SUCCESS;
+        p_msg->disc_result.result.disc_res.services = bta_dm_search_cb.services_found;
+        bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+        BCM_STRNCPY_S((char*)p_msg->disc_result.result.disc_res.bd_name,  sizeof(BD_NAME),
+                      (char*)bta_dm_search_cb.peer_name, (BD_NAME_LEN-1));
+
+        /* make sure the string is terminated */
+        p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN-1] = 0;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_sdp_callback
+**
+** Description      Callback from sdp with discovery status
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_sdp_callback (UINT16 sdp_status)
+{
+
+    tBTA_DM_SDP_RESULT * p_msg;
+
+    if ((p_msg = (tBTA_DM_SDP_RESULT *) GKI_getbuf(sizeof(tBTA_DM_SDP_RESULT))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_SDP_RESULT_EVT;
+        p_msg->sdp_result = sdp_status;
+        bta_sys_sendmsg(p_msg);
+
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_inq_results_cb
+**
+** Description      Inquiry results callback from BTM
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_inq_results_cb (tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir)
+{
+
+    tBTA_DM_SEARCH     result;
+    tBTM_INQ_INFO      *p_inq_info;
+    UINT16             service_class;
+
+    bdcpy(result.inq_res.bd_addr, p_inq->remote_bd_addr);
+    memcpy(result.inq_res.dev_class, p_inq->dev_class, DEV_CLASS_LEN);
+    BTM_COD_SERVICE_CLASS(service_class, p_inq->dev_class);
+    result.inq_res.is_limited = (service_class & BTM_COD_SERVICE_LMTD_DISCOVER)?TRUE:FALSE;
+    result.inq_res.rssi = p_inq->rssi;
+
+#if (BLE_INCLUDED == TRUE)
+    result.inq_res.ble_addr_type    = p_inq->ble_addr_type;
+    result.inq_res.inq_result_type  = p_inq->inq_result_type;
+    result.inq_res.device_type      = p_inq->device_type;
+    result.inq_res.flag             = p_inq->flag;
+#endif
+
+    /* application will parse EIR to find out remote device name */
+    result.inq_res.p_eir = p_eir;
+
+    if((p_inq_info = BTM_InqDbRead(p_inq->remote_bd_addr)) != NULL)
+    {
+        /* initialize remt_name_not_required to FALSE so that we get the name by default */
+        result.inq_res.remt_name_not_required = FALSE;
+
+    }
+
+    if(bta_dm_search_cb.p_search_cback)
+        bta_dm_search_cb.p_search_cback(BTA_DM_INQ_RES_EVT, &result);
+
+    if(p_inq_info)
+    {
+        /* application indicates if it knows the remote name, inside the callback
+         copy that to the inquiry data base*/
+        if(result.inq_res.remt_name_not_required)
+            p_inq_info->appl_knows_rem_name = TRUE;
+
+    }
+
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_inq_cmpl_cb
+**
+** Description      Inquiry complete callback from BTM
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_inq_cmpl_cb (void * p_result)
+{
+    tBTA_DM_MSG * p_msg;
+
+    if (bta_dm_search_cb.cancel_pending == FALSE)
+    {
+        APPL_TRACE_DEBUG("%s", __FUNCTION__);
+        p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG));
+        if (p_msg != NULL) {
+            p_msg->inq_cmpl.hdr.event = BTA_DM_INQUIRY_CMPL_EVT;
+            p_msg->inq_cmpl.num = ((tBTM_INQUIRY_CMPL *)p_result)->num_resp;
+            bta_sys_sendmsg(p_msg);
+        }
+    }
+    else
+    {
+        bta_dm_search_cb.cancel_pending = FALSE;
+        bta_dm_search_cancel_notify(NULL);
+
+        p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG));
+        if (p_msg != NULL) {
+            p_msg->hdr.event = BTA_DM_SEARCH_CMPL_EVT;
+            p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;
+            bta_sys_sendmsg(p_msg);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_service_search_remname_cback
+**
+** Description      Remote name call back from BTM during service discovery
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_service_search_remname_cback (BD_ADDR bd_addr, DEV_CLASS dc, BD_NAME bd_name)
+{
+    tBTM_REMOTE_DEV_NAME    rem_name;
+    tBTM_STATUS             btm_status;
+    UNUSED(dc);
+
+    APPL_TRACE_DEBUG("bta_dm_service_search_remname_cback name=<%s>", bd_name);
+
+    /* if this is what we are looking for */
+    if (!bdcmp( bta_dm_search_cb.peer_bdaddr, bd_addr))
+    {
+        rem_name.length = strlen((char*)bd_name);
+        if (rem_name.length > (BD_NAME_LEN-1))
+        {
+            rem_name.length = (BD_NAME_LEN-1);
+            rem_name.remote_bd_name[(BD_NAME_LEN-1)] = 0;
+        }
+        BCM_STRNCPY_S((char*)rem_name.remote_bd_name,  sizeof(BD_NAME), (char*)bd_name, (BD_NAME_LEN-1));
+        rem_name.status = BTM_SUCCESS;
+
+        bta_dm_remname_cback(&rem_name);
+    }
+    else
+    {
+        /* get name of device */
+        btm_status = BTM_ReadRemoteDeviceName (bta_dm_search_cb.peer_bdaddr,
+                                                (tBTM_CMPL_CB *) bta_dm_remname_cback,
+                                                BT_TRANSPORT_BR_EDR);
+        if ( btm_status == BTM_BUSY )
+        {
+            /* wait for next chance(notification of remote name discovery done) */
+            APPL_TRACE_DEBUG("bta_dm_service_search_remname_cback: BTM_ReadRemoteDeviceName is busy");
+        }
+        else if ( btm_status != BTM_CMD_STARTED )
+        {
+            /* if failed to start getting remote name then continue */
+            APPL_TRACE_WARNING("bta_dm_service_search_remname_cback: BTM_ReadRemoteDeviceName returns 0x%02X", btm_status);
+
+            rem_name.length = 0;
+            rem_name.remote_bd_name[0] = 0;
+            rem_name.status = btm_status;
+            bta_dm_remname_cback(&rem_name);
+        }
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_remname_cback
+**
+** Description      Remote name complete call back from BTM
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_remname_cback (tBTM_REMOTE_DEV_NAME *p_remote_name)
+{
+    tBTA_DM_REM_NAME * p_msg;
+
+    APPL_TRACE_DEBUG("bta_dm_remname_cback len = %d name=<%s>", p_remote_name->length,
+                      p_remote_name->remote_bd_name);
+
+    /* remote name discovery is done but it could be failed */
+    bta_dm_search_cb.name_discover_done = TRUE;
+    BCM_STRNCPY_S((char*)bta_dm_search_cb.peer_name, sizeof(BD_NAME), (char*)p_remote_name->remote_bd_name, (BD_NAME_LEN));
+    bta_dm_search_cb.peer_name[BD_NAME_LEN]=0;
+
+    BTM_SecDeleteRmtNameNotifyCallback(&bta_dm_service_search_remname_cback);
+
+#if BLE_INCLUDED == TRUE
+    if (bta_dm_search_cb.transport == BT_TRANSPORT_LE )
+    {
+        GAP_BleReadPeerPrefConnParams (bta_dm_search_cb.peer_bdaddr);
+    }
+#endif
+
+    if ((p_msg = (tBTA_DM_REM_NAME *) GKI_getbuf(sizeof(tBTA_DM_REM_NAME))) != NULL)
+    {
+        bdcpy (p_msg->result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+        BCM_STRNCPY_S((char*)p_msg->result.disc_res.bd_name, sizeof(BD_NAME), (char*)p_remote_name->remote_bd_name, (BD_NAME_LEN));
+
+        /* make sure the string is null terminated */
+        p_msg->result.disc_res.bd_name[BD_NAME_LEN] = 0;
+
+        p_msg->hdr.event = BTA_DM_REMT_NAME_EVT;
+        bta_sys_sendmsg(p_msg);
+
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_authorize_cback
+**
+** Description      cback requesting authorization
+**
+** Returns          void
+**
+*******************************************************************************/
+static UINT8 bta_dm_authorize_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
+                                     UINT8 *service_name, UINT8 service_id, BOOLEAN is_originator)
+{
+    tBTA_DM_SEC sec_event;
+    UINT8       index = 1;
+    UNUSED(service_name);
+    UNUSED(is_originator);
+
+    bdcpy(sec_event.authorize.bd_addr, bd_addr);
+    memcpy(sec_event.authorize.dev_class, dev_class, DEV_CLASS_LEN);
+
+    BCM_STRNCPY_S((char*)sec_event.authorize.bd_name, sizeof(BD_NAME), (char*)bd_name, (BD_NAME_LEN-1));
+
+    /* make sure the string is null terminated */
+    sec_event.authorize.bd_name[BD_NAME_LEN-1] = 0;
+
+#if ( defined(BTA_JV_INCLUDED) && BTA_JV_INCLUDED == TRUE )
+    sec_event.authorize.service = service_id;
+#endif
+
+    while(index < BTA_MAX_SERVICE_ID)
+    {
+        /* get the BTA service id corresponding to BTM id */
+        if(bta_service_id_to_btm_srv_id_lkup_tbl[index] == service_id)
+        {
+            sec_event.authorize.service = index;
+            break;
+        }
+        index++;
+    }
+
+
+    /* if supported service callback otherwise not authorized */
+    if(bta_dm_cb.p_sec_cback && (index < BTA_MAX_SERVICE_ID
+#if ( defined(BTA_JV_INCLUDED) && BTA_JV_INCLUDED == TRUE )
+        /* pass through JV service ID */
+        || (service_id >= BTA_FIRST_JV_SERVICE_ID && service_id <= BTA_LAST_JV_SERVICE_ID)
+#endif
+        ))
+    {
+        bta_dm_cb.p_sec_cback(BTA_DM_AUTHORIZE_EVT, &sec_event);
+        return BTM_CMD_STARTED;
+    }
+    else
+    {
+        return BTM_NOT_AUTHORIZED;
+    }
+}
+
+
+
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_pinname_cback
+**
+** Description      Callback requesting pin_key
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_pinname_cback (void *p_data)
+{
+    tBTM_REMOTE_DEV_NAME *p_result = (tBTM_REMOTE_DEV_NAME *)p_data;
+    tBTA_DM_SEC           sec_event;
+    UINT32                bytes_to_copy;
+    tBTA_DM_SEC_EVT       event = bta_dm_cb.pin_evt;
+
+    if (BTA_DM_SP_CFM_REQ_EVT == event)
+    {
+        /* Retrieved saved device class and bd_addr */
+        bdcpy(sec_event.cfm_req.bd_addr, bta_dm_cb.pin_bd_addr);
+        BTA_COPY_DEVICE_CLASS(sec_event.cfm_req.dev_class, bta_dm_cb.pin_dev_class);
+
+        if (p_result && p_result->status == BTM_SUCCESS)
+        {
+            bytes_to_copy = (p_result->length < (BD_NAME_LEN-1))
+            ? p_result->length : (BD_NAME_LEN-1);
+            memcpy(sec_event.cfm_req.bd_name, p_result->remote_bd_name, bytes_to_copy);
+            sec_event.pin_req.bd_name[BD_NAME_LEN-1] = 0;
+        }
+        else    /* No name found */
+            sec_event.cfm_req.bd_name[0] = 0;
+
+        sec_event.key_notif.passkey    = bta_dm_cb.num_val; /* get PIN code numeric number */
+
+        /* 1 additional event data fields for this event */
+        sec_event.cfm_req.just_works = bta_dm_cb.just_works;
+    }
+    else
+    {
+        /* Retrieved saved device class and bd_addr */
+        bdcpy(sec_event.pin_req.bd_addr, bta_dm_cb.pin_bd_addr);
+        BTA_COPY_DEVICE_CLASS(sec_event.pin_req.dev_class, bta_dm_cb.pin_dev_class);
+
+        if (p_result && p_result->status == BTM_SUCCESS)
+        {
+            bytes_to_copy = (p_result->length < (BD_NAME_LEN-1))
+            ? p_result->length : (BD_NAME_LEN-1);
+            memcpy(sec_event.pin_req.bd_name, p_result->remote_bd_name, bytes_to_copy);
+            sec_event.pin_req.bd_name[BD_NAME_LEN-1] = 0;
+        }
+        else    /* No name found */
+            sec_event.pin_req.bd_name[0] = 0;
+
+        event = bta_dm_cb.pin_evt;
+        sec_event.key_notif.passkey    = bta_dm_cb.num_val; /* get PIN code numeric number */
+    }
+
+    if( bta_dm_cb.p_sec_cback )
+        bta_dm_cb.p_sec_cback(event, &sec_event);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_pin_cback
+**
+** Description      Callback requesting pin_key
+**
+** Returns          void
+**
+*******************************************************************************/
+static UINT8 bta_dm_pin_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
+        BOOLEAN min_16_digit)
+{
+    tBTA_DM_SEC sec_event;
+
+    if (!bta_dm_cb.p_sec_cback)
+        return BTM_NOT_AUTHORIZED;
+
+    /* If the device name is not known, save bdaddr and devclass and initiate a name request */
+    if (bd_name[0] == 0)
+    {
+        bta_dm_cb.pin_evt = BTA_DM_PIN_REQ_EVT;
+        bdcpy(bta_dm_cb.pin_bd_addr, bd_addr);
+        BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class, dev_class);
+        if ((BTM_ReadRemoteDeviceName(bd_addr, bta_dm_pinname_cback, BT_TRANSPORT_BR_EDR)) == BTM_CMD_STARTED)
+            return BTM_CMD_STARTED;
+
+        APPL_TRACE_WARNING(" bta_dm_pin_cback() -> Failed to start Remote Name Request  ");
+    }
+
+    bdcpy(sec_event.pin_req.bd_addr, bd_addr);
+    BTA_COPY_DEVICE_CLASS(sec_event.pin_req.dev_class, dev_class);
+    BCM_STRNCPY_S((char*)sec_event.pin_req.bd_name, sizeof(BD_NAME), (char*)bd_name, (BD_NAME_LEN-1));
+    sec_event.pin_req.bd_name[BD_NAME_LEN-1] = 0;
+    sec_event.pin_req.min_16_digit = min_16_digit;
+
+    bta_dm_cb.p_sec_cback(BTA_DM_PIN_REQ_EVT, &sec_event);
+    return BTM_CMD_STARTED;
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_new_link_key_cback
+**
+** Description      Callback from BTM to notify new link key
+**
+** Returns          void
+**
+*******************************************************************************/
+static UINT8  bta_dm_new_link_key_cback(BD_ADDR bd_addr, DEV_CLASS dev_class,
+                                        BD_NAME bd_name, LINK_KEY key, UINT8 key_type)
+{
+    tBTA_DM_SEC sec_event;
+    tBTA_DM_AUTH_CMPL *p_auth_cmpl;
+    UINT8             event;
+    UNUSED(dev_class);
+
+    memset (&sec_event, 0, sizeof(tBTA_DM_SEC));
+
+    /* Not AMP Key type */
+    if (key_type != HCI_LKEY_TYPE_AMP_WIFI && key_type != HCI_LKEY_TYPE_AMP_UWB)
+    {
+        event = BTA_DM_AUTH_CMPL_EVT;
+        p_auth_cmpl = &sec_event.auth_cmpl;
+
+        bdcpy(p_auth_cmpl->bd_addr, bd_addr);
+
+        memcpy(p_auth_cmpl->bd_name, bd_name, (BD_NAME_LEN-1));
+        p_auth_cmpl->bd_name[BD_NAME_LEN-1] = 0;
+
+        p_auth_cmpl->key_present = TRUE;
+        p_auth_cmpl->key_type = key_type;
+        p_auth_cmpl->success = TRUE;
+
+        memcpy(p_auth_cmpl->key, key, LINK_KEY_LEN);
+        sec_event.auth_cmpl.fail_reason = HCI_SUCCESS;
+
+#if BLE_INCLUDED == TRUE
+        // Report the BR link key based on the BR/EDR address and type
+        BTM_ReadDevInfo(bd_addr, &sec_event.auth_cmpl.dev_type, &sec_event.auth_cmpl.addr_type);
+#endif
+        if(bta_dm_cb.p_sec_cback)
+            bta_dm_cb.p_sec_cback(event, &sec_event);
+    }
+    else
+    {
+        APPL_TRACE_WARNING("%s() Received AMP Key", __func__);
+    }
+
+    return BTM_CMD_STARTED;
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_authentication_complete_cback
+**
+** Description      Authentication complete callback from BTM
+**
+** Returns          void
+**
+*******************************************************************************/
+static UINT8 bta_dm_authentication_complete_cback(BD_ADDR bd_addr, DEV_CLASS dev_class,BD_NAME bd_name, int result)
+{
+    tBTA_DM_SEC sec_event;
+    UNUSED(dev_class);
+
+    if(result != BTM_SUCCESS)
+    {
+        memset(&sec_event, 0, sizeof(tBTA_DM_SEC));
+        bdcpy(sec_event.auth_cmpl.bd_addr, bd_addr);
+
+        memcpy(sec_event.auth_cmpl.bd_name, bd_name, (BD_NAME_LEN-1));
+        sec_event.auth_cmpl.bd_name[BD_NAME_LEN-1] = 0;
+
+#if BLE_INCLUDED == TRUE
+        // Report the BR link key based on the BR/EDR address and type
+        BTM_ReadDevInfo(bd_addr, &sec_event.auth_cmpl.dev_type, &sec_event.auth_cmpl.addr_type);
+#endif
+        sec_event.auth_cmpl.fail_reason = (UINT8)result;
+
+        if(bta_dm_cb.p_sec_cback)
+            bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
+
+        bta_dm_remove_sec_dev_entry(bd_addr);
+    }
+
+    return BTM_SUCCESS;
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_sp_cback
+**
+** Description      simple pairing callback from BTM
+**
+** Returns          void
+**
+*******************************************************************************/
+static UINT8 bta_dm_sp_cback (tBTM_SP_EVT event, tBTM_SP_EVT_DATA *p_data)
+{
+    tBTM_STATUS status = BTM_CMD_STARTED;
+    tBTA_DM_SEC sec_event;
+    tBTA_DM_SEC_EVT pin_evt = BTA_DM_SP_KEY_NOTIF_EVT;
+
+    APPL_TRACE_EVENT("bta_dm_sp_cback: %d", event);
+    if (!bta_dm_cb.p_sec_cback)
+        return BTM_NOT_AUTHORIZED;
+
+    /* TODO_SP */
+    switch(event)
+    {
+    case BTM_SP_IO_REQ_EVT:
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+        /* translate auth_req */
+        bta_dm_co_io_req(p_data->io_req.bd_addr, &p_data->io_req.io_cap,
+            &p_data->io_req.oob_data, &p_data->io_req.auth_req, p_data->io_req.is_orig);
+#endif
+#if BTM_OOB_INCLUDED == FALSE
+        status = BTM_SUCCESS;
+#endif
+
+        APPL_TRACE_EVENT("io mitm: %d oob_data:%d", p_data->io_req.auth_req, p_data->io_req.oob_data);
+        break;
+    case BTM_SP_IO_RSP_EVT:
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+        bta_dm_co_io_rsp(p_data->io_rsp.bd_addr, p_data->io_rsp.io_cap,
+                         p_data->io_rsp.oob_data, p_data->io_rsp.auth_req );
+#endif
+        break;
+
+    case BTM_SP_CFM_REQ_EVT:
+        pin_evt = BTA_DM_SP_CFM_REQ_EVT;
+        bta_dm_cb.just_works = sec_event.cfm_req.just_works = p_data->cfm_req.just_works;
+        sec_event.cfm_req.loc_auth_req = p_data->cfm_req.loc_auth_req;
+        sec_event.cfm_req.rmt_auth_req = p_data->cfm_req.rmt_auth_req;
+        sec_event.cfm_req.loc_io_caps = p_data->cfm_req.loc_io_caps;
+        sec_event.cfm_req.rmt_io_caps = p_data->cfm_req.rmt_io_caps;
+
+        /* continue to next case */
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+    /* Passkey entry mode, mobile device with output capability is very
+        unlikely to receive key request, so skip this event */
+    /*case BTM_SP_KEY_REQ_EVT: */
+    case BTM_SP_KEY_NOTIF_EVT:
+#endif
+        if(BTM_SP_CFM_REQ_EVT == event)
+        {
+          /* Due to the switch case falling through below to BTM_SP_KEY_NOTIF_EVT,
+             call remote name request using values from cfm_req */
+          if(p_data->cfm_req.bd_name[0] == 0)
+          {
+              bta_dm_cb.pin_evt = pin_evt;
+              bdcpy(bta_dm_cb.pin_bd_addr, p_data->cfm_req.bd_addr);
+              BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class, p_data->cfm_req.dev_class);
+              if ((BTM_ReadRemoteDeviceName(p_data->cfm_req.bd_addr, bta_dm_pinname_cback,
+                         BT_TRANSPORT_BR_EDR)) == BTM_CMD_STARTED)
+                  return BTM_CMD_STARTED;
+              APPL_TRACE_WARNING(" bta_dm_sp_cback() -> Failed to start Remote Name Request  ");
+          }
+          else
+          {
+              /* Due to the switch case falling through below to BTM_SP_KEY_NOTIF_EVT,
+                 copy these values into key_notif from cfm_req */
+              bdcpy(sec_event.key_notif.bd_addr, p_data->cfm_req.bd_addr);
+              BTA_COPY_DEVICE_CLASS(sec_event.key_notif.dev_class, p_data->cfm_req.dev_class);
+              BCM_STRNCPY_S((char*)sec_event.key_notif.bd_name, sizeof(BD_NAME),
+                   (char*)p_data->cfm_req.bd_name, (BD_NAME_LEN-1));
+              sec_event.key_notif.bd_name[BD_NAME_LEN-1] = 0;
+           }
+        }
+
+        bta_dm_cb.num_val = sec_event.key_notif.passkey = p_data->key_notif.passkey;
+        if (BTM_SP_KEY_NOTIF_EVT == event)
+        {
+            /* If the device name is not known, save bdaddr and devclass
+               and initiate a name request with values from key_notif */
+            if(p_data->key_notif.bd_name[0] == 0)
+            {
+                bta_dm_cb.pin_evt = pin_evt;
+                bdcpy(bta_dm_cb.pin_bd_addr, p_data->key_notif.bd_addr);
+                BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class, p_data->key_notif.dev_class);
+                if ((BTM_ReadRemoteDeviceName(p_data->key_notif.bd_addr, bta_dm_pinname_cback,
+                         BT_TRANSPORT_BR_EDR)) == BTM_CMD_STARTED)
+                return BTM_CMD_STARTED;
+                APPL_TRACE_WARNING(" bta_dm_sp_cback() -> Failed to start Remote Name Request  ");
+            }
+            else
+            {
+                bdcpy(sec_event.key_notif.bd_addr, p_data->key_notif.bd_addr);
+                BTA_COPY_DEVICE_CLASS(sec_event.key_notif.dev_class, p_data->key_notif.dev_class);
+                BCM_STRNCPY_S((char*)sec_event.key_notif.bd_name, sizeof(BD_NAME),
+                    (char*)p_data->key_notif.bd_name, (BD_NAME_LEN-1));
+                sec_event.key_notif.bd_name[BD_NAME_LEN-1] = 0;
+            }
+        }
+
+        bta_dm_cb.p_sec_cback(pin_evt, &sec_event);
+
+        break;
+
+#if BTM_OOB_INCLUDED == TRUE
+    case BTM_SP_LOC_OOB_EVT:
+        bta_dm_co_loc_oob((BOOLEAN)(p_data->loc_oob.status == BTM_SUCCESS),
+            p_data->loc_oob.c, p_data->loc_oob.r);
+        break;
+
+    case BTM_SP_RMT_OOB_EVT:
+        /* If the device name is not known, save bdaddr and devclass and initiate a name request */
+        if (p_data->rmt_oob.bd_name[0] == 0)
+        {
+             bta_dm_cb.pin_evt = BTA_DM_SP_RMT_OOB_EVT;
+             bdcpy(bta_dm_cb.pin_bd_addr, p_data->rmt_oob.bd_addr);
+             BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class, p_data->rmt_oob.dev_class);
+             if ((BTM_ReadRemoteDeviceName(p_data->rmt_oob.bd_addr, bta_dm_pinname_cback,
+                      BT_TRANSPORT_BR_EDR)) == BTM_CMD_STARTED)
+             return BTM_CMD_STARTED;
+             APPL_TRACE_WARNING(" bta_dm_sp_cback() -> Failed to start Remote Name Request  ");
+         }
+
+         bdcpy(sec_event.rmt_oob.bd_addr, p_data->rmt_oob.bd_addr);
+         BTA_COPY_DEVICE_CLASS(sec_event.rmt_oob.dev_class, p_data->rmt_oob.dev_class);
+         BCM_STRNCPY_S((char*)sec_event.rmt_oob.bd_name, sizeof(BD_NAME), (char*)p_data->rmt_oob.bd_name, (BD_NAME_LEN-1));
+            sec_event.rmt_oob.bd_name[BD_NAME_LEN-1] = 0;
+
+        bta_dm_cb.p_sec_cback(BTA_DM_SP_RMT_OOB_EVT, &sec_event);
+
+        bta_dm_co_rmt_oob(p_data->rmt_oob.bd_addr);
+        break;
+#endif
+    case BTM_SP_COMPLT_EVT:
+        /* do not report this event - handled by link_key_callback or auth_complete_callback */
+        break;
+
+    case BTM_SP_KEYPRESS_EVT:
+        memcpy(&sec_event.key_press, &p_data->key_press, sizeof(tBTM_SP_KEYPRESS));
+        bta_dm_cb.p_sec_cback(BTA_DM_SP_KEYPRESS_EVT, &sec_event);
+        break;
+
+    case BTM_SP_UPGRADE_EVT:
+        bta_dm_co_lk_upgrade(p_data->upgrade.bd_addr, &p_data->upgrade.upgrade );
+        break;
+
+    default:
+        status = BTM_NOT_AUTHORIZED;
+        break;
+    }
+    APPL_TRACE_EVENT("dm status: %d", status);
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_local_name_cback
+**
+** Description      Callback from btm after local name is read
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_local_name_cback(UINT8 *p_name)
+{
+    tBTA_DM_SEC sec_event;
+    UNUSED(p_name);
+
+    sec_event.enable.status = BTA_SUCCESS;
+
+    if(bta_dm_cb.p_sec_cback)
+        bta_dm_cb.p_sec_cback(BTA_DM_ENABLE_EVT, &sec_event);
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_bl_change_cback
+**
+** Description      Callback from btm when acl connection goes up or down
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_bl_change_cback (tBTM_BL_EVENT_DATA *p_data)
+{
+    tBTA_DM_ACL_CHANGE * p_msg;
+
+    if ((p_msg = (tBTA_DM_ACL_CHANGE *) GKI_getbuf(sizeof(tBTA_DM_ACL_CHANGE))) != NULL)
+    {
+        p_msg->event = p_data->event;
+        p_msg->is_new = FALSE;
+
+        switch(p_msg->event)
+        {
+        case BTM_BL_CONN_EVT:
+            p_msg->is_new = TRUE;
+            bdcpy(p_msg->bd_addr, p_data->conn.p_bda);
+#if BLE_INCLUDED == TRUE
+            p_msg->transport = p_data->conn.transport;
+            p_msg->handle = p_data->conn.handle;
+#endif
+            break;
+        case BTM_BL_DISCN_EVT:
+            bdcpy(p_msg->bd_addr, p_data->discn.p_bda);
+#if BLE_INCLUDED == TRUE
+            p_msg->transport = p_data->discn.transport;
+            p_msg->handle = p_data->discn.handle;
+#endif
+            break;
+        case BTM_BL_UPDATE_EVT:
+            p_msg->busy_level = p_data->update.busy_level;
+            p_msg->busy_level_flags = p_data->update.busy_level_flags;
+            break;
+        case BTM_BL_ROLE_CHG_EVT:
+            p_msg->new_role = p_data->role_chg.new_role;
+            p_msg->hci_status = p_data->role_chg.hci_status;
+            bdcpy(p_msg->bd_addr, p_data->role_chg.p_bda);
+            break;
+        case BTM_BL_COLLISION_EVT:
+            bdcpy(p_msg->bd_addr, p_data->conn.p_bda);
+            break;
+        }
+
+        p_msg->hdr.event = BTA_DM_ACL_CHANGE_EVT;
+        bta_sys_sendmsg(p_msg);
+
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_acl_change_cback
+**
+** Description      Callback from btm when acl connection goes up or down
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+#if BLE_INCLUDED == TRUE
+static void bta_dm_acl_change_cback(BD_ADDR p_bda, DEV_CLASS p_dc, BD_NAME p_bdn,
+                                    UINT8 *features, BOOLEAN is_new,UINT16 handle,
+                                    tBT_TRANSPORT transport)
+#else
+static void bta_dm_acl_change_cback(BD_ADDR p_bda, DEV_CLASS p_dc, BD_NAME p_bdn,
+                                    UINT8 *features, BOOLEAN is_new)
+#endif
+{
+    tBTA_DM_ACL_CHANGE *p_msg = (tBTA_DM_ACL_CHANGE *) GKI_getbuf(sizeof(tBTA_DM_ACL_CHANGE));
+    if (p_msg != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_ACL_CHANGE));
+
+        bdcpy(p_msg->bd_addr, p_bda);
+        p_msg->is_new = is_new;
+#if BLE_INCLUDED == TRUE
+        p_msg->handle = handle;
+        p_msg->transport = transport;
+#endif
+        /* This is collision case */
+        if (features != NULL)
+        {
+            if ((features[0] == 0xFF) && !is_new)
+                p_msg->event = BTM_BL_COLLISION_EVT;
+        }
+
+        p_msg->hdr.event = BTA_DM_ACL_CHANGE_EVT;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_rs_cback
+**
+** Description      Receives the role switch complete event
+**
+** Returns
+**
+*******************************************************************************/
+static void bta_dm_rs_cback (tBTM_ROLE_SWITCH_CMPL *p1)
+{
+    UNUSED(p1);
+    APPL_TRACE_WARNING("bta_dm_rs_cback:%d", bta_dm_cb.rs_event);
+    if(bta_dm_cb.rs_event == BTA_DM_API_SEARCH_EVT)
+    {
+        bta_dm_cb.search_msg.rs_res = BTA_DM_RS_OK; /* do not care about the result for now */
+        bta_dm_cb.rs_event = 0;
+        bta_dm_search_start((tBTA_DM_MSG *)&bta_dm_cb.search_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_check_av
+**
+** Description      This function checks if AV is active
+**                  if yes, make sure the AV link is master
+**
+** Returns          BOOLEAN - TRUE, if switch is in progress
+**
+*******************************************************************************/
+static BOOLEAN bta_dm_check_av(UINT16 event)
+{
+    BOOLEAN avoid_roleswitch = FALSE;
+    BOOLEAN switching = FALSE;
+    UINT8 i;
+    tBTA_DM_PEER_DEVICE *p_dev;
+
+#if defined(BTA_DM_AVOID_A2DP_ROLESWITCH_ON_INQUIRY) && (BTA_DM_AVOID_A2DP_ROLESWITCH_ON_INQUIRY == TRUE)
+
+    /* avoid role switch upon inquiry if a2dp is actively streaming as it
+       introduces an audioglitch due to FW scheduling delays (unavoidable) */
+    if (event == BTA_DM_API_SEARCH_EVT)
+    {
+        avoid_roleswitch = TRUE;
+    }
+#endif
+
+    APPL_TRACE_WARNING("bta_dm_check_av:%d", bta_dm_cb.cur_av_count);
+    if(bta_dm_cb.cur_av_count)
+    {
+        for(i=0; i<bta_dm_cb.device_list.count; i++)
+        {
+            p_dev = &bta_dm_cb.device_list.peer_device[i];
+            APPL_TRACE_WARNING("[%d]: state:%d, info:x%x, avoid_rs %d",
+                                i, p_dev->conn_state, p_dev->info, avoid_roleswitch);
+            if((p_dev->conn_state == BTA_DM_CONNECTED) && (p_dev->info & BTA_DM_DI_AV_ACTIVE) &&
+               (avoid_roleswitch == FALSE))
+            {
+                /* make master and take away the role switch policy */
+                if(BTM_CMD_STARTED == BTM_SwitchRole (p_dev->peer_bdaddr, HCI_ROLE_MASTER, (tBTM_CMPL_CB *)bta_dm_rs_cback))
+                {
+                    /* the role switch command is actually sent */
+                    bta_dm_cb.rs_event = event;
+                    switching = TRUE;
+                }
+                /* else either already master or can not switch for some reasons */
+                bta_dm_policy_cback(BTA_SYS_PLCY_CLR, 0, HCI_ENABLE_MASTER_SLAVE_SWITCH, p_dev->peer_bdaddr);
+                break;
+            }
+        }
+    }
+    return switching;
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_acl_change
+**
+** Description      Process BTA_DM_ACL_CHANGE_EVT
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_acl_change(tBTA_DM_MSG *p_data)
+{
+
+    UINT8 i;
+    UINT8 *p;
+    tBTA_DM_SEC conn;
+    BOOLEAN is_new = p_data->acl_change.is_new;
+    BD_ADDR_PTR     p_bda = p_data->acl_change.bd_addr;
+    BOOLEAN         need_policy_change = FALSE;
+    BOOLEAN         issue_unpair_cb = FALSE;
+
+    tBTA_DM_PEER_DEVICE *p_dev;
+    memset(&conn, 0, sizeof(tBTA_DM_SEC));
+
+    switch(p_data->acl_change.event)
+    {
+    case BTM_BL_UPDATE_EVT:     /* busy level update */
+        if( bta_dm_cb.p_sec_cback )
+        {
+            conn.busy_level.level = p_data->acl_change.busy_level;
+            conn.busy_level.level_flags = p_data->acl_change.busy_level_flags;
+            bta_dm_cb.p_sec_cback(BTA_DM_BUSY_LEVEL_EVT, &conn);
+        }
+        return;
+
+    case BTM_BL_ROLE_CHG_EVT:   /* role change event */
+        p_dev = bta_dm_find_peer_device(p_bda);
+        if(p_dev)
+        {
+            APPL_TRACE_DEBUG("bta_dm_acl_change role chg info:x%x new_role:%d dev count:%d",
+                p_dev->info, p_data->acl_change.new_role, bta_dm_cb.device_list.count);
+            if(p_dev->info & BTA_DM_DI_AV_ACTIVE)
+            {
+                /* there's AV activity on this link */
+                if(p_data->acl_change.new_role == HCI_ROLE_SLAVE && bta_dm_cb.device_list.count > 1
+                    && p_data->acl_change.hci_status == HCI_SUCCESS)
+                {
+                    /* more than one connections and the AV connection is role switched to slave
+                     * switch it back to master and remove the switch policy */
+                    BTM_SwitchRole(p_bda, BTM_ROLE_MASTER, NULL);
+                    need_policy_change = TRUE;
+                }
+                else if (p_bta_dm_cfg->avoid_scatter && (p_data->acl_change.new_role == HCI_ROLE_MASTER))
+                {
+                    /* if the link updated to be master include AV activities, remove the switch policy */
+                    need_policy_change = TRUE;
+                }
+
+                if(need_policy_change)
+                {
+                    bta_dm_policy_cback(BTA_SYS_PLCY_CLR, 0, HCI_ENABLE_MASTER_SLAVE_SWITCH, p_dev->peer_bdaddr);
+                }
+            }
+            else
+            {
+                /* there's AV no activity on this link and role switch happened
+                 * check if AV is active
+                 * if so, make sure the AV link is master */
+                bta_dm_check_av(0);
+            }
+            bta_sys_notify_role_chg(p_data->acl_change.bd_addr, p_data->acl_change.new_role, p_data->acl_change.hci_status);
+            bdcpy(conn.role_chg.bd_addr, p_bda);
+            conn.role_chg.new_role = (UINT8) p_data->acl_change.new_role;
+            if( bta_dm_cb.p_sec_cback )
+                bta_dm_cb.p_sec_cback(BTA_DM_ROLE_CHG_EVT, (tBTA_DM_SEC *)&conn);
+        }
+        return;
+    }
+
+    /* Collision report from Stack: Notify profiles */
+    if (p_data->acl_change.event == BTM_BL_COLLISION_EVT)
+    {
+        bta_sys_notify_collision (p_bda);
+        return;
+    }
+
+    if(is_new)
+    {
+        for(i=0; i<bta_dm_cb.device_list.count; i++)
+        {
+            if (!bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, p_bda)
+#if BLE_INCLUDED == TRUE
+                 && bta_dm_cb.device_list.peer_device[i].conn_handle == p_data->acl_change.handle
+#endif
+                 )
+                break;
+
+        }
+
+        if(i == bta_dm_cb.device_list.count)
+        {
+            if (bta_dm_cb.device_list.count < BTA_DM_NUM_PEER_DEVICE)
+            {
+                bdcpy(bta_dm_cb.device_list.peer_device[bta_dm_cb.device_list.count].peer_bdaddr, p_bda);
+                bta_dm_cb.device_list.peer_device[bta_dm_cb.device_list.count].link_policy = bta_dm_cb.cur_policy;
+                bta_dm_cb.device_list.count++;
+#if BLE_INCLUDED == TRUE
+                bta_dm_cb.device_list.peer_device[i].conn_handle = p_data->acl_change.handle;
+                if (p_data->acl_change.transport == BT_TRANSPORT_LE)
+                    bta_dm_cb.device_list.le_count++;
+#endif
+            } else {
+                APPL_TRACE_ERROR("%s max active connection reached, no resources", __func__);
+                return;
+            }
+        }
+
+        bta_dm_cb.device_list.peer_device[i].conn_state = BTA_DM_CONNECTED;
+        bta_dm_cb.device_list.peer_device[i].pref_role = BTA_ANY_ROLE;
+        bdcpy(conn.link_up.bd_addr, p_bda);
+        bta_dm_cb.device_list.peer_device[i].info = BTA_DM_DI_NONE;
+#if BLE_INCLUDED == TRUE
+        conn.link_up.link_type = p_data->acl_change.transport;
+        bta_dm_cb.device_list.peer_device[i].transport = p_data->acl_change.transport;
+#endif
+
+        if (((NULL != (p = BTM_ReadLocalFeatures ())) && HCI_SNIFF_SUB_RATE_SUPPORTED(p)) &&
+            ((NULL != (p = BTM_ReadRemoteFeatures (p_bda))) && HCI_SNIFF_SUB_RATE_SUPPORTED(p)))
+        {
+            /* both local and remote devices support SSR */
+            bta_dm_cb.device_list.peer_device[i].info = BTA_DM_DI_USE_SSR;
+        }
+        APPL_TRACE_WARNING("%s info: 0x%x", __func__, bta_dm_cb.device_list.peer_device[i].info);
+
+        if (bta_dm_cb.p_sec_cback)
+            bta_dm_cb.p_sec_cback(BTA_DM_LINK_UP_EVT, (tBTA_DM_SEC *)&conn);
+    } else {
+        for(i=0; i<bta_dm_cb.device_list.count; i++)
+        {
+            if (bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, p_bda)
+#if BLE_INCLUDED == TRUE
+                 ||bta_dm_cb.device_list.peer_device[i].transport != p_data->acl_change.transport
+#endif
+               )
+                continue;
+
+            if( bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_UNPAIRING )
+            {
+                if (BTM_SecDeleteDevice(bta_dm_cb.device_list.peer_device[i].peer_bdaddr))
+                    issue_unpair_cb = TRUE;
+
+                APPL_TRACE_DEBUG("%s: Unpairing: issue unpair CB = %d ",__FUNCTION__, issue_unpair_cb);
+            }
+
+            conn.link_down.is_removed = bta_dm_cb.device_list.peer_device[i].remove_dev_pending;
+
+            for(; i<bta_dm_cb.device_list.count ; i++)
+            {
+                memcpy(&bta_dm_cb.device_list.peer_device[i], &bta_dm_cb.device_list.peer_device[i+1], sizeof(bta_dm_cb.device_list.peer_device[i]));
+            }
+            break;
+        }
+        if(bta_dm_cb.device_list.count)
+            bta_dm_cb.device_list.count--;
+#if BLE_INCLUDED == TRUE
+        if ((p_data->acl_change.transport == BT_TRANSPORT_LE) &&
+             (bta_dm_cb.device_list.le_count))
+            bta_dm_cb.device_list.le_count--;
+        conn.link_down.link_type = p_data->acl_change.transport;
+#endif
+
+        if(bta_dm_search_cb.wait_disc && !bdcmp(bta_dm_search_cb.peer_bdaddr, p_bda))
+        {
+            bta_dm_search_cb.wait_disc = FALSE;
+
+            if(bta_dm_search_cb.sdp_results)
+            {
+                APPL_TRACE_EVENT(" timer stopped  ");
+                bta_sys_stop_timer(&bta_dm_search_cb.search_timer);
+                bta_dm_discover_next_device();
+            }
+
+        }
+
+        if(bta_dm_cb.disabling)
+        {
+            if(!BTM_GetNumAclLinks())
+            {
+                bta_sys_stop_timer(&bta_dm_cb.disable_timer);
+                bta_dm_cb.disable_timer.p_cback = (TIMER_CBACK*)&bta_dm_disable_conn_down_timer_cback;
+                /*
+                 * Start a timer to make sure that the profiles
+                 * get the disconnect event.
+                 */
+                bta_sys_start_timer(&bta_dm_cb.disable_timer, 0, 1000);
+            }
+        }
+        if (conn.link_down.is_removed)
+        {
+            BTM_SecDeleteDevice(p_bda);
+#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
+            /* need to remove all pending background connection */
+            BTA_GATTC_CancelOpen(0, p_bda, FALSE);
+            /* remove all cached GATT information */
+            BTA_GATTC_Refresh(p_bda);
+#endif
+         }
+
+        bdcpy(conn.link_down.bd_addr, p_bda);
+        conn.link_down.status = (UINT8) btm_get_acl_disc_reason_code();
+        if( bta_dm_cb.p_sec_cback )
+        {
+            bta_dm_cb.p_sec_cback(BTA_DM_LINK_DOWN_EVT, &conn);
+            if( issue_unpair_cb )
+                bta_dm_cb.p_sec_cback(BTA_DM_DEV_UNPAIRED_EVT, &conn);
+        }
+    }
+
+    bta_dm_adjust_roles(TRUE);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_disable_conn_down_timer_cback
+**
+** Description      Sends disable event to application
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_disable_conn_down_timer_cback (TIMER_LIST_ENT *p_tle)
+{
+    UNUSED(p_tle);
+    tBTA_SYS_HW_MSG *sys_enable_event;
+
+    /* disable the power managment module */
+    bta_dm_disable_pm();
+
+    /* register our callback to SYS HW manager */
+    bta_sys_hw_register( BTA_SYS_HW_BLUETOOTH, bta_dm_sys_hw_cback );
+
+    /* send a message to BTA SYS */
+    if ((sys_enable_event = (tBTA_SYS_HW_MSG *) GKI_getbuf(sizeof(tBTA_SYS_HW_MSG))) != NULL)
+    {
+        sys_enable_event->hdr.event = BTA_SYS_API_DISABLE_EVT;
+        sys_enable_event->hw_module = BTA_SYS_HW_BLUETOOTH;
+        bta_sys_sendmsg(sys_enable_event);
+    }
+
+    bta_dm_cb.disabling = FALSE;
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_rm_cback
+**
+** Description      Role management callback from sys
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_rm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+    UINT8 j;
+    tBTA_PREF_ROLES role;
+    tBTA_DM_PEER_DEVICE *p_dev;
+
+    p_dev = bta_dm_find_peer_device(peer_addr);
+    if( status == BTA_SYS_CONN_OPEN)
+    {
+        if(p_dev)
+        {
+            /* Do not set to connected if we are in the middle of unpairing. When AV stream is
+             * started it fakes out a SYS_CONN_OPEN to potentially trigger a role switch command.
+             * But this should not be done if we are in the middle of unpairing.
+             */
+            if (p_dev->conn_state != BTA_DM_UNPAIRING)
+                p_dev->conn_state = BTA_DM_CONNECTED;
+
+            for(j=1; j<= p_bta_dm_rm_cfg[0].app_id; j++)
+            {
+                if(((p_bta_dm_rm_cfg[j].app_id == app_id) || (p_bta_dm_rm_cfg[j].app_id == BTA_ALL_APP_ID))
+                    && (p_bta_dm_rm_cfg[j].id == id))
+                {
+                    role = p_bta_dm_rm_cfg[j].cfg;
+
+                    if(role > p_dev->pref_role )
+                        p_dev->pref_role = role;
+                    break;
+                }
+            }
+        }
+    }
+
+    if((BTA_ID_AV == id)||(BTA_ID_AVK ==id))
+    {
+        if( status == BTA_SYS_CONN_BUSY)
+        {
+            if(p_dev)
+                p_dev->info |= BTA_DM_DI_AV_ACTIVE;
+            /* AV calls bta_sys_conn_open with the A2DP stream count as app_id */
+            if(BTA_ID_AV == id)
+                bta_dm_cb.cur_av_count = bta_dm_get_av_count();
+        }
+        else if( status == BTA_SYS_CONN_IDLE)
+        {
+            if(p_dev)
+                p_dev->info &= ~BTA_DM_DI_AV_ACTIVE;
+
+            /* get cur_av_count from connected services */
+            if(BTA_ID_AV == id)
+                bta_dm_cb.cur_av_count = bta_dm_get_av_count();
+        }
+        APPL_TRACE_WARNING("bta_dm_rm_cback:%d, status:%d", bta_dm_cb.cur_av_count, status);
+    }
+
+    /* Don't adjust roles for each busy/idle state transition to avoid
+       excessive switch requests when individual profile busy/idle status
+       changes */
+    if ((status != BTA_SYS_CONN_BUSY) && (status != BTA_SYS_CONN_IDLE))
+        bta_dm_adjust_roles(FALSE);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_delay_role_switch_cback
+**
+** Description      Callback from btm to delay a role switch
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_delay_role_switch_cback(TIMER_LIST_ENT *p_tle)
+{
+    UNUSED(p_tle);
+    APPL_TRACE_EVENT("bta_dm_delay_role_switch_cback: initiating Delayed RS");
+    bta_dm_adjust_roles (FALSE);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_remove_sec_dev_entry
+**
+** Description      Removes device entry from Security device DB if ACL connection with
+**                  remtoe device does not exist, else schedule for dev entry removal upon
+                     ACL close
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr)
+{
+    UINT16 index = 0;
+    if ( BTM_IsAclConnectionUp(remote_bd_addr, BT_TRANSPORT_LE) ||
+         BTM_IsAclConnectionUp(remote_bd_addr, BT_TRANSPORT_BR_EDR))
+    {
+         APPL_TRACE_DEBUG("%s ACL is not down. Schedule for  Dev Removal when ACL closes",
+                            __FUNCTION__);
+        for (index = 0; index < bta_dm_cb.device_list.count; index ++)
+        {
+            if (!bdcmp( bta_dm_cb.device_list.peer_device[index].peer_bdaddr, remote_bd_addr))
+                break;
+        }
+        if (index != bta_dm_cb.device_list.count)
+        {
+            bta_dm_cb.device_list.peer_device[index].remove_dev_pending = TRUE;
+        }
+        else
+        {
+            APPL_TRACE_ERROR(" %s Device does not exist in DB", __FUNCTION__);
+        }
+    }
+    else
+    {
+        BTM_SecDeleteDevice (remote_bd_addr);
+#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
+        /* need to remove all pending background connection */
+        BTA_GATTC_CancelOpen(0, remote_bd_addr, FALSE);
+        /* remove all cached GATT information */
+        BTA_GATTC_Refresh(remote_bd_addr);
+#endif
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_adjust_roles
+**
+** Description      Adjust roles
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_adjust_roles(BOOLEAN delay_role_switch)
+{
+
+    UINT8 i;
+    BOOLEAN set_master_role = FALSE;
+#if BLE_INCLUDED == TRUE
+    UINT8 br_count = bta_dm_cb.device_list.count - bta_dm_cb.device_list.le_count;
+#else
+    UINT8 br_count = bta_dm_cb.device_list.count;
+#endif
+    if (br_count)
+    {
+
+        /* the configuration is no scatternet
+         * or AV connection exists and there are more than one ACL link */
+        if ( (p_bta_dm_rm_cfg[0].cfg == BTA_DM_NO_SCATTERNET) ||
+             (bta_dm_cb.cur_av_count && br_count > 1) )
+        {
+
+            L2CA_SetDesireRole (HCI_ROLE_MASTER);
+            set_master_role = TRUE;
+
+        }
+
+        for(i=0; i<bta_dm_cb.device_list.count; i++)
+        {
+            if (bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_CONNECTED
+#if BLE_INCLUDED == TRUE
+                && bta_dm_cb.device_list.peer_device[i].transport == BT_TRANSPORT_BR_EDR
+#endif
+                )
+            {
+                if(!set_master_role && (bta_dm_cb.device_list.peer_device[i].pref_role != BTA_ANY_ROLE)
+                    && (p_bta_dm_rm_cfg[0].cfg == BTA_DM_PARTIAL_SCATTERNET))
+                {
+                    L2CA_SetDesireRole (HCI_ROLE_MASTER);
+                    set_master_role = TRUE;
+                }
+
+                if((bta_dm_cb.device_list.peer_device[i].pref_role == BTA_MASTER_ROLE_ONLY)
+                    || (br_count > 1))
+                {
+
+                /* Initiating immediate role switch with certain remote devices
+                  has caused issues due to role  switch colliding with link encryption setup and
+                  causing encryption (and in turn the link) to fail .  These device . Firmware
+                  versions are stored in a blacklist and role switch with these devices are
+                  delayed to avoid the collision with link encryption setup */
+
+                    if (bta_dm_cb.device_list.peer_device[i].pref_role != BTA_SLAVE_ROLE_ONLY &&
+                            delay_role_switch == FALSE)
+                    {
+                        BTM_SwitchRole (bta_dm_cb.device_list.peer_device[i].peer_bdaddr,
+                                        HCI_ROLE_MASTER, NULL);
+                    }
+                    else
+                    {
+                        bta_dm_cb.switch_delay_timer.p_cback =
+                            (TIMER_CBACK*)&bta_dm_delay_role_switch_cback;
+                        bta_sys_start_timer(&bta_dm_cb.switch_delay_timer, 0, 500);
+                    }
+                }
+
+            }
+        }
+
+
+        if(!set_master_role)
+        {
+
+            L2CA_SetDesireRole (L2CAP_DESIRED_LINK_ROLE);
+
+        }
+
+    }
+    else
+    {
+        L2CA_SetDesireRole (L2CAP_DESIRED_LINK_ROLE);
+    }
+
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_get_remname
+**
+** Description      Returns a pointer to the remote name stored in the DM control
+**                  block if it exists, or from the BTM memory.
+**
+** Returns          char * - Pointer to the remote device name
+*******************************************************************************/
+static char *bta_dm_get_remname(void)
+{
+    char *p_name = (char *)bta_dm_search_cb.peer_name;
+    char *p_temp;
+
+    /* If the name isn't already stored, try retrieving from BTM */
+    if (*p_name == '\0')
+        if ((p_temp = BTM_SecReadDevName(bta_dm_search_cb.peer_bdaddr)) != NULL)
+            p_name = p_temp;
+
+    return p_name;
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_bond_cancel_complete_cback
+**
+** Description      Authentication complete callback from BTM
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_bond_cancel_complete_cback(tBTM_STATUS result)
+{
+
+    tBTA_DM_SEC sec_event;
+
+    if (result == BTM_SUCCESS)
+        sec_event.bond_cancel_cmpl.result = BTA_SUCCESS;
+    else
+        sec_event.bond_cancel_cmpl.result = BTA_FAILURE;
+
+    if(bta_dm_cb.p_sec_cback)
+    {
+        bta_dm_cb.p_sec_cback(BTA_DM_BOND_CANCEL_CMPL_EVT, &sec_event);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_set_eir
+**
+** Description      This function creates EIR tagged data and writes it to controller.
+**
+** Returns          None
+**
+*******************************************************************************/
+static void bta_dm_set_eir (char *local_name)
+{
+    BT_HDR   *p_buf;
+    UINT8    *p;
+    UINT8    *p_length;
+#if (BTA_EIR_CANNED_UUID_LIST != TRUE)
+    UINT8    *p_type;
+    UINT8    max_num_uuid;
+#if (BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+    UINT8    custom_uuid_idx;
+#endif  // BTA_EIR_SERVER_NUM_CUSTOM_UUID
+#endif  // BTA_EIR_CANNED_UUID_LIST
+#if (BTM_EIR_DEFAULT_FEC_REQUIRED == FALSE)
+    UINT8    free_eir_length = HCI_EXT_INQ_RESPONSE_LEN;
+#else  // BTM_EIR_DEFAULT_FEC_REQUIRED
+    UINT8    free_eir_length = HCI_DM5_PACKET_SIZE;
+#endif  // BTM_EIR_DEFAULT_FEC_REQUIRED
+    UINT8    num_uuid;
+    UINT8    data_type;
+    UINT8    local_name_len;
+
+    /* wait until complete to disable */
+    if (bta_dm_cb.disable_timer.in_use)
+        return;
+
+#if ( BTA_EIR_CANNED_UUID_LIST != TRUE )
+    /* wait until App is ready */
+    if (bta_dm_cb.app_ready_timer.in_use)
+        return;
+
+    /* if local name is not provided, get it from controller */
+    if( local_name == NULL )
+    {
+        if( BTM_ReadLocalDeviceName( &local_name ) != BTM_SUCCESS )
+        {
+            APPL_TRACE_ERROR("Fail to read local device name for EIR");
+        }
+    }
+#endif  // BTA_EIR_CANNED_UUID_LIST
+
+    /* Allocate a buffer to hold HCI command */
+    if ((p_buf = (BT_HDR *)GKI_getpoolbuf(BTM_CMD_POOL_ID)) == NULL)
+    {
+        APPL_TRACE_ERROR("bta_dm_set_eir couldn't allocate buffer");
+        return;
+    }
+    p = (UINT8 *)p_buf + BTM_HCI_EIR_OFFSET;
+
+    memset(p, 0x00, HCI_EXT_INQ_RESPONSE_LEN );
+
+    APPL_TRACE_DEBUG("BTA is generating EIR");
+
+    if( local_name )
+        local_name_len = strlen( local_name );
+    else
+        local_name_len = 0;
+
+    data_type = BTM_EIR_COMPLETE_LOCAL_NAME_TYPE;
+    /* if local name is longer than minimum length of shortened name */
+    /* check whether it needs to be shortened or not */
+    if( local_name_len > p_bta_dm_eir_cfg->bta_dm_eir_min_name_len )
+    {
+        /* get number of UUID 16-bit list */
+#if (BTA_EIR_CANNED_UUID_LIST == TRUE)
+        num_uuid = p_bta_dm_eir_cfg->bta_dm_eir_uuid16_len/LEN_UUID_16;
+#else  // BTA_EIR_CANNED_UUID_LIST
+        max_num_uuid = (free_eir_length - 2)/LEN_UUID_16;
+        data_type = BTM_GetEirSupportedServices( bta_dm_cb.eir_uuid, &p,
+                                                 max_num_uuid, &num_uuid );
+        p = (UINT8 *)p_buf + BTM_HCI_EIR_OFFSET; /* reset p */
+#endif  // BTA_EIR_CANNED_UUID_LIST
+
+        /* if UUID doesn't fit remaing space, shorten local name */
+        if ( local_name_len > (free_eir_length - 4 - num_uuid*LEN_UUID_16))
+        {
+            APPL_TRACE_WARNING("BTA EIR: local name is shortened");
+            local_name_len = p_bta_dm_eir_cfg->bta_dm_eir_min_name_len;
+            data_type = BTM_EIR_SHORTENED_LOCAL_NAME_TYPE;
+        }
+        else
+            data_type = BTM_EIR_COMPLETE_LOCAL_NAME_TYPE;
+    }
+
+    UINT8_TO_STREAM(p, local_name_len + 1);
+    UINT8_TO_STREAM(p, data_type);
+
+    if (local_name != NULL)
+    {
+        memcpy(p, local_name, local_name_len);
+        p += local_name_len;
+    }
+    free_eir_length -= local_name_len + 2;
+
+#if (BTA_EIR_CANNED_UUID_LIST == TRUE)
+    /* if UUID list is provided as static data in configuration */
+    if(( p_bta_dm_eir_cfg->bta_dm_eir_uuid16_len > 0 )
+        &&(p_bta_dm_eir_cfg->bta_dm_eir_uuid16))
+    {
+        if( free_eir_length > LEN_UUID_16 + 2)
+        {
+            free_eir_length -= 2;
+
+            if( free_eir_length >= p_bta_dm_eir_cfg->bta_dm_eir_uuid16_len)
+            {
+                num_uuid = p_bta_dm_eir_cfg->bta_dm_eir_uuid16_len / LEN_UUID_16;
+                data_type = BTM_EIR_COMPLETE_16BITS_UUID_TYPE;
+            }
+            else /* not enough room for all UUIDs */
+            {
+                APPL_TRACE_WARNING("BTA EIR: UUID 16-bit list is truncated");
+                num_uuid = free_eir_length / LEN_UUID_16;
+                data_type = BTM_EIR_MORE_16BITS_UUID_TYPE;
+            }
+            UINT8_TO_STREAM(p, num_uuid * LEN_UUID_16 + 1);
+            UINT8_TO_STREAM(p, data_type);
+            memcpy(p, p_bta_dm_eir_cfg->bta_dm_eir_uuid16, num_uuid * LEN_UUID_16 );
+            p += num_uuid * LEN_UUID_16;
+            free_eir_length -= num_uuid * LEN_UUID_16;
+        }
+    }
+#else /* (BTA_EIR_CANNED_UUID_LIST == TRUE) */
+    /* if UUID list is dynamic */
+    if ( free_eir_length >= 2)
+    {
+        p_length = p++;
+        p_type   = p++;
+        num_uuid = 0;
+
+        max_num_uuid = (free_eir_length - 2)/LEN_UUID_16;
+        data_type = BTM_GetEirSupportedServices( bta_dm_cb.eir_uuid, &p, max_num_uuid, &num_uuid );
+
+        if( data_type == BTM_EIR_MORE_16BITS_UUID_TYPE )
+        {
+            APPL_TRACE_WARNING("BTA EIR: UUID 16-bit list is truncated");
+        }
+#if (BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+        else
+        {
+            for (custom_uuid_idx = 0; custom_uuid_idx < BTA_EIR_SERVER_NUM_CUSTOM_UUID; custom_uuid_idx++)
+            {
+                if (bta_dm_cb.custom_uuid[custom_uuid_idx].len == LEN_UUID_16)
+                {
+                    if ( num_uuid < max_num_uuid )
+                    {
+                        UINT16_TO_STREAM(p, bta_dm_cb.custom_uuid[custom_uuid_idx].uu.uuid16);
+                        num_uuid++;
+                    }
+                    else
+                    {
+                        data_type = BTM_EIR_MORE_16BITS_UUID_TYPE;
+                        APPL_TRACE_WARNING("BTA EIR: UUID 16-bit list is truncated");
+                        break;
+                    }
+                }
+            }
+        }
+#endif /* (BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0) */
+
+        UINT8_TO_STREAM(p_length, num_uuid * LEN_UUID_16 + 1);
+        UINT8_TO_STREAM(p_type, data_type);
+        free_eir_length -= num_uuid * LEN_UUID_16 + 2;
+    }
+#endif /* (BTA_EIR_CANNED_UUID_LIST == TRUE) */
+
+#if ( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+    /* Adding 32-bit UUID list */
+    if ( free_eir_length >= 2)
+    {
+        p_length = p++;
+        p_type   = p++;
+        num_uuid = 0;
+        data_type = BTM_EIR_COMPLETE_32BITS_UUID_TYPE;
+
+        max_num_uuid = (free_eir_length - 2)/LEN_UUID_32;
+
+        for (custom_uuid_idx = 0; custom_uuid_idx < BTA_EIR_SERVER_NUM_CUSTOM_UUID; custom_uuid_idx++)
+        {
+            if (bta_dm_cb.custom_uuid[custom_uuid_idx].len == LEN_UUID_32)
+            {
+                if ( num_uuid < max_num_uuid )
+                {
+                    UINT32_TO_STREAM(p, bta_dm_cb.custom_uuid[custom_uuid_idx].uu.uuid32);
+                    num_uuid++;
+                }
+                else
+                {
+                    data_type = BTM_EIR_MORE_32BITS_UUID_TYPE;
+                    APPL_TRACE_WARNING("BTA EIR: UUID 32-bit list is truncated");
+                    break;
+                }
+            }
+        }
+
+        UINT8_TO_STREAM(p_length, num_uuid * LEN_UUID_32 + 1);
+        UINT8_TO_STREAM(p_type, data_type);
+        free_eir_length -= num_uuid * LEN_UUID_32 + 2;
+    }
+
+    /* Adding 128-bit UUID list */
+    if ( free_eir_length >= 2)
+    {
+        p_length = p++;
+        p_type   = p++;
+        num_uuid = 0;
+        data_type = BTM_EIR_COMPLETE_128BITS_UUID_TYPE;
+
+        max_num_uuid = (free_eir_length - 2)/LEN_UUID_128;
+
+        for (custom_uuid_idx = 0; custom_uuid_idx < BTA_EIR_SERVER_NUM_CUSTOM_UUID; custom_uuid_idx++)
+        {
+            if (bta_dm_cb.custom_uuid[custom_uuid_idx].len == LEN_UUID_128)
+            {
+                if ( num_uuid < max_num_uuid )
+                {
+                    ARRAY16_TO_STREAM(p, bta_dm_cb.custom_uuid[custom_uuid_idx].uu.uuid128);
+                    num_uuid++;
+                }
+                else
+                {
+                    data_type = BTM_EIR_MORE_128BITS_UUID_TYPE;
+                    APPL_TRACE_WARNING("BTA EIR: UUID 128-bit list is truncated");
+                    break;
+                }
+            }
+        }
+
+        UINT8_TO_STREAM(p_length, num_uuid * LEN_UUID_128 + 1);
+        UINT8_TO_STREAM(p_type, data_type);
+        free_eir_length -= num_uuid * LEN_UUID_128 + 2;
+    }
+#endif /* ( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0) */
+
+    /* if Flags are provided in configuration */
+    if(( p_bta_dm_eir_cfg->bta_dm_eir_flag_len > 0 )
+     &&( p_bta_dm_eir_cfg->bta_dm_eir_flags )
+     &&( free_eir_length >= p_bta_dm_eir_cfg->bta_dm_eir_flag_len + 2 ))
+    {
+        UINT8_TO_STREAM(p, p_bta_dm_eir_cfg->bta_dm_eir_flag_len + 1);
+        UINT8_TO_STREAM(p, BTM_EIR_FLAGS_TYPE);
+        memcpy(p, p_bta_dm_eir_cfg->bta_dm_eir_flags,
+               p_bta_dm_eir_cfg->bta_dm_eir_flag_len);
+        p += p_bta_dm_eir_cfg->bta_dm_eir_flag_len;
+        free_eir_length -= p_bta_dm_eir_cfg->bta_dm_eir_flag_len + 2;
+    }
+
+    /* if Manufacturer Specific are provided in configuration */
+    if(( p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec_len > 0 )
+     &&( p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec )
+     &&( free_eir_length >= p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec_len + 2 ))
+    {
+        p_length = p;
+
+        UINT8_TO_STREAM(p, p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec_len + 1);
+        UINT8_TO_STREAM(p, BTM_EIR_MANUFACTURER_SPECIFIC_TYPE);
+        memcpy(p, p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec,
+               p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec_len);
+        p += p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec_len;
+        free_eir_length -= p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec_len + 2;
+
+    }
+    else
+    {
+        p_length = NULL;
+    }
+
+    /* if Inquiry Tx Resp Power compiled */
+    if ((p_bta_dm_eir_cfg->bta_dm_eir_inq_tx_power) &&
+        (free_eir_length >= 3))
+    {
+        UINT8_TO_STREAM(p, 2);      /* Length field */
+        UINT8_TO_STREAM(p, BTM_EIR_TX_POWER_LEVEL_TYPE);
+        UINT8_TO_STREAM(p, *(p_bta_dm_eir_cfg->bta_dm_eir_inq_tx_power));
+        free_eir_length -= 3;
+    }
+
+    if( free_eir_length )
+        UINT8_TO_STREAM(p, 0); /* terminator of significant part */
+
+    BTM_WriteEIR( p_buf );
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_eir_search_services
+**
+** Description      This function searches services in received EIR
+**
+** Returns          None
+**
+*******************************************************************************/
+static void bta_dm_eir_search_services( tBTM_INQ_RESULTS  *p_result,
+                                        tBTA_SERVICE_MASK *p_services_to_search,
+                                        tBTA_SERVICE_MASK *p_services_found)
+{
+    tBTA_SERVICE_MASK       service_index = 0;
+    tBTM_EIR_SEARCH_RESULT  result;
+
+    APPL_TRACE_DEBUG("BTA searching services in EIR of BDA:0x%02X%02X%02X%02X%02X%02X",
+                        p_result->remote_bd_addr[0],p_result->remote_bd_addr[1],
+                        p_result->remote_bd_addr[2],p_result->remote_bd_addr[3],
+                        p_result->remote_bd_addr[4],p_result->remote_bd_addr[5]);
+
+    APPL_TRACE_DEBUG("    with services_to_search=0x%08X", *p_services_to_search);
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    /* always do GATT based service discovery by SDP instead of from EIR    */
+    /* if GATT based service is also to be put in EIR, need to modify this  */
+    while (service_index < (BTA_MAX_SERVICE_ID - 1))
+#else
+    while(service_index < BTA_MAX_SERVICE_ID)
+#endif
+    {
+        if( *p_services_to_search
+           & (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(service_index)))
+        {
+            result = BTM_HasInquiryEirService( p_result,
+                                               bta_service_id_to_uuid_lkup_tbl[service_index] );
+
+            /* Searching for HSP v1.2 only device */
+            if ((result != BTM_EIR_FOUND) &&
+                (bta_service_id_to_uuid_lkup_tbl[service_index] == UUID_SERVCLASS_HEADSET))
+            {
+                result = BTM_HasInquiryEirService (p_result, UUID_SERVCLASS_HEADSET_HS);
+            }
+
+            if( result == BTM_EIR_FOUND )
+            {
+                /* If Plug and Play service record, need to check to see if Broadcom stack */
+                /* However, EIR data doesn't have EXT_BRCM_VERSION so just skip it */
+                if( bta_service_id_to_uuid_lkup_tbl[service_index]
+                    != UUID_SERVCLASS_PNP_INFORMATION )
+                {
+
+                    *p_services_found |=
+                       (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(service_index));
+                    /* remove the service from services to be searched  */
+                    *p_services_to_search &=
+                       (tBTA_SERVICE_MASK)(~(BTA_SERVICE_ID_TO_SERVICE_MASK(service_index)));
+                }
+            }
+            else if( result == BTM_EIR_NOT_FOUND )
+            {
+                /* remove the service from services to be searched  */
+                *p_services_to_search &=
+                       (tBTA_SERVICE_MASK)(~(BTA_SERVICE_ID_TO_SERVICE_MASK(service_index)));
+            }
+        }
+
+        service_index++;
+    }
+
+    APPL_TRACE_ERROR("BTA EIR search result, services_to_search=0x%08X, services_found=0x%08X",
+                        *p_services_to_search, *p_services_found);
+}
+
+#if (BTA_EIR_CANNED_UUID_LIST != TRUE)
+/*******************************************************************************
+**
+** Function         bta_dm_eir_update_uuid
+**
+** Description      This function adds or removes service UUID in EIR database.
+**
+** Returns          None
+**
+*******************************************************************************/
+void bta_dm_eir_update_uuid(UINT16 uuid16, BOOLEAN adding)
+{
+    /* if this UUID is not advertised in EIR */
+    if( !BTM_HasEirService( p_bta_dm_eir_cfg->uuid_mask, uuid16 ))
+        return;
+
+    if( adding )
+    {
+        APPL_TRACE_EVENT("Adding UUID=0x%04X into EIR", uuid16);
+
+        BTM_AddEirService( bta_dm_cb.eir_uuid, uuid16 );
+    }
+    else
+    {
+        APPL_TRACE_EVENT("Removing UUID=0x%04X from EIR", uuid16);
+
+        BTM_RemoveEirService( bta_dm_cb.eir_uuid, uuid16 );
+    }
+
+    bta_dm_set_eir (NULL);
+
+    APPL_TRACE_EVENT("bta_dm_eir_update_uuid UUID bit mask=0x%08X %08X",
+                       bta_dm_cb.eir_uuid[1], bta_dm_cb.eir_uuid[0] );
+}
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_dm_enable_test_mode
+**
+** Description      enable test mode
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_enable_test_mode(tBTA_DM_MSG *p_data)
+{
+    UNUSED(p_data);
+    BTM_EnableTestMode();
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_disable_test_mode
+**
+** Description      disable test mode
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_disable_test_mode(tBTA_DM_MSG *p_data)
+{
+    UNUSED(p_data);
+    BTM_DeviceReset(NULL);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_execute_callback
+**
+** Description      Just execute a generic call back in the context of the BTU/BTA tack
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_execute_callback(tBTA_DM_MSG *p_data)
+{
+    /* sanity check */
+    if(p_data->exec_cback.p_exec_cback == NULL)
+    {
+        return;
+    }
+
+    p_data->exec_cback.p_exec_cback(p_data->exec_cback.p_param);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_encrypt_cback
+**
+** Description      link encryption complete callback.
+**
+** Returns         None
+**
+*******************************************************************************/
+void bta_dm_encrypt_cback(BD_ADDR bd_addr, tBT_TRANSPORT transport, void *p_ref_data, tBTM_STATUS result)
+{
+    tBTA_STATUS   bta_status = BTA_SUCCESS;
+    tBTA_DM_ENCRYPT_CBACK *p_callback = NULL;
+    UINT8   i ;
+    UNUSED(p_ref_data);
+
+    for (i=0; i<bta_dm_cb.device_list.count; i++)
+    {
+        if (bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, bd_addr) == 0 &&
+            bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_CONNECTED)
+            break;
+    }
+
+    if (i < bta_dm_cb.device_list.count)
+    {
+        p_callback = bta_dm_cb.device_list.peer_device[i].p_encrypt_cback;
+        bta_dm_cb.device_list.peer_device[i].p_encrypt_cback = NULL;
+    }
+
+    switch (result)
+    {
+        case BTM_SUCCESS:
+            break;
+        case BTM_WRONG_MODE:
+            bta_status = BTA_WRONG_MODE;
+            break;
+        case BTM_NO_RESOURCES:
+            bta_status = BTA_NO_RESOURCES;
+            break;
+        case BTM_BUSY:
+            bta_status = BTA_BUSY;
+            break;
+        default:
+            bta_status = BTA_FAILURE;
+            break;
+    }
+
+    APPL_TRACE_DEBUG("bta_dm_encrypt_cback status =%d p_callback=0x%x", bta_status, p_callback);
+
+    if (p_callback)
+    {
+        (*p_callback)(bd_addr, transport, bta_status);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_set_encryption
+**
+** Description      This function to encrypt the link
+**
+** Returns          None
+**
+*******************************************************************************/
+void bta_dm_set_encryption (tBTA_DM_MSG *p_data)
+{
+    UINT8 i ;
+
+    APPL_TRACE_DEBUG("bta_dm_set_encryption"); //todo
+    if (!p_data->set_encryption.p_callback)
+    {
+        APPL_TRACE_ERROR("bta_dm_set_encryption callback is not provided");
+        return;
+    }
+    for (i=0; i<bta_dm_cb.device_list.count; i++)
+    {
+        if (bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, p_data->set_encryption.bd_addr) == 0 &&
+            bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_CONNECTED)
+            break;
+    }
+    if (i < bta_dm_cb.device_list.count)
+    {
+        if (bta_dm_cb.device_list.peer_device[i].p_encrypt_cback)
+        {
+            APPL_TRACE_ERROR("earlier enc was not done for same device");
+            (*p_data->set_encryption.p_callback)(p_data->set_encryption.bd_addr,
+                                             p_data->set_encryption.transport,
+                                             BTA_BUSY);
+            return;
+        }
+
+        if (BTM_SetEncryption(p_data->set_encryption.bd_addr, p_data->set_encryption.transport,
+                                           bta_dm_encrypt_cback, &p_data->set_encryption.sec_act)
+                              == BTM_CMD_STARTED)
+        {
+            bta_dm_cb.device_list.peer_device[i].p_encrypt_cback = p_data->set_encryption.p_callback;
+        }
+    }
+}
+
+#if (BLE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         bta_dm_observe_results_cb
+**
+** Description      Callback for BLE Observe result
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_observe_results_cb (tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir)
+{
+;
+    tBTA_DM_SEARCH     result;
+    tBTM_INQ_INFO      *p_inq_info;
+    APPL_TRACE_DEBUG("bta_dm_observe_results_cb")
+
+    bdcpy(result.inq_res.bd_addr, p_inq->remote_bd_addr);
+    result.inq_res.rssi = p_inq->rssi;
+    result.inq_res.ble_addr_type    = p_inq->ble_addr_type;
+    result.inq_res.inq_result_type  = p_inq->inq_result_type;
+    result.inq_res.device_type      = p_inq->device_type;
+    result.inq_res.flag             = p_inq->flag;
+
+    /* application will parse EIR to find out remote device name */
+    result.inq_res.p_eir = p_eir;
+
+    if((p_inq_info = BTM_InqDbRead(p_inq->remote_bd_addr)) != NULL)
+    {
+        /* initialize remt_name_not_required to FALSE so that we get the name by default */
+        result.inq_res.remt_name_not_required = FALSE;
+    }
+
+    if(bta_dm_search_cb.p_scan_cback)
+        bta_dm_search_cb.p_scan_cback(BTA_DM_INQ_RES_EVT, &result);
+
+    if(p_inq_info)
+    {
+        /* application indicates if it knows the remote name, inside the callback
+         copy that to the inquiry data base*/
+        if(result.inq_res.remt_name_not_required)
+            p_inq_info->appl_knows_rem_name = TRUE;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_observe_cmpl_cb
+**
+** Description      Callback for BLE Observe complete
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_observe_cmpl_cb (void * p_result)
+{
+    tBTA_DM_SEARCH  data;
+
+    APPL_TRACE_DEBUG("bta_dm_observe_cmpl_cb");
+
+    data.inq_cmpl.num_resps = ((tBTM_INQUIRY_CMPL *)p_result)->num_resp;
+    if (bta_dm_search_cb.p_scan_cback)
+    {
+        bta_dm_search_cb.p_scan_cback(BTA_DM_INQ_CMPL_EVT, &data);
+    }
+}
+
+#if (SMP_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         bta_dm_ble_smp_cback
+**
+** Description      Callback for BLE SMP
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_DATA *p_data)
+{
+    tBTM_STATUS status = BTM_SUCCESS;
+    tBTA_DM_SEC sec_event;
+    char *p_name = NULL;
+    UINT8 i;
+    tBT_DEVICE_TYPE dev_type;
+
+    if (!bta_dm_cb.p_sec_cback)
+        return BTM_NOT_AUTHORIZED;
+
+    memset(&sec_event, 0, sizeof(tBTA_DM_SEC));
+    switch (event)
+    {
+        case BTM_LE_IO_REQ_EVT:
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+
+            bta_dm_co_ble_io_req(bda,
+                                 &p_data->io_req.io_cap,
+                                 &p_data->io_req.oob_data,
+                                 &p_data->io_req.auth_req,
+                                 &p_data->io_req.max_key_size,
+                                 &p_data->io_req.init_keys,
+                                 &p_data->io_req.resp_keys);
+#endif
+#if BTM_OOB_INCLUDED == FALSE
+            status = BTM_SUCCESS;
+#endif
+            APPL_TRACE_EVENT("io mitm: %d oob_data:%d\n", p_data->io_req.auth_req, p_data->io_req.oob_data);
+
+            break;
+
+        case BTM_LE_SEC_REQUEST_EVT:
+            bdcpy(sec_event.ble_req.bd_addr, bda);
+            p_name = BTM_SecReadDevName(bda);
+            if (p_name != NULL)
+            {
+                BCM_STRNCPY_S((char*)sec_event.ble_req.bd_name,
+                               sizeof(BD_NAME), p_name, (BD_NAME_LEN));
+            }
+            else
+            {
+                sec_event.ble_req.bd_name[0] = 0;
+            }
+            sec_event.ble_req.bd_name[BD_NAME_LEN] = 0;
+            bta_dm_cb.p_sec_cback(BTA_DM_BLE_SEC_REQ_EVT, &sec_event);
+            break;
+
+        case BTM_LE_KEY_NOTIF_EVT:
+            bdcpy(sec_event.key_notif.bd_addr, bda);
+            p_name = BTM_SecReadDevName(bda);
+            if (p_name != NULL)
+            {
+                BCM_STRNCPY_S((char*)sec_event.key_notif.bd_name,
+                               sizeof(BD_NAME), p_name, (BD_NAME_LEN));
+            }
+            else
+            {
+                sec_event.key_notif.bd_name[0] = 0;
+            }
+            sec_event.ble_req.bd_name[BD_NAME_LEN] = 0;
+            sec_event.key_notif.passkey = p_data->key_notif;
+            bta_dm_cb.p_sec_cback(BTA_DM_BLE_PASSKEY_NOTIF_EVT, &sec_event);
+            break;
+
+        case BTM_LE_KEY_REQ_EVT:
+            bdcpy(sec_event.ble_req.bd_addr, bda);
+            bta_dm_cb.p_sec_cback(BTA_DM_BLE_PASSKEY_REQ_EVT, &sec_event);
+            break;
+
+        case BTM_LE_OOB_REQ_EVT:
+            bdcpy(sec_event.ble_req.bd_addr, bda);
+            bta_dm_cb.p_sec_cback(BTA_DM_BLE_OOB_REQ_EVT, &sec_event);
+            break;
+
+        case BTM_LE_NC_REQ_EVT:
+            bdcpy(sec_event.key_notif.bd_addr, bda);
+            BCM_STRNCPY_S((char*)sec_event.key_notif.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN));
+            sec_event.ble_req.bd_name[BD_NAME_LEN] = 0;
+            sec_event.key_notif.passkey = p_data->key_notif;
+            bta_dm_cb.p_sec_cback(BTA_DM_BLE_NC_REQ_EVT, &sec_event);
+            break;
+
+        case BTM_LE_KEY_EVT:
+            bdcpy(sec_event.ble_key.bd_addr, bda);
+            sec_event.ble_key.key_type = p_data->key.key_type;
+            sec_event.ble_key.p_key_value = p_data->key.p_key_value;
+            bta_dm_cb.p_sec_cback(BTA_DM_BLE_KEY_EVT, &sec_event);
+            break;
+
+        case BTM_LE_COMPLT_EVT:
+            bdcpy(sec_event.auth_cmpl.bd_addr, bda);
+#if BLE_INCLUDED == TRUE
+            BTM_ReadDevInfo(bda, &sec_event.auth_cmpl.dev_type, &sec_event.auth_cmpl.addr_type);
+#endif
+            p_name = BTM_SecReadDevName(bda);
+            if (p_name != NULL)
+            {
+                BCM_STRNCPY_S((char*)sec_event.auth_cmpl.bd_name,
+                               sizeof(BD_NAME), p_name, (BD_NAME_LEN));
+            }
+            else
+            {
+                sec_event.auth_cmpl.bd_name[0] = 0;
+            }
+            if (p_data->complt.reason != 0)
+            {
+                sec_event.auth_cmpl.fail_reason = BTA_DM_AUTH_CONVERT_SMP_CODE(((UINT8)p_data->complt.reason));
+                /* delete this device entry from Sec Dev DB */
+                bta_dm_remove_sec_dev_entry (bda);
+            }
+            else
+            {
+                sec_event.auth_cmpl.success = TRUE;
+                if (!p_data->complt.smp_over_br)
+                    GATT_ConfigServiceChangeCCC(bda, TRUE, BT_TRANSPORT_LE);
+            }
+
+            if (bta_dm_cb.p_sec_cback)
+            {
+                //bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
+                bta_dm_cb.p_sec_cback(BTA_DM_BLE_AUTH_CMPL_EVT, &sec_event);
+            }
+
+            break;
+
+        default:
+            status = BTM_NOT_AUTHORIZED;
+            break;
+    }
+    return status;
+}
+#endif  /* SMP_INCLUDED == TRUE */
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_id_key_cback
+**
+** Description      Callback for BLE local ID keys
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_ble_id_key_cback (UINT8 key_type, tBTM_BLE_LOCAL_KEYS *p_key)
+{
+    UINT8   evt;
+    tBTA_DM_SEC dm_key;
+
+    switch (key_type)
+    {
+        case BTM_BLE_KEY_TYPE_ID:
+        case BTM_BLE_KEY_TYPE_ER:
+            if (bta_dm_cb.p_sec_cback)
+            {
+                memcpy(&dm_key.ble_id_keys, p_key, sizeof(tBTM_BLE_LOCAL_KEYS));
+
+                evt = (key_type == BTM_BLE_KEY_TYPE_ID) ? BTA_DM_BLE_LOCAL_IR_EVT :\
+                      BTA_DM_BLE_LOCAL_ER_EVT;
+                bta_dm_cb.p_sec_cback(evt, &dm_key);
+            }
+            break;
+
+        default:
+            APPL_TRACE_DEBUG("Unknown key type %d", key_type);
+            break;
+    }
+    return;
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_add_blekey
+**
+** Description      This function adds an BLE Key to an security database entry.
+**                  This function shall only be called AFTER BTA_DmAddBleDevice has been called.
+**                  It is normally called during host startup to restore all required information
+**                  stored in the NVRAM.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_add_blekey (tBTA_DM_MSG *p_data)
+{
+    if (!BTM_SecAddBleKey (p_data->add_ble_key.bd_addr,
+                           (tBTM_LE_KEY_VALUE *)&p_data->add_ble_key.blekey,
+                           p_data->add_ble_key.key_type))
+    {
+        APPL_TRACE_ERROR ("BTA_DM: Error adding BLE Key for device %08x%04x",
+                           (p_data->add_ble_key.bd_addr[0]<<24)+(p_data->add_ble_key.bd_addr[1]<<16)+\
+                           (p_data->add_ble_key.bd_addr[2]<<8)+p_data->add_ble_key.bd_addr[3],
+                           (p_data->add_ble_key.bd_addr[4]<<8)+p_data->add_ble_key.bd_addr[5]);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_add_ble_device
+**
+** Description      This function adds an BLE device to an security database entry.
+**                  It is normally called during host startup to restore all required information
+**                  stored in the NVRAM.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_add_ble_device (tBTA_DM_MSG *p_data)
+{
+    if (!BTM_SecAddBleDevice (p_data->add_ble_device.bd_addr, NULL,
+                              p_data->add_ble_device.dev_type  ,
+                              p_data->add_ble_device.addr_type))
+    {
+        APPL_TRACE_ERROR ("BTA_DM: Error adding BLE Device for device %08x%04x",
+                           (p_data->add_ble_device.bd_addr[0]<<24)+(p_data->add_ble_device.bd_addr[1]<<16)+ \
+                           (p_data->add_ble_device.bd_addr[2]<<8)+p_data->add_ble_device.bd_addr[3],
+                           (p_data->add_ble_device.bd_addr[4]<<8)+p_data->add_ble_device.bd_addr[5]);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_add_ble_device
+**
+** Description      This function adds an BLE device to an security database entry.
+**                  It is normally called during host startup to restore all required information
+**                  stored in the NVRAM.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_passkey_reply (tBTA_DM_MSG *p_data)
+{
+    if (p_data->pin_reply.accept)
+    {
+        BTM_BlePasskeyReply(p_data->ble_passkey_reply.bd_addr, BTM_SUCCESS, p_data->ble_passkey_reply.passkey);
+    }
+    else
+    {
+        BTM_BlePasskeyReply(p_data->ble_passkey_reply.bd_addr, BTM_NOT_AUTHORIZED, p_data->ble_passkey_reply.passkey);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_confirm_reply
+**
+** Description      This is response to SM numeric comparison request submitted
+**                  to application.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_confirm_reply (tBTA_DM_MSG *p_data)
+{
+    if (p_data->confirm.accept)
+    {
+        BTM_BleConfirmReply(p_data->confirm.bd_addr, BTM_SUCCESS);
+    }
+    else
+    {
+        BTM_BleConfirmReply(p_data->ble_passkey_reply.bd_addr, BTM_NOT_AUTHORIZED);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_security_grant
+**
+** Description      This function grant SMP security request access.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_security_grant (tBTA_DM_MSG *p_data)
+{
+    BTM_SecurityGrant(p_data->ble_sec_grant.bd_addr, p_data->ble_sec_grant.res);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_set_bg_conn_type
+**
+** Description      This function set the BLE background connection type
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_set_bg_conn_type (tBTA_DM_MSG *p_data)
+{
+    BTM_BleSetBgConnType(p_data->ble_set_bd_conn_type.bg_conn_type,
+                         p_data->ble_set_bd_conn_type.p_select_cback);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_set_conn_params
+**
+** Description      This function set the preferred connection parameters.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_set_conn_params (tBTA_DM_MSG *p_data)
+{
+    BTM_BleSetPrefConnParams(p_data->ble_set_conn_params.peer_bda,
+                             p_data->ble_set_conn_params.conn_int_min,
+                             p_data->ble_set_conn_params.conn_int_max,
+                             p_data->ble_set_conn_params.slave_latency,
+                             p_data->ble_set_conn_params.supervision_tout);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_set_conn_scan_params
+**
+** Description      This function sets BLE scan parameters.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_set_scan_params(tBTA_DM_MSG *p_data)
+{
+    BTM_BleSetScanParams(p_data->ble_set_scan_params.client_if,
+                         p_data->ble_set_scan_params.scan_int,
+                         p_data->ble_set_scan_params.scan_window,
+                         p_data->ble_set_scan_params.scan_mode,
+                         p_data->ble_set_scan_params.scan_param_setup_cback);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_set_conn_scan_params
+**
+** Description      This function set the preferred connection scan parameters.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_set_conn_scan_params (tBTA_DM_MSG *p_data)
+{
+    BTM_BleSetConnScanParams(p_data->ble_set_conn_scan_params.scan_int,
+                             p_data->ble_set_conn_scan_params.scan_window);
+}
+/*******************************************************************************
+**
+** Function         bta_dm_ble_update_conn_params
+**
+** Description      This function update LE connection parameters.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_update_conn_params (tBTA_DM_MSG *p_data)
+{
+    if (!L2CA_UpdateBleConnParams(p_data->ble_update_conn_params.bd_addr,
+                                 p_data->ble_update_conn_params.min_int,
+                                 p_data->ble_update_conn_params.max_int,
+                                 p_data->ble_update_conn_params.latency,
+                                 p_data->ble_update_conn_params.timeout))
+    {
+        APPL_TRACE_ERROR("Update connection parameters failed!");
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_set_rand_address
+**
+** Description      This function set the LE random address for the device.
+**
+** Parameters:		rand_addr:the random address whitch should be setting
+** Explanation:		This function added by Yulong at 2016/9/9 
+*******************************************************************************/
+void bta_dm_ble_set_rand_address(tBTA_DM_MSG *p_data)
+{
+	UINT8 len = sizeof(p_data->set_addr);
+	if(len != BD_ADDR_LEN)
+	{
+		APPL_TRACE_ERROR("Invalid random adress");
+		return;
+	}
+	if(p_data->set_addr.addr_type != BLE_ADDR_RANDOM)
+	{
+		APPL_TRACE_ERROR("Invalid random adress type = %d\n",p_data->set_addr.addr_type);
+		return;
+	}
+	//send the setting random address to BTM layer
+	BTM_BleSetRandAddress(p_data->set_addr.address);
+	
+}
+
+#if BLE_PRIVACY_SPT == TRUE
+/*******************************************************************************
+**
+** Function         bta_dm_ble_config_local_privacy
+**
+** Description      This function set the local device LE privacy settings.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_config_local_privacy (tBTA_DM_MSG *p_data)
+{
+    BTM_BleConfigPrivacy (p_data->ble_local_privacy.privacy_enable);
+}
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_observe
+**
+** Description      This function set the preferred connection scan parameters.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_observe (tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS status;
+    if (p_data->ble_observe.start)
+    {
+        /*Save the  callback to be called when a scan results are available */
+        bta_dm_search_cb.p_scan_cback = p_data->ble_observe.p_cback;
+        if ((status = BTM_BleObserve(TRUE, p_data->ble_observe.duration,
+                            bta_dm_observe_results_cb, bta_dm_observe_cmpl_cb))!= BTM_CMD_STARTED)
+        {
+            tBTA_DM_SEARCH  data;
+            APPL_TRACE_WARNING(" %s BTM_BleObserve  failed. status %d",__FUNCTION__,status);
+            data.inq_cmpl.num_resps = 0;
+            if (bta_dm_search_cb.p_scan_cback)
+            {
+                bta_dm_search_cb.p_scan_cback(BTA_DM_INQ_CMPL_EVT, &data);
+            }
+        }
+    }
+    else
+    {
+        bta_dm_search_cb.p_scan_cback = NULL;
+        BTM_BleObserve(FALSE, 0, NULL,NULL );
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_dm_ble_set_adv_params
+**
+** Description      This function set the adv parameters.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_set_adv_params (tBTA_DM_MSG *p_data)
+{
+    BTM_BleSetAdvParams(p_data->ble_set_adv_params.adv_int_min,
+                        p_data->ble_set_adv_params.adv_int_max,
+                        p_data->ble_set_adv_params.p_dir_bda,
+                        BTA_DM_BLE_ADV_CHNL_MAP);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_set_adv_config
+**
+** Description      This function set the customized ADV data configuration
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_set_adv_config (tBTA_DM_MSG *p_data)
+{
+    tBTA_STATUS status = BTA_FAILURE;
+
+    if (BTM_BleWriteAdvData(p_data->ble_set_adv_data.data_mask,
+                        (tBTM_BLE_ADV_DATA *)p_data->ble_set_adv_data.p_adv_cfg) == BTM_SUCCESS)
+    {
+        status = BTA_SUCCESS;
+    }
+
+    if (p_data->ble_set_adv_data.p_adv_data_cback)
+        (*p_data->ble_set_adv_data.p_adv_data_cback)(status);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_set_scan_rsp
+**
+** Description      This function set the customized ADV scan resp. configuration
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_set_scan_rsp (tBTA_DM_MSG *p_data)
+{
+    tBTA_STATUS status = BTA_FAILURE;
+
+    if(BTM_BleWriteScanRsp(p_data->ble_set_adv_data.data_mask,
+                        (tBTM_BLE_ADV_DATA *)p_data->ble_set_adv_data.p_adv_cfg) == BTM_SUCCESS)
+    {
+        status = BTA_SUCCESS;
+    }
+
+    if (p_data->ble_set_adv_data.p_adv_data_cback)
+        (*p_data->ble_set_adv_data.p_adv_data_cback)(status);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_set_data_length
+**
+** Description      This function set the maximum transmission packet size
+**
+** Parameters
+**
+*******************************************************************************/
+void bta_dm_ble_set_data_length(tBTA_DM_MSG *p_data)
+{
+    if (BTM_SetBleDataLength(p_data->ble_set_data_length.remote_bda,
+                        p_data->ble_set_data_length.tx_data_length) != BTM_SUCCESS)
+    {
+        APPL_TRACE_ERROR("%s failed", __FUNCTION__);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_broadcast
+**
+** Description      Starts or stops LE broadcasts
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_broadcast (tBTA_DM_MSG *p_data)
+{
+    BTM_BleBroadcast(p_data->ble_observe.start);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_multi_adv_enb
+**
+** Description      This function enables a single advertising instance
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_multi_adv_enb(tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS btm_status = 0;
+
+    bta_dm_cb.p_multi_adv_cback = p_data->ble_multi_adv_enb.p_cback;
+    if(BTM_BleMaxMultiAdvInstanceCount() > 0 && NULL != p_data->ble_multi_adv_enb.p_ref)
+    {
+        btm_status = BTM_BleEnableAdvInstance((tBTM_BLE_ADV_PARAMS*)
+                                            p_data->ble_multi_adv_enb.p_params,
+                                            p_data->ble_multi_adv_enb.p_cback,
+                                            p_data->ble_multi_adv_enb.p_ref);
+    }
+
+    if(BTM_CMD_STARTED != btm_status)
+    {
+        bta_dm_cb.p_multi_adv_cback(BTA_BLE_MULTI_ADV_ENB_EVT, 0xFF,
+                                    p_data->ble_multi_adv_enb.p_ref, BTA_FAILURE);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_dm_ble_multi_adv_param_upd
+**
+** Description      This function updates multiple advertising instance parameters
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_multi_adv_upd_param(tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS btm_status = 0;
+    void *p_ref = NULL;
+
+    if(BTM_BleMaxMultiAdvInstanceCount() > 0 && p_data->ble_multi_adv_param.inst_id > 0
+        && p_data->ble_multi_adv_param.inst_id < BTM_BleMaxMultiAdvInstanceCount())
+    {
+        btm_status = BTM_BleUpdateAdvInstParam(p_data->ble_multi_adv_param.inst_id,
+                         (tBTM_BLE_ADV_PARAMS*)p_data->ble_multi_adv_param.p_params);
+    }
+
+    if(BTM_CMD_STARTED != btm_status)
+    {
+       p_ref = btm_ble_multi_adv_get_ref(p_data->ble_multi_adv_param.inst_id);
+       bta_dm_cb.p_multi_adv_cback(BTA_BLE_MULTI_ADV_PARAM_EVT,
+                                   p_data->ble_multi_adv_param.inst_id, p_ref, BTA_FAILURE);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_dm_ble_multi_adv_data
+**
+** Description      This function write multiple advertising instance adv data
+**                  or scan response data
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_multi_adv_data(tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS btm_status = 0;
+    void *p_ref = NULL;
+
+    if(BTM_BleMaxMultiAdvInstanceCount() > 0 && p_data->ble_multi_adv_data.inst_id > 0
+        && p_data->ble_multi_adv_data.inst_id < BTM_BleMaxMultiAdvInstanceCount())
+    {
+        btm_status = BTM_BleCfgAdvInstData(p_data->ble_multi_adv_data.inst_id,
+                        p_data->ble_multi_adv_data.is_scan_rsp,
+                        p_data->ble_multi_adv_data.data_mask,
+                        (tBTM_BLE_ADV_DATA*)p_data->ble_multi_adv_data.p_data);
+    }
+
+    if(BTM_CMD_STARTED != btm_status)
+    {
+       p_ref = btm_ble_multi_adv_get_ref(p_data->ble_multi_adv_data.inst_id);
+       bta_dm_cb.p_multi_adv_cback(BTA_BLE_MULTI_ADV_DATA_EVT,
+                                   p_data->ble_multi_adv_data.inst_id, p_ref, BTA_FAILURE);
+    }
+
+}
+/*******************************************************************************
+**
+** Function         btm_dm_ble_multi_adv_disable
+**
+** Description      This function disable a single adv instance
+**
+** Parameters:
+**
+*******************************************************************************/
+void btm_dm_ble_multi_adv_disable(tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS btm_status = 0;
+    void *p_ref = NULL;
+
+    if(BTM_BleMaxMultiAdvInstanceCount() > 0 && p_data->ble_multi_adv_disable.inst_id > 0
+        && p_data->ble_multi_adv_disable.inst_id < BTM_BleMaxMultiAdvInstanceCount())
+    {
+        btm_status = BTM_BleDisableAdvInstance(p_data->ble_multi_adv_disable.inst_id);
+    }
+
+    if(BTM_CMD_STARTED != btm_status)
+    {
+       p_ref = btm_ble_multi_adv_get_ref(p_data->ble_multi_adv_disable.inst_id);
+       bta_dm_cb.p_multi_adv_cback(BTA_BLE_MULTI_ADV_DISABLE_EVT,
+                                   p_data->ble_multi_adv_disable.inst_id, p_ref, BTA_FAILURE);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_setup_storage
+**
+** Description      This function configures up the storage parameters for ADV batch scanning
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_setup_storage (tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS btm_status = 0;
+    tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
+
+    BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
+
+    if (0 != cmn_ble_vsc_cb.tot_scan_results_strg)
+    {
+        btm_status = BTM_BleSetStorageConfig(p_data->ble_set_storage.batch_scan_full_max,
+                                             p_data->ble_set_storage.batch_scan_trunc_max,
+                                             p_data->ble_set_storage.batch_scan_notify_threshold,
+                                             p_data->ble_set_storage.p_setup_cback,
+                                             p_data->ble_set_storage.p_thres_cback,
+                                             p_data->ble_set_storage.p_read_rep_cback,
+                                             p_data->ble_set_storage.ref_value);
+    }
+
+    if(BTM_CMD_STARTED != btm_status)
+       bta_ble_scan_setup_cb(BTM_BLE_BATCH_SCAN_CFG_STRG_EVT, p_data->ble_set_storage.ref_value,
+                             btm_status);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_enable_batch_scan
+**
+** Description      This function sets up the parameters and enables batch scan
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_enable_batch_scan (tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS btm_status = 0;
+    tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
+
+    BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
+
+    if (0 != cmn_ble_vsc_cb.tot_scan_results_strg)
+    {
+        btm_status = BTM_BleEnableBatchScan(p_data->ble_enable_scan.scan_mode,
+                                            p_data->ble_enable_scan.scan_int,
+                                            p_data->ble_enable_scan.scan_window,
+                                            p_data->ble_enable_scan.discard_rule,
+                                            p_data->ble_enable_scan.addr_type,
+                                            p_data->ble_enable_scan.ref_value);
+    }
+
+    if(BTM_CMD_STARTED != btm_status)
+       bta_ble_scan_setup_cb(BTM_BLE_BATCH_SCAN_ENABLE_EVT, p_data->ble_enable_scan.ref_value,
+                             btm_status);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_disable_batch_scan
+**
+** Description      This function disables the batch scan
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_disable_batch_scan (tBTA_DM_MSG *p_data)
+{
+    UNUSED(p_data);
+    tBTM_STATUS btm_status = 0;
+    tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
+
+    BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
+
+    if (0 != cmn_ble_vsc_cb.tot_scan_results_strg)
+    {
+        btm_status = BTM_BleDisableBatchScan(p_data->ble_disable_scan.ref_value);
+    }
+
+    if(BTM_CMD_STARTED != btm_status)
+       bta_ble_scan_setup_cb(BTM_BLE_BATCH_SCAN_DISABLE_EVT, p_data->ble_enable_scan.ref_value,
+                             btm_status);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_read_scan_reports
+**
+** Description      This function reads the batch scan reports
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_read_scan_reports(tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS btm_status = 0;
+    tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
+
+    BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
+
+    if (0 != cmn_ble_vsc_cb.tot_scan_results_strg)
+    {
+        btm_status = BTM_BleReadScanReports(p_data->ble_read_reports.scan_type,
+                                            p_data->ble_read_reports.ref_value);
+    }
+
+    if(BTM_CMD_STARTED != btm_status)
+       bta_ble_scan_setup_cb(BTM_BLE_BATCH_SCAN_READ_REPTS_EVT, p_data->ble_enable_scan.ref_value,
+                             btm_status);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_track_advertiser
+**
+** Description      This function tracks the specific advertiser
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_track_advertiser(tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS btm_status = 0;
+    BD_ADDR bda;
+    memset(&bda, 0 , sizeof(BD_ADDR));
+    tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
+    tBTA_DM_BLE_TRACK_ADV_DATA track_adv_data;
+
+    BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
+
+    if (0 != cmn_ble_vsc_cb.tot_scan_results_strg)
+    {
+        btm_status = BTM_BleTrackAdvertiser((tBTM_BLE_TRACK_ADV_CBACK *)
+                                            p_data->ble_track_advert.p_track_adv_cback,
+                                            p_data->ble_track_advert.ref_value);
+    }
+
+    if(BTM_CMD_STARTED != btm_status)
+    {
+        memset(&track_adv_data, 0, sizeof(tBTA_DM_BLE_TRACK_ADV_DATA));
+        track_adv_data.advertiser_info_present = NO_ADV_INFO_PRESENT; /* Indicates failure */
+        track_adv_data.client_if = (UINT8)p_data->ble_track_advert.ref_value;
+        p_data->ble_track_advert.p_track_adv_cback(&track_adv_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ble_scan_setup_cb
+**
+** Description      Handle the setup callback from BTM layer and forward it to app layer
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_ble_scan_setup_cb(tBTM_BLE_BATCH_SCAN_EVT evt, tBTM_BLE_REF_VALUE ref_value,
+                                  tBTM_STATUS status)
+{
+    tBTA_BLE_BATCH_SCAN_EVT bta_evt = 0;
+
+    APPL_TRACE_DEBUG("bta_ble_scan_setup_cb : evt: %d, ref_value: %d, status:%d", evt,
+                      ref_value, status);
+
+    switch(evt)
+    {
+        case BTM_BLE_BATCH_SCAN_ENABLE_EVT:
+           bta_evt = BTA_BLE_BATCH_SCAN_ENB_EVT;
+           break;
+        case BTM_BLE_BATCH_SCAN_CFG_STRG_EVT:
+           bta_evt = BTA_BLE_BATCH_SCAN_CFG_STRG_EVT;
+           break;
+        case BTM_BLE_BATCH_SCAN_DISABLE_EVT:
+            bta_evt = BTA_BLE_BATCH_SCAN_DIS_EVT;
+            break;
+        case BTM_BLE_BATCH_SCAN_PARAM_EVT:
+            bta_evt = BTA_BLE_BATCH_SCAN_PARAM_EVT;
+            break;
+        default:
+            break;
+    }
+
+    if(NULL != bta_dm_cb.p_setup_cback)
+       bta_dm_cb.p_setup_cback(bta_evt, ref_value, status);
+}
+
+
+#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
+/*******************************************************************************
+**
+** Function         bta_ble_scan_pf_cmpl
+**
+** Description      ADV payload filtering operation complete callback
+**
+**
+** Returns         TRUE if handled, otherwise FALSE.
+**
+*******************************************************************************/
+static void bta_ble_scan_cfg_cmpl(tBTM_BLE_PF_ACTION action, tBTM_BLE_SCAN_COND_OP cfg_op,
+                                 tBTM_BLE_PF_AVBL_SPACE avbl_space, tBTM_STATUS status,
+                                 tBTM_BLE_REF_VALUE ref_value)
+{
+    tBTA_STATUS st = (status == BTM_SUCCESS) ? BTA_SUCCESS: BTA_FAILURE;
+
+    APPL_TRACE_DEBUG("bta_ble_scan_cfg_cmpl: %d, %d, %d, %d", action, cfg_op, avbl_space, status);
+
+    if(bta_dm_cb.p_scan_filt_cfg_cback)
+       bta_dm_cb.p_scan_filt_cfg_cback(action, cfg_op, avbl_space, st, ref_value);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_cfg_filter_cond
+**
+** Description      This function configure adv payload filtering condition
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_cfg_filter_cond (tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS st = BTM_MODE_UNSUPPORTED;
+    tBTA_STATUS status = BTA_FAILURE;
+
+    tBTM_BLE_VSC_CB cmn_vsc_cb;
+
+    APPL_TRACE_DEBUG("bta_dm_cfg_filter_cond");
+    BTM_BleGetVendorCapabilities(&cmn_vsc_cb);
+    if(0 != cmn_vsc_cb.filter_support)
+    {
+        if ((st = BTM_BleCfgFilterCondition(p_data->ble_cfg_filter_cond.action,
+                            p_data->ble_cfg_filter_cond.cond_type,
+                            (tBTM_BLE_PF_FILT_INDEX)p_data->ble_cfg_filter_cond.filt_index,
+                            (tBTM_BLE_PF_COND_PARAM *)p_data->ble_cfg_filter_cond.p_cond_param,
+                            bta_ble_scan_cfg_cmpl, p_data->ble_cfg_filter_cond.ref_value))
+                == BTM_CMD_STARTED)
+        {
+            bta_dm_cb.p_scan_filt_cfg_cback = p_data->ble_cfg_filter_cond.p_filt_cfg_cback;
+            return;
+        }
+    }
+
+    if (p_data->ble_cfg_filter_cond.p_filt_cfg_cback)
+        p_data->ble_cfg_filter_cond.p_filt_cfg_cback(BTA_DM_BLE_PF_CONFIG_EVT,
+                                            p_data->ble_cfg_filter_cond.cond_type, 0, status,
+                                            p_data->ble_cfg_filter_cond.ref_value);
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_enable_scan_filter
+**
+** Description      This function enable/disable adv payload filtering condition
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_enable_scan_filter(tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS st = BTM_MODE_UNSUPPORTED;
+    tBTA_STATUS status = BTA_FAILURE;
+
+    tBTM_BLE_VSC_CB cmn_vsc_cb;
+    APPL_TRACE_DEBUG("bta_dm_enable_scan_filter");
+    BTM_BleGetVendorCapabilities(&cmn_vsc_cb);
+
+    if(0 != cmn_vsc_cb.filter_support)
+    {
+        if((st = BTM_BleEnableDisableFilterFeature(p_data->ble_enable_scan_filt.action,
+                   p_data->ble_enable_scan_filt.p_filt_status_cback,
+                   (tBTM_BLE_REF_VALUE)p_data->ble_enable_scan_filt.ref_value)) == BTM_CMD_STARTED)
+        bta_dm_cb.p_scan_filt_status_cback = p_data->ble_enable_scan_filt.p_filt_status_cback;
+        return;
+    }
+
+    if (p_data->ble_enable_scan_filt.p_filt_status_cback)
+        p_data->ble_enable_scan_filt.p_filt_status_cback (BTA_DM_BLE_PF_ENABLE_EVT,
+                                            p_data->ble_enable_scan_filt.ref_value, status);
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_scan_filter_param_setup
+**
+** Description      This function sets up scan filter params
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_scan_filter_param_setup (tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS st = BTM_MODE_UNSUPPORTED;
+    tBTA_STATUS status = BTA_FAILURE;
+
+    tBTM_BLE_VSC_CB cmn_vsc_cb;
+
+    APPL_TRACE_DEBUG("bta_dm_scan_filter_param_setup");
+    BTM_BleGetVendorCapabilities(&cmn_vsc_cb);
+    if(0 != cmn_vsc_cb.filter_support)
+    {
+        if ((st = BTM_BleAdvFilterParamSetup(p_data->ble_scan_filt_param_setup.action,
+                   p_data->ble_scan_filt_param_setup.filt_index,
+                  (tBTM_BLE_PF_FILT_PARAMS *)&p_data->ble_scan_filt_param_setup.filt_params,
+                   p_data->ble_scan_filt_param_setup.p_target,
+                   p_data->ble_scan_filt_param_setup.p_filt_param_cback,
+                   p_data->ble_scan_filt_param_setup.ref_value)) == BTM_CMD_STARTED)
+        {
+            bta_dm_cb.p_scan_filt_param_cback = p_data->ble_scan_filt_param_setup.p_filt_param_cback;
+            return;
+        }
+    }
+
+    if (p_data->ble_scan_filt_param_setup.p_filt_param_cback)
+        p_data->ble_scan_filt_param_setup.p_filt_param_cback (BTA_DM_BLE_PF_ENABLE_EVT, 0,
+                                        p_data->ble_scan_filt_param_setup.ref_value, status);
+
+    return;
+}
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_ble_enable_scan_cmpl
+**
+** Description      ADV payload filtering enable / disable complete callback
+**
+**
+** Returns          None
+**
+*******************************************************************************/
+static void bta_ble_energy_info_cmpl(tBTM_BLE_TX_TIME_MS tx_time,
+                                        tBTM_BLE_RX_TIME_MS rx_time,
+                                        tBTM_BLE_IDLE_TIME_MS idle_time,
+                                        tBTM_BLE_ENERGY_USED  energy_used,
+                                        tBTM_STATUS status)
+{
+    tBTA_STATUS st = (status == BTM_SUCCESS) ? BTA_SUCCESS: BTA_FAILURE;
+    tBTA_DM_CONTRL_STATE ctrl_state = 0;
+
+    if (BTA_SUCCESS == st)
+       ctrl_state = bta_dm_pm_obtain_controller_state();
+
+    if (bta_dm_cb.p_energy_info_cback)
+        bta_dm_cb.p_energy_info_cback(tx_time, rx_time, idle_time, energy_used, ctrl_state, st);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_get_energy_info
+**
+** Description      This function obtains the energy info
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_get_energy_info(tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS btm_status = 0;
+
+    bta_dm_cb.p_energy_info_cback = p_data->ble_energy_info.p_energy_info_cback;
+    btm_status = BTM_BleGetEnergyInfo(bta_ble_energy_info_cmpl);
+    if (BTM_CMD_STARTED != btm_status)
+        bta_ble_energy_info_cmpl(0, 0, 0, 0, btm_status);
+}
+
+#if ((defined BTA_GATT_INCLUDED) &&  (BTA_GATT_INCLUDED == TRUE))
+#ifndef BTA_DM_GATT_CLOSE_DELAY_TOUT
+#define BTA_DM_GATT_CLOSE_DELAY_TOUT    1000
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_dm_gattc_register
+**
+** Description      Register with GATTC in DM if BLE is needed.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_gattc_register(void)
+{
+    tBT_UUID                app_uuid = {LEN_UUID_128,{0}};
+
+    if (bta_dm_search_cb.client_if == BTA_GATTS_INVALID_IF)
+    {
+        memset (&app_uuid.uu.uuid128, 0x87, LEN_UUID_128);
+        BTA_GATTC_AppRegister(&app_uuid, bta_dm_gattc_callback);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         btm_dm_start_disc_gatt_services
+**
+** Description      This function starts a GATT service search request.
+**
+** Parameters:
+**
+*******************************************************************************/
+static void btm_dm_start_disc_gatt_services (UINT16 conn_id)
+{
+    tBT_UUID    *p_uuid = bta_dm_search_cb.p_srvc_uuid +
+                          bta_dm_search_cb.num_uuid - bta_dm_search_cb.uuid_to_search;
+
+    p_uuid = bta_dm_search_cb.p_srvc_uuid +
+             bta_dm_search_cb.num_uuid - bta_dm_search_cb.uuid_to_search;
+
+    /* always search for all services */
+    BTA_GATTC_ServiceSearchRequest(conn_id, p_uuid);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_gatt_disc_result
+**
+** Description      This function process the GATT service search result.
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_dm_gatt_disc_result(tBTA_GATT_ID service_id)
+{
+    tBTA_DM_SEARCH   result;
+
+    /*
+        * This logic will not work for gatt case.  We are checking against the bluetooth profiles here
+        * just copy the GATTID in raw data field and send it across.
+        */
+
+
+    if ( bta_dm_search_cb.ble_raw_used + sizeof(tBTA_GATT_ID) < bta_dm_search_cb.ble_raw_size )
+    {
+        APPL_TRACE_DEBUG("ADDING BLE SERVICE uuid=0x%x, ble_ptr = 0x%x, ble_raw_used = 0x%x",
+            service_id.uuid.uu.uuid16,bta_dm_search_cb.p_ble_rawdata,bta_dm_search_cb.ble_raw_used);
+
+        if(bta_dm_search_cb.p_ble_rawdata)
+        {
+            memcpy((bta_dm_search_cb.p_ble_rawdata + bta_dm_search_cb.ble_raw_used), &service_id,
+                   sizeof(service_id) );
+
+            bta_dm_search_cb.ble_raw_used += sizeof(service_id);
+        }
+        else
+        {
+            APPL_TRACE_ERROR("p_ble_rawdata is NULL");
+        }
+
+    }
+    else
+    {
+        APPL_TRACE_ERROR("%s out of room to accomodate more service ids ble_raw_size = %d ble_raw_used = %d", __FUNCTION__,bta_dm_search_cb.ble_raw_size, bta_dm_search_cb.ble_raw_used );
+    }
+
+    LOG_INFO("%s service_id_uuid_len=%d ", __func__, service_id.uuid.len);
+    if ( bta_dm_search_cb.state != BTA_DM_SEARCH_IDLE)
+    {
+
+        /* send result back to app now, one by one */
+        bdcpy (result.disc_ble_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+        BCM_STRNCPY_S((char*)result.disc_ble_res.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN-1));
+        result.disc_ble_res.bd_name[BD_NAME_LEN] = 0;
+        memcpy(&result.disc_ble_res.service, &service_id.uuid, sizeof(tBT_UUID));
+
+        bta_dm_search_cb.p_search_cback(BTA_DM_DISC_BLE_RES_EVT, &result);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_gatt_disc_complete
+**
+** Description      This function process the GATT service search complete.
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_dm_gatt_disc_complete(UINT16 conn_id, tBTA_GATT_STATUS status)
+{
+    tBTA_DM_MSG *p_msg;
+
+    APPL_TRACE_DEBUG("bta_dm_gatt_disc_complete conn_id = %d",conn_id);
+
+    if (bta_dm_search_cb.uuid_to_search > 0) bta_dm_search_cb.uuid_to_search --;
+
+    if (status == BTA_GATT_OK && bta_dm_search_cb.uuid_to_search > 0)
+    {
+        btm_dm_start_disc_gatt_services(conn_id);
+    }
+    else
+    {
+        bta_dm_search_cb.uuid_to_search = 0;
+
+        /* no more services to be discovered */
+        if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+        {
+            p_msg->hdr.event = BTA_DM_DISCOVERY_RESULT_EVT;
+            p_msg->disc_result.result.disc_res.result = (status == BTA_GATT_OK) ? BTA_SUCCESS :BTA_FAILURE;
+            APPL_TRACE_DEBUG("%s service found: 0x%08x", __FUNCTION__,
+                             bta_dm_search_cb.services_found);
+            p_msg->disc_result.result.disc_res.services = bta_dm_search_cb.services_found;
+            p_msg->disc_result.result.disc_res.num_uuids = 0;
+            p_msg->disc_result.result.disc_res.p_uuid_list = NULL;
+            bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+            BCM_STRNCPY_S((char*)p_msg->disc_result.result.disc_res.bd_name, sizeof(BD_NAME),
+                    bta_dm_get_remname(), (BD_NAME_LEN-1));
+
+            /* make sure the string is terminated */
+            p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN-1] = 0;
+
+            p_msg->disc_result.result.disc_res.device_type |= BT_DEVICE_TYPE_BLE;
+            if ( bta_dm_search_cb.ble_raw_used > 0 )
+            {
+                p_msg->disc_result.result.disc_res.p_raw_data = GKI_getbuf(bta_dm_search_cb.ble_raw_used);
+
+                memcpy( p_msg->disc_result.result.disc_res.p_raw_data,
+                            bta_dm_search_cb.p_ble_rawdata,
+                            bta_dm_search_cb.ble_raw_used );
+
+                p_msg->disc_result.result.disc_res.raw_data_size = bta_dm_search_cb.ble_raw_used;
+            }
+            else
+            {
+                p_msg->disc_result.result.disc_res.p_raw_data = NULL;
+                bta_dm_search_cb.p_ble_rawdata = 0;
+            }
+
+            bta_sys_sendmsg(p_msg);
+        }
+
+        if (conn_id != BTA_GATT_INVALID_CONN_ID)
+        {
+            /* start a GATT channel close delay timer */
+            bta_sys_start_timer(&bta_dm_search_cb.gatt_close_timer, BTA_DM_DISC_CLOSE_TOUT_EVT,
+                                 BTA_DM_GATT_CLOSE_DELAY_TOUT);
+            bdcpy(bta_dm_search_cb.pending_close_bda, bta_dm_search_cb.peer_bdaddr);
+        }
+        bta_dm_search_cb.gatt_disc_active = FALSE;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_close_gatt_conn
+**
+** Description      This function close the GATT connection after delay timeout.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_close_gatt_conn(tBTA_DM_MSG *p_data)
+{
+    UNUSED(p_data);
+
+    if (bta_dm_search_cb.conn_id != BTA_GATT_INVALID_CONN_ID)
+        BTA_GATTC_Close(bta_dm_search_cb.conn_id);
+
+    memset(bta_dm_search_cb.pending_close_bda, 0, BD_ADDR_LEN);
+    bta_dm_search_cb.conn_id = BTA_GATT_INVALID_CONN_ID;
+}
+/*******************************************************************************
+**
+** Function         btm_dm_start_gatt_discovery
+**
+** Description      This is GATT initiate the service search by open a GATT connection
+**                  first.
+**
+** Parameters:
+**
+*******************************************************************************/
+void btm_dm_start_gatt_discovery (BD_ADDR bd_addr)
+{
+    bta_dm_search_cb.gatt_disc_active = TRUE;
+
+    /* connection is already open */
+    if (bdcmp(bta_dm_search_cb.pending_close_bda, bd_addr) == 0 &&
+        bta_dm_search_cb.conn_id != BTA_GATT_INVALID_CONN_ID)
+    {
+        memset(bta_dm_search_cb.pending_close_bda, 0, BD_ADDR_LEN);
+        bta_sys_stop_timer(&bta_dm_search_cb.gatt_close_timer);
+        btm_dm_start_disc_gatt_services(bta_dm_search_cb.conn_id);
+    }
+    else
+        BTA_GATTC_Open(bta_dm_search_cb.client_if, bd_addr, TRUE, BTA_GATT_TRANSPORT_LE);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_cancel_gatt_discovery
+**
+** Description      This is GATT cancel the GATT service search.
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_dm_cancel_gatt_discovery(BD_ADDR bd_addr)
+{
+    if (bta_dm_search_cb.conn_id == BTA_GATT_INVALID_CONN_ID)
+    {
+        BTA_GATTC_CancelOpen(bta_dm_search_cb.client_if, bd_addr, TRUE);
+    }
+
+    bta_dm_gatt_disc_complete(bta_dm_search_cb.conn_id, (tBTA_GATT_STATUS) BTA_GATT_ERROR);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_proc_open_evt
+**
+** Description      process BTA_GATTC_OPEN_EVT in DM.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_proc_open_evt(tBTA_GATTC_OPEN *p_data)
+{
+    UINT8           *p1;
+    UINT8           *p2;
+
+    p1 = bta_dm_search_cb.peer_bdaddr;
+    p2 = p_data->remote_bda;
+
+    APPL_TRACE_DEBUG("DM Search state= %d search_cb.peer_dbaddr: [%08x%04x] connected_bda= [%08x%04x] ",
+                      bta_dm_search_cb.state,
+                      ((p1[0])<<24)+((p1[1])<<16)+((p1[2])<<8)+(p1[3]),
+                      ((p1[4])<<8)+ p1[5],
+                      ((p2[0])<<24)+((p2[1])<<16)+((p2[2])<<8)+(p2[3]),
+                      ((p2[4])<<8)+ p2[5]);
+
+    APPL_TRACE_DEBUG("BTA_GATTC_OPEN_EVT conn_id = %d client_if=%d status = %d" ,
+                      p_data->conn_id,
+                      p_data->client_if,
+                      p_data->status);
+
+    bta_dm_search_cb.conn_id = p_data->conn_id;
+
+    if (p_data->status == BTA_GATT_OK)
+    {
+        btm_dm_start_disc_gatt_services(p_data->conn_id);
+    }
+    else
+    {
+        bta_dm_gatt_disc_complete(BTA_GATT_INVALID_CONN_ID, p_data->status);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_gattc_callback
+**
+** Description      This is GATT client callback function used in DM.
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_dm_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
+{
+    APPL_TRACE_DEBUG("bta_dm_gattc_callback event = %d", event);
+
+    switch (event)
+    {
+        case BTA_GATTC_REG_EVT:
+            APPL_TRACE_DEBUG("BTA_GATTC_REG_EVT client_if = %d",  p_data->reg_oper.client_if);
+            if (p_data->reg_oper.status == BTA_GATT_OK)
+                bta_dm_search_cb.client_if = p_data->reg_oper.client_if;
+            else
+                bta_dm_search_cb.client_if = BTA_GATTS_INVALID_IF;
+            break;
+
+        case BTA_GATTC_OPEN_EVT:
+            bta_dm_proc_open_evt(&p_data->open);
+            break;
+
+        case BTA_GATTC_SEARCH_RES_EVT:
+            bta_dm_gatt_disc_result(p_data->srvc_res.service_uuid.id);
+            break;
+
+        case BTA_GATTC_SEARCH_CMPL_EVT:
+            if ( bta_dm_search_cb.state != BTA_DM_SEARCH_IDLE)
+                bta_dm_gatt_disc_complete(p_data->search_cmpl.conn_id, p_data->search_cmpl.status);
+            break;
+
+        case BTA_GATTC_CLOSE_EVT:
+            APPL_TRACE_DEBUG("BTA_GATTC_CLOSE_EVT reason = %d", p_data->close.reason);
+            /* in case of disconnect before search is completed */
+            if ( (bta_dm_search_cb.state != BTA_DM_SEARCH_IDLE) &&
+                 (bta_dm_search_cb.state != BTA_DM_SEARCH_ACTIVE) &&
+                 !memcmp(p_data->close.remote_bda, bta_dm_search_cb.peer_bdaddr, BD_ADDR_LEN))
+            {
+                bta_dm_gatt_disc_complete((UINT16)BTA_GATT_INVALID_CONN_ID,  (tBTA_GATT_STATUS) BTA_GATT_ERROR);
+            }
+            break;
+
+        default:
+            break;
+    }
+}
+
+#endif /* BTA_GATT_INCLUDED */
+
+#if BLE_VND_INCLUDED == TRUE
+/*******************************************************************************
+**
+** Function         bta_dm_ctrl_features_rd_cmpl_cback
+**
+** Description      callback to handle controller feature read complete
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_dm_ctrl_features_rd_cmpl_cback(tBTM_STATUS result)
+{
+    APPL_TRACE_DEBUG("%s  status = %d ", __FUNCTION__, result);
+    if (result == BTM_SUCCESS)
+    {
+        if(bta_dm_cb.p_sec_cback)
+            bta_dm_cb.p_sec_cback(BTA_DM_LE_FEATURES_READ, NULL);
+    }
+    else
+    {
+        APPL_TRACE_ERROR("%s Ctrl BLE feature read failed: status :%d",__FUNCTION__, result);
+    }
+
+}
+#endif /* BLE_VND_INCLUDED */
+
+#endif  /* BLE_INCLUDED */

+ 2165 - 0
components/bt/bluedroid/bta/dm/bta_dm_api.c

@@ -0,0 +1,2165 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2014 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the API implementation file for the BTA device manager.
+ *
+ ******************************************************************************/
+
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_dm_int.h"
+#include "bta_sys_int.h"
+#include "btm_api.h"
+#include "btm_int.h"
+#include <string.h>
+#include "utl.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_dm_reg =
+{
+    bta_dm_sm_execute,
+    bta_dm_sm_disable
+};
+
+static const tBTA_SYS_REG bta_dm_search_reg =
+{
+    bta_dm_search_sm_execute,
+    bta_dm_search_sm_disable
+};
+
+/*******************************************************************************
+**
+** Function         BTA_EnableBluetooth
+**
+** Description      Enables bluetooth service.  This function must be
+**                  called before any other functions in the BTA API are called.
+**
+**
+** Returns          tBTA_STATUS
+**
+*******************************************************************************/
+tBTA_STATUS BTA_EnableBluetooth(tBTA_DM_SEC_CBACK *p_cback)
+{
+
+    tBTA_DM_API_ENABLE    *p_msg;
+
+    /* Bluetooth disabling is in progress */
+    if (bta_dm_cb.disabling)
+        return BTA_FAILURE;
+
+    memset(&bta_dm_cb, 0, sizeof(bta_dm_cb));
+
+    bta_sys_register (BTA_ID_DM, &bta_dm_reg );
+    bta_sys_register (BTA_ID_DM_SEARCH, &bta_dm_search_reg );
+
+    /* if UUID list is not provided as static data */
+    bta_sys_eir_register(bta_dm_eir_update_uuid);
+
+    if ((p_msg = (tBTA_DM_API_ENABLE *) GKI_getbuf(sizeof(tBTA_DM_API_ENABLE))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_ENABLE_EVT;
+        p_msg->p_sec_cback = p_cback;
+        bta_sys_sendmsg(p_msg);
+        return BTA_SUCCESS;
+    }
+    return BTA_FAILURE;
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DisableBluetooth
+**
+** Description      Disables bluetooth service.  This function is called when
+**                  the application no longer needs bluetooth service
+**
+** Returns          void
+**
+*******************************************************************************/
+tBTA_STATUS BTA_DisableBluetooth(void)
+{
+
+    BT_HDR    *p_msg;
+
+    if ((p_msg = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_msg->event = BTA_DM_API_DISABLE_EVT;
+        bta_sys_sendmsg(p_msg);
+    }
+    else
+    {
+        return BTA_FAILURE;
+    }
+
+    return BTA_SUCCESS;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_EnableTestMode
+**
+** Description      Enables bluetooth device under test mode
+**
+**
+** Returns          tBTA_STATUS
+**
+*******************************************************************************/
+tBTA_STATUS BTA_EnableTestMode(void)
+{
+    BT_HDR    *p_msg;
+
+    APPL_TRACE_API("BTA_EnableTestMode");
+
+    if ((p_msg = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_msg->event = BTA_DM_API_ENABLE_TEST_MODE_EVT;
+        bta_sys_sendmsg(p_msg);
+        return BTA_SUCCESS;
+    }
+    return BTA_FAILURE;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DisableTestMode
+**
+** Description      Disable bluetooth device under test mode
+**
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_DisableTestMode(void)
+{
+    BT_HDR    *p_msg;
+
+    APPL_TRACE_API("BTA_DisableTestMode");
+
+    if ((p_msg = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_msg->event = BTA_DM_API_DISABLE_TEST_MODE_EVT;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetDeviceName
+**
+** Description      This function sets the Bluetooth name of local device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSetDeviceName(char *p_name)
+{
+
+    tBTA_DM_API_SET_NAME    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_SET_NAME *) GKI_getbuf(sizeof(tBTA_DM_API_SET_NAME))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_SET_NAME_EVT;
+        /* truncate the name if needed */
+        BCM_STRNCPY_S((char*)p_msg->name, sizeof(p_msg->name), p_name, BD_NAME_LEN-1);
+        p_msg->name[BD_NAME_LEN-1]=0;
+
+        bta_sys_sendmsg(p_msg);
+    }
+
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetVisibility
+**
+** Description      This function sets the Bluetooth connectable,
+**                  discoverable, pairable and conn paired only modes of local device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSetVisibility(tBTA_DM_DISC disc_mode, tBTA_DM_CONN conn_mode, UINT8 pairable_mode, UINT8 conn_filter )
+{
+
+    tBTA_DM_API_SET_VISIBILITY    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_SET_VISIBILITY *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_SET_VISIBILITY_EVT;
+        p_msg->disc_mode = disc_mode;
+        p_msg->conn_mode = conn_mode;
+        p_msg->pair_mode = pairable_mode;
+        p_msg->conn_paired_only = conn_filter;
+
+
+        bta_sys_sendmsg(p_msg);
+    }
+
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmSearch
+**
+** Description      This function searches for peer Bluetooth devices. It performs
+**                  an inquiry and gets the remote name for devices. Service
+**                  discovery is done if services is non zero
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSearch(tBTA_DM_INQ *p_dm_inq, tBTA_SERVICE_MASK services, tBTA_DM_SEARCH_CBACK *p_cback)
+{
+
+    tBTA_DM_API_SEARCH    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_SEARCH *) GKI_getbuf(sizeof(tBTA_DM_API_SEARCH))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_SEARCH));
+
+        p_msg->hdr.event = BTA_DM_API_SEARCH_EVT;
+        memcpy(&p_msg->inq_params, p_dm_inq, sizeof(tBTA_DM_INQ));
+        p_msg->services = services;
+        p_msg->p_cback = p_cback;
+        p_msg->rs_res  = BTA_DM_RS_NONE;
+        bta_sys_sendmsg(p_msg);
+    }
+
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmSearchCancel
+**
+** Description      This function  cancels a search initiated by BTA_DmSearch
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSearchCancel(void)
+{
+    BT_HDR    *p_msg;
+
+    if ((p_msg = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_msg->event = BTA_DM_API_SEARCH_CANCEL_EVT;
+        bta_sys_sendmsg(p_msg);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmDiscover
+**
+** Description      This function does service discovery for services of a
+**                  peer device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmDiscover(BD_ADDR bd_addr, tBTA_SERVICE_MASK services,
+                    tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search)
+{
+    tBTA_DM_API_DISCOVER    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_DISCOVER *) GKI_getbuf(sizeof(tBTA_DM_API_DISCOVER))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_DISCOVER));
+
+        p_msg->hdr.event = BTA_DM_API_DISCOVER_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->services = services;
+        p_msg->p_cback = p_cback;
+        p_msg->sdp_search = sdp_search;
+        bta_sys_sendmsg(p_msg);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmDiscoverUUID
+**
+** Description      This function does service discovery for services of a
+**                  peer device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmDiscoverUUID(BD_ADDR bd_addr, tSDP_UUID *uuid,
+                    tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search)
+{
+    tBTA_DM_API_DISCOVER    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_DISCOVER *) GKI_getbuf(sizeof(tBTA_DM_API_DISCOVER))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_DISCOVER_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->services = BTA_USER_SERVICE_MASK; //Not exposed at API level
+        p_msg->p_cback = p_cback;
+        p_msg->sdp_search = sdp_search;
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+        p_msg->num_uuid = 0;
+        p_msg->p_uuid = NULL;
+#endif
+        memcpy( &p_msg->uuid, uuid, sizeof(tSDP_UUID) );
+        bta_sys_sendmsg(p_msg);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmBond
+**
+** Description      This function initiates a bonding procedure with a peer
+**                  device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBond(BD_ADDR bd_addr)
+{
+    tBTA_DM_API_BOND    *p_msg;
+
+    p_msg = (tBTA_DM_API_BOND *) GKI_getbuf(sizeof(tBTA_DM_API_BOND));
+    if (p_msg != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_BOND_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->transport = BTA_TRANSPORT_UNKNOWN;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmBondByTransports
+**
+** Description      This function initiates a bonding procedure with a peer
+**                  device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBondByTransport(BD_ADDR bd_addr, tBTA_TRANSPORT transport)
+{
+    tBTA_DM_API_BOND    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_BOND *) GKI_getbuf(sizeof(tBTA_DM_API_BOND))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_BOND_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->transport = transport;
+        bta_sys_sendmsg(p_msg);
+    }
+
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmBondCancel
+**
+** Description      This function cancels the bonding procedure with a peer
+**                  device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBondCancel(BD_ADDR bd_addr)
+{
+    tBTA_DM_API_BOND_CANCEL    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_BOND_CANCEL *) GKI_getbuf(sizeof(tBTA_DM_API_BOND_CANCEL))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_BOND_CANCEL_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        bta_sys_sendmsg(p_msg);
+    }
+
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmPinReply
+**
+** Description      This function provides a pincode for a remote device when
+**                  one is requested by DM through BTA_DM_PIN_REQ_EVT
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmPinReply(BD_ADDR bd_addr, BOOLEAN accept, UINT8 pin_len, UINT8 *p_pin)
+
+{
+    tBTA_DM_API_PIN_REPLY    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_PIN_REPLY *) GKI_getbuf(sizeof(tBTA_DM_API_PIN_REPLY))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_PIN_REPLY_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->accept = accept;
+        if(accept)
+        {
+            p_msg->pin_len = pin_len;
+            memcpy(p_msg->p_pin, p_pin, pin_len);
+        }
+        bta_sys_sendmsg(p_msg);
+    }
+
+}
+
+#if (BTM_OOB_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         BTA_DmLocalOob
+**
+** Description      This function retrieves the OOB data from local controller.
+**                  The result is reported by:
+**                  - bta_dm_co_loc_oob_ext() if device supports secure
+**                    connections (SC)
+**                  - bta_dm_co_loc_oob() if device doesn't support SC
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmLocalOob(void)
+{
+    tBTA_DM_API_LOC_OOB    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_LOC_OOB *) GKI_getbuf(sizeof(tBTA_DM_API_LOC_OOB))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_LOC_OOB_EVT;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+#endif /* BTM_OOB_INCLUDED */
+/*******************************************************************************
+**
+** Function         BTA_DmConfirm
+**
+** Description      This function accepts or rejects the numerical value of the
+**                  Simple Pairing process on BTA_DM_SP_CFM_REQ_EVT
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmConfirm(BD_ADDR bd_addr, BOOLEAN accept)
+{
+    tBTA_DM_API_CONFIRM    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_CONFIRM *) GKI_getbuf(sizeof(tBTA_DM_API_CONFIRM))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_CONFIRM_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->accept = accept;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmAddDevice
+**
+** Description      This function adds a device to the security database list of
+**                  peer device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmAddDevice(BD_ADDR bd_addr, DEV_CLASS dev_class, LINK_KEY link_key,
+                     tBTA_SERVICE_MASK trusted_mask, BOOLEAN is_trusted,
+                     UINT8 key_type, tBTA_IO_CAP io_cap, UINT8 pin_length)
+{
+
+    tBTA_DM_API_ADD_DEVICE *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_ADD_DEVICE *) GKI_getbuf(sizeof(tBTA_DM_API_ADD_DEVICE))) != NULL)
+    {
+        memset (p_msg, 0, sizeof(tBTA_DM_API_ADD_DEVICE));
+
+        p_msg->hdr.event = BTA_DM_API_ADD_DEVICE_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->tm = trusted_mask;
+        p_msg->is_trusted = is_trusted;
+        p_msg->io_cap = io_cap;
+
+        if (link_key)
+        {
+            p_msg->link_key_known = TRUE;
+            p_msg->key_type = key_type;
+            memcpy(p_msg->link_key, link_key, LINK_KEY_LEN);
+        }
+
+        /* Load device class if specified */
+        if (dev_class)
+        {
+            p_msg->dc_known = TRUE;
+            memcpy (p_msg->dc, dev_class, DEV_CLASS_LEN);
+        }
+
+        memset (p_msg->bd_name, 0, BD_NAME_LEN + 1);
+        memset (p_msg->features, 0, sizeof (p_msg->features));
+        p_msg->pin_length = pin_length;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmRemoveDevice
+**
+** Description      This function removes a device fromthe security database list of
+**                  peer device. It manages unpairing even while connected.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+tBTA_STATUS BTA_DmRemoveDevice(BD_ADDR bd_addr)
+{
+    tBTA_DM_API_REMOVE_DEVICE *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_REMOVE_DEVICE *) GKI_getbuf(sizeof(tBTA_DM_API_REMOVE_DEVICE))) != NULL)
+    {
+        memset (p_msg, 0, sizeof(tBTA_DM_API_REMOVE_DEVICE));
+
+        p_msg->hdr.event = BTA_DM_API_REMOVE_DEVICE_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        bta_sys_sendmsg(p_msg);
+    }
+    else
+    {
+        return BTA_FAILURE;
+    }
+
+    return BTA_SUCCESS;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GetEirService
+**
+** Description      This function is called to get BTA service mask from EIR.
+**
+** Parameters       p_eir - pointer of EIR significant part
+**                  p_services - return the BTA service mask
+**
+** Returns          None
+**
+*******************************************************************************/
+extern const UINT16 bta_service_id_to_uuid_lkup_tbl [];
+void BTA_GetEirService( UINT8 *p_eir, tBTA_SERVICE_MASK *p_services )
+{
+    UINT8 xx, yy;
+    UINT8 num_uuid, max_num_uuid = 32;
+    UINT8 uuid_list[32*LEN_UUID_16];
+    UINT16 *p_uuid16 = (UINT16 *)uuid_list;
+    tBTA_SERVICE_MASK mask;
+
+    BTM_GetEirUuidList( p_eir, LEN_UUID_16, &num_uuid, uuid_list, max_num_uuid);
+    for( xx = 0; xx < num_uuid; xx++ )
+    {
+        mask = 1;
+        for( yy = 0; yy < BTA_MAX_SERVICE_ID; yy++ )
+        {
+            if( *(p_uuid16 + xx) == bta_service_id_to_uuid_lkup_tbl[yy] )
+            {
+                *p_services |= mask;
+                break;
+            }
+            mask <<= 1;
+        }
+
+        /* for HSP v1.2 only device */
+        if (*(p_uuid16 + xx) == UUID_SERVCLASS_HEADSET_HS)
+            *p_services |= BTA_HSP_SERVICE_MASK;
+
+       if (*(p_uuid16 + xx) == UUID_SERVCLASS_HDP_SOURCE)
+            *p_services |= BTA_HL_SERVICE_MASK;
+
+        if (*(p_uuid16 + xx) == UUID_SERVCLASS_HDP_SINK)
+            *p_services |= BTA_HL_SERVICE_MASK;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmGetConnectionState
+**
+** Description      Returns whether the remote device is currently connected.
+**
+** Returns          0 if the device is NOT connected.
+**
+*******************************************************************************/
+UINT16 BTA_DmGetConnectionState( BD_ADDR bd_addr )
+{
+    tBTA_DM_PEER_DEVICE * p_dev = bta_dm_find_peer_device(bd_addr);
+    return (p_dev && p_dev->conn_state == BTA_DM_CONNECTED);
+}
+
+
+/*******************************************************************************
+**                   Device Identification (DI) Server Functions
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function         BTA_DmSetLocalDiRecord
+**
+** Description      This function adds a DI record to the local SDP database.
+**
+** Returns          BTA_SUCCESS if record set sucessfully, otherwise error code.
+**
+*******************************************************************************/
+tBTA_STATUS BTA_DmSetLocalDiRecord( tBTA_DI_RECORD *p_device_info,
+                              UINT32 *p_handle )
+{
+    tBTA_STATUS  status = BTA_FAILURE;
+
+    if(bta_dm_di_cb.di_num < BTA_DI_NUM_MAX)
+    {
+        if(SDP_SetLocalDiRecord((tSDP_DI_RECORD *)p_device_info, p_handle) == SDP_SUCCESS)
+        {
+            if(!p_device_info->primary_record)
+            {
+                bta_dm_di_cb.di_handle[bta_dm_di_cb.di_num] = *p_handle;
+                bta_dm_di_cb.di_num ++;
+            }
+
+            bta_sys_add_uuid(UUID_SERVCLASS_PNP_INFORMATION);
+            status =  BTA_SUCCESS;
+        }
+    }
+
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         bta_dmexecutecallback
+**
+** Description      This function will request BTA to execute a call back in the context of BTU task
+**                  This API was named in lower case because it is only intended
+**                  for the internal customers(like BTIF).
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dmexecutecallback (tBTA_DM_EXEC_CBACK* p_callback, void * p_param)
+{
+    tBTA_DM_API_EXECUTE_CBACK *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_EXECUTE_CBACK *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_EXECUTE_CBACK_EVT;
+        p_msg->p_param= p_param;
+        p_msg->p_exec_cback= p_callback;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmAddBleKey
+**
+** Description      Add/modify LE device information.  This function will be
+**                  normally called during host startup to restore all required
+**                  information stored in the NVRAM.
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  p_le_key         - LE key values.
+**                  key_type         - LE SMP key type.
+**
+** Returns          BTA_SUCCESS if successful
+**                  BTA_FAIL if operation failed.
+**
+*******************************************************************************/
+void BTA_DmAddBleKey (BD_ADDR bd_addr, tBTA_LE_KEY_VALUE *p_le_key, tBTA_LE_KEY_TYPE key_type)
+{
+#if BLE_INCLUDED == TRUE
+
+    tBTA_DM_API_ADD_BLEKEY *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_ADD_BLEKEY *) GKI_getbuf(sizeof(tBTA_DM_API_ADD_BLEKEY))) != NULL)
+    {
+        memset (p_msg, 0, sizeof(tBTA_DM_API_ADD_BLEKEY));
+
+        p_msg->hdr.event = BTA_DM_API_ADD_BLEKEY_EVT;
+        p_msg->key_type = key_type;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        memcpy(&p_msg->blekey, p_le_key, sizeof(tBTA_LE_KEY_VALUE));
+
+        bta_sys_sendmsg(p_msg);
+    }
+
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmAddBleDevice
+**
+** Description      Add a BLE device.  This function will be normally called
+**                  during host startup to restore all required information
+**                  for a LE device stored in the NVRAM.
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  dev_type         - Remote device's device type.
+**                  addr_type        - LE device address type.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmAddBleDevice(BD_ADDR bd_addr, tBLE_ADDR_TYPE addr_type, tBT_DEVICE_TYPE dev_type)
+{
+#if BLE_INCLUDED == TRUE
+    tBTA_DM_API_ADD_BLE_DEVICE *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_ADD_BLE_DEVICE *) GKI_getbuf(sizeof(tBTA_DM_API_ADD_BLE_DEVICE))) != NULL)
+    {
+        memset (p_msg, 0, sizeof(tBTA_DM_API_ADD_BLE_DEVICE));
+
+        p_msg->hdr.event = BTA_DM_API_ADD_BLEDEVICE_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->addr_type = addr_type;
+        p_msg->dev_type = dev_type;
+
+        bta_sys_sendmsg(p_msg);
+    }
+#endif
+}
+/*******************************************************************************
+**
+** Function         BTA_DmBlePasskeyReply
+**
+** Description      Send BLE SMP passkey reply.
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  accept           - passkey entry sucessful or declined.
+**                  passkey          - passkey value, must be a 6 digit number,
+**                                     can be lead by 0.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBlePasskeyReply(BD_ADDR bd_addr, BOOLEAN accept, UINT32 passkey)
+{
+#if BLE_INCLUDED == TRUE
+    tBTA_DM_API_PASSKEY_REPLY    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_PASSKEY_REPLY *) GKI_getbuf(sizeof(tBTA_DM_API_PASSKEY_REPLY))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_PASSKEY_REPLY));
+
+        p_msg->hdr.event = BTA_DM_API_BLE_PASSKEY_REPLY_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->accept = accept;
+
+        if(accept)
+        {
+            p_msg->passkey = passkey;
+        }
+        bta_sys_sendmsg(p_msg);
+    }
+#endif
+}
+/*******************************************************************************
+**
+** Function         BTA_DmBleConfirmReply
+**
+** Description      Send BLE SMP SC user confirmation reply.
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  accept           - numbers to compare are the same or different.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBleConfirmReply(BD_ADDR bd_addr, BOOLEAN accept)
+{
+#if BLE_INCLUDED == TRUE
+    tBTA_DM_API_CONFIRM *p_msg = (tBTA_DM_API_CONFIRM *)GKI_getbuf(sizeof(tBTA_DM_API_CONFIRM));
+    if (p_msg != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_CONFIRM));
+        p_msg->hdr.event = BTA_DM_API_BLE_CONFIRM_REPLY_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->accept = accept;
+        bta_sys_sendmsg(p_msg);
+    }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleSecurityGrant
+**
+** Description      Grant security request access.
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  res              - security grant status.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBleSecurityGrant(BD_ADDR bd_addr, tBTA_DM_BLE_SEC_GRANT res)
+{
+#if BLE_INCLUDED == TRUE
+    tBTA_DM_API_BLE_SEC_GRANT    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_BLE_SEC_GRANT *) GKI_getbuf(sizeof(tBTA_DM_API_BLE_SEC_GRANT))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_SEC_GRANT));
+
+        p_msg->hdr.event = BTA_DM_API_BLE_SEC_GRANT_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->res = res;
+
+        bta_sys_sendmsg(p_msg);
+    }
+#endif
+}
+/*******************************************************************************
+**
+** Function         BTA_DmSetBlePrefConnParams
+**
+** Description      This function is called to set the preferred connection
+**                  parameters when default connection parameter is not desired.
+**
+** Parameters:      bd_addr          - BD address of the peripheral
+**                  scan_interval    - scan interval
+**                  scan_window      - scan window
+**                  min_conn_int     - minimum preferred connection interval
+**                  max_conn_int     - maximum preferred connection interval
+**                  slave_latency    - preferred slave latency
+**                  supervision_tout - preferred supervision timeout
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSetBlePrefConnParams(BD_ADDR bd_addr,
+                               UINT16 min_conn_int, UINT16 max_conn_int,
+                               UINT16 slave_latency, UINT16 supervision_tout )
+{
+#if BLE_INCLUDED == TRUE
+    tBTA_DM_API_BLE_CONN_PARAMS    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_BLE_CONN_PARAMS *) GKI_getbuf(sizeof(tBTA_DM_API_BLE_CONN_PARAMS))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_CONN_PARAMS));
+
+        p_msg->hdr.event = BTA_DM_API_BLE_CONN_PARAM_EVT;
+
+        memcpy(p_msg->peer_bda, bd_addr, BD_ADDR_LEN);
+
+        p_msg->conn_int_max     = max_conn_int;
+        p_msg->conn_int_min     = min_conn_int;
+        p_msg->slave_latency    = slave_latency;
+        p_msg->supervision_tout = supervision_tout;
+
+        bta_sys_sendmsg(p_msg);
+    }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetBleConnScanParams
+**
+** Description      This function is called to set scan parameters used in
+**                  BLE connection request
+**
+** Parameters:      scan_interval    - scan interval
+**                  scan_window      - scan window
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSetBleConnScanParams(UINT32 scan_interval, UINT32 scan_window)
+{
+    tBTA_DM_API_BLE_SCAN_PARAMS  *p_msg;
+    if ((p_msg = (tBTA_DM_API_BLE_SCAN_PARAMS *)GKI_getbuf(sizeof(tBTA_DM_API_BLE_SCAN_PARAMS))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_SCAN_PARAMS));
+        p_msg->hdr.event = BTA_DM_API_BLE_CONN_SCAN_PARAM_EVT;
+        p_msg->scan_int         = scan_interval;
+        p_msg->scan_window      = scan_window;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetBleScanParams
+**
+** Description      This function is called to set scan parameters
+**
+** Parameters:      client_if - Client IF
+**                  scan_interval - scan interval
+**                  scan_window - scan window
+**                  scan_mode - scan mode
+**                  scan_param_setup_status_cback - Set scan param status callback
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSetBleScanParams(tGATT_IF client_if, UINT32 scan_interval,
+                            UINT32 scan_window, tBLE_SCAN_MODE scan_mode,
+                            tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback)
+{
+    tBTA_DM_API_BLE_SCAN_PARAMS *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_BLE_SCAN_PARAMS *)GKI_getbuf(sizeof(tBTA_DM_API_BLE_SCAN_PARAMS))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_SCAN_PARAMS));
+        p_msg->hdr.event = BTA_DM_API_BLE_SCAN_PARAM_EVT;
+        p_msg->client_if = client_if;
+        p_msg->scan_int = scan_interval;
+        p_msg->scan_window = scan_window;
+        p_msg->scan_mode = scan_mode;
+        p_msg->scan_param_setup_cback = scan_param_setup_cback;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetBleAdvParams
+**
+** Description      This function sets the advertising parameters BLE functionality.
+**                  It is to be called when device act in peripheral or broadcaster
+**                  role.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSetBleAdvParams (UINT16 adv_int_min, UINT16 adv_int_max,
+                           tBLE_BD_ADDR *p_dir_bda)
+{
+#if BLE_INCLUDED == TRUE
+    tBTA_DM_API_BLE_ADV_PARAMS    *p_msg;
+
+    APPL_TRACE_API ("BTA_DmSetBleAdvParam: %d, %d", adv_int_min, adv_int_max);
+
+    if ((p_msg = (tBTA_DM_API_BLE_ADV_PARAMS *) GKI_getbuf(sizeof(tBTA_DM_API_BLE_ADV_PARAMS))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_ADV_PARAMS));
+
+        p_msg->hdr.event = BTA_DM_API_BLE_ADV_PARAM_EVT;
+
+        p_msg->adv_int_min      = adv_int_min;
+        p_msg->adv_int_max      = adv_int_max;
+
+        if (p_dir_bda != NULL)
+        {
+            p_msg->p_dir_bda = (tBLE_BD_ADDR *)(p_msg + 1);
+            memcpy(p_msg->p_dir_bda, p_dir_bda, sizeof(tBLE_BD_ADDR));
+        }
+
+        bta_sys_sendmsg(p_msg);
+    }
+#endif
+}
+/*******************************************************************************
+**                      BLE ADV data management API
+********************************************************************************/
+
+#if BLE_INCLUDED == TRUE
+/*******************************************************************************
+**
+** Function         BTA_DmBleSetAdvConfig
+**
+** Description      This function is called to override the BTA default ADV parameters.
+**
+** Parameters       data_mask: adv data mask.
+**                  p_adv_cfg: Pointer to User defined ADV data structure. This
+**                             memory space can not be freed until p_adv_data_cback
+**                             is received.
+**                  p_adv_data_cback: set adv data complete callback.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_DmBleSetAdvConfig (tBTA_BLE_AD_MASK data_mask, tBTA_BLE_ADV_DATA *p_adv_cfg,
+                            tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback)
+{
+    tBTA_DM_API_SET_ADV_CONFIG  *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_SET_ADV_CONFIG *)
+        GKI_getbuf(sizeof(tBTA_DM_API_SET_ADV_CONFIG))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_BLE_SET_ADV_CONFIG_EVT;
+        p_msg->data_mask = data_mask;
+        p_msg->p_adv_data_cback = p_adv_data_cback;
+        p_msg->p_adv_cfg = p_adv_cfg;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleSetScanRsp
+**
+** Description      This function is called to override the BTA scan response.
+**
+** Parameters       Pointer to User defined ADV data structure
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_DmBleSetScanRsp (tBTA_BLE_AD_MASK data_mask, tBTA_BLE_ADV_DATA *p_adv_cfg,
+                                 tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback)
+{
+    tBTA_DM_API_SET_ADV_CONFIG  *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_SET_ADV_CONFIG *)
+        GKI_getbuf(sizeof(tBTA_DM_API_SET_ADV_CONFIG))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_BLE_SET_SCAN_RSP_EVT;
+        p_msg->data_mask = data_mask;
+        p_msg->p_adv_data_cback = p_adv_data_cback;
+        p_msg->p_adv_cfg = p_adv_cfg;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleSetStorageParams
+**
+** Description      This function is called to override the BTA scan response.
+**
+** Parameters       batch_scan_full_max -Max storage space (in %) allocated to full scanning
+**                  batch_scan_trunc_max -Max storage space (in %) allocated to truncated scanning
+**                  batch_scan_notify_threshold -Setup notification level based on total space
+**                  p_setup_cback - Setup callback pointer
+**                  p_thres_cback - Threshold callback pointer
+**                  p_rep_cback - Reports callback pointer
+**                  ref_value - Ref value
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_DmBleSetStorageParams(UINT8 batch_scan_full_max,
+                                         UINT8 batch_scan_trunc_max,
+                                         UINT8 batch_scan_notify_threshold,
+                                         tBTA_BLE_SCAN_SETUP_CBACK *p_setup_cback,
+                                         tBTA_BLE_SCAN_THRESHOLD_CBACK *p_thres_cback,
+                                         tBTA_BLE_SCAN_REP_CBACK* p_rep_cback,
+                                         tBTA_DM_BLE_REF_VALUE ref_value)
+{
+    tBTA_DM_API_SET_STORAGE_CONFIG  *p_msg;
+    bta_dm_cb.p_setup_cback = p_setup_cback;
+    if ((p_msg = (tBTA_DM_API_SET_STORAGE_CONFIG *)
+          GKI_getbuf(sizeof(tBTA_DM_API_SET_STORAGE_CONFIG))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_BLE_SETUP_STORAGE_EVT;
+        p_msg->p_setup_cback=bta_ble_scan_setup_cb;
+        p_msg->p_thres_cback=p_thres_cback;
+        p_msg->p_read_rep_cback=p_rep_cback;
+        p_msg->ref_value = ref_value;
+        p_msg->batch_scan_full_max = batch_scan_full_max;
+        p_msg->batch_scan_trunc_max = batch_scan_trunc_max;
+        p_msg->batch_scan_notify_threshold = batch_scan_notify_threshold;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleEnableBatchScan
+**
+** Description      This function is called to enable the batch scan
+**
+** Parameters       scan_mode -Batch scan mode
+**                  scan_interval - Scan interval
+**                  scan_window - Scan window
+**                  discard_rule -Discard rules
+**                  addr_type - Address type
+**                  ref_value - Reference value
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_DmBleEnableBatchScan(tBTA_BLE_BATCH_SCAN_MODE scan_mode,
+                                         UINT32 scan_interval, UINT32 scan_window,
+                                         tBTA_BLE_DISCARD_RULE discard_rule,
+                                         tBLE_ADDR_TYPE        addr_type,
+                                         tBTA_DM_BLE_REF_VALUE ref_value)
+{
+    tBTA_DM_API_ENABLE_SCAN  *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_ENABLE_SCAN *) GKI_getbuf(sizeof(tBTA_DM_API_ENABLE_SCAN))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_BLE_ENABLE_BATCH_SCAN_EVT;
+        p_msg->scan_mode = scan_mode;
+        p_msg->scan_int = scan_interval;
+        p_msg->scan_window = scan_window;
+        p_msg->discard_rule = discard_rule;
+        p_msg->addr_type = addr_type;
+        p_msg->ref_value = ref_value;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleDisableBatchScan
+**
+** Description      This function is called to disable the batch scan
+**
+** Parameters       ref_value - Reference value
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_DmBleDisableBatchScan(tBTA_DM_BLE_REF_VALUE ref_value)
+{
+    tBTA_DM_API_DISABLE_SCAN  *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_DISABLE_SCAN *)
+         GKI_getbuf(sizeof(tBTA_DM_API_DISABLE_SCAN))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_BLE_DISABLE_BATCH_SCAN_EVT;
+        p_msg->ref_value = ref_value;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleReadScanReports
+**
+** Description      This function is called to read scan reports
+**
+** Parameters       scan_type -Batch scan mode
+**                  ref_value - Reference value
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_DmBleReadScanReports(tBTA_BLE_BATCH_SCAN_MODE scan_type,
+                                             tBTA_DM_BLE_REF_VALUE ref_value)
+{
+    tBTA_DM_API_READ_SCAN_REPORTS  *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_READ_SCAN_REPORTS *)
+          GKI_getbuf(sizeof(tBTA_DM_API_READ_SCAN_REPORTS))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_BLE_READ_SCAN_REPORTS_EVT;
+        p_msg->scan_type = scan_type;
+        p_msg->ref_value = ref_value;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleTrackAdvertiser
+**
+** Description      This function is called to track advertiser
+**
+** Parameters       ref_value - Reference value
+**                  p_track_adv_cback - Track ADV callback
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_DmBleTrackAdvertiser(tBTA_DM_BLE_REF_VALUE ref_value,
+                            tBTA_BLE_TRACK_ADV_CBACK *p_track_adv_cback)
+{
+    tBTA_DM_API_TRACK_ADVERTISER  *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_TRACK_ADVERTISER *)
+         GKI_getbuf(sizeof(tBTA_DM_API_TRACK_ADVERTISER))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_BLE_TRACK_ADVERTISER_EVT;
+        p_msg->p_track_adv_cback = p_track_adv_cback;
+        p_msg->ref_value = ref_value;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+#endif
+
+/*******************************************************************************
+**                      BLE ADV data management API
+********************************************************************************/
+#if BLE_INCLUDED == TRUE
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleBroadcast
+**
+** Description      This function starts or stops LE broadcasting.
+**
+** Parameters       start: start or stop broadcast.
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_DmBleBroadcast (BOOLEAN start)
+{
+    tBTA_DM_API_BLE_OBSERVE   *p_msg;
+
+    APPL_TRACE_API("BTA_DmBleBroadcast: start = %d ", start);
+
+    if ((p_msg = (tBTA_DM_API_BLE_OBSERVE *) GKI_getbuf(sizeof(tBTA_DM_API_BLE_OBSERVE))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_OBSERVE));
+
+        p_msg->hdr.event = BTA_DM_API_BLE_BROADCAST_EVT;
+        p_msg->start = start;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+#endif
+/*******************************************************************************
+**
+** Function         BTA_DmBleSetBgConnType
+**
+** Description      This function is called to set BLE connectable mode for a
+**                  peripheral device.
+**
+** Parameters       bg_conn_type: it can be auto connection, or selective connection.
+**                  p_select_cback: callback function when selective connection procedure
+**                              is being used.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBleSetBgConnType(tBTA_DM_BLE_CONN_TYPE bg_conn_type, tBTA_DM_BLE_SEL_CBACK *p_select_cback)
+{
+#if BLE_INCLUDED == TRUE
+    tBTA_DM_API_BLE_SET_BG_CONN_TYPE    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_BLE_SET_BG_CONN_TYPE *) GKI_getbuf(sizeof(tBTA_DM_API_BLE_SET_BG_CONN_TYPE))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_SET_BG_CONN_TYPE));
+
+        p_msg->hdr.event        = BTA_DM_API_BLE_SET_BG_CONN_TYPE;
+        p_msg->bg_conn_type     = bg_conn_type;
+        p_msg->p_select_cback   = p_select_cback;
+
+        bta_sys_sendmsg(p_msg);
+    }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_discover_send_msg
+**
+** Description      This function send discover message to BTA task.
+**
+** Returns          void
+**
+*******************************************************************************/
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+static void bta_dm_discover_send_msg(BD_ADDR bd_addr, tBTA_SERVICE_MASK_EXT *p_services,
+                    tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search,
+                    tBTA_TRANSPORT transport)
+{
+    tBTA_DM_API_DISCOVER    *p_msg;
+    UINT16  len = p_services ? (sizeof(tBTA_DM_API_DISCOVER) +
+                                sizeof(tBT_UUID) * p_services->num_uuid) :
+                                sizeof(tBTA_DM_API_DISCOVER);
+
+    if ((p_msg = (tBTA_DM_API_DISCOVER *) GKI_getbuf(len)) != NULL)
+    {
+        memset(p_msg, 0, len);
+
+        p_msg->hdr.event = BTA_DM_API_DISCOVER_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->p_cback = p_cback;
+        p_msg->sdp_search = sdp_search;
+        p_msg->transport    = transport;
+
+        if (p_services != NULL)
+        {
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+            p_msg->services = p_services->srvc_mask;
+            p_msg->num_uuid = p_services->num_uuid;
+            if (p_services->num_uuid != 0)
+            {
+                p_msg->p_uuid = (tBT_UUID *)(p_msg + 1);
+                memcpy(p_msg->p_uuid, p_services->p_uuid, sizeof(tBT_UUID) * p_services->num_uuid);
+            }
+#endif
+        }
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+#endif
+/*******************************************************************************
+**
+** Function         BTA_DmDiscoverByTransport
+**
+** Description      This function does service discovery on particular transport
+**                  for services of a
+**                  peer device. When services.num_uuid is 0, it indicates all
+**                  GATT based services are to be searched; otherwise a list of
+**                  UUID of interested services should be provided through
+**                  p_services->p_uuid.
+**
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmDiscoverByTransport(BD_ADDR bd_addr, tBTA_SERVICE_MASK_EXT *p_services,
+                    tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search,
+                    tBTA_TRANSPORT transport)
+{
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    bta_dm_discover_send_msg(bd_addr, p_services, p_cback, sdp_search, transport);
+#endif
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmDiscoverExt
+**
+** Description      This function does service discovery for services of a
+**                  peer device. When services.num_uuid is 0, it indicates all
+**                  GATT based services are to be searched; other wise a list of
+**                  UUID of interested services should be provided through
+**                  p_services->p_uuid.
+**
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmDiscoverExt(BD_ADDR bd_addr, tBTA_SERVICE_MASK_EXT *p_services,
+                    tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search)
+{
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    bta_dm_discover_send_msg(bd_addr, p_services, p_cback, sdp_search, BTA_TRANSPORT_UNKNOWN);
+#endif
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmSearchExt
+**
+** Description      This function searches for peer Bluetooth devices. It performs
+**                  an inquiry and gets the remote name for devices. Service
+**                  discovery is done if services is non zero
+**
+** Parameters       p_dm_inq: inquiry conditions
+**                  p_services: if service is not empty, service discovery will be done.
+**                            for all GATT based service condition, put num_uuid, and
+**                            p_uuid is the pointer to the list of UUID values.
+**                  p_cback: callback functino when search is completed.
+**
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSearchExt(tBTA_DM_INQ *p_dm_inq, tBTA_SERVICE_MASK_EXT *p_services, tBTA_DM_SEARCH_CBACK *p_cback)
+{
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    tBTA_DM_API_SEARCH    *p_msg;
+    UINT16  len = p_services ? (sizeof(tBTA_DM_API_SEARCH) + sizeof(tBT_UUID) * p_services->num_uuid) :
+                    sizeof(tBTA_DM_API_SEARCH);
+
+    if ((p_msg = (tBTA_DM_API_SEARCH *) GKI_getbuf(len)) != NULL)
+    {
+        memset(p_msg, 0, len);
+
+        p_msg->hdr.event = BTA_DM_API_SEARCH_EVT;
+        memcpy(&p_msg->inq_params, p_dm_inq, sizeof(tBTA_DM_INQ));
+        p_msg->p_cback = p_cback;
+        p_msg->rs_res  = BTA_DM_RS_NONE;
+
+
+        if (p_services != NULL)
+        {
+            p_msg->services = p_services->srvc_mask;
+            p_msg->num_uuid = p_services->num_uuid;
+
+            if (p_services->num_uuid != 0)
+            {
+                p_msg->p_uuid = (tBT_UUID *)(p_msg + 1);
+                memcpy(p_msg->p_uuid, p_services->p_uuid, sizeof(tBT_UUID) * p_services->num_uuid);
+            }
+            else
+                p_msg->p_uuid = NULL;
+        }
+
+        bta_sys_sendmsg(p_msg);
+    }
+#else
+    UNUSED(p_dm_inq);
+    UNUSED(p_services);
+    UNUSED(p_cback);
+#endif
+}
+/*******************************************************************************
+**
+** Function         BTA_DmBleUpdateConnectionParam
+**
+** Description      Update connection parameters, can only be used when connection is up.
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  min_int   -     minimum connection interval, [0x0004~ 0x4000]
+**                  max_int   -     maximum connection interval, [0x0004~ 0x4000]
+**                  latency   -     slave latency [0 ~ 500]
+**                  timeout   -     supervision timeout [0x000a ~ 0xc80]
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBleUpdateConnectionParam(BD_ADDR bd_addr, UINT16 min_int,
+                                    UINT16 max_int, UINT16 latency,
+                                    UINT16 timeout)
+{
+#if BLE_INCLUDED == TRUE
+    tBTA_DM_API_UPDATE_CONN_PARAM *p_msg;
+
+    p_msg = (tBTA_DM_API_UPDATE_CONN_PARAM *) GKI_getbuf(sizeof(tBTA_DM_API_UPDATE_CONN_PARAM));
+    if (p_msg != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_UPDATE_CONN_PARAM));
+
+        p_msg->hdr.event = BTA_DM_API_UPDATE_CONN_PARAM_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->min_int   = min_int;
+        p_msg->max_int   = max_int;
+        p_msg->latency   = latency;
+        p_msg->timeout   = timeout;
+
+        bta_sys_sendmsg(p_msg);
+    }
+#endif
+}
+/*******************************************************************************
+**
+** Function         BTA_DmBleConfigLocalPrivacy
+**
+** Description      Enable/disable privacy on the local device
+**
+** Parameters:      privacy_enable   - enable/disabe privacy on remote device.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBleConfigLocalPrivacy(BOOLEAN privacy_enable)
+{
+#if BLE_INCLUDED == TRUE && BLE_PRIVACY_SPT == TRUE
+    tBTA_DM_API_LOCAL_PRIVACY *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_LOCAL_PRIVACY *) GKI_getbuf(sizeof(tBTA_DM_API_ENABLE_PRIVACY))) != NULL)
+    {
+        memset (p_msg, 0, sizeof(tBTA_DM_API_LOCAL_PRIVACY));
+
+        p_msg->hdr.event = BTA_DM_API_LOCAL_PRIVACY_EVT;
+        p_msg->privacy_enable   = privacy_enable;
+
+        bta_sys_sendmsg(p_msg);
+    }
+#else
+    UNUSED (privacy_enable);
+#endif
+}
+
+#if BLE_INCLUDED == TRUE
+/*******************************************************************************
+**
+** Function         BTA_BleEnableAdvInstance
+**
+** Description      This function enable a Multi-ADV instance with the specififed
+**                  adv parameters
+**
+** Parameters       p_params: pointer to the adv parameter structure.
+**                  p_cback: callback function associated to this adv instance.
+**                  p_ref: reference data pointer to this adv instance.
+**
+** Returns          BTA_SUCCESS if command started sucessfully; otherwise failure.
+**
+*******************************************************************************/
+void BTA_BleEnableAdvInstance (tBTA_BLE_ADV_PARAMS *p_params,
+                                tBTA_BLE_MULTI_ADV_CBACK *p_cback,
+                                void *p_ref)
+{
+    tBTA_DM_API_BLE_MULTI_ADV_ENB    *p_msg;
+    UINT16 len = sizeof(tBTA_BLE_ADV_PARAMS) + sizeof(tBTA_DM_API_BLE_MULTI_ADV_ENB);
+
+    APPL_TRACE_API ("BTA_BleEnableAdvInstance");
+
+    if ((p_msg = (tBTA_DM_API_BLE_MULTI_ADV_ENB *) GKI_getbuf(len)) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_MULTI_ADV_ENB));
+
+        p_msg->hdr.event     = BTA_DM_API_BLE_MULTI_ADV_ENB_EVT;
+        p_msg->p_cback      = (void *)p_cback;
+        if (p_params != NULL)
+        {
+            p_msg->p_params =  (void *)(p_msg + 1);
+            memcpy(p_msg->p_params, p_params, sizeof(tBTA_BLE_ADV_PARAMS));
+        }
+        p_msg->p_ref        = p_ref;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_BleUpdateAdvInstParam
+**
+** Description      This function update a Multi-ADV instance with the specififed
+**                  adv parameters.
+**
+** Parameters       inst_id: Adv instance to update the parameter.
+**                  p_params: pointer to the adv parameter structure.
+**
+** Returns          BTA_SUCCESS if command started sucessfully; otherwise failure.
+**
+*******************************************************************************/
+void BTA_BleUpdateAdvInstParam (UINT8 inst_id, tBTA_BLE_ADV_PARAMS *p_params)
+{
+    tBTA_DM_API_BLE_MULTI_ADV_PARAM    *p_msg;
+    UINT16      len = sizeof(tBTA_BLE_ADV_PARAMS) + sizeof(tBTA_DM_API_BLE_MULTI_ADV_PARAM);
+
+    APPL_TRACE_API ("BTA_BleUpdateAdvInstParam");
+     if ((p_msg = (tBTA_DM_API_BLE_MULTI_ADV_PARAM *) GKI_getbuf(len)) != NULL)
+     {
+          memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_MULTI_ADV_PARAM));
+          p_msg->hdr.event     = BTA_DM_API_BLE_MULTI_ADV_PARAM_UPD_EVT;
+          p_msg->inst_id        = inst_id;
+          p_msg->p_params =  (void *)(p_msg + 1);
+          memcpy(p_msg->p_params, p_params, sizeof(tBTA_BLE_ADV_PARAMS));
+
+          bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_BleCfgAdvInstData
+**
+** Description      This function configure a Multi-ADV instance with the specififed
+**                  adv data or scan response data.
+**
+** Parameter        inst_id: Adv instance to configure the adv data or scan response.
+**                  is_scan_rsp: is the data scan response or adv data.
+**                  data_mask: adv data type as bit mask.
+**                  p_data: pointer to the ADV data structure tBTA_BLE_ADV_DATA. This
+**                  memory space can not be freed until BTA_BLE_MULTI_ADV_DATA_EVT
+**                  is sent to application.
+**
+** Returns          BTA_SUCCESS if command started sucessfully; otherwise failure.
+**
+*******************************************************************************/
+void BTA_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp,
+                            tBTA_BLE_AD_MASK data_mask,
+                            tBTA_BLE_ADV_DATA *p_data)
+{
+    tBTA_DM_API_BLE_MULTI_ADV_DATA    *p_msg;
+    UINT16      len =  sizeof(tBTA_DM_API_BLE_MULTI_ADV_DATA) ;
+
+    APPL_TRACE_API ("BTA_BleCfgAdvInstData");
+
+    if ((p_msg = (tBTA_DM_API_BLE_MULTI_ADV_DATA *) GKI_getbuf(len)) != NULL)
+    {
+          memset(p_msg, 0, len);
+          p_msg->hdr.event     = BTA_DM_API_BLE_MULTI_ADV_DATA_EVT;
+          p_msg->inst_id      = inst_id;
+          p_msg->is_scan_rsp  = is_scan_rsp;
+          p_msg->data_mask     = data_mask;
+          p_msg->p_data        = p_data;
+
+          bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_BleDisableAdvInstance
+**
+** Description      This function disable a Multi-ADV instance.
+**
+** Parameter        inst_id: instance ID to disable.
+**
+** Returns          BTA_SUCCESS if command started sucessfully; otherwise failure.
+**
+*******************************************************************************/
+void BTA_BleDisableAdvInstance (UINT8  inst_id)
+{
+    tBTA_DM_API_BLE_MULTI_ADV_DISABLE    *p_msg;
+
+    APPL_TRACE_API ("BTA_BleDisableAdvInstance: %d", inst_id);
+    if ((p_msg = (tBTA_DM_API_BLE_MULTI_ADV_DISABLE *)
+          GKI_getbuf(sizeof(tBTA_DM_API_BLE_MULTI_ADV_DISABLE))) != NULL)
+    {
+         memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_MULTI_ADV_DISABLE));
+         p_msg->hdr.event    = BTA_DM_API_BLE_MULTI_ADV_DISABLE_EVT;
+         p_msg->inst_id      = inst_id;
+         bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleCfgFilterCondition
+**
+** Description      This function is called to configure the adv data payload filter
+**                  condition.
+**
+** Parameters       action: to read/write/clear
+**                  cond_type: filter condition type
+**                  filt_index - Filter index
+**                  p_cond: filter condition parameter
+**                  p_cmpl_back - Command completed callback
+**                  ref_value - Reference value
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBleCfgFilterCondition(tBTA_DM_BLE_SCAN_COND_OP action,
+                                 tBTA_DM_BLE_PF_COND_TYPE cond_type,
+                                 tBTA_DM_BLE_PF_FILT_INDEX filt_index,
+                                 tBTA_DM_BLE_PF_COND_PARAM *p_cond,
+                                 tBTA_DM_BLE_PF_CFG_CBACK *p_cmpl_cback,
+                                 tBTA_DM_BLE_REF_VALUE ref_value)
+{
+#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
+    tBTA_DM_API_CFG_FILTER_COND *p_msg;
+    APPL_TRACE_API ("BTA_DmBleCfgFilterCondition: %d, %d", action, cond_type);
+
+    UINT16  len = sizeof(tBTA_DM_API_CFG_FILTER_COND) +
+                  sizeof(tBTA_DM_BLE_PF_COND_PARAM);
+    UINT8 *p;
+
+    if (NULL != p_cond)
+    {
+        switch(cond_type)
+        {
+            case BTA_DM_BLE_PF_SRVC_DATA_PATTERN:
+            case BTA_DM_BLE_PF_MANU_DATA:
+                /* Length of pattern and pattern mask and other elements in */
+                /* tBTA_DM_BLE_PF_MANU_COND */
+                len += ((p_cond->manu_data.data_len) * 2) +
+                        sizeof(UINT16) + sizeof(UINT16) + sizeof(UINT8);
+                break;
+
+            case BTA_DM_BLE_PF_LOCAL_NAME:
+                len += ((p_cond->local_name.data_len) + sizeof(UINT8));
+                break;
+
+            case BTM_BLE_PF_SRVC_UUID:
+            case BTM_BLE_PF_SRVC_SOL_UUID:
+                len += sizeof(tBLE_BD_ADDR) + sizeof(tBTA_DM_BLE_PF_COND_MASK);
+                break;
+
+            default:
+                break;
+        }
+    }
+
+    if ((p_msg = (tBTA_DM_API_CFG_FILTER_COND *) GKI_getbuf(len)) != NULL)
+    {
+        memset (p_msg, 0, len);
+
+        p_msg->hdr.event        = BTA_DM_API_CFG_FILTER_COND_EVT;
+        p_msg->action           = action;
+        p_msg->cond_type        = cond_type;
+        p_msg->filt_index       = filt_index;
+        p_msg->p_filt_cfg_cback = p_cmpl_cback;
+        p_msg->ref_value        = ref_value;
+        if (p_cond)
+        {
+            p_msg->p_cond_param = (tBTA_DM_BLE_PF_COND_PARAM *)(p_msg + 1);
+            memcpy(p_msg->p_cond_param, p_cond, sizeof(tBTA_DM_BLE_PF_COND_PARAM));
+
+            p = (UINT8 *)(p_msg->p_cond_param + 1);
+
+            if (cond_type == BTA_DM_BLE_PF_SRVC_DATA_PATTERN ||
+                cond_type == BTA_DM_BLE_PF_MANU_DATA)
+            {
+                p_msg->p_cond_param->manu_data.p_pattern = p;
+                p_msg->p_cond_param->manu_data.data_len = p_cond->manu_data.data_len;
+                memcpy(p_msg->p_cond_param->manu_data.p_pattern, p_cond->manu_data.p_pattern,
+                    p_cond->manu_data.data_len);
+                p += p_cond->manu_data.data_len;
+
+                if (cond_type == BTA_DM_BLE_PF_MANU_DATA)
+                {
+                    p_msg->p_cond_param->manu_data.company_id_mask =
+                        p_cond->manu_data.company_id_mask;
+                    if ( p_cond->manu_data.p_pattern_mask != NULL)
+                    {
+                        p_msg->p_cond_param->manu_data.p_pattern_mask = p;
+                        memcpy(p_msg->p_cond_param->manu_data.p_pattern_mask,
+                            p_cond->manu_data.p_pattern_mask, p_cond->manu_data.data_len);
+                    }
+                }
+            }
+            else if (cond_type == BTA_DM_BLE_PF_LOCAL_NAME)
+            {
+                p_msg->p_cond_param->local_name.p_data = p;
+                p_msg->p_cond_param->local_name.data_len =
+                    p_cond->local_name.data_len;
+                memcpy(p_msg->p_cond_param->local_name.p_data,
+                    p_cond->local_name.p_data, p_cond->local_name.data_len);
+            }
+            else if ((cond_type == BTM_BLE_PF_SRVC_UUID
+                || cond_type == BTM_BLE_PF_SRVC_SOL_UUID))
+            {
+                if (p_cond->srvc_uuid.p_target_addr != NULL)
+                {
+                    p_msg->p_cond_param->srvc_uuid.p_target_addr = (tBLE_BD_ADDR *)(p);
+                    p_msg->p_cond_param->srvc_uuid.p_target_addr->type =
+                        p_cond->srvc_uuid.p_target_addr->type;
+                    memcpy(p_msg->p_cond_param->srvc_uuid.p_target_addr->bda,
+                        p_cond->srvc_uuid.p_target_addr->bda, BD_ADDR_LEN);
+                    p = (UINT8*)( p_msg->p_cond_param->srvc_uuid.p_target_addr + 1);
+                }
+                if (p_cond->srvc_uuid.p_uuid_mask)
+                {
+                    p_msg->p_cond_param->srvc_uuid.p_uuid_mask = (tBTA_DM_BLE_PF_COND_MASK *)p;
+                    memcpy(p_msg->p_cond_param->srvc_uuid.p_uuid_mask,
+                        p_cond->srvc_uuid.p_uuid_mask, sizeof(tBTA_DM_BLE_PF_COND_MASK));
+                }
+            }
+        }
+
+        bta_sys_sendmsg(p_msg);
+    }
+#else
+    UNUSED(action);
+    UNUSED(cond_type);
+    UNUSED(filt_index);
+    UNUSED(p_cond);
+    UNUSED(p_cmpl_cback);
+    UNUSED(ref_value);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleScanFilterSetup
+**
+** Description      This function is called to setup the adv data payload filter param
+**
+** Parameters       p_target: enable the filter condition on a target device; if NULL
+**                  filt_index - Filter index
+**                  p_filt_params -Filter parameters
+**                  ref_value - Reference value
+**                  action - Add, delete or clear
+**                  p_cmpl_back - Command completed callback
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBleScanFilterSetup(UINT8 action, tBTA_DM_BLE_PF_FILT_INDEX filt_index,
+                                    tBTA_DM_BLE_PF_FILT_PARAMS *p_filt_params,
+                                    tBLE_BD_ADDR *p_target,
+                                    tBTA_DM_BLE_PF_PARAM_CBACK *p_cmpl_cback,
+                                    tBTA_DM_BLE_REF_VALUE ref_value)
+{
+#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
+    tBTA_DM_API_SCAN_FILTER_PARAM_SETUP *p_msg;
+    APPL_TRACE_API ("BTA_DmBleScanFilterSetup: %d", action);
+
+    UINT16  len = sizeof(tBTA_DM_API_SCAN_FILTER_PARAM_SETUP) + sizeof(tBLE_BD_ADDR);
+
+    if ((p_msg = (tBTA_DM_API_SCAN_FILTER_PARAM_SETUP *) GKI_getbuf(len)) != NULL)
+    {
+        memset (p_msg, 0, len);
+
+        p_msg->hdr.event        = BTA_DM_API_SCAN_FILTER_SETUP_EVT;
+        p_msg->action       = action;
+        p_msg->filt_index = filt_index;
+        if (p_filt_params)
+            memcpy(&p_msg->filt_params, p_filt_params, sizeof(tBTA_DM_BLE_PF_FILT_PARAMS));
+        p_msg->p_filt_param_cback = p_cmpl_cback;
+        p_msg->ref_value        = ref_value;
+
+        if (p_target)
+        {
+            p_msg->p_target = (tBLE_BD_ADDR *)(p_msg + 1);
+            memcpy(p_msg->p_target, p_target, sizeof(tBLE_BD_ADDR));
+        }
+
+        bta_sys_sendmsg(p_msg);
+    }
+#else
+    UNUSED(action);
+    UNUSED(filt_index);
+    UNUSED(p_filt_params);
+    UNUSED(p_target);
+    UNUSED(p_cmpl_cback);
+    UNUSED(ref_value);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleGetEnergyInfo
+**
+** Description      This function is called to obtain the energy info
+**
+** Parameters       p_cmpl_cback - Command complete callback
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBleGetEnergyInfo(tBTA_BLE_ENERGY_INFO_CBACK *p_cmpl_cback)
+{
+    tBTA_DM_API_ENERGY_INFO *p_msg;
+    APPL_TRACE_API ("BTA_DmBleGetEnergyInfo");
+
+    UINT16  len = sizeof(tBTA_DM_API_ENERGY_INFO) + sizeof(tBLE_BD_ADDR);
+
+    if ((p_msg = (tBTA_DM_API_ENERGY_INFO *) GKI_getbuf(len)) != NULL)
+    {
+        memset (p_msg, 0, len);
+        p_msg->hdr.event        = BTA_DM_API_BLE_ENERGY_INFO_EVT;
+        p_msg->p_energy_info_cback = p_cmpl_cback;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmEnableScanFilter
+**
+** Description      This function is called to enable the adv data payload filter
+**
+** Parameters       action - enable or disable the APCF feature
+**                  p_cmpl_cback - Command completed callback
+**                  ref_value - Reference value
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmEnableScanFilter(UINT8 action, tBTA_DM_BLE_PF_STATUS_CBACK *p_cmpl_cback,
+                                    tBTA_DM_BLE_REF_VALUE ref_value)
+{
+#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
+    tBTA_DM_API_ENABLE_SCAN_FILTER *p_msg;
+    APPL_TRACE_API ("BTA_DmEnableScanFilter: %d", action);
+
+    UINT16  len = sizeof(tBTA_DM_API_ENABLE_SCAN_FILTER) + sizeof(tBLE_BD_ADDR);
+
+    if ((p_msg = (tBTA_DM_API_ENABLE_SCAN_FILTER *) GKI_getbuf(len)) != NULL)
+    {
+        memset (p_msg, 0, len);
+
+        p_msg->hdr.event        = BTA_DM_API_SCAN_FILTER_ENABLE_EVT;
+        p_msg->action       = action;
+        p_msg->ref_value    = ref_value;
+        p_msg->p_filt_status_cback = p_cmpl_cback;
+
+        bta_sys_sendmsg(p_msg);
+    }
+#else
+    UNUSED(action);
+    UNUSED(p_cmpl_cback);
+    UNUSED(ref_value);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleUpdateConnectionParams
+**
+** Description      Update connection parameters, can only be used when connection is up.
+**
+** Parameters:      bd_addr   - BD address of the peer
+**                  min_int   -     minimum connection interval, [0x0004~ 0x4000]
+**                  max_int   -     maximum connection interval, [0x0004~ 0x4000]
+**                  latency   -     slave latency [0 ~ 500]
+**                  timeout   -     supervision timeout [0x000a ~ 0xc80]
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBleUpdateConnectionParams(BD_ADDR bd_addr, UINT16 min_int, UINT16 max_int,
+                                    UINT16 latency, UINT16 timeout)
+{
+    tBTA_DM_API_UPDATE_CONN_PARAM *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_UPDATE_CONN_PARAM *) GKI_getbuf(sizeof(tBTA_DM_API_UPDATE_CONN_PARAM))) != NULL)
+    {
+        memset (p_msg, 0, sizeof(tBTA_DM_API_UPDATE_CONN_PARAM));
+
+        p_msg->hdr.event = BTA_DM_API_UPDATE_CONN_PARAM_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->min_int   = min_int;
+        p_msg->max_int   = max_int;
+        p_msg->latency   = latency;
+        p_msg->timeout   = timeout;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleSetDataLength
+**
+** Description      This function is to set maximum LE data packet size
+**
+** Returns          void
+**
+**
+*******************************************************************************/
+void BTA_DmBleSetDataLength(BD_ADDR remote_device, UINT16 tx_data_length)
+{
+    tBTA_DM_API_BLE_SET_DATA_LENGTH *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_BLE_SET_DATA_LENGTH *)GKI_getbuf(sizeof(tBTA_DM_API_BLE_SET_DATA_LENGTH)))
+                  != NULL)
+    {
+        bdcpy(p_msg->remote_bda, remote_device);
+        p_msg->hdr.event = BTA_DM_API_SET_DATA_LENGTH_EVT;
+        p_msg->tx_data_length = tx_data_length;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+#endif
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetEncryption
+**
+** Description      This function is called to ensure that connection is
+**                  encrypted.  Should be called only on an open connection.
+**                  Typically only needed for connections that first want to
+**                  bring up unencrypted links, then later encrypt them.
+**
+** Parameters:      bd_addr       - Address of the peer device
+**                  transport     - transport of the link to be encruypted
+**                  p_callback    - Pointer to callback function to indicat the
+**                                  link encryption status
+**                  sec_act       - This is the security action to indicate
+**                                  what knid of BLE security level is required for
+**                                  the BLE link if the BLE is supported
+**                                  Note: This parameter is ignored for the BR/EDR link
+**                                        or the BLE is not supported
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSetEncryption(BD_ADDR bd_addr, tBTA_TRANSPORT transport, tBTA_DM_ENCRYPT_CBACK *p_callback,
+                            tBTA_DM_BLE_SEC_ACT sec_act)
+{
+    tBTA_DM_API_SET_ENCRYPTION   *p_msg;
+
+    APPL_TRACE_API("BTA_DmSetEncryption"); //todo
+    if ((p_msg = (tBTA_DM_API_SET_ENCRYPTION *) GKI_getbuf(sizeof(tBTA_DM_API_SET_ENCRYPTION))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_SET_ENCRYPTION));
+
+        p_msg->hdr.event = BTA_DM_API_SET_ENCRYPTION_EVT;
+
+        memcpy(p_msg->bd_addr, bd_addr, BD_ADDR_LEN);
+        p_msg->transport    = transport;
+        p_msg->p_callback      = p_callback;
+        p_msg->sec_act         = sec_act;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmCloseACL
+**
+** Description      This function force to close an ACL connection and remove the
+**                  device from the security database list of known devices.
+**
+** Parameters:      bd_addr       - Address of the peer device
+**                  remove_dev    - remove device or not after link down
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmCloseACL(BD_ADDR bd_addr, BOOLEAN remove_dev, tBTA_TRANSPORT transport)
+{
+    tBTA_DM_API_REMOVE_ACL   *p_msg;
+
+    APPL_TRACE_API("BTA_DmCloseACL");
+
+    if ((p_msg = (tBTA_DM_API_REMOVE_ACL *) GKI_getbuf(sizeof(tBTA_DM_API_REMOVE_ACL))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_REMOVE_ACL));
+
+        p_msg->hdr.event = BTA_DM_API_REMOVE_ACL_EVT;
+
+        memcpy(p_msg->bd_addr, bd_addr, BD_ADDR_LEN);
+        p_msg->remove_dev      = remove_dev;
+        p_msg->transport       = transport;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+#if BLE_INCLUDED == TRUE
+/*******************************************************************************
+**
+** Function         BTA_DmBleObserve
+**
+** Description      This procedure keep the device listening for advertising
+**                  events from a broadcast device.
+**
+** Parameters       start: start or stop observe.
+**
+** Returns          void
+
+**
+** Returns          void.
+**
+*******************************************************************************/
+extern void BTA_DmBleObserve(BOOLEAN start, UINT8 duration,
+                             tBTA_DM_SEARCH_CBACK *p_results_cb)
+{
+    tBTA_DM_API_BLE_OBSERVE   *p_msg;
+
+    APPL_TRACE_API("BTA_DmBleObserve:start = %d ", start);
+
+    if ((p_msg = (tBTA_DM_API_BLE_OBSERVE *) GKI_getbuf(sizeof(tBTA_DM_API_BLE_OBSERVE))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_OBSERVE));
+
+        p_msg->hdr.event = BTA_DM_API_BLE_OBSERVE_EVT;
+        p_msg->start = start;
+        p_msg->duration = duration;
+        p_msg->p_cback = p_results_cb;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetRandAddress
+**
+** Description      This function set the random address for the APP
+**
+** Parameters       rand_addr: the random address whith should be setting
+** 
+** Returns          void
+**
+**
+*******************************************************************************/
+extern void BTA_DmSetRandAddress(BD_ADDR rand_addr)
+{
+	tBTA_DM_APT_SET_DEV_ADDR *p_msg;
+	APPL_TRACE_API("set the random address ");
+	 if ((p_msg = (tBTA_DM_APT_SET_DEV_ADDR *) GKI_getbuf(sizeof(tBTA_DM_APT_SET_DEV_ADDR))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_APT_SET_DEV_ADDR));
+		memcpy(p_msg->address,rand_addr,BD_ADDR_LEN);
+        p_msg->hdr.event = BTA_DM_API_SET_RAND_ADDR_EVT;
+		p_msg->addr_type = BLE_ADDR_RANDOM;
+      	//start sent the msg to the bta system control moudle
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_VendorInit
+**
+** Description      This function initializes vendor specific
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_VendorInit (void)
+{
+    APPL_TRACE_API("BTA_VendorInit");
+}
+
+/*******************************************************************************
+**
+** Function         BTA_VendorCleanup
+**
+** Description      This function frees up Broadcom specific VS specific dynamic memory
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_VendorCleanup (void)
+{
+    tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
+    BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
+
+#if (BLE_INCLUDED == TRUE && BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE)
+    if (cmn_ble_vsc_cb.max_filter > 0)
+    {
+        btm_ble_adv_filter_cleanup();
+#if BLE_PRIVACY_SPT == TRUE
+        btm_ble_resolving_list_cleanup ();
+#endif
+    }
+
+    if (cmn_ble_vsc_cb.tot_scan_results_strg > 0)
+        btm_ble_batchscan_cleanup();
+#endif
+
+   if(cmn_ble_vsc_cb.adv_inst_max > 0)
+      btm_ble_multi_adv_cleanup();
+}
+
+#endif

+ 587 - 0
components/bt/bluedroid/bta/dm/bta_dm_cfg.c

@@ -0,0 +1,587 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This file contains compile-time configurable constants for the device
+ *  manager.
+ *
+ ******************************************************************************/
+
+#include <stddef.h>
+#include "bt_target.h"
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_dm_int.h"
+// #include "bta_jv_api.h"
+
+#ifndef BTA_DM_LINK_POLICY_SETTINGS
+#define BTA_DM_LINK_POLICY_SETTINGS    (HCI_ENABLE_MASTER_SLAVE_SWITCH | HCI_ENABLE_HOLD_MODE | HCI_ENABLE_SNIFF_MODE | HCI_ENABLE_PARK_MODE)
+#endif
+
+/* page timeout in 625uS */
+#ifndef BTA_DM_PAGE_TIMEOUT
+#define BTA_DM_PAGE_TIMEOUT    8192
+#endif
+
+/* link supervision timeout in 625uS (5 secs) */
+#ifndef BTA_DM_LINK_TIMEOUT
+#define BTA_DM_LINK_TIMEOUT    8000
+#endif
+
+/* TRUE to avoid scatternet when av is streaming (be the master) */
+#ifndef BTA_DM_AVOID_SCATTER_A2DP
+#define BTA_DM_AVOID_SCATTER_A2DP    TRUE
+#endif
+
+/* For Insight, PM cfg lookup tables are runtime configurable (to allow tweaking of params for power consumption measurements) */
+#ifndef BTE_SIM_APP
+#define tBTA_DM_PM_TYPE_QUALIFIER   const
+#else
+#define tBTA_DM_PM_TYPE_QUALIFIER
+#endif
+
+
+const tBTA_DM_CFG bta_dm_cfg =
+{
+    /* mobile phone COD */
+    BTA_DM_COD,
+    /* link policy settings */
+    BTA_DM_LINK_POLICY_SETTINGS,
+    /* page timeout in 625uS */
+    BTA_DM_PAGE_TIMEOUT,
+    /* link supervision timeout in 625uS*/
+    BTA_DM_LINK_TIMEOUT,
+    /* TRUE to avoid scatternet when av is streaming (be the master) */
+    BTA_DM_AVOID_SCATTER_A2DP
+};
+
+#ifndef BTA_DM_SCATTERNET
+/* By default, allow partial scatternet */
+#define BTA_DM_SCATTERNET BTA_DM_PARTIAL_SCATTERNET
+#endif
+
+#ifndef BTA_HH_ROLE
+/* By default, do not specify HH role (backward compatibility) */
+#define BTA_HH_ROLE BTA_ANY_ROLE
+#endif
+
+#ifndef BTA_AV_ROLE
+/* By default, AV role (backward BTA_MASTER_ROLE_PREF) */
+#define BTA_AV_ROLE BTA_MASTER_ROLE_PREF
+#endif
+
+#ifndef BTA_PANU_ROLE
+/* By default, AV role (backward BTA_MASTER_ROLE_PREF) */
+#define BTA_PANU_ROLE BTA_SLAVE_ROLE_ONLY
+#endif
+#define BTA_DM_NUM_RM_ENTRY    6
+
+/* appids for PAN used by insight sample application
+   these have to be same as defined in btui_int.h */
+#define BTUI_PAN_ID_PANU         0
+#define BTUI_PAN_ID_NAP          1
+#define BTUI_PAN_ID_GN           2
+
+/* First element is always for SYS:
+   app_id = # of entries table, cfg is
+   device scatternet support */
+const tBTA_DM_RM bta_dm_rm_cfg[] =
+{
+    {BTA_ID_SYS, BTA_DM_NUM_RM_ENTRY, BTA_DM_SCATTERNET},
+    {BTA_ID_PAN, BTUI_PAN_ID_NAP, BTA_ANY_ROLE},
+    {BTA_ID_PAN, BTUI_PAN_ID_GN, BTA_ANY_ROLE},
+    {BTA_ID_PAN, BTA_APP_ID_PAN_MULTI, BTA_MASTER_ROLE_ONLY},
+    {BTA_ID_PAN, BTUI_PAN_ID_PANU, BTA_PANU_ROLE},
+    {BTA_ID_HH,  BTA_ALL_APP_ID, BTA_HH_ROLE},
+    {BTA_ID_AV,  BTA_ALL_APP_ID, BTA_AV_ROLE}
+};
+
+
+tBTA_DM_CFG *p_bta_dm_cfg = (tBTA_DM_CFG *)&bta_dm_cfg;
+
+tBTA_DM_RM *p_bta_dm_rm_cfg = (tBTA_DM_RM *)&bta_dm_rm_cfg;
+
+#if BLE_INCLUDED == TRUE
+#  define BTA_DM_NUM_PM_ENTRY         21  /* number of entries in bta_dm_pm_cfg except the first */
+#  define BTA_DM_NUM_PM_SPEC          15  /* number of entries in bta_dm_pm_spec */
+#else
+#  define BTA_DM_NUM_PM_ENTRY         19  /* number of entries in bta_dm_pm_cfg except the first */
+#  define BTA_DM_NUM_PM_SPEC          13  /* number of entries in bta_dm_pm_spec */
+#endif
+
+tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_CFG bta_dm_pm_cfg[BTA_DM_NUM_PM_ENTRY + 1] =
+{
+  {BTA_ID_SYS, BTA_DM_NUM_PM_ENTRY, 0},  /* reserved: specifies length of this table. */
+  {BTA_ID_AG,  BTA_ALL_APP_ID,      0},  /* ag uses first spec table for app id 0 */
+  {BTA_ID_CT,  1,                   1},  /* ct (BTA_ID_CT,APP ID=1) spec table */
+  {BTA_ID_CG,  BTA_ALL_APP_ID,      1},  /* cg resue ct spec table */
+  {BTA_ID_DG,  BTA_ALL_APP_ID,      2},  /* dg spec table */
+  {BTA_ID_AV,  BTA_ALL_APP_ID,      4},  /* av spec table */
+  {BTA_ID_AVK, BTA_ALL_APP_ID,     12},  /* avk spec table */
+  {BTA_ID_FTC, BTA_ALL_APP_ID,      6},  /* ftc spec table */
+  {BTA_ID_FTS, BTA_ALL_APP_ID,      7},  /* fts spec table */
+  {BTA_ID_HD,  BTA_ALL_APP_ID,      3},  /* hd spec table */
+  {BTA_ID_HH,  BTA_ALL_APP_ID,      5},  /* hh spec table */
+  {BTA_ID_PBC, BTA_ALL_APP_ID,      2},  /* reuse dg spec table */
+  {BTA_ID_PBS, BTA_ALL_APP_ID,      7},  /* reuse fts spec table */
+  {BTA_ID_OPC, BTA_ALL_APP_ID,      6},  /* reuse ftc spec table */
+  {BTA_ID_OPS, BTA_ALL_APP_ID,      7},  /* reuse fts spec table */
+  {BTA_ID_MSE, BTA_ALL_APP_ID,      7},  /* reuse fts spec table */
+  // {BTA_ID_JV,  BTA_JV_PM_ID_1,      6},  /* app BTA_JV_PM_ID_1, reuse ftc spec table */
+  // {BTA_ID_JV,  BTA_ALL_APP_ID,      7},  /* reuse fts spec table */
+  {BTA_ID_HL,  BTA_ALL_APP_ID,      8},  /* reuse fts spec table */
+  {BTA_ID_PAN, BTUI_PAN_ID_PANU,    9},  /* PANU spec table */
+  {BTA_ID_PAN, BTUI_PAN_ID_NAP,    10},  /* NAP spec table */
+  {BTA_ID_HS,  BTA_ALL_APP_ID,     11}   /* HS spec table */
+#if BLE_INCLUDED == TRUE
+  ,{BTA_ID_GATTC,  BTA_ALL_APP_ID,  13}  /* gattc spec table */
+  ,{BTA_ID_GATTS,  BTA_ALL_APP_ID,  14}  /* gatts spec table */
+#endif
+};
+
+tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] =
+{
+  /* AG : 0 */
+ {
+  (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK),                           /* allow park & sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR2),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_SNIFF_A2DP_IDX,  7000},   {BTA_DM_PM_NO_ACTION, 0}},   /* conn open sniff  */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},   /* conn close  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},   /* app open */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},   /* app close */
+      {{BTA_DM_PM_SNIFF_SCO_OPEN_IDX, 7000},   {BTA_DM_PM_NO_ACTION, 0}},   /* sco open, active */
+      {{BTA_DM_PM_SNIFF_A2DP_IDX,  7000},   {BTA_DM_PM_NO_ACTION, 0}},   /* sco close sniff  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},   /* idle */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},   /* busy */
+      {{BTA_DM_PM_RETRY,  7000},   {BTA_DM_PM_NO_ACTION, 0}}    /* mode change retry */
+  }
+ },
+
+  /* CT, CG : 1 */
+ {
+  (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK),                           /* allow park & sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR2),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_PARK,   5000},  {BTA_DM_PM_NO_ACTION, 0}},    /* conn open  park */
+      {{BTA_DM_PM_NO_PREF,   0},  {BTA_DM_PM_NO_ACTION, 0}},    /* conn close  */
+      {{BTA_DM_PM_NO_ACTION, 0},  {BTA_DM_PM_NO_ACTION, 0}},    /* app open */
+      {{BTA_DM_PM_NO_ACTION, 0},  {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
+      {{BTA_DM_PM_SNIFF_A2DP_IDX, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open sniff */
+      {{BTA_DM_PM_PARK,   5000},  {BTA_DM_PM_NO_ACTION, 0}},    /* sco close  park */
+      {{BTA_DM_PM_NO_ACTION, 0},  {BTA_DM_PM_NO_ACTION, 0}},    /* idle */
+      {{BTA_DM_PM_NO_ACTION, 0},  {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
+      {{BTA_DM_PM_RETRY,  5000},  {BTA_DM_PM_NO_ACTION, 0}}     /* mode change retry */
+  }
+ },
+
+  /* DG, PBC : 2 */
+ {
+  (BTA_DM_PM_ACTIVE),                                             /* no power saving mode allowed */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR2),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_SNIFF,  5000},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn open active */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn close  */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app open */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco open  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco close   */
+      {{BTA_DM_PM_SNIFF,  1000},   {BTA_DM_PM_NO_ACTION, 0}},    /* idle */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}}     /* mode change retry */
+  }
+ },
+
+   /* HD : 3 */
+ {
+  (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK),                            /* allow park & sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR3),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_SNIFF_HD_ACTIVE_IDX, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn close */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app open */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco open  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco close */
+      {{BTA_DM_PM_SNIFF_HD_IDLE_IDX, 5000}, {BTA_DM_PM_NO_ACTION, 0}},   /* idle */
+      {{BTA_DM_PM_SNIFF_HD_ACTIVE_IDX, 0}, {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}}     /* mode change retry */
+  }
+ },
+
+   /* AV : 4 */
+ {
+  (BTA_DM_PM_SNIFF),                                             /* allow sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR2),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_SNIFF_A2DP_IDX, 7000}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open  sniff */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn close  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app open */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco open  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco close   */
+      {{BTA_DM_PM_SNIFF_A2DP_IDX, 7000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}}     /* mode change retry */
+  }
+ },
+
+  /* HH : 5 */
+ {
+  (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK),                            /* allow park & sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR1),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_SNIFF_HH_OPEN_IDX, BTA_DM_PM_HH_OPEN_DELAY},{BTA_DM_PM_NO_ACTION, 0}}, /* conn open  sniff */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn close  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app open */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco open  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco close, used for HH suspend   */
+      {{BTA_DM_PM_SNIFF_HH_IDLE_IDX, BTA_DM_PM_HH_IDLE_DELAY},   {BTA_DM_PM_NO_ACTION, 0}},    /* idle */
+      {{BTA_DM_PM_SNIFF_HH_ACTIVE_IDX, BTA_DM_PM_HH_ACTIVE_DELAY},   {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}}     /* mode change retry */
+  }
+ },
+
+  /* FTC, OPC, JV : 6 */
+ {
+  (BTA_DM_PM_SNIFF),                                             /* allow sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR2),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn open  active */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn close  */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app open */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco open  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco close   */
+      {{BTA_DM_PM_SNIFF_A2DP_IDX, 5000},   {BTA_DM_PM_NO_ACTION, 0}},    /* idle */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}}     /* mode change retry */
+  }
+ },
+
+  /* FTS, PBS, OPS, MSE, BTA_JV_PM_ID_1 : 7 */
+ {
+  (BTA_DM_PM_SNIFF),                                             /* allow sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR2),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn open  active */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn close  */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app open */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco open  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco close   */
+      {{BTA_DM_PM_SNIFF_A2DP_IDX, BTA_FTS_OPS_IDLE_TO_SNIFF_DELAY_MS}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}}     /* mode change retry */
+  }
+ },
+
+   /* HL : 8 */
+ {
+  (BTA_DM_PM_SNIFF),                                             /* allow sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR2),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_SNIFF_A2DP_IDX, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff  */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},   /* conn close  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},   /* app open */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},   /* app close */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},   /* sco open, active */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},   /* sco close sniff  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},   /* idle */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},   /* busy */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}}    /* mode change retry */
+  }
+ },
+
+  /* PANU : 9 */
+ {
+  (BTA_DM_PM_SNIFF),                                             /* allow sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR2),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn open  active */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn close  */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app open */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco open  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco close   */
+      {{BTA_DM_PM_SNIFF_A2DP_IDX, 5000},   {BTA_DM_PM_NO_ACTION, 0}},    /* idle */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}}     /* mode change retry */
+  }
+ },
+
+  /* NAP : 10 */
+ {
+  (BTA_DM_PM_SNIFF),                                             /* allow sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR2),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn open  active */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn close  */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app open */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco open  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco close   */
+      {{BTA_DM_PM_SNIFF_A2DP_IDX, 5000},   {BTA_DM_PM_NO_ACTION, 0}},    /* idle */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},   /* busy */
+
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}}     /* mode change retry */
+  }
+ },
+
+  /* HS : 11 */
+ {
+  (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK),                           /* allow park & sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR2),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_SNIFF,  7000},   {BTA_DM_PM_NO_ACTION, 0}},   /* conn open sniff  */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},   /* conn close  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},   /* app open */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},   /* app close */
+      {{BTA_DM_PM_SNIFF3, 7000},   {BTA_DM_PM_NO_ACTION, 0}},   /* sco open, active */
+      {{BTA_DM_PM_SNIFF,  7000},   {BTA_DM_PM_NO_ACTION, 0}},   /* sco close sniff  */
+      {{BTA_DM_PM_SNIFF,  7000},   {BTA_DM_PM_NO_ACTION, 0}},   /* idle */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},   /* busy */
+      {{BTA_DM_PM_RETRY,  7000},   {BTA_DM_PM_NO_ACTION, 0}}    /* mode change retry */
+  }
+ },
+
+  /* AVK : 12 */
+ {
+  (BTA_DM_PM_SNIFF),                                             /* allow sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR2),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_SNIFF,  3000},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn open  sniff */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn close  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app open */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco open  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco close   */
+      {{BTA_DM_PM_SNIFF4, 3000},   {BTA_DM_PM_NO_ACTION, 0}},    /* idle */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}}     /* mode change retry */
+  }
+ }
+
+#if BLE_INCLUDED == TRUE
+    /* GATTC : 13 */
+ ,{
+  (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK),                           /* allow park & sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR2),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_SNIFF_A2DP_IDX, 10000}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open  active */
+      {{BTA_DM_PM_NO_PREF,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn close  */
+      {{BTA_DM_PM_ACTIVE,     0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app open */
+      {{BTA_DM_PM_NO_ACTION,  0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
+      {{BTA_DM_PM_NO_ACTION,  0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco open  */
+      {{BTA_DM_PM_NO_ACTION,  0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco close   */
+      {{BTA_DM_PM_SNIFF_A2DP_IDX, 10000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+      {{BTA_DM_PM_ACTIVE,     0},   {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
+#if defined(AMP_INCLUDED) && (AMP_INCLUDED == TRUE)
+      {{BTA_DM_PM_NO_ACTION,  0},   {BTA_DM_PM_NO_ACTION, 0}},   /* amp */
+#endif
+      {{BTA_DM_PM_RETRY,   5000},   {BTA_DM_PM_NO_ACTION, 0}}    /* mode change retry */
+  }
+ }
+    /* GATTS : 14 */
+ ,{
+  (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK),                           /* allow park & sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR2),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn open  active */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn close  */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app open */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco open  */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco close   */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* idle */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
+#if defined(AMP_INCLUDED) && (AMP_INCLUDED == TRUE)
+      {{BTA_DM_PM_NO_PREF, 0},   {BTA_DM_PM_NO_ACTION, 0}},   /* amp */
+#endif
+      {{BTA_DM_PM_RETRY,  5000},   {BTA_DM_PM_NO_ACTION, 0}}    /* mode change retry */
+  }
+ }
+
+#endif
+
+#ifdef BTE_SIM_APP      /* For Insight builds only */
+ /* Entries at the end of the pm_spec table are user-defined (runtime configurable),
+    for power consumption experiments.
+    Insight finds the first user-defined entry by looking for the first BTA_DM_PM_NO_PREF.
+    The number of user_defined specs is defined by BTA_SWRAP_UD_PM_SPEC_COUNT */
+ ,
+ {BTA_DM_PM_NO_PREF},               /* pm_spec USER_DEFINED_0 */
+ {BTA_DM_PM_NO_PREF}                /* pm_spec USER_DEFINED_1 */
+#endif  /* BTE_SIM_APP */
+};
+
+/* Please refer to the SNIFF table definitions in bta_api.h.
+ *
+ * Adding to or Modifying the Table
+ * Additional sniff parameter entries can be added for BTA_DM_PM_SNIFF5 - BTA_DM_PM_SNIFF7.
+ * Overrides of additional table entries can be specified in bdroid_buildcfg.h.  If additional
+ * sniff parameter entries are added or an override of an existing entry is specified in
+ * bdroid_buildcfg.h then the BTA_DM_PM_*_IDX defines in bta_api.h will need to be match the new
+ * ordering.
+ *
+ * Table Ordering
+ * Sniff Table entries must be ordered from highest latency (biggest interval) to lowest latency.
+ * If there is a conflict among the connected services the setting with the lowest latency will
+ * be selected.
+ */
+tBTA_DM_PM_TYPE_QUALIFIER tBTM_PM_PWR_MD bta_dm_pm_md[] =
+{
+/*
+ * More sniff parameter entries can be added for
+ * BTA_DM_PM_SNIFF3 - BTA_DM_PM_SNIFF7, if needed. When entries are added or
+ * removed, BTA_DM_PM_PARK_IDX needs to be updated to reflect the actual index
+ * BTA_DM_PM_PARK_IDX is defined in bta_api.h and can be override by the
+ * bdroid_buildcfg.h settings.
+ * The SNIFF table entries must be in the order from highest latency (biggest
+ * interval) to lowest latency. If there's a conflict among the connected
+ * services, the setting with lowest latency wins.
+ */
+/* sniff modes: max interval, min interval, attempt, timeout */
+  {BTA_DM_PM_SNIFF_MAX, BTA_DM_PM_SNIFF_MIN, BTA_DM_PM_SNIFF_ATTEMPT, BTA_DM_PM_SNIFF_TIMEOUT, BTM_PM_MD_SNIFF}, /* for BTA_DM_PM_SNIFF - A2DP */
+  {BTA_DM_PM_SNIFF1_MAX, BTA_DM_PM_SNIFF1_MIN, BTA_DM_PM_SNIFF1_ATTEMPT, BTA_DM_PM_SNIFF1_TIMEOUT, BTM_PM_MD_SNIFF}, /* for BTA_DM_PM_SNIFF1 */
+  {BTA_DM_PM_SNIFF2_MAX, BTA_DM_PM_SNIFF2_MIN, BTA_DM_PM_SNIFF2_ATTEMPT, BTA_DM_PM_SNIFF2_TIMEOUT, BTM_PM_MD_SNIFF}, /* for BTA_DM_PM_SNIFF2- HD idle */
+  {BTA_DM_PM_SNIFF3_MAX, BTA_DM_PM_SNIFF3_MIN, BTA_DM_PM_SNIFF3_ATTEMPT, BTA_DM_PM_SNIFF3_TIMEOUT, BTM_PM_MD_SNIFF}, /* for BTA_DM_PM_SNIFF3- SCO open */
+  {BTA_DM_PM_SNIFF4_MAX, BTA_DM_PM_SNIFF4_MIN, BTA_DM_PM_SNIFF4_ATTEMPT, BTA_DM_PM_SNIFF4_TIMEOUT, BTM_PM_MD_SNIFF}, /* for BTA_DM_PM_SNIFF4- HD active */
+  {BTA_DM_PM_SNIFF5_MAX, BTA_DM_PM_SNIFF5_MIN, BTA_DM_PM_SNIFF5_ATTEMPT, BTA_DM_PM_SNIFF5_TIMEOUT, BTM_PM_MD_SNIFF}, /* for BTA_DM_PM_SNIFF5- HD active */
+  {BTA_DM_PM_PARK_MAX, BTA_DM_PM_PARK_MIN, BTA_DM_PM_PARK_ATTEMPT, BTA_DM_PM_PARK_TIMEOUT, BTM_PM_MD_PARK}
+
+#ifdef BTE_SIM_APP      /* For Insight builds only */
+  /* Entries at the end of the bta_dm_pm_md table are user-defined (runtime configurable),
+     for power consumption experiments.
+     Insight finds the first user-defined entry by looking for the first 'max=0'.
+     The number of user_defined specs is defined by BTA_SWRAP_UD_PM_DM_COUNT */
+  ,
+  {0},           /* CONN_OPEN/SCO_CLOSE power mode settings for pm_spec USER_DEFINED_0 */
+  {0},           /* SCO_OPEN power mode settings for pm_spec USER_DEFINED_0 */
+
+  {0},           /* CONN_OPEN/SCO_CLOSE power mode settings for pm_spec USER_DEFINED_1 */
+  {0}            /* SCO_OPEN power mode settings for pm_spec USER_DEFINED_1 */
+#endif  /* BTE_SIM_APP */
+};
+
+/* 0=max_lat -> no SSR */
+/* the smaller of the SSR max latency wins.
+ * the entries in this table must be from highest latency (biggest interval) to lowest latency */
+#if (BTM_SSR_INCLUDED == TRUE)
+tBTA_DM_SSR_SPEC bta_dm_ssr_spec[] =
+{
+    /*max_lat, min_rmt_to, min_loc_to*/
+    {0,      0, 0},     /* BTA_DM_PM_SSR0 - do not use SSR */
+    {0,      0, 2},     /* BTA_DM_PM_SSR1 - HH, can NOT share entry with any other profile,
+                           seting default max latency and min remote timeout as 0,
+                           and always read individual device preference from HH module */
+    {1200,   2, 2},     /* BTA_DM_PM_SSR2 - others (as long as sniff is allowed)*/
+    {360,  160, 2}      /* BTA_DM_PM_SSR3 - HD */
+};
+
+tBTA_DM_SSR_SPEC *p_bta_dm_ssr_spec = (tBTA_DM_SSR_SPEC *)&bta_dm_ssr_spec;
+#endif
+
+tBTA_DM_PM_CFG *p_bta_dm_pm_cfg = (tBTA_DM_PM_CFG *)&bta_dm_pm_cfg;
+tBTA_DM_PM_SPEC *p_bta_dm_pm_spec = (tBTA_DM_PM_SPEC *)&bta_dm_pm_spec;
+tBTM_PM_PWR_MD *p_bta_dm_pm_md = (tBTM_PM_PWR_MD *)&bta_dm_pm_md;
+
+/* The performance impact of EIR packet size
+**
+** When BTM_EIR_DEFAULT_FEC_REQUIRED is TRUE,
+** 1 to 17 bytes,    DM1 is used and most robust.
+** 18 to 121 bytes,  DM3 is used but impacts inquiry scan time with large number
+**                    of devices.(almost double with 150 users)
+** 122 to 224 bytes, DM5 is used but cause quite big performance loss even with
+**                    small number of users. so it is not recommended.
+** 225 to 240 bytes, DH5 is used without FEC but it not recommended.
+**                    (same reason of DM5)
+**
+** When BTM_EIR_DEFAULT_FEC_REQUIRED is FALSE,
+** 1 to 27 bytes,    DH1 is used but only robust at short range.
+** 28 to 183 bytes,  DH3 is used but only robust at short range and impacts inquiry
+**                    scan time with large number of devices.
+** 184 to 240 bytes, DH5 is used but it not recommended.
+*/
+
+#if (BTA_EIR_CANNED_UUID_LIST == TRUE)
+                                            /* for example */
+const UINT8 bta_dm_eir_uuid16_list[] = {    0x08, 0x11, /* Headset */
+                                            0x1E, 0x11, /* Handsfree */
+                                            0x0E, 0x11, /* AV Remote Control */
+                                            0x0B, 0x11, /* Audio Sink */
+};
+#endif  // BTA_EIR_CANNED_UUID_LIST
+
+/* Extended Inquiry Response */
+const tBTA_DM_EIR_CONF bta_dm_eir_cfg =
+{
+    50,    /* minimum length of local name when it is shortened */
+           /* if length of local name is longer than this and EIR has not enough */
+           /* room for all UUID list then local name is shortened to this length */
+#if (BTA_EIR_CANNED_UUID_LIST == TRUE)
+    8,
+    (UINT8 *)bta_dm_eir_uuid16_list,
+#else // BTA_EIR_CANNED_UUID_LIST
+    {   /* mask of UUID list in EIR */
+        0xFFFFFFFF, /* LSB is the first UUID of the first 32 UUIDs in BTM_EIR_UUID_LKUP_TBL */
+        0xFFFFFFFF  /* LSB is the first UUID of the next 32 UUIDs in BTM_EIR_UUID_LKUP_TBL */
+        /* BTM_EIR_UUID_LKUP_TBL can be overrided */
+    },
+#endif  // BTA_EIR_CANNED_UUID_LIST
+    NULL,   /* Inquiry TX power         */
+    0,      /* length of flags in bytes */
+    NULL,   /* flags for EIR */
+    0,      /* length of manufacturer specific in bytes */
+    NULL,   /* manufacturer specific */
+    0,      /* length of additional data in bytes */
+    NULL    /* additional data */
+};
+tBTA_DM_EIR_CONF *p_bta_dm_eir_cfg = (tBTA_DM_EIR_CONF*)&bta_dm_eir_cfg;

+ 117 - 0
components/bt/bluedroid/bta/dm/bta_dm_ci.c

@@ -0,0 +1,117 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the API implementation file for the BTA device manager.
+ *
+ ******************************************************************************/
+
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_dm_int.h"
+#include <string.h>
+#include "bta_dm_ci.h"
+
+
+#if (BTM_OOB_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         bta_dm_ci_io_req
+**
+** Description      This function must be called in response to function
+**                  bta_dm_co_io_req(), if *p_oob_data to BTA_OOB_UNKNOWN
+**                  by bta_dm_co_io_req().
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_ci_io_req(BD_ADDR bd_addr, tBTA_IO_CAP io_cap, tBTA_OOB_DATA oob_data,
+                                     tBTA_AUTH_REQ auth_req)
+
+{
+    tBTA_DM_CI_IO_REQ    *p_msg;
+
+    if ((p_msg = (tBTA_DM_CI_IO_REQ *) GKI_getbuf(sizeof(tBTA_DM_CI_IO_REQ))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_CI_IO_REQ_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->io_cap   = io_cap;
+        p_msg->oob_data = oob_data;
+        p_msg->auth_req = auth_req;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ci_rmt_oob
+**
+** Description      This function must be called in response to function
+**                  bta_dm_co_rmt_oob() to provide the OOB data associated
+**                  with the remote device.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_ci_rmt_oob(BOOLEAN accept, BD_ADDR bd_addr, BT_OCTET16 c, BT_OCTET16 r)
+{
+    tBTA_DM_CI_RMT_OOB    *p_msg;
+
+    if ((p_msg = (tBTA_DM_CI_RMT_OOB *) GKI_getbuf(sizeof(tBTA_DM_CI_RMT_OOB))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_CI_RMT_OOB_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->accept    = accept;
+        memcpy(p_msg->c, c, BT_OCTET16_LEN);
+        memcpy(p_msg->r, r, BT_OCTET16_LEN);
+        bta_sys_sendmsg(p_msg);
+    }
+}
+#endif /* BTM_OOB_INCLUDED */
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         bta_dm_sco_ci_data_ready
+**
+** Description      This function sends an event to indicating that the phone
+**                  has SCO data ready.
+**
+** Parameters       event: is obtained from bta_dm_sco_co_open() function, which
+**                          is the BTA event we want to send back to BTA module
+**                          when there is encoded data ready.
+**                  sco_handle: is the BTA sco handle which indicate a specific
+**                           SCO connection.
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_sco_ci_data_ready(UINT16 event, UINT16 sco_handle)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = event;
+        p_buf->layer_specific = sco_handle;
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+#endif

+ 1199 - 0
components/bt/bluedroid/bta/dm/bta_dm_int.h

@@ -0,0 +1,1199 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the private interface file for the BTA device manager.
+ *
+ ******************************************************************************/
+#ifndef BTA_DM_INT_H
+#define BTA_DM_INT_H
+
+#include "bt_target.h"
+
+#if (BLE_INCLUDED == TRUE && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+    #include "bta_gatt_api.h"
+#endif
+
+
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+
+
+#define BTA_COPY_DEVICE_CLASS(coddst, codsrc)   {((UINT8 *)(coddst))[0] = ((UINT8 *)(codsrc))[0]; \
+                                                 ((UINT8 *)(coddst))[1] = ((UINT8 *)(codsrc))[1];  \
+                                                 ((UINT8 *)(coddst))[2] = ((UINT8 *)(codsrc))[2];}
+
+
+#define BTA_DM_MSG_LEN 50
+
+#define BTA_SERVICE_ID_TO_SERVICE_MASK(id)       (1 << (id))
+
+/* DM events */
+enum
+{
+    /* device manager local device API events */
+    BTA_DM_API_ENABLE_EVT = BTA_SYS_EVT_START(BTA_ID_DM),
+    BTA_DM_API_DISABLE_EVT,
+    BTA_DM_API_SET_NAME_EVT,
+    BTA_DM_API_SET_VISIBILITY_EVT,
+
+    BTA_DM_ACL_CHANGE_EVT,
+    BTA_DM_API_ADD_DEVICE_EVT,
+    BTA_DM_API_REMOVE_ACL_EVT,
+
+    /* security API events */
+    BTA_DM_API_BOND_EVT,
+    BTA_DM_API_BOND_CANCEL_EVT,
+    BTA_DM_API_PIN_REPLY_EVT,
+
+    /* power manger events */
+    BTA_DM_PM_BTM_STATUS_EVT,
+    BTA_DM_PM_TIMER_EVT,
+
+    /* simple pairing events */
+    BTA_DM_API_CONFIRM_EVT,
+
+    BTA_DM_API_SET_ENCRYPTION_EVT,
+
+#if (BTM_OOB_INCLUDED == TRUE)
+    BTA_DM_API_LOC_OOB_EVT,
+    BTA_DM_CI_IO_REQ_EVT,
+    BTA_DM_CI_RMT_OOB_EVT,
+#endif /* BTM_OOB_INCLUDED */
+
+
+#if BLE_INCLUDED == TRUE
+    BTA_DM_API_ADD_BLEKEY_EVT,
+    BTA_DM_API_ADD_BLEDEVICE_EVT,
+    BTA_DM_API_BLE_PASSKEY_REPLY_EVT,
+    BTA_DM_API_BLE_CONFIRM_REPLY_EVT,
+    BTA_DM_API_BLE_SEC_GRANT_EVT,
+    BTA_DM_API_BLE_SET_BG_CONN_TYPE,
+    BTA_DM_API_BLE_CONN_PARAM_EVT,
+    BTA_DM_API_BLE_CONN_SCAN_PARAM_EVT,
+    BTA_DM_API_BLE_SCAN_PARAM_EVT,
+    BTA_DM_API_BLE_OBSERVE_EVT,
+    BTA_DM_API_UPDATE_CONN_PARAM_EVT,
+    /*******This event added by Yulong at 2016/9/9 to 
+    support the random address setting for the APP******/
+    BTA_DM_API_SET_RAND_ADDR_EVT,
+#if BLE_PRIVACY_SPT == TRUE
+    BTA_DM_API_LOCAL_PRIVACY_EVT,
+#endif
+    BTA_DM_API_BLE_ADV_PARAM_EVT,
+    BTA_DM_API_BLE_SET_ADV_CONFIG_EVT,
+    BTA_DM_API_BLE_SET_SCAN_RSP_EVT,
+    BTA_DM_API_BLE_BROADCAST_EVT,
+    BTA_DM_API_SET_DATA_LENGTH_EVT,
+
+#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
+    BTA_DM_API_CFG_FILTER_COND_EVT,
+    BTA_DM_API_SCAN_FILTER_SETUP_EVT,
+    BTA_DM_API_SCAN_FILTER_ENABLE_EVT,
+#endif
+    BTA_DM_API_BLE_MULTI_ADV_ENB_EVT,
+    BTA_DM_API_BLE_MULTI_ADV_PARAM_UPD_EVT,
+    BTA_DM_API_BLE_MULTI_ADV_DATA_EVT,
+    BTA_DM_API_BLE_MULTI_ADV_DISABLE_EVT,
+    BTA_DM_API_BLE_SETUP_STORAGE_EVT,
+    BTA_DM_API_BLE_ENABLE_BATCH_SCAN_EVT,
+    BTA_DM_API_BLE_DISABLE_BATCH_SCAN_EVT,
+    BTA_DM_API_BLE_READ_SCAN_REPORTS_EVT,
+    BTA_DM_API_BLE_TRACK_ADVERTISER_EVT,
+    BTA_DM_API_BLE_ENERGY_INFO_EVT,
+
+#endif
+
+    BTA_DM_API_ENABLE_TEST_MODE_EVT,
+    BTA_DM_API_DISABLE_TEST_MODE_EVT,
+    BTA_DM_API_EXECUTE_CBACK_EVT,
+    BTA_DM_API_REMOVE_ALL_ACL_EVT,
+    BTA_DM_API_REMOVE_DEVICE_EVT,
+    BTA_DM_MAX_EVT
+};
+
+
+/* DM search events */
+enum
+{
+    /* DM search API events */
+    BTA_DM_API_SEARCH_EVT = BTA_SYS_EVT_START(BTA_ID_DM_SEARCH),
+    BTA_DM_API_SEARCH_CANCEL_EVT,
+    BTA_DM_API_DISCOVER_EVT,
+    BTA_DM_INQUIRY_CMPL_EVT,
+    BTA_DM_REMT_NAME_EVT,
+    BTA_DM_SDP_RESULT_EVT,
+    BTA_DM_SEARCH_CMPL_EVT,
+    BTA_DM_DISCOVERY_RESULT_EVT,
+    BTA_DM_API_DI_DISCOVER_EVT,
+    BTA_DM_DISC_CLOSE_TOUT_EVT
+
+};
+
+/* data type for BTA_DM_API_ENABLE_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    tBTA_DM_SEC_CBACK *p_sec_cback;
+} tBTA_DM_API_ENABLE;
+
+/* data type for BTA_DM_API_SET_NAME_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    BD_NAME             name; /* max 248 bytes name, plus must be Null terminated */
+} tBTA_DM_API_SET_NAME;
+
+/* data type for BTA_DM_API_SET_VISIBILITY_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    tBTA_DM_DISC    disc_mode;
+    tBTA_DM_CONN    conn_mode;
+    UINT8           pair_mode;
+    UINT8           conn_paired_only;
+} tBTA_DM_API_SET_VISIBILITY;
+
+enum
+{
+    BTA_DM_RS_NONE,     /* straight API call */
+    BTA_DM_RS_OK,       /* the role switch result - successful */
+    BTA_DM_RS_FAIL      /* the role switch result - failed */
+};
+typedef UINT8 tBTA_DM_RS_RES;
+
+/* data type for BTA_DM_API_SEARCH_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    tBTA_DM_INQ inq_params;
+    tBTA_SERVICE_MASK services;
+    tBTA_DM_SEARCH_CBACK * p_cback;
+    tBTA_DM_RS_RES  rs_res;
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    UINT8           num_uuid;
+    tBT_UUID        *p_uuid;
+#endif
+} tBTA_DM_API_SEARCH;
+
+/* data type for BTA_DM_API_DISCOVER_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    BD_ADDR bd_addr;
+    tBTA_SERVICE_MASK services;
+    tBTA_DM_SEARCH_CBACK * p_cback;
+    BOOLEAN         sdp_search;
+    tBTA_TRANSPORT  transport;
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    UINT8           num_uuid;
+    tBT_UUID        *p_uuid;
+#endif
+    tSDP_UUID    uuid;
+} tBTA_DM_API_DISCOVER;
+
+/* data type for BTA_DM_API_DI_DISC_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    BD_ADDR             bd_addr;
+    tBTA_DISCOVERY_DB   *p_sdp_db;
+    UINT32              len;
+    tBTA_DM_SEARCH_CBACK * p_cback;
+}tBTA_DM_API_DI_DISC;
+
+/* data type for BTA_DM_API_BOND_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    BD_ADDR bd_addr;
+    tBTA_TRANSPORT transport;
+} tBTA_DM_API_BOND;
+
+/* data type for BTA_DM_API_BOND_CANCEL_EVT */
+typedef struct
+{
+    BT_HDR          hdr;
+    BD_ADDR         bd_addr;
+    tBTA_TRANSPORT  transport;
+} tBTA_DM_API_BOND_CANCEL;
+
+/* data type for BTA_DM_API_PIN_REPLY_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    BD_ADDR bd_addr;
+    BOOLEAN accept;
+    UINT8 pin_len;
+    UINT8 p_pin[PIN_CODE_LEN];
+} tBTA_DM_API_PIN_REPLY;
+
+/* data type for BTA_DM_API_LOC_OOB_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+} tBTA_DM_API_LOC_OOB;
+
+/* data type for BTA_DM_API_CONFIRM_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    BD_ADDR     bd_addr;
+    BOOLEAN     accept;
+} tBTA_DM_API_CONFIRM;
+
+/* data type for BTA_DM_CI_IO_REQ_EVT */
+typedef struct
+{
+    BT_HDR          hdr;
+    BD_ADDR         bd_addr;
+    tBTA_IO_CAP     io_cap;
+    tBTA_OOB_DATA   oob_data;
+    tBTA_AUTH_REQ   auth_req;
+} tBTA_DM_CI_IO_REQ;
+
+/* data type for BTA_DM_CI_RMT_OOB_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    BD_ADDR     bd_addr;
+    BT_OCTET16  c;
+    BT_OCTET16  r;
+    BOOLEAN     accept;
+} tBTA_DM_CI_RMT_OOB;
+
+/* data type for BTA_DM_REMT_NAME_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    tBTA_DM_SEARCH  result;
+} tBTA_DM_REM_NAME;
+
+/* data type for tBTA_DM_DISC_RESULT */
+typedef struct
+{
+    BT_HDR      hdr;
+    tBTA_DM_SEARCH  result;
+} tBTA_DM_DISC_RESULT;
+
+
+/* data type for BTA_DM_INQUIRY_CMPL_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    UINT8       num;
+} tBTA_DM_INQUIRY_CMPL;
+
+/* data type for BTA_DM_SDP_RESULT_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    UINT16 sdp_result;
+} tBTA_DM_SDP_RESULT;
+
+/* data type for BTA_DM_ACL_CHANGE_EVT */
+typedef struct
+{
+    BT_HDR          hdr;
+    tBTM_BL_EVENT   event;
+    UINT8           busy_level;
+    UINT8           busy_level_flags;
+    BOOLEAN         is_new;
+    UINT8           new_role;
+    BD_ADDR         bd_addr;
+    UINT8           hci_status;
+#if BLE_INCLUDED == TRUE
+    UINT16          handle;
+    tBT_TRANSPORT   transport;
+#endif
+} tBTA_DM_ACL_CHANGE;
+
+/* data type for BTA_DM_PM_BTM_STATUS_EVT */
+typedef struct
+{
+
+    BT_HDR          hdr;
+    BD_ADDR         bd_addr;
+    tBTM_PM_STATUS  status;
+    UINT16          value;
+    UINT8           hci_status;
+
+} tBTA_DM_PM_BTM_STATUS;
+
+/* data type for BTA_DM_PM_TIMER_EVT */
+typedef struct
+{
+    BT_HDR          hdr;
+    BD_ADDR         bd_addr;
+    tBTA_DM_PM_ACTION  pm_request;
+} tBTA_DM_PM_TIMER;
+
+
+/* data type for BTA_DM_API_ADD_DEVICE_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    BD_ADDR             bd_addr;
+    DEV_CLASS           dc;
+    LINK_KEY            link_key;
+    tBTA_SERVICE_MASK   tm;
+    BOOLEAN             is_trusted;
+    UINT8               key_type;
+    tBTA_IO_CAP         io_cap;
+    BOOLEAN             link_key_known;
+    BOOLEAN             dc_known;
+    BD_NAME             bd_name;
+    UINT8               features[BTA_FEATURE_BYTES_PER_PAGE * (BTA_EXT_FEATURES_PAGE_MAX + 1)];
+    UINT8               pin_length;
+} tBTA_DM_API_ADD_DEVICE;
+
+/* data type for BTA_DM_API_REMOVE_ACL_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    BD_ADDR             bd_addr;
+} tBTA_DM_API_REMOVE_DEVICE;
+
+/* data type for BTA_DM_API_EXECUTE_CBACK_EVT */
+typedef struct
+{
+    BT_HDR               hdr;
+    void *               p_param;
+    tBTA_DM_EXEC_CBACK  *p_exec_cback;
+} tBTA_DM_API_EXECUTE_CBACK;
+
+/* data type for tBTA_DM_API_SET_ENCRYPTION */
+typedef struct
+{
+    BT_HDR                    hdr;
+    tBTA_TRANSPORT            transport;
+    tBTA_DM_ENCRYPT_CBACK     *p_callback;
+    tBTA_DM_BLE_SEC_ACT       sec_act;
+    BD_ADDR                   bd_addr;
+} tBTA_DM_API_SET_ENCRYPTION;
+
+#if BLE_INCLUDED == TRUE
+typedef struct
+{
+    BT_HDR                  hdr;
+    BD_ADDR                 bd_addr;
+    tBTA_LE_KEY_VALUE       blekey;
+    tBTA_LE_KEY_TYPE        key_type;
+
+}tBTA_DM_API_ADD_BLEKEY;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    BD_ADDR                 bd_addr;
+    tBT_DEVICE_TYPE         dev_type ;
+    tBLE_ADDR_TYPE          addr_type;
+
+}tBTA_DM_API_ADD_BLE_DEVICE;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    BD_ADDR                 bd_addr;
+    BOOLEAN                 accept;
+    UINT32                  passkey;
+}tBTA_DM_API_PASSKEY_REPLY;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    BD_ADDR                 bd_addr;
+    tBTA_DM_BLE_SEC_GRANT   res;
+}tBTA_DM_API_BLE_SEC_GRANT;
+
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_DM_BLE_CONN_TYPE   bg_conn_type;
+    tBTA_DM_BLE_SEL_CBACK   *p_select_cback;
+}tBTA_DM_API_BLE_SET_BG_CONN_TYPE;
+
+/* set prefered BLE connection parameters for a device */
+typedef struct
+{
+    BT_HDR                  hdr;
+    BD_ADDR                 peer_bda;
+    UINT16                  conn_int_min;
+    UINT16                  conn_int_max;
+    UINT16                  supervision_tout;
+    UINT16                  slave_latency;
+
+}tBTA_DM_API_BLE_CONN_PARAMS;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    BD_ADDR                 peer_bda;
+    BOOLEAN                 privacy_enable;
+
+}tBTA_DM_API_ENABLE_PRIVACY;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    BOOLEAN                 privacy_enable;
+}tBTA_DM_API_LOCAL_PRIVACY;
+
+/* set scan parameter for BLE connections */
+typedef struct
+{
+    BT_HDR hdr;
+    tBTA_GATTC_IF client_if;
+    UINT32 scan_int;
+    UINT32 scan_window;
+    tBLE_SCAN_MODE scan_mode;
+    tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback;
+}tBTA_DM_API_BLE_SCAN_PARAMS;
+
+/* set scan parameter for BLE connections */
+typedef struct
+{
+    BT_HDR                  hdr;
+    UINT16                  scan_int;
+    UINT16                  scan_window;
+} tBTA_DM_API_BLE_CONN_SCAN_PARAMS;
+
+/* Data type for start/stop observe */
+typedef struct
+{
+    BT_HDR                  hdr;
+    BOOLEAN                 start;
+    UINT16                  duration;
+    tBTA_DM_SEARCH_CBACK * p_cback;
+}tBTA_DM_API_BLE_OBSERVE;
+
+typedef struct
+{
+    BT_HDR      hdr;
+    BD_ADDR     remote_bda;
+    UINT16      tx_data_length;
+}tBTA_DM_API_BLE_SET_DATA_LENGTH;
+
+/* set the address for BLE device
+   this type added by Yulong at 2016/9/9*/
+typedef struct
+{
+	BT_HDR      hdr;
+	tBLE_ADDR_TYPE addr_type;
+	BD_ADDR address;
+}tBTA_DM_APT_SET_DEV_ADDR;
+
+/* set adv parameter for BLE advertising */
+typedef struct
+{
+    BT_HDR                  hdr;
+    UINT16                  adv_int_min;
+    UINT16                  adv_int_max;
+    tBLE_BD_ADDR            *p_dir_bda;
+}tBTA_DM_API_BLE_ADV_PARAMS;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    BOOLEAN                 enable;
+
+}tBTA_DM_API_BLE_FEATURE;
+
+/* multi adv data structure */
+typedef struct
+{
+    BT_HDR                      hdr;
+    tBTA_BLE_MULTI_ADV_CBACK    *p_cback;
+    void                        *p_ref;
+    tBTA_BLE_ADV_PARAMS         *p_params;
+}tBTA_DM_API_BLE_MULTI_ADV_ENB;
+
+typedef struct
+{
+    BT_HDR                      hdr;
+    UINT8                        inst_id;
+    tBTA_BLE_ADV_PARAMS         *p_params;
+}tBTA_DM_API_BLE_MULTI_ADV_PARAM;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    UINT8                   inst_id;
+    BOOLEAN                 is_scan_rsp;
+    tBTA_BLE_AD_MASK        data_mask;
+    tBTA_BLE_ADV_DATA      *p_data;
+}tBTA_DM_API_BLE_MULTI_ADV_DATA;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    UINT8                   inst_id;
+}tBTA_DM_API_BLE_MULTI_ADV_DISABLE;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    UINT32                  data_mask;
+    tBTA_BLE_ADV_DATA       *p_adv_cfg;
+    tBTA_SET_ADV_DATA_CMPL_CBACK    *p_adv_data_cback;
+}tBTA_DM_API_SET_ADV_CONFIG;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    UINT8                   batch_scan_full_max;
+    UINT8                   batch_scan_trunc_max;
+    UINT8                   batch_scan_notify_threshold;
+    tBTA_BLE_SCAN_SETUP_CBACK *p_setup_cback;
+    tBTA_BLE_SCAN_THRESHOLD_CBACK *p_thres_cback;
+    tBTA_BLE_SCAN_REP_CBACK *p_read_rep_cback;
+    tBTA_DM_BLE_REF_VALUE    ref_value;
+} tBTA_DM_API_SET_STORAGE_CONFIG;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_BLE_BATCH_SCAN_MODE  scan_mode;
+    UINT32                  scan_int;
+    UINT32                  scan_window;
+    tBTA_BLE_DISCARD_RULE   discard_rule;
+    tBLE_ADDR_TYPE          addr_type;
+    tBTA_DM_BLE_REF_VALUE   ref_value;
+} tBTA_DM_API_ENABLE_SCAN;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_DM_BLE_REF_VALUE    ref_value;
+} tBTA_DM_API_DISABLE_SCAN;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_BLE_BATCH_SCAN_MODE scan_type;
+    tBTA_DM_BLE_REF_VALUE    ref_value;
+} tBTA_DM_API_READ_SCAN_REPORTS;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_DM_BLE_REF_VALUE ref_value;
+    tBTA_BLE_TRACK_ADV_CBACK *p_track_adv_cback;
+} tBTA_DM_API_TRACK_ADVERTISER;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_BLE_ENERGY_INFO_CBACK *p_energy_info_cback;
+} tBTA_DM_API_ENERGY_INFO;
+
+#endif /* BLE_INCLUDED */
+
+/* data type for BTA_DM_API_REMOVE_ACL_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    BD_ADDR     bd_addr;
+    BOOLEAN     remove_dev;
+    tBTA_TRANSPORT transport;
+
+}tBTA_DM_API_REMOVE_ACL;
+
+/* data type for BTA_DM_API_REMOVE_ALL_ACL_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    tBTA_DM_LINK_TYPE link_type;
+
+} tBTA_DM_API_REMOVE_ALL_ACL;
+typedef struct
+{
+    BT_HDR      hdr;
+    BD_ADDR     bd_addr;
+    UINT16      min_int;
+    UINT16      max_int;
+    UINT16      latency;
+    UINT16      timeout;
+}tBTA_DM_API_UPDATE_CONN_PARAM;
+
+#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
+typedef struct
+{
+    BT_HDR                          hdr;
+    tBTA_DM_BLE_SCAN_COND_OP        action;
+    tBTA_DM_BLE_PF_COND_TYPE        cond_type;
+    tBTA_DM_BLE_PF_FILT_INDEX       filt_index;
+    tBTA_DM_BLE_PF_COND_PARAM       *p_cond_param;
+    tBTA_DM_BLE_PF_CFG_CBACK      *p_filt_cfg_cback;
+    tBTA_DM_BLE_REF_VALUE            ref_value;
+}tBTA_DM_API_CFG_FILTER_COND;
+
+typedef struct
+{
+    BT_HDR                          hdr;
+    UINT8                           action;
+    tBTA_DM_BLE_PF_STATUS_CBACK    *p_filt_status_cback;
+    tBTA_DM_BLE_REF_VALUE            ref_value;
+}tBTA_DM_API_ENABLE_SCAN_FILTER;
+
+typedef struct
+{
+    BT_HDR                          hdr;
+    UINT8                           action;
+    tBTA_DM_BLE_PF_FILT_INDEX       filt_index;
+    tBTA_DM_BLE_PF_FILT_PARAMS      filt_params;
+    tBLE_BD_ADDR                    *p_target;
+    tBTA_DM_BLE_PF_PARAM_CBACK      *p_filt_param_cback;
+    tBTA_DM_BLE_REF_VALUE            ref_value;
+}tBTA_DM_API_SCAN_FILTER_PARAM_SETUP;
+#endif
+
+/* union of all data types */
+typedef union
+{
+    /* GKI event buffer header */
+    BT_HDR              hdr;
+    tBTA_DM_API_ENABLE  enable;
+
+    tBTA_DM_API_SET_NAME set_name;
+
+    tBTA_DM_API_SET_VISIBILITY set_visibility;
+
+    tBTA_DM_API_ADD_DEVICE  add_dev;
+
+    tBTA_DM_API_REMOVE_DEVICE remove_dev;
+
+    tBTA_DM_API_SEARCH search;
+
+    tBTA_DM_API_DISCOVER discover;
+
+    tBTA_DM_API_BOND bond;
+
+    tBTA_DM_API_BOND_CANCEL bond_cancel;
+
+    tBTA_DM_API_PIN_REPLY pin_reply;
+
+    tBTA_DM_API_LOC_OOB     loc_oob;
+    tBTA_DM_API_CONFIRM     confirm;
+    tBTA_DM_CI_IO_REQ       ci_io_req;
+    tBTA_DM_CI_RMT_OOB      ci_rmt_oob;
+
+    tBTA_DM_REM_NAME rem_name;
+
+    tBTA_DM_DISC_RESULT disc_result;
+
+    tBTA_DM_INQUIRY_CMPL inq_cmpl;
+
+    tBTA_DM_SDP_RESULT sdp_event;
+
+    tBTA_DM_ACL_CHANGE  acl_change;
+
+    tBTA_DM_PM_BTM_STATUS pm_status;
+
+    tBTA_DM_PM_TIMER pm_timer;
+
+    tBTA_DM_API_DI_DISC     di_disc;
+
+    tBTA_DM_API_EXECUTE_CBACK exec_cback;
+
+    tBTA_DM_API_SET_ENCRYPTION     set_encryption;
+
+#if BLE_INCLUDED == TRUE
+    tBTA_DM_API_ADD_BLEKEY              add_ble_key;
+    tBTA_DM_API_ADD_BLE_DEVICE          add_ble_device;
+    tBTA_DM_API_PASSKEY_REPLY           ble_passkey_reply;
+    tBTA_DM_API_BLE_SEC_GRANT           ble_sec_grant;
+    tBTA_DM_API_BLE_SET_BG_CONN_TYPE    ble_set_bd_conn_type;
+    tBTA_DM_API_BLE_CONN_PARAMS         ble_set_conn_params;
+    tBTA_DM_API_BLE_CONN_SCAN_PARAMS    ble_set_conn_scan_params;
+    tBTA_DM_API_BLE_SCAN_PARAMS         ble_set_scan_params;
+    tBTA_DM_API_BLE_OBSERVE             ble_observe;
+    tBTA_DM_API_ENABLE_PRIVACY          ble_remote_privacy;
+    tBTA_DM_API_LOCAL_PRIVACY           ble_local_privacy;
+    tBTA_DM_API_BLE_ADV_PARAMS          ble_set_adv_params;
+    tBTA_DM_API_SET_ADV_CONFIG          ble_set_adv_data;
+#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
+    tBTA_DM_API_SCAN_FILTER_PARAM_SETUP ble_scan_filt_param_setup;
+    tBTA_DM_API_CFG_FILTER_COND         ble_cfg_filter_cond;
+    tBTA_DM_API_ENABLE_SCAN_FILTER      ble_enable_scan_filt;
+#endif
+    tBTA_DM_API_UPDATE_CONN_PARAM       ble_update_conn_params;
+    tBTA_DM_API_BLE_SET_DATA_LENGTH     ble_set_data_length;
+	tBTA_DM_APT_SET_DEV_ADDR 			set_addr;
+    tBTA_DM_API_BLE_MULTI_ADV_ENB       ble_multi_adv_enb;
+    tBTA_DM_API_BLE_MULTI_ADV_PARAM     ble_multi_adv_param;
+    tBTA_DM_API_BLE_MULTI_ADV_DATA      ble_multi_adv_data;
+    tBTA_DM_API_BLE_MULTI_ADV_DISABLE   ble_multi_adv_disable;
+
+    tBTA_DM_API_SET_STORAGE_CONFIG      ble_set_storage;
+    tBTA_DM_API_ENABLE_SCAN             ble_enable_scan;
+    tBTA_DM_API_READ_SCAN_REPORTS       ble_read_reports;
+    tBTA_DM_API_DISABLE_SCAN            ble_disable_scan;
+    tBTA_DM_API_TRACK_ADVERTISER        ble_track_advert;
+    tBTA_DM_API_ENERGY_INFO             ble_energy_info;
+#endif
+
+    tBTA_DM_API_REMOVE_ACL              remove_acl;
+    tBTA_DM_API_REMOVE_ALL_ACL          remove_all_acl;
+
+} tBTA_DM_MSG;
+
+
+#define BTA_DM_NUM_PEER_DEVICE 7
+
+#define BTA_DM_NOT_CONNECTED  0
+#define BTA_DM_CONNECTED      1
+#define BTA_DM_UNPAIRING      2
+typedef UINT8 tBTA_DM_CONN_STATE;
+
+
+#define BTA_DM_DI_NONE          0x00       /* nothing special */
+#define BTA_DM_DI_USE_SSR       0x10       /* set this bit if ssr is supported for this link */
+#define BTA_DM_DI_AV_ACTIVE     0x20       /* set this bit if AV is active for this link */
+#define BTA_DM_DI_SET_SNIFF     0x01       /* set this bit if call BTM_SetPowerMode(sniff) */
+#define BTA_DM_DI_INT_SNIFF     0x02       /* set this bit if call BTM_SetPowerMode(sniff) & enter sniff mode */
+#define BTA_DM_DI_ACP_SNIFF     0x04       /* set this bit if peer init sniff */
+typedef UINT8 tBTA_DM_DEV_INFO;
+
+/* set power mode request type */
+#define BTA_DM_PM_RESTART       1
+#define BTA_DM_PM_NEW_REQ       2
+#define BTA_DM_PM_EXECUTE       3
+typedef UINT8   tBTA_DM_PM_REQ;
+
+typedef struct
+{
+    BD_ADDR                     peer_bdaddr;
+    UINT16                      link_policy;
+    tBTA_DM_CONN_STATE          conn_state;
+    tBTA_PREF_ROLES             pref_role;
+    BOOLEAN                     in_use;
+    tBTA_DM_DEV_INFO            info;
+    tBTA_DM_ENCRYPT_CBACK      *p_encrypt_cback;
+#if (BTM_SSR_INCLUDED == TRUE)
+    tBTM_PM_STATUS              prev_low;   /* previous low power mode used */
+#endif
+    tBTA_DM_PM_ACTION           pm_mode_attempted;
+    tBTA_DM_PM_ACTION           pm_mode_failed;
+    BOOLEAN                     remove_dev_pending;
+#if BLE_INCLUDED == TRUE
+    UINT16                      conn_handle;
+    tBT_TRANSPORT               transport;
+#endif
+} tBTA_DM_PEER_DEVICE;
+
+
+
+/* structure to store list of
+  active connections */
+typedef struct
+{
+    tBTA_DM_PEER_DEVICE    peer_device[BTA_DM_NUM_PEER_DEVICE];
+    UINT8                  count;
+#if BLE_INCLUDED == TRUE
+    UINT8                  le_count;
+#endif
+} tBTA_DM_ACTIVE_LINK;
+
+
+typedef struct
+{
+    BD_ADDR                 peer_bdaddr;
+    tBTA_SYS_ID             id;
+    UINT8                   app_id;
+    tBTA_SYS_CONN_STATUS    state;
+    BOOLEAN                 new_request;
+
+} tBTA_DM_SRVCS;
+
+#ifndef BTA_DM_NUM_CONN_SRVS
+#define BTA_DM_NUM_CONN_SRVS   10
+#endif
+
+typedef struct
+{
+
+    UINT8 count;
+    tBTA_DM_SRVCS  conn_srvc[BTA_DM_NUM_CONN_SRVS];
+
+}  tBTA_DM_CONNECTED_SRVCS;
+
+typedef struct
+{
+#define BTA_DM_PM_SNIFF_TIMER_IDX   0
+#define BTA_DM_PM_PARK_TIMER_IDX    1
+#define BTA_DM_PM_SUSPEND_TIMER_IDX 2
+#define BTA_DM_PM_MODE_TIMER_MAX    3
+    /*
+     * Keep three different timers for PARK, SNIFF and SUSPEND if TBFC is
+     * supported.
+     */
+    TIMER_LIST_ENT          timer[BTA_DM_PM_MODE_TIMER_MAX];
+
+    UINT8                   srvc_id[BTA_DM_PM_MODE_TIMER_MAX];
+    UINT8                   pm_action[BTA_DM_PM_MODE_TIMER_MAX];
+    UINT8                   active;     /* number of active timer */
+
+    BD_ADDR                 peer_bdaddr;
+    BOOLEAN                 in_use;
+} tBTA_PM_TIMER;
+
+extern tBTA_DM_CONNECTED_SRVCS bta_dm_conn_srvcs;
+
+#define BTA_DM_NUM_PM_TIMER 7
+
+/* DM control block */
+typedef struct
+{
+    BOOLEAN                     is_bta_dm_active;
+    tBTA_DM_ACTIVE_LINK         device_list;
+    tBTA_DM_SEC_CBACK           *p_sec_cback;
+#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+    tBTA_BLE_SCAN_SETUP_CBACK   *p_setup_cback;
+    tBTA_DM_BLE_PF_CFG_CBACK     *p_scan_filt_cfg_cback;
+    tBTA_DM_BLE_PF_STATUS_CBACK  *p_scan_filt_status_cback;
+    tBTA_DM_BLE_PF_PARAM_CBACK   *p_scan_filt_param_cback;
+    tBTA_BLE_MULTI_ADV_CBACK     *p_multi_adv_cback;
+    tBTA_BLE_ENERGY_INFO_CBACK   *p_energy_info_cback;
+#endif
+    UINT16                      state;
+    BOOLEAN                     disabling;
+    TIMER_LIST_ENT              disable_timer;
+    UINT32                      wbt_sdp_handle;          /* WIDCOMM Extensions SDP record handle */
+    UINT8                       wbt_scn;                 /* WIDCOMM Extensions SCN */
+    UINT8                       num_master_only;
+    UINT8                       pm_id;
+    tBTA_PM_TIMER               pm_timer[BTA_DM_NUM_PM_TIMER];
+    UINT32                      role_policy_mask;   /* the bits set indicates the modules that wants to remove role switch from the default link policy */
+    UINT16                      cur_policy;         /* current default link policy */
+    UINT16                      rs_event;           /* the event waiting for role switch */
+    UINT8                       cur_av_count;       /* current AV connecions */
+    BOOLEAN                     disable_pair_mode;          /* disable pair mode or not */
+    BOOLEAN                     conn_paired_only;   /* allow connectable to paired device only or not */
+    tBTA_DM_API_SEARCH          search_msg;
+    UINT16                      page_scan_interval;
+    UINT16                      page_scan_window;
+    UINT16                      inquiry_scan_interval;
+    UINT16                      inquiry_scan_window;
+
+    /* Storage for pin code request parameters */
+    BD_ADDR                     pin_bd_addr;
+    DEV_CLASS                   pin_dev_class;
+    tBTA_DM_SEC_EVT             pin_evt;
+    UINT32          num_val;        /* the numeric value for comparison. If just_works, do not show this number to UI */
+    BOOLEAN         just_works;     /* TRUE, if "Just Works" association model */
+#if ( BTA_EIR_CANNED_UUID_LIST != TRUE )
+    /* store UUID list for EIR */
+    TIMER_LIST_ENT              app_ready_timer;
+    UINT32                      eir_uuid[BTM_EIR_SERVICE_ARRAY_SIZE];
+#if (BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+    tBT_UUID                    custom_uuid[BTA_EIR_SERVER_NUM_CUSTOM_UUID];
+#endif
+
+#endif
+
+
+    tBTA_DM_ENCRYPT_CBACK      *p_encrypt_cback;
+    TIMER_LIST_ENT              switch_delay_timer;
+
+} tBTA_DM_CB;
+
+#ifndef BTA_DM_SDP_DB_SIZE
+#define BTA_DM_SDP_DB_SIZE 250
+#endif
+
+/* DM search control block */
+typedef struct
+{
+
+    tBTA_DM_SEARCH_CBACK * p_search_cback;
+    tBTM_INQ_INFO        * p_btm_inq_info;
+    tBTA_SERVICE_MASK      services;
+    tBTA_SERVICE_MASK      services_to_search;
+    tBTA_SERVICE_MASK      services_found;
+    tSDP_DISCOVERY_DB    * p_sdp_db;
+    UINT16                 state;
+    BD_ADDR                peer_bdaddr;
+    BOOLEAN                name_discover_done;
+    BD_NAME                peer_name;
+    TIMER_LIST_ENT         search_timer;
+    UINT8                  service_index;
+    tBTA_DM_MSG          * p_search_queue;   /* search or discover commands during search cancel stored here */
+    BOOLEAN                wait_disc;
+    BOOLEAN                sdp_results;
+    tSDP_UUID              uuid;
+    UINT8                  peer_scn;
+    BOOLEAN                sdp_search;
+    BOOLEAN                cancel_pending; /* inquiry cancel is pending */
+    tBTA_TRANSPORT         transport;
+#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+    tBTA_DM_SEARCH_CBACK * p_scan_cback;
+#if ((defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+    tBTA_GATTC_IF          client_if;
+    UINT8                  num_uuid;
+    tBT_UUID               *p_srvc_uuid;
+    UINT8                  uuid_to_search;
+    BOOLEAN                gatt_disc_active;
+    UINT16                 conn_id;
+    UINT8 *                 p_ble_rawdata;
+    UINT32                 ble_raw_size;
+    UINT32                 ble_raw_used;
+    TIMER_LIST_ENT         gatt_close_timer; /* GATT channel close delay timer */
+    BD_ADDR                pending_close_bda; /* pending GATT channel remote device address */
+#endif
+#endif
+
+
+} tBTA_DM_SEARCH_CB;
+
+/* DI control block */
+typedef struct
+{
+    tSDP_DISCOVERY_DB    * p_di_db;     /* pointer to the DI discovery database */
+    UINT8               di_num;         /* total local DI record number */
+    UINT32              di_handle[BTA_DI_NUM_MAX];  /* local DI record handle, the first one is primary record */
+}tBTA_DM_DI_CB;
+
+/* DM search state */
+enum
+{
+
+    BTA_DM_SEARCH_IDLE,
+    BTA_DM_SEARCH_ACTIVE,
+    BTA_DM_SEARCH_CANCELLING,
+    BTA_DM_DISCOVER_ACTIVE
+
+};
+
+
+
+typedef struct
+{
+    DEV_CLASS      dev_class;          /* local device class */
+    UINT16         policy_settings;    /* link policy setting hold, sniff, park, MS switch */
+    UINT16         page_timeout;       /* timeout for page in slots */
+    UINT16         link_timeout;       /* link supervision timeout in slots */
+    BOOLEAN        avoid_scatter;      /* TRUE to avoid scatternet when av is streaming (be the master) */
+
+} tBTA_DM_CFG;
+
+extern const UINT32 bta_service_id_to_btm_srv_id_lkup_tbl[];
+
+
+typedef struct
+{
+    UINT8   id;
+    UINT8   app_id;
+    UINT8   cfg;
+
+} tBTA_DM_RM ;
+
+extern tBTA_DM_CFG *p_bta_dm_cfg;
+extern tBTA_DM_RM *p_bta_dm_rm_cfg;
+
+typedef struct
+{
+
+  UINT8  id;
+  UINT8  app_id;
+  UINT8  spec_idx;  /* index of spec table to use */
+
+} tBTA_DM_PM_CFG;
+
+
+typedef struct
+{
+
+  tBTA_DM_PM_ACTION   power_mode;
+  UINT16              timeout;
+
+} tBTA_DM_PM_ACTN;
+
+typedef struct
+{
+
+  UINT8  allow_mask;         /* mask of sniff/hold/park modes to allow */
+#if (BTM_SSR_INCLUDED == TRUE)
+  UINT8  ssr;                /* set SSR on conn open/unpark */
+#endif
+  tBTA_DM_PM_ACTN actn_tbl [BTA_DM_PM_NUM_EVTS][2];
+
+} tBTA_DM_PM_SPEC;
+
+typedef struct
+{
+    UINT16      max_lat;
+    UINT16      min_rmt_to;
+    UINT16      min_loc_to;
+} tBTA_DM_SSR_SPEC;
+
+typedef struct
+{
+   UINT16 manufacturer;
+   UINT16 lmp_sub_version;
+   UINT8 lmp_version;
+}tBTA_DM_LMP_VER_INFO;
+
+extern tBTA_DM_PM_CFG *p_bta_dm_pm_cfg;
+extern tBTA_DM_PM_SPEC *p_bta_dm_pm_spec;
+extern tBTM_PM_PWR_MD *p_bta_dm_pm_md;
+#if (BTM_SSR_INCLUDED == TRUE)
+extern tBTA_DM_SSR_SPEC *p_bta_dm_ssr_spec;
+#endif
+
+/* update dynamic BRCM Aware EIR data */
+extern const tBTA_DM_EIR_CONF bta_dm_eir_cfg;
+extern tBTA_DM_EIR_CONF *p_bta_dm_eir_cfg;
+
+/* DM control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_DM_CB  bta_dm_cb;
+#else
+extern tBTA_DM_CB *bta_dm_cb_ptr;
+#define bta_dm_cb (*bta_dm_cb_ptr)
+#endif
+
+/* DM search control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_DM_SEARCH_CB  bta_dm_search_cb;
+#else
+extern tBTA_DM_SEARCH_CB *bta_dm_search_cb_ptr;
+#define bta_dm_search_cb (*bta_dm_search_cb_ptr)
+#endif
+
+/* DI control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_DM_DI_CB  bta_dm_di_cb;
+#else
+extern tBTA_DM_DI_CB *bta_dm_di_cb_ptr;
+#define bta_dm_di_cb (*bta_dm_di_cb_ptr)
+#endif
+
+extern BOOLEAN bta_dm_sm_execute(BT_HDR *p_msg);
+extern void bta_dm_sm_disable( void );
+extern BOOLEAN bta_dm_search_sm_execute(BT_HDR *p_msg);
+extern void bta_dm_search_sm_disable( void );
+
+
+extern void bta_dm_enable (tBTA_DM_MSG *p_data);
+extern void bta_dm_disable (tBTA_DM_MSG *p_data);
+extern void bta_dm_set_dev_name (tBTA_DM_MSG *p_data);
+extern void bta_dm_set_visibility (tBTA_DM_MSG *p_data);
+
+extern void bta_dm_set_scan_config(tBTA_DM_MSG *p_data);
+extern void bta_dm_vendor_spec_command(tBTA_DM_MSG *p_data);
+extern void bta_dm_bond (tBTA_DM_MSG *p_data);
+extern void bta_dm_bond_cancel (tBTA_DM_MSG *p_data);
+extern void bta_dm_pin_reply (tBTA_DM_MSG *p_data);
+extern void bta_dm_acl_change(tBTA_DM_MSG *p_data);
+extern void bta_dm_add_device (tBTA_DM_MSG *p_data);
+extern void bta_dm_remove_device (tBTA_DM_MSG *p_data);
+extern void bta_dm_close_acl(tBTA_DM_MSG *p_data);
+
+
+extern void bta_dm_pm_btm_status(tBTA_DM_MSG *p_data);
+extern void bta_dm_pm_timer(tBTA_DM_MSG *p_data);
+extern void bta_dm_add_ampkey (tBTA_DM_MSG *p_data);
+
+#if BLE_INCLUDED == TRUE
+extern void bta_dm_add_blekey (tBTA_DM_MSG *p_data);
+extern void bta_dm_add_ble_device (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_passkey_reply (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_confirm_reply (tBTA_DM_MSG *p_data);
+extern void bta_dm_security_grant (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_set_bg_conn_type (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_set_conn_params (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_set_scan_params(tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_set_conn_scan_params (tBTA_DM_MSG *p_data);
+extern void bta_dm_close_gatt_conn(tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_observe (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_update_conn_params (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_set_rand_address(tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_config_local_privacy (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_set_adv_params (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_set_adv_config (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_set_scan_rsp (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_broadcast (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_set_data_length(tBTA_DM_MSG *p_data);
+
+#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
+extern void bta_dm_cfg_filter_cond (tBTA_DM_MSG *p_data);
+extern void bta_dm_scan_filter_param_setup (tBTA_DM_MSG *p_data);
+extern void bta_dm_enable_scan_filter(tBTA_DM_MSG *p_data);
+#endif
+extern void btm_dm_ble_multi_adv_disable(tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_multi_adv_data(tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_multi_adv_upd_param(tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_multi_adv_enb(tBTA_DM_MSG *p_data);
+
+extern void bta_dm_ble_setup_storage(tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_enable_batch_scan(tBTA_DM_MSG * p_data);
+extern void bta_dm_ble_disable_batch_scan(tBTA_DM_MSG * p_data);
+extern void bta_dm_ble_read_scan_reports(tBTA_DM_MSG * p_data);
+extern void bta_dm_ble_track_advertiser(tBTA_DM_MSG * p_data);
+extern void bta_dm_ble_get_energy_info(tBTA_DM_MSG *p_data);
+
+#endif
+extern void bta_dm_set_encryption(tBTA_DM_MSG *p_data);
+extern void bta_dm_confirm(tBTA_DM_MSG *p_data);
+#if (BTM_OOB_INCLUDED == TRUE)
+extern void bta_dm_loc_oob(tBTA_DM_MSG *p_data);
+extern void bta_dm_ci_io_req_act(tBTA_DM_MSG *p_data);
+extern void bta_dm_ci_rmt_oob_act(tBTA_DM_MSG *p_data);
+#endif /* BTM_OOB_INCLUDED */
+
+extern void bta_dm_init_pm(void);
+extern void bta_dm_disable_pm(void);
+
+extern UINT8 bta_dm_get_av_count(void);
+extern void bta_dm_search_start (tBTA_DM_MSG *p_data);
+extern void bta_dm_search_cancel (tBTA_DM_MSG *p_data);
+extern void bta_dm_discover (tBTA_DM_MSG *p_data);
+extern void bta_dm_di_disc (tBTA_DM_MSG *p_data);
+extern void bta_dm_inq_cmpl (tBTA_DM_MSG *p_data);
+extern void bta_dm_rmt_name (tBTA_DM_MSG *p_data);
+extern void bta_dm_sdp_result (tBTA_DM_MSG *p_data);
+extern void bta_dm_search_cmpl (tBTA_DM_MSG *p_data);
+extern void bta_dm_free_sdp_db (tBTA_DM_MSG *p_data);
+extern void bta_dm_disc_result (tBTA_DM_MSG *p_data);
+extern void bta_dm_search_result (tBTA_DM_MSG *p_data);
+extern void bta_dm_discovery_cmpl (tBTA_DM_MSG *p_data);
+extern void bta_dm_queue_search (tBTA_DM_MSG *p_data);
+extern void bta_dm_queue_disc (tBTA_DM_MSG *p_data);
+extern void bta_dm_search_clear_queue (tBTA_DM_MSG *p_data);
+extern void bta_dm_search_cancel_cmpl (tBTA_DM_MSG *p_data);
+extern void bta_dm_search_cancel_notify (tBTA_DM_MSG *p_data);
+extern void bta_dm_search_cancel_transac_cmpl(tBTA_DM_MSG *p_data);
+extern void bta_dm_disc_rmt_name (tBTA_DM_MSG *p_data);
+extern tBTA_DM_PEER_DEVICE * bta_dm_find_peer_device(BD_ADDR peer_addr);
+
+extern void bta_dm_pm_active(BD_ADDR peer_addr);
+
+void bta_dm_eir_update_uuid(UINT16 uuid16, BOOLEAN adding);
+
+extern void bta_dm_enable_test_mode(tBTA_DM_MSG *p_data);
+extern void bta_dm_disable_test_mode(tBTA_DM_MSG *p_data);
+extern void bta_dm_execute_callback(tBTA_DM_MSG *p_data);
+
+
+extern void bta_dm_remove_all_acl(tBTA_DM_MSG *p_data);
+#endif /* BTA_DM_INT_H */

+ 376 - 0
components/bt/bluedroid/bta/dm/bta_dm_main.c

@@ -0,0 +1,376 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the main implementation file for the BTA device manager.
+ *
+ ******************************************************************************/
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_dm_int.h"
+
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_DM_CB  bta_dm_cb;
+tBTA_DM_SEARCH_CB bta_dm_search_cb;
+tBTA_DM_DI_CB       bta_dm_di_cb;
+#endif
+
+
+#define BTA_DM_NUM_ACTIONS  (BTA_DM_MAX_EVT & 0x00ff)
+
+/* type for action functions */
+typedef void (*tBTA_DM_ACTION)(tBTA_DM_MSG *p_data);
+
+/* action function list */
+const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] =
+{
+
+    /* device manager local device API events */
+    bta_dm_enable,            /* 0  BTA_DM_API_ENABLE_EVT */
+    bta_dm_disable,           /* 1  BTA_DM_API_DISABLE_EVT */
+    bta_dm_set_dev_name,      /* 2  BTA_DM_API_SET_NAME_EVT */
+    bta_dm_set_visibility,    /* 3  BTA_DM_API_SET_VISIBILITY_EVT */
+    bta_dm_acl_change,        /* 8  BTA_DM_ACL_CHANGE_EVT */
+    bta_dm_add_device,        /* 9  BTA_DM_API_ADD_DEVICE_EVT */
+    bta_dm_close_acl,        /* 10  BTA_DM_API_ADD_DEVICE_EVT */
+
+    /* security API events */
+    bta_dm_bond,              /* 11  BTA_DM_API_BOND_EVT */
+    bta_dm_bond_cancel,       /* 12  BTA_DM_API_BOND_CANCEL_EVT */
+    bta_dm_pin_reply,         /* 13 BTA_DM_API_PIN_REPLY_EVT */
+
+    /* power manger events */
+    bta_dm_pm_btm_status,     /* 16 BTA_DM_PM_BTM_STATUS_EVT */
+    bta_dm_pm_timer,          /* 17 BTA_DM_PM_TIMER_EVT*/
+
+    /* simple pairing events */
+    bta_dm_confirm,           /* 18 BTA_DM_API_CONFIRM_EVT */
+
+    bta_dm_set_encryption,    /* BTA_DM_API_SET_ENCRYPTION_EVT */
+
+#if (BTM_OOB_INCLUDED == TRUE)
+    bta_dm_loc_oob,           /* 20 BTA_DM_API_LOC_OOB_EVT */
+    bta_dm_ci_io_req_act,     /* 21 BTA_DM_CI_IO_REQ_EVT */
+    bta_dm_ci_rmt_oob_act,    /* 22 BTA_DM_CI_RMT_OOB_EVT */
+#endif /* BTM_OOB_INCLUDED */
+
+
+#if BLE_INCLUDED == TRUE
+    bta_dm_add_blekey,          /*  BTA_DM_API_ADD_BLEKEY_EVT           */
+    bta_dm_add_ble_device,      /*  BTA_DM_API_ADD_BLEDEVICE_EVT        */
+    bta_dm_ble_passkey_reply,   /*  BTA_DM_API_BLE_PASSKEY_REPLY_EVT    */
+    bta_dm_ble_confirm_reply,   /*  BTA_DM_API_BLE_CONFIRM_REPLY_EVT    */
+    bta_dm_security_grant,
+    bta_dm_ble_set_bg_conn_type,
+    bta_dm_ble_set_conn_params,  /* BTA_DM_API_BLE_CONN_PARAM_EVT */
+    bta_dm_ble_set_conn_scan_params,  /* BTA_DM_API_BLE_CONN_SCAN_PARAM_EVT */
+    bta_dm_ble_set_scan_params,  /* BTA_DM_API_BLE_SCAN_PARAM_EVT */
+    bta_dm_ble_observe,
+    bta_dm_ble_update_conn_params,   /* BTA_DM_API_UPDATE_CONN_PARAM_EVT */
+    /*******This handler function added by Yulong at 2016/9/9 to 
+    		support the random address setting for the APP******/
+    bta_dm_ble_set_rand_address,	/*BTA_DM_API_SET_RAND_ADDR_EVT*/
+#if BLE_PRIVACY_SPT == TRUE
+    bta_dm_ble_config_local_privacy,   /* BTA_DM_API_LOCAL_PRIVACY_EVT */
+#endif
+    bta_dm_ble_set_adv_params,     /* BTA_DM_API_BLE_ADV_PARAM_EVT */
+    bta_dm_ble_set_adv_config,     /* BTA_DM_API_BLE_SET_ADV_CONFIG_EVT */
+    bta_dm_ble_set_scan_rsp,       /* BTA_DM_API_BLE_SET_SCAN_RSPT */
+    bta_dm_ble_broadcast,          /* BTA_DM_API_BLE_BROADCAST_EVT */
+    bta_dm_ble_set_data_length,    /* BTA_DM_API_SET_DATA_LENGTH_EVT */
+#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
+    bta_dm_cfg_filter_cond,         /* BTA_DM_API_CFG_FILTER_COND_EVT */
+    bta_dm_scan_filter_param_setup, /* BTA_DM_API_SCAN_FILTER_SETUP_EVT */
+    bta_dm_enable_scan_filter,      /* BTA_DM_API_SCAN_FILTER_ENABLE_EVT */
+#endif
+    bta_dm_ble_multi_adv_enb,           /*  BTA_DM_API_BLE_MULTI_ADV_ENB_EVT*/
+    bta_dm_ble_multi_adv_upd_param,     /*  BTA_DM_API_BLE_MULTI_ADV_PARAM_UPD_EVT */
+    bta_dm_ble_multi_adv_data,          /*  BTA_DM_API_BLE_MULTI_ADV_DATA_EVT */
+    btm_dm_ble_multi_adv_disable,       /*  BTA_DM_API_BLE_MULTI_ADV_DISABLE_EVT */
+    bta_dm_ble_setup_storage,      /* BTA_DM_API_BLE_SETUP_STORAGE_EVT */
+    bta_dm_ble_enable_batch_scan,  /* BTA_DM_API_BLE_ENABLE_BATCH_SCAN_EVT */
+    bta_dm_ble_disable_batch_scan, /* BTA_DM_API_BLE_DISABLE_BATCH_SCAN_EVT */
+    bta_dm_ble_read_scan_reports,  /* BTA_DM_API_BLE_READ_SCAN_REPORTS_EVT */
+    bta_dm_ble_track_advertiser,   /* BTA_DM_API_BLE_TRACK_ADVERTISER_EVT */
+    bta_dm_ble_get_energy_info,    /* BTA_DM_API_BLE_ENERGY_INFO_EVT */
+#endif
+
+    bta_dm_enable_test_mode,    /*  BTA_DM_API_ENABLE_TEST_MODE_EVT     */
+    bta_dm_disable_test_mode,   /*  BTA_DM_API_DISABLE_TEST_MODE_EVT    */
+    bta_dm_execute_callback,    /*  BTA_DM_API_EXECUTE_CBACK_EVT        */
+
+    bta_dm_remove_all_acl,      /* BTA_DM_API_REMOVE_ALL_ACL_EVT */
+    bta_dm_remove_device,       /* BTA_DM_API_REMOVE_DEVICE_EVT */
+};
+
+
+
+/* state machine action enumeration list */
+enum
+{
+    BTA_DM_API_SEARCH,                  /* 0 bta_dm_search_start */
+    BTA_DM_API_SEARCH_CANCEL,           /* 1 bta_dm_search_cancel */
+    BTA_DM_API_DISCOVER,                /* 2 bta_dm_discover */
+    BTA_DM_INQUIRY_CMPL,                /* 3 bta_dm_inq_cmpl */
+    BTA_DM_REMT_NAME,                   /* 4 bta_dm_rmt_name */
+    BTA_DM_SDP_RESULT,                  /* 5 bta_dm_sdp_result */
+    BTA_DM_SEARCH_CMPL,                 /* 6 bta_dm_search_cmpl*/
+    BTA_DM_FREE_SDP_DB,                 /* 7 bta_dm_free_sdp_db */
+    BTA_DM_DISC_RESULT,                 /* 8 bta_dm_disc_result */
+    BTA_DM_SEARCH_RESULT,               /* 9 bta_dm_search_result */
+    BTA_DM_QUEUE_SEARCH,                /* 10 bta_dm_queue_search */
+    BTA_DM_QUEUE_DISC,                  /* 11 bta_dm_queue_disc */
+    BTA_DM_SEARCH_CLEAR_QUEUE,          /* 12 bta_dm_search_clear_queue */
+    BTA_DM_SEARCH_CANCEL_CMPL,          /* 13 bta_dm_search_cancel_cmpl */
+    BTA_DM_SEARCH_CANCEL_NOTIFY,        /* 14 bta_dm_search_cancel_notify */
+    BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL,  /* 15 bta_dm_search_cancel_transac_cmpl */
+    BTA_DM_DISC_RMT_NAME,               /* 16 bta_dm_disc_rmt_name */
+    BTA_DM_API_DI_DISCOVER,             /* 17 bta_dm_di_disc */
+#if BLE_INCLUDED == TRUE
+    BTA_DM_CLOSE_GATT_CONN,             /* 18 bta_dm_close_gatt_conn */
+#endif
+    BTA_DM_SEARCH_NUM_ACTIONS           /* 19 */
+};
+
+
+/* action function list */
+const tBTA_DM_ACTION bta_dm_search_action[] =
+{
+
+  bta_dm_search_start,              /* 0 BTA_DM_API_SEARCH */
+  bta_dm_search_cancel,             /* 1 BTA_DM_API_SEARCH_CANCEL */
+  bta_dm_discover,                  /* 2 BTA_DM_API_DISCOVER */
+  bta_dm_inq_cmpl,                  /* 3 BTA_DM_INQUIRY_CMPL */
+  bta_dm_rmt_name,                  /* 4 BTA_DM_REMT_NAME */
+  bta_dm_sdp_result,                /* 5 BTA_DM_SDP_RESULT */
+  bta_dm_search_cmpl,               /* 6 BTA_DM_SEARCH_CMPL */
+  bta_dm_free_sdp_db,               /* 7 BTA_DM_FREE_SDP_DB */
+  bta_dm_disc_result,               /* 8 BTA_DM_DISC_RESULT */
+  bta_dm_search_result,             /* 9 BTA_DM_SEARCH_RESULT */
+  bta_dm_queue_search,              /* 10 BTA_DM_QUEUE_SEARCH */
+  bta_dm_queue_disc,                /* 11 BTA_DM_QUEUE_DISC */
+  bta_dm_search_clear_queue,        /* 12 BTA_DM_SEARCH_CLEAR_QUEUE */
+  bta_dm_search_cancel_cmpl,        /* 13 BTA_DM_SEARCH_CANCEL_CMPL */
+  bta_dm_search_cancel_notify,      /* 14 BTA_DM_SEARCH_CANCEL_NOTIFY */
+  bta_dm_search_cancel_transac_cmpl, /* 15 BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL */
+  bta_dm_disc_rmt_name,             /* 16 BTA_DM_DISC_RMT_NAME */
+  bta_dm_di_disc                    /* 17 BTA_DM_API_DI_DISCOVER */
+#if BLE_INCLUDED == TRUE
+  ,bta_dm_close_gatt_conn
+#endif
+};
+
+#define BTA_DM_SEARCH_IGNORE       BTA_DM_SEARCH_NUM_ACTIONS
+/* state table information */
+#define BTA_DM_SEARCH_ACTIONS              2       /* number of actions */
+#define BTA_DM_SEARCH_NEXT_STATE           2       /* position of next state */
+#define BTA_DM_SEARCH_NUM_COLS             3       /* number of columns in state tables */
+
+
+
+/* state table for listen state */
+const UINT8 bta_dm_search_idle_st_table[][BTA_DM_SEARCH_NUM_COLS] =
+{
+
+/* Event                        Action 1                            Action 2                    Next State */
+/* API_SEARCH */            {BTA_DM_API_SEARCH,                BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE},
+/* API_SEARCH_CANCEL */     {BTA_DM_SEARCH_CANCEL_NOTIFY,      BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE},
+/* API_SEARCH_DISC */       {BTA_DM_API_DISCOVER,              BTA_DM_SEARCH_IGNORE,          BTA_DM_DISCOVER_ACTIVE},
+/* INQUIRY_CMPL */          {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE},
+/* REMT_NAME_EVT */         {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE},
+/* SDP_RESULT_EVT */        {BTA_DM_FREE_SDP_DB,               BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE},
+/* SEARCH_CMPL_EVT */       {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE},
+/* DISCV_RES_EVT */         {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE},
+/* API_DI_DISCOVER_EVT */   {BTA_DM_API_DI_DISCOVER,           BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE}
+#if BLE_INCLUDED == TRUE
+/* DISC_CLOSE_TOUT_EVT */   ,{BTA_DM_CLOSE_GATT_CONN,           BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE}
+#endif
+};
+const UINT8 bta_dm_search_search_active_st_table[][BTA_DM_SEARCH_NUM_COLS] =
+{
+
+/* Event                        Action 1                            Action 2                    Next State */
+/* API_SEARCH */            {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE},
+/* API_SEARCH_CANCEL */     {BTA_DM_API_SEARCH_CANCEL,         BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_CANCELLING},
+/* API_SEARCH_DISC */       {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE},
+/* INQUIRY_CMPL */          {BTA_DM_INQUIRY_CMPL,              BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE},
+/* REMT_NAME_EVT */         {BTA_DM_REMT_NAME,                 BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE},
+/* SDP_RESULT_EVT */        {BTA_DM_SDP_RESULT,                BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE},
+/* SEARCH_CMPL_EVT */       {BTA_DM_SEARCH_CMPL,               BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE},
+/* DISCV_RES_EVT */         {BTA_DM_SEARCH_RESULT,             BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE},
+/* API_DI_DISCOVER_EVT */   {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE}
+#if BLE_INCLUDED == TRUE
+/* DISC_CLOSE_TOUT_EVT */   ,{BTA_DM_CLOSE_GATT_CONN,          BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE}
+#endif
+
+};
+
+const UINT8 bta_dm_search_search_cancelling_st_table[][BTA_DM_SEARCH_NUM_COLS] =
+{
+
+/* Event                        Action 1                            Action 2                    Next State */
+/* API_SEARCH */            {BTA_DM_QUEUE_SEARCH,               BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_CANCELLING},
+/* API_SEARCH_CANCEL */     {BTA_DM_SEARCH_CLEAR_QUEUE,         BTA_DM_SEARCH_CANCEL_NOTIFY,   BTA_DM_SEARCH_CANCELLING},
+/* API_SEARCH_DISC */       {BTA_DM_QUEUE_DISC,                 BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_CANCELLING},
+/* INQUIRY_CMPL */          {BTA_DM_SEARCH_CANCEL_CMPL,         BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE},
+/* REMT_NAME_EVT */         {BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL, BTA_DM_SEARCH_CANCEL_CMPL,     BTA_DM_SEARCH_IDLE},
+/* SDP_RESULT_EVT */        {BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL, BTA_DM_SEARCH_CANCEL_CMPL,     BTA_DM_SEARCH_IDLE},
+/* SEARCH_CMPL_EVT */       {BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL, BTA_DM_SEARCH_CANCEL_CMPL,     BTA_DM_SEARCH_IDLE},
+/* DISCV_RES_EVT */         {BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL, BTA_DM_SEARCH_CANCEL_CMPL,     BTA_DM_SEARCH_IDLE},
+/* API_DI_DISCOVER_EVT */   {BTA_DM_SEARCH_IGNORE,              BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_CANCELLING}
+#if BLE_INCLUDED == TRUE
+/* DISC_CLOSE_TOUT_EVT */   ,{BTA_DM_SEARCH_IGNORE,              BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_CANCELLING}
+#endif
+
+};
+
+const UINT8 bta_dm_search_disc_active_st_table[][BTA_DM_SEARCH_NUM_COLS] =
+{
+
+/* Event                        Action 1                            Action 2                    Next State */
+/* API_SEARCH */            {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_DISCOVER_ACTIVE},
+/* API_SEARCH_CANCEL */     {BTA_DM_SEARCH_CANCEL_NOTIFY,      BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_CANCELLING},
+/* API_SEARCH_DISC */       {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_DISCOVER_ACTIVE},
+/* INQUIRY_CMPL */          {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_DISCOVER_ACTIVE},
+/* REMT_NAME_EVT */         {BTA_DM_DISC_RMT_NAME,             BTA_DM_SEARCH_IGNORE,          BTA_DM_DISCOVER_ACTIVE},
+/* SDP_RESULT_EVT */        {BTA_DM_SDP_RESULT,                BTA_DM_SEARCH_IGNORE,          BTA_DM_DISCOVER_ACTIVE},
+/* SEARCH_CMPL_EVT */       {BTA_DM_SEARCH_CMPL,               BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE},
+/* DISCV_RES_EVT */         {BTA_DM_DISC_RESULT,               BTA_DM_SEARCH_IGNORE,          BTA_DM_DISCOVER_ACTIVE},
+/* API_DI_DISCOVER_EVT */   {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_DISCOVER_ACTIVE}
+
+#if BLE_INCLUDED == TRUE
+/* DISC_CLOSE_TOUT_EVT */   ,{BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_DISCOVER_ACTIVE}
+#endif
+};
+
+typedef const UINT8 (*tBTA_DM_ST_TBL)[BTA_DM_SEARCH_NUM_COLS];
+
+/* state table */
+const tBTA_DM_ST_TBL bta_dm_search_st_tbl[] = {
+    bta_dm_search_idle_st_table,
+    bta_dm_search_search_active_st_table,
+    bta_dm_search_search_cancelling_st_table,
+    bta_dm_search_disc_active_st_table
+};
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_sm_disable
+**
+** Description     unregister BTA DM
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_sm_disable( )
+{
+    bta_sys_deregister( BTA_ID_DM );
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_sm_execute
+**
+** Description      State machine event handling function for DM
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN bta_dm_sm_execute(BT_HDR *p_msg)
+{
+    UINT16  event = p_msg->event & 0x00ff;
+
+    APPL_TRACE_EVENT("bta_dm_sm_execute event:0x%x", event);
+
+    /* execute action functions */
+    if(event < BTA_DM_NUM_ACTIONS)
+    {
+        (*bta_dm_action[event])( (tBTA_DM_MSG*) p_msg);
+    }
+
+    return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_sm_search_disable
+**
+** Description     unregister BTA SEARCH DM
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_search_sm_disable( )
+{
+    bta_sys_deregister( BTA_ID_DM_SEARCH );
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_search_sm_execute
+**
+** Description      State machine event handling function for DM
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN bta_dm_search_sm_execute(BT_HDR *p_msg)
+{
+    tBTA_DM_ST_TBL      state_table;
+    UINT8               action;
+    int                 i;
+
+    APPL_TRACE_EVENT("bta_dm_search_sm_execute state:%d, event:0x%x",
+        bta_dm_search_cb.state, p_msg->event);
+
+    /* look up the state table for the current state */
+    state_table = bta_dm_search_st_tbl[bta_dm_search_cb.state];
+
+    bta_dm_search_cb.state = state_table[p_msg->event & 0x00ff][BTA_DM_SEARCH_NEXT_STATE];
+
+
+    /* execute action functions */
+    for (i = 0; i < BTA_DM_SEARCH_ACTIONS; i++)
+    {
+        if ((action = state_table[p_msg->event & 0x00ff][i]) != BTA_DM_SEARCH_IGNORE)
+        {
+            (*bta_dm_search_action[action])( (tBTA_DM_MSG*) p_msg);
+        }
+        else
+        {
+            break;
+        }
+    }
+    return TRUE;
+}
+

+ 1242 - 0
components/bt/bluedroid/bta/dm/bta_dm_pm.c

@@ -0,0 +1,1242 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This file contains the action functions for device manager state
+ *  machine.
+ *
+ ******************************************************************************/
+
+// #include <assert.h>
+#include <string.h>
+
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_dm_int.h"
+#include "btm_api.h"
+
+
+static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+static void bta_dm_pm_set_mode(BD_ADDR peer_addr, tBTA_DM_PM_ACTION pm_mode,
+                               tBTA_DM_PM_REQ pm_req);
+static void bta_dm_pm_timer_cback(void *p_tle);
+static void bta_dm_pm_btm_cback(BD_ADDR bd_addr, tBTM_PM_STATUS status, UINT16 value, UINT8 hci_status);
+static BOOLEAN bta_dm_pm_park(BD_ADDR peer_addr);
+static BOOLEAN bta_dm_pm_sniff(tBTA_DM_PEER_DEVICE *p_peer_dev, UINT8 index);
+static BOOLEAN bta_dm_pm_is_sco_active ();
+static void bta_dm_pm_hid_check(BOOLEAN bScoActive);
+static void bta_dm_pm_set_sniff_policy(tBTA_DM_PEER_DEVICE *p_dev, BOOLEAN bDisable);
+static void bta_dm_pm_stop_timer_by_index(tBTA_PM_TIMER *p_timer,
+                                          UINT8 timer_idx);
+
+#if (BTM_SSR_INCLUDED == TRUE)
+#if (defined BTA_HH_INCLUDED && BTA_HH_INCLUDED == TRUE)
+#include "../hh/bta_hh_int.h"
+/* BTA_DM_PM_SSR1 will be dedicated for HH SSR setting entry, no other profile can use it */
+#define BTA_DM_PM_SSR_HH      BTA_DM_PM_SSR1
+#endif
+static void bta_dm_pm_ssr(BD_ADDR peer_addr);
+#endif
+
+tBTA_DM_CONNECTED_SRVCS bta_dm_conn_srvcs;
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_init_pm
+**
+** Description      Initializes the BT low power manager
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_init_pm(void)
+{
+    memset(&bta_dm_conn_srvcs, 0x00, sizeof(bta_dm_conn_srvcs));
+
+    /* if there are no power manger entries, so not register */
+    if(p_bta_dm_pm_cfg[0].app_id != 0)
+    {
+        bta_sys_pm_register((tBTA_SYS_CONN_CBACK*)bta_dm_pm_cback);
+
+        BTM_PmRegister((BTM_PM_REG_SET | BTM_PM_REG_NOTIF), &bta_dm_cb.pm_id,
+                       bta_dm_pm_btm_cback);
+    }
+
+    /* Need to initialize all PM timer service IDs */
+    for (int i = 0; i < BTA_DM_NUM_PM_TIMER; i++)
+    {
+        for (int j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++)
+            bta_dm_cb.pm_timer[i].srvc_id[j] = BTA_ID_MAX;
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_disable_pm
+**
+** Description      Disable PM
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_disable_pm(void)
+{
+    BTM_PmRegister( BTM_PM_DEREG, &bta_dm_cb.pm_id, NULL);
+
+    /*
+     * Deregister the PM callback from the system handling to prevent
+     * re-enabling the PM timers after this call if the callback is invoked.
+     */
+    bta_sys_pm_register((tBTA_SYS_CONN_CBACK*)NULL);
+
+    /* Need to stop all active timers. */
+    for (int i = 0; i < BTA_DM_NUM_PM_TIMER; i++)
+    {
+        for (int j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++)
+        {
+            bta_dm_pm_stop_timer_by_index(&bta_dm_cb.pm_timer[i], j);
+            bta_dm_cb.pm_timer[i].pm_action[j] = BTA_DM_PM_NO_ACTION;
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_get_av_count
+**
+** Description      Get the number of connected AV
+**
+**
+** Returns          number of av connections
+**
+*******************************************************************************/
+UINT8 bta_dm_get_av_count(void)
+{
+    UINT8 count = 0;
+    for (int i = 0; i < bta_dm_conn_srvcs.count; i++)
+    {
+        if (bta_dm_conn_srvcs.conn_srvc[i].id == BTA_ID_AV)
+            ++count;
+    }
+    return count;
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_stop_timer
+**
+** Description      stop a PM timer
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_pm_stop_timer(BD_ADDR peer_addr)
+{
+    APPL_TRACE_DEBUG("%s: ", __func__);
+
+    for(int i=0; i<BTA_DM_NUM_PM_TIMER; i++)
+    {
+        if (bta_dm_cb.pm_timer[i].in_use && !bdcmp(bta_dm_cb.pm_timer[i].peer_bdaddr, peer_addr))
+        {
+            for (int j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++)
+            {
+                bta_dm_pm_stop_timer_by_index(&bta_dm_cb.pm_timer[i], j);
+                /*
+                 * TODO: For now, stopping the timer does not reset
+                 * pm_action[j].
+                 * The reason is because some of the internal logic that
+                 * (re)assigns the pm_action[] values is taking into account
+                 * the older value; e.g., see the pm_action[] assignment in
+                 * function bta_dm_pm_start_timer().
+                 * Such subtlety in the execution logic is error prone, and
+                 * should be eliminiated in the future.
+                 */
+            }
+            break;
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_pm_action_to_timer_idx
+**
+** Description      convert power mode into timer index for each connected device
+**
+**
+** Returns          index of the power mode delay timer
+**
+*******************************************************************************/
+static UINT8 bta_pm_action_to_timer_idx(UINT8 pm_action)
+{
+    if (pm_action == BTA_DM_PM_SUSPEND)
+        return BTA_DM_PM_SUSPEND_TIMER_IDX;
+    else if (pm_action == BTA_DM_PM_PARK)
+        return BTA_DM_PM_PARK_TIMER_IDX;
+    else if ((pm_action & BTA_DM_PM_SNIFF) == BTA_DM_PM_SNIFF)
+        return BTA_DM_PM_SNIFF_TIMER_IDX;
+
+    /* Active, no preference, no action and retry */
+    return BTA_DM_PM_MODE_TIMER_MAX;
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_stop_timer_by_mode
+**
+** Description      stop a PM timer
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_pm_stop_timer_by_mode(BD_ADDR peer_addr, UINT8 power_mode)
+{
+    const UINT8 timer_idx = bta_pm_action_to_timer_idx(power_mode);
+    if (timer_idx == BTA_DM_PM_MODE_TIMER_MAX)
+        return;
+
+    for (int i = 0; i < BTA_DM_NUM_PM_TIMER; i++)
+    {
+        if (bta_dm_cb.pm_timer[i].in_use && !bdcmp(bta_dm_cb.pm_timer[i].peer_bdaddr, peer_addr))
+        {
+            if (bta_dm_cb.pm_timer[i].srvc_id[timer_idx] != BTA_ID_MAX)
+            {
+                bta_dm_pm_stop_timer_by_index(&bta_dm_cb.pm_timer[i], timer_idx);
+                /*
+                 * TODO: Intentionally setting pm_action[timer_idx].
+                 * This assignment should be eliminated in the future - see the
+                 * pm_action[] related comment inside function
+                 * bta_dm_pm_stop_timer().
+                 */
+                bta_dm_cb.pm_timer[i].pm_action[timer_idx] = power_mode;
+            }
+            break;
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_stop_timer_by_srvc_id
+**
+** Description      stop all timer started by the service ID.
+**
+**
+** Returns          index of the power mode delay timer
+**
+*******************************************************************************/
+static void bta_dm_pm_stop_timer_by_srvc_id(BD_ADDR peer_addr, UINT8 srvc_id)
+{
+    for (int i = 0; i < BTA_DM_NUM_PM_TIMER; i++)
+    {
+        if (bta_dm_cb.pm_timer[i].in_use && !bdcmp(bta_dm_cb.pm_timer[i].peer_bdaddr, peer_addr))
+        {
+            for (int j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++)
+            {
+                if (bta_dm_cb.pm_timer[i].srvc_id[j] == srvc_id)
+                {
+                    bta_dm_pm_stop_timer_by_index(&bta_dm_cb.pm_timer[i], j);
+                    bta_dm_cb.pm_timer[i].pm_action[j] = BTA_DM_PM_NO_ACTION;
+                    break;
+                }
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_start_timer
+**
+** Description      start a PM timer
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_pm_start_timer(tBTA_PM_TIMER *p_timer, UINT8 timer_idx,
+                                  INT32 timeout, UINT8 srvc_id, UINT8 pm_action)
+{
+    p_timer->in_use = TRUE;
+    p_timer->timer[timer_idx].p_cback = bta_dm_pm_timer_cback;
+
+    if (p_timer->srvc_id[timer_idx] == BTA_ID_MAX)
+        p_timer->active++;
+
+    if (p_timer->pm_action[timer_idx] < pm_action)
+        p_timer->pm_action[timer_idx] = pm_action;
+
+    p_timer->srvc_id[timer_idx] = srvc_id;
+
+    bta_sys_start_timer(&p_timer->timer[timer_idx], 0, timeout);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_stop_timer_by_index
+**
+** Description      stop a PM timer
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_pm_stop_timer_by_index(tBTA_PM_TIMER *p_timer,
+                                          UINT8 timer_idx)
+{
+    if ((p_timer == NULL) || (timer_idx >= BTA_DM_PM_MODE_TIMER_MAX))
+        return;
+
+    if (p_timer->srvc_id[timer_idx] == BTA_ID_MAX)
+        return;                 /* The timer was not scheduled */
+
+    assert(p_timer->in_use && (p_timer->active > 0));
+
+    bta_sys_stop_timer(&p_timer->timer[timer_idx]);
+    p_timer->srvc_id[timer_idx] = BTA_ID_MAX;
+    /* NOTE: pm_action[timer_idx] intentionally not reset */
+
+    p_timer->active--;
+    if (p_timer->active == 0)
+        p_timer->in_use = FALSE;
+}
+
+UINT32 bta_dm_pm_get_remaining_ticks (TIMER_LIST_ENT  *p_target_tle)
+{
+    return bta_sys_get_remaining_ticks(p_target_tle);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_cback
+**
+** Description      Conn change callback from sys for low power management
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+
+    UINT8 i,j;
+    UINT16 policy_setting;
+    UINT8 *p = NULL;
+    tBTA_DM_PEER_DEVICE *p_dev;
+
+#if (BTM_SSR_INCLUDED == TRUE)
+    int               index = BTA_DM_PM_SSR0;
+#endif
+
+    APPL_TRACE_DEBUG("bta_dm_pm_cback: st(%d), id(%d), app(%d)", status, id, app_id);
+
+    p_dev = bta_dm_find_peer_device(peer_addr);
+
+    /* find if there is an power mode entry for the service */
+    for(i=1; i<=p_bta_dm_pm_cfg[0].app_id; i++)
+    {
+
+        if((p_bta_dm_pm_cfg[i].id == id)
+            && ((p_bta_dm_pm_cfg[i].app_id == BTA_ALL_APP_ID ) || (p_bta_dm_pm_cfg[i].app_id == app_id )))
+            break;
+
+    }
+
+    /* if no entries are there for the app_id and subsystem in p_bta_dm_pm_spec*/
+    if(i> p_bta_dm_pm_cfg[0].app_id)
+        return;
+
+    bta_dm_pm_stop_timer_by_srvc_id(peer_addr, id);
+    /*p_dev = bta_dm_find_peer_device(peer_addr);*/
+
+#if (BTM_SSR_INCLUDED == TRUE)
+    /* set SSR parameters on SYS CONN OPEN */
+    if((BTA_SYS_CONN_OPEN == status) && p_dev && (p_dev->info & BTA_DM_DI_USE_SSR))
+    {
+        index = p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].ssr;
+    }
+#endif
+
+    /* if no action for the event */
+    if(p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].actn_tbl[status][0].power_mode == BTA_DM_PM_NO_ACTION)
+    {
+#if (BTM_SSR_INCLUDED == TRUE)
+        if(BTA_DM_PM_SSR0 == index) /* and do not need to set SSR, return. */
+#endif
+        return;
+    }
+
+    for(j=0; j<bta_dm_conn_srvcs.count ; j++)
+    {
+        /* check if an entry already present */
+        if((bta_dm_conn_srvcs.conn_srvc[j].id == id)
+            && (bta_dm_conn_srvcs.conn_srvc[j].app_id == app_id )
+            && !bdcmp(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr, peer_addr))
+        {
+            bta_dm_conn_srvcs.conn_srvc[j].new_request = TRUE;
+            break;
+        }
+
+    }
+
+        /* if subsystem has no more preference on the power mode remove
+       the cb */
+    if(p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].actn_tbl[status][0].power_mode == BTA_DM_PM_NO_PREF)
+    {
+        if(j != bta_dm_conn_srvcs.count)
+        {
+            bta_dm_conn_srvcs.count--;
+
+            for(; j<bta_dm_conn_srvcs.count ; j++)
+            {
+
+                memcpy(&bta_dm_conn_srvcs.conn_srvc[j], &bta_dm_conn_srvcs.conn_srvc[j+1], sizeof(bta_dm_conn_srvcs.conn_srvc[j]));
+
+            }
+        }
+        else
+        {
+            APPL_TRACE_WARNING("bta_dm_act no entry for connected service cbs");
+            return;
+        }
+    }
+    else if(j == bta_dm_conn_srvcs.count )
+    {
+        /* check if we have more connected service that cbs */
+        if(bta_dm_conn_srvcs.count == BTA_DM_NUM_CONN_SRVS)
+        {
+            APPL_TRACE_WARNING("bta_dm_act no more connected service cbs");
+            return;
+        }
+
+        /* fill in a new cb */
+        bta_dm_conn_srvcs.conn_srvc[j].id = id;
+        bta_dm_conn_srvcs.conn_srvc[j].app_id = app_id;
+        bta_dm_conn_srvcs.conn_srvc[j].new_request = TRUE;
+        bdcpy(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr, peer_addr);
+
+        APPL_TRACE_WARNING("new conn_srvc id:%d, app_id:%d", id, app_id);
+
+        bta_dm_conn_srvcs.count++;
+        bta_dm_conn_srvcs.conn_srvc[j].state = status;
+    }
+    else
+    {
+        /* no service is added or removed. only updating status. */
+        bta_dm_conn_srvcs.conn_srvc[j].state = status;
+    }
+
+    /* stop timer */
+    bta_dm_pm_stop_timer(peer_addr);
+
+    if(p_dev)
+    {
+        p_dev->pm_mode_attempted = 0;
+        p_dev->pm_mode_failed = 0;
+    }
+
+#if (BTM_SSR_INCLUDED == TRUE)
+    if(p_bta_dm_ssr_spec[index].max_lat
+#if (defined BTA_HH_INCLUDED && BTA_HH_INCLUDED == TRUE)
+       || index == BTA_DM_PM_SSR_HH
+#endif
+       )
+    {
+        bta_dm_pm_ssr(peer_addr);
+    }
+    else
+    {
+        if( ((NULL != (p = BTM_ReadLocalFeatures ())) && HCI_SNIFF_SUB_RATE_SUPPORTED(p)) &&
+            ((NULL != (p = BTM_ReadRemoteFeatures (peer_addr))) && HCI_SNIFF_SUB_RATE_SUPPORTED(p)) &&
+            (index == BTA_DM_PM_SSR0))
+        {
+            if (status == BTA_SYS_SCO_OPEN)
+            {
+                APPL_TRACE_DEBUG("%s: SCO inactive, reset SSR to zero", __func__);
+                BTM_SetSsrParams (peer_addr, 0,0,0 );
+            }
+            else if (status == BTA_SYS_SCO_CLOSE)
+            {
+                APPL_TRACE_DEBUG("%s: SCO active, back to old SSR", __func__);
+                bta_dm_pm_ssr(peer_addr);
+            }
+        }
+    }
+#endif
+
+    bta_dm_pm_set_mode(peer_addr, BTA_DM_PM_NO_ACTION, BTA_DM_PM_NEW_REQ);
+
+    /* perform the HID link workaround if needed
+    ** 1. If SCO up/down event is received OR
+    ** 2. If HID connection open is received and SCO is already active.
+    **     This will handle the case where HID connects when SCO already active
+    */
+    if ( BTM_IsDeviceUp() &&
+         ( ((status == BTA_SYS_SCO_OPEN) || (status == BTA_SYS_SCO_CLOSE)) ||
+           ((status == BTA_SYS_CONN_OPEN) && (id == BTA_ID_HH) && bta_dm_pm_is_sco_active()) ) )
+    {
+        BOOLEAN bScoActive;
+        if (status == BTA_SYS_CONN_OPEN)
+            bScoActive = TRUE;
+        else
+            bScoActive = (status == BTA_SYS_SCO_OPEN);
+
+        bta_dm_pm_hid_check(bScoActive);
+    }
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_set_mode
+**
+** Description      Set the power mode for the device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+
+static void bta_dm_pm_set_mode(BD_ADDR peer_addr, tBTA_DM_PM_ACTION pm_request,
+                               tBTA_DM_PM_REQ pm_req )
+{
+
+    tBTA_DM_PM_ACTION   pm_action = BTA_DM_PM_NO_ACTION;
+    UINT16              timeout = 0;
+    UINT8               i,j;
+    tBTA_DM_PM_ACTION   failed_pm = 0;
+    tBTA_DM_PEER_DEVICE *p_peer_device = NULL;
+    tBTA_DM_PM_ACTION    allowed_modes = 0;
+    tBTA_DM_PM_ACTION    pref_modes = 0;
+    tBTA_DM_PM_CFG      *p_pm_cfg;
+    tBTA_DM_PM_SPEC     *p_pm_spec;
+    tBTA_DM_PM_ACTN     *p_act0, *p_act1;
+    tBTA_DM_SRVCS       *p_srvcs = NULL;
+    BOOLEAN timer_started = FALSE;
+    UINT8   timer_idx, available_timer = BTA_DM_PM_MODE_TIMER_MAX;
+    UINT32  remaining_ticks = 0;
+
+    if(!bta_dm_cb.device_list.count)
+        return;
+
+    /* see if any attempt to put device in low power mode failed */
+    p_peer_device = bta_dm_find_peer_device(peer_addr);
+    /* if no peer device found return */
+    if (p_peer_device == NULL)
+        return;
+
+    failed_pm = p_peer_device->pm_mode_failed;
+
+    for(i=0; i<bta_dm_conn_srvcs.count ; i++)
+    {
+
+        p_srvcs = &bta_dm_conn_srvcs.conn_srvc[i];
+        if(!bdcmp(p_srvcs->peer_bdaddr, peer_addr))
+        {
+
+            /* p_bta_dm_pm_cfg[0].app_id is the number of entries */
+            for(j=1; j<=p_bta_dm_pm_cfg[0].app_id; j++)
+            {
+                if((p_bta_dm_pm_cfg[j].id == p_srvcs->id)
+                    && ((p_bta_dm_pm_cfg[j].app_id == BTA_ALL_APP_ID ) ||
+                    (p_bta_dm_pm_cfg[j].app_id == p_srvcs->app_id)))
+                    break;
+            }
+
+            p_pm_cfg = &p_bta_dm_pm_cfg[j];
+            p_pm_spec = &p_bta_dm_pm_spec[p_pm_cfg->spec_idx];
+            p_act0 = &p_pm_spec->actn_tbl[p_srvcs->state][0];
+            p_act1 = &p_pm_spec->actn_tbl[p_srvcs->state][1];
+
+            APPL_TRACE_DEBUG("bta_dm_pm_set_mode: srvcsid: %d, state: %d, j: %d", p_srvcs->id, p_srvcs->state, j);
+            allowed_modes |= p_pm_spec->allow_mask;
+
+            /* PM actions are in the order of strictness */
+
+            /* first check if the first preference is ok */
+            if(!(failed_pm & p_act0->power_mode))
+            {
+                pref_modes |= p_act0->power_mode;
+
+                if(p_act0->power_mode >= pm_action)
+                {
+                    pm_action = p_act0->power_mode;
+
+                    if (pm_req != BTA_DM_PM_NEW_REQ || p_srvcs->new_request)
+                    {
+                        p_srvcs->new_request = FALSE;
+                        timeout =  p_act0->timeout;
+                    }
+                }
+            }
+            /* if first preference has already failed, try second preference */
+            else if(!(failed_pm & p_act1->power_mode))
+            {
+                pref_modes |= p_act1->power_mode;
+
+                if(p_act1->power_mode > pm_action)
+                {
+                    pm_action = p_act1->power_mode;
+                    timeout =  p_act1->timeout;
+                }
+            }
+        }
+    }
+
+    if(pm_action & (BTA_DM_PM_PARK | BTA_DM_PM_SNIFF))
+    {
+        /* some service don't like the mode */
+        if(!(allowed_modes & pm_action))
+        {
+
+            /* select the other mode if its allowed and preferred, otherwise 0 which is BTA_DM_PM_NO_ACTION */
+            pm_action =  (allowed_modes & (BTA_DM_PM_PARK | BTA_DM_PM_SNIFF) & pref_modes);
+
+            /* no timeout needed if no action is required */
+            if(pm_action == BTA_DM_PM_NO_ACTION)
+            {
+                timeout = 0;
+            }
+
+        }
+    }
+    /* if need to start a timer */
+    if((pm_req != BTA_DM_PM_EXECUTE) && timeout)
+    {
+        for(i=0; i<BTA_DM_NUM_PM_TIMER; i++)
+        {
+            if(bta_dm_cb.pm_timer[i].in_use && bdcmp(bta_dm_cb.pm_timer[i].peer_bdaddr, peer_addr) == 0)
+            {
+                if ((timer_idx = bta_pm_action_to_timer_idx(pm_action)) != BTA_DM_PM_MODE_TIMER_MAX)
+                {
+                    remaining_ticks = bta_dm_pm_get_remaining_ticks(&bta_dm_cb.pm_timer[i].timer[timer_idx]);
+                    if (remaining_ticks < timeout)
+                    {
+			ets_printf("remain 00\n");
+                        /* Cancel and restart the timer */
+                        /*
+                         * TODO: The value of pm_action[timer_idx] is
+                         * conditionally updated between the two function
+                         * calls below when the timer is restarted.
+                         * This logic is error-prone and should be eliminated
+                         * in the future.
+                         */
+                        bta_dm_pm_stop_timer_by_index(&bta_dm_cb.pm_timer[i],
+                                                      timer_idx);
+                        bta_dm_pm_start_timer(&bta_dm_cb.pm_timer[i], timer_idx, timeout, p_srvcs->id, pm_action);
+                    }
+                    timer_started = TRUE;
+                }
+                break;
+            }
+            else if (!bta_dm_cb.pm_timer[i].in_use)
+            {
+                APPL_TRACE_DEBUG("%s dm_pm_timer:%d, %d", __func__, i, timeout);
+                if (available_timer == BTA_DM_PM_MODE_TIMER_MAX)
+                    available_timer = i;
+            }
+        }
+        /* new power mode for a new active connection */
+        if (!timer_started)
+        {
+            if( available_timer != BTA_DM_PM_MODE_TIMER_MAX)
+            {
+                bdcpy(bta_dm_cb.pm_timer[available_timer].peer_bdaddr, peer_addr);
+                if ((timer_idx = bta_pm_action_to_timer_idx(pm_action)) != BTA_DM_PM_MODE_TIMER_MAX)
+                {
+                    bta_dm_pm_start_timer(&bta_dm_cb.pm_timer[available_timer], timer_idx, timeout, p_srvcs->id, pm_action);
+                    timer_started = TRUE;
+                }
+            }
+            /* no more timers */
+            else
+            {
+                APPL_TRACE_WARNING("bta_dm_act dm_pm_timer no more");
+            }
+        }
+        return;
+    }
+    /* if pending power mode timer expires, and currecnt link is in a
+       lower power mode than current profile requirement, igonre it */
+    if (pm_req == BTA_DM_PM_EXECUTE && pm_request < pm_action)
+    {
+        APPL_TRACE_ERROR("Ignore the power mode request: %d", pm_request)
+        return;
+    }
+    if(pm_action == BTA_DM_PM_PARK)
+    {
+        p_peer_device->pm_mode_attempted = BTA_DM_PM_PARK;
+        bta_dm_pm_park(peer_addr);
+    }
+    else if(pm_action & BTA_DM_PM_SNIFF)
+    {
+        /* dont initiate SNIFF, if link_policy has it disabled */
+        if (p_peer_device->link_policy & HCI_ENABLE_SNIFF_MODE)
+        {
+            p_peer_device->pm_mode_attempted = BTA_DM_PM_SNIFF;
+            bta_dm_pm_sniff(p_peer_device, (UINT8)(pm_action & 0x0F) );
+        }
+        else
+        {
+            APPL_TRACE_DEBUG("bta_dm_pm_set_mode: Link policy disallows SNIFF, ignore request");
+        }
+    }
+    else if(pm_action == BTA_DM_PM_ACTIVE)
+    {
+        bta_dm_pm_active(peer_addr);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_ag_pm_park
+**
+** Description      Switch to park mode.
+**
+**
+** Returns          TRUE if park attempted, FALSE otherwise.
+**
+*******************************************************************************/
+static BOOLEAN bta_dm_pm_park(BD_ADDR peer_addr)
+{
+
+    tBTM_PM_MODE    mode = BTM_PM_STS_ACTIVE;
+
+    /* if not in park mode, switch to park */
+    BTM_ReadPowerMode(peer_addr, &mode);
+
+    if(mode != BTM_PM_MD_PARK)
+    {
+        BTM_SetPowerMode (bta_dm_cb.pm_id, peer_addr, &p_bta_dm_pm_md[BTA_DM_PM_PARK_IDX]);
+    }
+    return TRUE;
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_pm_sniff
+**
+** Description      Switch to sniff mode.
+**
+**
+** Returns          TRUE if sniff attempted, FALSE otherwise.
+**
+*******************************************************************************/
+static BOOLEAN bta_dm_pm_sniff(tBTA_DM_PEER_DEVICE *p_peer_dev, UINT8 index)
+{
+    tBTM_PM_MODE    mode = BTM_PM_STS_ACTIVE;
+    tBTM_PM_PWR_MD  pwr_md;
+    tBTM_STATUS     status;
+#if (BTM_SSR_INCLUDED == TRUE)
+    UINT8 *p_rem_feat = NULL;
+#endif
+
+    BTM_ReadPowerMode(p_peer_dev->peer_bdaddr, &mode);
+    p_rem_feat = BTM_ReadRemoteFeatures (p_peer_dev->peer_bdaddr);
+#if (BTM_SSR_INCLUDED == TRUE)
+    APPL_TRACE_DEBUG("bta_dm_pm_sniff cur:%d, idx:%d, info:x%x", mode, index, p_peer_dev->info);
+    if (mode != BTM_PM_MD_SNIFF ||
+        (HCI_SNIFF_SUB_RATE_SUPPORTED(BTM_ReadLocalFeatures ()) && p_rem_feat &&
+         HCI_SNIFF_SUB_RATE_SUPPORTED(p_rem_feat) &&
+         !(p_peer_dev->info & BTA_DM_DI_USE_SSR)))
+#else
+    APPL_TRACE_DEBUG("bta_dm_pm_sniff cur:%d, idx:%d", mode, index);
+    if(mode != BTM_PM_MD_SNIFF)
+#endif
+    {
+#if (BTM_SSR_INCLUDED == TRUE)
+        /* Dont initiate Sniff if controller has alreay accepted
+         * remote sniff params. This avoid sniff loop issue with
+         * some agrresive headsets who use sniff latencies more than
+         * DUT supported range of Sniff intervals.*/
+        if ((mode == BTM_PM_MD_SNIFF) && (p_peer_dev->info & BTA_DM_DI_ACP_SNIFF))
+        {
+            APPL_TRACE_DEBUG("%s: already in remote initiate sniff", __func__);
+            return TRUE;
+        }
+#endif
+        /* if the current mode is not sniff, issue the sniff command.
+         * If sniff, but SSR is not used in this link, still issue the command */
+        memcpy(&pwr_md, &p_bta_dm_pm_md[index], sizeof (tBTM_PM_PWR_MD));
+        if (p_peer_dev->info & BTA_DM_DI_INT_SNIFF)
+        {
+            pwr_md.mode |= BTM_PM_MD_FORCE;
+        }
+        status = BTM_SetPowerMode (bta_dm_cb.pm_id, p_peer_dev->peer_bdaddr, &pwr_md);
+        if (status == BTM_CMD_STORED|| status == BTM_CMD_STARTED)
+        {
+            p_peer_dev->info &= ~(BTA_DM_DI_INT_SNIFF|BTA_DM_DI_ACP_SNIFF);
+            p_peer_dev->info |= BTA_DM_DI_SET_SNIFF;
+        }
+        else if (status == BTM_SUCCESS)
+        {
+            APPL_TRACE_DEBUG("bta_dm_pm_sniff BTM_SetPowerMode() returns BTM_SUCCESS");
+            p_peer_dev->info &= ~(BTA_DM_DI_INT_SNIFF|BTA_DM_DI_ACP_SNIFF|BTA_DM_DI_SET_SNIFF);
+        }
+        else /* error */
+        {
+            APPL_TRACE_ERROR("bta_dm_pm_sniff BTM_SetPowerMode() returns ERROR status=%d", status);
+            p_peer_dev->info &= ~(BTA_DM_DI_INT_SNIFF|BTA_DM_DI_ACP_SNIFF|BTA_DM_DI_SET_SNIFF);
+        }
+    }
+    return TRUE;
+
+}
+/*******************************************************************************
+**
+** Function         bta_dm_pm_ssr
+**
+** Description      checks and sends SSR parameters
+**
+** Returns          void
+**
+*******************************************************************************/
+#if (BTM_SSR_INCLUDED == TRUE)
+static void bta_dm_pm_ssr(BD_ADDR peer_addr)
+{
+    tBTA_DM_SSR_SPEC *p_spec, *p_spec_cur;
+    UINT8   i,j;
+    int     ssr = BTA_DM_PM_SSR0;
+
+    /* go through the connected services */
+    for(i=0; i<bta_dm_conn_srvcs.count ; i++)
+    {
+        if(!bdcmp(bta_dm_conn_srvcs.conn_srvc[i].peer_bdaddr, peer_addr))
+        {
+            /* p_bta_dm_pm_cfg[0].app_id is the number of entries */
+            for(j=1; j<=p_bta_dm_pm_cfg[0].app_id; j++)
+            {
+                /* find the associated p_bta_dm_pm_cfg */
+                if((p_bta_dm_pm_cfg[j].id == bta_dm_conn_srvcs.conn_srvc[i].id)
+                    && ((p_bta_dm_pm_cfg[j].app_id == BTA_ALL_APP_ID )
+                    || (p_bta_dm_pm_cfg[j].app_id == bta_dm_conn_srvcs.conn_srvc[i].app_id)))
+                {
+                    APPL_TRACE_WARNING("bta_dm_pm_ssr conn_srvc id:%d, app_id:%d",
+                        bta_dm_conn_srvcs.conn_srvc[i].id, bta_dm_conn_srvcs.conn_srvc[i].app_id);
+                    break;
+                }
+            }
+
+            /* find the ssr index with the smallest max latency. */
+            p_spec_cur = &p_bta_dm_ssr_spec[p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr];
+            p_spec = &p_bta_dm_ssr_spec[ssr];
+
+#if (defined BTA_HH_INCLUDED && BTA_HH_INCLUDED == TRUE)
+            /* HH has the per connection SSR preference, already read the SSR params from BTA HH */
+            if (p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr == BTA_DM_PM_SSR_HH)
+            {
+                if (bta_hh_read_ssr_param(peer_addr, &p_spec_cur->max_lat, &p_spec_cur->min_rmt_to) == BTA_HH_ERR)
+                    continue;
+            }
+#endif
+            if (p_spec_cur->max_lat < p_spec->max_lat ||
+                (ssr == BTA_DM_PM_SSR0 && p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr != BTA_DM_PM_SSR0))
+            {
+                ssr = p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr;
+            }
+
+        }
+    }
+
+    p_spec = &p_bta_dm_ssr_spec[ssr];
+    APPL_TRACE_WARNING("bta_dm_pm_ssr:%d, lat:%d", ssr, p_spec->max_lat);
+    if(p_spec->max_lat)
+    {
+        /* set the SSR parameters. */
+        BTM_SetSsrParams (peer_addr, p_spec->max_lat,
+            p_spec->min_rmt_to, p_spec->min_loc_to);
+    }
+}
+#endif
+/*******************************************************************************
+**
+** Function         bta_dm_pm_active
+**
+** Description      Brings connection to active mode
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_pm_active(BD_ADDR peer_addr)
+{
+    tBTM_PM_PWR_MD  pm;
+
+    memset( (void*)&pm, 0, sizeof(pm));
+
+    /* switch to active mode */
+    pm.mode = BTM_PM_MD_ACTIVE;
+    BTM_SetPowerMode (bta_dm_cb.pm_id, peer_addr, &pm);
+
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_btm_cback
+**
+** Description      BTM power manager callback.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_pm_btm_cback(BD_ADDR bd_addr, tBTM_PM_STATUS status, UINT16 value, UINT8 hci_status)
+{
+   tBTA_DM_PM_BTM_STATUS  *p_buf;
+
+   if ((p_buf = (tBTA_DM_PM_BTM_STATUS *) GKI_getbuf(sizeof(tBTA_DM_PM_BTM_STATUS))) != NULL)
+    {
+        p_buf->hdr.event = BTA_DM_PM_BTM_STATUS_EVT;
+        p_buf->status = status;
+        p_buf->value = value;
+        p_buf->hci_status = hci_status;
+        bdcpy(p_buf->bd_addr, bd_addr);
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_timer_cback
+**
+** Description      Power management timer callback.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_pm_timer_cback(void *p_tle)
+{
+    UINT8 i, j;
+
+    for (i=0; i<BTA_DM_NUM_PM_TIMER; i++)
+    {
+        APPL_TRACE_DEBUG("dm_pm_timer[%d] in use? %d", i, bta_dm_cb.pm_timer[i].in_use);
+        if (bta_dm_cb.pm_timer[i].in_use)
+        {
+            for (j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++)
+            {
+                if(&bta_dm_cb.pm_timer[i].timer[j] == (TIMER_LIST_ENT*) p_tle)
+                {
+                    bta_dm_cb.pm_timer[i].active --;
+                    bta_dm_cb.pm_timer[i].srvc_id[j] = BTA_ID_MAX;
+                    APPL_TRACE_DEBUG("dm_pm_timer[%d] expires, timer_idx=%d", i, j);
+                    break;
+                }
+            }
+            if (bta_dm_cb.pm_timer[i].active == 0)
+                bta_dm_cb.pm_timer[i].in_use = FALSE;
+            if (j < BTA_DM_PM_MODE_TIMER_MAX)
+                break;
+        }
+    }
+
+    /* no more timers */
+    if (i==BTA_DM_NUM_PM_TIMER)
+        return;
+
+    tBTA_DM_PM_TIMER *p_buf = (tBTA_DM_PM_TIMER *) GKI_getbuf(sizeof(tBTA_DM_PM_TIMER));
+    if (p_buf != NULL)
+    {
+        p_buf->hdr.event = BTA_DM_PM_TIMER_EVT;
+        p_buf->pm_request = bta_dm_cb.pm_timer[i].pm_action[j];
+        bdcpy(p_buf->bd_addr, bta_dm_cb.pm_timer[i].peer_bdaddr);
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_btm_status
+**
+** Description      Process pm status event from btm
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_pm_btm_status(tBTA_DM_MSG *p_data)
+{
+    APPL_TRACE_DEBUG("%s status: %d", __func__, p_data->pm_status.status);
+
+    tBTA_DM_PEER_DEVICE *p_dev = bta_dm_find_peer_device(p_data->pm_status.bd_addr);
+    if (NULL == p_dev)
+        return;
+
+    tBTA_DM_DEV_INFO info = p_dev->info;
+    /* check new mode */
+    switch (p_data->pm_status.status)
+    {
+        case BTM_PM_STS_ACTIVE:
+            /* if our sniff or park attempt failed
+            we should not try it again*/
+            if (p_data->pm_status.hci_status != 0)
+            {
+                APPL_TRACE_ERROR("%s hci_status=%d", __func__, p_data->pm_status.hci_status);
+                p_dev->info &= ~(BTA_DM_DI_INT_SNIFF|BTA_DM_DI_ACP_SNIFF|BTA_DM_DI_SET_SNIFF);
+
+                if(p_dev->pm_mode_attempted &(BTA_DM_PM_PARK | BTA_DM_PM_SNIFF))
+                {
+                    p_dev->pm_mode_failed
+                        |= ((BTA_DM_PM_PARK | BTA_DM_PM_SNIFF) & p_dev->pm_mode_attempted);
+                    bta_dm_pm_stop_timer_by_mode(p_data->pm_status.bd_addr, p_dev->pm_mode_attempted);
+                    bta_dm_pm_set_mode(p_data->pm_status.bd_addr, BTA_DM_PM_NO_ACTION, BTA_DM_PM_RESTART);
+                }
+            }
+            else
+            {
+#if (BTM_SSR_INCLUDED == TRUE)
+                if(p_dev->prev_low)
+                {
+                    /* need to send the SSR paramaters to controller again */
+                    bta_dm_pm_ssr(p_dev->peer_bdaddr);
+                }
+                p_dev->prev_low = BTM_PM_STS_ACTIVE;
+#endif
+                /* link to active mode, need to restart the timer for next low power mode if needed */
+                bta_dm_pm_stop_timer(p_data->pm_status.bd_addr);
+                bta_dm_pm_set_mode(p_data->pm_status.bd_addr, BTA_DM_PM_NO_ACTION, BTA_DM_PM_RESTART);
+            }
+            break;
+
+#if (BTM_SSR_INCLUDED == TRUE)
+        case BTM_PM_STS_PARK:
+        case BTM_PM_STS_HOLD:
+            /* save the previous low power mode - for SSR.
+             * SSR parameters are sent to controller on "conn open".
+             * the numbers stay good until park/hold/detach */
+            if(p_dev->info & BTA_DM_DI_USE_SSR)
+                p_dev->prev_low = p_data->pm_status.status;
+            break;
+
+        case BTM_PM_STS_SSR:
+            if(p_data->pm_status.value)
+                p_dev->info |= BTA_DM_DI_USE_SSR;
+            else
+                p_dev->info &= ~BTA_DM_DI_USE_SSR;
+            break;
+#endif
+        case BTM_PM_STS_SNIFF:
+            if (p_data->pm_status.hci_status == 0)
+            {
+                /* Stop PM timer now if already active for
+                 * particular device since link is already
+                 * put in sniff mode by remote device, and
+                 * PM timer sole purpose is to put the link
+                 * in sniff mode from host side.
+                 */
+                bta_dm_pm_stop_timer(p_data->pm_status.bd_addr);
+            }
+            else
+            {
+                p_dev->info &= ~(BTA_DM_DI_SET_SNIFF | BTA_DM_DI_INT_SNIFF | BTA_DM_DI_ACP_SNIFF);
+                if (info & BTA_DM_DI_SET_SNIFF)
+                    p_dev->info |= BTA_DM_DI_INT_SNIFF;
+                else
+                    p_dev->info |= BTA_DM_DI_ACP_SNIFF;
+            }
+            break;
+
+        case BTM_PM_STS_ERROR:
+            p_dev->info &= ~BTA_DM_DI_SET_SNIFF;
+            break;
+
+        default:
+            break;
+    }
+
+
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_timer
+**
+** Description      Process pm timer event from btm
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_pm_timer(tBTA_DM_MSG *p_data)
+{
+    APPL_TRACE_EVENT("%s", __func__);
+    bta_dm_pm_set_mode(p_data->pm_timer.bd_addr, p_data->pm_timer.pm_request, BTA_DM_PM_EXECUTE);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_find_peer_device
+**
+** Description      Given an address, find the associated control block.
+**
+** Returns          tBTA_DM_PEER_DEVICE
+**
+*******************************************************************************/
+tBTA_DM_PEER_DEVICE * bta_dm_find_peer_device(BD_ADDR peer_addr)
+{
+    tBTA_DM_PEER_DEVICE *p_dev = NULL;
+
+    for (int i=0; i<bta_dm_cb.device_list.count; i++)
+    {
+        if(!bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, peer_addr))
+        {
+            p_dev = &bta_dm_cb.device_list.peer_device[i];
+            break;
+        }
+
+    }
+    return p_dev;
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_is_sco_active
+**
+** Description      Loop through connected services for HFP+State=SCO
+**
+** Returns          BOOLEAN. TRUE if SCO active, else FALSE
+**
+*******************************************************************************/
+static BOOLEAN bta_dm_pm_is_sco_active ()
+{
+    int j;
+    BOOLEAN bScoActive = FALSE;
+
+    for(j=0; j<bta_dm_conn_srvcs.count ; j++)
+    {
+        /* check if an entry already present */
+        if ( (bta_dm_conn_srvcs.conn_srvc[j].id == BTA_ID_AG )  && (bta_dm_conn_srvcs.conn_srvc[j].state == BTA_SYS_SCO_OPEN) )
+        {
+            bScoActive = TRUE;
+            break;
+        }
+    }
+
+    APPL_TRACE_DEBUG("bta_dm_is_sco_active: SCO active: %d", bScoActive);
+    return bScoActive;
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_hid_check
+**
+** Description      Disables/Enables sniff in link policy based on SCO Up/Down
+**
+** Returns          None
+**
+*******************************************************************************/
+
+static void bta_dm_pm_hid_check(BOOLEAN bScoActive)
+{
+    int j;
+
+    /* if HID is active, disable the link policy */
+    for(j=0; j<bta_dm_conn_srvcs.count ; j++)
+    {
+        /* check if an entry already present */
+        if(bta_dm_conn_srvcs.conn_srvc[j].id == BTA_ID_HH )
+        {
+            APPL_TRACE_DEBUG ("SCO status change(Active: %d), modify HID link policy. state: %d",
+                bScoActive, bta_dm_conn_srvcs.conn_srvc[j].state);
+            bta_dm_pm_set_sniff_policy( bta_dm_find_peer_device(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr), bScoActive);
+
+            /* if we had disabled link policy, seems like the hid device stop retrying SNIFF after a few tries. force sniff if needed */
+            if (!bScoActive)
+                bta_dm_pm_set_mode(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr, BTA_DM_PM_NO_ACTION,
+                                   BTA_DM_PM_RESTART);
+        }
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_set_sniff_policy
+**
+** Description      Disables/Enables sniff in link policy for the give device
+**
+** Returns          None
+**
+*******************************************************************************/
+static void bta_dm_pm_set_sniff_policy(tBTA_DM_PEER_DEVICE *p_dev, BOOLEAN bDisable)
+{
+    UINT16 policy_setting;
+
+    if (!p_dev)
+        return;
+
+    if (bDisable)
+    {
+        policy_setting = bta_dm_cb.cur_policy &
+            (HCI_ENABLE_MASTER_SLAVE_SWITCH |
+             HCI_ENABLE_HOLD_MODE  |
+             HCI_ENABLE_PARK_MODE);
+
+    }
+    else
+    {
+        /*  allow sniff after sco is closed */
+         policy_setting= bta_dm_cb.cur_policy;
+    }
+
+    /* if disabling SNIFF, make sure link is Active */
+    if (bDisable)
+        bta_dm_pm_active(p_dev->peer_bdaddr);
+
+    /* update device record and set link policy */
+    p_dev->link_policy = policy_setting;
+    BTM_SetLinkPolicy(p_dev->peer_bdaddr, &policy_setting);
+
+}
+
+#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+/*******************************************************************************
+**
+** Function         bta_dm_pm_obtain_controller_state
+**
+** Description      This function obtains the consolidated controller power state
+**
+** Parameters:
+**
+*******************************************************************************/
+tBTA_DM_CONTRL_STATE bta_dm_pm_obtain_controller_state(void)
+{
+    /*   Did not use counts as it is not sure, how accurate the count values are in
+     **  bta_dm_cb.device_list.count > 0 || bta_dm_cb.device_list.le_count > 0 */
+
+    tBTA_DM_CONTRL_STATE cur_state = BTA_DM_CONTRL_UNKNOWN;
+    cur_state = BTM_PM_ReadControllerState();
+
+    APPL_TRACE_DEBUG("bta_dm_pm_obtain_controller_state: %d", cur_state);
+    return cur_state;
+}
+#endif

+ 695 - 0
components/bt/bluedroid/bta/dm/bta_dm_sco.c

@@ -0,0 +1,695 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This file contains the down sampling utility to convert PCM samples in
+ *  16k/32k/48k/44.1k/22050/11025 sampling rate into 8K/16bits samples
+ *  required for SCO channel format. One API function isprovided and only
+ *  possible to be used when transmitting SCO data is sent via HCI
+ *  interface.
+ *
+ ******************************************************************************/
+#include <string.h>
+#include "bta_api.h"
+#include "bta_sys.h"
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE)
+
+#ifndef BTA_DM_SCO_DEBUG
+#define BTA_DM_SCO_DEBUG    FALSE
+#endif
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+#define BTA_DM_PCM_OVERLAP_SIZE			     48
+
+#define BTA_DM_PCM_SMPL_RATE_44100     44100
+#define BTA_DM_PCM_SMPL_RATE_22050     22050
+#define BTA_DM_PCM_SMPL_RATE_11025     11025
+
+/*****************************************************************************
+**  Data types for PCM Resampling utility
+*****************************************************************************/
+
+typedef INT32   (*PCONVERT_TO_BT_FILTERED)  (UINT8 *pSrc, void *pDst, UINT32 dwSrcSamples,
+                             UINT32 dwSrcSps,INT32 *pLastCurPos, UINT8 *pOverlapArea);
+typedef INT32   (*PCONVERT_TO_BT_NOFILTER)  (void *pSrc, void *pDst, UINT32 dwSrcSamples,
+                                             UINT32 dwSrcSps);
+typedef struct
+{
+    UINT8               overlap_area[BTA_DM_PCM_OVERLAP_SIZE * 4];
+    UINT32              cur_pos;    /* current position */
+    UINT32              src_sps;    /* samples per second (source audio data) */
+    PCONVERT_TO_BT_FILTERED     filter;    /* the action function to do the
+                                    conversion 44100, 22050, 11025*/
+    PCONVERT_TO_BT_NOFILTER     nofilter;    /* the action function to do
+                                        the conversion 48000, 32000, 16000*/
+    UINT32              bits;       /* number of bits per pcm sample */
+    UINT32              n_channels; /* number of channels (i.e. mono(1), stereo(2)...) */
+    UINT32              sample_size;
+    UINT32              can_be_filtered;
+    UINT32	            divisor;
+} tBTA_DM_PCM_RESAMPLE_CB;
+
+tBTA_DM_PCM_RESAMPLE_CB bta_dm_pcm_cb;
+
+/*****************************************************************************
+**  Macro Definition
+*****************************************************************************/
+
+
+#define CHECK_SATURATION16(x)                                           \
+            if (x > 32767)                                              \
+                x = 32767;                                              \
+            else if (x < -32768)                                        \
+                x = -32768;
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+#define CONVERT_44100_TO_BLUETOOTH(pStart, pEnd)                            \
+    {                                                                       \
+        INT32         out1, out2, out3, out4, out5;                         \
+        SRC_TYPE    *pS = (SRC_TYPE *)pStart;                               \
+        SRC_TYPE    *pSEnd = (SRC_TYPE *)pEnd;                              \
+                                                                            \
+        while (pS < pSEnd)                                                  \
+        {                                                                   \
+            CurrentPos -= 8000;                                             \
+                                                                            \
+            if (CurrentPos >= 0)                                            \
+            {                                                               \
+                pS += SRC_CHANNELS;                                         \
+                continue;                                                   \
+            }                                                               \
+            CurrentPos += dwSrcSps;                                         \
+                                                                            \
+            out1 = (SRC_SAMPLE(0) * 1587)                                   \
+                 + ((SRC_SAMPLE(1) + SRC_SAMPLE(-1)) * 1522)                \
+                 + ((SRC_SAMPLE(2) + SRC_SAMPLE(-2)) * 1337)                \
+                 + ((SRC_SAMPLE(3) + SRC_SAMPLE(-3)) * 1058);               \
+                                                                            \
+            out1 = out1 / 30000;                                            \
+                                                                            \
+            out2 = ((SRC_SAMPLE(4) + SRC_SAMPLE(-4)) * 725)                 \
+                 + ((SRC_SAMPLE(5) + SRC_SAMPLE(-5)) * 384)                 \
+                 + ((SRC_SAMPLE(6) + SRC_SAMPLE(-6)) * 79);                 \
+                                                                            \
+            out2 = out2 / 30000;                                            \
+                                                                            \
+            out3 = ((SRC_SAMPLE(7) + SRC_SAMPLE(-7)) * 156)                 \
+                 + ((SRC_SAMPLE(8) + SRC_SAMPLE(-8)) * 298)                 \
+                 + ((SRC_SAMPLE(9) + SRC_SAMPLE(-9)) * 345);                \
+                                                                            \
+            out3 = out3 / 30000;                                            \
+                                                                            \
+            out4 = ((SRC_SAMPLE(10) + SRC_SAMPLE(-10)) * 306)               \
+                 + ((SRC_SAMPLE(11) + SRC_SAMPLE(-11)) * 207)               \
+                 + ((SRC_SAMPLE(12) + SRC_SAMPLE(-12)) * 78);               \
+                                                                            \
+            out4 = out4 / 30000;                                            \
+                                                                            \
+            out5 = out1 + out2 - out3 - out4;                               \
+                                                                            \
+            CHECK_SATURATION16(out5);                                       \
+            *psBtOut++ = (INT16)out5;                                       \
+                                                                            \
+            pS += SRC_CHANNELS;                                             \
+        }                                                                   \
+    }
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+#define CONVERT_22050_TO_BLUETOOTH(pStart, pEnd)                            \
+    {                                                                       \
+        INT32         out1, out2, out3, out4, out5;                         \
+        SRC_TYPE    *pS = (SRC_TYPE *)pStart;                               \
+        SRC_TYPE    *pSEnd = (SRC_TYPE *)pEnd;                              \
+                                                                            \
+        while (pS < pSEnd)                                                  \
+        {                                                                   \
+            CurrentPos -= 8000;                                             \
+                                                                            \
+            if (CurrentPos >= 0)                                            \
+            {                                                               \
+                pS += SRC_CHANNELS;                                         \
+                continue;                                                   \
+            }                                                               \
+            CurrentPos += dwSrcSps;                                         \
+                                                                            \
+            out1 = (SRC_SAMPLE(0) * 2993)                                   \
+                 + ((SRC_SAMPLE(1) + SRC_SAMPLE(-1)) * 2568)                \
+                 + ((SRC_SAMPLE(2) + SRC_SAMPLE(-2)) * 1509)                \
+                 + ((SRC_SAMPLE(3) + SRC_SAMPLE(-3)) * 331);                \
+                                                                            \
+            out1 = out1 / 30000;                                            \
+                                                                            \
+            out2 = ((SRC_SAMPLE(4) + SRC_SAMPLE(-4)) * 454)                 \
+                 + ((SRC_SAMPLE(5) + SRC_SAMPLE(-5)) * 620)                 \
+                 + ((SRC_SAMPLE(6) + SRC_SAMPLE(-6)) * 305);                \
+                                                                            \
+            out2 = out2 / 30000;                                            \
+                                                                            \
+            out3 = ((SRC_SAMPLE(7) + SRC_SAMPLE(-7)) * 127)                 \
+                 + ((SRC_SAMPLE(8) + SRC_SAMPLE(-8)) * 350)                 \
+                 + ((SRC_SAMPLE(9) + SRC_SAMPLE(-9)) * 265)                 \
+                 + ((SRC_SAMPLE(10) + SRC_SAMPLE(-10)) * 6);                \
+                                                                            \
+            out3 = out3 / 30000;                                            \
+                                                                            \
+            out4 = ((SRC_SAMPLE(11) + SRC_SAMPLE(-11)) * 201);              \
+                                                                            \
+            out4 = out4 / 30000;                                            \
+                                                                            \
+            out5 = out1 - out2 + out3 - out4;                               \
+                                                                            \
+            CHECK_SATURATION16(out5);                                       \
+            *psBtOut++ = (INT16)out5;                                       \
+                                                                            \
+            pS += SRC_CHANNELS;                                             \
+        }                                                                   \
+    }
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+#define CONVERT_11025_TO_BLUETOOTH(pStart, pEnd)                            \
+    {                                                                       \
+        INT32         out1;                                                   \
+        SRC_TYPE    *pS = (SRC_TYPE *)pStart;                               \
+        SRC_TYPE    *pSEnd = (SRC_TYPE *)pEnd;                              \
+                                                                            \
+        while (pS < pSEnd)                                                  \
+        {                                                                   \
+            CurrentPos -= 8000;                                             \
+                                                                            \
+            if (CurrentPos >= 0)                                            \
+            {                                                               \
+                pS += SRC_CHANNELS;                                         \
+                continue;                                                   \
+            }                                                               \
+            CurrentPos += dwSrcSps;                                         \
+                                                                            \
+            out1 = (SRC_SAMPLE(0) * 6349)                                   \
+                 + ((SRC_SAMPLE(1) + SRC_SAMPLE(-1)) * 2874)                \
+                 - ((SRC_SAMPLE(2) + SRC_SAMPLE(-2)) * 1148)                \
+                 - ((SRC_SAMPLE(3) + SRC_SAMPLE(-3)) * 287)                 \
+                 + ((SRC_SAMPLE(4) + SRC_SAMPLE(-4)) * 675)                 \
+                 - ((SRC_SAMPLE(5) + SRC_SAMPLE(-5)) * 258)                 \
+                 - ((SRC_SAMPLE(6) + SRC_SAMPLE(-6)) * 206)                 \
+                 + ((SRC_SAMPLE(7) + SRC_SAMPLE(-7)) * 266);                \
+                                                                            \
+            out1 = out1 / 30000;                                            \
+                                                                            \
+            CHECK_SATURATION16(out1);                                       \
+            *psBtOut++ = (INT16)out1;                                       \
+                                                                            \
+            pS += SRC_CHANNELS;                                             \
+        }                                                                   \
+    }
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+#undef  SRC_CHANNELS
+#undef  SRC_SAMPLE
+#undef  SRC_TYPE
+
+#define SRC_TYPE        UINT8
+#define SRC_CHANNELS    1
+#define SRC_SAMPLE(x)   ((pS[x]  - 0x80) << 8)
+
+/*****************************************************************************
+**  Local Function
+*****************************************************************************/
+INT32 Convert_8M_ToBT_Filtered (UINT8 *pSrc, void *pDst, UINT32 dwSrcSamples,
+                    UINT32 dwSrcSps, INT32 *pLastCurPos, UINT8 *pOverlapArea)
+{
+    INT32             CurrentPos = *pLastCurPos;
+    SRC_TYPE        *pIn, *pInEnd;
+    SRC_TYPE        *pOv, *pOvEnd;
+    INT16           *psBtOut = (INT16 *)pDst;
+#if BTA_DM_SCO_DEBUG
+    APPL_TRACE_DEBUG("Convert_8M_ToBT_Filtered,  CurrentPos %d\n", CurrentPos);
+#endif
+    memcpy (pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 2), pSrc, BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+    pOv    = (SRC_TYPE *)(pOverlapArea + BTA_DM_PCM_OVERLAP_SIZE);
+	pOvEnd = (SRC_TYPE *)(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 3));
+
+    pIn     = (SRC_TYPE *)(pSrc + BTA_DM_PCM_OVERLAP_SIZE);
+	pInEnd  = (SRC_TYPE *)(pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - \
+        BTA_DM_PCM_OVERLAP_SIZE);
+
+    if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_44100)
+    {
+        CONVERT_44100_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_44100_TO_BLUETOOTH(pIn, pInEnd);
+    }
+    else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_22050)
+    {
+        CONVERT_22050_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_22050_TO_BLUETOOTH(pIn, pInEnd);
+    }
+    else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_11025)
+    {
+        CONVERT_11025_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_11025_TO_BLUETOOTH(pIn, pInEnd);
+    }
+
+    memcpy (pOverlapArea, pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - \
+        (BTA_DM_PCM_OVERLAP_SIZE * 2), BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+    *pLastCurPos = CurrentPos;
+
+    return (psBtOut - (INT16 *)pDst);
+}
+
+INT32 Convert_8M_ToBT_NoFilter (void *pSrc, void *pDst, UINT32 dwSrcSamples, UINT32 dwSrcSps)
+{
+    INT32             CurrentPos;
+    UINT8            *pbSrc = (UINT8 *)pSrc;
+    INT16           *psDst = (INT16 *)pDst;
+    INT16           sWorker;
+
+    //      start at dwSpsSrc / 2, decrement by 8000
+    //
+    CurrentPos = (dwSrcSps >> 1);
+
+    while (dwSrcSamples--)
+    {
+        CurrentPos -= 8000;
+
+        if (CurrentPos >= 0)
+            pbSrc++;
+        else
+        {
+            sWorker = *pbSrc++;
+            sWorker -= 0x80;
+            sWorker <<= 8;
+
+            *psDst++ = sWorker;
+
+            CurrentPos += dwSrcSps;
+        }
+    }
+
+    return (psDst - (INT16 *)pDst);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+#undef  SRC_CHANNELS
+#undef  SRC_SAMPLE
+#undef  SRC_TYPE
+
+#define SRC_TYPE        INT16
+#define SRC_CHANNELS    1
+#define SRC_SAMPLE(x)   pS[x]
+
+INT32 Convert_16M_ToBT_Filtered (UINT8 *pSrc, void *pDst, UINT32 dwSrcSamples,
+                                 UINT32 dwSrcSps, INT32 *pLastCurPos, UINT8 *pOverlapArea)
+{
+    INT32             CurrentPos = *pLastCurPos;
+    SRC_TYPE        *pIn, *pInEnd;
+    SRC_TYPE        *pOv, *pOvEnd;
+    INT16           *psBtOut = (INT16 *)pDst;
+
+    memcpy (pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 2), pSrc, BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+    pOv    = (SRC_TYPE *)(pOverlapArea + BTA_DM_PCM_OVERLAP_SIZE);
+	pOvEnd = (SRC_TYPE *)(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 3));
+
+    pIn     = (SRC_TYPE *)(pSrc + BTA_DM_PCM_OVERLAP_SIZE);
+	pInEnd  = (SRC_TYPE *)(pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - BTA_DM_PCM_OVERLAP_SIZE);
+
+    if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_44100)
+    {
+        CONVERT_44100_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_44100_TO_BLUETOOTH(pIn, pInEnd);
+    }
+    else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_22050)
+    {
+        CONVERT_22050_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_22050_TO_BLUETOOTH(pIn, pInEnd);
+    }
+    else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_11025)
+    {
+        CONVERT_11025_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_11025_TO_BLUETOOTH(pIn, pInEnd);
+    }
+
+    memcpy (pOverlapArea, pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - \
+        (BTA_DM_PCM_OVERLAP_SIZE * 2), BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+    *pLastCurPos = CurrentPos;
+
+    return (psBtOut - (INT16 *)pDst);
+}
+
+INT32 Convert_16M_ToBT_NoFilter (void *pSrc, void *pDst, UINT32 dwSrcSamples, UINT32 dwSrcSps)
+{
+    INT32             CurrentPos;
+    INT16           *psSrc = (INT16 *)pSrc;
+    INT16           *psDst = (INT16 *)pDst;
+
+    //      start at dwSpsSrc / 2, decrement by 8000
+    //
+    CurrentPos = (dwSrcSps >> 1);
+
+    while (dwSrcSamples--)
+    {
+        CurrentPos -= 8000;
+
+        if (CurrentPos >= 0)
+            psSrc++;
+        else
+        {
+            *psDst++ = *psSrc++;
+
+            CurrentPos += dwSrcSps;
+        }
+    }
+
+    return (psDst - (INT16 *)pDst);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+#undef  SRC_CHANNELS
+#undef  SRC_SAMPLE
+#undef  SRC_TYPE
+
+#define SRC_TYPE        UINT8
+#define SRC_CHANNELS    2
+#define SRC_SAMPLE(x) ((((pS[x * 2]  - 0x80) << 8) + ((pS[(x * 2) + 1]  - 0x80) << 8)) >> 1)
+
+INT32 Convert_8S_ToBT_Filtered (UINT8 *pSrc, void *pDst, UINT32 dwSrcSamples,
+                                UINT32 dwSrcSps, INT32 *pLastCurPos, UINT8 *pOverlapArea)
+{
+    INT32             CurrentPos = *pLastCurPos;
+    SRC_TYPE        *pIn, *pInEnd;
+    SRC_TYPE        *pOv, *pOvEnd;
+    INT16           *psBtOut = (INT16 *)pDst;
+
+#if BTA_DM_SCO_DEBUG
+    APPL_TRACE_DEBUG("Convert_8S_ToBT_Filtered CurrentPos %d, SRC_TYPE %d, SRC_CHANNELS %d, \
+        dwSrcSamples %d,  dwSrcSps %d",  	CurrentPos, sizeof (SRC_TYPE), SRC_CHANNELS, \
+        dwSrcSamples, dwSrcSps);
+#endif
+    memcpy (pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 2), pSrc, BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+    pOv    = (SRC_TYPE *)(pOverlapArea + BTA_DM_PCM_OVERLAP_SIZE);
+	pOvEnd = (SRC_TYPE *)(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 3));
+
+    pIn     = (SRC_TYPE *)(pSrc + BTA_DM_PCM_OVERLAP_SIZE);
+	pInEnd  = (SRC_TYPE *)(pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - BTA_DM_PCM_OVERLAP_SIZE);
+
+    if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_44100)
+    {
+        CONVERT_44100_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_44100_TO_BLUETOOTH(pIn, pInEnd);
+    }
+    else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_22050)
+    {
+        CONVERT_22050_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_22050_TO_BLUETOOTH(pIn, pInEnd);
+    }
+    else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_11025)
+    {
+        CONVERT_11025_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_11025_TO_BLUETOOTH(pIn, pInEnd);
+    }
+
+    memcpy (pOverlapArea, pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - \
+        (BTA_DM_PCM_OVERLAP_SIZE * 2), BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+    *pLastCurPos = CurrentPos;
+
+    return (psBtOut - (INT16 *)pDst);
+}
+
+INT32 Convert_8S_ToBT_NoFilter (void *pSrc, void *pDst, UINT32 dwSrcSamples, UINT32 dwSrcSps)
+{
+    INT32             CurrentPos;
+    UINT8            *pbSrc = (UINT8 *)pSrc;
+    INT16           *psDst = (INT16 *)pDst;
+    INT16           sWorker, sWorker2;
+
+    //      start at dwSpsSrc / 2, decrement by 8000
+    //
+    CurrentPos = (dwSrcSps >> 1);
+
+    while (dwSrcSamples--)
+    {
+        CurrentPos -= 8000;
+
+        if (CurrentPos >= 0)
+            pbSrc += 2;
+        else
+        {
+            sWorker = *(unsigned char *)pbSrc;
+            sWorker -= 0x80;
+            sWorker <<= 8;
+            pbSrc++;
+
+            sWorker2 = *(unsigned char *)pbSrc;
+            sWorker2 -= 0x80;
+            sWorker2 <<= 8;
+            pbSrc++;
+
+            sWorker += sWorker2;
+            sWorker >>= 1;
+
+            *psDst++ = sWorker;
+
+            CurrentPos += dwSrcSps;
+        }
+    }
+
+    return (psDst - (INT16 *)pDst);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+#undef  SRC_CHANNELS
+#undef  SRC_SAMPLE
+#undef  SRC_TYPE
+
+#define SRC_TYPE        INT16
+#define SRC_CHANNELS    2
+#define SRC_SAMPLE(x) ((pS[x * 2] + pS[(x * 2) + 1]) >> 1)
+
+INT32 Convert_16S_ToBT_Filtered (UINT8 *pSrc, void *pDst, UINT32 dwSrcSamples,
+                                 UINT32 dwSrcSps, INT32 *pLastCurPos, UINT8 *pOverlapArea)
+{
+    INT32             CurrentPos = *pLastCurPos;
+    SRC_TYPE        *pIn, *pInEnd;
+    SRC_TYPE        *pOv, *pOvEnd;
+    INT16           *psBtOut = (INT16 *)pDst;
+
+    memcpy (pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 2), pSrc, BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+    pOv    = (SRC_TYPE *)(pOverlapArea + BTA_DM_PCM_OVERLAP_SIZE);
+	pOvEnd = (SRC_TYPE *)(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 3));
+
+    pIn     = (SRC_TYPE *)(pSrc + BTA_DM_PCM_OVERLAP_SIZE);
+	pInEnd  = (SRC_TYPE *)(pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - BTA_DM_PCM_OVERLAP_SIZE);
+
+    if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_44100)
+    {
+        CONVERT_44100_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_44100_TO_BLUETOOTH(pIn, pInEnd);
+    }
+    else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_22050)
+    {
+        CONVERT_22050_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_22050_TO_BLUETOOTH(pIn, pInEnd);
+    }
+    else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_11025)
+    {
+        CONVERT_11025_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_11025_TO_BLUETOOTH(pIn, pInEnd);
+    }
+
+    memcpy (pOverlapArea, pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - \
+        (BTA_DM_PCM_OVERLAP_SIZE * 2), BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+    *pLastCurPos = CurrentPos;
+
+    return (psBtOut - (INT16 *)pDst);
+}
+
+INT32 Convert_16S_ToBT_NoFilter (void *pSrc, void *pDst, UINT32 dwSrcSamples, UINT32 dwSrcSps)
+{
+    INT32             CurrentPos;
+    INT16           *psSrc = (INT16 *)pSrc;
+    INT16           *psDst = (INT16 *)pDst;
+    INT16           sWorker;
+
+    //      start at dwSpsSrc / 2, decrement by 8000
+    //
+    CurrentPos = (dwSrcSps >> 1);
+
+    while (dwSrcSamples--)
+    {
+        CurrentPos -= 8000;
+
+        if (CurrentPos >= 0)
+            psSrc += 2;
+        else
+        {
+            /* CR 82894, to avoid overflow, divide before add */
+            sWorker  = ((*psSrc) >> 1 );
+            psSrc++;
+            sWorker += ((*psSrc) >> 1 );
+            psSrc++;
+
+            *psDst++ = sWorker;
+
+            CurrentPos += dwSrcSps;
+        }
+    }
+
+    return (psDst - (INT16 *)pDst);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmPcmInitSamples
+**
+** Description      initialize the down sample converter.
+**
+**                  src_sps: original samples per second (source audio data)
+**                            (ex. 44100, 48000)
+**                  bits: number of bits per pcm sample (16)
+**                  n_channels: number of channels (i.e. mono(1), stereo(2)...)
+**
+** Returns          none
+**
+*******************************************************************************/
+void BTA_DmPcmInitSamples (UINT32 src_sps, UINT32 bits, UINT32 n_channels)
+{
+    tBTA_DM_PCM_RESAMPLE_CB *p_cb = &bta_dm_pcm_cb;
+
+    p_cb->cur_pos       = src_sps / 2;
+    p_cb->src_sps       = src_sps;
+    p_cb->bits          = bits;
+    p_cb->n_channels    = n_channels;
+    p_cb->sample_size   = 2;
+    p_cb->divisor	    = 2;
+
+    memset(p_cb->overlap_area, 0, sizeof(p_cb->overlap_area) );
+
+    if ((src_sps == BTA_DM_PCM_SMPL_RATE_44100) ||
+        (src_sps == BTA_DM_PCM_SMPL_RATE_22050) ||
+        (src_sps == BTA_DM_PCM_SMPL_RATE_11025))
+         p_cb->can_be_filtered = 1;
+    else
+         p_cb->can_be_filtered = 0;
+
+#if BTA_DM_SCO_DEBUG
+    APPL_TRACE_DEBUG("bta_dm_pcm_init_samples: n_channels = %d bits = %d", n_channels, bits);
+#endif
+    if(n_channels == 1)
+    {
+        /* mono */
+        if(bits == 8)
+        {
+            p_cb->filter = (PCONVERT_TO_BT_FILTERED) Convert_8M_ToBT_Filtered;
+            p_cb->nofilter = (PCONVERT_TO_BT_NOFILTER) Convert_8M_ToBT_NoFilter;
+	        p_cb->divisor	 = 1;
+        }
+        else
+        {
+            p_cb->filter = (PCONVERT_TO_BT_FILTERED) Convert_16M_ToBT_Filtered;
+            p_cb->nofilter = (PCONVERT_TO_BT_NOFILTER) Convert_16M_ToBT_NoFilter;
+        }
+    }
+    else
+    {
+        /* stereo */
+        if(bits == 8)
+        {
+            p_cb->filter = (PCONVERT_TO_BT_FILTERED) Convert_8S_ToBT_Filtered;
+            p_cb->nofilter = (PCONVERT_TO_BT_NOFILTER) Convert_8S_ToBT_NoFilter;
+        }
+        else
+        {
+            p_cb->filter = (PCONVERT_TO_BT_FILTERED) Convert_16S_ToBT_Filtered;
+            p_cb->nofilter = (PCONVERT_TO_BT_NOFILTER) Convert_16S_ToBT_NoFilter;
+	        p_cb->divisor	 = 4;
+        }
+    }
+
+#if BTA_DM_SCO_DEBUG
+    APPL_TRACE_DEBUG("bta_pcm_init_dwn_sample: cur_pos %d, src_sps %d", \
+		p_cb->cur_pos, p_cb->src_sps);
+    APPL_TRACE_DEBUG("bta_pcm_init_dwn_sample: bits %d, n_channels %d, sample_size %d, ", \
+		p_cb->bits, p_cb->n_channels, p_cb->sample_size);
+    APPL_TRACE_DEBUG("bta_pcm_init_dwn_sample: can_be_filtered %d, n_channels: %d, \
+        divisor %d", p_cb->can_be_filtered, p_cb->n_channels, p_cb->divisor);
+#endif
+
+}
+
+/**************************************************************************************
+** Function         BTA_DmPcmResample
+**
+** Description      Down sampling utility to convert higher sampling rate into 8K/16bits
+**                  PCM samples.
+**
+** Parameters       p_src: pointer to the buffer where the original sampling PCM
+**                              are stored.
+**                  in_bytes:  Length of the input PCM sample buffer in byte.
+**                  p_dst:      pointer to the buffer which is to be used to store
+**                              the converted PCM samples.
+**
+**
+** Returns          INT32: number of samples converted.
+**
+**************************************************************************************/
+INT32 BTA_DmPcmResample (void *p_src, UINT32 in_bytes, void *p_dst)
+{
+    UINT32 out_sample;
+
+#if BTA_DM_SCO_DEBUG
+    APPL_TRACE_DEBUG("bta_pcm_resample : insamples  %d",  (in_bytes  / bta_dm_pcm_cb.divisor));
+#endif
+    if(bta_dm_pcm_cb.can_be_filtered)
+    {
+        out_sample = (*bta_dm_pcm_cb.filter) (p_src, p_dst, (in_bytes  / bta_dm_pcm_cb.divisor),
+            bta_dm_pcm_cb.src_sps, (INT32 *) &bta_dm_pcm_cb.cur_pos, bta_dm_pcm_cb.overlap_area);
+    }
+    else
+    {
+        out_sample = (*bta_dm_pcm_cb.nofilter) (p_src, p_dst,
+            (in_bytes / bta_dm_pcm_cb.divisor), bta_dm_pcm_cb.src_sps);
+    }
+
+#if BTA_DM_SCO_DEBUG
+    APPL_TRACE_DEBUG("bta_pcm_resample : outsamples  %d",  out_sample);
+#endif
+
+    return (out_sample * bta_dm_pcm_cb.sample_size);
+}
+#endif

+ 2379 - 0
components/bt/bluedroid/bta/gatt/bta_gattc_act.c

@@ -0,0 +1,2379 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This file contains the GATT client action functions for the state
+ *  machine.
+ *
+ ******************************************************************************/
+#define LOG_TAG "bt_bta_gattc"
+
+#include "bt_target.h"
+
+#include "utl.h"
+#include "gki.h"
+#include "bta_sys.h"
+
+#include "bta_gattc_int.h"
+#include "l2c_api.h"
+
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+#include "bta_hh_int.h"
+#endif
+
+// #include "btif/include/btif_debug_conn.h"
+
+#include <string.h>
+
+// #include "osi/include/log.h"
+
+#if BTA_GATT_INCLUDED && BLE_INCLUDED == TRUE
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+static void bta_gattc_conn_cback(tGATT_IF gattc_if, BD_ADDR bda, UINT16 conn_id,
+                                 BOOLEAN connected, tGATT_DISCONN_REASON reason,
+                                 tBT_TRANSPORT transport);
+
+static void  bta_gattc_cmpl_cback(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status,
+                                  tGATT_CL_COMPLETE *p_data);
+static void bta_gattc_cmpl_sendmsg(UINT16 conn_id, tGATTC_OPTYPE op,
+                                   tBTA_GATT_STATUS status,
+                                   tGATT_CL_COMPLETE *p_data);
+
+static void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg);
+static void bta_gattc_enc_cmpl_cback(tGATT_IF gattc_if, BD_ADDR bda);
+static void bta_gattc_cong_cback (UINT16 conn_id, BOOLEAN congested);
+
+static tGATT_CBACK bta_gattc_cl_cback =
+{
+    bta_gattc_conn_cback,
+    bta_gattc_cmpl_cback,
+    bta_gattc_disc_res_cback,
+    bta_gattc_disc_cmpl_cback,
+    NULL,
+    bta_gattc_enc_cmpl_cback,
+    bta_gattc_cong_cback
+};
+
+/* opcode(tGATTC_OPTYPE) order has to be comply with internal event order */
+static UINT16 bta_gattc_opcode_to_int_evt[] =
+{
+    BTA_GATTC_API_READ_EVT,
+    BTA_GATTC_API_WRITE_EVT,
+    BTA_GATTC_API_EXEC_EVT,
+    BTA_GATTC_API_CFG_MTU_EVT
+};
+
+#if (BT_TRACE_VERBOSE == TRUE)
+static const char *bta_gattc_op_code_name[] =
+{
+    "Unknown",
+    "Discovery",
+    "Read",
+    "Write",
+    "Exec",
+    "Config",
+    "Notification",
+    "Indication"
+};
+#endif
+/*****************************************************************************
+**  Action Functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function         bta_gattc_enable
+**
+** Description      Enables GATTC module
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_gattc_enable(tBTA_GATTC_CB *p_cb)
+{
+    APPL_TRACE_DEBUG("bta_gattc_enable");
+
+    if (p_cb->state == BTA_GATTC_STATE_DISABLED)
+    {
+        /* initialize control block */
+        memset(&bta_gattc_cb, 0, sizeof(tBTA_GATTC_CB));
+        p_cb->state = BTA_GATTC_STATE_ENABLED;
+    }
+    else
+    {
+        APPL_TRACE_DEBUG("GATTC is arelady enabled");
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_gattc_disable
+**
+** Description      Disable GATTC module by cleaning up all active connections
+**                  and deregister all application.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_disable(tBTA_GATTC_CB *p_cb)
+{
+    UINT8           i;
+
+    APPL_TRACE_DEBUG("bta_gattc_disable");
+
+    if (p_cb->state != BTA_GATTC_STATE_ENABLED)
+    {
+        APPL_TRACE_ERROR("not enabled or disable in pogress");
+        return;
+    }
+
+    for (i = 0; i <BTA_GATTC_CL_MAX; i ++)
+    {
+        if (p_cb->cl_rcb[i].in_use)
+        {
+            p_cb->state = BTA_GATTC_STATE_DISABLING;
+            /* don't deregister HH GATT IF */
+            /* HH GATT IF will be deregistered by bta_hh_le_deregister when disable HH */
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+            if (!bta_hh_le_is_hh_gatt_if(p_cb->cl_rcb[i].client_if)) {
+#endif
+                bta_gattc_deregister(p_cb, &p_cb->cl_rcb[i]);
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+            }
+#endif
+        }
+    }
+
+    /* no registered apps, indicate disable completed */
+    if (p_cb->state != BTA_GATTC_STATE_DISABLING)
+    {
+        p_cb->state = BTA_GATTC_STATE_DISABLED;
+        memset(p_cb, 0, sizeof(tBTA_GATTC_CB));
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_register
+**
+** Description      Register a GATT client application with BTA.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_register(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATTC               cb_data;
+    UINT8                    i;
+    tBT_UUID                 *p_app_uuid = &p_data->api_reg.app_uuid;
+    tBTA_GATTC_INT_START_IF  *p_buf;
+    tBTA_GATT_STATUS         status = BTA_GATT_NO_RESOURCES;
+
+
+    APPL_TRACE_DEBUG("bta_gattc_register state %d",p_cb->state);
+    memset(&cb_data, 0, sizeof(cb_data));
+    cb_data.reg_oper.status = BTA_GATT_NO_RESOURCES;
+
+     /* check if  GATTC module is already enabled . Else enable */
+     if (p_cb->state == BTA_GATTC_STATE_DISABLED)
+     {
+         bta_gattc_enable (p_cb);
+     }
+    /* todo need to check duplicate uuid */
+    for (i = 0; i < BTA_GATTC_CL_MAX; i ++)
+    {
+        if (!p_cb->cl_rcb[i].in_use)
+        {
+            if ((p_app_uuid == NULL) || (p_cb->cl_rcb[i].client_if = GATT_Register(p_app_uuid, &bta_gattc_cl_cback)) == 0)
+            {
+                APPL_TRACE_ERROR("Register with GATT stack failed.");
+                status = BTA_GATT_ERROR;
+            }
+            else
+            {
+                p_cb->cl_rcb[i].in_use = TRUE;
+                p_cb->cl_rcb[i].p_cback = p_data->api_reg.p_cback;
+                memcpy(&p_cb->cl_rcb[i].app_uuid, p_app_uuid, sizeof(tBT_UUID));
+
+                /* BTA use the same client interface as BTE GATT statck */
+                cb_data.reg_oper.client_if = p_cb->cl_rcb[i].client_if;
+
+                if ((p_buf = (tBTA_GATTC_INT_START_IF *) GKI_getbuf(sizeof(tBTA_GATTC_INT_START_IF))) != NULL)
+                {
+                    p_buf->hdr.event    = BTA_GATTC_INT_START_IF_EVT;
+                    p_buf->client_if    = p_cb->cl_rcb[i].client_if;
+
+                    bta_sys_sendmsg(p_buf);
+                    status = BTA_GATT_OK;
+                }
+                else
+                {
+                    GATT_Deregister(p_cb->cl_rcb[i].client_if);
+
+                    status = BTA_GATT_NO_RESOURCES;
+                    memset( &p_cb->cl_rcb[i], 0 , sizeof(tBTA_GATTC_RCB));
+                }
+                break;
+            }
+        }
+    }
+
+    /* callback with register event */
+    if (p_data->api_reg.p_cback)
+    {
+        if (p_app_uuid != NULL)
+            memcpy(&(cb_data.reg_oper.app_uuid),p_app_uuid,sizeof(tBT_UUID));
+
+        cb_data.reg_oper.status = status;
+        (*p_data->api_reg.p_cback)(BTA_GATTC_REG_EVT,  (tBTA_GATTC *)&cb_data);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_start_if
+**
+** Description      start an application interface.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gattc_start_if(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg)
+{
+    UNUSED(p_cb);
+
+    if (bta_gattc_cl_get_regcb(p_msg->int_start_if.client_if) !=NULL )
+    {
+        GATT_StartIf(p_msg->int_start_if.client_if);
+    }
+    else
+    {
+        APPL_TRACE_ERROR("Unable to start app.: Unknown interface =%d",p_msg->int_start_if.client_if );
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_deregister
+**
+** Description      De-Register a GATT client application with BTA.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_deregister(tBTA_GATTC_CB *p_cb, tBTA_GATTC_RCB  *p_clreg)
+{
+    UINT8               i;
+    BT_HDR              buf;
+
+    if (p_clreg != NULL)
+    {
+        /* remove bg connection associated with this rcb */
+        for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++)
+        {
+            if (p_cb->bg_track[i].in_use)
+            {
+                if (p_cb->bg_track[i].cif_mask & (1 <<(p_clreg->client_if - 1)))
+                {
+                    bta_gattc_mark_bg_conn(p_clreg->client_if, p_cb->bg_track[i].remote_bda, FALSE, FALSE);
+                    GATT_CancelConnect(p_clreg->client_if, p_cb->bg_track[i].remote_bda, FALSE);
+                }
+                if (p_cb->bg_track[i].cif_adv_mask & (1 <<(p_clreg->client_if - 1)))
+                {
+                    bta_gattc_mark_bg_conn(p_clreg->client_if, p_cb->bg_track[i].remote_bda, FALSE, TRUE);
+                }
+            }
+        }
+
+        if (p_clreg->num_clcb > 0)
+        {
+            /* close all CLCB related to this app */
+            for (i= 0; i < BTA_GATTC_CLCB_MAX; i ++)
+            {
+                if (p_cb->clcb[i].in_use && (p_cb->clcb[i].p_rcb == p_clreg))
+                {
+                    p_clreg->dereg_pending = TRUE;
+
+                    buf.event = BTA_GATTC_API_CLOSE_EVT;
+                    buf.layer_specific = p_cb->clcb[i].bta_conn_id;
+                    bta_gattc_close(&p_cb->clcb[i], (tBTA_GATTC_DATA *)&buf)  ;
+                }
+            }
+        }
+        else
+            bta_gattc_deregister_cmpl(p_clreg);
+    }
+    else
+    {
+        APPL_TRACE_ERROR("bta_gattc_deregister Deregister Failedm unknown client cif");
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_process_api_open
+**
+** Description      process connect API request.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_process_api_open (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg)
+{
+    UINT16 event = ((BT_HDR *)p_msg)->event;
+    tBTA_GATTC_CLCB *p_clcb = NULL;
+    tBTA_GATTC_RCB *p_clreg = bta_gattc_cl_get_regcb(p_msg->api_conn.client_if);
+    UNUSED(p_cb);
+
+    if (p_clreg != NULL)
+    {
+        if (p_msg->api_conn.is_direct)
+        {
+            if ((p_clcb = bta_gattc_find_alloc_clcb(p_msg->api_conn.client_if,
+                                                    p_msg->api_conn.remote_bda,
+                                                    p_msg->api_conn.transport)) != NULL)
+            {
+                bta_gattc_sm_execute(p_clcb, event, p_msg);
+            }
+            else
+            {
+                APPL_TRACE_ERROR("No resources to open a new connection.");
+
+                bta_gattc_send_open_cback(p_clreg,
+                                          BTA_GATT_NO_RESOURCES,
+                                          p_msg->api_conn.remote_bda,
+                                          BTA_GATT_INVALID_CONN_ID,
+                                          p_msg->api_conn.transport, 0);
+            }
+        }
+        else
+        {
+            bta_gattc_init_bk_conn(&p_msg->api_conn, p_clreg);
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR("bta_gattc_process_api_open Failed, unknown client_if: %d",
+                        p_msg->api_conn.client_if);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_process_api_open_cancel
+**
+** Description      process connect API request.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_process_api_open_cancel (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg)
+{
+    UINT16 event = ((BT_HDR *)p_msg)->event;
+    tBTA_GATTC_CLCB *p_clcb = NULL;
+    tBTA_GATTC_RCB *p_clreg;
+    tBTA_GATTC cb_data;
+    UNUSED(p_cb);
+
+    if (p_msg->api_cancel_conn.is_direct)
+    {
+        if ((p_clcb = bta_gattc_find_clcb_by_cif(p_msg->api_cancel_conn.client_if,
+                                                 p_msg->api_cancel_conn.remote_bda,
+                                                 BTA_GATT_TRANSPORT_LE)) != NULL)
+        {
+            bta_gattc_sm_execute(p_clcb, event, p_msg);
+        }
+        else
+        {
+            APPL_TRACE_ERROR("No such connection need to be cancelled");
+
+            p_clreg = bta_gattc_cl_get_regcb(p_msg->api_cancel_conn.client_if);
+
+            if (p_clreg && p_clreg->p_cback)
+            {
+                cb_data.status = BTA_GATT_ERROR;
+                (*p_clreg->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
+            }
+        }
+    }
+    else
+    {
+        bta_gattc_cancel_bk_conn(&p_msg->api_cancel_conn);
+
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_process_enc_cmpl
+**
+** Description      process encryption complete message.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_process_enc_cmpl(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg)
+{
+    tBTA_GATTC_RCB *p_clreg;
+    tBTA_GATTC cb_data;
+    UNUSED(p_cb);
+
+    p_clreg = bta_gattc_cl_get_regcb(p_msg->enc_cmpl.client_if);
+
+    if (p_clreg && p_clreg->p_cback)
+    {
+        memset(&cb_data, 0, sizeof(tBTA_GATTC));
+
+        cb_data.enc_cmpl.client_if = p_msg->enc_cmpl.client_if;
+        bdcpy(cb_data.enc_cmpl.remote_bda, p_msg->enc_cmpl.remote_bda);
+
+        (*p_clreg->p_cback)(BTA_GATTC_ENC_CMPL_CB_EVT, &cb_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_cancel_open_error
+**
+** Description
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_cancel_open_error(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATTC cb_data;
+    UNUSED(p_data);
+
+    cb_data.status=BTA_GATT_ERROR;
+
+    if ( p_clcb && p_clcb->p_rcb && p_clcb->p_rcb->p_cback )
+        (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_open_error
+**
+** Description
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_open_error(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    UNUSED(p_data);
+
+    APPL_TRACE_ERROR("Connection already opened. wrong state");
+
+    bta_gattc_send_open_cback(p_clcb->p_rcb,
+                              BTA_GATT_OK,
+                              p_clcb->bda,
+                              p_clcb->bta_conn_id,
+                              p_clcb->transport,
+                              0);
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_open_fail
+**
+** Description
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_open_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    UNUSED(p_data);
+
+    bta_gattc_send_open_cback(p_clcb->p_rcb,
+                              BTA_GATT_ERROR,
+                              p_clcb->bda,
+                              p_clcb->bta_conn_id,
+                              p_clcb->transport,
+                              0);
+    /* open failure, remove clcb */
+    bta_gattc_clcb_dealloc(p_clcb);
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_open
+**
+** Description      Process API connection function.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATTC_DATA gattc_data;
+
+    /* open/hold a connection */
+    if (!GATT_Connect(p_clcb->p_rcb->client_if, p_data->api_conn.remote_bda,
+                      TRUE, p_data->api_conn.transport))
+    {
+        APPL_TRACE_ERROR("Connection open failure");
+
+        bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_OPEN_FAIL_EVT, p_data);
+    }
+    else
+    {
+        /* a connected remote device */
+        if (GATT_GetConnIdIfConnected(p_clcb->p_rcb->client_if,
+                                      p_data->api_conn.remote_bda,
+                                      &p_clcb->bta_conn_id,
+                                      p_data->api_conn.transport))
+        {
+            gattc_data.int_conn.hdr.layer_specific = p_clcb->bta_conn_id;
+
+            bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, &gattc_data);
+        }
+        /* else wait for the callback event */
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_init_bk_conn
+**
+** Description      Process API Open for a background connection
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_init_bk_conn(tBTA_GATTC_API_OPEN *p_data, tBTA_GATTC_RCB *p_clreg)
+{
+    tBTA_GATT_STATUS         status = BTA_GATT_NO_RESOURCES;
+    UINT16                   conn_id;
+    tBTA_GATTC_CLCB         *p_clcb;
+    tBTA_GATTC_DATA         gattc_data;
+
+    if (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, TRUE, FALSE))
+    {
+        /* always call open to hold a connection */
+        if (!GATT_Connect(p_data->client_if, p_data->remote_bda, FALSE, p_data->transport))
+        {
+            uint8_t *bda = (uint8_t *)p_data->remote_bda;
+            status = BTA_GATT_ERROR;
+            APPL_TRACE_ERROR("%s unable to connect to remote bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
+                __func__, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
+
+        }
+        else
+        {
+            status = BTA_GATT_OK;
+
+            /* if is a connected remote device */
+            if (GATT_GetConnIdIfConnected(p_data->client_if,
+                                          p_data->remote_bda,
+                                          &conn_id,
+                                          p_data->transport))
+            {
+                if ((p_clcb = bta_gattc_find_alloc_clcb(p_data->client_if, p_data->remote_bda,
+                    BTA_GATT_TRANSPORT_LE)) != NULL)
+                {
+                    gattc_data.hdr.layer_specific = p_clcb->bta_conn_id = conn_id;
+
+                    /* open connection */
+                    bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, &gattc_data);
+                    status = BTA_GATT_OK;
+                }
+            }
+        }
+    }
+
+    /* open failure, report OPEN_EVT */
+    if (status != BTA_GATT_OK)
+    {
+        bta_gattc_send_open_cback(p_clreg, status, p_data->remote_bda,
+        BTA_GATT_INVALID_CONN_ID, BTA_GATT_TRANSPORT_LE, 0);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_cancel_bk_conn
+**
+** Description      Process API Cancel Open for a background connection
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_cancel_bk_conn(tBTA_GATTC_API_CANCEL_OPEN *p_data)
+{
+    tBTA_GATTC_RCB      *p_clreg;
+    tBTA_GATTC          cb_data;
+    cb_data.status = BTA_GATT_ERROR;
+
+    /* remove the device from the bg connection mask */
+    if (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, FALSE, FALSE))
+    {
+        if (GATT_CancelConnect(p_data->client_if, p_data->remote_bda, FALSE))
+        {
+            cb_data.status = BTA_GATT_OK;
+        }
+        else
+        {
+            APPL_TRACE_ERROR("bta_gattc_cancel_bk_conn failed");
+        }
+    }
+    p_clreg = bta_gattc_cl_get_regcb(p_data->client_if);
+
+    if (p_clreg && p_clreg->p_cback)
+    {
+        (*p_clreg->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
+    }
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_int_cancel_open_ok
+**
+** Description
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_cancel_open_ok(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATTC          cb_data;
+    UNUSED(p_data);
+
+    if ( p_clcb->p_rcb->p_cback )
+    {
+        cb_data.status = BTA_GATT_OK;
+        (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
+    }
+
+    bta_gattc_clcb_dealloc(p_clcb);
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_cancel_open
+**
+** Description
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_cancel_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATTC          cb_data;
+
+    if (GATT_CancelConnect(p_clcb->p_rcb->client_if, p_data->api_cancel_conn.remote_bda, TRUE))
+    {
+        bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CANCEL_OPEN_OK_EVT, p_data);
+    }
+    else
+    {
+        if ( p_clcb->p_rcb->p_cback )
+        {
+            cb_data.status = BTA_GATT_ERROR;
+            (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_conn
+**
+** Description      receive connection callback from stack
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_conn(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATTC_IF   gatt_if;
+    APPL_TRACE_DEBUG("bta_gattc_conn server cache state=%d",p_clcb->p_srcb->state);
+
+    if (p_data != NULL)
+    {
+        APPL_TRACE_DEBUG("bta_gattc_conn conn_id=%d",p_data->hdr.layer_specific);
+        p_clcb->bta_conn_id  = p_data->int_conn.hdr.layer_specific;
+
+        GATT_GetConnectionInfor(p_data->hdr.layer_specific,
+                                &gatt_if, p_clcb->bda, &p_clcb->transport);
+    }
+
+        p_clcb->p_srcb->connected = TRUE;
+
+        if (p_clcb->p_srcb->mtu == 0)
+            p_clcb->p_srcb->mtu = GATT_DEF_BLE_MTU_SIZE;
+
+        /* start database cache if needed */
+        if (p_clcb->p_srcb->p_srvc_cache == NULL ||
+            p_clcb->p_srcb->state != BTA_GATTC_SERV_IDLE)
+        {
+            if (p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE)
+            {
+                p_clcb->p_srcb->state = BTA_GATTC_SERV_LOAD;
+                bta_gattc_sm_execute(p_clcb, BTA_GATTC_START_CACHE_EVT, NULL);
+            }
+            else /* cache is building */
+                p_clcb->state = BTA_GATTC_DISCOVER_ST;
+        }
+
+        else
+        {
+            /* a pending service handle change indication */
+            if (p_clcb->p_srcb->srvc_hdl_chg)
+            {
+                p_clcb->p_srcb->srvc_hdl_chg = FALSE;
+                /* start discovery */
+                bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);
+            }
+        }
+
+        if (p_clcb->p_rcb)
+        {
+        /* there is no RM for GATT */
+        if (p_clcb->transport == BTA_TRANSPORT_BR_EDR)
+            bta_sys_conn_open(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda);
+
+        bta_gattc_send_open_cback(p_clcb->p_rcb,
+                                  BTA_GATT_OK,
+                                  p_clcb->bda,
+                                  p_clcb->bta_conn_id,
+                                  p_clcb->transport,
+                                  p_clcb->p_srcb->mtu);
+        }
+    }
+/*******************************************************************************
+**
+** Function         bta_gattc_close_fail
+**
+** Description      close a  connection.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_close_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATTC           cb_data;
+
+    if ( p_clcb->p_rcb->p_cback )
+    {
+        memset(&cb_data, 0, sizeof(tBTA_GATTC));
+        cb_data.close.client_if = p_clcb->p_rcb->client_if;
+        cb_data.close.conn_id   = p_data->hdr.layer_specific;
+        bdcpy(cb_data.close.remote_bda, p_clcb->bda);
+        cb_data.close.status    = BTA_GATT_ERROR;
+        cb_data.close.reason    = BTA_GATT_CONN_NONE;
+
+
+        (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CLOSE_EVT, &cb_data);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_api_close
+**
+** Description      close a GATTC connection.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATTC_CBACK    *p_cback = p_clcb->p_rcb->p_cback;
+    tBTA_GATTC_RCB      *p_clreg = p_clcb->p_rcb;
+    tBTA_GATTC           cb_data;
+
+    APPL_TRACE_DEBUG("bta_gattc_close conn_id=%d",p_clcb->bta_conn_id);
+
+    cb_data.close.client_if = p_clcb->p_rcb->client_if;
+    cb_data.close.conn_id   = p_clcb->bta_conn_id;
+    cb_data.close.reason    = p_clcb->reason;
+    cb_data.close.status    = p_clcb->status;
+    bdcpy(cb_data.close.remote_bda, p_clcb->bda);
+
+    if (p_clcb->transport == BTA_TRANSPORT_BR_EDR)
+        bta_sys_conn_close( BTA_ID_GATTC ,BTA_ALL_APP_ID, p_clcb->bda);
+
+    bta_gattc_clcb_dealloc(p_clcb);
+
+    if (p_data->hdr.event == BTA_GATTC_API_CLOSE_EVT)
+    {
+        cb_data.close.status = GATT_Disconnect(p_data->hdr.layer_specific);
+    }
+    else if (p_data->hdr.event == BTA_GATTC_INT_DISCONN_EVT)
+    {
+        cb_data.close.status = p_data->int_conn.reason;
+        cb_data.close.reason = p_data->int_conn.reason;
+    }
+
+    if(p_cback)
+        (* p_cback)(BTA_GATTC_CLOSE_EVT,   (tBTA_GATTC *)&cb_data);
+
+    if (p_clreg->num_clcb == 0 && p_clreg->dereg_pending)
+    {
+        bta_gattc_deregister_cmpl(p_clreg);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_reset_discover_st
+**
+** Description      when a SRCB finished discovery, tell all related clcb.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_reset_discover_st(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_STATUS status)
+{
+    tBTA_GATTC_CB   *p_cb = &bta_gattc_cb;
+    UINT8 i;
+
+    for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++)
+    {
+        if (p_cb->clcb[i].p_srcb == p_srcb)
+        {
+            p_cb->clcb[i].status = status;
+            bta_gattc_sm_execute(&p_cb->clcb[i], BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_disc_close
+**
+** Description      close a GATTC connection while in discovery state.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_disc_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    APPL_TRACE_DEBUG("%s: Discovery cancel conn_id=%d", __func__,
+                     p_clcb->bta_conn_id);
+
+    if (p_clcb->disc_active)
+        bta_gattc_reset_discover_st(p_clcb->p_srcb, BTA_GATT_ERROR);
+    else
+        p_clcb->state = BTA_GATTC_CONN_ST;
+
+    // This function only gets called as the result of a BTA_GATTC_API_CLOSE_EVT
+    // while in the BTA_GATTC_DISCOVER_ST state. Once the state changes, the
+    // connection itself still needs to be closed to resolve the original event.
+    if (p_clcb->state == BTA_GATTC_CONN_ST)
+    {
+        APPL_TRACE_DEBUG("State is back to BTA_GATTC_CONN_ST. "
+                         "Trigger connection close");
+        bta_gattc_close(p_clcb, p_data);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_set_discover_st
+**
+** Description      when a SRCB start discovery, tell all related clcb and set
+**                  the state.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_set_discover_st(tBTA_GATTC_SERV *p_srcb)
+{
+    tBTA_GATTC_CB   *p_cb = &bta_gattc_cb;
+    UINT8   i;
+
+#if BLE_INCLUDED == TRUE
+    L2CA_EnableUpdateBleConnParams(p_srcb->server_bda, FALSE);
+#endif
+    for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++)
+    {
+        if (p_cb->clcb[i].p_srcb == p_srcb)
+        {
+            p_cb->clcb[i].status = BTA_GATT_OK;
+            p_cb->clcb[i].state = BTA_GATTC_DISCOVER_ST;
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_restart_discover
+**
+** Description      process service change in discovery state, mark up the auto
+**                  update flag and set status to be discovery cancel for current
+**                  discovery.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_restart_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    UNUSED(p_data);
+
+    p_clcb->status      = BTA_GATT_CANCEL;
+    p_clcb->auto_update = BTA_GATTC_DISC_WAITING;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_cfg_mtu
+**
+** Description      Configure MTU size on the GATT connection.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_cfg_mtu(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATT_STATUS    status;
+
+    if (bta_gattc_enqueue(p_clcb, p_data))
+    {
+        status = GATTC_ConfigureMTU (p_clcb->bta_conn_id, p_data->api_mtu.mtu);
+
+        /* if failed, return callback here */
+        if (status != GATT_SUCCESS && status != GATT_CMD_STARTED)
+        {
+            /* Dequeue the data, if it was enqueued */
+            if (p_clcb->p_q_cmd == p_data)
+                p_clcb->p_q_cmd = NULL;
+
+            bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_CONFIG, status, NULL);
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_start_discover
+**
+** Description      Start a discovery send to server.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_start_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    UNUSED(p_data);
+
+    APPL_TRACE_DEBUG("bta_gattc_start_discover conn_id=%d p_clcb->p_srcb->state = %d ",
+        p_clcb->bta_conn_id, p_clcb->p_srcb->state);
+
+    if (((p_clcb->p_q_cmd == NULL || p_clcb->auto_update == BTA_GATTC_REQ_WAITING) &&
+        p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE) ||
+        p_clcb->p_srcb->state == BTA_GATTC_SERV_DISC)
+    /* no pending operation, start discovery right away */
+    {
+        p_clcb->auto_update = BTA_GATTC_NO_SCHEDULE;
+
+        if (p_clcb->p_srcb != NULL)
+        {
+            /* clear the service change mask */
+            p_clcb->p_srcb->srvc_hdl_chg = FALSE;
+            p_clcb->p_srcb->update_count = 0;
+            p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC_ACT;
+
+            if (p_clcb->transport == BTA_TRANSPORT_LE)
+                L2CA_EnableUpdateBleConnParams(p_clcb->p_srcb->server_bda, FALSE);
+
+            /* set all srcb related clcb into discovery ST */
+            bta_gattc_set_discover_st(p_clcb->p_srcb);
+
+            if ((p_clcb->status = bta_gattc_init_cache(p_clcb->p_srcb)) == BTA_GATT_OK)
+            {
+                p_clcb->status = bta_gattc_discover_pri_service(p_clcb->bta_conn_id,
+                                                               p_clcb->p_srcb, GATT_DISC_SRVC_ALL);
+            }
+            if (p_clcb->status != BTA_GATT_OK)
+            {
+                APPL_TRACE_ERROR("discovery on server failed");
+                bta_gattc_reset_discover_st(p_clcb->p_srcb, p_clcb->status);
+            }
+            else
+                p_clcb->disc_active = TRUE;
+        }
+        else
+        {
+            APPL_TRACE_ERROR("unknown device, can not start discovery");
+        }
+    }
+    /* pending operation, wait until it finishes */
+    else
+    {
+        p_clcb->auto_update = BTA_GATTC_DISC_WAITING;
+
+        if (p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE)
+            p_clcb->state = BTA_GATTC_CONN_ST; /* set clcb state */
+    }
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_disc_cmpl
+**
+** Description      discovery on server is finished
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATTC_DATA *p_q_cmd = p_clcb->p_q_cmd;
+    UNUSED(p_data);
+
+    APPL_TRACE_DEBUG("bta_gattc_disc_cmpl conn_id=%d",p_clcb->bta_conn_id);
+
+#if BLE_INCLUDED == TRUE
+    if(p_clcb->transport == BTA_TRANSPORT_LE)
+        L2CA_EnableUpdateBleConnParams(p_clcb->p_srcb->server_bda, TRUE);
+#endif
+    p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE;
+    p_clcb->disc_active = FALSE;
+
+    if (p_clcb->status != GATT_SUCCESS)
+    {
+        /* clean up cache */
+        if(p_clcb->p_srcb && p_clcb->p_srcb->p_srvc_cache)
+        {
+            while (!GKI_queue_is_empty(&p_clcb->p_srcb->cache_buffer))
+            {
+                GKI_freebuf (GKI_dequeue (&p_clcb->p_srcb->cache_buffer));
+            }
+            p_clcb->p_srcb->p_srvc_cache = NULL;
+        }
+
+        /* used to reset cache in application */
+        bta_gattc_co_cache_reset(p_clcb->p_srcb->server_bda);
+    }
+    /* release pending attribute list buffer */
+    utl_freebuf((void **)&p_clcb->p_srcb->p_srvc_list);
+
+    if (p_clcb->auto_update == BTA_GATTC_DISC_WAITING)
+    {
+        /* start discovery again */
+        bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);
+    }
+    /* get any queued command to proceed */
+    else if (p_q_cmd != NULL)
+    {
+        p_clcb->p_q_cmd = NULL;
+
+        bta_gattc_sm_execute(p_clcb, p_q_cmd->hdr.event, p_q_cmd);
+        /* if the command executed requeued the cmd, we don't
+         * want to free the underlying buffer that's being
+         * referenced by p_clcb->p_q_cmd
+         */
+        if (p_q_cmd != p_clcb->p_q_cmd) {
+            utl_freebuf((void **)&p_q_cmd);
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_read
+**
+** Description      Read an attribute
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_read(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    UINT16 handle = 0;
+    tGATT_READ_PARAM    read_param;
+    tBTA_GATT_STATUS    status;
+
+    memset (&read_param, 0 ,sizeof(tGATT_READ_PARAM));
+
+    if (bta_gattc_enqueue(p_clcb, p_data))
+    {
+        if ((handle = bta_gattc_id2handle(p_clcb->p_srcb,
+                                          &p_data->api_read.srvc_id,
+                                          &p_data->api_read.char_id,
+                                          p_data->api_read.p_descr_type)) == 0)
+        {
+            status = BTA_GATT_ERROR;
+        }
+        else
+        {
+            read_param.by_handle.handle = handle;
+            read_param.by_handle.auth_req = p_data->api_read.auth_req;
+
+            status = GATTC_Read(p_clcb->bta_conn_id, GATT_READ_BY_HANDLE, &read_param);
+        }
+
+        /* read fail */
+        if (status != BTA_GATT_OK)
+        {
+            /* Dequeue the data, if it was enqueued */
+            if (p_clcb->p_q_cmd == p_data)
+                p_clcb->p_q_cmd = NULL;
+
+            bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_READ, status, NULL);
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_read_multi
+**
+** Description      read multiple
+**
+** Returns          None.
+*********************************************************************************/
+void bta_gattc_read_multi(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    UINT16              i, handle;
+    tBTA_GATT_STATUS    status = BTA_GATT_OK;
+    tGATT_READ_PARAM    read_param;
+    tBTA_GATTC_ATTR_ID  *p_id;
+
+    if (bta_gattc_enqueue(p_clcb, p_data))
+    {
+        memset(&read_param, 0, sizeof(tGATT_READ_PARAM));
+
+        p_id = p_data->api_read_multi.p_id_list;
+
+        for (i = 0; i < p_data->api_read_multi.num_attr && p_id; i ++, p_id ++)
+        {
+            handle = 0;
+
+            if (p_id->id_type == BTA_GATT_TYPE_CHAR)
+            {
+                handle = bta_gattc_id2handle(p_clcb->p_srcb,
+                                     &p_id->id_value.char_id.srvc_id,
+                                     &p_id->id_value.char_id.char_id,
+                                     NULL);
+            }
+            else if (p_id->id_type == BTA_GATT_TYPE_CHAR_DESCR)
+            {
+                handle = bta_gattc_id2handle(p_clcb->p_srcb,
+                                     &p_id->id_value.char_descr_id.char_id.srvc_id,
+                                     &p_id->id_value.char_descr_id.char_id.char_id,
+                                     &p_id->id_value.char_descr_id.descr_id);
+            }
+            else
+            {
+                APPL_TRACE_ERROR("invalud ID type: %d", p_id->id_type);
+            }
+
+            if (handle == 0)
+            {
+                status = BTA_GATT_ERROR;
+                break;
+            }
+        }
+        if (status == BTA_GATT_OK)
+        {
+            read_param.read_multiple.num_handles = p_data->api_read_multi.num_attr;
+            read_param.read_multiple.auth_req = p_data->api_read_multi.auth_req;
+
+            status = GATTC_Read(p_clcb->bta_conn_id, GATT_READ_MULTIPLE, &read_param);
+        }
+
+        /* read fail */
+        if (status != BTA_GATT_OK)
+        {
+            /* Dequeue the data, if it was enqueued */
+            if (p_clcb->p_q_cmd == p_data)
+                p_clcb->p_q_cmd = NULL;
+
+            bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_READ, status, NULL);
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_write
+**
+** Description      Write an attribute
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_write(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    UINT16              handle = 0;
+    tGATT_VALUE         attr = {0};
+    tBTA_GATT_STATUS    status = BTA_GATT_OK;
+
+    if (bta_gattc_enqueue(p_clcb, p_data))
+    {
+        if ((handle = bta_gattc_id2handle(p_clcb->p_srcb,
+                                          &p_data->api_write.srvc_id,
+                                          &p_data->api_write.char_id,
+                                          p_data->api_write.p_descr_type)) == 0)
+        {
+            status = BTA_GATT_ERROR;
+        }
+        else
+        {
+            attr.handle= handle;
+            attr.offset = p_data->api_write.offset;
+            attr.len    = p_data->api_write.len;
+            attr.auth_req = p_data->api_write.auth_req;
+
+            if (p_data->api_write.p_value)
+                memcpy(attr.value, p_data->api_write.p_value, p_data->api_write.len);
+
+            status = GATTC_Write(p_clcb->bta_conn_id, p_data->api_write.write_type, &attr);
+        }
+
+        /* write fail */
+        if (status != BTA_GATT_OK)
+        {
+            /* Dequeue the data, if it was enqueued */
+            if (p_clcb->p_q_cmd == p_data)
+                p_clcb->p_q_cmd = NULL;
+
+            bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_WRITE, status, NULL);
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_execute
+**
+** Description      send execute write
+**
+** Returns          None.
+*********************************************************************************/
+void bta_gattc_execute(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATT_STATUS    status;
+
+    if (bta_gattc_enqueue(p_clcb, p_data))
+    {
+        status = GATTC_ExecuteWrite(p_clcb->bta_conn_id, p_data->api_exec.is_execute);
+
+        if (status != BTA_GATT_OK)
+        {
+            /* Dequeue the data, if it was enqueued */
+            if (p_clcb->p_q_cmd == p_data)
+                p_clcb->p_q_cmd = NULL;
+
+            bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_EXE_WRITE, status, NULL);
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_confirm
+**
+** Description      send handle value confirmation
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_confirm(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    UINT16 handle;
+
+    if ((handle = bta_gattc_id2handle(p_clcb->p_srcb,
+                                      &p_data->api_confirm.srvc_id,
+                                      &p_data->api_confirm.char_id,
+                                      NULL)) == 0)
+    {
+        APPL_TRACE_ERROR("Can not map service/char ID into valid handle");
+    }
+    else
+    {
+        if (GATTC_SendHandleValueConfirm(p_data->api_confirm.hdr.layer_specific, handle)
+            != GATT_SUCCESS)
+        {
+            APPL_TRACE_ERROR("bta_gattc_confirm to handle [0x%04x] failed", handle);
+        }
+        else
+        {
+            /* if over BR_EDR, inform PM for mode change */
+            if (p_clcb->transport == BTA_TRANSPORT_BR_EDR)
+            {
+                bta_sys_busy(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda);
+                bta_sys_idle(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda);
+            }
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_read_cmpl
+**
+** Description      read complete
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_read_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
+{
+    UINT8               event;
+    tBTA_GATTC          cb_data;
+    tBTA_GATT_READ_VAL  read_value;
+
+    memset(&cb_data, 0, sizeof(tBTA_GATTC));
+    memset(&read_value, 0, sizeof(tBTA_GATT_READ_VAL));
+
+    cb_data.read.status     = p_data->status;
+
+    if (p_data->p_cmpl != NULL && p_data->status == BTA_GATT_OK)
+    {
+        if (bta_gattc_handle2id(p_clcb->p_srcb,
+                                p_data->p_cmpl->att_value.handle,
+                                &cb_data.read.srvc_id,
+                                &cb_data.read.char_id,
+                                &cb_data.read.descr_type) == FALSE)
+        {
+            cb_data.read.status = BTA_GATT_INTERNAL_ERROR;
+            APPL_TRACE_ERROR("can not map to GATT ID. handle = 0x%04x",
+                                p_data->p_cmpl->att_value.handle);
+        }
+        else
+        {
+            cb_data.read.status = bta_gattc_pack_read_cb_data(p_clcb->p_srcb,
+                                                              &cb_data.read.descr_type.uuid,
+                                                              &p_data->p_cmpl->att_value,
+                                                              &read_value);
+            cb_data.read.p_value = &read_value;
+        }
+    }
+    else
+    {
+        cb_data.read.srvc_id = p_clcb->p_q_cmd->api_read.srvc_id;
+        cb_data.read.char_id = p_clcb->p_q_cmd->api_read.char_id;
+        if (p_clcb->p_q_cmd->api_read.p_descr_type)
+            memcpy(&cb_data.read.descr_type, p_clcb->p_q_cmd->api_read.p_descr_type,
+                   sizeof(tBTA_GATT_ID));
+    }
+
+    event = (p_clcb->p_q_cmd->api_read.p_descr_type == NULL) ?
+                    BTA_GATTC_READ_CHAR_EVT: BTA_GATTC_READ_DESCR_EVT;
+    cb_data.read.conn_id = p_clcb->bta_conn_id;
+
+    utl_freebuf((void **)&p_clcb->p_q_cmd);
+    /* read complete, callback */
+    ( *p_clcb->p_rcb->p_cback)(event, (tBTA_GATTC *)&cb_data);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_write_cmpl
+**
+** Description      write complete
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_write_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
+{
+    tBTA_GATTC      cb_data = {0};
+    UINT8          event;
+
+    memset(&cb_data, 0, sizeof(tBTA_GATTC));
+
+    cb_data.write.status     = p_data->status;
+
+    if (p_data->p_cmpl != NULL)
+    {
+        bta_gattc_handle2id(p_clcb->p_srcb, p_data->p_cmpl->att_value.handle,
+                            &cb_data.write.srvc_id, &cb_data.write.char_id,
+                            &cb_data.write.descr_type);
+    }
+    else
+    {
+        memcpy(&cb_data.write.srvc_id, &p_clcb->p_q_cmd->api_write.srvc_id,
+                sizeof(tBTA_GATT_SRVC_ID));
+        memcpy(&cb_data.write.char_id, &p_clcb->p_q_cmd->api_write.char_id,
+                sizeof(tBTA_GATT_ID));
+        if (p_clcb->p_q_cmd->api_write.p_descr_type)
+            memcpy(&cb_data.write.descr_type, p_clcb->p_q_cmd->api_write.p_descr_type,
+                   sizeof(tBTA_GATT_ID));
+    }
+
+    if (p_clcb->p_q_cmd->api_write.hdr.event == BTA_GATTC_API_WRITE_EVT &&
+        p_clcb->p_q_cmd->api_write.write_type == BTA_GATTC_WRITE_PREPARE)
+
+        event = BTA_GATTC_PREP_WRITE_EVT;
+
+    else if (p_clcb->p_q_cmd->api_write.p_descr_type == NULL)
+
+        event = BTA_GATTC_WRITE_CHAR_EVT;
+
+    else
+        event = BTA_GATTC_WRITE_DESCR_EVT;
+
+    utl_freebuf((void **)&p_clcb->p_q_cmd);
+    cb_data.write.conn_id = p_clcb->bta_conn_id;
+    /* write complete, callback */
+    ( *p_clcb->p_rcb->p_cback)(event, (tBTA_GATTC *)&cb_data);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_exec_cmpl
+**
+** Description      execute write complete
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_exec_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
+{
+    tBTA_GATTC          cb_data;
+
+    utl_freebuf((void **)&p_clcb->p_q_cmd);
+
+    p_clcb->status      = BTA_GATT_OK;
+
+    /* execute complete, callback */
+    cb_data.exec_cmpl.conn_id = p_clcb->bta_conn_id;
+    cb_data.exec_cmpl.status = p_data->status;
+
+    ( *p_clcb->p_rcb->p_cback)(BTA_GATTC_EXEC_EVT,  &cb_data);
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_cfg_mtu_cmpl
+**
+** Description      configure MTU operation complete
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_cfg_mtu_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
+{
+    tBTA_GATTC          cb_data;
+
+    utl_freebuf((void **)&p_clcb->p_q_cmd);
+
+
+    if (p_data->p_cmpl  &&  p_data->status == BTA_GATT_OK)
+        p_clcb->p_srcb->mtu  = p_data->p_cmpl->mtu;
+
+    /* configure MTU complete, callback */
+    p_clcb->status          = p_data->status;
+    cb_data.cfg_mtu.conn_id = p_clcb->bta_conn_id;
+    cb_data.cfg_mtu.status  = p_data->status;
+    cb_data.cfg_mtu.mtu     = p_clcb->p_srcb->mtu;
+
+    (*p_clcb->p_rcb->p_cback) (BTA_GATTC_CFG_MTU_EVT,  &cb_data);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_op_cmpl
+**
+** Description      operation completed.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void  bta_gattc_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    UINT8           op = (UINT8)p_data->op_cmpl.op_code;
+    UINT8           mapped_op = 0;
+
+    APPL_TRACE_DEBUG("bta_gattc_op_cmpl op = %d", op);
+
+    if (op == GATTC_OPTYPE_INDICATION || op == GATTC_OPTYPE_NOTIFICATION)
+    {
+        APPL_TRACE_ERROR("unexpected operation, ignored");
+    }
+    else if (op >= GATTC_OPTYPE_READ)
+    {
+        if (p_clcb->p_q_cmd == NULL)
+        {
+            APPL_TRACE_ERROR("No pending command");
+            return;
+        }
+        if (p_clcb->p_q_cmd->hdr.event != bta_gattc_opcode_to_int_evt[op - GATTC_OPTYPE_READ])
+        {
+            mapped_op = p_clcb->p_q_cmd->hdr.event - BTA_GATTC_API_READ_EVT + GATTC_OPTYPE_READ;
+            if ( mapped_op > GATTC_OPTYPE_INDICATION)   mapped_op = 0;
+
+#if (BT_TRACE_VERBOSE == TRUE)
+            APPL_TRACE_ERROR("expect op:(%s :0x%04x), receive unexpected operation (%s).",
+                                bta_gattc_op_code_name[mapped_op] , p_clcb->p_q_cmd->hdr.event,
+                                bta_gattc_op_code_name[op]);
+#else
+            APPL_TRACE_ERROR("expect op:(%u :0x%04x), receive unexpected operation (%u).",
+                                mapped_op , p_clcb->p_q_cmd->hdr.event, op);
+#endif
+            return;
+        }
+
+        /* discard responses if service change indication is received before operation completed */
+        if (p_clcb->auto_update == BTA_GATTC_DISC_WAITING && p_clcb->p_srcb->srvc_hdl_chg)
+        {
+            APPL_TRACE_DEBUG("Discard all responses when service change indication is received.");
+            p_data->op_cmpl.status = GATT_ERROR;
+        }
+
+        /* service handle change void the response, discard it */
+        if (op == GATTC_OPTYPE_READ)
+            bta_gattc_read_cmpl(p_clcb, &p_data->op_cmpl);
+
+        else if (op == GATTC_OPTYPE_WRITE)
+            bta_gattc_write_cmpl(p_clcb, &p_data->op_cmpl);
+
+        else if (op == GATTC_OPTYPE_EXE_WRITE)
+            bta_gattc_exec_cmpl(p_clcb, &p_data->op_cmpl);
+
+        else if (op == GATTC_OPTYPE_CONFIG)
+            bta_gattc_cfg_mtu_cmpl(p_clcb, &p_data->op_cmpl);
+
+        if (p_clcb->auto_update == BTA_GATTC_DISC_WAITING)
+        {
+            p_clcb->auto_update = BTA_GATTC_REQ_WAITING;
+            bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_op_cmpl
+**
+** Description      operation completed.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void  bta_gattc_ignore_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    UNUSED(p_clcb);
+
+    /* receive op complete when discovery is started, ignore the response,
+        and wait for discovery finish and resent */
+    APPL_TRACE_DEBUG("bta_gattc_ignore_op_cmpl op = %d", p_data->hdr.layer_specific);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_search
+**
+** Description      start a search in the local server cache
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_search(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATT_STATUS    status = GATT_INTERNAL_ERROR;
+    tBTA_GATTC cb_data;
+    APPL_TRACE_DEBUG("bta_gattc_search conn_id=%d",p_clcb->bta_conn_id);
+    if (p_clcb->p_srcb && p_clcb->p_srcb->p_srvc_cache)
+    {
+        status = BTA_GATT_OK;
+        /* search the local cache of a server device */
+        bta_gattc_search_service(p_clcb, p_data->api_search.p_srvc_uuid);
+    }
+    cb_data.search_cmpl.status  = status;
+    cb_data.search_cmpl.conn_id = p_clcb->bta_conn_id;
+
+    /* end of search or no server cache available */
+    ( *p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_CMPL_EVT,  &cb_data);
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_q_cmd
+**
+** Description      enqueue a command into control block, usually because discovery
+**                  operation is busy.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_q_cmd(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    bta_gattc_enqueue(p_clcb, p_data);
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_cache_open
+**
+** Description      open a NV cache for loading
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_cache_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    UNUSED(p_data);
+
+    bta_gattc_set_discover_st(p_clcb->p_srcb);
+
+    APPL_TRACE_DEBUG("bta_gattc_cache_open conn_id=%d",p_clcb->bta_conn_id);
+    bta_gattc_co_cache_open(p_clcb->p_srcb->server_bda, BTA_GATTC_CI_CACHE_OPEN_EVT,
+                            p_clcb->bta_conn_id, FALSE);
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_start_load
+**
+** Description      start cache loading by sending callout open cache
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_ci_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    APPL_TRACE_DEBUG("bta_gattc_ci_open conn_id=%d server state=%d" ,
+                      p_clcb->bta_conn_id, p_clcb->p_srcb->state);
+    if (p_clcb->p_srcb->state == BTA_GATTC_SERV_LOAD)
+    {
+        if (p_data->ci_open.status == BTA_GATT_OK)
+        {
+            p_clcb->p_srcb->attr_index = 0;
+            bta_gattc_co_cache_load(p_clcb->p_srcb->server_bda,
+                                    BTA_GATTC_CI_CACHE_LOAD_EVT,
+                                    p_clcb->p_srcb->attr_index,
+                                    p_clcb->bta_conn_id);
+        }
+        else
+        {
+            p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC;
+            /* cache open failure, start discovery */
+            bta_gattc_start_discover(p_clcb, NULL);
+        }
+    }
+    if (p_clcb->p_srcb->state == BTA_GATTC_SERV_SAVE)
+    {
+        if (p_data->ci_open.status == BTA_GATT_OK)
+        {
+            if (!bta_gattc_cache_save(p_clcb->p_srcb, p_clcb->bta_conn_id))
+            {
+                p_data->ci_open.status = BTA_GATT_ERROR;
+            }
+        }
+        if (p_data->ci_open.status != BTA_GATT_OK)
+        {
+            p_clcb->p_srcb->attr_index = 0;
+            bta_gattc_co_cache_close(p_clcb->p_srcb->server_bda, p_clcb->bta_conn_id);
+            bta_gattc_reset_discover_st(p_clcb->p_srcb, p_clcb->status);
+
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_ci_load
+**
+** Description      cache loading received.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_ci_load(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+
+    APPL_TRACE_DEBUG("bta_gattc_ci_load conn_id=%d load status=%d",
+                      p_clcb->bta_conn_id, p_data->ci_load.status);
+
+    if (p_data->ci_load.status == BTA_GATT_OK ||
+         p_data->ci_load.status == BTA_GATT_MORE)
+    {
+        if (p_data->ci_load.num_attr != 0)
+            bta_gattc_rebuild_cache(p_clcb->p_srcb, p_data->ci_load.num_attr,
+                                p_data->ci_load.attr, p_clcb->p_srcb->attr_index);
+
+        if (p_data->ci_load.status == BTA_GATT_OK)
+        {
+            p_clcb->p_srcb->attr_index = 0;
+            bta_gattc_reset_discover_st(p_clcb->p_srcb, BTA_GATT_OK);
+            bta_gattc_co_cache_close(p_clcb->p_srcb->server_bda, 0);
+        }
+        else /* load more */
+        {
+            p_clcb->p_srcb->attr_index += p_data->ci_load.num_attr;
+
+            bta_gattc_co_cache_load(p_clcb->p_srcb->server_bda,
+                                    BTA_GATTC_CI_CACHE_LOAD_EVT,
+                                    p_clcb->p_srcb->attr_index,
+                                    p_clcb->bta_conn_id);
+        }
+    }
+    else
+    {
+        bta_gattc_co_cache_close(p_clcb->p_srcb->server_bda, 0);
+        p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC;
+        p_clcb->p_srcb->attr_index = 0;
+        /* cache load failure, start discovery */
+        bta_gattc_start_discover(p_clcb, NULL);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_ci_save
+**
+** Description      cache loading received.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_ci_save(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    UNUSED(p_data);
+
+    APPL_TRACE_DEBUG("bta_gattc_ci_save conn_id=%d  " ,
+                      p_clcb->bta_conn_id   );
+
+    if (!bta_gattc_cache_save(p_clcb->p_srcb, p_clcb->bta_conn_id))
+    {
+        p_clcb->p_srcb->attr_index = 0;
+        bta_gattc_co_cache_close(p_clcb->p_srcb->server_bda, 0);
+        bta_gattc_reset_discover_st(p_clcb->p_srcb, p_clcb->status);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_fail
+**
+** Description      report API call failure back to apps
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    UNUSED(p_data);
+
+    if (p_clcb->status == BTA_GATT_OK)
+    {
+        APPL_TRACE_ERROR("operation not supported at current state [%d]", p_clcb->state);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_deregister_cmpl
+**
+** Description      De-Register a GATT client application with BTA completed.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg)
+{
+    tBTA_GATTC_CB       *p_cb = &bta_gattc_cb;
+    tBTA_GATTC_IF       client_if = p_clreg->client_if;
+    tBTA_GATTC          cb_data;
+    tBTA_GATTC_CBACK    *p_cback = p_clreg->p_cback;
+
+    memset(&cb_data, 0, sizeof(tBTA_GATTC));
+
+    GATT_Deregister(p_clreg->client_if);
+    memset(p_clreg, 0, sizeof(tBTA_GATTC_RCB));
+
+    cb_data.reg_oper.client_if = client_if;
+    cb_data.reg_oper.status    = BTA_GATT_OK;
+
+    if (p_cback)
+        /* callback with de-register event */
+        (*p_cback)(BTA_GATTC_DEREG_EVT,  (tBTA_GATTC *)&cb_data);
+
+    if (bta_gattc_num_reg_app() == 0 && p_cb->state == BTA_GATTC_STATE_DISABLING)
+    {
+        p_cb->state = BTA_GATTC_STATE_DISABLED;
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_conn_cback
+**
+** Description      callback functions to GATT client stack.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_gattc_conn_cback(tGATT_IF gattc_if, BD_ADDR bda, UINT16 conn_id,
+                                 BOOLEAN connected, tGATT_DISCONN_REASON reason,
+                                 tBT_TRANSPORT transport)
+{
+    tBTA_GATTC_DATA *p_buf;
+
+    if (reason != 0)
+    {
+        APPL_TRACE_WARNING("%s() - cif=%d connected=%d conn_id=%d reason=0x%04x",
+                      __FUNCTION__, gattc_if, connected, conn_id, reason);
+    }
+
+    bt_bdaddr_t bdaddr;
+    bdcpy(bdaddr.address, bda);
+    /*
+    if (connected)
+        btif_debug_conn_state(bdaddr, BTIF_DEBUG_CONNECTED, GATT_CONN_UNKNOWN);
+    else
+        btif_debug_conn_state(bdaddr, BTIF_DEBUG_DISCONNECTED, reason);
+    */
+    if ((p_buf = (tBTA_GATTC_DATA *) GKI_getbuf(sizeof(tBTA_GATTC_DATA))) != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_GATTC_DATA));
+
+        p_buf->int_conn.hdr.event            = connected ? BTA_GATTC_INT_CONN_EVT:
+                                                           BTA_GATTC_INT_DISCONN_EVT;
+        p_buf->int_conn.hdr.layer_specific   = conn_id;
+        p_buf->int_conn.client_if            = gattc_if;
+        p_buf->int_conn.role                 = L2CA_GetBleConnRole(bda);
+        p_buf->int_conn.reason               = reason;
+        p_buf->int_conn.transport            = transport;
+        bdcpy(p_buf->int_conn.remote_bda, bda);
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_enc_cmpl_cback
+**
+** Description      encryption complete callback function to GATT client stack.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_gattc_enc_cmpl_cback(tGATT_IF gattc_if, BD_ADDR bda)
+{
+    tBTA_GATTC_DATA *p_buf;
+    tBTA_GATTC_CLCB *p_clcb = NULL;
+
+    if ((p_clcb = bta_gattc_find_clcb_by_cif(gattc_if, bda, BTA_GATT_TRANSPORT_LE)) == NULL)
+    {
+        return;
+    }
+
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+    /* filter this event just for BTA HH LE GATT client,
+       In the future, if we want to enable encryption complete event
+       for all GATT clients, we can remove this code */
+    if (!bta_hh_le_is_hh_gatt_if(gattc_if))
+    {
+        return;
+    }
+#endif
+
+    APPL_TRACE_DEBUG("bta_gattc_enc_cmpl_cback: cif = %d", gattc_if);
+
+    if ((p_buf = (tBTA_GATTC_DATA *) GKI_getbuf(sizeof(tBTA_GATTC_DATA))) != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_GATTC_DATA));
+
+        p_buf->enc_cmpl.hdr.event            = BTA_GATTC_ENC_CMPL_EVT;
+        p_buf->enc_cmpl.hdr.layer_specific   = p_clcb->bta_conn_id;
+        p_buf->enc_cmpl.client_if            = gattc_if;
+        bdcpy(p_buf->enc_cmpl.remote_bda, bda);
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_process_api_refresh
+**
+** Description      process refresh API to delete cache and start a new discovery
+**                  if currently connected.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg)
+{
+    tBTA_GATTC_SERV *p_srvc_cb = bta_gattc_find_srvr_cache(p_msg->api_conn.remote_bda);
+    tBTA_GATTC_CLCB      *p_clcb = &bta_gattc_cb.clcb[0];
+    BOOLEAN         found = FALSE;
+    UINT8           i;
+    UNUSED(p_cb);
+
+    if (p_srvc_cb != NULL)
+    {
+        /* try to find a CLCB */
+        if (p_srvc_cb->connected && p_srvc_cb->num_clcb != 0)
+        {
+            for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++, p_clcb ++)
+            {
+                if (p_clcb->in_use && p_clcb->p_srcb == p_srvc_cb)
+                {
+                    found = TRUE;
+                    break;
+                }
+            }
+            if (found)
+            {
+                bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);
+                return;
+            }
+        }
+        /* in all other cases, mark it and delete the cache */
+        if (p_srvc_cb->p_srvc_cache != NULL)
+        {
+            while (!GKI_queue_is_empty(&p_srvc_cb->cache_buffer))
+                GKI_freebuf (GKI_dequeue (&p_srvc_cb->cache_buffer));
+
+            p_srvc_cb->p_srvc_cache = NULL;
+        }
+    }
+    /* used to reset cache in application */
+    bta_gattc_co_cache_reset(p_msg->api_conn.remote_bda);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_process_srvc_chg_ind
+**
+** Description      process service change indication.
+**
+** Returns          None.
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_process_srvc_chg_ind(UINT16 conn_id,
+                                       tBTA_GATTC_RCB      *p_clrcb,
+                                       tBTA_GATTC_SERV     *p_srcb,
+                                       tBTA_GATTC_CLCB      *p_clcb,
+                                       tBTA_GATTC_NOTIFY    *p_notify,
+                                       UINT16 handle)
+{
+    tBT_UUID        gattp_uuid, srvc_chg_uuid;
+    BOOLEAN         processed = FALSE;
+    UINT8           i;
+
+    gattp_uuid.len = 2;
+    gattp_uuid.uu.uuid16 = UUID_SERVCLASS_GATT_SERVER;
+
+    srvc_chg_uuid.len = 2;
+    srvc_chg_uuid.uu.uuid16 = GATT_UUID_GATT_SRV_CHGD;
+
+    if (bta_gattc_uuid_compare(&p_notify->char_id.srvc_id.id.uuid, &gattp_uuid, TRUE) &&
+        bta_gattc_uuid_compare(&p_notify->char_id.char_id.uuid, &srvc_chg_uuid, TRUE))
+    {
+        processed = TRUE;
+        /* mark service handle change pending */
+        p_srcb->srvc_hdl_chg = TRUE;
+        /* clear up all notification/indication registration */
+        bta_gattc_clear_notif_registration(conn_id);
+        /* service change indication all received, do discovery update */
+        if ( ++ p_srcb->update_count == bta_gattc_num_reg_app())
+        {
+            /* not an opened connection; or connection busy */
+            /* search for first available clcb and start discovery */
+            if (p_clcb == NULL || (p_clcb && p_clcb->p_q_cmd != NULL))
+            {
+                for (i = 0 ; i < BTA_GATTC_CLCB_MAX; i ++)
+                {
+                    if (bta_gattc_cb.clcb[i].in_use &&
+                        bta_gattc_cb.clcb[i].p_srcb == p_srcb &&
+                        bta_gattc_cb.clcb[i].p_q_cmd == NULL)
+                    {
+                        p_clcb = &bta_gattc_cb.clcb[i];
+                        break;
+                    }
+                }
+            }
+            /* send confirmation here if this is an indication, it should always be */
+            GATTC_SendHandleValueConfirm(conn_id, handle);
+
+            /* if connection available, refresh cache by doing discovery now */
+            if (p_clcb != NULL)
+                bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);
+        }
+        /* notify applicationf or service change */
+        if (p_clrcb->p_cback != NULL)
+        {
+           (* p_clrcb->p_cback)(BTA_GATTC_SRVC_CHG_EVT, (tBTA_GATTC *)p_srcb->server_bda);
+        }
+
+    }
+
+    return processed;
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_proc_other_indication
+**
+** Description      process all non-service change indication/notification.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_proc_other_indication(tBTA_GATTC_CLCB *p_clcb, UINT8 op,
+                                     tGATT_CL_COMPLETE *p_data,
+                                     tBTA_GATTC_NOTIFY *p_notify)
+{
+    APPL_TRACE_DEBUG("bta_gattc_proc_other_indication check \
+                       p_data->att_value.handle=%d p_data->handle=%d",
+                       p_data->att_value.handle, p_data->handle);
+    APPL_TRACE_DEBUG("is_notify", p_notify->is_notify);
+
+    p_notify->is_notify = (op == GATTC_OPTYPE_INDICATION) ? FALSE : TRUE;
+    p_notify->len = p_data->att_value.len;
+    bdcpy(p_notify->bda, p_clcb->bda);
+    memcpy(p_notify->value, p_data->att_value.value, p_data->att_value.len);
+    p_notify->conn_id = p_clcb->bta_conn_id;
+
+    if (p_clcb->p_rcb->p_cback)
+        (*p_clcb->p_rcb->p_cback)(BTA_GATTC_NOTIF_EVT,  (tBTA_GATTC *)p_notify);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_process_indicate
+**
+** Description      process indication/notification.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_process_indicate(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_CL_COMPLETE *p_data)
+{
+    UINT16              handle = p_data->att_value.handle;
+    tBTA_GATTC_CLCB     *p_clcb ;
+    tBTA_GATTC_RCB      *p_clrcb = NULL;
+    tBTA_GATTC_SERV     *p_srcb = NULL;
+    tBTA_GATTC_NOTIFY   notify;
+    BD_ADDR             remote_bda;
+    tBTA_GATTC_IF       gatt_if;
+    tBTA_TRANSPORT transport;
+
+    if (!GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda, &transport))
+    {
+        APPL_TRACE_ERROR("%s indication/notif for unknown app", __func__);
+        if (op == GATTC_OPTYPE_INDICATION)
+            GATTC_SendHandleValueConfirm(conn_id, handle);
+        return;
+    }
+
+    if ((p_clrcb = bta_gattc_cl_get_regcb(gatt_if)) == NULL)
+    {
+        APPL_TRACE_ERROR("%s indication/notif for unregistered app", __func__);
+        if (op == GATTC_OPTYPE_INDICATION)
+            GATTC_SendHandleValueConfirm(conn_id, handle);
+        return;
+    }
+
+    if ((p_srcb = bta_gattc_find_srcb(remote_bda)) == NULL)
+    {
+        APPL_TRACE_ERROR("%s indication/notif for unknown device, ignore", __func__);
+        if (op == GATTC_OPTYPE_INDICATION)
+            GATTC_SendHandleValueConfirm(conn_id, handle);
+        return;
+    }
+
+    p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+
+    if (bta_gattc_handle2id(p_srcb, handle,
+                            &notify.char_id.srvc_id,
+                            &notify.char_id.char_id,
+                            &notify.descr_type))
+    {
+        /* if non-service change indication/notification, forward to application */
+        if (!bta_gattc_process_srvc_chg_ind(conn_id, p_clrcb, p_srcb, p_clcb, &notify, handle))
+        {
+            /* if app registered for the notification */
+            if (bta_gattc_check_notif_registry(p_clrcb, p_srcb, &notify))
+            {
+                /* connection not open yet */
+                if (p_clcb == NULL)
+                {
+                    if ((p_clcb = bta_gattc_clcb_alloc(gatt_if, remote_bda, transport)) != NULL)
+                    {
+                        p_clcb->bta_conn_id = conn_id;
+                        p_clcb->transport   = transport;
+
+                        bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, NULL);
+                    }
+                    else
+                    {
+                        APPL_TRACE_ERROR("No resources");
+                    }
+                }
+
+                if (p_clcb != NULL)
+                    bta_gattc_proc_other_indication(p_clcb, op, p_data, &notify);
+            }
+            /* no one intersted and need ack? */
+            else if (op == GATTC_OPTYPE_INDICATION)
+            {
+                APPL_TRACE_DEBUG("%s no one interested, ack now", __func__);
+                GATTC_SendHandleValueConfirm(conn_id, handle);
+            }
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR("%s Indi/Notif for Unknown handle[0x%04x], can not find in local cache.",
+                         __func__, handle);
+        if (op == GATTC_OPTYPE_INDICATION)
+            GATTC_SendHandleValueConfirm(conn_id, handle);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_cmpl_cback
+**
+** Description      client operation complete callback register with BTE GATT.
+**
+** Returns          None.
+**
+*******************************************************************************/
+static void  bta_gattc_cmpl_cback(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status,
+                                  tGATT_CL_COMPLETE *p_data)
+{
+    tBTA_GATTC_CLCB     *p_clcb;
+    APPL_TRACE_DEBUG("bta_gattc_cmpl_cback: conn_id = %d op = %d status = %d",
+                      conn_id, op, status);
+
+    /* notification and indication processed right away */
+    if (op == GATTC_OPTYPE_NOTIFICATION || op == GATTC_OPTYPE_INDICATION)
+    {
+        bta_gattc_process_indicate(conn_id, op, p_data);
+        return;
+    }
+    /* for all other operation, not expected if w/o connection */
+    else if ((p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id)) == NULL)
+    {
+        APPL_TRACE_ERROR("bta_gattc_cmpl_cback unknown conn_id =  %d, ignore data", conn_id);
+        return;
+    }
+
+    /* if over BR_EDR, inform PM for mode change */
+    if (p_clcb->transport == BTA_TRANSPORT_BR_EDR)
+    {
+        bta_sys_busy(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda);
+        bta_sys_idle(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda);
+    }
+
+    bta_gattc_cmpl_sendmsg(conn_id, op, status, p_data);
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_cmpl_sendmsg
+**
+** Description      client operation complete send message
+**
+** Returns          None.
+**
+*******************************************************************************/
+static void bta_gattc_cmpl_sendmsg(UINT16 conn_id, tGATTC_OPTYPE op,
+                                   tBTA_GATT_STATUS status,
+                                   tGATT_CL_COMPLETE *p_data)
+{
+    const UINT16         len = sizeof(tBTA_GATTC_OP_CMPL) + sizeof(tGATT_CL_COMPLETE);
+    tBTA_GATTC_OP_CMPL  *p_buf = (tBTA_GATTC_OP_CMPL *) GKI_getbuf(len);
+
+    if (p_buf != NULL)
+    {
+        memset(p_buf, 0, len);
+        p_buf->hdr.event = BTA_GATTC_OP_CMPL_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+        p_buf->status = status;
+        p_buf->op_code = op;
+
+        if (p_data != NULL)
+        {
+            p_buf->p_cmpl = (tGATT_CL_COMPLETE *)(p_buf + 1);
+            memcpy(p_buf->p_cmpl, p_data, sizeof(tGATT_CL_COMPLETE));
+        }
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_cong_cback
+**
+** Description      congestion callback for BTA GATT client.
+**
+** Returns          void
+**
+********************************************************************************/
+static void bta_gattc_cong_cback (UINT16 conn_id, BOOLEAN congested)
+{
+    tBTA_GATTC_CLCB *p_clcb;
+    tBTA_GATTC cb_data;
+
+    if ((p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id)) != NULL)
+    {
+        if (p_clcb->p_rcb->p_cback)
+        {
+            cb_data.congest.conn_id = conn_id;
+            cb_data.congest.congested = congested;
+
+            (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CONGEST_EVT, &cb_data);
+        }
+    }
+}
+
+#if BLE_INCLUDED == TRUE
+/*******************************************************************************
+**
+** Function         bta_gattc_init_clcb_conn
+**
+** Description      Initaite a BTA CLCB connection
+**
+** Returns          void
+**
+********************************************************************************/
+void bta_gattc_init_clcb_conn(UINT8 cif, BD_ADDR remote_bda)
+{
+    tBTA_GATTC_CLCB     *p_clcb = NULL;
+    tBTA_GATTC_DATA     gattc_data;
+    UINT16              conn_id;
+
+    /* should always get the connection ID */
+    if (GATT_GetConnIdIfConnected(cif, remote_bda, &conn_id, BTA_GATT_TRANSPORT_LE) == FALSE)
+    {
+        APPL_TRACE_ERROR("bta_gattc_init_clcb_conn ERROR: not a connected device");
+        return;
+    }
+
+    /* initaite a new connection here */
+    if ((p_clcb = bta_gattc_clcb_alloc(cif, remote_bda, BTA_GATT_TRANSPORT_LE)) != NULL)
+    {
+        gattc_data.hdr.layer_specific = p_clcb->bta_conn_id = conn_id;
+
+        gattc_data.api_conn.client_if = cif;
+        memcpy(gattc_data.api_conn.remote_bda, remote_bda, BD_ADDR_LEN);
+        gattc_data.api_conn.is_direct = TRUE;
+
+        bta_gattc_sm_execute(p_clcb, BTA_GATTC_API_OPEN_EVT, &gattc_data);
+    }
+    else
+    {
+        APPL_TRACE_ERROR("No resources");
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_process_listen_all
+**
+** Description      process listen all, send open callback to application for all
+**                  connected slave LE link.
+**
+** Returns          void
+**
+********************************************************************************/
+void bta_gattc_process_listen_all(UINT8 cif)
+{
+    UINT8               i_conn = 0;
+    tBTA_GATTC_CONN     *p_conn = &bta_gattc_cb.conn_track[0];
+
+    for (i_conn = 0; i_conn < BTA_GATTC_CONN_MAX; i_conn++, p_conn ++)
+    {
+        if (p_conn->in_use )
+        {
+            if (bta_gattc_find_clcb_by_cif(cif, p_conn->remote_bda, BTA_GATT_TRANSPORT_LE) == NULL)
+            {
+                bta_gattc_init_clcb_conn(cif, p_conn->remote_bda);
+            }
+            /* else already connected */
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_listen
+**
+** Description      Start or stop a listen for connection
+**
+** Returns          void
+**
+********************************************************************************/
+void bta_gattc_listen(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg)
+{
+    tBTA_GATTC_RCB      *p_clreg = bta_gattc_cl_get_regcb(p_msg->api_listen.client_if);
+    tBTA_GATTC          cb_data;
+    UNUSED(p_cb);
+
+    cb_data.reg_oper.status = BTA_GATT_ERROR;
+    cb_data.reg_oper.client_if = p_msg->api_listen.client_if;
+
+    if (p_clreg == NULL)
+    {
+        APPL_TRACE_ERROR("bta_gattc_listen failed, unknown client_if: %d",
+                            p_msg->api_listen.client_if);
+        return;
+    }
+    /* mark bg conn record */
+    if (bta_gattc_mark_bg_conn(p_msg->api_listen.client_if,
+                               (BD_ADDR_PTR) p_msg->api_listen.remote_bda,
+                               p_msg->api_listen.start,
+                               TRUE))
+    {
+        if (!GATT_Listen(p_msg->api_listen.client_if,
+                         p_msg->api_listen.start,
+                         p_msg->api_listen.remote_bda))
+        {
+            APPL_TRACE_ERROR("Listen failure");
+            (*p_clreg->p_cback)(BTA_GATTC_LISTEN_EVT, &cb_data);
+        }
+        else
+        {
+            cb_data.status = BTA_GATT_OK;
+
+            (*p_clreg->p_cback)(BTA_GATTC_LISTEN_EVT, &cb_data);
+
+            if (p_msg->api_listen.start)
+            {
+                /* if listen to a specific target */
+                if (p_msg->api_listen.remote_bda != NULL)
+                {
+
+                    /* if is a connected remote device */
+                    if (L2CA_GetBleConnRole(p_msg->api_listen.remote_bda) == HCI_ROLE_SLAVE &&
+                        bta_gattc_find_clcb_by_cif(p_msg->api_listen.client_if,
+                                                   p_msg->api_listen.remote_bda,
+                                                   BTA_GATT_TRANSPORT_LE) == NULL)
+                    {
+
+                        bta_gattc_init_clcb_conn(p_msg->api_listen.client_if,
+                                                p_msg->api_listen.remote_bda);
+                    }
+                }
+                /* if listen to all */
+                else
+                {
+                    LOG_DEBUG("Listen For All now");
+                    /* go through all connected device and send
+                    callback for all connected slave connection */
+                    bta_gattc_process_listen_all(p_msg->api_listen.client_if);
+                }
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_broadcast
+**
+** Description      Start or stop broadcasting
+**
+** Returns          void
+**
+********************************************************************************/
+void bta_gattc_broadcast(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg)
+{
+    tBTA_GATTC_RCB      *p_clreg = bta_gattc_cl_get_regcb(p_msg->api_listen.client_if);
+    tBTA_GATTC          cb_data;
+    UNUSED(p_cb);
+
+    cb_data.reg_oper.client_if = p_msg->api_listen.client_if;
+    cb_data.reg_oper.status = BTM_BleBroadcast(p_msg->api_listen.start);
+
+    if (p_clreg && p_clreg->p_cback)
+        (*p_clreg->p_cback)(BTA_GATTC_LISTEN_EVT, &cb_data);
+}
+#endif
+#endif

+ 1106 - 0
components/bt/bluedroid/bta/gatt/bta_gattc_api.c

@@ -0,0 +1,1106 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2010-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the implementation of the API for GATT module of BTA.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_gatt_api.h"
+#include "bta_gattc_int.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_gattc_reg =
+{
+    bta_gattc_hdl_event,
+    BTA_GATTC_Disable
+};
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_Disable
+**
+** Description      This function is called to disable GATTC module
+**
+** Parameters       None.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_Disable(void)
+{
+    BT_HDR  *p_buf;
+
+    if (bta_sys_is_register(BTA_ID_GATTC) == FALSE)
+    {
+        APPL_TRACE_WARNING("GATTC Module not enabled/already disabled");
+        return;
+    }
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_GATTC_API_DISABLE_EVT;
+        bta_sys_sendmsg(p_buf);
+    }
+    bta_sys_deregister(BTA_ID_GATTC);
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_AppRegister
+**
+** Description      This function is called to register application callbacks
+**                    with BTA GATTC module.
+**
+** Parameters       p_app_uuid - applicaiton UUID
+**                  p_client_cb - pointer to the application callback function.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_AppRegister(tBT_UUID *p_app_uuid, tBTA_GATTC_CBACK *p_client_cb)
+{
+    tBTA_GATTC_API_REG  *p_buf;
+
+    if (bta_sys_is_register(BTA_ID_GATTC) == FALSE)
+    {
+        bta_sys_register(BTA_ID_GATTC, &bta_gattc_reg);
+    }
+
+    if ((p_buf = (tBTA_GATTC_API_REG *) GKI_getbuf(sizeof(tBTA_GATTC_API_REG))) != NULL)
+    {
+        p_buf->hdr.event    = BTA_GATTC_API_REG_EVT;
+        if (p_app_uuid != NULL)
+            memcpy(&p_buf->app_uuid, p_app_uuid, sizeof(tBT_UUID));
+        p_buf->p_cback      = p_client_cb;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_AppDeregister
+**
+** Description      This function is called to deregister an application
+**                  from BTA GATTC module.
+**
+** Parameters       client_if - client interface identifier.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_AppDeregister(tBTA_GATTC_IF client_if)
+{
+    tBTA_GATTC_API_DEREG  *p_buf;
+
+    if ((p_buf = (tBTA_GATTC_API_DEREG *) GKI_getbuf(sizeof(tBTA_GATTC_API_DEREG))) != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTC_API_DEREG_EVT;
+        p_buf->client_if = client_if;
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_Open
+**
+** Description      Open a direct connection or add a background auto connection
+**                  bd address
+**
+** Parameters       client_if: server interface.
+**                  remote_bda: remote device BD address.
+**                  is_direct: direct connection or background auto connection
+**                  transport: Transport to be used for GATT connection (BREDR/LE)
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTC_Open(tBTA_GATTC_IF client_if, BD_ADDR remote_bda,
+                    BOOLEAN is_direct, tBTA_GATT_TRANSPORT transport)
+{
+    tBTA_GATTC_API_OPEN  *p_buf;
+
+    if ((p_buf = (tBTA_GATTC_API_OPEN *) GKI_getbuf(sizeof(tBTA_GATTC_API_OPEN))) != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTC_API_OPEN_EVT;
+
+        p_buf->client_if = client_if;
+        p_buf->is_direct = is_direct;
+        p_buf->transport = transport;
+        memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);
+
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_CancelOpen
+**
+** Description      Cancel a direct open connection or remove a background auto connection
+**                  bd address
+**
+** Parameters       client_if: server interface.
+**                  remote_bda: remote device BD address.
+**                  is_direct: direct connection or background auto connection
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTC_CancelOpen(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, BOOLEAN is_direct)
+{
+    tBTA_GATTC_API_CANCEL_OPEN  *p_buf;
+
+    if ((p_buf = (tBTA_GATTC_API_CANCEL_OPEN *) GKI_getbuf(sizeof(tBTA_GATTC_API_CANCEL_OPEN))) != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTC_API_CANCEL_OPEN_EVT;
+
+        p_buf->client_if = client_if;
+        p_buf->is_direct = is_direct;
+        memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_Close
+**
+** Description      Close a connection to a GATT server.
+**
+** Parameters       conn_id: connectino ID to be closed.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTC_Close(UINT16 conn_id)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_GATTC_API_CLOSE_EVT;
+
+        p_buf->layer_specific = conn_id;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTC_ConfigureMTU
+**
+** Description      Configure the MTU size in the GATT channel. This can be done
+**                  only once per connection.
+**
+** Parameters       conn_id: connection ID.
+**                  mtu: desired MTU size to use.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTC_ConfigureMTU (UINT16 conn_id, UINT16 mtu)
+{
+    tBTA_GATTC_API_CFG_MTU  *p_buf;
+
+    if ((p_buf = (tBTA_GATTC_API_CFG_MTU *) GKI_getbuf(sizeof(tBTA_GATTC_API_CFG_MTU))) != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTC_API_CFG_MTU_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+
+        p_buf->mtu = mtu;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTC_ServiceSearchRequest
+**
+** Description      This function is called to request a GATT service discovery
+**                    on a GATT server. This function report service search result
+**                  by a callback event, and followed by a service search complete
+**                  event.
+**
+** Parameters       conn_id: connection ID.
+**                  p_srvc_uuid: a UUID of the service application is interested in.
+**                              If Null, discover for all services.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_ServiceSearchRequest (UINT16 conn_id, tBT_UUID *p_srvc_uuid)
+{
+    tBTA_GATTC_API_SEARCH  *p_buf;
+    UINT16  len = sizeof(tBTA_GATTC_API_SEARCH) + sizeof(tBT_UUID);
+
+    if ((p_buf = (tBTA_GATTC_API_SEARCH *) GKI_getbuf(len)) != NULL)
+    {
+        memset(p_buf, 0, len);
+
+        p_buf->hdr.event = BTA_GATTC_API_SEARCH_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+
+        if (p_srvc_uuid)
+        {
+            p_buf->p_srvc_uuid = (tBT_UUID *)(p_buf + 1);
+            memcpy(p_buf->p_srvc_uuid, p_srvc_uuid, sizeof(tBT_UUID));
+        }
+        else
+            p_buf->p_srvc_uuid = NULL;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetFirstChar
+**
+** Description      This function is called to find the first characteristic of the
+**                  service on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_srvc_id: the service ID of which the characteristic is belonged to.
+**                  p_char_uuid_cond: Characteristic UUID, if NULL find the first available
+**                               characteristic.
+**                  p_char_result: output parameter which will store the GATT
+**                                  characteristic ID.
+**                  p_property: output parameter to carry the characteristic property.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS  BTA_GATTC_GetFirstChar (UINT16 conn_id, tBTA_GATT_SRVC_ID *p_srvc_id,
+                                          tBT_UUID *p_char_uuid_cond,
+                                          tBTA_GATTC_CHAR_ID *p_char_result,
+                                          tBTA_GATT_CHAR_PROP *p_property)
+{
+    tBTA_GATT_STATUS    status;
+
+    if (!p_srvc_id || !p_char_result)
+        return BTA_GATT_ILLEGAL_PARAMETER;
+
+    if ((status = bta_gattc_query_cache(conn_id, BTA_GATTC_ATTR_TYPE_CHAR, p_srvc_id, NULL,
+                                        p_char_uuid_cond, &p_char_result->char_id, (void *)p_property))
+        == BTA_GATT_OK)
+    {
+        memcpy(&p_char_result->srvc_id, p_srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+    }
+
+    return status;
+
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetNextChar
+**
+** Description      This function is called to find the next characteristic of the
+**                  service on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_start_char_id: start the characteristic search from the next record
+**                           after the one identified by char_id.
+**                  p_char_uuid_cond: Characteristic UUID, if NULL find the first available
+**                               characteristic.
+**                  p_char_result: output parameter which will store the GATT
+**                                  characteristic ID.
+**                  p_property: output parameter to carry the characteristic property.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS  BTA_GATTC_GetNextChar (UINT16 conn_id,
+                                         tBTA_GATTC_CHAR_ID *p_start_char_id,
+                                         tBT_UUID           *p_char_uuid_cond,
+                                         tBTA_GATTC_CHAR_ID *p_char_result,
+                                         tBTA_GATT_CHAR_PROP    *p_property)
+{
+    tBTA_GATT_STATUS    status;
+
+    if (!p_start_char_id || !p_char_result)
+        return BTA_GATT_ILLEGAL_PARAMETER;
+
+    if ((status = bta_gattc_query_cache(conn_id, BTA_GATTC_ATTR_TYPE_CHAR,
+                                        &p_start_char_id->srvc_id,
+                                        &p_start_char_id->char_id,
+                                        p_char_uuid_cond,
+                                        &p_char_result->char_id,
+                                        (void *) p_property))
+        == BTA_GATT_OK)
+    {
+        memcpy(&p_char_result->srvc_id, &p_start_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+    }
+
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetFirstCharDescr
+**
+** Description      This function is called to find the first characteristic descriptor of the
+**                  characteristic on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_char_id: the characteristic ID of which the descriptor is belonged to.
+**                  p_descr_uuid_cond: Characteristic Descr UUID, if NULL find the first available
+**                               characteristic.
+**                  p_descr_result: output parameter which will store the GATT
+**                                  characteristic descriptor ID.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS  BTA_GATTC_GetFirstCharDescr (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id,
+                                                tBT_UUID *p_descr_uuid_cond,
+                                                tBTA_GATTC_CHAR_DESCR_ID *p_descr_result)
+{
+    tBTA_GATT_STATUS    status;
+
+    if (!p_char_id || !p_descr_result)
+        return BTA_GATT_ILLEGAL_PARAMETER;
+
+    memset(p_descr_result, 0, sizeof(tBTA_GATTC_CHAR_DESCR_ID));
+
+    if ((status = bta_gattc_query_cache(conn_id,
+                                        BTA_GATTC_ATTR_TYPE_CHAR_DESCR,
+                                        &p_char_id->srvc_id,
+                                        &p_char_id->char_id,
+                                        p_descr_uuid_cond,
+                                        &p_descr_result->char_id.char_id,
+                                        NULL))
+        == BTA_GATT_OK)
+    {
+        memcpy(&p_descr_result->descr_id, &p_descr_result->char_id.char_id, sizeof(tBTA_GATT_ID));
+        memcpy(&p_descr_result->char_id, p_char_id, sizeof(tBTA_GATTC_CHAR_ID));
+    }
+    return status;
+
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetNextCharDescr
+**
+** Description      This function is called to find the next characteristic descriptor
+**                  of the characterisctic.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_start_descr_id: start the descriptor search from the next record
+**                           after the one identified by p_start_descr_id.
+**                  p_descr_uuid_cond: Characteristic descriptor UUID, if NULL find
+**                               the first available characteristic descriptor.
+**                  p_descr_result: output parameter which will store the GATT
+**                                  characteristic descriptor ID.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS  BTA_GATTC_GetNextCharDescr (UINT16 conn_id,
+                                             tBTA_GATTC_CHAR_DESCR_ID *p_start_descr_id,
+                                             tBT_UUID           *p_descr_uuid_cond,
+                                             tBTA_GATTC_CHAR_DESCR_ID *p_descr_result)
+{
+    tBTA_GATT_STATUS    status;
+
+    if (!p_start_descr_id || !p_descr_result)
+        return BTA_GATT_ILLEGAL_PARAMETER;
+
+    memset(p_descr_result, 0, sizeof(tBTA_GATTC_CHAR_DESCR_ID));
+
+    if ((status = bta_gattc_query_cache(conn_id, BTA_GATTC_ATTR_TYPE_CHAR_DESCR,
+                                        &p_start_descr_id->char_id.srvc_id,
+                                        &p_start_descr_id->char_id.char_id,
+                                        p_descr_uuid_cond,
+                                        &p_descr_result->char_id.char_id,
+                                        (void *)&p_start_descr_id->descr_id))
+        == BTA_GATT_OK)
+    {
+        memcpy(&p_descr_result->descr_id, &p_descr_result->char_id.char_id, sizeof(tBTA_GATT_ID));
+        memcpy(&p_descr_result->char_id, p_start_descr_id, sizeof(tBTA_GATTC_CHAR_ID));
+    }
+
+    return status;
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetFirstIncludedService
+**
+** Description      This function is called to find the first included service of the
+**                  service on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_srvc_id: the service ID of which the characteristic is belonged to.
+**                  p_uuid_cond: Characteristic UUID, if NULL find the first available
+**                               characteristic.
+**                  p_result: output parameter which will store the GATT ID
+**                              of the included service found.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS  BTA_GATTC_GetFirstIncludedService(UINT16 conn_id, tBTA_GATT_SRVC_ID *p_srvc_id,
+                                                    tBT_UUID *p_uuid_cond, tBTA_GATTC_INCL_SVC_ID *p_result)
+{
+    tBTA_GATT_STATUS    status;
+
+    if (!p_srvc_id || !p_result)
+        return BTA_GATT_ILLEGAL_PARAMETER;
+
+    if ((status = bta_gattc_query_cache(conn_id,
+                                        BTA_GATTC_ATTR_TYPE_INCL_SRVC,
+                                        p_srvc_id,
+                                        NULL,
+                                        p_uuid_cond,
+                                        &p_result->incl_svc_id.id,
+                                        (void *)&p_result->incl_svc_id.is_primary))
+        == BTA_GATT_OK)
+    {
+        memcpy(&p_result->srvc_id, p_srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+    }
+
+    return status;
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetNextIncludedService
+**
+** Description      This function is called to find the next included service of the
+**                  service on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_start_id: start the search from the next record
+**                                  after the one identified by p_start_id.
+**                  p_uuid_cond: Included service UUID, if NULL find the first available
+**                               included service.
+**                  p_result: output parameter which will store the GATT ID
+**                              of the included service found.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS  BTA_GATTC_GetNextIncludedService(UINT16 conn_id,
+                                                   tBTA_GATTC_INCL_SVC_ID *p_start_id,
+                                                   tBT_UUID               *p_uuid_cond,
+                                                   tBTA_GATTC_INCL_SVC_ID *p_result)
+{
+    tBTA_GATT_STATUS    status;
+
+    if (!p_start_id || !p_result)
+        return BTA_GATT_ILLEGAL_PARAMETER;
+
+    if ((status = bta_gattc_query_cache(conn_id,
+                                        BTA_GATTC_ATTR_TYPE_INCL_SRVC,
+                                        &p_start_id->srvc_id,
+                                        &p_start_id->incl_svc_id.id,
+                                        p_uuid_cond,
+                                        &p_result->incl_svc_id.id,
+                                        (void *)&p_result->incl_svc_id.is_primary))
+        == BTA_GATT_OK)
+    {
+        memcpy(&p_result->srvc_id, &p_start_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+    }
+
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_ReadCharacteristic
+**
+** Description      This function is called to read a service's characteristics of
+**                    the given characteritisc ID.
+**
+** Parameters       conn_id - connectino ID.
+**                    p_char_id - characteritic ID to read.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_ReadCharacteristic(UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id,
+                                  tBTA_GATT_AUTH_REQ auth_req)
+{
+    tBTA_GATTC_API_READ  *p_buf;
+
+    if ((p_buf = (tBTA_GATTC_API_READ *) GKI_getbuf(sizeof(tBTA_GATTC_API_READ))) != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_GATTC_API_READ));
+
+        p_buf->hdr.event = BTA_GATTC_API_READ_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+        p_buf->auth_req = auth_req;
+
+        memcpy(&p_buf->srvc_id, &p_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+        memcpy(&p_buf->char_id, &p_char_id->char_id, sizeof(tBTA_GATT_ID));
+        p_buf->p_descr_type = NULL;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_ReadCharDescr
+**
+** Description      This function is called to read a characteristics descriptor.
+**
+** Parameters       conn_id - connection ID.
+**                    p_char_descr_id - characteritic descriptor ID to read.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_ReadCharDescr (UINT16 conn_id,
+                              tBTA_GATTC_CHAR_DESCR_ID  *p_descr_id,
+                              tBTA_GATT_AUTH_REQ auth_req)
+{
+    tBTA_GATTC_API_READ  *p_buf;
+    UINT16  len = (UINT16)(sizeof(tBTA_GATT_ID) + sizeof(tBTA_GATTC_API_READ));
+
+    if ((p_buf = (tBTA_GATTC_API_READ *) GKI_getbuf(len)) != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_GATTC_API_READ));
+
+        p_buf->hdr.event = BTA_GATTC_API_READ_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+        p_buf->auth_req = auth_req;
+
+        memcpy(&p_buf->srvc_id, &p_descr_id->char_id.srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+        memcpy(&p_buf->char_id, &p_descr_id->char_id.char_id, sizeof(tBTA_GATT_ID));
+        p_buf->p_descr_type  = (tBTA_GATT_ID *)(p_buf + 1);
+
+        memcpy(p_buf->p_descr_type, &p_descr_id->descr_id, sizeof(tBTA_GATT_ID));
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTC_ReadMultiple
+**
+** Description      This function is called to read multiple characteristic or
+**                  characteristic descriptors.
+**
+** Parameters       conn_id - connectino ID.
+**                    p_read_multi - pointer to the read multiple parameter.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_ReadMultiple(UINT16 conn_id, tBTA_GATTC_MULTI *p_read_multi,
+                            tBTA_GATT_AUTH_REQ auth_req)
+{
+    tBTA_GATTC_API_READ_MULTI  *p_buf;
+    tBTA_GATTC_ATTR_ID          *p_value;
+    UINT16      len = (UINT16)(sizeof(tBTA_GATTC_API_READ_MULTI) +
+                               p_read_multi->num_attr * sizeof(tBTA_GATTC_ATTR_ID));
+    UINT8       i;
+
+    if ((p_buf = (tBTA_GATTC_API_READ_MULTI *) GKI_getbuf(len)) != NULL)
+    {
+        memset(p_buf, 0, len);
+
+        p_buf->hdr.event = BTA_GATTC_API_READ_MULTI_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+        p_buf->auth_req = auth_req;
+
+        p_buf->num_attr = p_read_multi->num_attr;
+
+        if (p_buf->num_attr > 0)
+        {
+            p_buf->p_id_list = p_value = (tBTA_GATTC_ATTR_ID *)(p_buf + 1);
+
+            for (i = 0; i < p_buf->num_attr; i ++, p_value ++)
+            {
+                memcpy(p_value, &p_read_multi->id_list[i], sizeof(tBTA_GATTC_ATTR_ID));
+            }
+        }
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_WriteCharValue
+**
+** Description      This function is called to write characteristic value.
+**
+** Parameters       conn_id - connection ID.
+**                    p_char_id - characteristic ID to write.
+**                    write_type - type of write.
+**                  len: length of the data to be written.
+**                  p_value - the value to be written.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_WriteCharValue ( UINT16 conn_id,
+                                tBTA_GATTC_CHAR_ID *p_char_id,
+                                tBTA_GATTC_WRITE_TYPE  write_type,
+                                UINT16 len,
+                                UINT8 *p_value,
+                                tBTA_GATT_AUTH_REQ auth_req)
+{
+    tBTA_GATTC_API_WRITE  *p_buf;
+
+    if ((p_buf = (tBTA_GATTC_API_WRITE *) GKI_getbuf((UINT16)(sizeof(tBTA_GATTC_API_WRITE) + len))) != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_GATTC_API_WRITE) + len);
+
+        p_buf->hdr.event = BTA_GATTC_API_WRITE_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+        p_buf->auth_req = auth_req;
+
+        memcpy(&p_buf->srvc_id, &p_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+        memcpy(&p_buf->char_id, &p_char_id->char_id, sizeof(tBTA_GATT_ID));
+
+        p_buf->write_type = write_type;
+        p_buf->len = len;
+
+        if (p_value && len > 0)
+        {
+            p_buf->p_value = (UINT8 *)(p_buf + 1);
+            memcpy(p_buf->p_value, p_value, len);
+        }
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTC_WriteCharDescr
+**
+** Description      This function is called to write characteristic descriptor value.
+**
+** Parameters       conn_id - connection ID
+**                    p_char_descr_id - characteristic descriptor ID to write.
+**                  write_type - write type.
+**                  p_value - the value to be written.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_WriteCharDescr (UINT16 conn_id,
+                               tBTA_GATTC_CHAR_DESCR_ID *p_char_descr_id,
+                               tBTA_GATTC_WRITE_TYPE  write_type,
+                               tBTA_GATT_UNFMT      *p_data,
+                               tBTA_GATT_AUTH_REQ auth_req)
+{
+    tBTA_GATTC_API_WRITE  *p_buf;
+    UINT16  len = sizeof(tBTA_GATTC_API_WRITE) + sizeof(tBTA_GATT_ID);
+
+    if (p_data != NULL)
+        len += p_data->len;
+
+    if ((p_buf = (tBTA_GATTC_API_WRITE *) GKI_getbuf(len)) != NULL)
+    {
+        memset(p_buf, 0, len);
+
+        p_buf->hdr.event = BTA_GATTC_API_WRITE_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+        p_buf->auth_req = auth_req;
+
+        memcpy(&p_buf->srvc_id, &p_char_descr_id->char_id.srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+        memcpy(&p_buf->char_id, &p_char_descr_id->char_id.char_id, sizeof(tBTA_GATT_ID));
+        p_buf->p_descr_type = (tBTA_GATT_ID *)(p_buf + 1);
+        memcpy(p_buf->p_descr_type, &p_char_descr_id->descr_id, sizeof(tBTA_GATT_ID));
+        p_buf->write_type = write_type;
+
+        if (p_data && p_data->len != 0)
+        {
+            p_buf->p_value  = (UINT8 *)(p_buf->p_descr_type + 1);
+            p_buf->len      = p_data->len;
+            /* pack the descr data */
+            memcpy(p_buf->p_value, p_data->p_value, p_data->len);
+        }
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTC_PrepareWrite
+**
+** Description      This function is called to prepare write a characteristic value.
+**
+** Parameters       conn_id - connection ID.
+**                    p_char_id - GATT characteritic ID of the service.
+**                  offset - offset of the write value.
+**                  len: length of the data to be written.
+**                  p_value - the value to be written.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_PrepareWrite  (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id,
+                              UINT16 offset, UINT16 len, UINT8 *p_value,
+                              tBTA_GATT_AUTH_REQ auth_req)
+{
+    tBTA_GATTC_API_WRITE  *p_buf;
+
+    if ((p_buf = (tBTA_GATTC_API_WRITE *) GKI_getbuf((UINT16)(sizeof(tBTA_GATTC_API_WRITE) + len))) != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_GATTC_API_WRITE) + len);
+
+        p_buf->hdr.event = BTA_GATTC_API_WRITE_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+        p_buf->auth_req = auth_req;
+
+        memcpy(&p_buf->srvc_id, &p_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+        memcpy(&p_buf->char_id, &p_char_id->char_id, sizeof(tBTA_GATT_ID));
+
+        p_buf->write_type = BTA_GATTC_WRITE_PREPARE;
+        p_buf->offset   = offset;
+        p_buf->len = len;
+
+        if (p_value && len > 0)
+        {
+            p_buf->p_value = (UINT8 *)(p_buf + 1);
+            memcpy(p_buf->p_value, p_value, len);
+        }
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTC_ExecuteWrite
+**
+** Description      This function is called to execute write a prepare write sequence.
+**
+** Parameters       conn_id - connection ID.
+**                    is_execute - execute or cancel.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_ExecuteWrite  (UINT16 conn_id, BOOLEAN is_execute)
+{
+    tBTA_GATTC_API_EXEC  *p_buf;
+
+    if ((p_buf = (tBTA_GATTC_API_EXEC *) GKI_getbuf((UINT16)sizeof(tBTA_GATTC_API_EXEC))) != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_GATTC_API_EXEC));
+
+        p_buf->hdr.event = BTA_GATTC_API_EXEC_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+
+        p_buf->is_execute = is_execute;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTC_SendIndConfirm
+**
+** Description      This function is called to send handle value confirmation.
+**
+** Parameters       conn_id - connection ID.
+**                    p_char_id - characteristic ID to confirm.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_SendIndConfirm (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id)
+{
+    tBTA_GATTC_API_CONFIRM  *p_buf;
+
+    APPL_TRACE_API("BTA_GATTC_SendIndConfirm conn_id=%d service uuid1=0x%x char uuid=0x%x",
+                    conn_id, p_char_id->srvc_id.id.uuid.uu.uuid16, p_char_id->char_id.uuid.uu.uuid16);
+
+    if ((p_buf = (tBTA_GATTC_API_CONFIRM *) GKI_getbuf(sizeof(tBTA_GATTC_API_CONFIRM))) != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_GATTC_API_CONFIRM));
+
+        p_buf->hdr.event = BTA_GATTC_API_CONFIRM_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+
+        memcpy(&p_buf->srvc_id, &p_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+        memcpy(&p_buf->char_id, &p_char_id->char_id, sizeof(tBTA_GATT_ID));
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_RegisterForNotifications
+**
+** Description      This function is called to register for notification of a service.
+**
+** Parameters       client_if - client interface.
+**                  bda - target GATT server.
+**                  p_char_id - pointer to GATT characteristic ID.
+**
+** Returns          OK if registration succeed, otherwise failed.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS BTA_GATTC_RegisterForNotifications (tBTA_GATTC_IF client_if,
+                                                     BD_ADDR bda,
+                                                     tBTA_GATTC_CHAR_ID *p_char_id)
+{
+    tBTA_GATTC_RCB      *p_clreg;
+    tBTA_GATT_STATUS    status = BTA_GATT_ILLEGAL_PARAMETER;
+    UINT8               i;
+
+    if (!p_char_id)
+    {
+        APPL_TRACE_ERROR("deregistration failed, unknow char id");
+        return status;
+    }
+
+    if ((p_clreg = bta_gattc_cl_get_regcb(client_if)) != NULL)
+    {
+        for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
+        {
+            if ( p_clreg->notif_reg[i].in_use &&
+                 !memcmp(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN) &&
+                  bta_gattc_charid_compare(&p_clreg->notif_reg[i].char_id, p_char_id))
+            {
+                APPL_TRACE_WARNING("notification already registered");
+                status = BTA_GATT_OK;
+                break;
+            }
+        }
+        if (status != BTA_GATT_OK)
+        {
+            for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
+            {
+                if (!p_clreg->notif_reg[i].in_use)
+                {
+                    memset((void *)&p_clreg->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
+
+                    p_clreg->notif_reg[i].in_use = TRUE;
+                    memcpy(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN);
+
+                    p_clreg->notif_reg[i].char_id.srvc_id.is_primary = p_char_id->srvc_id.is_primary;
+                    bta_gattc_cpygattid(&p_clreg->notif_reg[i].char_id.srvc_id.id, &p_char_id->srvc_id.id);
+                    bta_gattc_cpygattid(&p_clreg->notif_reg[i].char_id.char_id, &p_char_id->char_id);
+
+                    status = BTA_GATT_OK;
+                    break;
+                }
+            }
+            if (i == BTA_GATTC_NOTIF_REG_MAX)
+            {
+                status = BTA_GATT_NO_RESOURCES;
+                APPL_TRACE_ERROR("Max Notification Reached, registration failed.");
+            }
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR("Client_if: %d Not Registered", client_if);
+    }
+
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_DeregisterForNotifications
+**
+** Description      This function is called to de-register for notification of a service.
+**
+** Parameters       client_if - client interface.
+**                  bda - target GATT server.
+**                  p_char_id - pointer to GATT characteristic ID.
+**
+** Returns          OK if deregistration succeed, otherwise failed.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS BTA_GATTC_DeregisterForNotifications (tBTA_GATTC_IF client_if,
+                                                       BD_ADDR bda,
+                                                       tBTA_GATTC_CHAR_ID *p_char_id)
+{
+    tBTA_GATTC_RCB      *p_clreg;
+    tBTA_GATT_STATUS    status = BTA_GATT_ILLEGAL_PARAMETER;
+    UINT8               i;
+
+    if (!p_char_id)
+    {
+        APPL_TRACE_ERROR("%s deregistration failed, unknown char id", __func__);
+        return status;
+    }
+
+    if ((p_clreg = bta_gattc_cl_get_regcb(client_if)) != NULL)
+    {
+        for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
+        {
+            if (p_clreg->notif_reg[i].in_use &&
+                !memcmp(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN) &&
+                bta_gattc_charid_compare(&p_clreg->notif_reg[i].char_id, p_char_id))
+            {
+                APPL_TRACE_DEBUG("%s deregistered bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
+                    __func__, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
+                memset(&p_clreg->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
+                status = BTA_GATT_OK;
+                break;
+            }
+        }
+        if (i == BTA_GATTC_NOTIF_REG_MAX)
+        {
+            status = BTA_GATT_ERROR;
+            APPL_TRACE_ERROR("%s registration not found bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
+                __func__, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR("%s client_if: %d not registered bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
+            __func__, client_if, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
+    }
+
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_Refresh
+**
+** Description      Refresh the server cache of the remote device
+**
+** Parameters       remote_bda: remote device BD address.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTC_Refresh(BD_ADDR remote_bda)
+{
+    tBTA_GATTC_API_OPEN  *p_buf;
+
+    if ((p_buf = (tBTA_GATTC_API_OPEN *) GKI_getbuf(sizeof(tBTA_GATTC_API_OPEN))) != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTC_API_REFRESH_EVT;
+
+        memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);
+
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_Listen
+**
+** Description      Start advertisement to listen for connection request for a GATT
+**                  client application.
+**
+** Parameters       client_if: server interface.
+**                  start: to start or stop listening for connection
+**                  remote_bda: remote device BD address, if listen to all device
+**                              use NULL.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTC_Listen(tBTA_GATTC_IF client_if, BOOLEAN start, BD_ADDR_PTR target_bda)
+{
+    tBTA_GATTC_API_LISTEN  *p_buf;
+
+    if ((p_buf = (tBTA_GATTC_API_LISTEN *) GKI_getbuf((UINT16)(sizeof(tBTA_GATTC_API_LISTEN) + BD_ADDR_LEN))) != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTC_API_LISTEN_EVT;
+
+        p_buf->client_if = client_if;
+        p_buf->start = start;
+        if (target_bda)
+        {
+            p_buf->remote_bda = (UINT8*)(p_buf + 1);
+            memcpy(p_buf->remote_bda, target_bda, BD_ADDR_LEN);
+        }
+        else
+            p_buf->remote_bda = NULL;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_Broadcast
+**
+** Description      Start broadcasting (non-connectable advertisements)
+**
+** Parameters       client_if: client interface.
+**                  start: to start or stop listening for connection
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTC_Broadcast(tBTA_GATTC_IF client_if, BOOLEAN start)
+{
+    tBTA_GATTC_API_LISTEN  *p_buf;
+
+    if ((p_buf = (tBTA_GATTC_API_LISTEN *) GKI_getbuf((UINT16)(sizeof(tBTA_GATTC_API_LISTEN) + BD_ADDR_LEN))) != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTC_API_BROADCAST_EVT;
+        p_buf->client_if = client_if;
+        p_buf->start = start;
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+#endif /* BTA_GATT_INCLUDED */
+

+ 1637 - 0
components/bt/bluedroid/bta/gatt/bta_gattc_cache.c

@@ -0,0 +1,1637 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This file contains the GATT client discovery procedures and cache
+ *  related functions.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+#include "utl.h"
+#include "gki.h"
+#include "bta_sys.h"
+#include "sdp_api.h"
+#include "sdpdefs.h"
+#include "bta_gattc_int.h"
+#include "btm_api.h"
+#include "btm_ble_api.h"
+
+#define LOG_TAG "bt_bta_gattc"
+// #include "osi/include/log.h"
+
+static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb);
+static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb);
+
+#define BTA_GATT_SDP_DB_SIZE 4096
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+static char *bta_gattc_attr_type[] =
+{
+    "I", /* Included Service */
+    "C", /* Characteristic */
+    "D" /* Characteristic Descriptor */
+};
+/* utility functions */
+
+/*******************************************************************************
+**
+** Function         bta_gattc_display_cache_server
+**
+** Description      debug function to display the server cache.
+**
+** Returns          none.
+**
+*******************************************************************************/
+static void bta_gattc_display_cache_server(tBTA_GATTC_CACHE *p_cache)
+{
+    UINT8 i = 0, j;
+    tBTA_GATTC_CACHE    *p_cur_srvc = p_cache;
+    tBTA_GATTC_CACHE_ATTR   *p_attr;
+
+    APPL_TRACE_ERROR("<================Start Server Cache =============>");
+
+    while (p_cur_srvc)
+    {
+        APPL_TRACE_ERROR("Service[%d]: handle[%d ~ %d] %s[0x%04x] inst[%d]",
+                          i, p_cur_srvc->s_handle, p_cur_srvc->e_handle,
+                          ((p_cur_srvc->service_uuid.id.uuid.len == 2) ? "uuid16" : "uuid128"),
+                          p_cur_srvc->service_uuid.id.uuid.uu.uuid16,
+                          p_cur_srvc->service_uuid.id.inst_id);
+        i ++;
+
+        p_attr = p_cur_srvc->p_attr;
+
+        for (j = 0; p_attr; j ++ )
+        {
+            APPL_TRACE_ERROR("\t Attr[0x%04x] handle[%d] uuid[0x%04x] inst[%d] type[%s] prop[0x%1x]",
+                              j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16, p_attr->inst_id,
+                              bta_gattc_attr_type[p_attr->attr_type], p_attr->property);
+
+            p_attr = p_attr->p_next;
+        }
+        p_cur_srvc = p_cur_srvc->p_next;
+    }
+
+    APPL_TRACE_ERROR("<================End Server Cache =============>");
+    APPL_TRACE_ERROR(" ");
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_display_explore_record
+**
+** Description      debug function to display the exploration list
+**
+** Returns          none.
+**
+*******************************************************************************/
+static void bta_gattc_display_explore_record(tBTA_GATTC_ATTR_REC *p_rec, UINT8 num_rec)
+{
+    UINT8 i;
+    tBTA_GATTC_ATTR_REC *pp = p_rec;
+
+    APPL_TRACE_ERROR("<================Start Explore Queue =============>");
+    for (i = 0; i < num_rec; i ++, pp ++)
+    {
+        APPL_TRACE_ERROR("\t rec[%d] uuid[0x%04x] s_handle[%d] e_handle[%d] is_primary[%d]",
+                          i + 1, pp->uuid.uu.uuid16, pp->s_handle, pp->e_handle, pp->is_primary);
+    }
+    APPL_TRACE_ERROR("<================ End Explore Queue =============>");
+    APPL_TRACE_ERROR(" ");
+
+}
+#endif  /* BTA_GATT_DEBUG == TRUE */
+
+
+/*******************************************************************************
+**
+** Function         bta_gattc_alloc_cache_buf
+**
+** Description      Allocate a GKI buffer for database cache.
+**
+** Returns          status
+**
+*******************************************************************************/
+BT_HDR *bta_gattc_alloc_cache_buf(tBTA_GATTC_SERV *p_srvc_cb)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *)GKI_getpoolbuf(GATT_DB_POOL_ID)) == NULL)
+    {
+        APPL_TRACE_DEBUG("No resources: GKI buffer allocation failed.");
+        utl_freebuf((void **)&p_srvc_cb->p_srvc_list);
+        p_srvc_cb->free_byte = 0;
+    }
+    else
+    {
+        memset(p_buf, 0, GKI_get_buf_size(p_buf));
+        p_srvc_cb->p_free = (UINT8 *) p_buf;
+        p_srvc_cb->free_byte = GKI_get_buf_size(p_buf);
+
+        /* link into buffer queue */
+        GKI_enqueue(&p_srvc_cb->cache_buffer, p_buf);
+    }
+#if BTA_GATT_DEBUG== TRUE
+    APPL_TRACE_DEBUG("allocating new buffer: free byte = %d", p_srvc_cb->free_byte);
+#endif
+    return p_buf;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_init_cache
+**
+** Description      Initialize the database cache and discovery related resources.
+**
+** Returns          status
+**
+*******************************************************************************/
+tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb)
+{
+    tBTA_GATT_STATUS    status = BTA_GATT_OK;
+
+    while (!GKI_queue_is_empty(&p_srvc_cb->cache_buffer))
+        GKI_freebuf (GKI_dequeue (&p_srvc_cb->cache_buffer));
+
+    utl_freebuf((void **)&p_srvc_cb->p_srvc_list);
+
+    if ((p_srvc_cb->p_srvc_list = (tBTA_GATTC_ATTR_REC*)GKI_getbuf(BTA_GATTC_ATTR_LIST_SIZE)) == NULL)
+    {
+        APPL_TRACE_DEBUG("No resources: GKI buffer allocation failed.");
+        status = GATT_NO_RESOURCES;
+    }
+    else
+    {
+        p_srvc_cb->total_srvc = 0;
+        p_srvc_cb->cur_srvc_idx =
+        p_srvc_cb->cur_char_idx =
+        p_srvc_cb->next_avail_idx = 0;
+
+        if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL)
+        {
+            status = GATT_NO_RESOURCES;
+        }
+        else
+        {
+            p_srvc_cb->p_cur_srvc = p_srvc_cb->p_srvc_cache = NULL;
+        }
+    }
+
+    return status;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_get_srvc_inst_id
+**
+** Description      get service instance number
+**
+** Returns          instance ID of the service.
+**
+*******************************************************************************/
+static UINT8 bta_gattc_get_srvc_inst_id(tBTA_GATTC_SERV *p_srvc_cb, tBT_UUID uuid)
+{
+    UINT8 i = 0, inst = 0;
+    tBTA_GATTC_ATTR_REC   *p_srvc_rec;
+
+    for (i = 0; i < p_srvc_cb->total_srvc; i ++)
+    /*
+    for (; i < p_srvc_cb->cur_srvc_idx; i ++)*/
+    {
+        p_srvc_rec = p_srvc_cb->p_srvc_list + i;
+
+        if (bta_gattc_uuid_compare(&p_srvc_rec->uuid, &uuid, TRUE))
+            inst ++;
+    }
+    return inst ;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_get_char_inst_id
+**
+** Description      get characteristic instance number
+**
+** Returns          characteristic instance ID.
+**
+*******************************************************************************/
+static UINT8 bta_gattc_get_char_inst_id(tBTA_GATTC_CACHE *p_service_cache, tBT_UUID *p_uuid)
+{
+    UINT8 inst = 0;
+    tBTA_GATTC_CACHE_ATTR   *p_attr;
+    tBT_UUID    attr_uuid;
+
+    p_attr = p_service_cache->p_attr;
+
+    while (p_attr)
+    {
+        bta_gattc_pack_attr_uuid(p_attr, &attr_uuid);
+
+        if (bta_gattc_uuid_compare(&attr_uuid, p_uuid, TRUE))
+            inst ++;
+
+        p_attr = p_attr->p_next;
+    }
+
+    return inst ;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_get_char_descr_inst_id
+**
+** Description      get characteristic descriptor instance number
+**
+** Returns          characteristic instance ID.
+**
+*******************************************************************************/
+static UINT8 bta_gattc_get_char_descr_inst_id(tBTA_GATTC_CACHE_ATTR *p_char_attr, tBT_UUID *p_uuid)
+{
+    UINT8 inst = 0;
+    tBT_UUID    attr_uuid;
+
+    if (p_char_attr != NULL)
+        p_char_attr = p_char_attr->p_next;
+
+    while (p_char_attr)
+    {
+        bta_gattc_pack_attr_uuid(p_char_attr, &attr_uuid);
+
+        if (bta_gattc_uuid_compare(&attr_uuid, p_uuid, TRUE))
+            inst ++;
+
+        p_char_attr = p_char_attr->p_next;
+    }
+    return inst ;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_add_srvc_to_cache
+**
+** Description      Add a service into database cache.
+**
+** Returns          status
+**
+*******************************************************************************/
+static tBTA_GATT_STATUS bta_gattc_add_srvc_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
+                                                    UINT16 s_handle, UINT16 e_handle,
+                                                    tBT_UUID *p_uuid,
+                                                    BOOLEAN is_primary, UINT8 srvc_inst)
+{
+    tBTA_GATTC_CACHE    *p_new_srvc = NULL;
+    tBTA_GATT_STATUS    status = BTA_GATT_OK;
+
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+    APPL_TRACE_DEBUG("Add a service into Service");
+    APPL_TRACE_DEBUG("free byte = %d,  req %d bytes.", p_srvc_cb->free_byte, sizeof(tBTA_GATTC_CACHE))
+#endif
+
+    if (p_srvc_cb->free_byte < sizeof(tBTA_GATTC_CACHE))
+    {
+        if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL)
+            return GATT_NO_RESOURCES;
+    }
+
+    p_new_srvc = (tBTA_GATTC_CACHE *)p_srvc_cb->p_free;
+    /* update service information */
+    p_new_srvc->s_handle = s_handle;
+    p_new_srvc->e_handle = e_handle;
+    p_new_srvc->service_uuid.is_primary = is_primary;
+    memcpy(&p_new_srvc->service_uuid.id.uuid, p_uuid, sizeof(tBT_UUID));
+    p_new_srvc->service_uuid.id.inst_id = srvc_inst;
+    p_new_srvc->p_next  = NULL;
+
+    if (p_srvc_cb->p_cur_srvc != NULL)
+        p_srvc_cb->p_cur_srvc->p_next = p_new_srvc;
+    p_srvc_cb->p_cur_srvc = p_new_srvc;
+    p_srvc_cb->p_cur_srvc->p_cur_char = NULL;
+
+    /* first service */
+    if (p_srvc_cb->p_srvc_cache == NULL)
+        p_srvc_cb->p_srvc_cache = p_new_srvc;
+
+    /* update buffer managament info */
+    p_srvc_cb->p_free += sizeof(tBTA_GATTC_CACHE);
+    p_srvc_cb->free_byte -= sizeof(tBTA_GATTC_CACHE);
+
+
+    return status;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_add_attr_to_cache
+**
+** Description      Add an attribute into database cache buffer.
+**
+** Returns          status
+**
+*******************************************************************************/
+static tBTA_GATT_STATUS bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
+                                                    UINT16 handle,
+                                                    tBT_UUID *p_uuid,
+                                                    UINT8 property,
+                                                    tBTA_GATTC_ATTR_TYPE type)
+{
+    tBTA_GATTC_CACHE_ATTR *p_attr;
+    tBTA_GATT_STATUS    status = BTA_GATT_OK;
+    UINT16  len = sizeof(tBTA_GATTC_CACHE_ATTR) + p_uuid->len;
+    UINT8   *pp;
+
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+    APPL_TRACE_DEBUG("bta_gattc_add_attr_to_cache: Add a [%s] into Service", bta_gattc_attr_type[type]);
+    APPL_TRACE_DEBUG("handle=%d uuid16=0x%x property=0x%x type=%d", handle, p_uuid->uu.uuid16, property, type);
+    APPL_TRACE_DEBUG("free byte = %d,  req %d bytes.", p_srvc_cb->free_byte, len);
+#endif
+
+    if (p_srvc_cb->p_cur_srvc == NULL)
+    {
+        APPL_TRACE_ERROR("Illegal action to add char/descr/incl srvc before adding a service!");
+        return GATT_WRONG_STATE;
+    }
+
+    if (p_srvc_cb->free_byte < len)
+    {
+        if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL)
+            return GATT_NO_RESOURCES;
+    }
+
+    p_attr = (tBTA_GATTC_CACHE_ATTR *)p_srvc_cb->p_free;
+
+    p_attr->attr_handle = handle;
+    p_attr->attr_type   = type;
+    p_attr->property    = property;
+    p_attr->uuid_len    = p_uuid->len;
+    p_attr->p_uuid      = (tBTA_GATTC_UUID *)(p_attr + 1);
+    p_attr->p_next      = NULL;
+
+    pp = (UINT8 *)p_attr->p_uuid;
+
+    if (p_uuid->len == LEN_UUID_16)
+    {
+        UINT16_TO_STREAM(pp, p_uuid->uu.uuid16);
+    }
+    else if (p_uuid->len == LEN_UUID_128)
+    {
+        memcpy(pp, p_uuid->uu.uuid128, LEN_UUID_128);
+    }
+
+    if (type == BTA_GATTC_ATTR_TYPE_CHAR)
+    {
+        p_attr->inst_id = bta_gattc_get_char_inst_id(p_srvc_cb->p_cur_srvc, p_uuid);
+        p_srvc_cb->p_cur_srvc->p_cur_char = p_attr;
+    }
+    else if (type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
+        p_attr->inst_id = bta_gattc_get_char_descr_inst_id(p_srvc_cb->p_cur_srvc->p_cur_char, p_uuid);
+    else /* TODO: --->> temp treat included service as single instance */
+        p_attr->inst_id = 0;
+
+    /* update service information */
+    p_srvc_cb->p_free += len;
+    p_srvc_cb->free_byte -= len;
+
+    /* first attribute within the service, update the attribute pointer */
+    if (p_srvc_cb->p_cur_srvc->p_attr == NULL)
+    {
+        p_srvc_cb->p_cur_srvc->p_attr = p_attr;
+    }
+    if (p_srvc_cb->p_cur_srvc->p_last_attr != NULL)
+        p_srvc_cb->p_cur_srvc->p_last_attr->p_next = p_attr;
+
+    p_srvc_cb->p_cur_srvc->p_last_attr = p_attr;
+
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_get_disc_range
+**
+** Description      get discovery stating and ending handle range.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_get_disc_range(tBTA_GATTC_SERV *p_srvc_cb, UINT16 *p_s_hdl, UINT16 *p_e_hdl, BOOLEAN is_srvc)
+{
+    tBTA_GATTC_ATTR_REC *p_rec = NULL;
+
+    if (is_srvc)
+    {
+        p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx;
+        *p_s_hdl = p_rec->s_handle;
+    }
+    else
+    {
+        p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;
+        *p_s_hdl = p_rec->s_handle + 1;
+    }
+
+    *p_e_hdl = p_rec->e_handle;
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+    APPL_TRACE_DEBUG("discover range [%d ~ %d]",p_rec->s_handle, p_rec->e_handle);
+#endif
+    return;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_discover_pri_service
+**
+** Description      Start primary service discovery
+**
+** Returns          status of the operation.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS bta_gattc_discover_pri_service(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb,
+                                                    UINT8 disc_type)
+{
+    tBTA_GATTC_CLCB     *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+    tBTA_GATT_STATUS    status =  BTA_GATT_ERROR;
+
+    if (p_clcb)
+    {
+        if (p_clcb->transport == BTA_TRANSPORT_LE)
+            status = bta_gattc_discover_procedure(conn_id, p_server_cb, disc_type);
+        else
+            status = bta_gattc_sdp_service_disc(conn_id, p_server_cb);
+    }
+
+    return status;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_discover_procedure
+**
+** Description      Start a particular type of discovery procedure on server.
+**
+** Returns          status of the operation.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS bta_gattc_discover_procedure(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb,
+                                                   UINT8 disc_type)
+{
+    tGATT_DISC_PARAM param;
+    BOOLEAN is_service = TRUE;
+
+    memset(&param, 0, sizeof(tGATT_DISC_PARAM));
+
+    if (disc_type == GATT_DISC_SRVC_ALL || disc_type == GATT_DISC_SRVC_BY_UUID)
+    {
+        param.s_handle = 1;
+        param.e_handle = 0xFFFF;
+    }
+    else
+    {
+        if (disc_type == GATT_DISC_CHAR_DSCPT)
+            is_service = FALSE;
+
+        bta_gattc_get_disc_range(p_server_cb, &param.s_handle, &param.e_handle, is_service);
+
+        if (param.s_handle > param.e_handle)
+        {
+            return GATT_ERROR;
+        }
+    }
+    return GATTC_Discover (conn_id, disc_type, &param);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_start_disc_include_srvc
+**
+** Description      Start discovery for included service
+**
+** Returns          status of the operation.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS bta_gattc_start_disc_include_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
+{
+    return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_INC_SRVC);
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_start_disc_char
+**
+** Description      Start discovery for characteristic
+**
+** Returns          status of the operation.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS bta_gattc_start_disc_char(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
+{
+    p_srvc_cb->total_char = 0;
+
+    return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR);
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_start_disc_char_dscp
+**
+** Description      Start discovery for characteristic descriptor
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gattc_start_disc_char_dscp(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
+{
+    APPL_TRACE_DEBUG("starting discover characteristics descriptor");
+
+    if (bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR_DSCPT) != 0)
+        bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_explore_srvc
+**
+** Description      process the service discovery complete event
+**
+** Returns          status
+**
+*******************************************************************************/
+static void bta_gattc_explore_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
+{
+    tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx;
+    tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+
+    APPL_TRACE_DEBUG("Start service discovery: srvc_idx = %d", p_srvc_cb->cur_srvc_idx);
+
+    p_srvc_cb->cur_char_idx = p_srvc_cb->next_avail_idx = p_srvc_cb->total_srvc;
+
+    if (p_clcb == NULL)
+    {
+        APPL_TRACE_ERROR("unknown connection ID");
+        return;
+    }
+    /* start expore a service if there is service not been explored */
+    if (p_srvc_cb->cur_srvc_idx < p_srvc_cb->total_srvc)
+    {
+        /* add the first service into cache */
+        if (bta_gattc_add_srvc_to_cache (p_srvc_cb,
+                                         p_rec->s_handle,
+                                         p_rec->e_handle,
+                                         &p_rec->uuid,
+                                         p_rec->is_primary,
+                                         p_rec->srvc_inst_id) == 0)
+        {
+            /* start discovering included services */
+            bta_gattc_start_disc_include_srvc(conn_id, p_srvc_cb);
+            return;
+        }
+    }
+    /* no service found at all, the end of server discovery*/
+    LOG_WARN("%s no more services found", __func__);
+
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+    bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache);
+#endif
+    /* save cache to NV */
+    p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE;
+    bta_gattc_co_cache_open(p_srvc_cb->server_bda, BTA_GATTC_CI_CACHE_OPEN_EVT,
+                            conn_id, TRUE);
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_incl_srvc_disc_cmpl
+**
+** Description      process the relationship discovery complete event
+**
+** Returns          status
+**
+*******************************************************************************/
+static void bta_gattc_incl_srvc_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
+{
+    p_srvc_cb->cur_char_idx = p_srvc_cb->total_srvc;
+
+    /* start discoverying characteristic */
+    bta_gattc_start_disc_char(conn_id, p_srvc_cb);
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_char_disc_cmpl
+**
+** Description      process the characteristic discovery complete event
+**
+** Returns          status
+**
+*******************************************************************************/
+static void bta_gattc_char_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
+{
+    tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;
+
+    /* if there are characteristic needs to be explored */
+    if (p_srvc_cb->total_char > 0)
+    {
+        /* add the first characteristic into cache */
+        bta_gattc_add_attr_to_cache (p_srvc_cb,
+                                     p_rec->s_handle,
+                                     &p_rec->uuid,
+                                     p_rec->property,
+                                     BTA_GATTC_ATTR_TYPE_CHAR);
+
+        /* start discoverying characteristic descriptor , if failed, disc for next char*/
+        bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
+    }
+    else /* otherwise start with next service */
+    {
+        p_srvc_cb->cur_srvc_idx ++;
+
+        bta_gattc_explore_srvc (conn_id, p_srvc_cb);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_char_dscpt_disc_cmpl
+**
+** Description      process the char descriptor discovery complete event
+**
+** Returns          status
+**
+*******************************************************************************/
+static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
+{
+    tBTA_GATTC_ATTR_REC *p_rec = NULL;
+
+    if (-- p_srvc_cb->total_char > 0)
+    {
+        p_rec = p_srvc_cb->p_srvc_list + (++ p_srvc_cb->cur_char_idx);
+        /* add the next characteristic into cache */
+        bta_gattc_add_attr_to_cache (p_srvc_cb,
+                                     p_rec->s_handle,
+                                     &p_rec->uuid,
+                                     p_rec->property,
+                                     BTA_GATTC_ATTR_TYPE_CHAR);
+
+        /* start discoverying next characteristic for char descriptor */
+        bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
+    }
+    else
+    /* all characteristic has been explored, start with next service if any */
+    {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+        APPL_TRACE_ERROR("all char has been explored");
+#endif
+        p_srvc_cb->cur_srvc_idx ++;
+        bta_gattc_explore_srvc (conn_id, p_srvc_cb);
+    }
+
+}
+static BOOLEAN bta_gattc_srvc_in_list(tBTA_GATTC_SERV *p_srvc_cb, UINT16 s_handle,
+                                      UINT16 e_handle, tBT_UUID uuid)
+{
+    tBTA_GATTC_ATTR_REC *p_rec = NULL;
+    UINT8   i;
+    BOOLEAN exist_srvc = FALSE;
+    UNUSED(uuid);
+
+    if (!GATT_HANDLE_IS_VALID(s_handle) || !GATT_HANDLE_IS_VALID(e_handle))
+    {
+        APPL_TRACE_ERROR("invalid included service handle: [0x%04x ~ 0x%04x]", s_handle, e_handle);
+        exist_srvc = TRUE;
+    }
+    else
+    {
+        for (i = 0; i < p_srvc_cb->next_avail_idx; i ++)
+        {
+            p_rec = p_srvc_cb->p_srvc_list + i;
+
+            /* a new service should not have any overlap with other service handle range */
+            if (p_rec->s_handle == s_handle || p_rec->e_handle == e_handle)
+            {
+                exist_srvc = TRUE;
+                break;
+            }
+        }
+    }
+    return exist_srvc;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_add_srvc_to_list
+**
+** Description      Add a service into explore pending list
+**
+** Returns          status
+**
+*******************************************************************************/
+static tBTA_GATT_STATUS bta_gattc_add_srvc_to_list(tBTA_GATTC_SERV *p_srvc_cb,
+                                                   UINT16 s_handle, UINT16 e_handle,
+                                                   tBT_UUID uuid, BOOLEAN is_primary)
+{
+    tBTA_GATTC_ATTR_REC *p_rec = NULL;
+    tBTA_GATT_STATUS    status = BTA_GATT_OK;
+
+    if (p_srvc_cb->p_srvc_list && p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR)
+    {
+        p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;
+
+        APPL_TRACE_DEBUG("%s handle=%d, service type=0x%04x",
+                            __func__, s_handle, uuid.uu.uuid16);
+
+        p_rec->s_handle     = s_handle;
+        p_rec->e_handle     = e_handle;
+        p_rec->is_primary   = is_primary;
+        p_rec->srvc_inst_id = bta_gattc_get_srvc_inst_id(p_srvc_cb, uuid);
+        memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID));
+
+        p_srvc_cb->total_srvc ++;
+        p_srvc_cb->next_avail_idx ++;
+    }
+    else
+    {   /* allocate bigger buffer ?? */
+        status = GATT_DB_FULL;
+
+        APPL_TRACE_ERROR("service not added, no resources or wrong state");
+    }
+    return status;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_add_char_to_list
+**
+** Description      Add a characteristic into explore pending list
+**
+** Returns          status
+**
+*******************************************************************************/
+static tBTA_GATT_STATUS bta_gattc_add_char_to_list(tBTA_GATTC_SERV *p_srvc_cb,
+                                                   UINT16 decl_handle, UINT16 value_handle,
+                                                   tBT_UUID uuid, UINT8 property)
+{
+    tBTA_GATTC_ATTR_REC *p_rec = NULL;
+    tBTA_GATT_STATUS    status = BTA_GATT_OK;
+
+    if (p_srvc_cb->p_srvc_list == NULL)
+    {
+        APPL_TRACE_ERROR("No service available, unexpected char discovery result");
+        status = BTA_GATT_INTERNAL_ERROR;
+    }
+    else if (p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR)
+    {
+
+        p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;
+
+        p_srvc_cb->total_char ++;
+
+        p_rec->s_handle = value_handle;
+        p_rec->property = property;
+        p_rec->e_handle = (p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx)->e_handle;
+        memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID));
+
+        /* update the endind handle of pervious characteristic if available */
+        if (p_srvc_cb->total_char > 1)
+        {
+            p_rec -= 1;
+            p_rec->e_handle = decl_handle - 1;
+        }
+        p_srvc_cb->next_avail_idx ++;
+    }
+    else
+    {
+        APPL_TRACE_ERROR("char not added, no resources");
+        /* allocate bigger buffer ?? */
+        status = BTA_GATT_DB_FULL;
+    }
+    return status;
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_sdp_callback
+**
+** Description      Process the discovery result from sdp
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_sdp_callback (UINT16 sdp_status)
+{
+    tSDP_DISC_REC       *p_sdp_rec = NULL;
+    tBT_UUID            service_uuid;
+    tSDP_PROTOCOL_ELEM  pe;
+    UINT16              start_handle = 0, end_handle = 0;
+    tBTA_GATTC_SERV     *p_srvc_cb = bta_gattc_find_scb_by_cid(bta_gattc_cb.sdp_conn_id);
+
+    if(((sdp_status == SDP_SUCCESS) || (sdp_status == SDP_DB_FULL)) && p_srvc_cb != NULL)
+    {
+        do
+        {
+            /* find a service record, report it */
+            p_sdp_rec = SDP_FindServiceInDb(bta_gattc_cb.p_sdp_db,
+                                            0, p_sdp_rec);
+            if (p_sdp_rec)
+            {
+                if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid))
+                {
+
+                    if (SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_ATT, &pe))
+                    {
+                        start_handle    = (UINT16) pe.params[0];
+                        end_handle      = (UINT16) pe.params[1];
+
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+                        APPL_TRACE_EVENT("Found ATT service [0x%04x] handle[0x%04x ~ 0x%04x]",
+                                        service_uuid.uu.uuid16, start_handle, end_handle);
+#endif
+
+                        if (GATT_HANDLE_IS_VALID(start_handle) && GATT_HANDLE_IS_VALID(end_handle)&&
+                            p_srvc_cb != NULL)
+                        {
+                            /* discover services result, add services into a service list */
+                            bta_gattc_add_srvc_to_list(p_srvc_cb,
+                                                       start_handle,
+                                                       end_handle,
+                                                       service_uuid,
+                                                       TRUE);
+                        }
+                        else
+                        {
+                            APPL_TRACE_ERROR("invalid start_handle = %d end_handle = %d",
+                                                start_handle, end_handle);
+                        }
+                }
+
+
+                }
+            }
+        } while (p_sdp_rec);
+    }
+
+    if ( p_srvc_cb != NULL)
+        /* start discover primary service */
+        bta_gattc_explore_srvc(bta_gattc_cb.sdp_conn_id, p_srvc_cb);
+    else
+    {
+        APPL_TRACE_ERROR("GATT service discovery is done on unknown connection");
+    }
+
+    GKI_freebuf(bta_gattc_cb.p_sdp_db);
+    bta_gattc_cb.p_sdp_db  = NULL;
+    bta_gattc_cb.sdp_conn_id = 0;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_sdp_service_disc
+**
+** Description      Start DSP Service Discovert
+**
+** Returns          void
+**
+*******************************************************************************/
+static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb)
+{
+    tSDP_UUID       uuid;
+    UINT16          num_attrs = 2;
+    UINT16          attr_list[2];
+    tBTA_GATT_STATUS    status = BTA_GATT_ERROR;
+
+    memset (&uuid, 0, sizeof(tSDP_UUID));
+
+    uuid.len = LEN_UUID_16;
+    uuid.uu.uuid16 = UUID_PROTOCOL_ATT;
+
+     if((bta_gattc_cb.p_sdp_db = (tSDP_DISCOVERY_DB *)GKI_getbuf(BTA_GATT_SDP_DB_SIZE)) != NULL)
+    {
+        attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
+        attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
+
+        SDP_InitDiscoveryDb (bta_gattc_cb.p_sdp_db, BTA_GATT_SDP_DB_SIZE, 1,
+                             &uuid, num_attrs, attr_list);
+
+        if(!SDP_ServiceSearchAttributeRequest (p_server_cb->server_bda,
+                                              bta_gattc_cb.p_sdp_db, &bta_gattc_sdp_callback))
+        {
+            GKI_freebuf(bta_gattc_cb.p_sdp_db);
+            bta_gattc_cb.p_sdp_db = NULL;
+        }
+        else
+        {
+            bta_gattc_cb.sdp_conn_id = conn_id;
+            status = BTA_GATT_OK;
+        }
+     }
+     return status;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_disc_res_cback
+**                  bta_gattc_disc_cmpl_cback
+**
+** Description      callback functions to GATT client stack.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES *p_data)
+{
+    tBTA_GATTC_SERV * p_srvc_cb = NULL;
+    BOOLEAN          pri_srvc;
+    tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+
+    p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
+
+    if (p_srvc_cb != NULL && p_clcb != NULL && p_clcb->state == BTA_GATTC_DISCOVER_ST)
+    {
+        switch (disc_type)
+        {
+            case GATT_DISC_SRVC_ALL:
+                /* discover services result, add services into a service list */
+                bta_gattc_add_srvc_to_list(p_srvc_cb,
+                                           p_data->handle,
+                                           p_data->value.group_value.e_handle,
+                                           p_data->value.group_value.service_type,
+                                           TRUE);
+
+                break;
+            case GATT_DISC_SRVC_BY_UUID:
+                bta_gattc_add_srvc_to_list(p_srvc_cb,
+                                           p_data->handle,
+                                           p_data->value.group_value.e_handle,
+                                           p_data->value.group_value.service_type,
+                                           TRUE);
+                break;
+
+            case GATT_DISC_INC_SRVC:
+                /* add included service into service list if it's secondary or it never showed up
+                   in the primary service search */
+                pri_srvc = bta_gattc_srvc_in_list(p_srvc_cb,
+                                                  p_data->value.incl_service.s_handle,
+                                                  p_data->value.incl_service.e_handle,
+                                                  p_data->value.incl_service.service_type);
+
+                if (!pri_srvc)
+                    bta_gattc_add_srvc_to_list(p_srvc_cb,
+                                               p_data->value.incl_service.s_handle,
+                                               p_data->value.incl_service.e_handle,
+                                               p_data->value.incl_service.service_type,
+                                               FALSE);
+                /* add into database */
+                bta_gattc_add_attr_to_cache(p_srvc_cb,
+                                            p_data->handle,
+                                            &p_data->value.incl_service.service_type,
+                                            pri_srvc,
+                                            BTA_GATTC_ATTR_TYPE_INCL_SRVC);
+                break;
+
+            case GATT_DISC_CHAR:
+                /* add char value into database */
+                bta_gattc_add_char_to_list(p_srvc_cb,
+                                           p_data->handle,
+                                           p_data->value.dclr_value.val_handle,
+                                           p_data->value.dclr_value.char_uuid,
+                                           p_data->value.dclr_value.char_prop);
+                break;
+
+            case GATT_DISC_CHAR_DSCPT:
+                bta_gattc_add_attr_to_cache(p_srvc_cb, p_data->handle, &p_data->type, 0,
+                                            BTA_GATTC_ATTR_TYPE_CHAR_DESCR);
+                break;
+        }
+    }
+}
+void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status)
+{
+    tBTA_GATTC_SERV * p_srvc_cb;
+    tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+
+    if ( p_clcb && (status != GATT_SUCCESS || p_clcb->status != GATT_SUCCESS) )
+    {
+        if (p_clcb->status == GATT_SUCCESS)
+            p_clcb->status = status;
+        bta_gattc_sm_execute(p_clcb, BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
+        return;
+    }
+    p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
+
+    if (p_srvc_cb != NULL)
+    {
+        switch (disc_type)
+        {
+            case GATT_DISC_SRVC_ALL:
+            case GATT_DISC_SRVC_BY_UUID:
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+                bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx);
+#endif
+                bta_gattc_explore_srvc(conn_id, p_srvc_cb);
+                break;
+
+            case GATT_DISC_INC_SRVC:
+                bta_gattc_incl_srvc_disc_cmpl(conn_id, p_srvc_cb);
+
+                break;
+
+            case GATT_DISC_CHAR:
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+                bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx);
+#endif
+                bta_gattc_char_disc_cmpl(conn_id, p_srvc_cb);
+                break;
+
+            case GATT_DISC_CHAR_DSCPT:
+                bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
+                break;
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_id2handle
+**
+** Description      map GATT ID to handle in a given cache.
+**
+** Returns          the handle mapped. 0 if not found.
+**
+*******************************************************************************/
+UINT16 bta_gattc_id2handle(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_SRVC_ID *p_service_id,
+                           tBTA_GATT_ID *p_char_id, tBTA_GATT_ID *p_descr_uuid)
+{
+    tBTA_GATTC_CACHE    *p_cache = p_srcb->p_srvc_cache;
+    tBTA_GATTC_CACHE_ATTR   *p_attr;
+    UINT8       j;
+    UINT16      handle = 0;
+    tBT_UUID    attr_uuid;
+    BOOLEAN     char_map = FALSE, done = FALSE;
+
+    while (p_service_id && p_cache && !done)
+    {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+        APPL_TRACE_DEBUG("Service: handle[%d] uuid[0x%04x] inst[%d]",
+                          p_cache->s_handle, p_cache->service_uuid.id.uuid.uu.uuid16,
+                          p_cache->service_uuid.id.inst_id);
+#endif
+        p_attr = p_cache->p_attr;
+
+        if (bta_gattc_srvcid_compare(p_service_id, &p_cache->service_uuid))
+        {
+            for (j = 0; p_attr; j ++)
+            {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+                APPL_TRACE_DEBUG("\t Attr[0x%04x] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
+                                  j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16,
+                                    p_attr->inst_id, p_attr->attr_type);
+#endif
+                bta_gattc_pack_attr_uuid(p_attr, &attr_uuid);
+
+                if (bta_gattc_uuid_compare(&p_char_id->uuid, &attr_uuid, TRUE) &&
+                    p_char_id->inst_id == p_attr->inst_id)
+                {
+                    if (p_descr_uuid == NULL)
+                    {
+                        handle = p_attr->attr_handle;
+                        done = TRUE;
+                        break;
+                    }
+                    else
+                    {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+                        APPL_TRACE_DEBUG("found matching characteristic for the descriptor");
+#endif
+                        char_map = TRUE;
+                    }
+                }
+                else if (char_map == TRUE)
+                {
+                    if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
+                    {
+
+                        if (p_descr_uuid != NULL &&
+                            bta_gattc_uuid_compare(&p_descr_uuid->uuid, &attr_uuid, TRUE) &&
+                            p_descr_uuid->inst_id == p_attr->inst_id)
+                        {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+                            APPL_TRACE_DEBUG("found descriptor!!");
+#endif
+                            handle = p_attr->attr_handle;
+                            done = TRUE;
+                            break;
+                        }
+                        else
+                        {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+                            APPL_TRACE_DEBUG("descriptor UUID not matching");
+#endif
+                        }
+                    }
+                    else /* another char */
+                    {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+                       APPL_TRACE_DEBUG("no matching descptr found!!start of next characteristic");
+#endif
+                        char_map = FALSE;
+                        done = TRUE;
+                        break;
+                    }
+                }
+                p_attr = p_attr->p_next;
+            }
+        }
+        p_cache = p_cache->p_next;
+    }
+
+    return handle;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_handle2id
+**
+** Description      map a handle to GATT ID in a given cache.
+**
+** Returns          FALSE if map can not be found.
+**
+*******************************************************************************/
+
+BOOLEAN bta_gattc_handle2id(tBTA_GATTC_SERV *p_srcb, UINT16 handle, tBTA_GATT_SRVC_ID *p_service_id,
+                            tBTA_GATT_ID *p_char_id, tBTA_GATT_ID *p_descr_type)
+{
+    tBTA_GATTC_CACHE    *p_cache = p_srcb->p_srvc_cache;
+    tBTA_GATTC_CACHE_ATTR   *p_attr, *p_char = NULL;
+    UINT8       j;
+
+    memset(p_service_id, 0, sizeof(tBTA_GATT_SRVC_ID));
+    memset(p_char_id, 0, sizeof(tBTA_GATT_ID));
+    memset(p_descr_type, 0, sizeof(tBTA_GATT_ID));
+
+    while (p_cache)
+    {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+        APPL_TRACE_DEBUG("Service: handle[%d] uuid[0x%04x] inst[%d]",
+                          p_cache->s_handle, p_cache->service_uuid.id.uuid.uu.uuid16,
+                          p_cache->service_uuid.id.inst_id);
+#endif
+        /* a service found */
+        if (p_cache->s_handle == handle)
+        {
+            memcpy(p_service_id, &p_cache->service_uuid, sizeof(tBTA_GATT_SRVC_ID));
+
+            return TRUE;
+        }
+        else /* start looking for attributes within the service */
+        {
+            p_attr = p_cache->p_attr;
+
+            for (j = 0; p_attr; j ++)
+            {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+                APPL_TRACE_DEBUG("\t Attr[0x%04x] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
+                                  j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16,
+                                  p_attr->inst_id, p_attr->attr_type);
+#endif
+                if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR)
+                    p_char = p_attr;
+
+                if (handle == p_attr->attr_handle)
+                {
+                    memcpy(p_service_id, &p_cache->service_uuid, sizeof(tBTA_GATT_SRVC_ID));
+
+                    if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
+                    {
+                        bta_gattc_pack_attr_uuid(p_attr, &p_descr_type->uuid);
+                        p_descr_type->inst_id = p_attr->inst_id;
+
+                        if (p_char != NULL)
+                        {
+                            bta_gattc_pack_attr_uuid(p_char, &p_char_id->uuid);
+                            p_char_id->inst_id = p_char->inst_id;
+                        }
+                        else
+                        {
+                            APPL_TRACE_ERROR("descptr does not belong to any chracteristic");
+                        }
+                    }
+                    else
+                    /* is a characterisitc value or included service */
+                    {
+                        bta_gattc_pack_attr_uuid(p_attr, &p_char_id->uuid);
+                        p_char_id->inst_id =p_attr->inst_id;
+                    }
+                    return TRUE;
+                }
+                p_attr = p_attr->p_next;
+            }
+        }
+        p_cache = p_cache->p_next;
+    }
+
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_search_service
+**
+** Description      search local cache for matching service record.
+**
+** Returns          FALSE if map can not be found.
+**
+*******************************************************************************/
+void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID *p_uuid)
+{
+    tBTA_GATTC_SERV     *p_srcb = p_clcb->p_srcb;
+    tBTA_GATTC_CACHE    *p_cache = p_srcb->p_srvc_cache;
+    tBTA_GATTC          cb_data;
+
+    while (p_cache)
+    {
+        if (bta_gattc_uuid_compare(p_uuid, &p_cache->service_uuid.id.uuid, FALSE))
+        {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+            APPL_TRACE_DEBUG("found service [0x%04x], inst[%d] handle [%d]",
+                              p_cache->service_uuid.id.uuid.uu.uuid16,
+                              p_cache->service_uuid.id.inst_id,
+                              p_cache->s_handle);
+#endif
+            if (p_clcb->p_rcb->p_cback)
+            {
+                memset(&cb_data, 0, sizeof(tBTA_GATTC));
+
+                cb_data.srvc_res.conn_id = p_clcb->bta_conn_id;
+                memcpy(&cb_data.srvc_res.service_uuid, &p_cache->service_uuid,
+                        sizeof(tBTA_GATT_SRVC_ID));
+
+                (* p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_RES_EVT, &cb_data);
+            }
+        }
+        p_cache = p_cache->p_next;
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_find_record
+**
+** Description      search local cache for matching attribute record.
+**
+** Parameter        p_result: output parameter to store the characteristic/
+**                            included service GATT ID.
+**
+** Returns          GATT_ERROR is no recording found. BTA_GATT_OK if record found.
+**
+*******************************************************************************/
+static tBTA_GATT_STATUS bta_gattc_find_record(tBTA_GATTC_SERV *p_srcb,
+                                              tBTA_GATTC_ATTR_TYPE attr_type,
+                                              tBTA_GATT_SRVC_ID *p_service_id,
+                                              tBTA_GATT_ID  *p_start_rec,
+                                              tBT_UUID      * p_uuid_cond,
+                                              tBTA_GATT_ID  *p_result,
+                                              void *p_param)
+{
+    tBTA_GATTC_CACHE    *p_cache = p_srcb->p_srvc_cache;
+    tBTA_GATT_STATUS    status = BTA_GATT_ERROR;
+    UINT8               i, j;
+    tBTA_GATTC_CACHE_ATTR   *p_attr;
+    BOOLEAN             char_found = FALSE, descr_found = FALSE;
+    tBTA_GATT_ID        *p_descr_id = (tBTA_GATT_ID *)p_param;;
+
+    for (i = 0; p_cache && status != BTA_GATT_OK; i ++)
+    {
+        if (bta_gattc_srvcid_compare(p_service_id, &p_cache->service_uuid))
+        {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+            APPL_TRACE_DEBUG("found matching service [0x%04x], inst[%d]",
+                              p_cache->service_uuid.id.uuid.uu.uuid16,
+                              p_cache->service_uuid.id.inst_id);
+#endif
+            p_attr = p_cache->p_attr;
+
+            for (j = 0; p_attr; j ++)
+            {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+                APPL_TRACE_DEBUG("\t Attr[%d] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
+                                  j + 1, p_attr->attr_handle,
+                                  p_attr->p_uuid->uuid16,
+                                  p_attr->inst_id,
+                                  p_attr->attr_type);
+#endif
+                bta_gattc_pack_attr_uuid(p_attr, &p_result->uuid);
+
+                if (p_start_rec != NULL && char_found == FALSE)
+                {
+                    /* find the starting record first */
+                    if (bta_gattc_uuid_compare(&p_start_rec->uuid, &p_result->uuid, FALSE) &&
+                        p_start_rec->inst_id  == p_attr->inst_id &&
+                        (attr_type == p_attr->attr_type ||
+                        /* find descriptor would look for characteristic first */
+                         (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR &&
+                          p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR)))
+                    {
+                        char_found = TRUE;
+                    }
+                }
+                else
+                {
+                    /* if looking for descriptor, here is the where the descrptor to be found */
+                    if (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
+                    {
+                        /* next characeteristic already, return error */
+                        if (p_attr->attr_type != BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
+                        {
+                            break;
+                        }
+                        else
+                        {
+                            /* find starting descriptor */
+                            if (p_descr_id != NULL && !descr_found)
+                            {
+                                if (bta_gattc_uuid_compare(&p_descr_id->uuid, &p_result->uuid, TRUE)
+                                    && p_descr_id->inst_id == p_attr->inst_id)
+                                {
+                                    descr_found = TRUE;
+                                }
+                            }
+                            else
+                            {
+                                /* with matching descriptor */
+                                if (bta_gattc_uuid_compare(p_uuid_cond, &p_result->uuid, FALSE))
+                                {
+                                    p_result->inst_id = p_attr->inst_id;
+                                    status = BTA_GATT_OK;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                    else
+                    {
+                        if (bta_gattc_uuid_compare(p_uuid_cond, &p_result->uuid, FALSE) &&
+                            attr_type == p_attr->attr_type)
+                        {
+
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+                            APPL_TRACE_DEBUG("found char handle mapping characteristic");
+#endif
+                            p_result->inst_id = p_attr->inst_id;
+
+                            if (p_param != NULL)
+                            {
+                                if (attr_type == BTA_GATTC_ATTR_TYPE_CHAR ||
+                                    attr_type == BTA_GATTC_ATTR_TYPE_INCL_SRVC)
+                                {
+                                    *(tBTA_GATT_CHAR_PROP *)p_param = p_attr->property;
+                                }
+                            }
+
+                            status = BTA_GATT_OK;
+                            break;
+                        }
+                    }
+                }
+                p_attr = p_attr->p_next;
+            }
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+            if (status)
+            {
+                APPL_TRACE_ERROR("In the given service, can not find matching record");
+            }
+#endif
+            break;
+        }
+
+        p_cache = p_cache->p_next;
+    }
+    return status;
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_query_cache
+**
+** Description      search local cache for matching attribute record.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_srvc_id: the service ID of which the characteristic is belonged to.
+**                  *p_start_rec: start the search from the next record
+**                                  after the one identified by *p_start_rec.
+**                  p_uuid_cond: UUID, if NULL find the first available
+**                               characteristic/included service.
+**                  p_output:   output parameter which will store the GATT ID
+**                              of the characteristic /included service found.
+**
+** Returns          BTA_GATT_ERROR is no recording found. BTA_GATT_OK if record found.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS bta_gattc_query_cache(UINT16 conn_id,
+                                       tBTA_GATTC_ATTR_TYPE query_type,
+                                       tBTA_GATT_SRVC_ID *p_srvc_id,
+                                       tBTA_GATT_ID *p_start_rec,
+                                       tBT_UUID *p_uuid_cond,
+                                       tBTA_GATT_ID *p_output,
+                                       void *p_param)
+{
+    tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+    tBTA_GATT_STATUS status = BTA_GATT_ILLEGAL_PARAMETER;
+
+    if (p_clcb != NULL )
+    {
+        if (p_clcb->state == BTA_GATTC_CONN_ST)
+        {
+            if (p_clcb->p_srcb &&
+                !p_clcb->p_srcb->p_srvc_list && /* no active discovery */
+                p_clcb->p_srcb->p_srvc_cache)
+            {
+                status = bta_gattc_find_record(p_clcb->p_srcb,
+                                               query_type,
+                                               p_srvc_id,
+                                               p_start_rec,
+                                               p_uuid_cond,
+                                               p_output,
+                                               p_param);
+            }
+            else
+            {
+                status = BTA_GATT_ERROR;
+                APPL_TRACE_ERROR("No server cache available");
+            }
+        }
+        else
+        {
+            APPL_TRACE_ERROR("server cache not available, CLCB state = %d", p_clcb->state);
+
+            status = (p_clcb->state == BTA_GATTC_DISCOVER_ST) ? BTA_GATT_BUSY : BTA_GATT_ERROR;
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR("Unknown conn ID: %d", conn_id);
+    }
+
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_rebuild_cache
+**
+** Description      rebuild server cache from NV cache.
+**
+** Parameters
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srvc_cb, UINT16 num_attr,
+                             tBTA_GATTC_NV_ATTR *p_attr, UINT16 attr_index)
+{
+    /* first attribute loading, initialize buffer */
+    APPL_TRACE_ERROR("bta_gattc_rebuild_cache");
+    if (attr_index == 0)
+    {
+        while (!GKI_queue_is_empty(&p_srvc_cb->cache_buffer))
+            GKI_freebuf (GKI_dequeue (&p_srvc_cb->cache_buffer));
+
+        if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL)
+        {
+            APPL_TRACE_ERROR("allocate cache buffer failed, no resources");
+        }
+        else
+        {
+            p_srvc_cb->p_cur_srvc = p_srvc_cb->p_srvc_cache = NULL;
+        }
+    }
+
+    while (num_attr > 0 && p_attr != NULL)
+    {
+        switch (p_attr->attr_type)
+        {
+            case BTA_GATTC_ATTR_TYPE_SRVC:
+                bta_gattc_add_srvc_to_cache(p_srvc_cb,
+                                            p_attr->s_handle,
+                                            p_attr->e_handle,
+                                            &p_attr->uuid,
+                                            p_attr->is_primary,
+                                            p_attr->id);
+                break;
+
+            case BTA_GATTC_ATTR_TYPE_CHAR:
+            case BTA_GATTC_ATTR_TYPE_CHAR_DESCR:
+            case BTA_GATTC_ATTR_TYPE_INCL_SRVC:
+                bta_gattc_add_attr_to_cache(p_srvc_cb,
+                                            p_attr->s_handle,
+                                            &p_attr->uuid,
+                                            p_attr->prop,
+                                            p_attr->attr_type);
+                break;
+        }
+        p_attr ++;
+        num_attr --;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_fill_nv_attr
+**
+** Description      fill a NV attribute entry value
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR *p_attr, UINT8 type, UINT16 s_handle,
+                            UINT16 e_handle, UINT8 id, tBT_UUID uuid, UINT8 prop,
+                            BOOLEAN is_primary)
+{
+    p_attr->s_handle    = s_handle;
+    p_attr->e_handle    = e_handle;
+    p_attr->attr_type   = type;
+    p_attr->is_primary  = is_primary;
+    p_attr->id          = id;
+    p_attr->prop        = prop;
+
+    memcpy(&p_attr->uuid, &uuid, sizeof(tBT_UUID));
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_cache_save
+**
+** Description      save the server cache into NV
+**
+** Returns          None.
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id)
+{
+    tBTA_GATTC_CACHE        *p_cur_srvc = p_srvc_cb->p_srvc_cache;
+    UINT8                   i = 0;
+    UINT16                  offset = 0;
+    tBTA_GATTC_NV_ATTR      nv_attr[BTA_GATTC_NV_LOAD_MAX];
+    tBTA_GATTC_CACHE_ATTR   *p_attr;
+    tBT_UUID                uuid;
+
+    while (p_cur_srvc && i < BTA_GATTC_NV_LOAD_MAX)
+    {
+        if (offset ++ >= p_srvc_cb->attr_index)
+        {
+            bta_gattc_fill_nv_attr(&nv_attr[i++],
+                                   BTA_GATTC_ATTR_TYPE_SRVC,
+                                   p_cur_srvc->s_handle,
+                                   p_cur_srvc->e_handle,
+                                   p_cur_srvc->service_uuid.id.inst_id,
+                                   p_cur_srvc->service_uuid.id.uuid,
+                                   0,
+                                   p_cur_srvc->service_uuid.is_primary);
+        }
+
+        p_attr = p_cur_srvc->p_attr;
+
+        for (; p_attr && i < BTA_GATTC_NV_LOAD_MAX ; offset ++, p_attr = p_attr->p_next)
+        {
+            if (offset >= p_srvc_cb->attr_index)
+            {
+                if ((uuid.len = p_attr->uuid_len) == LEN_UUID_16)
+                {
+                    uuid.uu.uuid16 = p_attr->p_uuid->uuid16;
+                }
+                else
+                {
+                    memcpy(uuid.uu.uuid128, p_attr->p_uuid->uuid128, LEN_UUID_128);
+                }
+
+                bta_gattc_fill_nv_attr(&nv_attr[i++],
+                                       p_attr->attr_type,
+                                       p_attr->attr_handle,
+                                       0,
+                                       p_attr->inst_id,
+                                       uuid,
+                                       p_attr->property,
+                                       FALSE);
+            }
+        }
+        p_cur_srvc = p_cur_srvc->p_next;
+    }
+
+    if (i > 0)
+    {
+        bta_gattc_co_cache_save(p_srvc_cb->server_bda, BTA_GATTC_CI_CACHE_SAVE_EVT, i,
+                                nv_attr, p_srvc_cb->attr_index, conn_id);
+
+        p_srvc_cb->attr_index += i;
+
+        return TRUE;
+    }
+    else
+    {
+        return FALSE;
+    }
+}
+#endif /* BTA_GATT_INCLUDED */
+

+ 140 - 0
components/bt/bluedroid/bta/gatt/bta_gattc_ci.c

@@ -0,0 +1,140 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2010-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the implementation file for the GATT call-in functions.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_gattc_ci.h"
+#include "gki.h"
+#include "utl.h"
+
+/*******************************************************************************
+**
+** Function         bta_gattc_ci_cache_open
+**
+** Description      This function sends an event to indicate server cache open
+**                  completed.
+**
+** Parameters       server_bda - server BDA of this cache.
+**                  status - BTA_GATT_OK if full buffer of data,
+**                           BTA_GATT_FAIL if an error has occurred.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_ci_cache_open(BD_ADDR server_bda, UINT16 evt, tBTA_GATT_STATUS status,
+                             UINT16 conn_id)
+{
+    tBTA_GATTC_CI_EVT  *p_evt;
+    UNUSED(server_bda);
+
+    if ((p_evt = (tBTA_GATTC_CI_EVT *) GKI_getbuf(sizeof(tBTA_GATTC_CI_EVT))) != NULL)
+    {
+        p_evt->hdr.event = evt;
+        p_evt->hdr.layer_specific = conn_id;
+
+        p_evt->status = status;
+        bta_sys_sendmsg(p_evt);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_ci_cache_load
+**
+** Description      This function sends an event to BTA indicating the phone has
+**                  load the servere cache and ready to send it to the stack.
+**
+** Parameters       server_bda - server BDA of this cache.
+**                  num_bytes_read - number of bytes read into the buffer
+**                      specified in the read callout-function.
+**                  status - BTA_GATT_OK if full buffer of data,
+**                           BTA_GATT_FAIL if an error has occurred.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_ci_cache_load(BD_ADDR server_bda, UINT16 evt, UINT16 num_attr,
+                             tBTA_GATTC_NV_ATTR *p_attr, tBTA_GATT_STATUS status,
+                             UINT16 conn_id)
+{
+    tBTA_GATTC_CI_LOAD  *p_evt;
+    UNUSED(server_bda);
+
+    if ((p_evt = (tBTA_GATTC_CI_LOAD *) GKI_getbuf(sizeof(tBTA_GATTC_CI_LOAD))) != NULL)
+    {
+        memset(p_evt, 0, sizeof(tBTA_GATTC_CI_LOAD));
+
+        p_evt->hdr.event = evt;
+        p_evt->hdr.layer_specific = conn_id;
+
+        p_evt->status    = status;
+        p_evt->num_attr  = (num_attr > BTA_GATTC_NV_LOAD_MAX) ? BTA_GATTC_NV_LOAD_MAX : num_attr;
+
+        if (p_evt->num_attr > 0 && p_attr != NULL)
+        {
+            memcpy(p_evt->attr, p_attr, p_evt->num_attr * sizeof(tBTA_GATTC_NV_ATTR));
+        }
+
+        bta_sys_sendmsg(p_evt);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_ci_cache_save
+**
+** Description      This function sends an event to BTA indicating the phone has
+**                  save the servere cache.
+**
+** Parameters       server_bda - server BDA of this cache.
+**                  evt - callin event code.
+**                  status - BTA_GATT_OK if full buffer of data,
+**                           BTA_GATT_ERROR if an error has occurred.
+*8                  conn_id - for this NV operation for.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_ci_cache_save(BD_ADDR server_bda, UINT16 evt, tBTA_GATT_STATUS status,
+                             UINT16 conn_id)
+{
+    tBTA_GATTC_CI_EVT  *p_evt;
+    UNUSED(server_bda);
+
+    if ((p_evt = (tBTA_GATTC_CI_EVT *) GKI_getbuf(sizeof(tBTA_GATTC_CI_EVT))) != NULL)
+    {
+        p_evt->hdr.event = evt;
+        p_evt->hdr.layer_specific = conn_id;
+
+        p_evt->status = status;
+        bta_sys_sendmsg(p_evt);
+    }
+}
+#endif /* BTA_GATT_INCLUDED */

+ 542 - 0
components/bt/bluedroid/bta/gatt/bta_gattc_main.c

@@ -0,0 +1,542 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This file contains the GATT client main functions and state machine.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+
+#include "bta_gattc_int.h"
+#include "gki.h"
+
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+
+/* state machine action enumeration list */
+enum
+{
+    BTA_GATTC_OPEN,
+    BTA_GATTC_OPEN_FAIL,
+    BTA_GATTC_OPEN_ERROR,
+    BTA_GATTC_CANCEL_OPEN,
+    BTA_GATTC_CANCEL_OPEN_OK,
+    BTA_GATTC_CANCEL_OPEN_ERROR,
+    BTA_GATTC_CONN,
+    BTA_GATTC_START_DISCOVER,
+    BTA_GATTC_DISC_CMPL,
+
+    BTA_GATTC_Q_CMD,
+    BTA_GATTC_CLOSE,
+    BTA_GATTC_CLOSE_FAIL,
+    BTA_GATTC_READ,
+    BTA_GATTC_WRITE,
+
+    BTA_GATTC_OP_CMPL,
+    BTA_GATTC_SEARCH,
+    BTA_GATTC_FAIL,
+    BTA_GATTC_CONFIRM,
+    BTA_GATTC_EXEC,
+    BTA_GATTC_READ_MULTI,
+    BTA_GATTC_CI_OPEN,
+    BTA_GATTC_CI_LOAD,
+    BTA_GATTC_CI_SAVE,
+    BTA_GATTC_CACHE_OPEN,
+    BTA_GATTC_IGNORE_OP_CMPL,
+    BTA_GATTC_DISC_CLOSE,
+    BTA_GATTC_RESTART_DISCOVER,
+    BTA_GATTC_CFG_MTU,
+
+    BTA_GATTC_IGNORE
+};
+/* type for action functions */
+typedef void (*tBTA_GATTC_ACTION)(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+
+/* action function list */
+const tBTA_GATTC_ACTION bta_gattc_action[] =
+{
+    bta_gattc_open,
+    bta_gattc_open_fail,
+    bta_gattc_open_error,
+    bta_gattc_cancel_open,
+    bta_gattc_cancel_open_ok,
+    bta_gattc_cancel_open_error,
+    bta_gattc_conn,
+    bta_gattc_start_discover,
+    bta_gattc_disc_cmpl,
+
+    bta_gattc_q_cmd,
+    bta_gattc_close,
+    bta_gattc_close_fail,
+    bta_gattc_read,
+    bta_gattc_write,
+
+    bta_gattc_op_cmpl,
+    bta_gattc_search,
+    bta_gattc_fail,
+    bta_gattc_confirm,
+    bta_gattc_execute,
+    bta_gattc_read_multi,
+    bta_gattc_ci_open,
+    bta_gattc_ci_load,
+    bta_gattc_ci_save,
+    bta_gattc_cache_open,
+    bta_gattc_ignore_op_cmpl,
+    bta_gattc_disc_close,
+    bta_gattc_restart_discover,
+    bta_gattc_cfg_mtu
+};
+
+
+/* state table information */
+#define BTA_GATTC_ACTIONS           1       /* number of actions */
+#define BTA_GATTC_NEXT_STATE          1       /* position of next state */
+#define BTA_GATTC_NUM_COLS            2       /* number of columns in state tables */
+
+/* state table for idle state */
+static const UINT8 bta_gattc_st_idle[][BTA_GATTC_NUM_COLS] =
+{
+/* Event                            Action 1                  Next state */
+/* BTA_GATTC_API_OPEN_EVT           */   {BTA_GATTC_OPEN,              BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_INT_OPEN_FAIL_EVT      */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_API_CANCEL_OPEN_EVT    */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_INT_CANCEL_OPEN_OK_EVT */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
+
+/* BTA_GATTC_API_READ_EVT           */   {BTA_GATTC_FAIL,              BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_API_WRITE_EVT          */   {BTA_GATTC_FAIL,              BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_API_EXEC_EVT           */   {BTA_GATTC_FAIL,              BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_API_CFG_MTU_EVT        */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
+
+/* BTA_GATTC_API_CLOSE_EVT          */   {BTA_GATTC_CLOSE_FAIL,        BTA_GATTC_IDLE_ST},
+
+/* BTA_GATTC_API_SEARCH_EVT         */   {BTA_GATTC_FAIL,              BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_API_CONFIRM_EVT        */   {BTA_GATTC_FAIL,              BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_API_READ_MULTI_EVT     */   {BTA_GATTC_FAIL,              BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_API_REFRESH_EVT        */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
+
+/* BTA_GATTC_INT_CONN_EVT           */   {BTA_GATTC_CONN,              BTA_GATTC_CONN_ST},
+/* BTA_GATTC_INT_DISCOVER_EVT       */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_DISCOVER_CMPL_EVT      */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_OP_CMPL_EVT            */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_INT_DISCONN_EVT       */    {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
+
+
+/* ===> for cache loading, saving   */
+/* BTA_GATTC_START_CACHE_EVT        */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_CI_CACHE_OPEN_EVT      */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_CI_CACHE_LOAD_EVT      */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_CI_CACHE_SAVE_EVT      */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST}
+};
+
+/* state table for wait for open state */
+static const UINT8 bta_gattc_st_w4_conn[][BTA_GATTC_NUM_COLS] =
+{
+/* Event                            Action 1                             Next state */
+/* BTA_GATTC_API_OPEN_EVT           */   {BTA_GATTC_OPEN,              BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_INT_OPEN_FAIL_EVT      */   {BTA_GATTC_OPEN_FAIL,         BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_API_CANCEL_OPEN_EVT    */   {BTA_GATTC_CANCEL_OPEN,       BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_INT_CANCEL_OPEN_OK_EVT */   {BTA_GATTC_CANCEL_OPEN_OK,    BTA_GATTC_IDLE_ST},
+
+/* BTA_GATTC_API_READ_EVT           */   {BTA_GATTC_FAIL,               BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_API_WRITE_EVT          */   {BTA_GATTC_FAIL,               BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_API_EXEC_EVT           */   {BTA_GATTC_FAIL,               BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_API_CFG_MTU_EVT        */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
+
+/* BTA_GATTC_API_CLOSE_EVT          */   {BTA_GATTC_CANCEL_OPEN,         BTA_GATTC_W4_CONN_ST},
+
+/* BTA_GATTC_API_SEARCH_EVT         */   {BTA_GATTC_FAIL,               BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_API_CONFIRM_EVT        */   {BTA_GATTC_FAIL,               BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_API_READ_MULTI_EVT     */   {BTA_GATTC_FAIL,               BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_API_REFRESH_EVT        */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
+
+/* BTA_GATTC_INT_CONN_EVT           */   {BTA_GATTC_CONN,               BTA_GATTC_CONN_ST},
+/* BTA_GATTC_INT_DISCOVER_EVT       */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_DISCOVER_CMPL_EVT       */  {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_OP_CMPL_EVT            */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_INT_DISCONN_EVT      */     {BTA_GATTC_OPEN_FAIL,          BTA_GATTC_IDLE_ST},
+
+/* ===> for cache loading, saving   */
+/* BTA_GATTC_START_CACHE_EVT        */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_CI_CACHE_OPEN_EVT      */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_CI_CACHE_LOAD_EVT      */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_CI_CACHE_SAVE_EVT      */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST}
+};
+
+/* state table for open state */
+static const UINT8 bta_gattc_st_connected[][BTA_GATTC_NUM_COLS] =
+{
+/* Event                            Action 1                            Next state */
+/* BTA_GATTC_API_OPEN_EVT           */   {BTA_GATTC_OPEN,               BTA_GATTC_CONN_ST},
+/* BTA_GATTC_INT_OPEN_FAIL_EVT      */   {BTA_GATTC_IGNORE,             BTA_GATTC_CONN_ST},
+/* BTA_GATTC_API_CANCEL_OPEN_EVT    */   {BTA_GATTC_CANCEL_OPEN_ERROR, BTA_GATTC_CONN_ST},
+/* BTA_GATTC_INT_CANCEL_OPEN_OK_EVT */   {BTA_GATTC_IGNORE,            BTA_GATTC_CONN_ST},
+
+/* BTA_GATTC_API_READ_EVT           */   {BTA_GATTC_READ,               BTA_GATTC_CONN_ST},
+/* BTA_GATTC_API_WRITE_EVT          */   {BTA_GATTC_WRITE,              BTA_GATTC_CONN_ST},
+/* BTA_GATTC_API_EXEC_EVT           */   {BTA_GATTC_EXEC,               BTA_GATTC_CONN_ST},
+/* BTA_GATTC_API_CFG_MTU_EVT        */   {BTA_GATTC_CFG_MTU,            BTA_GATTC_CONN_ST},
+
+/* BTA_GATTC_API_CLOSE_EVT          */   {BTA_GATTC_CLOSE,              BTA_GATTC_IDLE_ST},
+
+/* BTA_GATTC_API_SEARCH_EVT         */   {BTA_GATTC_SEARCH,             BTA_GATTC_CONN_ST},
+/* BTA_GATTC_API_CONFIRM_EVT        */   {BTA_GATTC_CONFIRM,            BTA_GATTC_CONN_ST},
+/* BTA_GATTC_API_READ_MULTI_EVT     */   {BTA_GATTC_READ_MULTI,         BTA_GATTC_CONN_ST},
+/* BTA_GATTC_API_REFRESH_EVT        */   {BTA_GATTC_IGNORE,             BTA_GATTC_CONN_ST},
+
+/* BTA_GATTC_INT_CONN_EVT           */   {BTA_GATTC_IGNORE,             BTA_GATTC_CONN_ST},
+/* BTA_GATTC_INT_DISCOVER_EVT       */   {BTA_GATTC_START_DISCOVER,     BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_DISCOVER_CMPL_EVT       */  {BTA_GATTC_IGNORE,             BTA_GATTC_CONN_ST},
+/* BTA_GATTC_OP_CMPL_EVT            */   {BTA_GATTC_OP_CMPL,            BTA_GATTC_CONN_ST},
+
+/* BTA_GATTC_INT_DISCONN_EVT        */   {BTA_GATTC_CLOSE,              BTA_GATTC_IDLE_ST},
+
+/* ===> for cache loading, saving   */
+/* BTA_GATTC_START_CACHE_EVT        */   {BTA_GATTC_CACHE_OPEN,         BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_CI_CACHE_OPEN_EVT      */   {BTA_GATTC_IGNORE,             BTA_GATTC_CONN_ST},
+/* BTA_GATTC_CI_CACHE_LOAD_EVT      */   {BTA_GATTC_IGNORE,             BTA_GATTC_CONN_ST},
+/* BTA_GATTC_CI_CACHE_SAVE_EVT      */   {BTA_GATTC_IGNORE,             BTA_GATTC_CONN_ST}
+};
+
+/* state table for discover state */
+static const UINT8 bta_gattc_st_discover[][BTA_GATTC_NUM_COLS] =
+{
+/* Event                            Action 1                            Next state */
+/* BTA_GATTC_API_OPEN_EVT           */   {BTA_GATTC_OPEN,               BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_INT_OPEN_FAIL_EVT      */   {BTA_GATTC_IGNORE,             BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_API_CANCEL_OPEN_EVT    */   {BTA_GATTC_CANCEL_OPEN_ERROR,  BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_INT_CANCEL_OPEN_OK_EVT */   {BTA_GATTC_FAIL,               BTA_GATTC_DISCOVER_ST},
+
+/* BTA_GATTC_API_READ_EVT           */   {BTA_GATTC_Q_CMD,              BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_API_WRITE_EVT          */   {BTA_GATTC_Q_CMD,              BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_API_EXEC_EVT           */   {BTA_GATTC_Q_CMD,              BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_API_CFG_MTU_EVT        */   {BTA_GATTC_Q_CMD,              BTA_GATTC_DISCOVER_ST},
+
+/* BTA_GATTC_API_CLOSE_EVT          */   {BTA_GATTC_DISC_CLOSE,         BTA_GATTC_DISCOVER_ST},
+
+/* BTA_GATTC_API_SEARCH_EVT         */   {BTA_GATTC_Q_CMD,              BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_API_CONFIRM_EVT        */   {BTA_GATTC_CONFIRM,            BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_API_READ_MULTI_EVT     */   {BTA_GATTC_Q_CMD,              BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_API_REFRESH_EVT        */   {BTA_GATTC_IGNORE,             BTA_GATTC_DISCOVER_ST},
+
+/* BTA_GATTC_INT_CONN_EVT           */   {BTA_GATTC_CONN,               BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_INT_DISCOVER_EVT       */   {BTA_GATTC_RESTART_DISCOVER,   BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_DISCOVER_CMPL_EVT      */   {BTA_GATTC_DISC_CMPL,          BTA_GATTC_CONN_ST},
+/* BTA_GATTC_OP_CMPL_EVT            */   {BTA_GATTC_IGNORE_OP_CMPL,     BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_INT_DISCONN_EVT        */   {BTA_GATTC_CLOSE,              BTA_GATTC_IDLE_ST},
+
+/* ===> for cache loading, saving       */
+/* BTA_GATTC_START_CACHE_EVT        */   {BTA_GATTC_IGNORE,             BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_CI_CACHE_OPEN_EVT      */   {BTA_GATTC_CI_OPEN,            BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_CI_CACHE_LOAD_EVT      */   {BTA_GATTC_CI_LOAD,            BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_CI_CACHE_SAVE_EVT      */   {BTA_GATTC_CI_SAVE,            BTA_GATTC_DISCOVER_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_GATTC_ST_TBL)[BTA_GATTC_NUM_COLS];
+
+/* state table */
+const tBTA_GATTC_ST_TBL bta_gattc_st_tbl[] =
+{
+    bta_gattc_st_idle,
+    bta_gattc_st_w4_conn,
+    bta_gattc_st_connected,
+    bta_gattc_st_discover
+};
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* GATTC control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_GATTC_CB  bta_gattc_cb;
+#endif
+
+#if BTA_GATT_DEBUG == TRUE
+static char *gattc_evt_code(tBTA_GATTC_INT_EVT evt_code);
+static char *gattc_state_code(tBTA_GATTC_STATE state_code);
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_gattc_sm_execute
+**
+** Description      State machine event handling function for GATTC
+**
+**
+** Returns          BOOLEAN  : TRUE if queued client request buffer can be immediately released
+**                                        else FALSE
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_sm_execute(tBTA_GATTC_CLCB *p_clcb, UINT16 event, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATTC_ST_TBL     state_table;
+    UINT8               action;
+    int                 i;
+    BOOLEAN             rt = TRUE;
+#if BTA_GATT_DEBUG == TRUE
+    tBTA_GATTC_STATE in_state = p_clcb->state;
+    UINT16         in_event = event;
+    APPL_TRACE_DEBUG("bta_gattc_sm_execute: State 0x%02x [%s], Event 0x%x[%s]", in_state,
+                      gattc_state_code(in_state),
+                      in_event,
+                      gattc_evt_code(in_event));
+#endif
+
+
+    /* look up the state table for the current state */
+    state_table = bta_gattc_st_tbl[p_clcb->state];
+
+    event &= 0x00FF;
+
+    /* set next state */
+    p_clcb->state = state_table[event][BTA_GATTC_NEXT_STATE];
+
+    /* execute action functions */
+    for (i = 0; i < BTA_GATTC_ACTIONS; i++)
+    {
+        if ((action = state_table[event][i]) != BTA_GATTC_IGNORE)
+        {
+            (*bta_gattc_action[action])(p_clcb, p_data);
+            if (p_clcb->p_q_cmd == p_data) {
+                /* buffer is queued, don't free in the bta dispatcher.
+                 * we free it ourselves when a completion event is received.
+                 */
+                rt = FALSE;
+            }
+        }
+        else
+        {
+            break;
+        }
+    }
+
+#if BTA_GATT_DEBUG == TRUE
+    if (in_state != p_clcb->state)
+    {
+        APPL_TRACE_DEBUG("GATTC State Change: [%s] -> [%s] after Event [%s]",
+                          gattc_state_code(in_state),
+                          gattc_state_code(p_clcb->state),
+                          gattc_evt_code(in_event));
+    }
+#endif
+    return rt;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_hdl_event
+**
+** Description      GATT client main event handling function.
+**
+**
+** Returns          BOOLEAN
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg)
+{
+    tBTA_GATTC_CB *p_cb = &bta_gattc_cb;
+    tBTA_GATTC_CLCB *p_clcb = NULL;
+    tBTA_GATTC_RCB      *p_clreg;
+    BOOLEAN             rt = TRUE;
+#if BTA_GATT_DEBUG == TRUE
+    APPL_TRACE_DEBUG("bta_gattc_hdl_event: Event [%s]", gattc_evt_code(p_msg->event));
+#endif
+    switch (p_msg->event)
+    {
+        case BTA_GATTC_API_DISABLE_EVT:
+            bta_gattc_disable(p_cb);
+            break;
+
+        case BTA_GATTC_API_REG_EVT:
+            bta_gattc_register(p_cb, (tBTA_GATTC_DATA *) p_msg);
+            break;
+
+        case BTA_GATTC_INT_START_IF_EVT:
+            bta_gattc_start_if(p_cb, (tBTA_GATTC_DATA *) p_msg);
+            break;
+
+        case BTA_GATTC_API_DEREG_EVT:
+            p_clreg = bta_gattc_cl_get_regcb(((tBTA_GATTC_DATA *)p_msg)->api_dereg.client_if);
+            bta_gattc_deregister(p_cb, p_clreg);
+            break;
+
+        case BTA_GATTC_API_OPEN_EVT:
+            bta_gattc_process_api_open(p_cb, (tBTA_GATTC_DATA *) p_msg);
+            break;
+
+        case BTA_GATTC_API_CANCEL_OPEN_EVT:
+            bta_gattc_process_api_open_cancel(p_cb, (tBTA_GATTC_DATA *) p_msg);
+            break;
+
+        case BTA_GATTC_API_REFRESH_EVT:
+            bta_gattc_process_api_refresh(p_cb, (tBTA_GATTC_DATA *) p_msg);
+            break;
+
+#if BLE_INCLUDED == TRUE
+        case BTA_GATTC_API_LISTEN_EVT:
+            bta_gattc_listen(p_cb, (tBTA_GATTC_DATA *) p_msg);
+            break;
+        case BTA_GATTC_API_BROADCAST_EVT:
+            bta_gattc_broadcast(p_cb, (tBTA_GATTC_DATA *) p_msg);
+            break;
+#endif
+
+        case BTA_GATTC_ENC_CMPL_EVT:
+            bta_gattc_process_enc_cmpl(p_cb, (tBTA_GATTC_DATA *) p_msg);
+            break;
+
+        default:
+            if (p_msg->event == BTA_GATTC_INT_CONN_EVT)
+                p_clcb = bta_gattc_find_int_conn_clcb((tBTA_GATTC_DATA *) p_msg);
+            else if (p_msg->event == BTA_GATTC_INT_DISCONN_EVT)
+                p_clcb = bta_gattc_find_int_disconn_clcb((tBTA_GATTC_DATA *) p_msg);
+            else
+                p_clcb = bta_gattc_find_clcb_by_conn_id(p_msg->layer_specific);
+
+            if (p_clcb != NULL)
+            {
+                rt = bta_gattc_sm_execute(p_clcb, p_msg->event, (tBTA_GATTC_DATA *) p_msg);
+            }
+            else
+            {
+                APPL_TRACE_DEBUG("Ignore unknown conn ID: %d", p_msg->layer_specific);
+            }
+
+            break;
+    }
+
+
+    return rt;
+}
+
+
+/*****************************************************************************
+**  Debug Functions
+*****************************************************************************/
+#if BTA_GATT_DEBUG == TRUE
+
+/*******************************************************************************
+**
+** Function         gattc_evt_code
+**
+** Description
+**
+** Returns          void
+**
+*******************************************************************************/
+static char *gattc_evt_code(tBTA_GATTC_INT_EVT evt_code)
+{
+    switch (evt_code)
+    {
+        case BTA_GATTC_API_OPEN_EVT:
+            return "BTA_GATTC_API_OPEN_EVT";
+        case BTA_GATTC_INT_OPEN_FAIL_EVT:
+            return "BTA_GATTC_INT_OPEN_FAIL_EVT";
+        case BTA_GATTC_API_CANCEL_OPEN_EVT:
+            return "BTA_GATTC_API_CANCEL_OPEN_EVT";
+        case BTA_GATTC_INT_CANCEL_OPEN_OK_EVT:
+            return "BTA_GATTC_INT_CANCEL_OPEN_OK_EVT";
+        case BTA_GATTC_API_READ_EVT:
+            return "BTA_GATTC_API_READ_EVT";
+        case BTA_GATTC_API_WRITE_EVT:
+            return "BTA_GATTC_API_WRITE_EVT";
+        case BTA_GATTC_API_EXEC_EVT:
+            return "BTA_GATTC_API_EXEC_EVT";
+        case BTA_GATTC_API_CLOSE_EVT:
+            return "BTA_GATTC_API_CLOSE_EVT";
+        case BTA_GATTC_API_SEARCH_EVT:
+            return "BTA_GATTC_API_SEARCH_EVT";
+        case BTA_GATTC_API_CONFIRM_EVT:
+            return "BTA_GATTC_API_CONFIRM_EVT";
+        case BTA_GATTC_API_READ_MULTI_EVT:
+            return "BTA_GATTC_API_READ_MULTI_EVT";
+        case BTA_GATTC_INT_CONN_EVT:
+            return "BTA_GATTC_INT_CONN_EVT";
+        case BTA_GATTC_INT_DISCOVER_EVT:
+            return "BTA_GATTC_INT_DISCOVER_EVT";
+        case BTA_GATTC_DISCOVER_CMPL_EVT:
+            return "BTA_GATTC_DISCOVER_CMPL_EVT";
+        case BTA_GATTC_OP_CMPL_EVT:
+            return "BTA_GATTC_OP_CMPL_EVT";
+        case BTA_GATTC_INT_DISCONN_EVT:
+            return "BTA_GATTC_INT_DISCONN_EVT";
+        case BTA_GATTC_START_CACHE_EVT:
+            return "BTA_GATTC_START_CACHE_EVT";
+        case BTA_GATTC_CI_CACHE_OPEN_EVT:
+            return "BTA_GATTC_CI_CACHE_OPEN_EVT";
+        case BTA_GATTC_CI_CACHE_LOAD_EVT:
+            return "BTA_GATTC_CI_CACHE_LOAD_EVT";
+        case BTA_GATTC_CI_CACHE_SAVE_EVT:
+            return "BTA_GATTC_CI_CACHE_SAVE_EVT";
+        case BTA_GATTC_INT_START_IF_EVT:
+            return "BTA_GATTC_INT_START_IF_EVT";
+        case BTA_GATTC_API_REG_EVT:
+            return "BTA_GATTC_API_REG_EVT";
+        case BTA_GATTC_API_DEREG_EVT:
+            return "BTA_GATTC_API_DEREG_EVT";
+        case BTA_GATTC_API_REFRESH_EVT:
+            return "BTA_GATTC_API_REFRESH_EVT";
+        case BTA_GATTC_API_LISTEN_EVT:
+            return "BTA_GATTC_API_LISTEN_EVT";
+        case BTA_GATTC_API_DISABLE_EVT:
+            return "BTA_GATTC_API_DISABLE_EVT";
+        case BTA_GATTC_API_CFG_MTU_EVT:
+            return "BTA_GATTC_API_CFG_MTU_EVT";
+        default:
+            return "unknown GATTC event code";
+    }
+}
+
+/*******************************************************************************
+**
+** Function         gattc_state_code
+**
+** Description
+**
+** Returns          void
+**
+*******************************************************************************/
+static char *gattc_state_code(tBTA_GATTC_STATE state_code)
+{
+    switch (state_code)
+    {
+        case BTA_GATTC_IDLE_ST:
+            return "GATTC_IDLE_ST";
+        case BTA_GATTC_W4_CONN_ST:
+            return "GATTC_W4_CONN_ST";
+        case BTA_GATTC_CONN_ST:
+            return "GATTC_CONN_ST";
+        case BTA_GATTC_DISCOVER_ST:
+            return "GATTC_DISCOVER_ST";
+        default:
+            return "unknown GATTC state code";
+    }
+}
+
+#endif  /* Debug Functions */
+#endif /* BTA_GATT_INCLUDED */

+ 973 - 0
components/bt/bluedroid/bta/gatt/bta_gattc_utils.c

@@ -0,0 +1,973 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This file contains the GATT client utility function.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+
+#include "bdaddr.h"
+// #include "btif/include/btif_util.h"
+#include "gki.h"
+#include "utl.h"
+#include "bta_sys.h"
+#include "bta_gattc_int.h"
+#include "l2c_api.h"
+
+#define LOG_TAG "bt_bta_gattc"
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+
+static const UINT8  base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
+    0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+static const BD_ADDR dummy_bda = {0,0,0,0,0,0};
+
+/*******************************************************************************
+**
+** Function         bta_gatt_convert_uuid16_to_uuid128
+**
+** Description      Convert a 16 bits UUID to be an standard 128 bits one.
+**
+** Returns          TRUE if two uuid match; FALSE otherwise.
+**
+*******************************************************************************/
+void bta_gatt_convert_uuid16_to_uuid128(UINT8 uuid_128[LEN_UUID_128], UINT16 uuid_16)
+{
+    UINT8   *p = &uuid_128[LEN_UUID_128 - 4];
+
+    memcpy (uuid_128, base_uuid, LEN_UUID_128);
+
+    UINT16_TO_STREAM(p, uuid_16);
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_uuid_compare
+**
+** Description      Compare two UUID to see if they are the same.
+**
+** Returns          TRUE if two uuid match; FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_uuid_compare (tBT_UUID *p_src, tBT_UUID *p_tar, BOOLEAN is_precise)
+{
+    UINT8  su[LEN_UUID_128], tu[LEN_UUID_128];
+    UINT8  *ps, *pt;
+
+    /* any of the UUID is unspecified */
+    if (p_src == 0 || p_tar == 0)
+    {
+        if (is_precise)
+            return FALSE;
+        else
+            return TRUE;
+    }
+
+    /* If both are 16-bit, we can do a simple compare */
+    if (p_src->len == 2 && p_tar->len == 2)
+    {
+        return p_src->uu.uuid16 == p_tar->uu.uuid16;
+    }
+
+    /* One or both of the UUIDs is 128-bit */
+    if (p_src->len == LEN_UUID_16)
+    {
+        /* convert a 16 bits UUID to 128 bits value */
+        bta_gatt_convert_uuid16_to_uuid128(su, p_src->uu.uuid16);
+        ps = su;
+    }
+    else
+        ps = p_src->uu.uuid128;
+
+    if (p_tar->len == LEN_UUID_16)
+    {
+        /* convert a 16 bits UUID to 128 bits value */
+        bta_gatt_convert_uuid16_to_uuid128(tu, p_tar->uu.uuid16);
+        pt = tu;
+    }
+    else
+        pt = p_tar->uu.uuid128;
+
+    return(memcmp(ps, pt, LEN_UUID_128) == 0);
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_cl_get_regcb
+**
+** Description      get registration control block by client interface.
+**
+** Returns          pointer to the regcb
+**
+*******************************************************************************/
+tBTA_GATTC_RCB * bta_gattc_cl_get_regcb(UINT8 client_if)
+{
+    UINT8   i = 0;
+    tBTA_GATTC_RCB  *p_clrcb = &bta_gattc_cb.cl_rcb[0];
+
+    for (i = 0; i < BTA_GATTC_CL_MAX; i ++, p_clrcb ++)
+    {
+        if (p_clrcb->in_use &&
+            p_clrcb->client_if == client_if)
+            return p_clrcb;
+    }
+    return NULL;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_num_reg_app
+**
+** Description      find the number of registered application.
+**
+** Returns          pointer to the regcb
+**
+*******************************************************************************/
+UINT8 bta_gattc_num_reg_app(void)
+{
+    UINT8   i = 0, j = 0;
+
+    for (i = 0; i < BTA_GATTC_CL_MAX; i ++)
+    {
+        if (bta_gattc_cb.cl_rcb[i].in_use)
+            j ++;
+    }
+    return j;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_find_clcb_by_cif
+**
+** Description      get clcb by client interface and remote bd adddress
+**
+** Returns          pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_cif (UINT8 client_if, BD_ADDR remote_bda,
+                                              tBTA_TRANSPORT transport)
+{
+    tBTA_GATTC_CLCB *p_clcb = &bta_gattc_cb.clcb[0];
+    UINT8   i;
+
+    for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++, p_clcb ++)
+    {
+        if (p_clcb->in_use &&
+            p_clcb->p_rcb->client_if == client_if &&
+            p_clcb->transport == transport &&
+            bdcmp(p_clcb->bda, remote_bda) == 0)
+            return p_clcb;
+    }
+    return NULL;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_find_clcb_by_conn_id
+**
+** Description      get clcb by connection ID
+**
+** Returns          pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_conn_id (UINT16 conn_id)
+{
+    tBTA_GATTC_CLCB *p_clcb = &bta_gattc_cb.clcb[0];
+    UINT8 i;
+
+    for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++, p_clcb ++)
+    {
+        if (p_clcb->in_use &&
+            p_clcb->bta_conn_id == conn_id)
+            return p_clcb;
+    }
+    return NULL;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_clcb_alloc
+**
+** Description      allocate CLCB
+**
+** Returns          pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CLCB * bta_gattc_clcb_alloc(tBTA_GATTC_IF client_if, BD_ADDR remote_bda,
+                                       tBTA_TRANSPORT transport)
+{
+    UINT8               i_clcb = 0;
+    tBTA_GATTC_CLCB     *p_clcb = NULL;
+
+    for (i_clcb = 0; i_clcb < BTA_GATTC_CLCB_MAX; i_clcb++)
+    {
+        if (!bta_gattc_cb.clcb[i_clcb].in_use)
+        {
+#if BTA_GATT_DEBUG == TRUE
+            APPL_TRACE_DEBUG("bta_gattc_clcb_alloc: found clcb[%d] available",i_clcb);
+#endif
+            p_clcb                  = &bta_gattc_cb.clcb[i_clcb];
+            p_clcb->in_use          = TRUE;
+            p_clcb->status          = BTA_GATT_OK;
+            p_clcb->transport       = transport;
+            bdcpy(p_clcb->bda, remote_bda);
+
+            p_clcb->p_rcb = bta_gattc_cl_get_regcb(client_if);
+
+            if ((p_clcb->p_srcb = bta_gattc_find_srcb(remote_bda)) == NULL)
+                p_clcb->p_srcb      = bta_gattc_srcb_alloc(remote_bda);
+
+            if (p_clcb->p_rcb != NULL && p_clcb->p_srcb != NULL)
+            {
+                p_clcb->p_srcb->num_clcb ++;
+                p_clcb->p_rcb->num_clcb ++;
+            }
+            else
+            {
+                /* release this clcb if clcb or srcb allocation failed */
+                p_clcb->in_use = FALSE;
+                p_clcb = NULL;
+            }
+            break;
+        }
+    }
+    return p_clcb;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_find_alloc_clcb
+**
+** Description      find or allocate CLCB if not found.
+**
+** Returns          pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CLCB *bta_gattc_find_alloc_clcb(tBTA_GATTC_IF client_if, BD_ADDR remote_bda,
+                                           tBTA_TRANSPORT transport)
+{
+    tBTA_GATTC_CLCB *p_clcb ;
+
+    if ((p_clcb = bta_gattc_find_clcb_by_cif(client_if, remote_bda, transport)) == NULL)
+    {
+        p_clcb = bta_gattc_clcb_alloc(client_if, remote_bda, transport);
+    }
+    return p_clcb;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_clcb_dealloc
+**
+** Description      Deallocte a clcb
+**
+** Returns          pointer to the clcb
+**
+*******************************************************************************/
+void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb)
+{
+    tBTA_GATTC_SERV     *p_srcb = NULL;
+
+    if (p_clcb)
+    {
+        p_srcb = p_clcb->p_srcb;
+        if (p_srcb->num_clcb)
+            p_srcb->num_clcb --;
+
+        if (p_clcb->p_rcb->num_clcb)
+            p_clcb->p_rcb->num_clcb --;
+
+        /* if the srcb is no longer needed, reset the state */
+        if ( p_srcb->num_clcb == 0)
+        {
+            p_srcb->connected = FALSE;
+            p_srcb->state = BTA_GATTC_SERV_IDLE;
+            p_srcb->mtu = 0;
+        }
+
+        utl_freebuf((void **)&p_clcb->p_q_cmd);
+
+        memset(p_clcb, 0, sizeof(tBTA_GATTC_CLCB));
+    }
+    else
+    {
+        APPL_TRACE_ERROR("bta_gattc_clcb_dealloc p_clcb=NULL");
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_find_srcb
+**
+** Description      find server cache by remote bd address currently in use
+**
+** Returns          pointer to the server cache.
+**
+*******************************************************************************/
+tBTA_GATTC_SERV * bta_gattc_find_srcb(BD_ADDR bda)
+{
+    tBTA_GATTC_SERV *p_srcb = &bta_gattc_cb.known_server[0];
+    UINT8   i;
+
+    for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_srcb ++)
+    {
+        if (p_srcb->in_use && bdcmp(p_srcb->server_bda, bda) == 0)
+            return p_srcb;
+    }
+    return NULL;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_find_srvr_cache
+**
+** Description      find server cache by remote bd address
+**
+** Returns          pointer to the server cache.
+**
+*******************************************************************************/
+tBTA_GATTC_SERV * bta_gattc_find_srvr_cache(BD_ADDR bda)
+{
+    tBTA_GATTC_SERV *p_srcb = &bta_gattc_cb.known_server[0];
+    UINT8   i;
+
+    for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_srcb ++)
+    {
+        if (bdcmp(p_srcb->server_bda, bda) == 0)
+            return p_srcb;
+    }
+    return NULL;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_find_scb_by_cid
+**
+** Description      find server control block by connection ID
+**
+** Returns          pointer to the server cache.
+**
+*******************************************************************************/
+tBTA_GATTC_SERV * bta_gattc_find_scb_by_cid (UINT16 conn_id)
+{
+    tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+
+    if (p_clcb)
+        return p_clcb->p_srcb;
+    else
+        return NULL;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_srcb_alloc
+**
+** Description      allocate server cache control block
+**
+** Returns          pointer to the server cache.
+**
+*******************************************************************************/
+tBTA_GATTC_SERV * bta_gattc_srcb_alloc(BD_ADDR bda)
+{
+    tBTA_GATTC_SERV *p_tcb = &bta_gattc_cb.known_server[0],
+                             *p_recycle = NULL;
+    BOOLEAN         found = FALSE;
+    UINT8           i;
+
+    for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_tcb ++)
+    {
+        if (!p_tcb->in_use)
+        {
+            found = TRUE;
+            break;
+        }
+        else if (!p_tcb->connected)
+        {
+            p_recycle = p_tcb;
+        }
+    }
+
+    /* if not found, try to recycle one known device */
+    if (!found && !p_recycle)
+        p_tcb = NULL;
+    else if (!found && p_recycle)
+        p_tcb = p_recycle;
+
+    if (p_tcb != NULL)
+    {
+        while (!GKI_queue_is_empty(&p_tcb->cache_buffer))
+            GKI_freebuf (GKI_dequeue (&p_tcb->cache_buffer));
+
+        utl_freebuf((void **)&p_tcb->p_srvc_list);
+        memset(p_tcb, 0 , sizeof(tBTA_GATTC_SERV));
+
+        p_tcb->in_use = TRUE;
+        bdcpy(p_tcb->server_bda, bda);
+    }
+    return p_tcb;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_enqueue
+**
+** Description      enqueue a client request in clcb.
+**
+** Returns          success or failure.
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+
+ if (p_clcb->p_q_cmd == NULL)
+ {
+     p_clcb->p_q_cmd = p_data;
+ }
+ else
+ {
+     APPL_TRACE_ERROR("already has a pending command!!");
+     /* skip the callback now. ----- need to send callback ? */
+ }
+ return (p_clcb->p_q_cmd != NULL) ? TRUE : FALSE;
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_pack_attr_uuid
+**
+** Description      pack UUID into a stream.
+**
+** Returns
+**
+*******************************************************************************/
+void bta_gattc_pack_attr_uuid(tBTA_GATTC_CACHE_ATTR   *p_attr, tBT_UUID *p_uuid)
+{
+    UINT8 *pp = (UINT8 *)p_attr->p_uuid;
+
+    memset(p_uuid, 0, sizeof(tBT_UUID));
+
+    p_uuid->len = p_attr->uuid_len;
+
+    if (p_attr->uuid_len == LEN_UUID_16)
+    {
+        STREAM_TO_UINT16(p_uuid->uu.uuid16, pp);
+    }
+    else
+    {
+        memcpy(p_uuid->uu.uuid128, pp, LEN_UUID_128);
+    }
+
+    return;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_cpygattid
+**
+** Description      copy two tBTA_GATT_ID value
+**
+** Returns
+**
+*******************************************************************************/
+void bta_gattc_cpygattid(tBTA_GATT_ID *p_des, tBTA_GATT_ID *p_src)
+{
+    memset ((void *)p_des, 0, sizeof(tBTA_GATT_ID));
+
+    p_des->inst_id = p_src->inst_id;
+
+    p_des->uuid.len = p_src->uuid.len;
+
+    if (p_des->uuid.len == LEN_UUID_16)
+    {
+        p_des->uuid.uu.uuid16 = p_src->uuid.uu.uuid16;
+    }
+    else if (p_des->uuid.len == LEN_UUID_128)
+    {
+        memcpy(p_des->uuid.uu.uuid128, p_src->uuid.uu.uuid128, LEN_UUID_128);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_gattid_compare
+**
+** Description      compare two tBTA_GATT_ID type of pointer
+**
+** Returns
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_gattid_compare(tBTA_GATT_ID *p_src, tBTA_GATT_ID *p_tar)
+{
+    if (p_src->inst_id == p_tar->inst_id &&
+        bta_gattc_uuid_compare (&p_src->uuid, &p_tar->uuid, TRUE ))
+        return TRUE;
+    else
+        return FALSE;
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_srvcid_compare
+**
+** Description      compare two tBTA_GATT_SRVC_ID type of pointer
+**
+** Returns
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_srvcid_compare(tBTA_GATT_SRVC_ID *p_src, tBTA_GATT_SRVC_ID *p_tar)
+{
+    if (p_src->is_primary == p_tar->is_primary &&
+        bta_gattc_gattid_compare (&p_src->id, &p_tar->id))
+        return TRUE;
+    else
+        return FALSE;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_charid_compare
+**
+** Description      compare two tBTA_GATTC_CHAR_ID type of pointer
+**
+** Returns
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_charid_compare(tBTA_GATTC_CHAR_ID *p_src, tBTA_GATTC_CHAR_ID *p_tar)
+{
+    if (bta_gattc_gattid_compare (&p_src->char_id, &p_tar->char_id) &&
+        bta_gattc_srvcid_compare (&p_src->srvc_id, &p_tar->srvc_id))
+        return TRUE;
+    else
+        return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_check_notif_registry
+**
+** Description      check if the service notificaition has been registered.
+**
+** Returns
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_check_notif_registry(tBTA_GATTC_RCB  *p_clreg, tBTA_GATTC_SERV *p_srcb,
+                                       tBTA_GATTC_NOTIFY  *p_notify)
+{
+    UINT8           i;
+
+    for (i = 0 ; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
+    {
+        if (p_clreg->notif_reg[i].in_use &&
+            bdcmp(p_clreg->notif_reg[i].remote_bda, p_srcb->server_bda) == 0 &&
+            bta_gattc_charid_compare (&p_clreg->notif_reg[i].char_id, &p_notify->char_id))
+        {
+            APPL_TRACE_DEBUG("Notification registered!");
+            return TRUE;
+        }
+    }
+    return FALSE;
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_clear_notif_registration
+**
+** Description      clear up the notification registration information by BD_ADDR.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_clear_notif_registration(UINT16 conn_id)
+{
+    BD_ADDR             remote_bda;
+    tBTA_GATTC_IF       gatt_if;
+    tBTA_GATTC_RCB      *p_clrcb ;
+    UINT8       i;
+    tGATT_TRANSPORT     transport;
+
+    if (GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda, &transport))
+    {
+        if ((p_clrcb = bta_gattc_cl_get_regcb(gatt_if)) != NULL)
+        {
+            for (i = 0 ; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
+            {
+                if (p_clrcb->notif_reg[i].in_use &&
+                    !bdcmp(p_clrcb->notif_reg[i].remote_bda, remote_bda))
+                    memset(&p_clrcb->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
+            }
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR("can not clear indication/notif registration for unknown app");
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_pack_cb_data
+**
+** Description      pack the data from read response into callback data structure.
+**
+** Returns
+**
+*******************************************************************************/
+tBTA_GATT_STATUS bta_gattc_pack_read_cb_data(tBTA_GATTC_SERV *p_srcb,
+                                             tBT_UUID *p_descr_uuid,
+                                             tGATT_VALUE *p_attr,
+                                             tBTA_GATT_READ_VAL *p_value)
+{
+    UINT8                   i = 0, *pp = p_attr->value;
+    tBT_UUID                uuid = {LEN_UUID_16, {GATT_UUID_CHAR_AGG_FORMAT}};
+    UINT16                  handle;
+    tBTA_GATT_STATUS        status = BTA_GATT_OK;
+
+    /* GATT_UUID_CHAR_AGG_FORMAT */
+    if (bta_gattc_uuid_compare (&uuid, p_descr_uuid, TRUE))
+    {
+        while (p_attr->len >= 2 && i < BTA_GATTC_MULTI_MAX)
+        {
+            STREAM_TO_UINT16(handle, pp);
+
+            if (bta_gattc_handle2id(p_srcb,
+                                    handle,
+                                    &p_value->aggre_value.pre_format[i].char_id.srvc_id,
+                                    &p_value->aggre_value.pre_format[i].char_id.char_id,
+                                    &p_value->aggre_value.pre_format[i].descr_id) == FALSE)
+            {
+                status = BTA_GATT_INTERNAL_ERROR;
+                APPL_TRACE_ERROR("can not map to GATT ID. handle = 0x%04x", handle);
+                break;
+            }
+            i ++;
+            p_attr->len -= 2;
+        }
+        p_value->aggre_value.num_pres_fmt = i;
+    }
+    else
+    {
+        /* all others, take as raw format */
+        p_value->unformat.len = p_attr->len;
+        p_value->unformat.p_value = p_attr->value;
+    }
+    return status;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_mark_bg_conn
+**
+** Description      mark background connection status when a bg connection is initiated
+**                  or terminated.
+**
+** Returns          TRUE if success; FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR_PTR remote_bda_ptr,
+                                BOOLEAN add, BOOLEAN is_listen)
+{
+    tBTA_GATTC_BG_TCK   *p_bg_tck = &bta_gattc_cb.bg_track[0];
+    UINT8   i = 0;
+    tBTA_GATTC_CIF_MASK  *p_cif_mask;
+
+    for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_bg_tck ++)
+    {
+        if (p_bg_tck->in_use &&
+            ((remote_bda_ptr != NULL && bdcmp(p_bg_tck->remote_bda, remote_bda_ptr) == 0) ||
+            (remote_bda_ptr == NULL && bdcmp(p_bg_tck->remote_bda, dummy_bda) == 0)))
+        {
+             p_cif_mask = is_listen ? &p_bg_tck->cif_adv_mask : &p_bg_tck->cif_mask;
+
+            if (add)
+                /* mask on the cif bit */
+                *p_cif_mask |= (1 <<(client_if - 1));
+            else
+            {
+                if (client_if != 0)
+                    *p_cif_mask &= (~(1 <<(client_if - 1)));
+                else
+                    *p_cif_mask = 0;
+            }
+            /* no BG connection for this device, make it available */
+            if (p_bg_tck->cif_mask == 0 && p_bg_tck->cif_adv_mask == 0)
+            {
+                memset(p_bg_tck, 0, sizeof(tBTA_GATTC_BG_TCK));
+            }
+            return TRUE;
+        }
+    }
+    if (!add)
+    {
+        if (remote_bda_ptr)
+        {
+	  // bdstr_t bdstr = {0};
+	    char bdstr[18] = {0};
+            APPL_TRACE_ERROR("%s unable to find the bg connection mask for: %s", __func__,
+                bdaddr_to_string((bt_bdaddr_t *)remote_bda_ptr, bdstr, sizeof(bdstr)));
+        }
+        return FALSE;
+    }
+    else /* adding a new device mask */
+    {
+        for (i = 0, p_bg_tck = &bta_gattc_cb.bg_track[0];
+             i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_bg_tck ++)
+        {
+            if (!p_bg_tck->in_use)
+            {
+                p_bg_tck->in_use = TRUE;
+                if (remote_bda_ptr)
+                    bdcpy(p_bg_tck->remote_bda, remote_bda_ptr);
+                else
+                    bdcpy(p_bg_tck->remote_bda, dummy_bda);
+
+                p_cif_mask = is_listen ? &p_bg_tck->cif_adv_mask : &p_bg_tck->cif_mask;
+
+                *p_cif_mask = (1 <<(client_if - 1));
+                return TRUE;
+            }
+        }
+        APPL_TRACE_ERROR("no available space to mark the bg connection status");
+        return FALSE;
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_check_bg_conn
+**
+** Description      check if this is a background connection background connection.
+**
+** Returns          TRUE if success; FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_check_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR remote_bda, UINT8 role)
+{
+    tBTA_GATTC_BG_TCK   *p_bg_tck = &bta_gattc_cb.bg_track[0];
+    UINT8       i = 0;
+    BOOLEAN     is_bg_conn = FALSE;
+
+    for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX && !is_bg_conn; i ++, p_bg_tck ++)
+    {
+        if (p_bg_tck->in_use &&
+            (bdcmp(p_bg_tck->remote_bda, remote_bda) == 0 ||
+             bdcmp(p_bg_tck->remote_bda, dummy_bda) == 0))
+        {
+            if (((p_bg_tck->cif_mask &(1 <<(client_if - 1))) != 0) &&
+                role == HCI_ROLE_MASTER)
+                is_bg_conn = TRUE;
+
+            if (((p_bg_tck->cif_adv_mask &(1 <<(client_if - 1))) != 0) &&
+                role == HCI_ROLE_SLAVE)
+                is_bg_conn = TRUE;
+        }
+    }
+    return is_bg_conn;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_send_open_cback
+**
+** Description      send open callback
+**
+** Returns
+**
+*******************************************************************************/
+void bta_gattc_send_open_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS status,
+                                BD_ADDR remote_bda, UINT16 conn_id,
+                                tBTA_TRANSPORT transport, UINT16 mtu)
+{
+    tBTA_GATTC      cb_data;
+
+    if (p_clreg->p_cback)
+    {
+        memset(&cb_data, 0, sizeof(tBTA_GATTC));
+
+        cb_data.open.status = status;
+        cb_data.open.client_if = p_clreg->client_if;
+        cb_data.open.conn_id = conn_id;
+        cb_data.open.mtu = mtu;
+        cb_data.open.transport = transport;
+        bdcpy(cb_data.open.remote_bda, remote_bda);
+
+        (*p_clreg->p_cback)(BTA_GATTC_OPEN_EVT, &cb_data);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_conn_alloc
+**
+** Description      allocate connection tracking spot
+**
+** Returns          pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CONN * bta_gattc_conn_alloc(BD_ADDR remote_bda)
+{
+    UINT8               i_conn = 0;
+    tBTA_GATTC_CONN     *p_conn = &bta_gattc_cb.conn_track[0];
+
+    for (i_conn = 0; i_conn < BTA_GATTC_CONN_MAX; i_conn++, p_conn ++)
+    {
+        if (!p_conn->in_use)
+        {
+#if BTA_GATT_DEBUG == TRUE
+            APPL_TRACE_DEBUG("bta_gattc_conn_alloc: found conn_track[%d] available",i_conn);
+#endif
+            p_conn->in_use          = TRUE;
+            bdcpy(p_conn->remote_bda, remote_bda);
+            return p_conn;
+        }
+    }
+    return NULL;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_conn_find
+**
+** Description      allocate connection tracking spot
+**
+** Returns          pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CONN * bta_gattc_conn_find(BD_ADDR remote_bda)
+{
+    UINT8               i_conn = 0;
+    tBTA_GATTC_CONN     *p_conn = &bta_gattc_cb.conn_track[0];
+
+    for (i_conn = 0; i_conn < BTA_GATTC_CONN_MAX; i_conn++, p_conn ++)
+    {
+        if (p_conn->in_use && bdcmp(remote_bda, p_conn->remote_bda) == 0)
+        {
+#if BTA_GATT_DEBUG == TRUE
+            APPL_TRACE_DEBUG("bta_gattc_conn_find: found conn_track[%d] matched",i_conn);
+#endif
+            return p_conn;
+        }
+    }
+    return NULL;
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_gattc_conn_find_alloc
+**
+** Description      find or allocate connection tracking spot
+**
+** Returns          pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CONN * bta_gattc_conn_find_alloc(BD_ADDR remote_bda)
+{
+    tBTA_GATTC_CONN     *p_conn = bta_gattc_conn_find (remote_bda);
+
+    if (p_conn == NULL)
+    {
+        p_conn = bta_gattc_conn_alloc(remote_bda);
+    }
+    return p_conn;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_conn_dealloc
+**
+** Description      de-allocate connection tracking spot
+**
+** Returns          pointer to the clcb
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_conn_dealloc(BD_ADDR remote_bda)
+{
+    tBTA_GATTC_CONN     *p_conn = bta_gattc_conn_find (remote_bda);
+
+    if (p_conn != NULL)
+    {
+        p_conn->in_use = FALSE;
+        memset(p_conn->remote_bda, 0, BD_ADDR_LEN);
+        return TRUE;
+    }
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_find_int_conn_clcb
+**
+** Description      try to locate a clcb when an internal connecion event arrives.
+**
+** Returns          pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CLCB * bta_gattc_find_int_conn_clcb(tBTA_GATTC_DATA *p_msg)
+{
+    tBTA_GATTC_CLCB *p_clcb = NULL;
+
+    if (p_msg->int_conn.role == HCI_ROLE_SLAVE)
+        bta_gattc_conn_find_alloc(p_msg->int_conn.remote_bda);
+
+    /* try to locate a logic channel */
+    if ((p_clcb = bta_gattc_find_clcb_by_cif(p_msg->int_conn.client_if,
+                                             p_msg->int_conn.remote_bda,
+                                             p_msg->int_conn.transport)) == NULL)
+    {
+        /* for a background connection or listening connection */
+        if (/*p_msg->int_conn.role == HCI_ROLE_SLAVE ||  */
+            bta_gattc_check_bg_conn(p_msg->int_conn.client_if,
+                                    p_msg->int_conn.remote_bda,
+                                    p_msg->int_conn.role))
+        {
+            /* allocate a new channel */
+            p_clcb = bta_gattc_clcb_alloc(p_msg->int_conn.client_if,
+                                          p_msg->int_conn.remote_bda,
+                                          p_msg->int_conn.transport);
+        }
+    }
+    return p_clcb;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_find_int_disconn_clcb
+**
+** Description      try to locate a clcb when an internal disconnect callback arrives.
+**
+** Returns          pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CLCB * bta_gattc_find_int_disconn_clcb(tBTA_GATTC_DATA *p_msg)
+{
+    tBTA_GATTC_CLCB         *p_clcb = NULL;
+
+    bta_gattc_conn_dealloc(p_msg->int_conn.remote_bda);
+    if ((p_clcb = bta_gattc_find_clcb_by_conn_id(p_msg->int_conn.hdr.layer_specific)) == NULL)
+    {
+        /* connection attempt failed, send connection callback event */
+        p_clcb = bta_gattc_find_clcb_by_cif(p_msg->int_conn.client_if,
+                                            p_msg->int_conn.remote_bda,
+                                            p_msg->int_conn.transport);
+    }
+    if (p_clcb == NULL)
+    {
+        APPL_TRACE_DEBUG(" disconnection ID: [%d] not used by BTA",
+            p_msg->int_conn.hdr.layer_specific);
+    }
+    return p_clcb;
+}
+
+#endif /* BTA_GATT_INCLUDED */

+ 992 - 0
components/bt/bluedroid/bta/gatt/bta_gatts_act.c

@@ -0,0 +1,992 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This file contains the GATT Server action functions for the state
+ *  machine.
+ *
+ ******************************************************************************/
+
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include "utl.h"
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_gatts_int.h"
+#include "bta_gatts_co.h"
+#include "btm_ble_api.h"
+// #include "btif/include/btif_debug_conn.h"
+#include <string.h>
+
+static void bta_gatts_nv_save_cback(BOOLEAN is_saved, tGATTS_HNDL_RANGE *p_hndl_range);
+static BOOLEAN bta_gatts_nv_srv_chg_cback(tGATTS_SRV_CHG_CMD cmd, tGATTS_SRV_CHG_REQ *p_req,
+                                                tGATTS_SRV_CHG_RSP *p_rsp);
+
+static void bta_gatts_conn_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
+                                      BOOLEAN connected, tGATT_DISCONN_REASON reason,
+                                      tGATT_TRANSPORT transport);
+static void bta_gatts_send_request_cback (UINT16 conn_id,
+                                          UINT32 trans_id,
+                                          tGATTS_REQ_TYPE req_type, tGATTS_DATA *p_data);
+static void bta_gatts_cong_cback (UINT16 conn_id, BOOLEAN congested);
+
+static tGATT_CBACK bta_gatts_cback =
+{
+    bta_gatts_conn_cback,
+    NULL,
+    NULL,
+    NULL,
+    bta_gatts_send_request_cback,
+    NULL,
+    bta_gatts_cong_cback
+};
+
+tGATT_APPL_INFO bta_gatts_nv_cback =
+{
+    bta_gatts_nv_save_cback,
+    bta_gatts_nv_srv_chg_cback
+};
+
+/*******************************************************************************
+**
+** Function         bta_gatts_nv_save_cback
+**
+** Description      NV save callback function.
+**
+** Parameter        is_add: true is to add a handle range; otherwise is to delete.
+** Returns          none.
+**
+*******************************************************************************/
+static void bta_gatts_nv_save_cback(BOOLEAN is_add, tGATTS_HNDL_RANGE *p_hndl_range)
+{
+    bta_gatts_co_update_handle_range(is_add, (tBTA_GATTS_HNDL_RANGE *)p_hndl_range);
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_gatts_nv_srv_chg_cback
+**
+** Description      NV save callback function.
+**
+** Parameter        is_add: true is to add a handle range; otherwise is to delete.
+** Returns          none.
+**
+*******************************************************************************/
+static BOOLEAN bta_gatts_nv_srv_chg_cback(tGATTS_SRV_CHG_CMD cmd,
+                                              tGATTS_SRV_CHG_REQ *p_req, tGATTS_SRV_CHG_RSP *p_rsp)
+{
+    return bta_gatts_co_srv_chg((tBTA_GATTS_SRV_CHG_CMD) cmd,
+                                (tBTA_GATTS_SRV_CHG_REQ *) p_req,
+                                (tBTA_GATTS_SRV_CHG_RSP *) p_rsp);
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_gatts_enable
+**
+** Description      enable BTA GATTS module.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_enable(tBTA_GATTS_CB *p_cb)
+{
+    UINT8 index=0;
+    tBTA_GATTS_HNDL_RANGE handle_range;
+
+    if (p_cb->enabled)
+    {
+        APPL_TRACE_DEBUG("GATTS already enabled.");
+    }
+    else
+    {
+        memset(p_cb, 0, sizeof(tBTA_GATTS_CB));
+
+        p_cb->enabled = TRUE;
+
+        while ( bta_gatts_co_load_handle_range(index, &handle_range))
+        {
+            GATTS_AddHandleRange((tGATTS_HNDL_RANGE *)&handle_range);
+            memset(&handle_range, 0, sizeof(tGATTS_HNDL_RANGE));
+            index++;
+        }
+
+        APPL_TRACE_DEBUG("bta_gatts_enable: num of handle range added=%d", index);
+
+        if (!GATTS_NVRegister(&bta_gatts_nv_cback))
+        {
+            APPL_TRACE_ERROR("BTA GATTS NV register failed.");
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gatts_api_disable
+**
+** Description      disable BTA GATTS module.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_api_disable(tBTA_GATTS_CB *p_cb)
+{
+    UINT8 i;
+
+    if (p_cb->enabled)
+    {
+        for (i = 0; i < BTA_GATTS_MAX_APP_NUM; i ++)
+        {
+            if (p_cb->rcb[i].in_use)
+            {
+                GATT_Deregister(p_cb->rcb[i].gatt_if);
+            }
+        }
+        memset(p_cb, 0, sizeof(tBTA_GATTS_CB));
+    }
+    else
+    {
+        APPL_TRACE_ERROR("GATTS not enabled");
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gatts_register
+**
+** Description      register an application.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_register(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg)
+{
+    tBTA_GATTS_INT_START_IF  *p_buf;
+    tBTA_GATTS               cb_data;
+    tBTA_GATT_STATUS         status = BTA_GATT_OK;
+    UINT8                    i, first_unuse = 0xff;
+
+    if (p_cb->enabled == FALSE)
+    {
+        bta_gatts_enable(p_cb);
+    }
+
+    for (i = 0; i < BTA_GATTS_MAX_APP_NUM; i ++)
+    {
+        if (p_cb->rcb[i].in_use)
+        {
+            if (bta_gatts_uuid_compare(p_cb->rcb[i].app_uuid, p_msg->api_reg.app_uuid))
+            {
+                APPL_TRACE_ERROR("application already registered.\n");
+                status = BTA_GATT_DUP_REG;
+                break;
+            }
+        }
+    }
+
+    if (status == BTA_GATT_OK)
+    {
+        for (i = 0; i < BTA_GATTS_MAX_APP_NUM; i ++)
+        {
+            if (first_unuse == 0xff && !p_cb->rcb[i].in_use)
+            {
+                first_unuse = i;
+                break;
+            }
+        }
+
+        cb_data.reg_oper.server_if = BTA_GATTS_INVALID_IF;
+// btla-specific ++
+        memcpy(&cb_data.reg_oper.uuid, &p_msg->api_reg.app_uuid, sizeof(tBT_UUID));
+// btla-specific --
+        if (first_unuse != 0xff)
+        {
+            APPL_TRACE_ERROR("register application first_unuse rcb_idx = %d", first_unuse);
+
+            p_cb->rcb[first_unuse].in_use = TRUE;
+            p_cb->rcb[first_unuse].p_cback = p_msg->api_reg.p_cback;
+            memcpy(&p_cb->rcb[first_unuse].app_uuid, &p_msg->api_reg.app_uuid, sizeof(tBT_UUID));
+            cb_data.reg_oper.server_if      =
+            p_cb->rcb[first_unuse].gatt_if  =
+            GATT_Register(&p_msg->api_reg.app_uuid, &bta_gatts_cback);
+            if ( !p_cb->rcb[first_unuse].gatt_if)
+            {
+                status = BTA_GATT_NO_RESOURCES;
+            }
+            else
+            {
+                if ((p_buf =
+                  (tBTA_GATTS_INT_START_IF *) GKI_getbuf(sizeof(tBTA_GATTS_INT_START_IF))) != NULL)
+                {
+                    p_buf->hdr.event    = BTA_GATTS_INT_START_IF_EVT;
+                    p_buf->server_if    = p_cb->rcb[first_unuse].gatt_if;
+
+                    bta_sys_sendmsg(p_buf);
+                }
+                else
+                {
+                    status = BTA_GATT_NO_RESOURCES;
+                    memset( &p_cb->rcb[first_unuse], 0 , sizeof(tBTA_GATTS_RCB));
+                }
+            }
+        }
+        else
+        {
+            status = BTA_GATT_NO_RESOURCES;
+        }
+
+    }
+    cb_data.reg_oper.status = status;
+    if (p_msg->api_reg.p_cback)
+        (*p_msg->api_reg.p_cback)(BTA_GATTS_REG_EVT, &cb_data);
+
+	LOG_ERROR("status=%x\n",status);
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_gatts_start_if
+**
+** Description      start an application interface.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_start_if(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg)
+{
+    UNUSED(p_cb);
+
+    if (bta_gatts_find_app_rcb_by_app_if(p_msg->int_start_if.server_if))
+    {
+        GATT_StartIf(p_msg->int_start_if.server_if);
+    }
+    else
+    {
+        APPL_TRACE_ERROR("Unable to start app.: Unknown interface =%d",
+            p_msg->int_start_if.server_if );
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_deregister
+**
+** Description      deregister an application.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_deregister(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg)
+{
+    tBTA_GATT_STATUS    status = BTA_GATT_ERROR;
+    tBTA_GATTS_CBACK    *p_cback = NULL;
+    UINT8               i;
+    tBTA_GATTS          cb_data;
+
+    cb_data.reg_oper.server_if = p_msg->api_dereg.server_if;
+    cb_data.reg_oper.status = status;
+
+    for (i = 0; i < BTA_GATTS_MAX_APP_NUM; i ++)
+    {
+        if (p_cb->rcb[i].in_use && p_cb->rcb[i].gatt_if == p_msg->api_dereg.server_if)
+        {
+            p_cback = p_cb->rcb[i].p_cback;
+            status = BTA_GATT_OK;
+
+            /* deregister the app */
+            GATT_Deregister(p_cb->rcb[i].gatt_if);
+
+            /* reset cb */
+            memset(&p_cb->rcb[i], 0, sizeof(tBTA_GATTS_RCB));
+            cb_data.reg_oper.status = status;
+            break;
+        }
+    }
+
+    if (p_cback)
+    {
+        (*p_cback)(BTA_GATTS_DEREG_EVT, &cb_data);
+    }
+    else
+    {
+        APPL_TRACE_ERROR("application not registered.");
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_create_srvc
+**
+** Description      action function to create a service.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_create_srvc(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
+{
+    UINT8               rcb_idx;
+    tBTA_GATTS          cb_data;
+    UINT8               srvc_idx;
+    UINT16              service_id = 0;
+
+    cb_data.create.status = BTA_GATT_ERROR;
+
+    rcb_idx = bta_gatts_find_app_rcb_idx_by_app_if(p_cb, p_msg->api_create_svc.server_if);
+
+    APPL_TRACE_ERROR("create service rcb_idx = %d", rcb_idx);
+
+    if (rcb_idx != BTA_GATTS_INVALID_APP)
+    {
+        if ((srvc_idx = bta_gatts_alloc_srvc_cb(p_cb, rcb_idx)) != BTA_GATTS_INVALID_APP)
+        {
+            /* create the service now */
+            service_id = GATTS_CreateService (p_cb->rcb[rcb_idx].gatt_if,
+                                              &p_msg->api_create_svc.service_uuid,
+                                              p_msg->api_create_svc.inst,
+                                              p_msg->api_create_svc.num_handle,
+                                              p_msg->api_create_svc.is_pri);
+
+            if (service_id != 0)
+            {
+                memcpy(&p_cb->srvc_cb[srvc_idx].service_uuid,
+                    &p_msg->api_create_svc.service_uuid, sizeof(tBT_UUID));
+                p_cb->srvc_cb[srvc_idx].service_id   = service_id;
+                p_cb->srvc_cb[srvc_idx].inst_num     = p_msg->api_create_svc.inst;
+                p_cb->srvc_cb[srvc_idx].idx          = srvc_idx;
+
+                cb_data.create.status      = BTA_GATT_OK;
+                cb_data.create.service_id  = service_id;
+// btla-specific ++
+                cb_data.create.is_primary  = p_msg->api_create_svc.is_pri;
+// btla-specific --
+                cb_data.create.server_if   = p_cb->rcb[rcb_idx].gatt_if;
+            }
+            else
+            {
+                cb_data.status  = BTA_GATT_ERROR;
+                memset(&p_cb->srvc_cb[srvc_idx], 0, sizeof(tBTA_GATTS_SRVC_CB));
+                APPL_TRACE_ERROR("service creation failed.");
+            }
+// btla-specific ++
+            memcpy(&cb_data.create.uuid, &p_msg->api_create_svc.service_uuid, sizeof(tBT_UUID));
+            cb_data.create.svc_instance= p_msg->api_create_svc.inst;
+// btla-specific --
+        }
+        if (p_cb->rcb[rcb_idx].p_cback)
+            (* p_cb->rcb[rcb_idx].p_cback)(BTA_GATTS_CREATE_EVT, &cb_data);
+    }
+    else /* application not registered */
+    {
+        APPL_TRACE_ERROR("Application not registered");
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_add_include_srvc
+**
+** Description      action function to add an included service.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_add_include_srvc(tBTA_GATTS_SRVC_CB *p_srvc_cb,tBTA_GATTS_DATA * p_msg)
+{
+    tBTA_GATTS_RCB  *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
+    UINT16          attr_id = 0;
+    tBTA_GATTS      cb_data;
+
+    attr_id = GATTS_AddIncludeService(p_msg->api_add_incl_srvc.hdr.layer_specific,
+                                      p_msg->api_add_incl_srvc.included_service_id);
+
+    cb_data.add_result.server_if = p_rcb->gatt_if;
+    cb_data.add_result.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
+    cb_data.add_result.attr_id = attr_id;
+
+    if (attr_id)
+    {
+        cb_data.add_result.status = BTA_GATT_OK;
+    }
+    else
+    {
+        cb_data.add_result.status = BTA_GATT_ERROR;
+    }
+
+    if (p_rcb->p_cback)
+        (*p_rcb->p_cback)(BTA_GATTS_ADD_INCL_SRVC_EVT, &cb_data);
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_add_char
+**
+** Description      action function to add characteristic.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_add_char(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg)
+{
+    tBTA_GATTS_RCB  *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
+    UINT16          attr_id = 0;
+    tBTA_GATTS      cb_data;
+
+    attr_id = GATTS_AddCharacteristic(p_msg->api_add_char.hdr.layer_specific,
+                                      &p_msg->api_add_char.char_uuid,
+                                      p_msg->api_add_char.perm,
+                                      p_msg->api_add_char.property);
+    cb_data.add_result.server_if = p_rcb->gatt_if;
+    cb_data.add_result.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
+    cb_data.add_result.attr_id = attr_id;
+// btla-specific ++
+    memcpy(&cb_data.add_result.char_uuid, &p_msg->api_add_char.char_uuid, sizeof(tBT_UUID));
+// btla-specific --
+
+    if (attr_id)
+    {
+        cb_data.add_result.status = BTA_GATT_OK;
+    }
+    else
+    {
+        cb_data.add_result.status = BTA_GATT_ERROR;
+    }
+
+    if (p_rcb->p_cback)
+        (*p_rcb->p_cback)(BTA_GATTS_ADD_CHAR_EVT, &cb_data);
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_add_char_descr
+**
+** Description      action function to add characteristic descriptor.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_add_char_descr(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg)
+{
+    tBTA_GATTS_RCB  *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
+    UINT16          attr_id = 0;
+    tBTA_GATTS      cb_data;
+
+    attr_id = GATTS_AddCharDescriptor(p_msg->api_add_char_descr.hdr.layer_specific,
+                                       p_msg->api_add_char_descr.perm,
+                                       &p_msg->api_add_char_descr.descr_uuid);
+
+    cb_data.add_result.server_if = p_rcb->gatt_if;
+    cb_data.add_result.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
+    cb_data.add_result.attr_id = attr_id;
+// btla-specific ++
+    memcpy(&cb_data.add_result.char_uuid, &p_msg->api_add_char_descr.descr_uuid, sizeof(tBT_UUID));
+// btla-specific --
+
+    if (attr_id)
+    {
+        cb_data.add_result.status = BTA_GATT_OK;
+    }
+    else
+    {
+        cb_data.add_result.status = BTA_GATT_ERROR;
+    }
+
+    if (p_rcb->p_cback)
+        (*p_rcb->p_cback)(BTA_GATTS_ADD_CHAR_DESCR_EVT, &cb_data);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_delete_service
+**
+** Description      action function to delete a service.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_delete_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg)
+{
+    tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
+    tBTA_GATTS      cb_data;
+
+    cb_data.srvc_oper.server_if = p_rcb->gatt_if;
+    cb_data.srvc_oper.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
+
+    if (GATTS_DeleteService(p_rcb->gatt_if,
+                            &p_srvc_cb->service_uuid,
+                            p_srvc_cb->inst_num))
+    {
+        cb_data.srvc_oper.status = BTA_GATT_OK;
+        memset(p_srvc_cb, 0, sizeof(tBTA_GATTS_SRVC_CB));
+    }
+    else
+    {
+        cb_data.srvc_oper.status = BTA_GATT_ERROR;
+    }
+
+    if (p_rcb->p_cback)
+        (*p_rcb->p_cback)(BTA_GATTS_DELELTE_EVT, &cb_data);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_start_service
+**
+** Description      action function to start a service.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_start_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg)
+{
+    tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
+    tBTA_GATTS      cb_data;
+
+    cb_data.srvc_oper.server_if = p_rcb->gatt_if;
+    cb_data.srvc_oper.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
+
+    if (GATTS_StartService(p_rcb->gatt_if,
+                           p_srvc_cb->service_id,
+                           p_msg->api_start.transport) ==  GATT_SUCCESS)
+    {
+        APPL_TRACE_DEBUG("bta_gatts_start_service service_id= %d", p_srvc_cb->service_id);
+        cb_data.srvc_oper.status = BTA_GATT_OK;
+    }
+    else
+    {
+        cb_data.srvc_oper.status = BTA_GATT_ERROR;
+    }
+
+    if (p_rcb->p_cback)
+        (*p_rcb->p_cback)(BTA_GATTS_START_EVT, &cb_data);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_stop_service
+**
+** Description      action function to stop a service.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_stop_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg)
+{
+    tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
+    tBTA_GATTS      cb_data;
+    UNUSED(p_msg);
+
+    GATTS_StopService(p_srvc_cb->service_id);
+    cb_data.srvc_oper.server_if = p_rcb->gatt_if;
+    cb_data.srvc_oper.service_id = p_srvc_cb->service_id;
+    cb_data.srvc_oper.status = BTA_GATT_OK;
+    APPL_TRACE_ERROR("bta_gatts_stop_service service_id= %d", p_srvc_cb->service_id);
+
+    if (p_rcb->p_cback)
+        (*p_rcb->p_cback)(BTA_GATTS_STOP_EVT, &cb_data);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_send_rsp
+**
+** Description      GATTS send response.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_send_rsp (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
+{
+    UNUSED(p_cb);
+
+    if (GATTS_SendRsp (p_msg->api_rsp.hdr.layer_specific,
+                        p_msg->api_rsp.trans_id,
+                        p_msg->api_rsp.status,
+                        (tGATTS_RSP *)p_msg->api_rsp.p_rsp) != GATT_SUCCESS)
+    {
+        APPL_TRACE_ERROR("Sending response failed");
+    }
+
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_indicate_handle
+**
+** Description      GATTS send handle value indication or notification.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_indicate_handle (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
+{
+    tBTA_GATTS_SRVC_CB  *p_srvc_cb;
+    tBTA_GATTS_RCB      *p_rcb = NULL;
+    tBTA_GATT_STATUS    status = BTA_GATT_ILLEGAL_PARAMETER;
+    tGATT_IF            gatt_if;
+    BD_ADDR             remote_bda;
+    tBTA_TRANSPORT transport;
+    tBTA_GATTS          cb_data;
+
+    p_srvc_cb = bta_gatts_find_srvc_cb_by_attr_id (p_cb, p_msg->api_indicate.attr_id);
+
+    if (p_srvc_cb )
+    {
+        if (GATT_GetConnectionInfor(p_msg->api_indicate.hdr.layer_specific,
+            &gatt_if, remote_bda, &transport))
+        {
+            p_rcb = bta_gatts_find_app_rcb_by_app_if(gatt_if);
+
+            if (p_msg->api_indicate.need_confirm)
+
+                status = GATTS_HandleValueIndication (p_msg->api_indicate.hdr.layer_specific,
+                                                      p_msg->api_indicate.attr_id,
+                                                      p_msg->api_indicate.len,
+                                                      p_msg->api_indicate.value);
+            else
+                status = GATTS_HandleValueNotification (p_msg->api_indicate.hdr.layer_specific,
+                                                        p_msg->api_indicate.attr_id,
+                                                        p_msg->api_indicate.len,
+                                                        p_msg->api_indicate.value);
+
+            /* if over BR_EDR, inform PM for mode change */
+            if (transport == BTA_TRANSPORT_BR_EDR)
+            {
+                bta_sys_busy(BTA_ID_GATTS, BTA_ALL_APP_ID, remote_bda);
+                bta_sys_idle(BTA_ID_GATTS, BTA_ALL_APP_ID, remote_bda);
+            }
+        }
+        else
+        {
+            APPL_TRACE_ERROR("Unknown connection ID: %d fail sending notification",
+                              p_msg->api_indicate.hdr.layer_specific);
+        }
+
+        if ((status != GATT_SUCCESS || !p_msg->api_indicate.need_confirm) &&
+            p_rcb && p_cb->rcb[p_srvc_cb->rcb_idx].p_cback)
+        {
+            cb_data.req_data.status = status;
+            cb_data.req_data.conn_id = p_msg->api_indicate.hdr.layer_specific;
+
+            (*p_rcb->p_cback)(BTA_GATTS_CONF_EVT, &cb_data);
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR("Not an registered servce attribute ID: 0x%04x",
+                          p_msg->api_indicate.attr_id);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_gatts_open
+**
+** Description
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_open (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
+{
+    tBTA_GATTS_RCB      *p_rcb=NULL;
+    tBTA_GATT_STATUS    status= BTA_GATT_ERROR;
+    UINT16              conn_id;
+    UNUSED(p_cb);
+
+    if ((p_rcb = bta_gatts_find_app_rcb_by_app_if(p_msg->api_open.server_if)) != NULL)
+    {
+        /* should always get the connection ID */
+        if (GATT_Connect(p_rcb->gatt_if, p_msg->api_open.remote_bda,
+                        p_msg->api_open.is_direct, p_msg->api_open.transport))
+        {
+            status = BTA_GATT_OK;
+
+            if (GATT_GetConnIdIfConnected(p_rcb->gatt_if, p_msg->api_open.remote_bda,
+                                            &conn_id, p_msg->api_open.transport))
+            {
+                status = BTA_GATT_ALREADY_OPEN;
+            }
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR("Inavlide server_if=%d", p_msg->api_open.server_if);
+    }
+
+    if (p_rcb && p_rcb->p_cback)
+        (*p_rcb->p_cback)(BTA_GATTS_OPEN_EVT,  (tBTA_GATTS *)&status);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_cancel_open
+**
+** Description
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_cancel_open (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
+{
+    tBTA_GATTS_RCB      *p_rcb;
+    tBTA_GATT_STATUS    status= BTA_GATT_ERROR;
+    UNUSED(p_cb);
+
+    if ((p_rcb = bta_gatts_find_app_rcb_by_app_if(p_msg->api_cancel_open.server_if)) != NULL)
+    {
+        if (!GATT_CancelConnect(p_rcb->gatt_if, p_msg->api_cancel_open.remote_bda,
+                                p_msg->api_cancel_open.is_direct))
+        {
+            APPL_TRACE_ERROR("bta_gatts_cancel_open failed for open request");
+        }
+        else
+        {
+            status= BTA_GATT_OK;
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR("Inavlide server_if=%d", p_msg->api_cancel_open.server_if);
+    }
+
+    if (p_rcb && p_rcb->p_cback)
+        (*p_rcb->p_cback)(BTA_GATTS_CANCEL_OPEN_EVT,  (tBTA_GATTS *)&status);
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_close
+**
+** Description
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_close (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
+{
+    tBTA_GATTS_RCB     *p_rcb;
+    tBTA_GATT_STATUS    status= BTA_GATT_ERROR;
+    tGATT_IF            gatt_if;
+    BD_ADDR             remote_bda;
+    tBTA_GATT_TRANSPORT transport;
+
+    UNUSED(p_cb);
+
+    if (GATT_GetConnectionInfor(p_msg->hdr.layer_specific, &gatt_if, remote_bda, &transport))
+    {
+        if (GATT_Disconnect(p_msg->hdr.layer_specific) != GATT_SUCCESS)
+        {
+            APPL_TRACE_ERROR("bta_gatts_close fail conn_id=%d", p_msg->hdr.layer_specific);
+        }
+        else
+        {
+            status= BTA_GATT_OK;
+        }
+
+        p_rcb = bta_gatts_find_app_rcb_by_app_if(gatt_if);
+
+        if (p_rcb && p_rcb->p_cback)
+        {
+            if (transport == BTA_TRANSPORT_BR_EDR)
+                bta_sys_conn_close( BTA_ID_GATTS ,BTA_ALL_APP_ID, remote_bda);
+
+            (*p_rcb->p_cback)(BTA_GATTS_CLOSE_EVT,  (tBTA_GATTS *)&status);
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR("Unknown connection ID: %d", p_msg->hdr.layer_specific);
+    }
+
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_listen
+**
+** Description      Start or stop listening for LE connection on a GATT server
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_listen(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
+{
+    tBTA_GATTS_RCB     *p_rcb = bta_gatts_find_app_rcb_by_app_if(p_msg->api_listen.server_if);
+    tBTA_GATTS          cb_data;
+    UNUSED(p_cb);
+
+    cb_data.reg_oper.status = BTA_GATT_OK;
+    cb_data.reg_oper.server_if = p_msg->api_listen.server_if;
+
+    if (p_rcb == NULL)
+    {
+        APPL_TRACE_ERROR("Unknown GATTS application");
+        return;
+    }
+
+    if (!GATT_Listen(p_msg->api_listen.server_if,
+                     p_msg->api_listen.start,
+                     p_msg->api_listen.remote_bda))
+    {
+        cb_data.status = BTA_GATT_ERROR;
+        APPL_TRACE_ERROR("bta_gatts_listen Listen failed");
+    }
+
+    if (p_rcb->p_cback)
+        (*p_rcb->p_cback)(BTA_GATTS_LISTEN_EVT, &cb_data);
+}
+
+/*******************************************************************************
+**
+** Function         bta_gatts_request_cback
+**
+** Description      GATTS attribute request callback.
+**
+** Returns          none.
+**
+*******************************************************************************/
+static void bta_gatts_send_request_cback (UINT16 conn_id,
+                                          UINT32 trans_id,
+                                          tGATTS_REQ_TYPE req_type, tGATTS_DATA *p_data)
+{
+    tBTA_GATTS          cb_data;
+    tBTA_GATTS_RCB     *p_rcb;
+    tGATT_IF            gatt_if;
+    tBTA_GATT_TRANSPORT transport;
+
+    memset(&cb_data, 0 , sizeof(tBTA_GATTS));
+
+    if (GATT_GetConnectionInfor(conn_id, &gatt_if, cb_data.req_data.remote_bda, &transport))
+    {
+        p_rcb = bta_gatts_find_app_rcb_by_app_if(gatt_if);
+
+        APPL_TRACE_DEBUG ("bta_gatts_send_request_cback conn_id=%d trans_id=%d req_type=%d",
+                            conn_id, trans_id, req_type);
+
+        if (p_rcb && p_rcb->p_cback)
+        {
+            /* if over BR_EDR, inform PM for mode change */
+            if (transport == BTA_TRANSPORT_BR_EDR)
+            {
+                bta_sys_busy(BTA_ID_GATTS, BTA_ALL_APP_ID, cb_data.req_data.remote_bda);
+                bta_sys_idle(BTA_ID_GATTS, BTA_ALL_APP_ID, cb_data.req_data.remote_bda);
+            }
+
+            cb_data.req_data.conn_id    = conn_id;
+            cb_data.req_data.trans_id   = trans_id;
+            cb_data.req_data.p_data     = (tBTA_GATTS_REQ_DATA *)p_data;
+
+            (*p_rcb->p_cback)(req_type,  &cb_data);
+        }
+        else
+        {
+            APPL_TRACE_ERROR("connection request on gatt_if[%d] is not interested", gatt_if);
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR("request received on unknown connectino ID: %d", conn_id);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gatts_conn_cback
+**
+** Description      connection callback.
+**
+** Returns          none.
+**
+*******************************************************************************/
+static void bta_gatts_conn_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
+                                  BOOLEAN connected, tGATT_DISCONN_REASON reason,
+                                  tGATT_TRANSPORT transport)
+{
+    tBTA_GATTS      cb_data;
+    UINT8           evt = connected ? BTA_GATTS_CONNECT_EVT: BTA_GATTS_DISCONNECT_EVT;
+    tBTA_GATTS_RCB  *p_reg;
+
+    APPL_TRACE_DEBUG ("bta_gatts_conn_cback gatt_if=%d conn_id=%d connected=%d reason = 0x%04d",
+                        gatt_if, conn_id, connected, reason);
+    APPL_TRACE_DEBUG("bta_gatts_conn_cback  bda :%02x-%02x-%02x-%02x-%02x-%02x ",
+                      bda[0],  bda[1], bda[2],  bda[3], bda[4],  bda[5]);
+
+    bt_bdaddr_t bdaddr;
+    bdcpy(bdaddr.address, bda);
+    /*
+    if (connected)
+        btif_debug_conn_state(bdaddr, BTIF_DEBUG_CONNECTED, GATT_CONN_UNKNOWN);
+    else
+        btif_debug_conn_state(bdaddr, BTIF_DEBUG_DISCONNECTED, reason);
+    */
+    p_reg = bta_gatts_find_app_rcb_by_app_if(gatt_if);
+
+    if (p_reg && p_reg->p_cback)
+    {
+        /* there is no RM for GATT */
+        if (transport == BTA_TRANSPORT_BR_EDR)
+        {
+            if (connected)
+                bta_sys_conn_open(BTA_ID_GATTS, BTA_ALL_APP_ID, bda);
+            else
+                bta_sys_conn_close( BTA_ID_GATTS ,BTA_ALL_APP_ID, bda);
+        }
+
+        cb_data.conn.conn_id = conn_id;
+        cb_data.conn.server_if = gatt_if;
+        cb_data.conn.reason = reason;
+        cb_data.conn.transport = transport;
+        memcpy(cb_data.conn.remote_bda, bda, BD_ADDR_LEN);
+        (*p_reg->p_cback)(evt, &cb_data);
+    }
+    else
+    {
+        APPL_TRACE_ERROR("bta_gatts_conn_cback server_if=%d not found",gatt_if);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gatts_cong_cback
+**
+** Description      congestion callback.
+**
+** Returns          none.
+**
+*******************************************************************************/
+static void bta_gatts_cong_cback (UINT16 conn_id, BOOLEAN congested)
+{
+    tBTA_GATTS_RCB *p_rcb;
+    tGATT_IF gatt_if;
+    tBTA_GATT_TRANSPORT transport;
+    tBTA_GATTS cb_data;
+
+    if (GATT_GetConnectionInfor(conn_id, &gatt_if, cb_data.req_data.remote_bda, &transport))
+    {
+        p_rcb = bta_gatts_find_app_rcb_by_app_if(gatt_if);
+
+        if (p_rcb && p_rcb->p_cback)
+        {
+            cb_data.congest.conn_id = conn_id;
+            cb_data.congest.congested = congested;
+
+            (*p_rcb->p_cback)(BTA_GATTS_CONGEST_EVT, &cb_data);
+        }
+    }
+}
+#endif /* BTA_GATT_INCLUDED */

+ 581 - 0
components/bt/bluedroid/bta/gatt/bta_gatts_api.c

@@ -0,0 +1,581 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2010-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the implementation of the API for GATT server of BTA.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_gatt_api.h"
+#include "bta_gatts_int.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_gatts_reg =
+{
+    bta_gatts_hdl_event,
+    BTA_GATTS_Disable
+};
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_Disable
+**
+** Description      This function is called to disable GATTS module
+**
+** Parameters       None.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTS_Disable(void)
+{
+    BT_HDR  *p_buf;
+
+    if (bta_sys_is_register(BTA_ID_GATTS) == FALSE)
+    {
+        APPL_TRACE_WARNING("GATTS Module not enabled/already disabled");
+        return;
+    }
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_GATTS_API_DISABLE_EVT;
+        bta_sys_sendmsg(p_buf);
+    }
+    bta_sys_deregister(BTA_ID_GATTS);
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_AppRegister
+**
+** Description      This function is called to register application callbacks
+**                    with BTA GATTS module.
+**
+** Parameters       p_app_uuid - applicaiton UUID
+**                  p_cback - pointer to the application callback function.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTS_AppRegister(tBT_UUID *p_app_uuid, tBTA_GATTS_CBACK *p_cback)
+{
+    tBTA_GATTS_API_REG  *p_buf;
+
+    /* register with BTA system manager */
+    if (bta_sys_is_register(BTA_ID_GATTS) == FALSE)
+    {
+        bta_sys_register(BTA_ID_GATTS, &bta_gatts_reg);
+    }
+
+    if ((p_buf = (tBTA_GATTS_API_REG *) GKI_getbuf(sizeof(tBTA_GATTS_API_REG))) != NULL)
+    {
+        p_buf->hdr.event    = BTA_GATTS_API_REG_EVT;
+
+        if (p_app_uuid != NULL)
+            memcpy(&p_buf->app_uuid, p_app_uuid, sizeof(tBT_UUID));
+        p_buf->p_cback      = p_cback;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_AppDeregister
+**
+** Description      De-register with GATT Server.
+**
+** Parameters       app_id: applicatino ID.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTS_AppDeregister(tBTA_GATTS_IF server_if)
+{
+    tBTA_GATTS_API_DEREG  *p_buf;
+
+    if ((p_buf = (tBTA_GATTS_API_DEREG *) GKI_getbuf(sizeof(tBTA_GATTS_API_DEREG))) != NULL)
+    {
+        p_buf->hdr.event    = BTA_GATTS_API_DEREG_EVT;
+        p_buf->server_if    = server_if;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_CreateService
+**
+** Description      Create a service. When service creation is done, a callback
+**                  event BTA_GATTS_CREATE_SRVC_EVT is called to report status
+**                  and service ID to the profile. The service ID obtained in
+**                  the callback function needs to be used when adding included
+**                  service and characteristics/descriptors into the service.
+**
+** Parameters       app_id: Profile ID this service is belonged to.
+**                  p_service_uuid: service UUID.
+**                  inst: instance ID number of this service.
+**                  num_handle: numble of handle requessted for this service.
+**                  is_primary: is this service a primary one or not.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTS_CreateService(tBTA_GATTS_IF server_if, tBT_UUID *p_service_uuid, UINT8 inst,
+                             UINT16 num_handle, BOOLEAN is_primary)
+{
+    tBTA_GATTS_API_CREATE_SRVC  *p_buf;
+
+    if ((p_buf = (tBTA_GATTS_API_CREATE_SRVC *) GKI_getbuf(sizeof(tBTA_GATTS_API_CREATE_SRVC))) != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTS_API_CREATE_SRVC_EVT;
+
+        p_buf->server_if = server_if;
+        p_buf->inst = inst;
+        memcpy(&p_buf->service_uuid, p_service_uuid, sizeof(tBT_UUID));
+        p_buf->num_handle = num_handle;
+        p_buf->is_pri = is_primary;  
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTS_AddIncludeService
+**
+** Description      This function is called to add an included service. After included
+**                  service is included, a callback event BTA_GATTS_ADD_INCL_SRVC_EVT
+**                  is reported the included service ID.
+**
+** Parameters       service_id: service ID to which this included service is to
+**                              be added.
+**                  included_service_id: the service ID to be included.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTS_AddIncludeService(UINT16 service_id, UINT16 included_service_id)
+{
+    tBTA_GATTS_API_ADD_INCL_SRVC  *p_buf;
+
+    if ((p_buf =
+         (tBTA_GATTS_API_ADD_INCL_SRVC *) GKI_getbuf(sizeof(tBTA_GATTS_API_ADD_INCL_SRVC)))
+        != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTS_API_ADD_INCL_SRVC_EVT;
+
+        p_buf->hdr.layer_specific = service_id;
+        p_buf->included_service_id = included_service_id;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTS_AddCharacteristic
+**
+** Description      This function is called to add a characteristic into a service.
+**
+** Parameters       service_id: service ID to which this included service is to
+**                              be added.
+**                  p_char_uuid : Characteristic UUID.
+**                  perm      : Characteristic value declaration attribute permission.
+**                  property  : Characteristic Properties
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTS_AddCharacteristic (UINT16 service_id,  tBT_UUID  *p_char_uuid,
+                                  tBTA_GATT_PERM perm, tBTA_GATT_CHAR_PROP property)
+{
+    tBTA_GATTS_API_ADD_CHAR  *p_buf;
+
+    if ((p_buf = (tBTA_GATTS_API_ADD_CHAR *) GKI_getbuf(sizeof(tBTA_GATTS_API_ADD_CHAR))) != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_GATTS_API_ADD_CHAR));
+
+        p_buf->hdr.event = BTA_GATTS_API_ADD_CHAR_EVT;
+        p_buf->hdr.layer_specific = service_id;
+        p_buf->perm = perm;
+        p_buf->property = property;
+
+        if (p_char_uuid)
+        {
+            memcpy(&p_buf->char_uuid, p_char_uuid, sizeof(tBT_UUID));
+        }
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_AddCharDescriptor
+**
+** Description      This function is called to add characteristic descriptor. When
+**                  it's done, a callback event BTA_GATTS_ADD_DESCR_EVT is called
+**                  to report the status and an ID number for this descriptor.
+**
+** Parameters       service_id: service ID to which this charatceristic descriptor is to
+**                              be added.
+**                  perm: descriptor access permission.
+**                  p_descr_uuid: descriptor UUID.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+void BTA_GATTS_AddCharDescriptor (UINT16 service_id,
+                                  tBTA_GATT_PERM perm,
+                                  tBT_UUID  * p_descr_uuid)
+{
+    tBTA_GATTS_API_ADD_DESCR  *p_buf;
+    UINT16  len = sizeof(tBTA_GATTS_API_ADD_DESCR);
+
+
+    if ((p_buf = (tBTA_GATTS_API_ADD_DESCR *) GKI_getbuf(len)) != NULL)
+    {
+        memset(p_buf, 0, len);
+
+        p_buf->hdr.event = BTA_GATTS_API_ADD_DESCR_EVT;
+        p_buf->hdr.layer_specific = service_id;
+        p_buf->perm = perm;
+
+        if (p_descr_uuid)
+        {
+            memcpy(&p_buf->descr_uuid, p_descr_uuid, sizeof(tBT_UUID));
+        }
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_DeleteService
+**
+** Description      This function is called to delete a service. When this is done,
+**                  a callback event BTA_GATTS_DELETE_EVT is report with the status.
+**
+** Parameters       service_id: service_id to be deleted.
+**
+** Returns          returns none.
+**
+*******************************************************************************/
+void  BTA_GATTS_DeleteService(UINT16 service_id)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_GATTS_API_DEL_SRVC_EVT;
+
+        p_buf->layer_specific = service_id;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_StartService
+**
+** Description      This function is called to start a service.
+**
+** Parameters       service_id: the service ID to be started.
+**                  sup_transport: supported trasnport.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void  BTA_GATTS_StartService(UINT16 service_id, tBTA_GATT_TRANSPORT sup_transport)
+{
+    tBTA_GATTS_API_START  *p_buf;
+
+    if ((p_buf = (tBTA_GATTS_API_START *) GKI_getbuf(sizeof(tBTA_GATTS_API_START))) != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTS_API_START_SRVC_EVT;
+
+        p_buf->hdr.layer_specific = service_id;
+        p_buf->transport = sup_transport;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_StopService
+**
+** Description      This function is called to stop a service.
+**
+** Parameters       service_id - service to be topped.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTS_StopService(UINT16 service_id)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_GATTS_API_STOP_SRVC_EVT;
+
+        p_buf->layer_specific = service_id;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_HandleValueIndication
+**
+** Description      This function is called to read a characteristics descriptor.
+**
+** Parameters       bda - remote device bd address to indicate.
+**					attr_id - attribute ID to indicate.
+**                  data_len - indicate data length.
+**                  p_data: data to indicate.
+**                  need_confirm - if this indication expects a confirmation or not.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTS_HandleValueIndication (UINT16 conn_id, UINT16 attr_id, UINT16 data_len,
+                                      UINT8 *p_data, BOOLEAN need_confirm)
+{
+    tBTA_GATTS_API_INDICATION  *p_buf;
+    UINT16  len = sizeof(tBTA_GATTS_API_INDICATION);
+
+    if ((p_buf = (tBTA_GATTS_API_INDICATION *) GKI_getbuf(len)) != NULL)
+    {
+        memset(p_buf, 0, len);
+
+        p_buf->hdr.event = BTA_GATTS_API_INDICATION_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+        p_buf->attr_id = attr_id;
+        p_buf->need_confirm = need_confirm;
+
+        if (data_len > 0 && p_data != NULL)
+        {
+            p_buf->len = data_len;
+            memcpy(p_buf->value, p_data, data_len);
+
+        }
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTS_SendRsp
+**
+** Description      This function is called to send a response to a request.
+**
+** Parameters       conn_id - connection identifier.
+**                  trans_id - transaction ID.
+**                  status - response status
+**                  p_msg - response data.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id,
+                        tBTA_GATT_STATUS status, tBTA_GATTS_RSP *p_msg)
+{
+    tBTA_GATTS_API_RSP  *p_buf;
+    UINT16  len = sizeof(tBTA_GATTS_API_RSP) + sizeof(tBTA_GATTS_RSP);
+
+    if ((p_buf = (tBTA_GATTS_API_RSP *) GKI_getbuf(len)) != NULL)
+    {
+        memset(p_buf, 0, len);
+
+        p_buf->hdr.event    = BTA_GATTS_API_RSP_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+        p_buf->trans_id = trans_id;
+        p_buf->status = status;
+
+        if (p_msg != NULL)
+        {
+            p_buf->p_rsp = (tBTA_GATTS_RSP *)(p_buf + 1);
+            memcpy(p_buf->p_rsp, p_msg, sizeof(tBTA_GATTS_RSP));
+        }
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_Open
+**
+** Description      Open a direct open connection or add a background auto connection
+**                  bd address
+**
+** Parameters       server_if: server interface.
+**                  remote_bda: remote device BD address.
+**                  is_direct: direct connection or background auto connection
+**                  transport : Transport on which GATT connection to be opened (BR/EDR or LE)
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTS_Open(tBTA_GATTS_IF server_if, BD_ADDR remote_bda, BOOLEAN is_direct,
+                    tBTA_GATT_TRANSPORT transport)
+{
+    tBTA_GATTS_API_OPEN  *p_buf;
+
+    if ((p_buf = (tBTA_GATTS_API_OPEN *) GKI_getbuf(sizeof(tBTA_GATTS_API_OPEN))) != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTS_API_OPEN_EVT;
+        p_buf->server_if = server_if;
+        p_buf->is_direct = is_direct;
+        p_buf->transport = transport;
+        memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_CancelOpen
+**
+** Description      Cancel a direct open connection or remove a background auto connection
+**                  bd address
+**
+** Parameters       server_if: server interface.
+**                  remote_bda: remote device BD address.
+**                  is_direct: direct connection or background auto connection
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTS_CancelOpen(tBTA_GATTS_IF server_if, BD_ADDR remote_bda, BOOLEAN is_direct)
+{
+    tBTA_GATTS_API_CANCEL_OPEN  *p_buf;
+
+    if ((p_buf = (tBTA_GATTS_API_CANCEL_OPEN *) GKI_getbuf(sizeof(tBTA_GATTS_API_CANCEL_OPEN))) != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTS_API_CANCEL_OPEN_EVT;
+        p_buf->server_if = server_if;
+        p_buf->is_direct = is_direct;
+        memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_Close
+**
+** Description      Close a connection  a remote device.
+**
+** Parameters       conn_id: connectino ID to be closed.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTS_Close(UINT16 conn_id)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_GATTS_API_CLOSE_EVT;
+        p_buf->layer_specific = conn_id;
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTS_Listen
+**
+** Description      Start advertisement to listen for connection request for a
+**                  GATT server
+**
+** Parameters       server_if: server interface.
+**                  start: to start or stop listening for connection
+**                  remote_bda: remote device BD address, if listen to all device
+**                              use NULL.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTS_Listen(tBTA_GATTS_IF server_if, BOOLEAN start, BD_ADDR_PTR target_bda)
+{
+    tBTA_GATTS_API_LISTEN  *p_buf;
+
+    if ((p_buf = (tBTA_GATTS_API_LISTEN *) GKI_getbuf((UINT16)(sizeof(tBTA_GATTS_API_LISTEN) + BD_ADDR_LEN))) != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTS_API_LISTEN_EVT;
+
+        p_buf->server_if    = server_if;
+        p_buf->start        = start;
+
+        if (target_bda)
+        {
+            p_buf->remote_bda = (UINT8*)(p_buf + 1);
+            memcpy(p_buf->remote_bda, target_bda, BD_ADDR_LEN);
+        }
+        else
+            p_buf->remote_bda = NULL;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+#endif /* BTA_GATT_INCLUDED */

+ 144 - 0
components/bt/bluedroid/bta/gatt/bta_gatts_main.c

@@ -0,0 +1,144 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+ *
+ *  This file contains the GATT server main functions and state machine.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+
+#include "bta_gatts_int.h"
+#include "gki.h"
+
+/* type for service building action functions */
+typedef void (*tBTA_GATTS_SRVC_ACT)(tBTA_GATTS_SRVC_CB *p_rcb, tBTA_GATTS_DATA *p_data);
+
+/* service building action function list */
+const tBTA_GATTS_SRVC_ACT bta_gatts_srvc_build_act[] =
+{
+    bta_gatts_add_include_srvc,
+    bta_gatts_add_char,
+    bta_gatts_add_char_descr,
+    bta_gatts_delete_service,
+    bta_gatts_start_service,
+    bta_gatts_stop_service,
+};
+
+/* GATTS control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_GATTS_CB  bta_gatts_cb;
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_gatts_hdl_event
+**
+** Description      BTA GATT server main event handling function.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN bta_gatts_hdl_event(BT_HDR *p_msg)
+{
+    tBTA_GATTS_CB *p_cb = &bta_gatts_cb;
+    tBTA_GATTS_SRVC_CB *p_srvc_cb = NULL;
+
+    switch (p_msg->event)
+    {
+        case BTA_GATTS_API_DISABLE_EVT:
+            bta_gatts_api_disable(p_cb);
+            break;
+
+        case BTA_GATTS_API_REG_EVT:
+	    LOG_ERROR("bta_gatts_register\n");
+            bta_gatts_register(p_cb, (tBTA_GATTS_DATA *) p_msg);
+            break;
+
+        case BTA_GATTS_INT_START_IF_EVT:
+            bta_gatts_start_if(p_cb, (tBTA_GATTS_DATA *) p_msg);
+            break;
+
+        case BTA_GATTS_API_DEREG_EVT:
+            bta_gatts_deregister(p_cb, (tBTA_GATTS_DATA *) p_msg);
+            break;
+
+        case BTA_GATTS_API_CREATE_SRVC_EVT:
+            bta_gatts_create_srvc(p_cb, (tBTA_GATTS_DATA *) p_msg);
+            break;
+
+        case BTA_GATTS_API_INDICATION_EVT:
+            bta_gatts_indicate_handle(p_cb,(tBTA_GATTS_DATA *) p_msg);
+            break;
+
+        case BTA_GATTS_API_OPEN_EVT:
+            bta_gatts_open(p_cb,(tBTA_GATTS_DATA *) p_msg);
+            break;
+
+        case BTA_GATTS_API_CANCEL_OPEN_EVT:
+            bta_gatts_cancel_open(p_cb,(tBTA_GATTS_DATA *) p_msg);
+            break;
+
+        case BTA_GATTS_API_CLOSE_EVT:
+            bta_gatts_close(p_cb,(tBTA_GATTS_DATA *) p_msg);
+            break;
+
+        case BTA_GATTS_API_RSP_EVT:
+            bta_gatts_send_rsp(p_cb,(tBTA_GATTS_DATA *) p_msg);
+            break;
+
+        case BTA_GATTS_API_LISTEN_EVT:
+            bta_gatts_listen(p_cb,(tBTA_GATTS_DATA *) p_msg);
+            break;
+
+
+        case BTA_GATTS_API_ADD_INCL_SRVC_EVT:
+        case BTA_GATTS_API_ADD_CHAR_EVT:
+        case BTA_GATTS_API_ADD_DESCR_EVT:
+        case BTA_GATTS_API_DEL_SRVC_EVT:
+        case BTA_GATTS_API_START_SRVC_EVT:
+        case BTA_GATTS_API_STOP_SRVC_EVT:
+
+            p_srvc_cb = bta_gatts_find_srvc_cb_by_srvc_id(p_cb,
+                                ((tBTA_GATTS_DATA *)p_msg)->api_add_incl_srvc.hdr.layer_specific);
+
+            if (p_srvc_cb != NULL)
+            {
+                bta_gatts_srvc_build_act[p_msg->event - BTA_GATTS_API_ADD_INCL_SRVC_EVT](p_srvc_cb, (tBTA_GATTS_DATA *) p_msg);
+            }
+            else
+            {
+                APPL_TRACE_ERROR("service not created");
+            }
+            break;
+
+        default:
+            break;
+    }
+
+
+    return (TRUE);
+}
+
+#endif /* BTA_GATT_INCLUDED */

+ 234 - 0
components/bt/bluedroid/bta/gatt/bta_gatts_utils.c

@@ -0,0 +1,234 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This file contains the GATT client utility function.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+#include "utl.h"
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_gatts_int.h"
+
+static const UINT8  base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
+    0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+/*******************************************************************************
+**
+** Function         bta_gatt_convert_uuid16_to_uuid128
+**
+** Description      Convert a 16 bits UUID to be an standard 128 bits one.
+**
+** Returns          TRUE if two uuid match; FALSE otherwise.
+**
+*******************************************************************************/
+static void bta_gatt_convert_uuid16_to_uuid128(UINT8 uuid_128[LEN_UUID_128], UINT16 uuid_16)
+{
+    UINT8   *p = &uuid_128[LEN_UUID_128 - 4];
+
+    memcpy (uuid_128, base_uuid, LEN_UUID_128);
+
+    UINT16_TO_STREAM(p, uuid_16);
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_alloc_srvc_cb
+**
+** Description      allocate a service control block.
+**
+** Returns          pointer to the control block, or otherwise NULL when failed.
+**
+*******************************************************************************/
+UINT8 bta_gatts_alloc_srvc_cb(tBTA_GATTS_CB *p_cb, UINT8 rcb_idx)
+{
+    UINT8 i;
+
+    for (i = 0; i < BTA_GATTS_MAX_SRVC_NUM; i ++)
+    {
+        if (!p_cb->srvc_cb[i].in_use)
+        {
+            p_cb->srvc_cb[i].in_use = TRUE;
+            p_cb->srvc_cb[i].rcb_idx = rcb_idx;
+            return i;
+        }
+    }
+    return BTA_GATTS_INVALID_APP;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gatts_find_app_rcb_by_app_if
+**
+** Description      find the index of the application control block by app ID.
+**
+** Returns          pointer to the control block if success, otherwise NULL
+**
+*******************************************************************************/
+tBTA_GATTS_RCB *bta_gatts_find_app_rcb_by_app_if(tBTA_GATTS_IF server_if)
+{
+    UINT8 i;
+    tBTA_GATTS_RCB *p_reg;
+
+    for (i = 0, p_reg = bta_gatts_cb.rcb; i < BTA_GATTS_MAX_APP_NUM; i ++, p_reg++)
+    {
+        if (p_reg->in_use && p_reg->gatt_if == server_if)
+            return p_reg;
+    }
+    return NULL;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gatts_find_app_rcb_idx_by_app_if
+**
+** Description      find the index of the application control block by app ID.
+**
+** Returns          index of the control block, or BTA_GATTS_INVALID_APP if failed.
+**
+*******************************************************************************/
+
+UINT8 bta_gatts_find_app_rcb_idx_by_app_if(tBTA_GATTS_CB *p_cb, tBTA_GATTS_IF server_if)
+{
+    UINT8 i;
+
+    for (i = 0; i < BTA_GATTS_MAX_APP_NUM; i ++)
+    {
+        if (p_cb->rcb[i].in_use && p_cb->rcb[i].gatt_if == server_if)
+            return i;
+    }
+    return BTA_GATTS_INVALID_APP;
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_find_srvc_cb_by_srvc_id
+**
+** Description      find the service control block by service ID.
+**
+** Returns          pointer to the rcb.
+**
+*******************************************************************************/
+tBTA_GATTS_SRVC_CB * bta_gatts_find_srvc_cb_by_srvc_id(tBTA_GATTS_CB *p_cb, UINT16 service_id)
+{
+    UINT8 i;
+    APPL_TRACE_DEBUG("bta_gatts_find_srvc_cb_by_srvc_id  service_id=%d", service_id);
+    for (i = 0; i < BTA_GATTS_MAX_SRVC_NUM; i ++)
+    {
+        if (p_cb->srvc_cb[i].in_use &&
+            p_cb->srvc_cb[i].service_id == service_id)
+        {
+            APPL_TRACE_DEBUG("bta_gatts_find_srvc_cb_by_srvc_id  found service cb index =%d", i);
+            return &p_cb->srvc_cb[i];
+        }
+    }
+    return NULL;
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_find_srvc_cb_by_attr_id
+**
+** Description      find the service control block by attribute ID.
+**
+** Returns          pointer to the rcb.
+**
+*******************************************************************************/
+tBTA_GATTS_SRVC_CB * bta_gatts_find_srvc_cb_by_attr_id(tBTA_GATTS_CB *p_cb, UINT16 attr_id)
+{
+    UINT8 i;
+
+    for (i = 0; i < (BTA_GATTS_MAX_SRVC_NUM); i ++)
+    {
+        if (/* middle service */
+            (i < (BTA_GATTS_MAX_SRVC_NUM - 1) &&
+             p_cb->srvc_cb[i].in_use &&
+             p_cb->srvc_cb[i + 1].in_use &&
+             attr_id >= p_cb->srvc_cb[i].service_id &&
+             attr_id < p_cb->srvc_cb[i + 1].service_id) ||
+            /* last active service */
+            (i < (BTA_GATTS_MAX_SRVC_NUM - 1) &&
+             p_cb->srvc_cb[i].in_use &&
+             !p_cb->srvc_cb[i + 1].in_use &&
+             attr_id >= p_cb->srvc_cb[i].service_id)    ||
+            /* last service incb */
+            (i == (BTA_GATTS_MAX_SRVC_NUM - 1) &&
+             attr_id >= p_cb->srvc_cb[i].service_id)
+           )
+        {
+            return &p_cb->srvc_cb[i];
+        }
+    }
+    return NULL;
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_uuid_compare
+**
+** Description      Compare two UUID to see if they are the same.
+**
+** Returns          TRUE if two uuid match; FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN bta_gatts_uuid_compare(tBT_UUID tar, tBT_UUID src)
+{
+    UINT8  su[LEN_UUID_128], tu[LEN_UUID_128];
+    UINT8  *ps, *pt;
+
+    /* any of the UUID is unspecified */
+    if (src.len == 0 || tar.len == 0)
+    {
+        return TRUE;
+    }
+
+    /* If both are 16-bit, we can do a simple compare */
+    if (src.len == 2 && tar.len == 2)
+    {
+        return src.uu.uuid16 == tar.uu.uuid16;
+    }
+
+    /* One or both of the UUIDs is 128-bit */
+    if (src.len == LEN_UUID_16)
+    {
+        /* convert a 16 bits UUID to 128 bits value */
+        bta_gatt_convert_uuid16_to_uuid128(su, src.uu.uuid16);
+        ps = su;
+    }
+    else
+        ps = src.uu.uuid128;
+
+    if (tar.len == LEN_UUID_16)
+    {
+        /* convert a 16 bits UUID to 128 bits value */
+        bta_gatt_convert_uuid16_to_uuid128(tu, tar.uu.uuid16);
+        pt = tu;
+    }
+    else
+        pt = tar.uu.uuid128;
+
+    return(memcmp(ps, pt, LEN_UUID_128) == 0);
+}
+
+
+
+
+#endif

+ 1329 - 0
components/bt/bluedroid/bta/hh/bta_hh_act.c

@@ -0,0 +1,1329 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2005-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This file contains the HID host action functions.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
+
+#include <string.h>
+
+#include "bta_sys.h"
+#include "btm_api.h"
+#include "l2c_api.h"
+#include "bta_hh_int.h"
+#include "bta_hh_co.h"
+#include "utl.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+
+/*****************************************************************************
+**  Local Function prototypes
+*****************************************************************************/
+static void bta_hh_cback (UINT8 dev_handle, BD_ADDR addr, UINT8 event,
+                            UINT32 data, BT_HDR *pdata);
+static tBTA_HH_STATUS bta_hh_get_trans_status(UINT32 result);
+
+#if BTA_HH_DEBUG
+static char* bta_hh_get_w4_event(UINT16 event);
+static char * bta_hh_hid_event_name(UINT16 event);
+#endif
+
+/*****************************************************************************
+**  Action Functions
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function         bta_hh_api_enable
+**
+** Description      Perform necessary operations to enable HID host.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_api_enable(tBTA_HH_DATA *p_data)
+{
+    tBTA_HH_STATUS      status = BTA_HH_ERR;
+    UINT8               xx;
+
+    /* initialize BTE HID */
+    HID_HostInit();
+
+    memset(&bta_hh_cb, 0, sizeof(tBTA_HH_CB));
+
+    HID_HostSetSecurityLevel("", p_data->api_enable.sec_mask);
+
+    /* Register with L2CAP */
+    if ( HID_HostRegister (bta_hh_cback) == HID_SUCCESS)
+    {
+        /* store parameters */
+        bta_hh_cb.p_cback = p_data->api_enable.p_cback;
+
+        status = BTA_HH_OK;
+        /* initialize device CB */
+        for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx ++)
+        {
+            bta_hh_cb.kdev[xx].state        = BTA_HH_IDLE_ST;
+            bta_hh_cb.kdev[xx].hid_handle   = BTA_HH_INVALID_HANDLE;
+            bta_hh_cb.kdev[xx].index        = xx;
+        }
+
+        /* initialize control block map */
+        for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx ++)
+            bta_hh_cb.cb_index[xx]          = BTA_HH_IDX_INVALID;
+    }
+
+#if (BTA_HH_LE_INCLUDED == TRUE)
+    if (status == BTA_HH_OK)
+    {
+        bta_hh_le_enable();
+    }
+    else
+#endif
+        /* signal BTA call back event */
+        (* bta_hh_cb.p_cback)(BTA_HH_ENABLE_EVT, (tBTA_HH *)&status);
+}
+/*******************************************************************************
+**
+** Function         bta_hh_api_disable
+**
+** Description      Perform necessary operations to disable HID host.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_api_disable(void)
+{
+    UINT8 xx;
+
+    /* service is not enabled */
+    if (bta_hh_cb.p_cback == NULL)
+        return;
+
+    /* no live connection, signal DISC_CMPL_EVT directly */
+    if (!bta_hh_cb.cnt_num)
+    {
+        bta_hh_disc_cmpl();
+    }
+    else /* otherwise, disconnect all live connections */
+    {
+        bta_hh_cb.w4_disable = TRUE;
+
+        for(xx = 0; xx < BTA_HH_MAX_DEVICE; xx ++)
+        {
+            /* send API_CLOSE event to every connected device */
+            if ( bta_hh_cb.kdev[xx].state == BTA_HH_CONN_ST )
+            {
+                /* disconnect all connected devices */
+                bta_hh_sm_execute(&bta_hh_cb.kdev[xx],
+                                BTA_HH_API_CLOSE_EVT,
+                                NULL);
+            }
+        }
+    }
+
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_disc_cmpl
+**
+** Description      All connections have been closed, disable service.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_disc_cmpl(void)
+{
+    tBTA_HH_STATUS  status = BTA_HH_OK;
+
+    /* Deregister with lower layer */
+    if (HID_HostDeregister() != HID_SUCCESS)
+        status = BTA_HH_ERR;
+
+#if (BTA_HH_LE_INCLUDED == TRUE)
+    bta_hh_le_deregister();
+    UNUSED(status);
+#else
+    bta_hh_cleanup_disable(status);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_sdp_cback
+**
+** Description      SDP callback function.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hh_sdp_cback(UINT16 result, UINT16 attr_mask,
+                                  tHID_DEV_SDP_INFO *sdp_rec )
+{
+    tBTA_HH_DEV_CB     *p_cb = bta_hh_cb.p_cur;
+    UINT8              hdl = 0;
+    tBTA_HH_STATUS    status = BTA_HH_ERR_SDP;
+
+    /* make sure sdp succeeded and hh has not been disabled */
+    if ((result == SDP_SUCCESS) && (p_cb != NULL))
+    {
+        /* security is required for the connection, add attr_mask bit*/
+        if (p_cb->sec_mask)
+            attr_mask |= HID_SEC_REQUIRED;
+
+#if BTA_HH_DEBUG
+        APPL_TRACE_EVENT("bta_hh_sdp_cback: p_cb: %d result 0x%02x, \
+                            attr_mask 0x%02x, handle %x", \
+                            p_cb, result, attr_mask,p_cb->hid_handle);
+#endif
+
+        /* check to see type of device is supported , and should not been added before */
+        if (bta_hh_tod_spt(p_cb, sdp_rec->sub_class))
+        {
+            /* if not added before */
+            if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE)
+            {
+                /*  add device/update attr_mask information */
+                if(HID_HostAddDev (p_cb->addr, attr_mask, &hdl) == HID_SUCCESS)
+                {
+                    status = BTA_HH_OK;
+                    /* update cb_index[] map */
+                    bta_hh_cb.cb_index[hdl] = p_cb->index;
+                }
+                else
+                {
+                    p_cb->app_id = 0;
+                }
+            }
+            else
+            {
+                hdl = p_cb->hid_handle;
+            }
+            /* else : incoming connection after SDP should update the SDP information as well */
+
+            if (p_cb->app_id != 0)
+            {
+                /* update cb information with attr_mask, dscp_info etc. */
+                bta_hh_add_device_to_list(p_cb,  hdl, attr_mask,
+                                            &sdp_rec->dscp_info,
+                                            sdp_rec->sub_class,
+                                            sdp_rec->ssr_max_latency,
+                                            sdp_rec->ssr_min_tout,
+                                            p_cb->app_id);
+
+                p_cb->dscp_info.ctry_code = sdp_rec->ctry_code;
+
+                status = BTA_HH_OK;
+            }
+
+        }
+        else /* type of device is not supported */
+            status = BTA_HH_ERR_TOD_UNSPT;
+    }
+
+    /* free disc_db when SDP is completed */
+    utl_freebuf((void **)&bta_hh_cb.p_disc_db);
+
+    /* send SDP_CMPL_EVT into state machine */
+    bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
+
+    return;
+}
+/*******************************************************************************
+**
+** Function         bta_hh_di_sdp_cback
+**
+** Description      SDP DI callback function.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hh_di_sdp_cback(UINT16 result)
+{
+    tBTA_HH_DEV_CB     *p_cb = bta_hh_cb.p_cur;
+    tBTA_HH_STATUS         status = BTA_HH_ERR_SDP;
+    tSDP_DI_GET_RECORD  di_rec;
+    tHID_STATUS ret;
+#if BTA_HH_DEBUG
+    APPL_TRACE_EVENT("bta_hh_di_sdp_cback: p_cb: %d result 0x%02x", p_cb, result);
+#endif
+
+    /* if DI record does not exist on remote device, vendor_id in tBTA_HH_DEV_DSCP_INFO will be
+         * set to 0xffff and we will allow the connection to go through. Spec mandates that DI
+         * record be set, but many HID devices do not set this. So for IOP purposes, we allow the
+         * connection to go through and update the DI record to invalid DI entry.*/
+    if (((result == SDP_SUCCESS) || (result == SDP_NO_RECS_MATCH)) && (p_cb != NULL))
+    {
+        if(result == SDP_SUCCESS && SDP_GetNumDiRecords(bta_hh_cb.p_disc_db) != 0)
+        {
+            /* always update information with primary DI record */
+            if (SDP_GetDiRecord(1, &di_rec, bta_hh_cb.p_disc_db) == SDP_SUCCESS)
+            {
+                bta_hh_update_di_info(p_cb, di_rec.rec.vendor, di_rec.rec.product, di_rec.rec.version, 0);
+            }
+
+        }
+        else /* no DI recrod available */
+        {
+            bta_hh_update_di_info(p_cb, BTA_HH_VENDOR_ID_INVALID, 0, 0, 0);
+        }
+
+        if ((ret = HID_HostGetSDPRecord(p_cb->addr,
+                                 bta_hh_cb.p_disc_db,
+                                 p_bta_hh_cfg->sdp_db_size,
+                                 bta_hh_sdp_cback)) == HID_SUCCESS)
+        {
+            status = BTA_HH_OK;
+        }
+        else
+        {
+#if BTA_HH_DEBUG
+            APPL_TRACE_DEBUG ("bta_hh_di_sdp_cback:  HID_HostGetSDPRecord failed: Status 0x%2x",
+                               ret);
+#endif
+        }
+    }
+
+
+    if (status != BTA_HH_OK)
+    {
+        utl_freebuf((void **)&bta_hh_cb.p_disc_db);
+        /* send SDP_CMPL_EVT into state machine */
+        bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
+    }
+    return;
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hh_start_sdp
+**
+** Description      Start SDP service search, and obtain necessary SDP records.
+**                  Only one SDP service search request is allowed at the same
+**                  time. For every BTA_HhOpen API call, do SDP first unless SDP
+**                  has been done previously.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_start_sdp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+    tBTA_HH_STATUS          status = BTA_HH_ERR_SDP;
+    UINT8                   hdl;
+
+    p_cb->sec_mask  = p_data->api_conn.sec_mask;
+    p_cb->mode      = p_data->api_conn.mode;
+    bta_hh_cb.p_cur = p_cb;
+
+#if (BTA_HH_LE_INCLUDED == TRUE)
+    if (bta_hh_is_le_device(p_cb, p_data->api_conn.bd_addr))
+    {
+        bta_hh_le_open_conn(p_cb, p_data->api_conn.bd_addr);
+        return;
+    }
+#endif
+
+    /* if previously virtually cabled device, skip SDP */
+    if (p_cb->app_id)
+    {
+        status = BTA_HH_OK;
+#if BTA_HH_DEBUG
+        APPL_TRACE_DEBUG("bta_hh_start_sdp:: skip SDP for known devices");
+#endif
+        if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE)
+        {
+            if (HID_HostAddDev (p_cb->addr, p_cb->attr_mask, &hdl) \
+                == HID_SUCCESS)
+            {
+                /* update device CB with newly register device handle */
+                bta_hh_add_device_to_list(p_cb,  hdl, p_cb->attr_mask, NULL,
+                                          p_cb->sub_class,
+                                          p_cb->dscp_info.ssr_max_latency,
+                                          p_cb->dscp_info.ssr_min_tout,
+                                          p_cb->app_id);
+                /* update cb_index[] map */
+                bta_hh_cb.cb_index[hdl] = p_cb->index;
+            }
+            else
+                status = BTA_HH_ERR_NO_RES;
+        }
+        bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
+
+        return;
+    }
+    /* GetSDPRecord. at one time only one SDP precedure can be active */
+    else if (!bta_hh_cb.p_disc_db)
+    {
+        bta_hh_cb.p_disc_db = (tSDP_DISCOVERY_DB *) GKI_getbuf(p_bta_hh_cfg->sdp_db_size);
+
+        if (bta_hh_cb.p_disc_db == NULL)
+        {
+            status = BTA_HH_ERR_NO_RES;
+        }
+        else
+        {
+            bta_hh_cb.p_cur = p_cb;
+            /* do DI discovery first */
+            if (SDP_DiDiscover(p_data->api_conn.bd_addr,
+                                         bta_hh_cb.p_disc_db,
+                                         p_bta_hh_cfg->sdp_db_size,
+                                         bta_hh_di_sdp_cback) != SDP_SUCCESS)
+            {
+#if BTA_HH_DEBUG
+                APPL_TRACE_DEBUG ("bta_hh_start_sdp:  SDP_DiDiscover failed: \
+                    Status 0x%2X",status);
+#endif
+                status = BTA_HH_ERR_SDP;
+                utl_freebuf((void **)&bta_hh_cb.p_disc_db);
+            }
+            else
+                status = BTA_HH_OK;
+        }
+    }
+
+    if (status != BTA_HH_OK)
+        bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
+
+    return;
+
+}
+/*******************************************************************************
+**
+** Function         bta_hh_sdp_cmpl
+**
+** Description      When SDP completed, initiate a connection or report error depend
+**                  on SDP result.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_sdp_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+    tBTA_HH_CONN            conn_dat;
+    tBTA_HH_STATUS          status = p_data->status;
+
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG ("bta_hh_sdp_cmpl:  status 0x%2X",p_data->status);
+#endif
+
+    /* initialize call back data */
+    memset((void *)&conn_dat, 0, sizeof(tBTA_HH_CONN));
+    conn_dat.handle = p_cb->hid_handle;
+    bdcpy(conn_dat.bda, p_cb->addr);
+
+    /* if SDP compl success */
+    if ( status == BTA_HH_OK)
+    {
+        /* not incoming connection doing SDP, initiate a HID connection */
+        if (!p_cb->incoming_conn)
+        {
+            tHID_STATUS ret;
+            /* set security level */
+            HID_HostSetSecurityLevel("", p_cb->sec_mask);
+
+            /* open HID connection */
+            if ((ret = HID_HostOpenDev (p_cb->hid_handle)) != HID_SUCCESS)
+            {
+#if BTA_HH_DEBUG
+                APPL_TRACE_DEBUG ("bta_hh_sdp_cmpl:  HID_HostOpenDev failed: \
+                    Status 0x%2X",ret);
+#endif
+                /* open fail, remove device from management device list */
+                HID_HostRemoveDev( p_cb->hid_handle);
+                status = BTA_HH_ERR;
+            }
+            else
+            {
+                status = BTA_HH_OK;
+            }
+        }
+        else /* incoming connection SDP finish */
+        {
+            bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, NULL);
+        }
+    }
+
+    if (status != BTA_HH_OK)
+    {
+        /* Check if this was incoming connection request  from an unknown device
+           **and connection failed due to missing HID Device SDP UUID
+           **In above condition, disconnect the link as well as remove the
+           **device from list of HID devices*/
+        if ((status == BTA_HH_ERR_SDP) &&
+           (p_cb->incoming_conn) &&(p_cb->app_id == 0))
+        {
+            APPL_TRACE_DEBUG ("bta_hh_sdp_cmpl:SDP failed for  incoming conn :hndl %d",
+                                p_cb->incoming_hid_handle);
+            HID_HostRemoveDev( p_cb->incoming_hid_handle);
+        }
+        conn_dat.status = status;
+        (* bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
+
+        /* move state machine W4_CONN ->IDLE */
+        bta_hh_sm_execute(p_cb, BTA_HH_API_CLOSE_EVT, NULL);
+
+        /* if this is an outgoing connection to an unknown device, clean up cb */
+        if (p_cb->app_id == 0 && !p_cb->incoming_conn)
+        {
+            /* clean up device control block */
+            bta_hh_clean_up_kdev(p_cb);
+        }
+#if BTA_HH_DEBUG
+        bta_hh_trace_dev_db();
+#endif
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_api_disc_act
+**
+** Description      HID Host initiate a disconnection.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_api_disc_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+    tBTA_HH_CBDATA    disc_dat;
+    tHID_STATUS     status;
+
+#if BTA_HH_LE_INCLUDED == TRUE
+    if (p_cb->is_le_device)
+        bta_hh_le_api_disc_act(p_cb);
+    else
+#endif
+    {
+        /* found an active connection */
+        disc_dat.handle = p_data ?(UINT8)p_data->hdr.layer_specific :p_cb->hid_handle;
+        disc_dat.status = BTA_HH_ERR;
+
+        status = HID_HostCloseDev(disc_dat.handle);
+
+        if (status)
+            (* bta_hh_cb.p_cback)(BTA_HH_CLOSE_EVT, (tBTA_HH *)&disc_dat);
+    }
+
+    return;
+
+}
+/*******************************************************************************
+**
+** Function         bta_hh_open_cmpl_act
+**
+** Description      HID host connection completed
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_open_cmpl_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+    tBTA_HH_CONN        conn ;
+    UINT8   dev_handle = p_data ? (UINT8)p_data->hid_cback.hdr.layer_specific : \
+                        p_cb->hid_handle;
+
+    memset((void *)&conn, 0, sizeof (tBTA_HH_CONN));
+    conn.handle = dev_handle;
+    bdcpy(conn.bda, p_cb->addr);
+
+    /* increase connection number */
+    bta_hh_cb.cnt_num ++;
+
+    /* initialize device driver */
+    bta_hh_co_open(p_cb->hid_handle, p_cb->sub_class,
+                       p_cb->attr_mask,  p_cb->app_id);
+
+#if (BTA_HH_LE_INCLUDED == TRUE)
+    conn.status = p_cb->status;
+    conn.le_hid = p_cb->is_le_device;
+    conn.scps_supported = p_cb->scps_supported;
+
+    if (!p_cb->is_le_device)
+#endif
+    {
+        /* inform role manager */
+        bta_sys_conn_open( BTA_ID_HH ,p_cb->app_id, p_cb->addr);
+    }
+    /* set protocol mode when not default report mode */
+    if ( p_cb->mode != BTA_HH_PROTO_RPT_MODE
+#if (BTA_HH_LE_INCLUDED == TRUE)
+         && !p_cb->is_le_device
+#endif
+        )
+    {
+        if ((HID_HostWriteDev(dev_handle,
+                              HID_TRANS_SET_PROTOCOL, HID_PAR_PROTOCOL_BOOT_MODE,
+                              0,
+                              0, NULL)) != HID_SUCCESS)
+        {
+            /* HID connection is up, while SET_PROTO fail */
+            conn.status = BTA_HH_ERR_PROTO;
+            (* bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn);
+        }
+        else
+        {
+            conn.status = BTA_HH_OK;
+            p_cb->w4_evt = BTA_HH_OPEN_EVT;
+        }
+    }
+    else
+        (* bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn);
+
+    p_cb->incoming_conn = FALSE;
+    p_cb->incoming_hid_handle = BTA_HH_INVALID_HANDLE;
+
+}
+/*******************************************************************************
+**
+** Function         bta_hh_open_act
+**
+** Description      HID host receive HID_OPEN_EVT .
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_open_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+    tBTA_HH_API_CONN    conn_data;
+
+    UINT8   dev_handle = p_data ? (UINT8)p_data->hid_cback.hdr.layer_specific : \
+                        p_cb->hid_handle;
+
+#if BTA_HH_DEBUG
+    APPL_TRACE_EVENT ("bta_hh_open_act:  Device[%d] connected", dev_handle);
+#endif
+
+    /* SDP has been done */
+    if (p_cb->app_id != 0)
+    {
+        bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, p_data);
+    }
+    else
+    /*  app_id == 0 indicates an incoming conenction request arrives without SDP
+        performed, do it first */
+    {
+        p_cb->incoming_conn = TRUE;
+        /* store the handle here in case sdp fails - need to disconnect */
+        p_cb->incoming_hid_handle = dev_handle;
+
+        memset(&conn_data, 0, sizeof(tBTA_HH_API_CONN));
+        bdcpy(conn_data.bd_addr, p_cb->addr);
+        bta_hh_start_sdp(p_cb, (tBTA_HH_DATA *)&conn_data);
+    }
+
+    return;
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hh_data_act
+**
+** Description      HID Host process a data report
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_data_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA * p_data)
+{
+    BT_HDR  *pdata = p_data->hid_cback.p_data;
+    UINT8   *p_rpt = (UINT8 *)(pdata + 1) + pdata->offset;
+
+    bta_hh_co_data((UINT8)p_data->hid_cback.hdr.layer_specific, p_rpt, pdata->len,
+                    p_cb->mode, p_cb->sub_class, p_cb->dscp_info.ctry_code, p_cb->addr, p_cb->app_id);
+
+    utl_freebuf((void **)&pdata);
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hh_handsk_act
+**
+** Description      HID Host process a handshake acknoledgement.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_handsk_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA * p_data)
+{
+    tBTA_HH_CBDATA  cback_data ;
+    tBTA_HH_HSDATA  hs_data;
+    tBTA_HH_CONN    conn ;
+
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG("HANDSHAKE received for: event = %s data= %d",
+        bta_hh_get_w4_event(p_cb->w4_evt), p_data->hid_cback.data);
+#endif
+
+    memset(&hs_data, 0, sizeof(tBTA_HH_HSDATA));
+    memset(&cback_data, 0, sizeof(tBTA_HH_CBDATA));
+
+    switch (p_cb->w4_evt)
+    {
+        /* GET_ transsaction, handshake indicate unsupported request */
+        case BTA_HH_GET_PROTO_EVT:
+            hs_data.rsp_data.proto_mode = BTA_HH_PROTO_UNKNOWN;
+            /* fall through */
+        case BTA_HH_GET_RPT_EVT:
+        case BTA_HH_GET_IDLE_EVT :
+            hs_data.handle = p_cb->hid_handle;
+            /* if handshake gives an OK code for these transaction, fill in UNSUPT */
+            if ((hs_data.status = bta_hh_get_trans_status(p_data->hid_cback.data)) == BTA_HH_OK)
+                 hs_data.status = BTA_HH_HS_TRANS_NOT_SPT;
+
+            (* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&hs_data);
+            p_cb->w4_evt = 0;
+            break;
+
+        /* acknoledgement from HID device for SET_ transaction */
+        case BTA_HH_SET_RPT_EVT:
+        case BTA_HH_SET_PROTO_EVT:
+        case BTA_HH_SET_IDLE_EVT :
+            cback_data.handle  = p_cb->hid_handle;
+            cback_data.status = bta_hh_get_trans_status(p_data->hid_cback.data);
+            (* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&cback_data);
+            p_cb->w4_evt = 0;
+            break;
+
+        /* SET_PROTOCOL when open connection */
+        case BTA_HH_OPEN_EVT:
+            conn.status =p_data->hid_cback.data ? BTA_HH_ERR_PROTO: BTA_HH_OK;
+            conn.handle = p_cb->hid_handle;
+            bdcpy(conn.bda, p_cb->addr);
+            (* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&conn);
+#if BTA_HH_DEBUG
+            bta_hh_trace_dev_db();
+#endif
+            p_cb->w4_evt = 0;
+            break;
+
+        default:
+            /* unknow transaction handshake response */
+            APPL_TRACE_DEBUG("unknown transaction type");
+            break;
+    }
+
+    /* transaction achknoledgement received, inform PM for mode change */
+    bta_sys_idle(BTA_ID_HH, p_cb->app_id, p_cb->addr);
+    return;
+}
+/*******************************************************************************
+**
+** Function         bta_hh_ctrl_dat_act
+**
+** Description      HID Host process a data report from control channel.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_ctrl_dat_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA * p_data)
+{
+    BT_HDR          *pdata = p_data->hid_cback.p_data;
+    UINT8           *data = (UINT8 *)(pdata + 1) + pdata->offset;
+    tBTA_HH_HSDATA    hs_data;
+
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG("Ctrl DATA received w4: event[%s]",
+                        bta_hh_get_w4_event(p_cb->w4_evt));
+#endif
+    hs_data.status  = BTA_HH_OK;
+    hs_data.handle  = p_cb->hid_handle;
+
+    switch (p_cb->w4_evt)
+    {
+    case BTA_HH_GET_IDLE_EVT:
+        hs_data.rsp_data.idle_rate = *data;
+        break;
+    case BTA_HH_GET_RPT_EVT:
+        hs_data.rsp_data.p_rpt_data = pdata;
+        break;
+    case BTA_HH_GET_PROTO_EVT:
+        /* match up BTE/BTA report/boot mode def*/
+        hs_data.rsp_data.proto_mode = ((*data) == HID_PAR_PROTOCOL_REPORT)? \
+                    BTA_HH_PROTO_RPT_MODE : BTA_HH_PROTO_BOOT_MODE;
+#if BTA_HH_DEBUG
+        APPL_TRACE_DEBUG("GET_PROTOCOL Mode = [%s]",
+            (hs_data.rsp_data.proto_mode == BTA_HH_PROTO_RPT_MODE)? "Report" : "Boot");
+#endif
+        break;
+    /* should not expect control DATA for SET_ transaction */
+    case BTA_HH_SET_PROTO_EVT:
+        /* fall through */
+    case BTA_HH_SET_RPT_EVT:
+        /* fall through */
+    case BTA_HH_SET_IDLE_EVT :
+        /* fall through */
+    default:
+#if BTA_HH_DEBUG
+        APPL_TRACE_DEBUG("invalid  transaction type for DATA payload: 4_evt[%s]",
+                        bta_hh_get_w4_event(p_cb->w4_evt));
+#endif
+        break;
+    }
+
+    /* inform PM for mode change */
+    bta_sys_busy(BTA_ID_HH, p_cb->app_id, p_cb->addr);
+    bta_sys_idle(BTA_ID_HH, p_cb->app_id, p_cb->addr);
+
+    (* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&hs_data);
+
+    p_cb->w4_evt = 0;
+    utl_freebuf((void **)&pdata);
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_open_failure
+**
+** Description      report HID open failure when at wait for connection state and receive
+**                  device close event.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_open_failure(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+    tBTA_HH_CONN            conn_dat ;
+    UINT32                  reason = p_data->hid_cback.data;    /* Reason for closing (32-bit) */
+
+    memset(&conn_dat, 0, sizeof(tBTA_HH_CONN));
+     conn_dat.handle = p_cb->hid_handle;
+     conn_dat.status = (reason == HID_ERR_AUTH_FAILED) ?
+                                    BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR;
+     bdcpy(conn_dat.bda, p_cb->addr);
+     HID_HostCloseDev(p_cb->hid_handle);
+
+     /* Report OPEN fail event */
+     (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
+
+#if BTA_HH_DEBUG
+    bta_hh_trace_dev_db();
+#endif
+    /* clean up control block, but retain SDP info and device handle */
+    p_cb->vp            = FALSE;
+    p_cb->w4_evt        = 0;
+
+    /* if no connection is active and HH disable is signaled, disable service */
+    if (bta_hh_cb.cnt_num == 0 && bta_hh_cb.w4_disable)
+    {
+        bta_hh_disc_cmpl();
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_close_act
+**
+** Description      HID Host process a close event
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_close_act (tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+    tBTA_HH_CONN            conn_dat ;
+    tBTA_HH_CBDATA          disc_dat = {BTA_HH_OK, 0};
+    UINT32                  reason = p_data->hid_cback.data;    /* Reason for closing (32-bit) */
+
+    /* if HID_HDEV_EVT_VC_UNPLUG was received, report BTA_HH_VC_UNPLUG_EVT */
+    UINT16     event = p_cb->vp ? BTA_HH_VC_UNPLUG_EVT : BTA_HH_CLOSE_EVT;
+
+    disc_dat.handle = p_cb->hid_handle;
+    disc_dat.status = p_data->hid_cback.data;
+
+    /* Check reason for closing */
+    if ((reason & (HID_L2CAP_CONN_FAIL|HID_L2CAP_REQ_FAIL)) ||  /* Failure to initialize connection (page timeout or l2cap error) */
+        (reason == HID_ERR_AUTH_FAILED) ||                      /* Authenication error (while initiating) */
+        (reason == HID_ERR_L2CAP_FAILED))                       /* Failure creating l2cap connection */
+    {
+        /* Failure in opening connection */
+        conn_dat.handle = p_cb->hid_handle;
+        conn_dat.status = (reason == HID_ERR_AUTH_FAILED) ? BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR;
+        bdcpy(conn_dat.bda, p_cb->addr);
+        HID_HostCloseDev(p_cb->hid_handle);
+
+        /* Report OPEN fail event */
+        (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
+
+#if BTA_HH_DEBUG
+        bta_hh_trace_dev_db();
+#endif
+        return;
+    }
+    /* otherwise report CLOSE/VC_UNPLUG event */
+    else
+    {
+        /* finaliza device driver */
+        bta_hh_co_close(p_cb->hid_handle, p_cb->app_id);
+        /* inform role manager */
+        bta_sys_conn_close( BTA_ID_HH ,p_cb->app_id, p_cb->addr);
+        /* update total conn number */
+        bta_hh_cb.cnt_num --;
+
+        if (disc_dat.status)
+            disc_dat.status = BTA_HH_ERR;
+
+        (*bta_hh_cb.p_cback)(event, (tBTA_HH *)&disc_dat);
+
+        /* if virtually unplug, remove device */
+        if (p_cb->vp )
+        {
+            HID_HostRemoveDev( p_cb->hid_handle);
+            bta_hh_clean_up_kdev(p_cb);
+        }
+
+#if BTA_HH_DEBUG
+        bta_hh_trace_dev_db();
+#endif
+    }
+
+    /* clean up control block, but retain SDP info and device handle */
+    p_cb->vp            = FALSE;
+    p_cb->w4_evt        = 0;
+
+    /* if no connection is active and HH disable is signaled, disable service */
+    if (bta_hh_cb.cnt_num == 0 && bta_hh_cb.w4_disable)
+    {
+        bta_hh_disc_cmpl();
+    }
+
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_get_dscp_act
+**
+** Description      Get device report descriptor
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_get_dscp_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+    UNUSED(p_data);
+
+#if (BTA_HH_LE_INCLUDED == TRUE)
+    if (p_cb->is_le_device)
+    {
+        bta_hh_le_get_dscp_act(p_cb);
+    }
+    else
+#endif
+    (*bta_hh_cb.p_cback)(BTA_HH_GET_DSCP_EVT, (tBTA_HH *)&p_cb->dscp_info);
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_maint_dev_act
+**
+** Description      HID Host maintain device list.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_maint_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+    tBTA_HH_MAINT_DEV       *p_dev_info = &p_data->api_maintdev;
+    tBTA_HH_DEV_INFO        dev_info ;
+    UINT8                   dev_handle;
+
+    dev_info.status = BTA_HH_ERR;
+    dev_info.handle = BTA_HH_INVALID_HANDLE;
+
+    switch (p_dev_info->sub_event)
+    {
+    case BTA_HH_ADD_DEV_EVT:    /* add a device */
+        bdcpy(dev_info.bda, p_dev_info->bda);
+        /* initialize callback data */
+        if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE)
+        {
+#if (BTA_HH_LE_INCLUDED == TRUE)
+            if (bta_hh_is_le_device(p_cb, p_data->api_conn.bd_addr))
+            {
+                dev_info.handle   = bta_hh_le_add_device(p_cb, p_dev_info);
+                dev_info.status   = BTA_HH_OK;
+            }
+            else
+#endif
+
+            if (HID_HostAddDev(p_dev_info->bda, p_dev_info->attr_mask, &dev_handle)\
+                            == HID_SUCCESS)
+            {
+                dev_info.handle   = dev_handle;
+                dev_info.status   = BTA_HH_OK;
+
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+                /* update DI information */
+                bta_hh_update_di_info(p_cb,
+                                      p_dev_info->dscp_info.vendor_id,
+                                      p_dev_info->dscp_info.product_id,
+                                      p_dev_info->dscp_info.version,
+                                      p_dev_info->dscp_info.flag);
+#else
+                bta_hh_update_di_info(p_cb,
+                                      p_dev_info->dscp_info.vendor_id,
+                                      p_dev_info->dscp_info.product_id,
+                                      p_dev_info->dscp_info.version,
+                                      0);
+
+#endif
+                /* add to BTA device list */
+                bta_hh_add_device_to_list(p_cb, dev_handle,
+                                          p_dev_info->attr_mask,
+                                          &p_dev_info->dscp_info.descriptor,
+                                          p_dev_info->sub_class,
+                                          p_dev_info->dscp_info.ssr_max_latency,
+                                          p_dev_info->dscp_info.ssr_min_tout,
+                                          p_dev_info->app_id);
+                /* update cb_index[] map */
+                bta_hh_cb.cb_index[dev_handle] = p_cb->index;
+            }
+        }
+        else    /* device already been added */
+        {
+            dev_info.handle = p_cb->hid_handle;
+            dev_info.status = BTA_HH_OK;
+        }
+#if BTA_HH_DEBUG
+        bta_hh_trace_dev_db();
+#endif
+
+        break;
+    case BTA_HH_RMV_DEV_EVT:    /* remove device */
+        dev_info.handle = (UINT8)p_dev_info->hdr.layer_specific;
+        bdcpy(dev_info.bda, p_cb->addr);
+
+#if BTA_HH_LE_INCLUDED == TRUE
+        if (p_cb->is_le_device)
+        {
+            bta_hh_le_remove_dev_bg_conn(p_cb);
+            bta_hh_sm_execute(p_cb, BTA_HH_API_CLOSE_EVT, NULL);
+            bta_hh_clean_up_kdev(p_cb);
+        }
+        else
+#endif
+        {
+            if(HID_HostRemoveDev( dev_info.handle ) == HID_SUCCESS)
+            {
+                dev_info.status  = BTA_HH_OK;
+
+                /* remove from known device list in BTA */
+                bta_hh_clean_up_kdev(p_cb);
+            }
+        }
+        break;
+
+    default:
+        APPL_TRACE_DEBUG("invalid command");
+        break;
+    }
+
+    (* bta_hh_cb.p_cback)(p_dev_info->sub_event, (tBTA_HH *)&dev_info);
+}
+/*******************************************************************************
+**
+** Function         bta_hh_write_dev_act
+**
+** Description      Write device action. can be SET/GET/DATA transaction.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+    tBTA_HH_CBDATA     cbdata = {BTA_HH_OK, 0};
+    UINT16  event = (p_data->api_sndcmd.t_type - BTA_HH_FST_BTE_TRANS_EVT) +
+                        BTA_HH_FST_TRANS_CB_EVT;
+
+#if BTA_HH_LE_INCLUDED == TRUE
+    if (p_cb->is_le_device)
+        bta_hh_le_write_dev_act(p_cb, p_data);
+    else
+#endif
+    {
+
+    cbdata.handle = p_cb->hid_handle;
+
+    /* match up BTE/BTA report/boot mode def */
+    if (p_data->api_sndcmd.t_type == HID_TRANS_SET_PROTOCOL)
+    {
+        p_data->api_sndcmd.param = ( p_data->api_sndcmd.param == BTA_HH_PROTO_RPT_MODE) ?\
+                        HID_PAR_PROTOCOL_REPORT :HID_PAR_PROTOCOL_BOOT_MODE;
+    }
+
+    if (HID_HostWriteDev (p_cb->hid_handle,
+                       p_data->api_sndcmd.t_type,
+                       p_data->api_sndcmd.param,
+                       p_data->api_sndcmd.data,
+                       p_data->api_sndcmd.rpt_id,
+                       p_data->api_sndcmd.p_data) != HID_SUCCESS)
+    {
+        APPL_TRACE_ERROR("HID_HostWriteDev Error ");
+        cbdata.status = BTA_HH_ERR;
+
+        if (p_data->api_sndcmd.t_type != HID_TRANS_CONTROL &&
+            p_data->api_sndcmd.t_type != HID_TRANS_DATA)
+            (* bta_hh_cb.p_cback)(event, (tBTA_HH *)&cbdata);
+        else if (p_data->api_sndcmd.param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG)
+            (* bta_hh_cb.p_cback)(BTA_HH_VC_UNPLUG_EVT, (tBTA_HH *)&cbdata);
+    }
+    else
+    {
+
+        switch(p_data->api_sndcmd.t_type)
+        {
+        case HID_TRANS_SET_PROTOCOL:
+            /* fall through */
+        case HID_TRANS_GET_REPORT:
+            /* fall through */
+        case HID_TRANS_SET_REPORT:
+            /* fall through */
+        case HID_TRANS_GET_PROTOCOL:
+            /* fall through */
+        case HID_TRANS_GET_IDLE:
+            /* fall through */
+        case HID_TRANS_SET_IDLE:/* set w4_handsk event name for callback function use */
+            p_cb->w4_evt = event;
+            break;
+        case HID_TRANS_DATA:  /* output report */
+            /* fall through */
+        case HID_TRANS_CONTROL:
+            /* no handshake event will be generated */
+            /* if VC_UNPLUG is issued, set flag */
+            if (p_data->api_sndcmd.param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG)
+                p_cb->vp = TRUE;
+
+            break;
+        /* currently not expected */
+        case HID_TRANS_DATAC:
+        default:
+            APPL_TRACE_DEBUG("bta_hh_write_dev_act:: cmd type = %d",
+                            p_data->api_sndcmd.t_type);
+            break;
+        }
+
+        /* if not control type transaction, notify PM for energy control */
+        if (p_data->api_sndcmd.t_type != HID_TRANS_CONTROL)
+        {
+            /* inform PM for mode change */
+            bta_sys_busy(BTA_ID_HH, p_cb->app_id, p_cb->addr);
+            bta_sys_idle(BTA_ID_HH, p_cb->app_id, p_cb->addr);
+        }
+        else if (p_data->api_sndcmd.param == BTA_HH_CTRL_SUSPEND)
+        {
+			bta_sys_sco_close(BTA_ID_HH, p_cb->app_id, p_cb->addr);
+        }
+        else if (p_data->api_sndcmd.param == BTA_HH_CTRL_EXIT_SUSPEND)
+        {
+            bta_sys_busy(BTA_ID_HH, p_cb->app_id, p_cb->addr);
+        }
+    }
+
+    }
+    return;
+}
+
+/*****************************************************************************
+**  Static Function
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function         bta_hh_cback
+**
+** Description      BTA HH callback function.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hh_cback (UINT8 dev_handle, BD_ADDR addr, UINT8 event,
+                        UINT32 data, BT_HDR *pdata)
+{
+    tBTA_HH_CBACK_DATA    *p_buf = NULL;
+    UINT16  sm_event = BTA_HH_INVALID_EVT;
+    UINT8   xx = 0;
+
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG("bta_hh_cback::HID_event [%s]", bta_hh_hid_event_name(event));
+#endif
+
+    switch (event)
+    {
+    case HID_HDEV_EVT_OPEN:
+        sm_event = BTA_HH_INT_OPEN_EVT;
+        break;
+    case HID_HDEV_EVT_CLOSE:
+        sm_event = BTA_HH_INT_CLOSE_EVT;
+        break;
+    case HID_HDEV_EVT_INTR_DATA:
+        sm_event = BTA_HH_INT_DATA_EVT;
+        break;
+    case HID_HDEV_EVT_HANDSHAKE:
+        sm_event = BTA_HH_INT_HANDSK_EVT;
+        break;
+    case HID_HDEV_EVT_CTRL_DATA:
+        sm_event = BTA_HH_INT_CTRL_DATA;
+        break;
+    case HID_HDEV_EVT_RETRYING:
+        break;
+    case HID_HDEV_EVT_INTR_DATC:
+    case HID_HDEV_EVT_CTRL_DATC:
+        /* Unhandled events: Free buffer for DATAC */
+        utl_freebuf((void **)&pdata);
+        break;
+    case HID_HDEV_EVT_VC_UNPLUG:
+        for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++)
+        {
+            if (bta_hh_cb.kdev[xx].hid_handle == dev_handle)
+            {
+               bta_hh_cb.kdev[xx].vp = TRUE;
+               break;
+            }
+        }
+        break;
+    }
+
+    if (sm_event != BTA_HH_INVALID_EVT &&
+        (p_buf = (tBTA_HH_CBACK_DATA *)GKI_getbuf(sizeof(tBTA_HH_CBACK_DATA) +
+                    sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->hdr.event  = sm_event;
+        p_buf->hdr.layer_specific = (UINT16)dev_handle;
+        p_buf->data       = data;
+        bdcpy(p_buf->addr, addr);
+        p_buf->p_data     = pdata;
+
+        bta_sys_sendmsg(p_buf);
+    }
+
+}
+/*******************************************************************************
+**
+** Function         bta_hh_get_trans_status
+**
+** Description      translate a handshake result code into BTA HH
+**                  status code
+**
+*******************************************************************************/
+static tBTA_HH_STATUS bta_hh_get_trans_status(UINT32 result)
+{
+    switch(result)
+    {
+    case HID_PAR_HANDSHAKE_RSP_SUCCESS :                /*   (0) */
+        return BTA_HH_OK;
+    case HID_PAR_HANDSHAKE_RSP_NOT_READY :              /*   (1) */
+    case HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID:      /*   (2) */
+    case HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ :    /*   (3) */
+    case HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM :      /*   (4) */
+        return (tBTA_HH_STATUS)result;
+    case HID_PAR_HANDSHAKE_RSP_ERR_UNKNOWN :            /*   (14) */
+    case HID_PAR_HANDSHAKE_RSP_ERR_FATAL  :             /*   (15) */
+    default:
+        return BTA_HH_HS_ERROR;
+        break;
+    }
+}
+/*****************************************************************************
+**  Debug Functions
+*****************************************************************************/
+
+#if (defined BTA_HH_DEBUG && BTA_HH_DEBUG == TRUE)
+static char* bta_hh_get_w4_event(UINT16 event)
+{
+    switch (event)
+    {
+    case BTA_HH_GET_RPT_EVT:
+        return "BTA_HH_GET_RPT_EVT";
+    case BTA_HH_SET_RPT_EVT:
+        return "BTA_HH_SET_RPT_EVT";
+    case BTA_HH_GET_PROTO_EVT:
+        return "BTA_HH_GET_PROTO_EVT";
+    case BTA_HH_SET_PROTO_EVT:
+        return "BTA_HH_SET_PROTO_EVT";
+    case BTA_HH_GET_IDLE_EVT:
+        return "BTA_HH_GET_IDLE_EVT";
+    case BTA_HH_SET_IDLE_EVT:
+        return "BTA_HH_SET_IDLE_EVT";
+    case BTA_HH_OPEN_EVT:
+        return "BTA_HH_OPEN_EVT";
+    default:
+        return "Unknown event";
+    }
+
+}
+
+static char * bta_hh_hid_event_name(UINT16 event)
+{
+    switch (event)
+    {
+    case HID_HDEV_EVT_OPEN:
+        return "HID_HDEV_EVT_OPEN";
+    case HID_HDEV_EVT_CLOSE:
+        return "HID_HDEV_EVT_CLOSE";
+    case HID_HDEV_EVT_RETRYING:
+        return "HID_HDEV_EVT_RETRYING";
+    case HID_HDEV_EVT_INTR_DATA:
+        return "HID_HDEV_EVT_INTR_DATA";
+    case HID_HDEV_EVT_INTR_DATC:
+        return "HID_HDEV_EVT_INTR_DATC";
+    case HID_HDEV_EVT_CTRL_DATA:
+        return "HID_HDEV_EVT_CTRL_DATA";
+    case HID_HDEV_EVT_CTRL_DATC:
+        return "HID_HDEV_EVT_CTRL_DATC";
+    case HID_HDEV_EVT_HANDSHAKE:
+        return "HID_HDEV_EVT_HANDSHAKE";
+    case HID_HDEV_EVT_VC_UNPLUG:
+        return "HID_HDEV_EVT_VC_UNPLUG";
+    default:
+        return "Unknown HID event";
+    }
+}
+#endif
+#endif /* BTA_HH_INCLUDED */
+

+ 496 - 0
components/bt/bluedroid/bta/hh/bta_hh_api.c

@@ -0,0 +1,496 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2005-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This file contains the HID HOST API in the subsystem of BTA.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "bta_hh_api.h"
+#include "bta_hh_int.h"
+#include "l2c_api.h"
+#include "utl.h"
+
+#define LOG_TAG "bt_bta_hh"
+#include "osi/include/log.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_hh_reg =
+{
+    bta_hh_hdl_event,
+    BTA_HhDisable
+};
+
+/*******************************************************************************
+**
+** Function         BTA_HhEnable
+**
+** Description      Enable the HID host.  This function must be called before
+**                  any other functions in the HID host API are called. When the
+**                  enable operation is complete the callback function will be
+**                  called with BTA_HH_ENABLE_EVT.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhEnable(tBTA_SEC sec_mask, tBTA_HH_CBACK *p_cback)
+{
+    tBTA_HH_API_ENABLE *p_buf;
+
+    /* register with BTA system manager */
+    bta_sys_register(BTA_ID_HH, &bta_hh_reg);
+
+    LOG_INFO("%s sec_mask:0x%x p_cback:%p", __func__, sec_mask, p_cback);
+    p_buf = (tBTA_HH_API_ENABLE *)GKI_getbuf((UINT16)sizeof(tBTA_HH_API_ENABLE));
+
+    if (p_buf != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_HH_API_ENABLE));
+
+        p_buf->hdr.event = BTA_HH_API_ENABLE_EVT;
+        p_buf->p_cback = p_cback;
+        p_buf->sec_mask = sec_mask;
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HhDisable
+**
+** Description      Disable the HID host. If the server is currently
+**                  connected, the connection will be closed.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhDisable(void)
+{
+    BT_HDR  *p_buf;
+
+    bta_sys_deregister(BTA_ID_HH);
+    if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_HH_API_DISABLE_EVT;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HhClose
+**
+** Description      Disconnect a connection.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhClose(UINT8 dev_handle)
+{
+    BT_HDR    *p_buf;
+
+    if ((p_buf = (BT_HDR *)GKI_getbuf((UINT16)sizeof(BT_HDR))) != NULL)
+    {
+        memset(p_buf, 0, sizeof(BT_HDR));
+        p_buf->event            = BTA_HH_API_CLOSE_EVT;
+        p_buf->layer_specific   = (UINT16) dev_handle;
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HhOpen
+**
+** Description      Connect to a device of specified BD address in specified
+**                  protocol mode and security level.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhOpen(BD_ADDR dev_bda, tBTA_HH_PROTO_MODE mode, tBTA_SEC sec_mask)
+{
+    tBTA_HH_API_CONN *p_buf;
+
+    p_buf = (tBTA_HH_API_CONN *)GKI_getbuf((UINT16)sizeof(tBTA_HH_API_CONN));
+
+    if (p_buf!= NULL)
+    {
+        memset((void *)p_buf, 0, sizeof(tBTA_HH_API_CONN));
+
+        p_buf->hdr.event            = BTA_HH_API_OPEN_EVT;
+        p_buf->hdr.layer_specific   = BTA_HH_INVALID_HANDLE;
+        p_buf->sec_mask             = sec_mask;
+        p_buf->mode                 = mode;
+        bdcpy(p_buf->bd_addr, dev_bda);
+
+        bta_sys_sendmsg((void *)p_buf);
+    }
+    else
+    {
+        APPL_TRACE_ERROR("No resource to send HID host Connect request.");
+    }
+}
+
+/*******************************************************************************
+**
+** Function  bta_hh_snd_write_dev
+**
+*******************************************************************************/
+static void bta_hh_snd_write_dev(UINT8 dev_handle, UINT8 t_type, UINT8 param,
+                                 UINT16 data, UINT8 rpt_id, BT_HDR  *p_data)
+{
+    tBTA_HH_CMD_DATA *p_buf;
+    UINT16          len = (UINT16) (sizeof(tBTA_HH_CMD_DATA) );
+
+    if ((p_buf = (tBTA_HH_CMD_DATA *)GKI_getbuf(len))!= NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_HH_CMD_DATA));
+
+        p_buf->hdr.event = BTA_HH_API_WRITE_DEV_EVT;
+        p_buf->hdr.layer_specific   = (UINT16) dev_handle;
+        p_buf->t_type   = t_type;
+        p_buf->data     = data;
+        p_buf->param    = param;
+        p_buf->p_data   = p_data;
+        p_buf->rpt_id   = rpt_id;
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+/*******************************************************************************
+**
+** Function         BTA_HhSetReport
+**
+** Description      send SET_REPORT to device.
+**
+** Parameter        dev_handle: device handle
+**                  r_type:     report type, could be BTA_HH_RPTT_OUTPUT or
+**                              BTA_HH_RPTT_FEATURE.
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhSetReport(UINT8 dev_handle, tBTA_HH_RPT_TYPE r_type, BT_HDR *p_data)
+{
+    bta_hh_snd_write_dev(dev_handle, HID_TRANS_SET_REPORT, r_type, 0, 0, p_data);
+}
+/*******************************************************************************
+**
+** Function         BTA_HhGetReport
+**
+** Description      Send a GET_REPORT to HID device.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhGetReport(UINT8 dev_handle, tBTA_HH_RPT_TYPE r_type, UINT8 rpt_id, UINT16 buf_size)
+{
+    UINT8 param = (buf_size) ? (r_type | 0x08) : r_type;
+
+    bta_hh_snd_write_dev(dev_handle, HID_TRANS_GET_REPORT, param,
+                        buf_size, rpt_id, NULL);
+}
+/*******************************************************************************
+**
+** Function         BTA_HhSetProtoMode
+**
+** Description      This function set the protocol mode at specified HID handle
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhSetProtoMode(UINT8 dev_handle, tBTA_HH_PROTO_MODE p_type)
+{
+    bta_hh_snd_write_dev(dev_handle, HID_TRANS_SET_PROTOCOL, (UINT8)p_type,
+                        0, 0, NULL);
+}
+/*******************************************************************************
+**
+** Function         BTA_HhGetProtoMode
+**
+** Description      This function get protocol mode information.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhGetProtoMode(UINT8 dev_handle)
+{
+    bta_hh_snd_write_dev(dev_handle, HID_TRANS_GET_PROTOCOL, 0, 0, 0, NULL);
+}
+/*******************************************************************************
+**
+** Function         BTA_HhSetIdle
+**
+** Description      send SET_IDLE to device.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhSetIdle(UINT8 dev_handle, UINT16 idle_rate)
+{
+    bta_hh_snd_write_dev(dev_handle, HID_TRANS_SET_IDLE, 0, idle_rate, 0, NULL);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HhGetIdle
+**
+** Description      Send a GET_IDLE from HID device.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhGetIdle(UINT8 dev_handle)
+{
+    bta_hh_snd_write_dev(dev_handle, HID_TRANS_GET_IDLE, 0, 0, 0, NULL);
+}
+/*******************************************************************************
+**
+** Function         BTA_HhSendCtrl
+**
+** Description      Send a control command to HID device.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhSendCtrl(UINT8 dev_handle, tBTA_HH_TRANS_CTRL_TYPE c_type)
+{
+    bta_hh_snd_write_dev(dev_handle, HID_TRANS_CONTROL, (UINT8)c_type, 0, 0, NULL);
+}
+/*******************************************************************************
+**
+** Function         BTA_HhSendData
+**
+** Description      This function send DATA transaction to HID device.
+**
+** Parameter        dev_handle: device handle
+**                  dev_bda: remote device address
+**                  p_data: data to be sent in the DATA transaction; or
+**                          the data to be write into the Output Report of a LE HID
+**                          device. The report is identified the report ID which is
+**                          the value of the byte (UINT8 *)(p_buf + 1) + p_buf->offset.
+**                          p_data->layer_specific needs to be set to the report type,
+**                          it can be OUTPUT report, or FEATURE report.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhSendData(UINT8 dev_handle, BD_ADDR dev_bda, BT_HDR  *p_data)
+{
+    UNUSED(dev_bda);
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+    if (p_data->layer_specific != BTA_HH_RPTT_OUTPUT)
+    {
+        APPL_TRACE_ERROR("ERROR! Wrong report type! Write Command only valid for output report!");
+        return;
+    }
+#endif
+    bta_hh_snd_write_dev(dev_handle, HID_TRANS_DATA, (UINT8)p_data->layer_specific, 0, 0, p_data);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HhGetDscpInfo
+**
+** Description      Get HID device report descriptor
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhGetDscpInfo(UINT8 dev_handle)
+{
+    BT_HDR    *p_buf;
+
+    if ((p_buf = (BT_HDR *)GKI_getbuf((UINT16)sizeof(BT_HDR))) != NULL)
+    {
+        memset(p_buf, 0, sizeof(BT_HDR));
+        p_buf->event            = BTA_HH_API_GET_DSCP_EVT;
+        p_buf->layer_specific   = (UINT16) dev_handle;
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HhAddDev
+**
+** Description      Add a virtually cabled device into HID-Host device list
+**                  to manage and assign a device handle for future API call,
+**                  host applciation call this API at start-up to initialize its
+**                  virtually cabled devices.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhAddDev(BD_ADDR bda, tBTA_HH_ATTR_MASK attr_mask, UINT8 sub_class,
+                  UINT8 app_id, tBTA_HH_DEV_DSCP_INFO dscp_info)
+{
+    tBTA_HH_MAINT_DEV    *p_buf;
+    UINT16  len = sizeof(tBTA_HH_MAINT_DEV) + dscp_info.descriptor.dl_len;
+
+    p_buf = (tBTA_HH_MAINT_DEV *)GKI_getbuf(len);
+
+    if (p_buf != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_HH_MAINT_DEV));
+
+        p_buf->hdr.event            = BTA_HH_API_MAINT_DEV_EVT;
+        p_buf->sub_event            = BTA_HH_ADD_DEV_EVT;
+        p_buf->hdr.layer_specific   = BTA_HH_INVALID_HANDLE;
+
+        p_buf->attr_mask            = (UINT16) attr_mask;
+        p_buf->sub_class            = sub_class;
+        p_buf->app_id               = app_id;
+        bdcpy(p_buf->bda, bda);
+
+        memcpy(&p_buf->dscp_info, &dscp_info, sizeof(tBTA_HH_DEV_DSCP_INFO));
+        if ( dscp_info.descriptor.dl_len != 0 && dscp_info.descriptor.dsc_list)
+        {
+            p_buf->dscp_info.descriptor.dl_len =  dscp_info.descriptor.dl_len;
+            p_buf->dscp_info.descriptor.dsc_list = (UINT8 *)(p_buf + 1);
+            memcpy(p_buf->dscp_info.descriptor.dsc_list, dscp_info.descriptor.dsc_list, dscp_info.descriptor.dl_len);
+        }
+        else
+        {
+            p_buf->dscp_info.descriptor.dsc_list = NULL;
+            p_buf->dscp_info.descriptor.dl_len = 0;
+        }
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+/*******************************************************************************
+**
+** Function         BTA_HhRemoveDev
+**
+** Description      Remove a device from the HID host devices list.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhRemoveDev(UINT8 dev_handle )
+{
+    tBTA_HH_MAINT_DEV    *p_buf;
+
+    p_buf = (tBTA_HH_MAINT_DEV *)GKI_getbuf((UINT16)sizeof(tBTA_HH_MAINT_DEV));
+
+    if (p_buf != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_HH_MAINT_DEV));
+
+        p_buf->hdr.event            = BTA_HH_API_MAINT_DEV_EVT;
+        p_buf->sub_event            = BTA_HH_RMV_DEV_EVT;
+        p_buf->hdr.layer_specific   = (UINT16) dev_handle;
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+#if BTA_HH_LE_INCLUDED == TRUE
+
+/*******************************************************************************
+**
+** Function         BTA_HhUpdateLeScanParam
+**
+** Description      Update the scan paramteters if connected to a LE hid device as
+**                  report host.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhUpdateLeScanParam(UINT8 dev_handle, UINT16 scan_int, UINT16 scan_win)
+{
+    tBTA_HH_SCPP_UPDATE    *p_buf;
+
+    p_buf = (tBTA_HH_SCPP_UPDATE *)GKI_getbuf((UINT16)sizeof(tBTA_HH_SCPP_UPDATE));
+
+    if (p_buf != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_HH_SCPP_UPDATE));
+
+        p_buf->hdr.event            = BTA_HH_API_SCPP_UPDATE_EVT;
+        p_buf->hdr.layer_specific   = (UINT16) dev_handle;
+        p_buf->scan_int             =  scan_int;
+        p_buf->scan_win             =  scan_win;
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+#endif
+/*******************************************************************************/
+/*                          Utility Function                                   */
+/*******************************************************************************/
+
+/*******************************************************************************
+**
+** Function         BTA_HhParseBootRpt
+**
+** Description      This utility function parse a boot mode report.
+**                  For keyboard report, report data will carry the keycode max
+**                  up to 6 key press in one report. Application need to convert
+**                  the keycode into keypress character according to keyboard
+**                  language.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhParseBootRpt(tBTA_HH_BOOT_RPT *p_data, UINT8 *p_report,
+                        UINT16 report_len)
+{
+    p_data->dev_type = BTA_HH_DEVT_UNKNOWN;
+
+    if (p_report)
+    {
+        /* first byte is report ID */
+        switch (p_report[0])
+        {
+        case BTA_HH_KEYBD_RPT_ID: /* key board report ID */
+            p_data->dev_type = p_report[0];
+            bta_hh_parse_keybd_rpt(p_data, p_report + 1, (UINT16)(report_len -1));
+            break;
+
+        case BTA_HH_MOUSE_RPT_ID: /* mouse report ID */
+            p_data->dev_type = p_report[0];
+            bta_hh_parse_mice_rpt(p_data, p_report + 1, (UINT16)(report_len - 1));
+            break;
+
+        default:
+            APPL_TRACE_DEBUG("Unknown boot report: %d", p_report[0]);;
+            break;
+        }
+    }
+
+    return;
+}
+
+#endif /* BTA_HH_INCLUDED */

+ 62 - 0
components/bt/bluedroid/bta/hh/bta_hh_cfg.c

@@ -0,0 +1,62 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2005-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This file contains compile-time configurable constants for the BTA Hid
+ *  Host.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#include "bta_hh_api.h"
+
+/* max number of device types supported by BTA */
+#define BTA_HH_MAX_DEVT_SPT         9
+
+/* size of database for service discovery */
+#ifndef BTA_HH_DISC_BUF_SIZE
+#define BTA_HH_DISC_BUF_SIZE        GKI_MAX_BUF_SIZE
+#endif
+
+
+
+/* The type of devices supported by BTA HH and corresponding application ID */
+tBTA_HH_SPT_TOD p_devt_list[BTA_HH_MAX_DEVT_SPT] =
+{
+    {BTA_HH_DEVT_MIC, BTA_HH_APP_ID_MI},
+    {BTA_HH_DEVT_KBD, BTA_HH_APP_ID_KB},
+    {BTA_HH_DEVT_KBD|BTA_HH_DEVT_MIC, BTA_HH_APP_ID_KB},
+    {BTA_HH_DEVT_RMC, BTA_HH_APP_ID_RMC},
+    {BTA_HH_DEVT_RMC | BTA_HH_DEVT_KBD, BTA_HH_APP_ID_RMC},
+    {BTA_HH_DEVT_MIC | BTA_HH_DEVT_DGT, BTA_HH_APP_ID_MI},
+    {BTA_HH_DEVT_JOS, BTA_HH_APP_ID_JOY},
+    {BTA_HH_DEVT_GPD, BTA_HH_APP_ID_GPAD},
+    {BTA_HH_DEVT_UNKNOWN, BTA_HH_APP_ID_3DSG}
+};
+
+
+const tBTA_HH_CFG bta_hh_cfg =
+{
+    BTA_HH_MAX_DEVT_SPT,            /* number of supported type of devices */
+    p_devt_list,                    /* ToD & AppID list */
+    BTA_HH_DISC_BUF_SIZE            /* HH SDP discovery database size */
+};
+
+
+tBTA_HH_CFG *p_bta_hh_cfg = (tBTA_HH_CFG *)&bta_hh_cfg;

+ 415 - 0
components/bt/bluedroid/bta/hh/bta_hh_int.h

@@ -0,0 +1,415 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2005-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This file contains BTA HID Host internal definitions
+ *
+ ******************************************************************************/
+
+#ifndef BTA_HH_INT_H
+#define BTA_HH_INT_H
+
+#include "bta_sys.h"
+#include "utl.h"
+#include "bta_hh_api.h"
+
+#if BTA_HH_LE_INCLUDED == TRUE
+xxx
+#include "bta_gatt_api.h"
+#endif
+
+/* can be moved to bta_api.h */
+#define BTA_HH_MAX_RPT_CHARS    8
+
+#if (BTA_GATT_INCLUDED == FALSE || BLE_INCLUDED == FALSE)
+#undef BTA_HH_LE_INCLUDED
+#define BTA_HH_LE_INCLUDED      FALSE
+#endif
+
+/* state machine events, these events are handled by the state machine */
+enum
+{
+    BTA_HH_API_OPEN_EVT     = BTA_SYS_EVT_START(BTA_ID_HH),
+    BTA_HH_API_CLOSE_EVT,
+    BTA_HH_INT_OPEN_EVT,
+    BTA_HH_INT_CLOSE_EVT,
+    BTA_HH_INT_DATA_EVT,
+    BTA_HH_INT_CTRL_DATA,
+    BTA_HH_INT_HANDSK_EVT,
+    BTA_HH_SDP_CMPL_EVT,
+    BTA_HH_API_WRITE_DEV_EVT,
+    BTA_HH_API_GET_DSCP_EVT,
+    BTA_HH_API_MAINT_DEV_EVT,
+    BTA_HH_OPEN_CMPL_EVT,
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+    BTA_HH_GATT_CLOSE_EVT,
+    BTA_HH_GATT_OPEN_EVT,
+    BTA_HH_START_ENC_EVT,
+    BTA_HH_ENC_CMPL_EVT,
+    BTA_HH_GATT_READ_CHAR_CMPL_EVT,
+    BTA_HH_GATT_WRITE_CHAR_CMPL_EVT,
+    BTA_HH_GATT_READ_DESCR_CMPL_EVT,
+    BTA_HH_GATT_WRITE_DESCR_CMPL_EVT,
+    BTA_HH_API_SCPP_UPDATE_EVT,
+    BTA_HH_GATT_ENC_CMPL_EVT,
+#endif
+
+    /* not handled by execute state machine */
+    BTA_HH_API_ENABLE_EVT,
+    BTA_HH_API_DISABLE_EVT,
+    BTA_HH_DISC_CMPL_EVT
+};
+typedef UINT16 tBTA_HH_INT_EVT;         /* HID host internal events */
+
+#define BTA_HH_INVALID_EVT      (BTA_HH_DISC_CMPL_EVT + 1)
+
+/* event used to map between BTE event and BTA event */
+#define BTA_HH_FST_TRANS_CB_EVT         BTA_HH_GET_RPT_EVT
+#define BTA_HH_FST_BTE_TRANS_EVT        HID_TRANS_GET_REPORT
+
+/* sub event code used for device maintainence API call */
+#define BTA_HH_ADD_DEV          0
+#define BTA_HH_REMOVE_DEV       1
+
+/* state machine states */
+enum
+{
+    BTA_HH_NULL_ST,
+    BTA_HH_IDLE_ST,
+    BTA_HH_W4_CONN_ST,
+    BTA_HH_CONN_ST
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+    ,BTA_HH_W4_SEC
+#endif
+    ,BTA_HH_INVALID_ST    /* Used to check invalid states before executing SM function */
+
+};
+typedef UINT8 tBTA_HH_STATE;
+
+/* data structure used to send a command/data to HID device */
+typedef struct
+{
+    BT_HDR           hdr;
+    UINT8            t_type;
+    UINT8            param;
+    UINT8            rpt_id;
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+    UINT8            srvc_id;
+#endif
+    UINT16           data;
+    BT_HDR           *p_data;
+}tBTA_HH_CMD_DATA;
+
+/* data type for BTA_HH_API_ENABLE_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    UINT8               sec_mask;
+    UINT8               service_name[BTA_SERVICE_NAME_LEN+1];
+    tBTA_HH_CBACK   *p_cback;
+} tBTA_HH_API_ENABLE;
+
+typedef struct
+{
+    BT_HDR          hdr;
+    BD_ADDR         bd_addr;
+    UINT8           sec_mask;
+    tBTA_HH_PROTO_MODE  mode;
+}tBTA_HH_API_CONN;
+
+/* internal event data from BTE HID callback */
+typedef struct
+{
+    BT_HDR          hdr;
+    BD_ADDR         addr;
+    UINT32          data;
+    BT_HDR          *p_data;
+}tBTA_HH_CBACK_DATA;
+
+typedef struct
+{
+    BT_HDR              hdr;
+    BD_ADDR             bda;
+    UINT16              attr_mask;
+    UINT16              sub_event;
+    UINT8               sub_class;
+    UINT8               app_id;
+    tBTA_HH_DEV_DSCP_INFO      dscp_info;
+}tBTA_HH_MAINT_DEV;
+
+#if BTA_HH_LE_INCLUDED == TRUE
+typedef struct
+{
+    BT_HDR              hdr;
+    UINT16              conn_id;
+    tBTA_GATT_REASON    reason;         /* disconnect reason code, not useful when connect event is reported */
+
+}tBTA_HH_LE_CLOSE;
+
+typedef struct
+{
+    BT_HDR              hdr;
+    UINT16              scan_int;
+    UINT16              scan_win;
+}tBTA_HH_SCPP_UPDATE;
+#endif
+/* union of all event data types */
+typedef union
+{
+    BT_HDR                   hdr;
+    tBTA_HH_API_ENABLE       api_enable;
+    tBTA_HH_API_CONN         api_conn;
+    tBTA_HH_CMD_DATA         api_sndcmd;
+    tBTA_HH_CBACK_DATA       hid_cback;
+    tBTA_HH_STATUS           status;
+    tBTA_HH_MAINT_DEV        api_maintdev;
+#if BTA_HH_LE_INCLUDED == TRUE
+    tBTA_HH_LE_CLOSE         le_close;
+    tBTA_GATTC_OPEN          le_open;
+    tBTA_HH_SCPP_UPDATE      le_scpp_update;
+    tBTA_GATTC_ENC_CMPL_CB   le_enc_cmpl;
+#endif
+} tBTA_HH_DATA;
+
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+typedef struct
+{
+    UINT8                   index;
+    BOOLEAN                 in_use;
+    UINT8                   inst_id;    /* share service instance ID and report instance ID, as
+                                           hi 4 for service instance ID, low 4 as charatceristic instance ID */
+    tBTA_HH_RPT_TYPE        rpt_type;
+    UINT16                  uuid;
+    UINT8                   prop;
+    UINT8                   rpt_id;
+    BOOLEAN                 client_cfg_exist;
+    UINT16                  client_cfg_value;
+}tBTA_HH_LE_RPT;
+
+#ifndef BTA_HH_LE_RPT_MAX
+#define BTA_HH_LE_RPT_MAX       20
+#endif
+
+typedef struct
+{
+    BOOLEAN                 in_use;
+    tBTA_HH_LE_RPT          report[BTA_HH_LE_RPT_MAX];
+
+#define BTA_HH_LE_PROTO_MODE_BIT        0x01
+#define BTA_HH_LE_CP_BIT                0x02
+    UINT8                   option_char; /* control point char exisit or not */
+
+    BOOLEAN                 expl_incl_srvc;
+    UINT8                   incl_srvc_inst; /* assuming only one included service : battery service */
+    UINT8                   cur_expl_char_idx; /* currently discovering service index */
+    UINT8                   *rpt_map;
+    UINT16                  ext_rpt_ref;
+    tBTA_HH_DEV_DESCR       descriptor;
+
+}tBTA_HH_LE_HID_SRVC;
+
+#ifndef BTA_HH_LE_HID_SRVC_MAX
+#define BTA_HH_LE_HID_SRVC_MAX      1
+#endif
+
+/* convert a HID handle to the LE CB index */
+#define BTA_HH_GET_LE_CB_IDX(x)         (((x) >> 4) - 1)
+/* convert a GATT connection ID to HID device handle, it is the hi 4 bits of a UINT8 */
+#define BTA_HH_GET_LE_DEV_HDL(x)        (UINT8)(((x)  + 1) << 4)
+/* check to see if th edevice handle is a LE device handle */
+#define BTA_HH_IS_LE_DEV_HDL(x)        ((x) & 0xf0)
+#define BTA_HH_IS_LE_DEV_HDL_VALID(x)  (((x)>>4) <= BTA_HH_LE_MAX_KNOWN)
+#endif
+
+/* device control block */
+typedef struct
+{
+    tBTA_HH_DEV_DSCP_INFO  dscp_info;      /* report descriptor and DI information */
+    BD_ADDR             addr;           /* BD-Addr of the HID device */
+    UINT16              attr_mask;      /* attribute mask */
+    UINT16              w4_evt;         /* W4_handshake event name */
+    UINT8               index;          /* index number referenced to handle index */
+    UINT8               sub_class;      /* Cod sub class */
+    UINT8               sec_mask;       /* security mask */
+    UINT8               app_id;         /* application ID for this connection */
+    UINT8               hid_handle;     /* device handle : low 4 bits for regular HID: HID_HOST_MAX_DEVICES can not exceed 15;
+                                                            high 4 bits for LE HID: GATT_MAX_PHY_CHANNEL can not exceed 15 */
+    BOOLEAN             vp;             /* virtually unplug flag */
+    BOOLEAN             in_use;         /* control block currently in use */
+    BOOLEAN             incoming_conn;  /* is incoming connection? */
+    UINT8               incoming_hid_handle;  /* temporary handle for incoming connection? */
+    BOOLEAN             opened;         /* TRUE if device successfully opened HID connection */
+    tBTA_HH_PROTO_MODE  mode;           /* protocol mode */
+    tBTA_HH_STATE       state;          /* CB state */
+
+#if (BTA_HH_LE_INCLUDED == TRUE)
+#define BTA_HH_LE_DISC_NONE     0x00
+#define BTA_HH_LE_DISC_HIDS     0x01
+#define BTA_HH_LE_DISC_DIS      0x02
+#define BTA_HH_LE_DISC_SCPS     0x04
+
+    UINT8               disc_active;
+    tBTA_HH_STATUS      status;
+    tBTA_GATT_REASON    reason;
+    BOOLEAN             is_le_device;
+    tBTA_HH_LE_HID_SRVC hid_srvc[BTA_HH_LE_HID_SRVC_MAX];
+    UINT16              conn_id;
+    BOOLEAN             in_bg_conn;
+    UINT8               total_srvc;
+    UINT8               clt_cfg_idx;
+    UINT8               cur_srvc_index; /* currently discovering service index */
+    BOOLEAN             scps_supported;
+
+#define BTA_HH_LE_SCPS_NOTIFY_NONE    0
+#define BTA_HH_LE_SCPS_NOTIFY_SPT  0x01
+#define BTA_HH_LE_SCPS_NOTIFY_ENB  0x02
+    UINT8               scps_notify;   /* scan refresh supported/notification enabled */
+#endif
+
+    BOOLEAN             security_pending;
+} tBTA_HH_DEV_CB;
+
+/* key board parsing control block */
+typedef struct
+{
+    BOOLEAN             mod_key[4]; /* ctrl, shift(upper), Alt, GUI */
+    BOOLEAN             num_lock;
+    BOOLEAN             caps_lock;
+    UINT8               last_report[BTA_HH_MAX_RPT_CHARS];
+} tBTA_HH_KB_CB;
+
+/******************************************************************************
+** Main Control Block
+*******************************************************************************/
+typedef struct
+{
+    tBTA_HH_KB_CB           kb_cb;                  /* key board control block,
+                                                       suppose BTA will connect
+                                                       to only one keyboard at
+                                                        the same time */
+    tBTA_HH_DEV_CB          kdev[BTA_HH_MAX_DEVICE]; /* device control block */
+    tBTA_HH_DEV_CB*         p_cur;              /* current device control
+                                                       block idx, used in sdp */
+    UINT8                   cb_index[BTA_HH_MAX_KNOWN]; /* maintain a CB index
+                                                        map to dev handle */
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+    UINT8                   le_cb_index[BTA_HH_MAX_DEVICE]; /* maintain a CB index map to LE dev handle */
+    tBTA_GATTC_IF           gatt_if;
+#endif
+    tBTA_HH_CBACK       *p_cback;               /* Application callbacks */
+    tSDP_DISCOVERY_DB*      p_disc_db;
+    UINT8                   trace_level;            /* tracing level */
+    UINT8                   cnt_num;                /* connected device number */
+    BOOLEAN                 w4_disable;             /* w4 disable flag */
+}
+tBTA_HH_CB;
+
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_HH_CB  bta_hh_cb;
+#else
+extern tBTA_HH_CB *bta_hh_cb_ptr;
+#define bta_hh_cb (*bta_hh_cb_ptr)
+#endif
+
+/* from bta_hh_cfg.c */
+extern tBTA_HH_CFG *p_bta_hh_cfg;
+
+/*****************************************************************************
+**  Function prototypes
+*****************************************************************************/
+extern BOOLEAN bta_hh_hdl_event(BT_HDR *p_msg);
+extern void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16 event,
+                              tBTA_HH_DATA *p_data);
+
+/* action functions */
+extern void bta_hh_api_disc_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_open_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_close_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_data_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA * p_data);
+extern void bta_hh_ctrl_dat_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA * p_data);
+extern void bta_hh_start_sdp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_sdp_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_get_dscp_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_handsk_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_maint_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_open_cmpl_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_open_failure(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+
+/* utility functions */
+extern UINT8  bta_hh_find_cb(BD_ADDR bda);
+extern void bta_hh_parse_keybd_rpt(tBTA_HH_BOOT_RPT *p_kb_data,
+             UINT8 *p_report, UINT16 report_len);
+extern void bta_hh_parse_mice_rpt(tBTA_HH_BOOT_RPT *p_kb_data,
+                                  UINT8 *p_report, UINT16 report_len);
+extern BOOLEAN bta_hh_tod_spt(tBTA_HH_DEV_CB *p_cb,UINT8 sub_class);
+extern void bta_hh_clean_up_kdev(tBTA_HH_DEV_CB *p_cb);
+
+extern void bta_hh_add_device_to_list(tBTA_HH_DEV_CB *p_cb, UINT8 handle,
+                                      UINT16 attr_mask,
+                                      tHID_DEV_DSCP_INFO *p_dscp_info,
+                                      UINT8 sub_class, UINT16 max_latency, UINT16 min_tout, UINT8 app_id);
+extern void bta_hh_update_di_info(tBTA_HH_DEV_CB *p_cb, UINT16 vendor_id, UINT16 product_id,
+                           UINT16 version, UINT8 flag);
+extern void bta_hh_cleanup_disable(tBTA_HH_STATUS status);
+
+extern UINT8 bta_hh_dev_handle_to_cb_idx(UINT8 dev_handle);
+
+/* action functions used outside state machine */
+extern void bta_hh_api_enable(tBTA_HH_DATA *p_data);
+extern void bta_hh_api_disable(void);
+extern void bta_hh_disc_cmpl(void);
+
+extern tBTA_HH_STATUS bta_hh_read_ssr_param(BD_ADDR bd_addr, UINT16 *p_max_ssr_lat, UINT16 *p_min_ssr_tout);
+
+/* functions for LE HID */
+extern void bta_hh_le_enable(void);
+extern BOOLEAN bta_hh_le_is_hh_gatt_if(tBTA_GATTC_IF client_if);
+extern void bta_hh_le_deregister(void);
+extern BOOLEAN bta_hh_is_le_device(tBTA_HH_DEV_CB *p_cb, BD_ADDR remote_bda);
+extern void bta_hh_le_open_conn(tBTA_HH_DEV_CB *p_cb, BD_ADDR remote_bda);
+extern void bta_hh_le_api_disc_act(tBTA_HH_DEV_CB *p_cb);
+extern void bta_hh_le_get_dscp_act(tBTA_HH_DEV_CB *p_cb);
+extern void bta_hh_le_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern UINT8 bta_hh_le_add_device(tBTA_HH_DEV_CB *p_cb, tBTA_HH_MAINT_DEV *p_dev_info);
+extern void bta_hh_le_remove_dev_bg_conn(tBTA_HH_DEV_CB *p_cb);
+extern void bta_hh_le_open_fail(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_gatt_open(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_gatt_close(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_start_security(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
+extern void bta_hh_start_srvc_discovery(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
+extern void bta_hh_w4_le_read_char_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
+extern void bta_hh_le_read_char_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
+extern void bta_hh_w4_le_read_descr_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
+extern void bta_hh_le_read_descr_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
+extern void bta_hh_w4_le_write_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
+extern void bta_hh_le_write_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
+extern void bta_hh_le_write_char_descr_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
+extern void bta_hh_start_security(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
+extern void bta_hh_security_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
+extern void bta_hh_le_update_scpp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
+extern void bta_hh_le_notify_enc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_ci_load_rpt (tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
+
+#if BTA_HH_DEBUG
+extern void bta_hh_trace_dev_db(void);
+#endif
+
+#endif
+

+ 3168 - 0
components/bt/bluedroid/bta/hh/bta_hh_le.c

@@ -0,0 +1,3168 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#include "bta_api.h"
+#include "bta_hh_int.h"
+
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+
+#include "bta_api.h"
+#include <string.h>
+#include "btm_api.h"
+#include "btm_ble_api.h"
+#include "bta_hh_co.h"
+#include "bta_gatt_api.h"
+#include "srvc_api.h"
+#include "btm_int.h"
+#include "utl.h"
+
+#define LOG_TAG "bt_bta_hh"
+#include "osi/include/log.h"
+
+#ifndef BTA_HH_LE_RECONN
+#define BTA_HH_LE_RECONN    TRUE
+#endif
+
+#define BTA_HH_APP_ID_LE            0xff
+
+#define BTA_HH_LE_RPT_TYPE_VALID(x)     ((x) <= BTA_LE_HID_RPT_FEATURE && (x)>=BTA_LE_HID_RPT_INPUT)
+
+#define BTA_HH_LE_RPT_INST_ID_MAP(s,c)  (UINT8)(((s)<<4)|(c))
+#define BTA_HH_LE_RPT_GET_SRVC_INST_ID(x)  (UINT8)(x  >> 4)
+#define BTA_HH_LE_RPT_GET_RPT_INST_ID(x)  (UINT8)(x & 0x0f)
+
+
+#define BTA_HH_LE_PROTO_BOOT_MODE      0x00
+#define BTA_HH_LE_PROTO_REPORT_MODE      0x01
+
+#define BTA_HH_SCPP_INST_DEF            0
+
+#define BTA_HH_LE_DISC_CHAR_NUM     8
+static const UINT16 bta_hh_le_disc_char_uuid[BTA_HH_LE_DISC_CHAR_NUM] =
+{
+    GATT_UUID_HID_INFORMATION,
+    GATT_UUID_HID_REPORT_MAP,
+    GATT_UUID_HID_CONTROL_POINT,
+    GATT_UUID_HID_REPORT,
+    GATT_UUID_HID_BT_KB_INPUT,
+    GATT_UUID_HID_BT_KB_OUTPUT,
+    GATT_UUID_HID_BT_MOUSE_INPUT,
+    GATT_UUID_HID_PROTO_MODE        /* always make sure this is the last attribute to discover */
+};
+
+#define BTA_LE_HID_RTP_UUID_MAX     5
+static const UINT16 bta_hh_uuid_to_rtp_type[BTA_LE_HID_RTP_UUID_MAX][2] =
+{
+    {GATT_UUID_HID_REPORT,       BTA_HH_RPTT_INPUT},
+    {GATT_UUID_HID_BT_KB_INPUT,  BTA_HH_RPTT_INPUT},
+    {GATT_UUID_HID_BT_KB_OUTPUT, BTA_HH_RPTT_OUTPUT},
+    {GATT_UUID_HID_BT_MOUSE_INPUT, BTA_HH_RPTT_INPUT},
+    {GATT_UUID_BATTERY_LEVEL,      BTA_HH_RPTT_INPUT}
+};
+
+
+static void bta_hh_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data);
+static void bta_hh_le_search_hid_chars(tBTA_HH_DEV_CB *p_dev_cb);
+static void bta_hh_le_search_hid_included(tBTA_HH_DEV_CB *p_dev_cb);
+static void bta_hh_le_search_scps(tBTA_HH_DEV_CB *p_cb);
+static void bta_hh_le_search_scps_chars(tBTA_HH_DEV_CB *p_cb);
+static void bta_hh_le_register_scpp_notif(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_STATUS status);
+static void bta_hh_le_register_scpp_notif_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_STATUS status);
+static void bta_hh_le_add_dev_bg_conn(tBTA_HH_DEV_CB *p_cb, BOOLEAN check_bond);
+static void bta_hh_process_cache_rpt (tBTA_HH_DEV_CB *p_cb,
+                                      tBTA_HH_RPT_CACHE_ENTRY *p_rpt_cache,
+                                      UINT8 num_rpt);
+
+#define BTA_HH_LE_SRVC_DEF      0
+
+#if BTA_HH_DEBUG == TRUE
+static const char *bta_hh_le_rpt_name[4] =
+{
+    "UNKNOWN",
+    "INPUT",
+    "OUTPUT",
+    "FEATURE"
+};
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_hid_report_dbg
+**
+** Description      debug function to print out all HID report available on remote
+**                  device.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hh_le_hid_report_dbg(tBTA_HH_DEV_CB *p_cb)
+{
+    UINT8 i , j;
+    tBTA_HH_LE_RPT  *p_rpt;
+    char *  rpt_name;
+
+    APPL_TRACE_DEBUG("HID Report DB");
+    for (i = 0; i < BTA_HH_LE_HID_SRVC_MAX; i ++)
+    {
+        if (p_cb->hid_srvc[i].in_use)
+        {
+            p_rpt = &p_cb->hid_srvc[i].report[0];
+
+            APPL_TRACE_DEBUG("\t HID serivce inst: %d", i);
+
+            for (j = 0; j < BTA_HH_LE_RPT_MAX; j ++, p_rpt++)
+            {
+                rpt_name = "Unknown";
+                if (p_rpt->in_use)
+                {
+                    if (p_rpt->uuid == GATT_UUID_HID_REPORT)
+                        rpt_name = "Report";
+                    if (p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT)
+                        rpt_name = "Boot KB Input";
+                    if (p_rpt->uuid == GATT_UUID_HID_BT_KB_OUTPUT)
+                        rpt_name = "Boot KB Output";
+                    if (p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT)
+                        rpt_name = "Boot MI Input";
+
+
+                    APPL_TRACE_DEBUG("\t\t [%s- 0x%04x] [Type: %s], [ReportID: %d] [inst_id: %d]  [Clt_cfg: %d]",
+                        rpt_name,
+                        p_rpt->uuid ,
+                        ((p_rpt->rpt_type < 4) ? bta_hh_le_rpt_name[p_rpt->rpt_type] : "UNKNOWN"),
+                        p_rpt->rpt_id,
+                        p_rpt->inst_id,
+                        p_rpt->client_cfg_value);
+                }
+                else
+                    break;
+            }
+        }
+        else
+            break;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_uuid_to_str
+**
+** Description
+**
+** Returns          void
+**
+*******************************************************************************/
+static char *bta_hh_uuid_to_str(UINT16 uuid)
+{
+    switch(uuid)
+    {
+        case GATT_UUID_HID_INFORMATION:
+            return "GATT_UUID_HID_INFORMATION";
+        case GATT_UUID_HID_REPORT_MAP:
+            return "GATT_UUID_HID_REPORT_MAP";
+        case GATT_UUID_HID_CONTROL_POINT:
+            return "GATT_UUID_HID_CONTROL_POINT";
+        case GATT_UUID_HID_REPORT:
+            return "GATT_UUID_HID_REPORT";
+        case GATT_UUID_HID_PROTO_MODE:
+            return "GATT_UUID_HID_PROTO_MODE";
+        case GATT_UUID_HID_BT_KB_INPUT:
+            return "GATT_UUID_HID_BT_KB_INPUT";
+        case GATT_UUID_HID_BT_KB_OUTPUT:
+            return "GATT_UUID_HID_BT_KB_OUTPUT";
+        case GATT_UUID_HID_BT_MOUSE_INPUT:
+            return "GATT_UUID_HID_BT_MOUSE_INPUT";
+        case GATT_UUID_CHAR_CLIENT_CONFIG:
+            return "GATT_UUID_CHAR_CLIENT_CONFIG";
+        case GATT_UUID_EXT_RPT_REF_DESCR:
+            return "GATT_UUID_EXT_RPT_REF_DESCR";
+        case GATT_UUID_RPT_REF_DESCR:
+            return "GATT_UUID_RPT_REF_DESCR";
+        default:
+            return "Unknown UUID";
+    }
+}
+
+#endif
+/*******************************************************************************
+**
+** Function         bta_hh_le_enable
+**
+** Description      initialize LE HID related functionality
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_le_enable(void)
+{
+    char       app_name[LEN_UUID_128 + 1];
+    tBT_UUID    app_uuid = {LEN_UUID_128,{0}};
+    UINT8       xx;
+
+    bta_hh_cb.gatt_if = BTA_GATTS_INVALID_IF;
+
+    for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx ++)
+        bta_hh_cb.le_cb_index[xx]       = BTA_HH_IDX_INVALID;
+
+    memset (app_name, 0, LEN_UUID_128 + 1);
+    strncpy(app_name, "BTA HH OVER LE", LEN_UUID_128);
+
+    memcpy((void *)app_uuid.uu.uuid128, (void *)app_name, LEN_UUID_128);
+
+    BTA_GATTC_AppRegister(&app_uuid, bta_hh_gattc_callback);
+
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_register_cmpl
+**
+** Description      BTA HH register with BTA GATTC completed
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_le_register_cmpl(tBTA_GATTC_REG *p_reg)
+{
+    tBTA_HH_STATUS      status = BTA_HH_ERR;
+
+    if (p_reg->status == BTA_GATT_OK)
+    {
+        bta_hh_cb.gatt_if = p_reg->client_if;
+        status = BTA_HH_OK;
+    }
+    else
+        bta_hh_cb.gatt_if = BTA_GATTS_INVALID_IF;
+
+    /* signal BTA call back event */
+    (* bta_hh_cb.p_cback)(BTA_HH_ENABLE_EVT, (tBTA_HH *)&status);
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_is_hh_gatt_if
+**
+** Description      Check to see if client_if is BTA HH LE GATT interface
+**
+**
+** Returns          whether it is HH GATT IF
+**
+*******************************************************************************/
+BOOLEAN bta_hh_le_is_hh_gatt_if(tBTA_GATTC_IF client_if)
+{
+    return (bta_hh_cb.gatt_if == client_if);
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_deregister
+**
+** Description      De-register BTA HH from BTA GATTC
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_le_deregister(void)
+{
+    BTA_GATTC_AppDeregister(bta_hh_cb.gatt_if);
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_is_le_device
+**
+** Description      Check to see if the remote device is a LE only device
+**
+** Parameters:
+**
+*******************************************************************************/
+BOOLEAN bta_hh_is_le_device(tBTA_HH_DEV_CB *p_cb, BD_ADDR remote_bda)
+{
+    p_cb->is_le_device = BTM_UseLeLink (remote_bda);
+
+    return p_cb->is_le_device;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_add_hid_srvc_entry
+**
+** Description      Add a HID service entry in the HID device control block
+**
+** Parameters:
+**
+*******************************************************************************/
+BOOLEAN bta_hh_le_add_hid_srvc_entry(tBTA_HH_DEV_CB *p_dev_cb, UINT8 idx)
+{
+    BOOLEAN added = FALSE;
+
+    if (idx < BTA_HH_LE_HID_SRVC_MAX)
+    {
+        p_dev_cb->hid_srvc[idx].in_use = TRUE;
+        added = TRUE;
+    }
+    else
+    {
+        APPL_TRACE_ERROR("DB full,max HID service entry!");
+    }
+    return added;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_open_conn
+**
+** Description      open a GATT connection first.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_le_open_conn(tBTA_HH_DEV_CB *p_cb, BD_ADDR remote_bda)
+{
+    /* update cb_index[] map */
+    p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
+    memcpy(p_cb->addr, remote_bda, BD_ADDR_LEN);
+    bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
+    p_cb->in_use = TRUE;
+
+    BTA_GATTC_Open(bta_hh_cb.gatt_if, remote_bda, TRUE, BTA_GATT_TRANSPORT_LE);
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_fill_16bits_gatt_id
+**
+** Description      Utility function to fill a GATT ID strucure
+**
+*******************************************************************************/
+void bta_hh_le_fill_16bits_gatt_id(UINT8 inst_id, UINT16 uuid,  tBTA_GATT_ID *p_output)
+{
+    p_output->inst_id        = inst_id;
+    p_output->uuid.len       = LEN_UUID_16;
+    p_output->uuid.uu.uuid16 = uuid;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_fill_16bits_srvc_id
+**
+** Description      Utility function to fill a service ID strucure with a 16 bits
+**                  service UUID.
+**
+*******************************************************************************/
+void bta_hh_le_fill_16bits_srvc_id(BOOLEAN is_pri, UINT8 inst_id, UINT16 srvc_uuid,
+                                   tBTA_GATT_SRVC_ID *p_output)
+{
+    memset((void *)p_output, 0, sizeof(tBTA_GATT_SRVC_ID));
+    p_output->is_primary        = is_pri;
+    bta_hh_le_fill_16bits_gatt_id(inst_id, srvc_uuid, &p_output->id);
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_fill_16bits_char_id
+**
+** Description      Utility function to fill a char ID strucure with a 16 bits
+**                  char UUID.
+**
+*******************************************************************************/
+void bta_hh_le_fill_16bits_char_id(UINT8 inst_id, UINT16 char_uuid,
+                                   tBTA_GATT_ID *p_output)
+{
+    memset((void *)p_output, 0, sizeof(tBTA_GATT_ID));
+    bta_hh_le_fill_16bits_gatt_id(inst_id, char_uuid, p_output);
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_find_dev_cb_by_conn_id
+**
+** Description      Utility function find a device control block by connection ID.
+**
+*******************************************************************************/
+tBTA_HH_DEV_CB * bta_hh_le_find_dev_cb_by_conn_id(UINT16 conn_id)
+{
+    UINT8   i;
+    tBTA_HH_DEV_CB *p_dev_cb = &bta_hh_cb.kdev[0];
+
+    for (i = 0; i < BTA_HH_MAX_DEVICE; i ++, p_dev_cb ++)
+    {
+        if (p_dev_cb->in_use  && p_dev_cb->conn_id == conn_id)
+            return p_dev_cb;
+    }
+    return NULL;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_find_dev_cb_by_bda
+**
+** Description      Utility function find a device control block by BD address.
+**
+*******************************************************************************/
+tBTA_HH_DEV_CB * bta_hh_le_find_dev_cb_by_bda(BD_ADDR bda)
+{
+    UINT8   i;
+    tBTA_HH_DEV_CB *p_dev_cb = &bta_hh_cb.kdev[0];
+
+    for (i = 0; i < BTA_HH_MAX_DEVICE; i ++, p_dev_cb ++)
+    {
+        if (p_dev_cb->in_use  &&
+            memcmp(p_dev_cb->addr, bda, BD_ADDR_LEN) == 0)
+            return p_dev_cb;
+    }
+    return NULL;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_find_service_inst_by_battery_inst_id
+**
+** Description      find HID service instance ID by battery service instance ID
+**
+*******************************************************************************/
+UINT8 bta_hh_le_find_service_inst_by_battery_inst_id(tBTA_HH_DEV_CB *p_cb, UINT8 ba_inst_id)
+{
+    UINT8   i;
+
+    for (i = 0; i < BTA_HH_LE_HID_SRVC_MAX; i ++)
+    {
+        if (p_cb->hid_srvc[i].in_use &&
+            p_cb->hid_srvc[i].incl_srvc_inst == ba_inst_id)
+        {
+            return i;
+        }
+    }
+    return BTA_HH_IDX_INVALID;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_find_report_entry
+**
+** Description      find the report entry by service instance and report UUID and
+**                  instance ID
+**
+*******************************************************************************/
+tBTA_HH_LE_RPT * bta_hh_le_find_report_entry(tBTA_HH_DEV_CB *p_cb,
+                                             UINT8  srvc_inst_id,  /* service instance ID */
+                                             UINT16 rpt_uuid,
+                                             UINT8  char_inst_id)
+{
+    UINT8   i;
+    UINT8   hid_inst_id = srvc_inst_id;
+    tBTA_HH_LE_RPT *p_rpt;
+
+    if (rpt_uuid == GATT_UUID_BATTERY_LEVEL)
+    {
+        hid_inst_id = bta_hh_le_find_service_inst_by_battery_inst_id(p_cb, srvc_inst_id);
+
+        if (hid_inst_id == BTA_HH_IDX_INVALID)
+            return NULL;
+    }
+
+    p_rpt = &p_cb->hid_srvc[hid_inst_id].report[0];
+
+    for (i = 0; i < BTA_HH_LE_RPT_MAX; i ++, p_rpt ++)
+    {
+        if (p_rpt->uuid == rpt_uuid &&
+            p_rpt->inst_id == BTA_HH_LE_RPT_INST_ID_MAP(srvc_inst_id, char_inst_id))
+        {
+
+            return p_rpt;
+        }
+    }
+    return NULL;
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_find_rpt_by_idtype
+**
+** Description      find a report entry by report ID and protocol mode
+**
+** Returns          void
+**
+*******************************************************************************/
+tBTA_HH_LE_RPT * bta_hh_le_find_rpt_by_idtype(tBTA_HH_LE_RPT*p_head, UINT8 mode,
+                                              tBTA_HH_RPT_TYPE r_type, UINT8 rpt_id)
+{
+    tBTA_HH_LE_RPT *p_rpt = p_head;
+    UINT8   i;
+
+#if BTA_HH_DEBUG == TRUE
+    APPL_TRACE_DEBUG("bta_hh_le_find_rpt_by_idtype: r_type: %d rpt_id: %d", r_type, rpt_id);
+#endif
+
+    for (i = 0 ; i < BTA_HH_LE_RPT_MAX; i ++, p_rpt++)
+    {
+        if (p_rpt->in_use && p_rpt->rpt_id == rpt_id && r_type == p_rpt->rpt_type)
+        {
+            /* return battery report w/o condition */
+            if (p_rpt->uuid == GATT_UUID_BATTERY_LEVEL)
+                return p_rpt;
+
+            if (mode == BTA_HH_PROTO_RPT_MODE && p_rpt->uuid == GATT_UUID_HID_REPORT)
+                return p_rpt;
+
+            if ( mode ==BTA_HH_PROTO_BOOT_MODE &&
+                (p_rpt->uuid >= GATT_UUID_HID_BT_KB_INPUT && p_rpt->uuid <= GATT_UUID_HID_BT_MOUSE_INPUT))
+                return p_rpt;
+        }
+    }
+    return NULL;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_find_alloc_report_entry
+**
+** Description      find or allocate a report entry in the HID service report list.
+**
+*******************************************************************************/
+tBTA_HH_LE_RPT * bta_hh_le_find_alloc_report_entry(tBTA_HH_DEV_CB *p_cb,
+                                                   UINT8 srvc_inst_id,
+                                                   UINT16 rpt_uuid,
+                                                   UINT8  inst_id,
+                                                   UINT8  prop)
+{
+    UINT8   i, hid_inst_id = srvc_inst_id;
+    tBTA_HH_LE_RPT *p_rpt;
+
+    if (rpt_uuid == GATT_UUID_BATTERY_LEVEL)
+    {
+        hid_inst_id = bta_hh_le_find_service_inst_by_battery_inst_id(p_cb, srvc_inst_id);
+
+        if (hid_inst_id == BTA_HH_IDX_INVALID)
+            return NULL;
+    }
+    p_rpt = &p_cb->hid_srvc[hid_inst_id].report[0];
+
+    for (i = 0; i < BTA_HH_LE_RPT_MAX; i ++, p_rpt ++)
+    {
+        if (!p_rpt->in_use ||
+            (p_rpt->uuid == rpt_uuid &&
+             p_rpt->inst_id == BTA_HH_LE_RPT_INST_ID_MAP(srvc_inst_id, inst_id)))
+        {
+            if (!p_rpt->in_use)
+            {
+                p_rpt->in_use   = TRUE;
+                p_rpt->index    = i;
+                p_rpt->inst_id  = BTA_HH_LE_RPT_INST_ID_MAP(srvc_inst_id, inst_id);
+                p_rpt->prop     = prop;
+                p_rpt->uuid     = rpt_uuid;
+
+                /* assign report type */
+                for (i = 0; i < BTA_LE_HID_RTP_UUID_MAX; i ++)
+                {
+                    if (bta_hh_uuid_to_rtp_type[i][0] == rpt_uuid)
+                    {
+                        p_rpt->rpt_type = (tBTA_HH_RPT_TYPE)bta_hh_uuid_to_rtp_type[i][1];
+
+                        if (rpt_uuid == GATT_UUID_HID_BT_KB_INPUT || rpt_uuid == GATT_UUID_HID_BT_KB_OUTPUT)
+                            p_rpt->rpt_id = BTA_HH_KEYBD_RPT_ID;
+
+                        if (rpt_uuid == GATT_UUID_HID_BT_MOUSE_INPUT)
+                            p_rpt->rpt_id = BTA_HH_MOUSE_RPT_ID;
+
+                        break;
+                    }
+                }
+            }
+            return p_rpt;
+        }
+    }
+    return NULL;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_read_char_dscrpt
+**
+** Description      read characteristic descriptor
+**
+*******************************************************************************/
+tBTA_HH_STATUS bta_hh_le_read_char_dscrpt(tBTA_HH_DEV_CB *p_cb, UINT16 srvc_uuid, UINT8 srvc_inst_id,
+                                UINT16 char_uuid, UINT8 char_inst_id, UINT16 char_descp_uuid)
+{
+    tBTA_GATTC_CHAR_ID  char_id;
+    tBT_UUID        descr_uuid;
+    tBTA_GATTC_CHAR_DESCR_ID    descr_id;
+    tBTA_HH_STATUS  status = BTA_HH_ERR;
+
+    bta_hh_le_fill_16bits_srvc_id(TRUE, srvc_inst_id, srvc_uuid, &char_id.srvc_id);
+    bta_hh_le_fill_16bits_char_id(char_inst_id, char_uuid, &char_id.char_id);
+
+    descr_uuid.len       = LEN_UUID_16;
+    descr_uuid.uu.uuid16 = char_descp_uuid;
+
+    /* find the report reference descriptor */
+    if (BTA_GATTC_GetFirstCharDescr(p_cb->conn_id,
+                                &char_id,
+                                &descr_uuid,
+                                &descr_id) == BTA_GATT_OK)
+    {
+        BTA_GATTC_ReadCharDescr(p_cb->conn_id,
+                                &descr_id,
+                                BTA_GATT_AUTH_REQ_NONE);
+
+        status = BTA_HH_OK;
+    }
+    else
+    {
+#if BTA_HH_DEBUG == TRUE
+      LOG_WARN("%s No descriptor exists: %s(0x%04x)", __func__,
+          bta_hh_uuid_to_str(char_descp_uuid), char_descp_uuid);
+#endif
+    }
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_read_rpt_ref_descr
+**
+** Description      read report refernece descriptors in service discovery process
+**
+*******************************************************************************/
+void bta_hh_le_read_rpt_ref_descr(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_LE_RPT *p_rpt)
+{
+    BOOLEAN started = FALSE;
+    UINT16  srvc_uuid, char_uuid;
+
+    while (p_rpt != NULL)
+    {
+        if(!p_rpt->in_use)
+            break;
+
+        if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT)
+        {
+            /* is battery report */
+            if (p_rpt->uuid == GATT_UUID_BATTERY_LEVEL)
+            {
+#if BTA_HH_DEBUG == TRUE
+                APPL_TRACE_DEBUG("read battery level report reference descriptor");
+#endif
+                srvc_uuid = UUID_SERVCLASS_BATTERY;
+                char_uuid = GATT_UUID_BATTERY_LEVEL;
+            }
+            else
+            {
+#if BTA_HH_DEBUG == TRUE
+                APPL_TRACE_DEBUG("read HID report reference descriptor");
+#endif
+                srvc_uuid = UUID_SERVCLASS_LE_HID;
+                char_uuid = GATT_UUID_HID_REPORT;
+            }
+
+            if (bta_hh_le_read_char_dscrpt(p_dev_cb,
+                                            srvc_uuid,
+                                            BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt->inst_id),
+                                            char_uuid,
+                                            BTA_HH_LE_RPT_GET_RPT_INST_ID(p_rpt->inst_id),
+                                            GATT_UUID_RPT_REF_DESCR)
+                == BTA_HH_OK)
+            {
+                started = TRUE;
+                break;
+            }
+        }
+
+        if (p_rpt->index == BTA_HH_LE_RPT_MAX - 1)
+            break;
+
+        p_rpt ++;
+    }
+
+
+    /* if no report reference descriptor */
+    if (!started)
+    {
+        /* explore next char */
+        bta_hh_le_search_hid_chars(p_dev_cb);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_save_rpt_ref
+**
+** Description      save report reference information and move to next one.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_le_save_rpt_ref(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_LE_RPT  *p_rpt,
+                            tBTA_GATTC_READ *p_data)
+{
+    UINT8                       *pp;
+    tBTA_HH_RPT_CACHE_ENTRY     rpt_entry;
+
+    /* if the length of the descriptor value is right, parse it */
+    if (p_data->status == BTA_GATT_OK &&
+        p_data->p_value && p_data->p_value->unformat.len == 2)
+    {
+        pp = p_data->p_value->unformat.p_value;
+
+        STREAM_TO_UINT8(p_rpt->rpt_id, pp);
+        STREAM_TO_UINT8(p_rpt->rpt_type, pp);
+
+        if (p_rpt->rpt_type > BTA_HH_RPTT_FEATURE) /* invalid report type */
+            p_rpt->rpt_type = BTA_HH_RPTT_RESRV;
+
+#if BTA_HH_DEBUG == TRUE
+        APPL_TRACE_DEBUG("report ID: %d", p_rpt->rpt_id);
+#endif
+        rpt_entry.rpt_id    = p_rpt->rpt_id;
+        rpt_entry.rpt_type  = p_rpt->rpt_type;
+        rpt_entry.rpt_uuid  = p_rpt->uuid;
+        rpt_entry.prop      = p_rpt->prop;
+        rpt_entry.inst_id   = p_rpt->inst_id;
+
+        bta_hh_le_co_rpt_info(p_dev_cb->addr,
+                              &rpt_entry,
+                              p_dev_cb->app_id);
+    }
+    else if (p_data->status == BTA_GATT_INSUF_AUTHENTICATION)
+    {
+        /* close connection right away */
+        p_dev_cb->status = BTA_HH_ERR_AUTH_FAILED;
+        /* close the connection and report service discovery complete with error */
+        bta_hh_le_api_disc_act(p_dev_cb);
+        return;
+    }
+
+    if (p_rpt->index < BTA_HH_LE_RPT_MAX - 1)
+        p_rpt ++;
+    else
+        p_rpt = NULL;
+
+    /* read next report reference descriptor  */
+    bta_hh_le_read_rpt_ref_descr(p_dev_cb, p_rpt);
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_save_rpt_ref
+**
+** Description      save report reference information and move to next one.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_le_save_ext_rpt_ref(tBTA_HH_DEV_CB *p_dev_cb,
+                                tBTA_GATTC_READ *p_data)
+{
+    UINT8 *pp;
+
+    /* if the length of the descriptor value is right, parse it
+      assume it's a 16 bits UUID */
+    if (p_data->status == BTA_GATT_OK &&
+        p_data->p_value && p_data->p_value->unformat.len == 2)
+    {
+        pp = p_data->p_value->unformat.p_value;
+        STREAM_TO_UINT16(p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].ext_rpt_ref, pp);
+
+#if BTA_HH_DEBUG == TRUE
+        APPL_TRACE_DEBUG("External Report Reference UUID 0x%04x",
+                    p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].ext_rpt_ref);
+#endif
+    }
+    bta_hh_le_search_hid_chars(p_dev_cb);
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_register_input_notif
+**
+** Description      Register for all notifications for the report applicable
+**                  for the protocol mode.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_le_register_input_notif(tBTA_HH_DEV_CB *p_dev_cb, UINT8 srvc_inst,
+                                    UINT8 proto_mode, BOOLEAN register_ba)
+{
+    tBTA_HH_LE_RPT  *p_rpt = &p_dev_cb->hid_srvc[srvc_inst].report[0];
+    tBTA_GATTC_CHAR_ID  char_id;
+    UINT8   i;
+    UINT16  srvc_uuid;
+
+#if BTA_HH_DEBUG == TRUE
+    APPL_TRACE_DEBUG("bta_hh_le_register_input_notif mode: %d", proto_mode);
+#endif
+
+    for (i = 0; i < BTA_HH_LE_RPT_MAX; i ++, p_rpt ++)
+    {
+        if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT)
+        {
+            if (p_rpt->uuid == GATT_UUID_BATTERY_LEVEL)
+                srvc_uuid = UUID_SERVCLASS_BATTERY;
+            else
+                srvc_uuid = UUID_SERVCLASS_LE_HID;
+
+            bta_hh_le_fill_16bits_srvc_id(TRUE, BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt->inst_id), srvc_uuid, &char_id.srvc_id);
+            bta_hh_le_fill_16bits_char_id(BTA_HH_LE_RPT_GET_RPT_INST_ID(p_rpt->inst_id), p_rpt->uuid, &char_id.char_id);
+
+            if (register_ba && p_rpt->uuid == GATT_UUID_BATTERY_LEVEL)
+            {
+                BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if,
+                                                   p_dev_cb->addr,
+                                                   &char_id);
+            }
+            /* boot mode, deregister report input notification */
+            else if (proto_mode == BTA_HH_PROTO_BOOT_MODE)
+            {
+                if (p_rpt->uuid == GATT_UUID_HID_REPORT &&
+                    p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION)
+                {
+                    APPL_TRACE_DEBUG("---> Deregister Report ID: %d", p_rpt->rpt_id);
+                    BTA_GATTC_DeregisterForNotifications(bta_hh_cb.gatt_if,
+                                                       p_dev_cb->addr,
+                                                       &char_id);
+                }
+                /* register boot reports notification */
+                else if (p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
+                         p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT)
+                {
+                    APPL_TRACE_DEBUG("<--- Register Boot Report ID: %d", p_rpt->rpt_id);
+                    BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if,
+                                                       p_dev_cb->addr,
+                                                       &char_id);
+                }
+            }
+            else if (proto_mode == BTA_HH_PROTO_RPT_MODE)
+            {
+                if ((p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
+                    p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT) &&
+                    p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION)
+                {
+
+                    APPL_TRACE_DEBUG("---> Deregister Boot Report ID: %d", p_rpt->rpt_id);
+                    BTA_GATTC_DeregisterForNotifications(bta_hh_cb.gatt_if,
+                                                       p_dev_cb->addr,
+                                                       &char_id);
+                }
+                else if (p_rpt->uuid == GATT_UUID_HID_REPORT &&
+                         p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION)
+                {
+                    APPL_TRACE_DEBUG("<--- Register Report ID: %d", p_rpt->rpt_id);
+                    BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if,
+                                                       p_dev_cb->addr,
+                                                       &char_id);
+                }
+            }
+            /*
+            else unknow protocol mode */
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_open_cmpl
+**
+** Description      HID over GATT connection sucessfully opened
+**
+*******************************************************************************/
+void bta_hh_le_open_cmpl(tBTA_HH_DEV_CB *p_cb)
+{
+    if ( p_cb->disc_active == BTA_HH_LE_DISC_NONE)
+    {
+#if BTA_HH_DEBUG
+        bta_hh_le_hid_report_dbg(p_cb);
+#endif
+        bta_hh_le_register_input_notif(p_cb, 0, p_cb->mode, TRUE);
+        bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, NULL);
+
+#if (BTA_HH_LE_RECONN == TRUE)
+        if (p_cb->status == BTA_HH_OK)
+        {
+            bta_hh_le_add_dev_bg_conn(p_cb, TRUE);
+        }
+#endif
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_write_char_clt_cfg
+**
+** Description      Utility function to find and write client configuration of
+**                  a characteristic
+**
+*******************************************************************************/
+BOOLEAN bta_hh_le_write_char_clt_cfg(tBTA_HH_DEV_CB *p_cb,
+                                     UINT8 srvc_inst_id, UINT16 srvc_uuid16,
+                                     UINT8 char_inst_id, UINT16 char_uuid16,
+                                     UINT16 clt_cfg_value)
+{
+    tBTA_GATTC_CHAR_ID          char_id;
+    tBT_UUID                    descr_cond;
+    tBTA_GATTC_CHAR_DESCR_ID    descr_id;
+    tBTA_GATT_UNFMT             value;
+    UINT8                      buf[2], *pp = buf;
+
+    bta_hh_le_fill_16bits_srvc_id(TRUE, srvc_inst_id, srvc_uuid16, &char_id.srvc_id);
+    bta_hh_le_fill_16bits_char_id(char_inst_id, char_uuid16, &char_id.char_id);
+
+    descr_cond.len       = LEN_UUID_16;
+    descr_cond.uu.uuid16 = GATT_UUID_CHAR_CLIENT_CONFIG;
+
+    value.len = 2;
+    value.p_value = buf;
+
+    UINT16_TO_STREAM(pp, clt_cfg_value);
+
+    if (BTA_GATTC_GetFirstCharDescr(p_cb->conn_id,
+                                    &char_id,
+                                    &descr_cond,
+                                    &descr_id) == BTA_GATT_OK)
+    {
+        BTA_GATTC_WriteCharDescr(p_cb->conn_id,
+                            &descr_id,
+                            BTA_GATTC_TYPE_WRITE,
+                            &value,
+                            BTA_GATT_AUTH_REQ_NONE);
+
+        return TRUE;
+    }
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_write_rpt_clt_cfg
+**
+** Description      write client configuration. This is only for input report
+**                  enable all input notification upon connection open.
+**
+*******************************************************************************/
+BOOLEAN bta_hh_le_write_rpt_clt_cfg(tBTA_HH_DEV_CB *p_cb, UINT8 srvc_inst_id)
+{
+    UINT8           i;
+    tBTA_HH_LE_RPT  *p_rpt = &p_cb->hid_srvc[srvc_inst_id].report[p_cb->clt_cfg_idx];
+    UINT16          srvc_uuid;
+
+    for (i = p_cb->clt_cfg_idx; i < BTA_HH_LE_RPT_MAX && p_rpt->in_use; i ++, p_rpt ++)
+    {
+        /* enable notification for all input report, regardless mode */
+        if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT)
+
+        {
+            if (p_rpt->uuid == GATT_UUID_BATTERY_LEVEL)
+                srvc_uuid = UUID_SERVCLASS_BATTERY;
+            else
+                srvc_uuid = UUID_SERVCLASS_LE_HID;
+
+            if (bta_hh_le_write_char_clt_cfg(p_cb,
+                                             BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt->inst_id),
+                                             srvc_uuid,
+                                             BTA_HH_LE_RPT_GET_RPT_INST_ID(p_rpt->inst_id),
+                                             p_rpt->uuid,
+                                             BTA_GATT_CLT_CONFIG_NOTIFICATION))
+            {
+                p_cb->clt_cfg_idx = i;
+                return TRUE;
+            }
+        }
+
+    }
+    p_cb->clt_cfg_idx = 0;
+
+    /* client configuration is completed, send open callback */
+    if (p_cb->state == BTA_HH_W4_CONN_ST)
+    {
+        p_cb->disc_active &= ~BTA_HH_LE_DISC_HIDS;
+
+        /* discover scan parameter profile is act as report host */
+        bta_hh_le_search_scps(p_cb);
+    }
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_set_protocol_mode
+**
+** Description      Set remote device protocol mode.
+**
+*******************************************************************************/
+BOOLEAN bta_hh_le_set_protocol_mode(tBTA_HH_DEV_CB *p_cb, tBTA_HH_PROTO_MODE mode)
+{
+    tBTA_GATTC_CHAR_ID  char_id;
+    tBTA_HH_CBDATA      cback_data ;
+    BOOLEAN             exec = FALSE;
+
+    APPL_TRACE_DEBUG("bta_hh_le_set_protocol_mode attempt mode: %s",
+                      (mode == BTA_HH_PROTO_RPT_MODE)? "Report": "Boot");
+
+    cback_data.handle  = p_cb->hid_handle;
+    /* boot mode is not supported in the remote device */
+    if ((p_cb->hid_srvc[BTA_HH_LE_SRVC_DEF].option_char & BTA_HH_LE_PROTO_MODE_BIT) == 0)
+    {
+        p_cb->mode  = BTA_HH_PROTO_RPT_MODE;
+
+        if (mode == BTA_HH_PROTO_BOOT_MODE)
+        {
+            APPL_TRACE_ERROR("Set Boot Mode failed!! No PROTO_MODE Char!");
+            cback_data.status = BTA_HH_ERR;
+        }
+        else
+        {
+            /* if set to report mode, need to de-register all input report notification */
+            bta_hh_le_register_input_notif(p_cb, 0, p_cb->mode, FALSE);
+            cback_data.status = BTA_HH_OK;
+        }
+        if (p_cb->state == BTA_HH_W4_CONN_ST)
+        {
+            p_cb->status = (cback_data.status == BTA_HH_OK)? BTA_HH_OK: BTA_HH_ERR_PROTO;
+        }
+        else
+            (* bta_hh_cb.p_cback)(BTA_HH_SET_PROTO_EVT, (tBTA_HH *)&cback_data);
+    }
+    else if (p_cb->mode != mode)
+    {
+        bta_hh_le_fill_16bits_srvc_id(TRUE, 0, UUID_SERVCLASS_LE_HID, &char_id.srvc_id);
+        bta_hh_le_fill_16bits_char_id(0, GATT_UUID_HID_PROTO_MODE, &char_id.char_id);
+
+        p_cb->mode = mode;
+        mode = (mode == BTA_HH_PROTO_BOOT_MODE)? BTA_HH_LE_PROTO_BOOT_MODE : BTA_HH_LE_PROTO_REPORT_MODE;
+
+        BTA_GATTC_WriteCharValue(p_cb->conn_id,
+                                 &char_id,
+                                 BTA_GATTC_TYPE_WRITE_NO_RSP,
+                                 1,
+                                 &mode,
+                                 BTA_GATT_AUTH_REQ_NONE);
+        exec        = TRUE;
+    }
+
+    return exec;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_get_protocol_mode
+**
+** Description      Get remote device protocol mode.
+**
+*******************************************************************************/
+void bta_hh_le_get_protocol_mode(tBTA_HH_DEV_CB *p_cb)
+{
+    tBTA_GATTC_CHAR_ID  char_id;
+    tBTA_HH_HSDATA    hs_data;
+    UINT8 i;
+
+    p_cb->w4_evt = BTA_HH_GET_PROTO_EVT;
+
+    for (i = 0; i< BTA_HH_LE_HID_SRVC_MAX; i ++)
+    {
+        if (p_cb->hid_srvc[i].in_use &&
+            p_cb->hid_srvc[i].option_char & BTA_HH_LE_PROTO_MODE_BIT)
+        {
+            bta_hh_le_fill_16bits_srvc_id(TRUE, 0, UUID_SERVCLASS_LE_HID, &char_id.srvc_id);
+            bta_hh_le_fill_16bits_char_id(0, GATT_UUID_HID_PROTO_MODE, &char_id.char_id);
+
+            BTA_GATTC_ReadCharacteristic(p_cb->conn_id,
+                                        &char_id,
+                                        BTA_GATT_AUTH_REQ_NONE);
+            break;
+        }
+    }
+    /* no service support protocol_mode, by default report mode */
+    if (i == BTA_HH_LE_HID_SRVC_MAX)
+    {
+        hs_data.status  = BTA_HH_OK;
+        hs_data.handle  = p_cb->hid_handle;
+        hs_data.rsp_data.proto_mode = BTA_HH_PROTO_RPT_MODE;
+        p_cb->w4_evt = 0;
+        (* bta_hh_cb.p_cback)(BTA_HH_GET_PROTO_EVT, (tBTA_HH *)&hs_data);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_expl_rpt
+**
+** Description      explore all report characteristic
+**
+*******************************************************************************/
+void bta_hh_le_expl_rpt(tBTA_HH_DEV_CB *p_dev_cb,
+                           tBTA_GATTC_CHAR_ID *p_char_id,
+                           tBT_UUID *p_char_cond,
+                           tBTA_GATT_CHAR_PROP prop)
+{
+    tBTA_GATTC_CHAR_ID  char_result;
+
+    do
+    {
+        if (bta_hh_le_find_alloc_report_entry(p_dev_cb,
+                                          p_dev_cb->cur_srvc_index,
+                                          GATT_UUID_HID_REPORT,
+                                          p_char_id->char_id.inst_id,
+                                          prop) == NULL)
+        {
+            APPL_TRACE_ERROR("Add report entry failed !!!");
+            break;
+        }
+
+        APPL_TRACE_DEBUG("Find more REPORT");
+
+        if (BTA_GATTC_GetNextChar(p_dev_cb->conn_id,
+                          p_char_id,
+                          p_char_cond,
+                          &char_result,
+                          &prop) != BTA_GATT_OK)
+            break;
+
+        p_char_id = &char_result;
+    }
+    while (1);
+
+    LOG_INFO("%s all BLE reports searched", __func__);
+    bta_hh_le_read_rpt_ref_descr(p_dev_cb,
+                                 &p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].report[0]);
+
+
+    return ;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_expl_boot_rpt
+**
+** Description      explore boot report
+**
+*******************************************************************************/
+void bta_hh_le_expl_boot_rpt(tBTA_HH_DEV_CB *p_dev_cb, UINT16 char_uuid,
+                                tBTA_GATT_CHAR_PROP prop)
+{
+    if (bta_hh_le_find_alloc_report_entry(p_dev_cb,
+                                      p_dev_cb->cur_srvc_index,
+                                      char_uuid,
+                                      0,
+                                      prop) == NULL)
+
+    {
+        APPL_TRACE_ERROR("Add report entry failed !!!");
+    }
+
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_dis_cback
+**
+** Description      DIS read complete callback
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_le_dis_cback(BD_ADDR addr, tDIS_VALUE *p_dis_value)
+{
+    tBTA_HH_DEV_CB *p_cb = bta_hh_le_find_dev_cb_by_bda(addr);
+
+
+    if (p_cb == NULL || p_dis_value == NULL)
+    {
+        APPL_TRACE_ERROR("received unexpected/error DIS callback");
+        return;
+    }
+
+    p_cb->disc_active &= ~BTA_HH_LE_DISC_DIS;
+    /* plug in the PnP info for this device */
+    if (p_dis_value->attr_mask & DIS_ATTR_PNP_ID_BIT)
+    {
+#if BTA_HH_DEBUG == TRUE
+        APPL_TRACE_DEBUG("Plug in PnP info: product_id = %02x, vendor_id = %04x, version = %04x",
+                p_dis_value->pnp_id.product_id,
+                p_dis_value->pnp_id.vendor_id,
+                p_dis_value->pnp_id.product_version);
+#endif
+        p_cb->dscp_info.product_id = p_dis_value->pnp_id.product_id;
+        p_cb->dscp_info.vendor_id  = p_dis_value->pnp_id.vendor_id;
+        p_cb->dscp_info.version    = p_dis_value->pnp_id.product_version;
+    }
+    bta_hh_le_open_cmpl(p_cb);
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_pri_service_discovery
+**
+** Description      Initialize GATT discovery on the remote LE HID device by opening
+**                  a GATT connection first.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_le_pri_service_discovery(tBTA_HH_DEV_CB *p_cb)
+{
+    tBT_UUID        pri_srvc;
+
+    bta_hh_le_co_reset_rpt_cache(p_cb->addr, p_cb->app_id);
+
+    p_cb->disc_active |= (BTA_HH_LE_DISC_HIDS|BTA_HH_LE_DISC_DIS);
+
+    /* read DIS info */
+    if (!DIS_ReadDISInfo(p_cb->addr, bta_hh_le_dis_cback, DIS_ATTR_PNP_ID_BIT))
+    {
+        APPL_TRACE_ERROR("read DIS failed");
+        p_cb->disc_active &= ~BTA_HH_LE_DISC_DIS;
+    }
+
+    /* in parallel */
+    /* start primary service discovery for HID service */
+    pri_srvc.len        = LEN_UUID_16;
+    pri_srvc.uu.uuid16  = UUID_SERVCLASS_LE_HID;
+    BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, &pri_srvc);
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_encrypt_cback
+**
+** Description      link encryption complete callback for bond verification.
+**
+** Returns          None
+**
+*******************************************************************************/
+void bta_hh_le_encrypt_cback(BD_ADDR bd_addr, tBTA_GATT_TRANSPORT transport,
+                                    void *p_ref_data, tBTM_STATUS result)
+{
+    UINT8   idx = bta_hh_find_cb(bd_addr);
+    tBTA_HH_DEV_CB *p_dev_cb;
+    UNUSED(p_ref_data);
+    UNUSED (transport);
+
+    if (idx != BTA_HH_IDX_INVALID)
+        p_dev_cb = &bta_hh_cb.kdev[idx];
+    else
+    {
+        APPL_TRACE_ERROR("unexpected encryption callback, ignore");
+        return;
+    }
+    p_dev_cb->status = (result == BTM_SUCCESS) ? BTA_HH_OK : BTA_HH_ERR_SEC;
+    p_dev_cb->reason = result;
+
+    bta_hh_sm_execute(p_dev_cb, BTA_HH_ENC_CMPL_EVT, NULL);
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_security_cmpl
+**
+** Description      Security check completed, start the service discovery
+**                  if no cache available, otherwise report connection open completed
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_security_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
+{
+    tBTA_HH_RPT_CACHE_ENTRY     *p_rpt_cache;
+    UINT8                       num_rpt = 0;
+    UNUSED(p_buf);
+
+    if (p_cb->status == BTA_HH_OK)
+    {
+        APPL_TRACE_DEBUG("bta_hh_security_cmpl OK");
+        if (!p_cb->hid_srvc[BTA_HH_LE_SRVC_DEF].in_use)
+        {
+            APPL_TRACE_DEBUG("bta_hh_security_cmpl no reports loaded, try to load");
+            /* start loading the cache if not in stack */
+            if ((p_rpt_cache = bta_hh_le_co_cache_load(p_cb->addr, &num_rpt, p_cb->app_id)) != NULL)
+            {
+                bta_hh_process_cache_rpt(p_cb, p_rpt_cache, num_rpt);
+            }
+        }
+        /*  discovery has been done for HID service */
+        if (p_cb->app_id != 0 && p_cb->hid_srvc[BTA_HH_LE_SRVC_DEF].in_use)
+        {
+            /* configure protocol mode */
+            if (bta_hh_le_set_protocol_mode(p_cb, p_cb->mode) == FALSE)
+            {
+                APPL_TRACE_ERROR("bta_hh_security_cmpl");
+                bta_hh_le_open_cmpl(p_cb);
+            }
+        }
+        /* start primary service discovery for HID service */
+        else
+        {
+            bta_hh_le_pri_service_discovery(p_cb);
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR("%s() - encryption failed; status=0x%04x, reason=0x%04x",
+                __FUNCTION__, p_cb->status, p_cb->reason);
+        if (!(p_cb->status == BTA_HH_ERR_SEC && p_cb->reason == BTM_ERR_PROCESSING))
+            bta_hh_le_api_disc_act(p_cb);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_notify_enc_cmpl
+**
+** Description      process GATT encryption complete event
+**
+** Returns
+**
+*******************************************************************************/
+void bta_hh_le_notify_enc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
+{
+    if (p_cb == NULL || p_cb->security_pending == FALSE ||
+        p_buf == NULL || p_buf->le_enc_cmpl.client_if != bta_hh_cb.gatt_if)
+    {
+        return;
+    }
+
+    p_cb->security_pending = FALSE;
+    bta_hh_start_security(p_cb, NULL);
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_clear_service_cache
+**
+** Description      clear the service cache
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_clear_service_cache(tBTA_HH_DEV_CB *p_cb)
+{
+    UINT8 i;
+    tBTA_HH_LE_HID_SRVC     *p_hid_srvc = &p_cb->hid_srvc[0];
+
+    p_cb->app_id = 0;
+    p_cb->total_srvc = 0;
+    p_cb->dscp_info.descriptor.dsc_list = NULL;
+
+    for (i = 0; i < BTA_HH_LE_HID_SRVC_MAX; i ++, p_hid_srvc ++)
+    {
+        utl_freebuf((void **)&p_hid_srvc->rpt_map);
+        memset(p_hid_srvc, 0, sizeof(tBTA_HH_LE_HID_SRVC));
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_start_security
+**
+** Description      start the security check of the established connection
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_start_security(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
+{
+    UINT8           sec_flag=0;
+    tBTM_SEC_DEV_REC  *p_dev_rec;
+    UNUSED(p_buf);
+
+    p_dev_rec = btm_find_dev(p_cb->addr);
+    if (p_dev_rec)
+    {
+        if (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING ||
+            p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING)
+        {
+            /* if security collision happened, wait for encryption done */
+            p_cb->security_pending = TRUE;
+            return;
+        }
+    }
+
+    /* verify bond */
+    BTM_GetSecurityFlagsByTransport(p_cb->addr, &sec_flag, BT_TRANSPORT_LE);
+
+    /* if link has been encrypted */
+    if (sec_flag & BTM_SEC_FLAG_ENCRYPTED)
+    {
+        bta_hh_sm_execute(p_cb, BTA_HH_ENC_CMPL_EVT, NULL);
+    }
+    /* if bonded and link not encrypted */
+    else if (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN)
+    {
+        sec_flag = BTM_BLE_SEC_ENCRYPT;
+        p_cb->status = BTA_HH_ERR_AUTH_FAILED;
+        BTM_SetEncryption(p_cb->addr, BTA_TRANSPORT_LE, bta_hh_le_encrypt_cback, &sec_flag);
+    }
+    /* unbonded device, report security error here */
+    else if (p_cb->sec_mask != BTA_SEC_NONE)
+    {
+        sec_flag = BTM_BLE_SEC_ENCRYPT_NO_MITM;
+        p_cb->status = BTA_HH_ERR_AUTH_FAILED;
+        bta_hh_clear_service_cache(p_cb);
+        BTM_SetEncryption(p_cb->addr, BTA_TRANSPORT_LE, bta_hh_le_encrypt_cback, &sec_flag);
+    }
+    /* otherwise let it go through */
+    else
+    {
+        bta_hh_sm_execute(p_cb, BTA_HH_ENC_CMPL_EVT, NULL);
+    }
+
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_gatt_open
+**
+** Description      process GATT open event.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_gatt_open(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
+{
+    tBTA_GATTC_OPEN *p_data = &p_buf->le_open;
+    UINT8           *p2;
+    tHID_STATUS     status = BTA_HH_ERR;
+
+    /* if received invalid callback data , ignore it */
+    if (p_cb == NULL || p_data == NULL)
+        return;
+
+    p2 = p_data->remote_bda;
+
+    APPL_TRACE_DEBUG("bta_hh_gatt_open BTA_GATTC_OPEN_EVT bda= [%08x%04x] status =%d",
+                      ((p2[0])<<24)+((p2[1])<<16)+((p2[2])<<8)+(p2[3]),
+                      ((p2[4])<<8)+ p2[5],p_data->status);
+
+    if (p_data->status == BTA_GATT_OK)
+    {
+        p_cb->is_le_device  = TRUE;
+        p_cb->in_use    = TRUE;
+        p_cb->conn_id   = p_data->conn_id;
+        p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
+
+        bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
+
+#if BTA_HH_DEBUG == TRUE
+        APPL_TRACE_DEBUG("hid_handle = %2x conn_id = %04x cb_index = %d", p_cb->hid_handle, p_cb->conn_id, p_cb->index);
+#endif
+
+        bta_hh_sm_execute(p_cb, BTA_HH_START_ENC_EVT, NULL);
+
+    }
+    else /* open failure */
+    {
+        bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_close
+**
+** Description      This function process the GATT close event and post it as a
+**                  BTA HH internal event
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_le_close(tBTA_GATTC_CLOSE * p_data)
+{
+    tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->remote_bda);
+    tBTA_HH_LE_CLOSE    *p_buf = NULL;
+    UINT16  sm_event = BTA_HH_GATT_CLOSE_EVT;
+
+    if (p_dev_cb != NULL &&
+        (p_buf = (tBTA_HH_LE_CLOSE *)GKI_getbuf(sizeof(tBTA_HH_LE_CLOSE))) != NULL)
+    {
+        p_buf->hdr.event            = sm_event;
+        p_buf->hdr.layer_specific   = (UINT16)p_dev_cb->hid_handle;
+        p_buf->conn_id              = p_data->conn_id;
+        p_buf->reason               = p_data->reason;
+
+        p_dev_cb->conn_id           = BTA_GATT_INVALID_CONN_ID;
+        p_dev_cb->security_pending  = FALSE;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_search_result
+**
+** Description      This function process the GATT service search result.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_le_search_result(tBTA_GATTC_SRVC_RES *p_srvc_result)
+{
+    tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_srvc_result->conn_id);
+
+    if (p_dev_cb != NULL)
+    {
+        switch (p_srvc_result->service_uuid.id.uuid.uu.uuid16)
+        {
+        case UUID_SERVCLASS_LE_HID:
+            if (p_srvc_result->service_uuid.is_primary)
+            {
+                /* found HID primamry service */
+                /* TODO: proceed to find battery and device info */
+                if (bta_hh_le_add_hid_srvc_entry(p_dev_cb, p_dev_cb->total_srvc))
+                    p_dev_cb->total_srvc ++;
+                APPL_TRACE_DEBUG("num of hid service: %d", p_dev_cb->total_srvc);
+            }
+            break;
+
+        case UUID_SERVCLASS_SCAN_PARAM : /* scan parameter service */
+            bta_hh_le_search_scps_chars(p_dev_cb);
+            break;
+        }
+
+    }
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_gatt_disc_cmpl
+**
+** Description      Check to see if the remote device is a LE only device
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_le_gatt_disc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_STATUS status)
+{
+    APPL_TRACE_DEBUG("bta_hh_le_gatt_disc_cmpl ");
+
+    /* if open sucessful or protocol mode not desired, keep the connection open but inform app */
+    if (status == BTA_HH_OK || status == BTA_HH_ERR_PROTO)
+    {
+        /* assign a special APP ID temp, since device type unknown */
+        p_cb->app_id = BTA_HH_APP_ID_LE;
+
+        /* set report notification configuration */
+        p_cb->clt_cfg_idx = 0;
+        bta_hh_le_write_rpt_clt_cfg(p_cb, BTA_HH_LE_SRVC_DEF);
+    }
+    else /* error, close the GATT connection */
+    {
+        /* close GATT connection if it's on */
+        bta_hh_le_api_disc_act(p_cb);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_srvc_expl_srvc
+**
+** Description      This function discover the next avaible HID service.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_le_srvc_expl_srvc(tBTA_HH_DEV_CB *p_dev_cb)
+{
+#if BTA_HH_DEBUG == TRUE
+    APPL_TRACE_DEBUG("bta_hh_le_srvc_expl_srvc cur_srvc_index = %d in_use = %d",
+                    p_dev_cb->cur_srvc_index,
+                    p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].in_use);
+#endif
+
+    if (p_dev_cb->cur_srvc_index < BTA_HH_LE_HID_SRVC_MAX &&
+        p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].in_use)
+    {
+        if (!p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].expl_incl_srvc)
+            /* explore included service first */
+            bta_hh_le_search_hid_included(p_dev_cb);
+        else
+        {
+            /* explore characterisc */
+            p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].cur_expl_char_idx = 0;
+            bta_hh_le_search_hid_chars(p_dev_cb);
+        }
+    }
+    else /* all service discvery finished */
+    {
+        bta_hh_le_gatt_disc_cmpl(p_dev_cb, p_dev_cb->status);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_srvc_search_cmpl
+**
+** Description      This function process the GATT service search complete.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_le_srvc_search_cmpl(tBTA_GATTC_SEARCH_CMPL *p_data)
+{
+    tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->conn_id);
+
+    /* service search exception or no HID service is supported on remote */
+    if (p_dev_cb == NULL)
+        return;
+
+    if(p_data->status != BTA_GATT_OK || p_dev_cb->total_srvc == 0)
+    {
+        p_dev_cb->status = BTA_HH_ERR_SDP;
+        /* close the connection and report service discovery complete with error */
+        bta_hh_le_api_disc_act(p_dev_cb);
+    }
+    /* GATT service discovery sucessfully finished */
+    else
+    {
+        if (p_dev_cb->disc_active  & BTA_HH_LE_DISC_SCPS)
+        {
+            p_dev_cb->disc_active  &= ~BTA_HH_LE_DISC_SCPS;
+            bta_hh_le_open_cmpl(p_dev_cb);
+        }
+        else /* discover HID service */
+        {
+        p_dev_cb->cur_srvc_index = 0;
+        bta_hh_le_srvc_expl_srvc(p_dev_cb);
+    }
+}
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_search_hid_included
+**
+** Description      This function search the included service within the HID service.
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_hh_le_search_hid_included(tBTA_HH_DEV_CB *p_dev_cb)
+{
+    tBT_UUID    srvc_cond, char_cond;
+    tBTA_GATTC_INCL_SVC_ID  inc_srvc_result;
+    tBTA_GATT_SRVC_ID srvc_id;
+    tBTA_GATTC_CHAR_ID  char_result;
+    tBTA_GATT_CHAR_PROP prop = 0;
+
+    bta_hh_le_fill_16bits_srvc_id(TRUE, p_dev_cb->cur_srvc_index, UUID_SERVCLASS_LE_HID, &srvc_id);
+
+    srvc_cond.len = LEN_UUID_16;
+    srvc_cond.uu.uuid16 = UUID_SERVCLASS_BATTERY;
+
+    if (BTA_GATTC_GetFirstIncludedService(p_dev_cb->conn_id,
+                            &srvc_id,
+                            &srvc_cond,
+                            &inc_srvc_result) == BTA_GATT_OK)
+    {
+        /* read include service UUID */
+        p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].incl_srvc_inst = inc_srvc_result.incl_svc_id.id.inst_id;
+
+        char_cond.len = LEN_UUID_16;
+        char_cond.uu.uuid16 = GATT_UUID_BATTERY_LEVEL;
+
+        /* find the battery characteristic */
+        if (BTA_GATTC_GetFirstChar( p_dev_cb->conn_id,
+                                    &inc_srvc_result.incl_svc_id,
+                                    &char_cond,
+                                    &char_result,
+                                    &prop) == BTA_GATT_OK)
+        {
+
+            if (bta_hh_le_find_alloc_report_entry(p_dev_cb,
+                                                  char_result.srvc_id.id.inst_id,
+                                                  GATT_UUID_BATTERY_LEVEL,
+                                                  char_result.char_id.inst_id,
+                                                  prop) == NULL)
+            {
+                APPL_TRACE_ERROR("Add battery report entry failed !!!")
+            }
+
+            /* read the battery characteristic */
+            BTA_GATTC_ReadCharacteristic(p_dev_cb->conn_id,
+                                         &char_result,
+                                         BTA_GATT_AUTH_REQ_NONE);
+
+            return;
+
+        }
+        else
+        {
+            APPL_TRACE_ERROR("Remote device does not have battery level");
+        }
+    }
+
+    p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].expl_incl_srvc = TRUE;
+
+    bta_hh_le_srvc_expl_srvc(p_dev_cb);
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_read_battery_level_cmpl
+**
+** Description      This function process the battery level read
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_read_battery_level_cmpl(UINT8 status, tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
+{
+    UNUSED(status);
+    UNUSED(p_data);
+
+    p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].expl_incl_srvc = TRUE;
+    bta_hh_le_srvc_expl_srvc(p_dev_cb);
+}
+/*******************************************************************************
+**
+** Function         bta_hh_le_search_hid_chars
+**
+** Description      This function discover all characteristics a service and
+**                  all descriptors available.
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_hh_le_search_hid_chars(tBTA_HH_DEV_CB *p_dev_cb)
+{
+    tBT_UUID    char_cond;
+    tBTA_GATTC_CHAR_ID  char_result;
+    tBTA_GATT_CHAR_PROP prop;
+    BOOLEAN     next = TRUE;
+    UINT16      char_uuid = 0;
+    tBTA_GATT_SRVC_ID srvc_id;
+
+    if (p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].cur_expl_char_idx == BTA_HH_LE_DISC_CHAR_NUM ||
+        (p_dev_cb->status != BTA_HH_OK && p_dev_cb->status != BTA_HH_ERR_PROTO))
+    {
+        p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].cur_expl_char_idx = 0;
+        /* explore next service */
+        p_dev_cb->cur_srvc_index ++;
+        bta_hh_le_srvc_expl_srvc(p_dev_cb);
+        return;
+    }
+
+    p_dev_cb->hid_srvc[ p_dev_cb->cur_srvc_index].cur_expl_char_idx ++;
+    char_uuid = bta_hh_le_disc_char_uuid[p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].cur_expl_char_idx - 1];
+
+    char_cond.len = LEN_UUID_16;
+    char_cond.uu.uuid16 = char_uuid;
+
+    bta_hh_le_fill_16bits_srvc_id(TRUE, p_dev_cb->cur_srvc_index, UUID_SERVCLASS_LE_HID, &srvc_id);
+
+#if BTA_HH_DEBUG == TRUE
+    APPL_TRACE_DEBUG("bta_hh_le_search_hid_chars: looking for %s(0x%04x)",
+                       bta_hh_uuid_to_str(char_uuid), char_uuid);
+#endif
+
+    if (BTA_GATTC_GetFirstChar( p_dev_cb->conn_id,
+                            &srvc_id,
+                            &char_cond,
+                            &char_result,
+                            &prop) == BTA_GATT_OK)
+    {
+        switch (char_uuid)
+        {
+        case GATT_UUID_HID_CONTROL_POINT:
+            p_dev_cb->hid_srvc[char_result.srvc_id.id.inst_id].option_char |= BTA_HH_LE_CP_BIT;
+            next = TRUE;
+            break;
+        case GATT_UUID_HID_INFORMATION:
+        case GATT_UUID_HID_REPORT_MAP:
+            /* read the char value */
+            BTA_GATTC_ReadCharacteristic(p_dev_cb->conn_id,
+                                        &char_result,
+                                        BTA_GATT_AUTH_REQ_NONE);
+            next = FALSE;
+            break;
+
+        case GATT_UUID_HID_PROTO_MODE:
+            p_dev_cb->hid_srvc[char_result.srvc_id.id.inst_id].option_char |= BTA_HH_LE_PROTO_MODE_BIT;
+            next = !bta_hh_le_set_protocol_mode(p_dev_cb, p_dev_cb->mode);
+            break;
+
+        case GATT_UUID_HID_REPORT:
+            bta_hh_le_expl_rpt(p_dev_cb, &char_result, &char_cond, prop);
+            next = FALSE;
+            break;
+
+        /* found boot mode report types */
+        case GATT_UUID_HID_BT_KB_OUTPUT:
+        case GATT_UUID_HID_BT_MOUSE_INPUT:
+        case GATT_UUID_HID_BT_KB_INPUT:
+            bta_hh_le_expl_boot_rpt(p_dev_cb, char_uuid, prop);
+            break;
+        }
+    }
+    else
+    {
+        if (char_uuid == GATT_UUID_HID_PROTO_MODE)
+            next = !bta_hh_le_set_protocol_mode(p_dev_cb, p_dev_cb->mode);
+
+    }
+
+    if (next == TRUE)
+    {
+        bta_hh_le_search_hid_chars(p_dev_cb);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_save_rpt_map
+**
+** Description      save the report map into the control block.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_le_save_rpt_map(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
+{
+    UINT8           *pp ;
+    tBTA_HH_LE_HID_SRVC *p_srvc = &p_dev_cb->hid_srvc[p_data->srvc_id.id.inst_id];
+
+    pp = p_data->p_value->unformat.p_value;
+
+    /* save report descriptor */
+    if (p_srvc->rpt_map != NULL)
+        GKI_freebuf((void*)p_srvc->rpt_map);
+
+    if (p_data->p_value->unformat.len > 0)
+        p_srvc->rpt_map = (UINT8 *)GKI_getbuf(p_data->p_value->unformat.len);
+
+    if (p_srvc->rpt_map != NULL)
+    {
+        STREAM_TO_ARRAY(p_srvc->rpt_map, pp, p_data->p_value->unformat.len);
+        p_srvc->descriptor.dl_len = p_data->p_value->unformat.len;
+        p_srvc->descriptor.dsc_list = p_dev_cb->hid_srvc[p_data->srvc_id.id.inst_id].rpt_map;
+    }
+
+    if (bta_hh_le_read_char_dscrpt(p_dev_cb,
+                                   UUID_SERVCLASS_LE_HID,
+                               p_data->srvc_id.id.inst_id,
+                               GATT_UUID_HID_REPORT_MAP,
+                               p_data->char_id.inst_id,
+                               GATT_UUID_EXT_RPT_REF_DESCR) != BTA_HH_OK)
+    {
+        bta_hh_le_search_hid_chars(p_dev_cb);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_proc_get_rpt_cmpl
+**
+** Description      Process the Read report complete, send GET_REPORT_EVT to application
+**                  with the report data.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_le_proc_get_rpt_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
+{
+    BT_HDR              *p_buf = NULL;
+    tBTA_HH_LE_RPT      *p_rpt;
+    tBTA_HH_HSDATA      hs_data;
+    UINT8               *pp ;
+
+    if (p_dev_cb->w4_evt != BTA_HH_GET_RPT_EVT)
+    {
+        APPL_TRACE_ERROR("Unexpected READ cmpl, w4_evt = %d", p_dev_cb->w4_evt);
+        return;
+    }
+
+    memset(&hs_data, 0, sizeof(hs_data));
+    hs_data.status  = BTA_HH_ERR;
+    hs_data.handle  = p_dev_cb->hid_handle;
+
+    if (p_data->status == BTA_GATT_OK)
+    {
+        p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
+                                            p_data->srvc_id.id.inst_id,//BTA_HH_LE_SRVC_DEF,
+                                            p_data->char_id.uuid.uu.uuid16,
+                                            p_data->char_id.inst_id);
+
+        if (p_rpt != NULL &&
+            p_data->p_value != NULL &&
+            (p_buf = (BT_HDR *)GKI_getbuf((UINT16)(sizeof(BT_HDR) +p_data->p_value->unformat.len + 1))) != NULL)
+        {
+            /* pack data send to app */
+            hs_data.status  = BTA_HH_OK;
+            p_buf->len = p_data->p_value->unformat.len + 1;
+            p_buf->layer_specific = 0;
+            p_buf->offset = 0;
+
+            /* attach report ID as the first byte of the report before sending it to USB HID driver */
+            pp = (UINT8*)(p_buf + 1);
+            UINT8_TO_STREAM(pp, p_rpt->rpt_id);
+            memcpy(pp, p_data->p_value->unformat.p_value, p_data->p_value->unformat.len);
+
+            hs_data.rsp_data.p_rpt_data =p_buf;
+        }
+    }
+
+    p_dev_cb->w4_evt = 0;
+    (* bta_hh_cb.p_cback)(BTA_HH_GET_RPT_EVT, (tBTA_HH *)&hs_data);
+
+    utl_freebuf((void **)&p_buf);
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_proc_read_proto_mode
+**
+** Description      Process the Read protocol mode, send GET_PROTO_EVT to application
+**                  with the protocol mode.
+**
+*******************************************************************************/
+void bta_hh_le_proc_read_proto_mode(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
+{
+    tBTA_HH_HSDATA      hs_data;
+
+    hs_data.status  = BTA_HH_ERR;
+    hs_data.handle  = p_dev_cb->hid_handle;
+    hs_data.rsp_data.proto_mode = p_dev_cb->mode;
+
+    if (p_data->status == BTA_GATT_OK && p_data->p_value)
+    {
+        hs_data.status  = BTA_HH_OK;
+        /* match up BTE/BTA report/boot mode def*/
+        hs_data.rsp_data.proto_mode = *(p_data->p_value->unformat.p_value);
+        /* LE repot mode is the opposite value of BR/EDR report mode, flip it here */
+        if (hs_data.rsp_data.proto_mode == 0)
+            hs_data.rsp_data.proto_mode = BTA_HH_PROTO_BOOT_MODE;
+        else
+            hs_data.rsp_data.proto_mode = BTA_HH_PROTO_RPT_MODE;
+
+        p_dev_cb->mode = hs_data.rsp_data.proto_mode;
+    }
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG("LE GET_PROTOCOL Mode = [%s]",
+                        (hs_data.rsp_data.proto_mode == BTA_HH_PROTO_RPT_MODE)? "Report" : "Boot");
+#endif
+
+    p_dev_cb->w4_evt = 0;
+    (* bta_hh_cb.p_cback)(BTA_HH_GET_PROTO_EVT, (tBTA_HH *)&hs_data);
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_w4_le_read_char_cmpl
+**
+** Description      process the GATT read complete in W4_CONN state.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_w4_le_read_char_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
+{
+    tBTA_GATTC_READ     * p_data = (tBTA_GATTC_READ *)p_buf;
+    UINT8               *pp ;
+
+    if (p_data->char_id.uuid.uu.uuid16 == GATT_UUID_BATTERY_LEVEL)
+    {
+        bta_hh_read_battery_level_cmpl(p_data->status, p_dev_cb, p_data);
+    }
+    else
+    {
+        if (p_data->status == BTA_GATT_OK && p_data->p_value)
+        {
+            pp = p_data->p_value->unformat.p_value;
+
+            switch (p_data->char_id.uuid.uu.uuid16)
+            {
+           /* save device information */
+            case GATT_UUID_HID_INFORMATION:
+                STREAM_TO_UINT16(p_dev_cb->dscp_info.version, pp);
+                STREAM_TO_UINT8(p_dev_cb->dscp_info.ctry_code, pp);
+                STREAM_TO_UINT8(p_dev_cb->dscp_info.flag, pp);
+                break;
+
+            case GATT_UUID_HID_REPORT_MAP:
+                bta_hh_le_save_rpt_map(p_dev_cb, p_data);
+                return;
+
+            default:
+#if BTA_HH_DEBUG == TRUE
+                APPL_TRACE_ERROR("Unexpected read %s(0x%04x)",
+                                bta_hh_uuid_to_str(p_data->char_id.uuid.uu.uuid16),
+                                p_data->char_id.uuid.uu.uuid16);
+#endif
+                break;
+            }
+        }
+        else
+        {
+#if BTA_HH_DEBUG == TRUE
+            APPL_TRACE_ERROR("read uuid %s[0x%04x] error: %d",
+                                bta_hh_uuid_to_str(p_data->char_id.uuid.uu.uuid16),
+                                p_data->char_id.uuid.uu.uuid16,
+                                p_data->status);
+#else
+            APPL_TRACE_ERROR("read uuid [0x%04x] error: %d", p_data->char_id.uuid.uu.uuid16, p_data->status);
+#endif
+        }
+        bta_hh_le_search_hid_chars(p_dev_cb);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_read_char_cmpl
+**
+** Description      a characteristic value is received.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_le_read_char_cmpl (tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
+{
+    tBTA_GATTC_READ * p_data = (tBTA_GATTC_READ *)p_buf;
+
+    switch (p_data->char_id.uuid.uu.uuid16)
+    {
+    /* GET_REPORT */
+    case GATT_UUID_HID_REPORT:
+    case GATT_UUID_HID_BT_KB_INPUT:
+    case GATT_UUID_HID_BT_KB_OUTPUT:
+    case GATT_UUID_HID_BT_MOUSE_INPUT:
+    case GATT_UUID_BATTERY_LEVEL: /* read battery level */
+        bta_hh_le_proc_get_rpt_cmpl(p_dev_cb, p_data);
+        break;
+
+    case GATT_UUID_HID_PROTO_MODE:
+        bta_hh_le_proc_read_proto_mode(p_dev_cb, p_data);
+        break;
+
+    default:
+        APPL_TRACE_ERROR("Unexpected Read UUID: 0x%04x", p_data->char_id.uuid.uu.uuid16);
+        break;
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_read_descr_cmpl
+**
+** Description      read characteristic descriptor is completed in CONN st.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_le_read_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
+{
+    tBTA_HH_LE_RPT  *p_rpt;
+    tBTA_GATTC_READ * p_data = (tBTA_GATTC_READ *)p_buf;
+    UINT8   *pp;
+
+    /* if a report client configuration */
+    if (p_data->descr_type.uuid.uu.uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG)
+    {
+        if ((p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
+                                                 BTA_HH_LE_SRVC_DEF,
+                                                 p_data->char_id.uuid.uu.uuid16,
+                                                 p_data->char_id.inst_id)) != NULL)
+        {
+            pp = p_data->p_value->unformat.p_value;
+            STREAM_TO_UINT16(p_rpt->client_cfg_value, pp);
+
+            APPL_TRACE_DEBUG("Read Client Configuration: 0x%04x", p_rpt->client_cfg_value);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_read_battery_level_descr_cmpl
+**
+** Description      Process report reference descriptor for battery level is completed
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_le_read_battery_level_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ * p_data)
+{
+    tBTA_HH_LE_RPT  *p_rpt;
+    UINT16 descr_uuid = p_data->descr_type.uuid.uu.uuid16;
+
+    /* read report reference descriptor for battery level is completed */
+    if (descr_uuid == GATT_UUID_RPT_REF_DESCR)
+    {
+        if ((p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
+                                            p_data->srvc_id.id.inst_id,
+                                            GATT_UUID_BATTERY_LEVEL,
+                                            p_data->char_id.inst_id)) == NULL)
+        {
+            bta_hh_le_search_hid_chars(p_dev_cb);
+        }
+        else
+            bta_hh_le_save_rpt_ref(p_dev_cb, p_rpt, p_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_w4_le_read_descr_cmpl
+**
+** Description      read characteristic descriptor is completed in W4_CONN st.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_w4_le_read_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
+{
+    tBTA_HH_LE_RPT  *p_rpt;
+    tBTA_GATTC_READ * p_data = (tBTA_GATTC_READ *)p_buf;
+    UINT16 char_uuid16;
+
+    if (p_data == NULL)
+        return;
+
+    char_uuid16 = p_data->char_id.uuid.uu.uuid16;
+
+#if BTA_HH_DEBUG == TRUE
+    APPL_TRACE_DEBUG("bta_hh_w4_le_read_descr_cmpl uuid: %s(0x%04x)",
+                        bta_hh_uuid_to_str(p_data->descr_type.uuid.uu.uuid16),
+                        p_data->descr_type.uuid.uu.uuid16);
+#endif
+    switch (char_uuid16)
+    {
+    case GATT_UUID_HID_REPORT:
+        if ((p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
+                                            p_data->srvc_id.id.inst_id,
+                                            GATT_UUID_HID_REPORT,
+                                            p_data->char_id.inst_id)) == NULL)
+        {
+            bta_hh_le_search_hid_chars(p_dev_cb);
+        }
+        else
+            bta_hh_le_save_rpt_ref(p_dev_cb, p_rpt, p_data);
+        break;
+
+    case GATT_UUID_HID_REPORT_MAP:
+        bta_hh_le_save_ext_rpt_ref(p_dev_cb, p_data);
+        break;
+
+    case GATT_UUID_BATTERY_LEVEL:
+        bta_hh_le_read_battery_level_descr_cmpl(p_dev_cb, p_data);
+        break;
+
+    default:
+        APPL_TRACE_ERROR("unknown descriptor read complete for uuid: 0x%04x", char_uuid16);
+        break;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_w4_le_write_cmpl
+**
+** Description      Write charactersitic complete event at W4_CONN st.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_w4_le_write_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
+{
+    tBTA_GATTC_WRITE    *p_data = (tBTA_GATTC_WRITE *)p_buf;
+
+    if (p_data == NULL)
+        return;
+
+    if (p_data->char_id.uuid.uu.uuid16 == GATT_UUID_HID_PROTO_MODE)
+    {
+        p_dev_cb->status = (p_data->status == BTA_GATT_OK) ? BTA_HH_OK : BTA_HH_ERR_PROTO;
+
+        if ((p_dev_cb->disc_active & BTA_HH_LE_DISC_HIDS) != 0)
+        {
+            bta_hh_le_search_hid_chars(p_dev_cb);
+        }
+        else
+        {
+            bta_hh_le_open_cmpl(p_dev_cb);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_write_cmpl
+**
+** Description      Write charactersitic complete event at CONN st.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_le_write_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
+{
+    tBTA_GATTC_WRITE    *p_data = (tBTA_GATTC_WRITE *)p_buf;
+    tBTA_HH_CBDATA      cback_data ;
+    UINT16              cb_evt = p_dev_cb->w4_evt;
+
+    if (p_data == NULL  || cb_evt == 0)
+        return;
+
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG("bta_hh_le_write_cmpl w4_evt: %d", p_dev_cb->w4_evt);
+#endif
+    switch (p_data->char_id.uuid.uu.uuid16)
+    {
+    /* Set protocol finished */
+    case GATT_UUID_HID_PROTO_MODE:
+        cback_data.handle  = p_dev_cb->hid_handle;
+        if (p_data->status == BTA_GATT_OK)
+        {
+            bta_hh_le_register_input_notif(p_dev_cb, p_data->srvc_id.id.inst_id, p_dev_cb->mode, FALSE);
+            cback_data.status = BTA_HH_OK;
+        }
+        else
+            cback_data.status =  BTA_HH_ERR;
+        p_dev_cb->w4_evt = 0;
+        (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data);
+        break;
+
+    /* Set Report finished */
+    case GATT_UUID_HID_REPORT:
+    case GATT_UUID_HID_BT_KB_INPUT:
+    case GATT_UUID_HID_BT_MOUSE_INPUT:
+    case GATT_UUID_HID_BT_KB_OUTPUT:
+        cback_data.handle  = p_dev_cb->hid_handle;
+        cback_data.status = (p_data->status == BTA_GATT_OK)? BTA_HH_OK : BTA_HH_ERR;
+        p_dev_cb->w4_evt = 0;
+        (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data);
+        break;
+
+    case GATT_UUID_SCAN_INT_WINDOW:
+        bta_hh_le_register_scpp_notif(p_dev_cb, p_data->status);
+        break;
+
+
+    default:
+        break;
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_write_char_descr_cmpl
+**
+** Description      Write charactersitic descriptor complete event
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_le_write_char_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
+{
+    tBTA_GATTC_WRITE    *p_data = (tBTA_GATTC_WRITE *)p_buf;
+    UINT8   srvc_inst_id, hid_inst_id;
+
+    /* only write client configuration possible */
+    if (p_data->descr_type.uuid.uu.uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG)
+    {
+        srvc_inst_id = p_data->srvc_id.id.inst_id;
+        hid_inst_id = srvc_inst_id;
+        switch (p_data->char_id.uuid.uu.uuid16)
+        {
+        case GATT_UUID_BATTERY_LEVEL: /* battery level clt cfg registered */
+            hid_inst_id = bta_hh_le_find_service_inst_by_battery_inst_id(p_dev_cb, srvc_inst_id);
+            /* fall through */
+        case GATT_UUID_HID_BT_KB_INPUT:
+        case GATT_UUID_HID_BT_MOUSE_INPUT:
+        case GATT_UUID_HID_REPORT:
+            if (p_data->status == BTA_GATT_OK)
+                p_dev_cb->hid_srvc[hid_inst_id].report[p_dev_cb->clt_cfg_idx].client_cfg_value =
+                        BTA_GATT_CLT_CONFIG_NOTIFICATION;
+            p_dev_cb->clt_cfg_idx ++;
+            bta_hh_le_write_rpt_clt_cfg(p_dev_cb, hid_inst_id);
+
+            break;
+
+        case GATT_UUID_SCAN_REFRESH:
+            bta_hh_le_register_scpp_notif_cmpl(p_dev_cb, p_data->status);
+            break;
+
+        default:
+            APPL_TRACE_ERROR("Unknown char ID clt cfg: 0x%04x", p_data->char_id.uuid.uu.uuid16);
+        }
+    }
+    else
+    {
+#if BTA_HH_DEBUG == TRUE
+            APPL_TRACE_ERROR("Unexpected write to %s(0x%04x)",
+                        bta_hh_uuid_to_str(p_data->descr_type.uuid.uu.uuid16),
+                        p_data->descr_type.uuid.uu.uuid16);
+#else
+            APPL_TRACE_ERROR("Unexpected write to (0x%04x)",
+                        p_data->descr_type.uuid.uu.uuid16);
+#endif
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_input_rpt_notify
+**
+** Description      process the notificaton event, most likely for input report.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_le_input_rpt_notify(tBTA_GATTC_NOTIFY *p_data)
+{
+    tBTA_HH_DEV_CB       *p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->conn_id);
+    UINT8           app_id;
+    UINT8           *p_buf;
+    tBTA_HH_LE_RPT  *p_rpt;
+
+    if (p_dev_cb == NULL)
+    {
+        APPL_TRACE_ERROR("notification received from Unknown device");
+        return;
+    }
+    app_id= p_dev_cb->app_id;
+
+    p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
+                                        BTA_HH_LE_SRVC_DEF,
+                                        p_data->char_id.char_id.uuid.uu.uuid16,
+                                        p_data->char_id.char_id.inst_id);
+    if (p_rpt == NULL)
+    {
+        APPL_TRACE_ERROR("notification received for Unknown Report");
+        return;
+    }
+
+    if (p_data->char_id.char_id.uuid.uu.uuid16 == GATT_UUID_HID_BT_MOUSE_INPUT)
+        app_id = BTA_HH_APP_ID_MI;
+    else if (p_data->char_id.char_id.uuid.uu.uuid16 == GATT_UUID_HID_BT_KB_INPUT)
+        app_id = BTA_HH_APP_ID_KB;
+
+    APPL_TRACE_DEBUG("Notification received on report ID: %d", p_rpt->rpt_id);
+
+    /* need to append report ID to the head of data */
+    if (p_rpt->rpt_id != 0)
+    {
+        if ((p_buf = (UINT8 *)GKI_getbuf((UINT16)(p_data->len + 1))) == NULL)
+        {
+            APPL_TRACE_ERROR("No resources to send report data");
+            return;
+        }
+
+        p_buf[0] = p_rpt->rpt_id;
+        memcpy(&p_buf[1], p_data->value, p_data->len);
+        ++p_data->len;
+    } else {
+        p_buf = p_data->value;
+    }
+
+    bta_hh_co_data((UINT8)p_dev_cb->hid_handle,
+                    p_buf,
+                    p_data->len,
+                    p_dev_cb->mode,
+                    0 , /* no sub class*/
+                    p_dev_cb->dscp_info.ctry_code,
+                    p_dev_cb->addr,
+                    app_id);
+
+    if (p_buf != p_data->value)
+        GKI_freebuf(p_buf);
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_gatt_open_fail
+**
+** Description      action function to process the open fail
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_le_open_fail(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+    tBTA_HH_CONN            conn_dat ;
+
+    /* open failure in the middle of service discovery, clear all services */
+    if (p_cb->disc_active & BTA_HH_LE_DISC_HIDS)
+    {
+        bta_hh_clear_service_cache(p_cb);
+    }
+
+    p_cb->disc_active = BTA_HH_LE_DISC_NONE;
+    /* Failure in opening connection or GATT discovery failure */
+    conn_dat.handle = p_cb->hid_handle;
+    memcpy(conn_dat.bda, p_cb->addr, BD_ADDR_LEN);
+    conn_dat.le_hid = TRUE;
+    conn_dat.scps_supported = p_cb->scps_supported;
+
+    if (p_cb->status == BTA_HH_OK)
+        conn_dat.status = (p_data->le_close.reason == BTA_GATT_CONN_UNKNOWN) ? p_cb->status : BTA_HH_ERR;
+    else
+        conn_dat.status = p_cb->status;
+
+    /* Report OPEN fail event */
+    (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_gatt_close
+**
+** Description      action function to process the GATT close int he state machine.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_gatt_close(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+    tBTA_HH_CBDATA          disc_dat = {BTA_HH_OK, 0};
+
+    /* finaliza device driver */
+    bta_hh_co_close(p_cb->hid_handle, p_cb->app_id);
+    /* update total conn number */
+    bta_hh_cb.cnt_num --;
+
+    disc_dat.handle = p_cb->hid_handle;
+    disc_dat.status = p_cb->status;
+
+    (*bta_hh_cb.p_cback)(BTA_HH_CLOSE_EVT, (tBTA_HH *)&disc_dat);
+
+    /* if no connection is active and HH disable is signaled, disable service */
+    if (bta_hh_cb.cnt_num == 0 && bta_hh_cb.w4_disable)
+    {
+        bta_hh_disc_cmpl();
+    }
+    else
+    {
+#if (BTA_HH_LE_RECONN == TRUE)
+    if (p_data->le_close.reason == BTA_GATT_CONN_TIMEOUT)
+    {
+        bta_hh_le_add_dev_bg_conn(p_cb, FALSE);
+    }
+#endif
+    }
+
+    return;
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_api_disc_act
+**
+** Description      initaite a Close API to a remote HID device
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_le_api_disc_act(tBTA_HH_DEV_CB *p_cb)
+{
+    if (p_cb->conn_id != BTA_GATT_INVALID_CONN_ID)
+    {
+        BTA_GATTC_Close(p_cb->conn_id);
+        /* remove device from background connection if intended to disconnect,
+           do not allow reconnection */
+        bta_hh_le_remove_dev_bg_conn(p_cb);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_get_rpt
+**
+** Description      GET_REPORT on a LE HID Report
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_le_get_rpt(tBTA_HH_DEV_CB *p_cb, UINT8 srvc_inst, tBTA_HH_RPT_TYPE r_type, UINT8 rpt_id)
+{
+    tBTA_HH_LE_RPT  *p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc[srvc_inst].report, p_cb->mode, r_type, rpt_id);
+    tBTA_GATTC_CHAR_ID  char_id;
+    UINT16  srvc_uuid = UUID_SERVCLASS_LE_HID;
+
+    if (p_rpt == NULL)
+    {
+        APPL_TRACE_ERROR("bta_hh_le_get_rpt: no matching report");
+        return;
+    }
+    if (p_rpt->uuid == GATT_UUID_BATTERY_LEVEL)
+        srvc_uuid = UUID_SERVCLASS_BATTERY;
+
+    p_cb->w4_evt = BTA_HH_GET_RPT_EVT;
+
+    bta_hh_le_fill_16bits_srvc_id(TRUE, srvc_inst, srvc_uuid, &char_id.srvc_id);
+    bta_hh_le_fill_16bits_char_id(p_rpt->inst_id, p_rpt->uuid, &char_id.char_id);
+
+    BTA_GATTC_ReadCharacteristic(p_cb->conn_id,
+                                 &char_id,
+                                 BTA_GATT_AUTH_REQ_NONE);
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_write_rpt
+**
+** Description      SET_REPORT/or DATA output on a LE HID Report
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_le_write_rpt(tBTA_HH_DEV_CB *p_cb, UINT8 srvc_inst,
+                         tBTA_GATTC_WRITE_TYPE   write_type,
+                         tBTA_HH_RPT_TYPE r_type,
+                         BT_HDR *p_buf, UINT16 w4_evt )
+{
+    tBTA_HH_LE_RPT  *p_rpt;
+    tBTA_GATTC_CHAR_ID  char_id;
+    UINT8   *p_value, rpt_id;
+
+    if (p_buf == NULL || p_buf->len == 0)
+    {
+        APPL_TRACE_ERROR("bta_hh_le_write_rpt: Illegal data");
+        return;
+    }
+
+    /* strip report ID from the data */
+    p_value = (UINT8 *)(p_buf + 1) + p_buf->offset;
+    STREAM_TO_UINT8(rpt_id, p_value);
+    p_buf->len -= 1;
+
+    p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc[srvc_inst].report, p_cb->mode, r_type, rpt_id);
+
+    if (p_rpt == NULL)
+    {
+        APPL_TRACE_ERROR("bta_hh_le_write_rpt: no matching report");
+        GKI_freebuf(p_buf);
+        return;
+    }
+
+    APPL_TRACE_ERROR("bta_hh_le_write_rpt: ReportID: 0x%02x Data Len: %d", rpt_id, p_buf->len);
+
+    p_cb->w4_evt = w4_evt;
+
+    bta_hh_le_fill_16bits_srvc_id(TRUE, srvc_inst, UUID_SERVCLASS_LE_HID, &char_id.srvc_id);
+    bta_hh_le_fill_16bits_char_id(p_rpt->inst_id, p_rpt->uuid, &char_id.char_id);
+
+    BTA_GATTC_WriteCharValue(p_cb->conn_id,
+                             &char_id,
+                             write_type, /* default to use write request */
+                             p_buf->len,
+                             p_value,
+                             BTA_GATT_AUTH_REQ_NONE);
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_suspend
+**
+** Description      send LE suspend or exit suspend mode to remote device.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_le_suspend(tBTA_HH_DEV_CB *p_cb, tBTA_HH_TRANS_CTRL_TYPE ctrl_type)
+{
+    UINT8 i;
+    tBTA_GATTC_CHAR_ID  char_id;
+
+    ctrl_type -= BTA_HH_CTRL_SUSPEND;
+
+    for (i = 0; i < BTA_HH_LE_HID_SRVC_MAX; i ++)
+    {
+        bta_hh_le_fill_16bits_srvc_id(TRUE, i, UUID_SERVCLASS_LE_HID, &char_id.srvc_id);
+        bta_hh_le_fill_16bits_char_id(0, GATT_UUID_HID_CONTROL_POINT, &char_id.char_id);
+
+        BTA_GATTC_WriteCharValue(p_cb->conn_id,
+                                 &char_id,
+                                 BTA_GATTC_TYPE_WRITE_NO_RSP, /* default to use write request */
+                                 1,
+                                 &ctrl_type,
+                                 BTA_GATT_AUTH_REQ_NONE);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_write_dev_act
+**
+** Description      Write LE device action. can be SET/GET/DATA transaction.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_le_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+    switch(p_data->api_sndcmd.t_type)
+    {
+        case HID_TRANS_SET_PROTOCOL:
+            p_cb->w4_evt = BTA_HH_SET_PROTO_EVT;
+            bta_hh_le_set_protocol_mode(p_cb, p_data->api_sndcmd.param);
+            break;
+
+        case HID_TRANS_GET_PROTOCOL:
+            bta_hh_le_get_protocol_mode(p_cb);
+            break;
+
+        case HID_TRANS_GET_REPORT:
+            bta_hh_le_get_rpt(p_cb,
+                              BTA_HH_LE_SRVC_DEF,
+                              p_data->api_sndcmd.param,
+                              p_data->api_sndcmd.rpt_id);
+            break;
+
+        case HID_TRANS_SET_REPORT:
+            bta_hh_le_write_rpt(p_cb,
+                                BTA_HH_LE_SRVC_DEF,
+                                BTA_GATTC_TYPE_WRITE,
+                                p_data->api_sndcmd.param,
+                                p_data->api_sndcmd.p_data,
+                                BTA_HH_SET_RPT_EVT);
+            break;
+
+        case HID_TRANS_DATA:  /* output report */
+
+            bta_hh_le_write_rpt(p_cb,
+                                BTA_HH_LE_SRVC_DEF,
+                                BTA_GATTC_TYPE_WRITE_NO_RSP,
+                                p_data->api_sndcmd.param,
+                                p_data->api_sndcmd.p_data,
+                                BTA_HH_DATA_EVT);
+            break;
+
+        case HID_TRANS_CONTROL:
+            /* no handshake event will be generated */
+            /* if VC_UNPLUG is issued, set flag */
+            if (p_data->api_sndcmd.param == BTA_HH_CTRL_SUSPEND ||
+                p_data->api_sndcmd.param == BTA_HH_CTRL_EXIT_SUSPEND)
+            {
+                bta_hh_le_suspend(p_cb, p_data->api_sndcmd.param);
+            }
+            break;
+
+        default:
+            APPL_TRACE_ERROR("%s unsupported transaction for BLE HID device: %d",
+                __func__, p_data->api_sndcmd.t_type);
+            break;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_get_dscp_act
+**
+** Description      Send ReportDescriptor to application for all HID services.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_le_get_dscp_act(tBTA_HH_DEV_CB *p_cb)
+{
+    UINT8 i;
+
+    for (i = 0 ;i < BTA_HH_LE_HID_SRVC_MAX; i ++)
+    {
+        if (p_cb->hid_srvc[i].in_use)
+        {
+            p_cb->dscp_info.descriptor.dl_len = p_cb->hid_srvc[i].descriptor.dl_len;
+            p_cb->dscp_info.descriptor.dsc_list = p_cb->hid_srvc[i].descriptor.dsc_list;
+
+            (*bta_hh_cb.p_cback)(BTA_HH_GET_DSCP_EVT, (tBTA_HH *)&p_cb->dscp_info);
+        }
+        else
+            break;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_add_dev_bg_conn
+**
+** Description      Remove a LE HID device from back ground connection procedure.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hh_le_add_dev_bg_conn(tBTA_HH_DEV_CB *p_cb, BOOLEAN check_bond)
+{
+    UINT8           sec_flag=0;
+    BOOLEAN         to_add = TRUE;
+
+    if (check_bond)
+    {
+        /* start reconnection if remote is a bonded device */
+        /* verify bond */
+        BTM_GetSecurityFlagsByTransport(p_cb->addr, &sec_flag, BT_TRANSPORT_LE);
+
+        if ((sec_flag & BTM_SEC_FLAG_LKEY_KNOWN) == 0)
+            to_add = FALSE;
+    }
+
+    if (/*p_cb->dscp_info.flag & BTA_HH_LE_NORMAL_CONN &&*/
+        !p_cb->in_bg_conn && to_add)
+    {
+        /* add device into BG connection to accept remote initiated connection */
+        BTA_GATTC_Open(bta_hh_cb.gatt_if, p_cb->addr, FALSE, BTA_GATT_TRANSPORT_LE);
+        p_cb->in_bg_conn = TRUE;
+
+        BTA_DmBleSetBgConnType(BTA_DM_BLE_CONN_AUTO, NULL);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_add_device
+**
+** Description      Add a LE HID device as a known device, and also add the address
+**                  into back ground connection WL for incoming connection.
+**
+** Returns          void
+**
+*******************************************************************************/
+UINT8 bta_hh_le_add_device(tBTA_HH_DEV_CB *p_cb, tBTA_HH_MAINT_DEV *p_dev_info)
+{
+    p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
+    bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
+
+    /* update DI information */
+    bta_hh_update_di_info(p_cb,
+                          p_dev_info->dscp_info.vendor_id,
+                          p_dev_info->dscp_info.product_id,
+                          p_dev_info->dscp_info.version,
+                          p_dev_info->dscp_info.flag);
+
+    /* add to BTA device list */
+    bta_hh_add_device_to_list(p_cb, p_cb->hid_handle,
+                              p_dev_info->attr_mask,
+                              &p_dev_info->dscp_info.descriptor,
+                              p_dev_info->sub_class,
+                              p_dev_info->dscp_info.ssr_max_latency,
+                              p_dev_info->dscp_info.ssr_min_tout,
+                              p_dev_info->app_id);
+
+    bta_hh_le_add_dev_bg_conn(p_cb, FALSE);
+
+    return p_cb->hid_handle;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_remove_dev_bg_conn
+**
+** Description      Remove a LE HID device from back ground connection procedure.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_le_remove_dev_bg_conn(tBTA_HH_DEV_CB *p_dev_cb)
+{
+    if (p_dev_cb->in_bg_conn)
+    {
+        p_dev_cb->in_bg_conn = FALSE;
+
+        BTA_GATTC_CancelOpen(bta_hh_cb.gatt_if, p_dev_cb->addr, FALSE);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_update_scpp
+**
+** Description      action function to update the scan parameters on remote HID
+**                  device
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_hh_le_update_scpp(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
+{
+    tBTA_GATTC_CHAR_ID  char_id;
+    UINT8   value[4], *p = value;
+    tBTA_HH_CBDATA      cback_data ;
+
+    if (!p_dev_cb->is_le_device ||
+        p_dev_cb->mode != BTA_HH_PROTO_RPT_MODE ||
+        p_dev_cb->scps_supported == FALSE)
+    {
+        APPL_TRACE_ERROR("Can not set ScPP scan paramter as boot host, or remote does not support ScPP ");
+
+        cback_data.handle = p_dev_cb->hid_handle;
+        cback_data.status = BTA_HH_ERR;
+        (* bta_hh_cb.p_cback)(BTA_HH_UPDATE_SCPP_EVT, (tBTA_HH *)&cback_data);
+
+        return;
+    }
+
+    p_dev_cb->w4_evt = BTA_HH_UPDATE_SCPP_EVT;
+
+    UINT16_TO_STREAM(p, p_buf->le_scpp_update.scan_int);
+    UINT16_TO_STREAM(p, p_buf->le_scpp_update.scan_win);
+
+    bta_hh_le_fill_16bits_srvc_id(TRUE, BTA_HH_SCPP_INST_DEF, UUID_SERVCLASS_SCAN_PARAM, &char_id.srvc_id);
+    bta_hh_le_fill_16bits_char_id(BTA_HH_SCPP_INST_DEF, GATT_UUID_SCAN_INT_WINDOW, &char_id.char_id);
+
+    BTA_GATTC_WriteCharValue(p_dev_cb->conn_id,
+                             &char_id,
+                             BTA_GATTC_TYPE_WRITE_NO_RSP,
+                             2,
+                             value,
+                             BTA_GATT_AUTH_REQ_NONE);
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_gattc_callback
+**
+** Description      This is GATT client callback function used in BTA HH.
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_hh_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
+{
+    tBTA_HH_DEV_CB *p_dev_cb;
+    UINT16          evt;
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG("bta_hh_gattc_callback event = %d", event);
+#endif
+    if (p_data == NULL)
+        return;
+
+    switch (event)
+    {
+        case BTA_GATTC_REG_EVT: /* 0 */
+            bta_hh_le_register_cmpl(&p_data->reg_oper);
+            break;
+
+        case BTA_GATTC_DEREG_EVT: /* 1 */
+            bta_hh_cleanup_disable(p_data->reg_oper.status);
+            break;
+
+        case BTA_GATTC_OPEN_EVT: /* 2 */
+            p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->open.remote_bda);
+            if (p_dev_cb) {
+                bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_OPEN_EVT, (tBTA_HH_DATA *)&p_data->open);
+            }
+            break;
+
+        case BTA_GATTC_READ_CHAR_EVT: /* 3 */
+        case BTA_GATTC_READ_DESCR_EVT: /* 8 */
+            p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->read.conn_id);
+            if (event == BTA_GATTC_READ_CHAR_EVT)
+                evt = BTA_HH_GATT_READ_CHAR_CMPL_EVT;
+            else
+                evt = BTA_HH_GATT_READ_DESCR_CMPL_EVT;
+
+            bta_hh_sm_execute(p_dev_cb, evt, (tBTA_HH_DATA *)&p_data->read);
+            break;
+
+        case BTA_GATTC_WRITE_DESCR_EVT: /* 9 */
+        case BTA_GATTC_WRITE_CHAR_EVT: /* 4 */
+            p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->write.conn_id);
+            if (event == BTA_GATTC_WRITE_CHAR_EVT)
+                evt = BTA_HH_GATT_WRITE_CHAR_CMPL_EVT;
+            else
+                evt = BTA_HH_GATT_WRITE_DESCR_CMPL_EVT;
+
+            bta_hh_sm_execute(p_dev_cb, evt, (tBTA_HH_DATA *)&p_data->write);
+            break;
+
+        case BTA_GATTC_CLOSE_EVT: /* 5 */
+            bta_hh_le_close(&p_data->close);
+            break;
+
+        case BTA_GATTC_SEARCH_CMPL_EVT: /* 6 */
+            bta_hh_le_srvc_search_cmpl(&p_data->search_cmpl);
+            break;
+
+        case BTA_GATTC_SEARCH_RES_EVT: /* 7 */
+            bta_hh_le_search_result(&p_data->srvc_res);
+            break;
+
+
+
+        case BTA_GATTC_NOTIF_EVT: /* 10 */
+            bta_hh_le_input_rpt_notify(&p_data->notify);
+            break;
+
+        case BTA_GATTC_ENC_CMPL_CB_EVT: /* 17 */
+            p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->enc_cmpl.remote_bda);
+            if (p_dev_cb) {
+                bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_ENC_CMPL_EVT,
+                              (tBTA_HH_DATA *)&p_data->enc_cmpl);
+            }
+            break;
+
+        default:
+            break;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_hid_read_rpt_clt_cfg
+**
+** Description      a test command to read report descriptor client configuration
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_le_hid_read_rpt_clt_cfg(BD_ADDR bd_addr, UINT8 rpt_id)
+{
+    tBTA_HH_DEV_CB *p_cb = NULL;
+    tBTA_HH_LE_RPT *p_rpt ;
+    UINT8           index = BTA_HH_IDX_INVALID;
+
+    index = bta_hh_find_cb(bd_addr);
+    if ((index = bta_hh_find_cb(bd_addr))== BTA_HH_IDX_INVALID)
+    {
+        APPL_TRACE_ERROR("unknown device");
+        return;
+    }
+
+    p_cb = &bta_hh_cb.kdev[index];
+
+    p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc[BTA_HH_LE_SRVC_DEF].report, p_cb->mode, BTA_HH_RPTT_INPUT, rpt_id);
+
+    if (p_rpt == NULL)
+    {
+        APPL_TRACE_ERROR("bta_hh_le_write_rpt: no matching report");
+        return;
+    }
+
+    bta_hh_le_read_char_dscrpt(p_cb,
+                               UUID_SERVCLASS_LE_HID,
+                               BTA_HH_LE_SRVC_DEF,
+                               p_rpt->uuid,
+                               p_rpt->inst_id,
+                               GATT_UUID_CHAR_CLIENT_CONFIG);
+
+
+
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_search_scps
+**
+** Description      discovery scan parameter service if act as report host, otherwise
+**                  finish LE connection.
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_hh_le_search_scps(tBTA_HH_DEV_CB *p_cb)
+{
+    tBT_UUID        pri_srvc;
+
+    if ( p_cb->mode == BTA_HH_PROTO_RPT_MODE)
+    {
+        p_cb->disc_active  |= BTA_HH_LE_DISC_SCPS;
+        /* start  service discovery for Scan Parameter service */
+        pri_srvc.len        = LEN_UUID_16;
+        pri_srvc.uu.uuid16  = UUID_SERVCLASS_SCAN_PARAM;
+
+        BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, &pri_srvc);
+    }
+    else
+        bta_hh_le_open_cmpl(p_cb);
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_search_scps_chars
+**
+** Description      find ScPS optional characteristics scan refresh
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_hh_le_search_scps_chars(tBTA_HH_DEV_CB *p_cb)
+{
+    tBTA_GATT_SRVC_ID   srvc_id;
+    tBT_UUID            char_cond;
+    tBTA_GATTC_CHAR_ID  char_result;
+    tBTA_GATT_CHAR_PROP prop;
+
+    p_cb->scps_supported = TRUE;
+    bta_hh_le_fill_16bits_srvc_id(TRUE, 0, UUID_SERVCLASS_SCAN_PARAM, &srvc_id);
+
+    char_cond.len   = LEN_UUID_16;
+    char_cond.uu.uuid16 = GATT_UUID_SCAN_REFRESH;
+
+    /* look for scan refresh */
+    if (BTA_GATTC_GetFirstChar( p_cb->conn_id,
+                                &srvc_id,
+                                &char_cond,
+                                &char_result,
+                                &prop) == BTA_GATT_OK)
+    {
+        if (prop & BTA_GATT_CHAR_PROP_BIT_NOTIFY)
+            p_cb->scps_notify |= BTA_HH_LE_SCPS_NOTIFY_SPT;
+        else
+            p_cb->scps_notify = BTA_HH_LE_SCPS_NOTIFY_NONE;
+
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_register_scpp_notif
+**
+** Description      register scan parameter refresh notitication complete
+**
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_hh_le_register_scpp_notif(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_STATUS status)
+{
+    UINT8               sec_flag=0;
+    tBTA_GATTC_CHAR_ID  char_id;
+
+    /* if write scan parameter sucessful */
+    /* if bonded and notification is not enabled, configure the client configuration */
+    if (status == BTA_GATT_OK &&
+        (p_dev_cb->scps_notify & BTA_HH_LE_SCPS_NOTIFY_SPT) != 0 &&
+        (p_dev_cb->scps_notify & BTA_HH_LE_SCPS_NOTIFY_ENB) == 0)
+    {
+        BTM_GetSecurityFlagsByTransport(p_dev_cb->addr, &sec_flag, BT_TRANSPORT_LE);
+        if ((sec_flag & BTM_SEC_FLAG_LKEY_KNOWN))
+        {
+            if (bta_hh_le_write_char_clt_cfg (p_dev_cb,
+                                              BTA_HH_SCPP_INST_DEF,
+                                              UUID_SERVCLASS_SCAN_PARAM,
+                                              BTA_HH_SCPP_INST_DEF,
+                                              GATT_UUID_SCAN_REFRESH,
+                                              BTA_GATT_CLT_CONFIG_NOTIFICATION))
+            {
+                bta_hh_le_fill_16bits_srvc_id(TRUE, BTA_HH_SCPP_INST_DEF, UUID_SERVCLASS_SCAN_PARAM, &char_id.srvc_id);
+                bta_hh_le_fill_16bits_char_id(BTA_HH_SCPP_INST_DEF, GATT_UUID_SCAN_REFRESH, &char_id.char_id);
+
+                BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if,
+                                                   p_dev_cb->addr,
+                                                   &char_id);
+                return;
+            }
+        }
+    }
+    bta_hh_le_register_scpp_notif_cmpl(p_dev_cb, status);
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_register_scpp_notif_cmpl
+**
+** Description      action function to register scan parameter refresh notitication
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_hh_le_register_scpp_notif_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_STATUS status)
+{
+    tBTA_HH_CBDATA      cback_data ;
+    UINT16              cb_evt = p_dev_cb->w4_evt;
+
+    if (status == BTA_GATT_OK)
+        p_dev_cb->scps_notify = (BTA_HH_LE_SCPS_NOTIFY_ENB | BTA_HH_LE_SCPS_NOTIFY_SPT);
+
+    cback_data.handle  = p_dev_cb->hid_handle;
+    cback_data.status = (status == BTA_GATT_OK)? BTA_HH_OK : BTA_HH_ERR;
+    p_dev_cb->w4_evt = 0;
+    (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data);
+
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_process_cache_rpt
+**
+** Description      Process the cached reports
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_hh_process_cache_rpt (tBTA_HH_DEV_CB *p_cb,
+                                      tBTA_HH_RPT_CACHE_ENTRY *p_rpt_cache,
+                                      UINT8 num_rpt)
+{
+    UINT8                       i = 0;
+    tBTA_HH_LE_RPT              *p_rpt;
+
+    if (num_rpt != 0)  /* no cache is found */
+    {
+        p_cb->hid_srvc[BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt_cache->inst_id)].in_use = TRUE;
+
+        /* set the descriptor info */
+        p_cb->hid_srvc[BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt_cache->inst_id)].descriptor.dl_len =
+                p_cb->dscp_info.descriptor.dl_len;
+        p_cb->hid_srvc[BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt_cache->inst_id)].descriptor.dsc_list =
+                    p_cb->dscp_info.descriptor.dsc_list;
+
+        for (; i <num_rpt; i ++, p_rpt_cache ++)
+        {
+            if ((p_rpt = bta_hh_le_find_alloc_report_entry (p_cb,
+                                               BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt_cache->inst_id),
+                                               p_rpt_cache->rpt_uuid,
+                                               BTA_HH_LE_RPT_GET_RPT_INST_ID(p_rpt_cache->inst_id),
+                                               p_rpt_cache->prop))  == NULL)
+            {
+                APPL_TRACE_ERROR("bta_hh_process_cache_rpt: allocation report entry failure");
+                break;
+            }
+            else
+            {
+                p_rpt->rpt_type =  p_rpt_cache->rpt_type;
+                p_rpt->rpt_id   =  p_rpt_cache->rpt_id;
+
+                if(p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
+                    p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT ||
+                    (p_rpt->uuid == GATT_UUID_HID_REPORT && p_rpt->rpt_type == BTA_HH_RPTT_INPUT))
+                {
+                    p_rpt->client_cfg_value = BTA_GATT_CLT_CONFIG_NOTIFICATION;
+                }
+            }
+        }
+    }
+}
+
+#endif
+
+
+
+

+ 593 - 0
components/bt/bluedroid/bta/hh/bta_hh_main.c

@@ -0,0 +1,593 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2005-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This file contains the HID host main functions and state machine.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
+
+#include <string.h>
+
+#include "bta_hh_api.h"
+#include "bta_hh_int.h"
+#include "gki.h"
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+/* state machine action enumeration list */
+enum
+{
+    BTA_HH_API_DISC_ACT,        /* HID host process API close action    */
+    BTA_HH_OPEN_ACT,            /* HID host process BTA_HH_EVT_OPEN     */
+    BTA_HH_CLOSE_ACT,           /* HID host process BTA_HH_EVT_CLOSE    */
+    BTA_HH_DATA_ACT,            /* HID host receive data report         */
+    BTA_HH_CTRL_DAT_ACT,
+    BTA_HH_HANDSK_ACT,
+    BTA_HH_START_SDP,           /* HID host inquery                     */
+    BTA_HH_SDP_CMPL,
+    BTA_HH_WRITE_DEV_ACT,
+    BTA_HH_GET_DSCP_ACT,
+    BTA_HH_MAINT_DEV_ACT,
+    BTA_HH_OPEN_CMPL_ACT,
+    BTA_HH_OPEN_FAILURE,
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+    BTA_HH_GATT_CLOSE,
+    BTA_HH_LE_OPEN_FAIL,
+    BTA_HH_GATT_OPEN,
+    BTA_HH_W4_LE_READ_CHAR,
+    BTA_HH_LE_READ_CHAR,
+    BTA_HH_W4_LE_READ_DESCR,
+    BTA_HH_LE_READ_DESCR,
+    BTA_HH_W4_LE_WRITE,
+    BTA_HH_LE_WRITE,
+    BTA_HH_WRITE_DESCR,
+    BTA_HH_START_SEC,
+    BTA_HH_SEC_CMPL,
+    BTA_HH_LE_UPDATE_SCPP,
+    BTA_HH_GATT_ENC_CMPL,
+#endif
+    BTA_HH_NUM_ACTIONS
+};
+
+#define BTA_HH_IGNORE       BTA_HH_NUM_ACTIONS
+
+/* type for action functions */
+typedef void (*tBTA_HH_ACTION)(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+
+/* action functions */
+const tBTA_HH_ACTION bta_hh_action[] =
+{
+    bta_hh_api_disc_act,
+    bta_hh_open_act,
+    bta_hh_close_act,
+    bta_hh_data_act,
+    bta_hh_ctrl_dat_act,
+    bta_hh_handsk_act,
+    bta_hh_start_sdp,
+    bta_hh_sdp_cmpl,
+    bta_hh_write_dev_act,
+    bta_hh_get_dscp_act,
+    bta_hh_maint_dev_act,
+    bta_hh_open_cmpl_act,
+    bta_hh_open_failure
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+    ,bta_hh_gatt_close
+    ,bta_hh_le_open_fail
+    ,bta_hh_gatt_open
+    ,bta_hh_w4_le_read_char_cmpl
+    ,bta_hh_le_read_char_cmpl
+    ,bta_hh_w4_le_read_descr_cmpl
+    ,bta_hh_le_read_descr_cmpl
+    ,bta_hh_w4_le_write_cmpl
+    ,bta_hh_le_write_cmpl
+    ,bta_hh_le_write_char_descr_cmpl
+    ,bta_hh_start_security
+    ,bta_hh_security_cmpl
+    ,bta_hh_le_update_scpp
+    ,bta_hh_le_notify_enc_cmpl
+#endif
+};
+
+/* state table information */
+#define BTA_HH_ACTION                   0       /* position of action */
+#define BTA_HH_NEXT_STATE               1       /* position of next state */
+#define BTA_HH_NUM_COLS                 2       /* number of columns */
+
+/* state table for idle state */
+const UINT8 bta_hh_st_idle[][BTA_HH_NUM_COLS] =
+{
+/* Event                          Action                    Next state */
+/* BTA_HH_API_OPEN_EVT      */    {BTA_HH_START_SDP,     BTA_HH_W4_CONN_ST },
+/* BTA_HH_API_CLOSE_EVT     */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
+/* BTA_HH_INT_OPEN_EVT      */    {BTA_HH_OPEN_ACT,      BTA_HH_W4_CONN_ST },
+/* BTA_HH_INT_CLOSE_EVT     */    {BTA_HH_CLOSE_ACT,     BTA_HH_IDLE_ST    },
+/* BTA_HH_INT_DATA_EVT      */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
+/* BTA_HH_INT_CTRL_DATA     */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
+/* BTA_HH_INT_HANDSK_EVT    */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
+/* BTA_HH_SDP_CMPL_EVT      */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
+/* BTA_HH_API_WRITE_DEV_EVT */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
+/* BTA_HH_API_GET_DSCP_EVT  */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
+/* BTA_HH_API_MAINT_DEV_EVT */    {BTA_HH_MAINT_DEV_ACT, BTA_HH_IDLE_ST    },
+/* BTA_HH_OPEN_CMPL_EVT        */  {BTA_HH_OPEN_CMPL_ACT, BTA_HH_CONN_ST    }
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+/* BTA_HH_GATT_CLOSE_EVT    */   ,{BTA_HH_IGNORE,         BTA_HH_IDLE_ST    }
+/* BTA_HH_GATT_OPEN_EVT    */    ,{BTA_HH_GATT_OPEN,      BTA_HH_W4_CONN_ST }
+/* BTA_HH_START_ENC_EVT    */    ,{BTA_HH_IGNORE,         BTA_HH_IDLE_ST    }
+/* BTA_HH_ENC_CMPL_EVT     */    ,{BTA_HH_IGNORE,         BTA_HH_IDLE_ST    }
+/* READ_CHAR_CMPL_EVT */         ,{BTA_HH_IGNORE,       BTA_HH_IDLE_ST  }
+/* BTA_HH_GATT_WRITE_CMPL_EVT*/    ,{BTA_HH_IGNORE,       BTA_HH_IDLE_ST  }
+/* READ_DESCR_CMPL_EVT */        ,{BTA_HH_IGNORE,           BTA_HH_IDLE_ST  }
+/* WRITE_DESCR_CMPL_EVT */       ,{BTA_HH_IGNORE,           BTA_HH_IDLE_ST   }
+/* SCPP_UPDATE_EVT */            ,{BTA_HH_IGNORE,           BTA_HH_IDLE_ST   }
+/* BTA_HH_GATT_ENC_CMPL_EVT */   ,{BTA_HH_IGNORE,           BTA_HH_IDLE_ST   }
+#endif
+
+};
+
+
+const UINT8 bta_hh_st_w4_conn[][BTA_HH_NUM_COLS] =
+{
+/* Event                          Action                 Next state */
+/* BTA_HH_API_OPEN_EVT      */    {BTA_HH_IGNORE,        BTA_HH_W4_CONN_ST },
+/* BTA_HH_API_CLOSE_EVT     */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
+/* BTA_HH_INT_OPEN_EVT      */    {BTA_HH_OPEN_ACT,      BTA_HH_W4_CONN_ST },
+/* BTA_HH_INT_CLOSE_EVT     */    {BTA_HH_OPEN_FAILURE,  BTA_HH_IDLE_ST    },
+/* BTA_HH_INT_DATA_EVT      */    {BTA_HH_IGNORE,        BTA_HH_W4_CONN_ST },
+/* BTA_HH_INT_CTRL_DATA     */    {BTA_HH_IGNORE,        BTA_HH_W4_CONN_ST },
+/* BTA_HH_INT_HANDSK_EVT    */    {BTA_HH_IGNORE,        BTA_HH_W4_CONN_ST },
+/* BTA_HH_SDP_CMPL_EVT      */    {BTA_HH_SDP_CMPL,      BTA_HH_W4_CONN_ST },
+/* BTA_HH_API_WRITE_DEV_EVT */    {BTA_HH_WRITE_DEV_ACT, BTA_HH_W4_CONN_ST },
+/* BTA_HH_API_GET_DSCP_EVT  */    {BTA_HH_IGNORE,        BTA_HH_W4_CONN_ST },
+/* BTA_HH_API_MAINT_DEV_EVT */    {BTA_HH_MAINT_DEV_ACT, BTA_HH_IDLE_ST    },
+/* BTA_HH_OPEN_CMPL_EVT     */    {BTA_HH_OPEN_CMPL_ACT, BTA_HH_CONN_ST    }
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+/* BTA_HH_GATT_CLOSE_EVT    */   ,{BTA_HH_LE_OPEN_FAIL,  BTA_HH_IDLE_ST    }
+/* BTA_HH_GATT_OPEN_EVT    */    ,{BTA_HH_GATT_OPEN,     BTA_HH_W4_CONN_ST }
+/* BTA_HH_START_ENC_EVT    */    ,{BTA_HH_START_SEC,     BTA_HH_W4_SEC     }
+/* BTA_HH_ENC_CMPL_EVT     */    ,{BTA_HH_IGNORE,        BTA_HH_W4_CONN_ST }
+/* READ_CHAR_CMPL_EVT */        ,{BTA_HH_W4_LE_READ_CHAR,    BTA_HH_W4_CONN_ST  }
+/* BTA_HH_GATT_WRITE_CMPL_EVT*/  ,{BTA_HH_W4_LE_WRITE,    BTA_HH_W4_CONN_ST  }
+/* READ_DESCR_CMPL_EVT */        ,{BTA_HH_W4_LE_READ_DESCR, BTA_HH_W4_CONN_ST  }
+/* WRITE_DESCR_CMPL_EVT */       ,{BTA_HH_WRITE_DESCR,   BTA_HH_W4_CONN_ST   }
+/* SCPP_UPDATE_EVT */            ,{BTA_HH_IGNORE,           BTA_HH_W4_CONN_ST   }
+/* BTA_HH_GATT_ENC_CMPL_EVT */   ,{BTA_HH_IGNORE,        BTA_HH_W4_CONN_ST }
+#endif
+};
+
+
+const UINT8 bta_hh_st_connected[][BTA_HH_NUM_COLS] =
+{
+/* Event                          Action                 Next state */
+/* BTA_HH_API_OPEN_EVT      */    {BTA_HH_IGNORE,        BTA_HH_CONN_ST    },
+/* BTA_HH_API_CLOSE_EVT     */    {BTA_HH_API_DISC_ACT,  BTA_HH_CONN_ST    },
+/* BTA_HH_INT_OPEN_EVT      */    {BTA_HH_OPEN_ACT,      BTA_HH_CONN_ST    },
+/* BTA_HH_INT_CLOSE_EVT     */    {BTA_HH_CLOSE_ACT,     BTA_HH_IDLE_ST    },
+/* BTA_HH_INT_DATA_EVT      */    {BTA_HH_DATA_ACT,      BTA_HH_CONN_ST    },
+/* BTA_HH_INT_CTRL_DATA     */    {BTA_HH_CTRL_DAT_ACT,  BTA_HH_CONN_ST    },
+/* BTA_HH_INT_HANDSK_EVT    */    {BTA_HH_HANDSK_ACT,    BTA_HH_CONN_ST    },
+/* BTA_HH_SDP_CMPL_EVT      */    {BTA_HH_IGNORE,         BTA_HH_CONN_ST       },
+/* BTA_HH_API_WRITE_DEV_EVT */    {BTA_HH_WRITE_DEV_ACT, BTA_HH_CONN_ST    },
+/* BTA_HH_API_GET_DSCP_EVT  */    {BTA_HH_GET_DSCP_ACT,  BTA_HH_CONN_ST    },
+/* BTA_HH_API_MAINT_DEV_EVT */    {BTA_HH_MAINT_DEV_ACT, BTA_HH_CONN_ST    },
+/* BTA_HH_OPEN_CMPL_EVT        */    {BTA_HH_IGNORE,         BTA_HH_CONN_ST    }
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+/* BTA_HH_GATT_CLOSE_EVT    */    ,{BTA_HH_GATT_CLOSE,    BTA_HH_IDLE_ST    }
+/* BTA_HH_GATT_OPEN_EVT    */    ,{BTA_HH_IGNORE,        BTA_HH_CONN_ST    }
+/* BTA_HH_START_ENC_EVT    */    ,{BTA_HH_IGNORE,        BTA_HH_CONN_ST     }
+/* BTA_HH_ENC_CMPL_EVT     */    ,{BTA_HH_IGNORE,        BTA_HH_CONN_ST     }
+/* READ_CHAR_CMPL_EVT */         ,{BTA_HH_LE_READ_CHAR,  BTA_HH_CONN_ST     }
+/* WRITE_CHAR_CMPL_EVT*/         ,{BTA_HH_LE_WRITE,      BTA_HH_CONN_ST     }
+/* READ_DESCR_CMPL_EVT */        ,{BTA_HH_LE_READ_DESCR, BTA_HH_CONN_ST     }   /* do not currently read any descr when connection up */
+/* WRITE_DESCR_CMPL_EVT */       ,{BTA_HH_WRITE_DESCR,   BTA_HH_CONN_ST     }   /* do not currently write any descr when connection up */
+/* SCPP_UPDATE_EVT */            ,{BTA_HH_LE_UPDATE_SCPP,  BTA_HH_CONN_ST   }
+/* BTA_HH_GATT_ENC_CMPL_EVT */   ,{BTA_HH_IGNORE,        BTA_HH_CONN_ST     }
+#endif
+};
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+const UINT8 bta_hh_st_w4_sec[][BTA_HH_NUM_COLS] =
+{
+/* Event                          Action                 Next state */
+/* BTA_HH_API_OPEN_EVT      */    {BTA_HH_IGNORE,        BTA_HH_W4_SEC  },
+/* BTA_HH_API_CLOSE_EVT     */    {BTA_HH_API_DISC_ACT,  BTA_HH_W4_SEC  },
+/* BTA_HH_INT_OPEN_EVT      */    {BTA_HH_IGNORE,        BTA_HH_W4_SEC  },
+/* BTA_HH_INT_CLOSE_EVT     */    {BTA_HH_OPEN_FAILURE,  BTA_HH_IDLE_ST },
+/* BTA_HH_INT_DATA_EVT      */    {BTA_HH_IGNORE,        BTA_HH_W4_SEC  },
+/* BTA_HH_INT_CTRL_DATA     */    {BTA_HH_IGNORE,        BTA_HH_W4_SEC  },
+/* BTA_HH_INT_HANDSK_EVT    */    {BTA_HH_IGNORE,        BTA_HH_W4_SEC  },
+/* BTA_HH_SDP_CMPL_EVT      */    {BTA_HH_IGNORE,        BTA_HH_W4_SEC  },
+/* BTA_HH_API_WRITE_DEV_EVT */    {BTA_HH_IGNORE  ,      BTA_HH_W4_SEC  },
+/* BTA_HH_API_GET_DSCP_EVT  */    {BTA_HH_IGNORE,        BTA_HH_W4_SEC  },
+/* BTA_HH_API_MAINT_DEV_EVT */    {BTA_HH_MAINT_DEV_ACT, BTA_HH_W4_SEC  },
+/* BTA_HH_OPEN_CMPL_EVT     */    {BTA_HH_IGNORE,        BTA_HH_W4_SEC  },
+/* BTA_HH_GATT_CLOSE_EVT    */    {BTA_HH_LE_OPEN_FAIL,  BTA_HH_IDLE_ST },
+/* BTA_HH_GATT_OPEN_EVT    */     {BTA_HH_IGNORE,        BTA_HH_W4_SEC  },
+/* BTA_HH_START_ENC_EVT    */     {BTA_HH_IGNORE,        BTA_HH_W4_SEC     },
+/* BTA_HH_ENC_CMPL_EVT     */     {BTA_HH_SEC_CMPL,      BTA_HH_W4_CONN_ST },
+/* READ_CHAR_CMPL_EVT */          {BTA_HH_IGNORE,        BTA_HH_W4_SEC     },
+/* BTA_HH_GATT_WRITE_CMPL_EVT*/   {BTA_HH_IGNORE,        BTA_HH_W4_SEC     },
+/* READ_DESCR_CMPL_EVT */         {BTA_HH_IGNORE,        BTA_HH_W4_SEC   },
+/* WRITE_DESCR_CMPL_EVT */        {BTA_HH_IGNORE,        BTA_HH_W4_SEC   }
+/* SCPP_UPDATE_EVT */            ,{BTA_HH_IGNORE,        BTA_HH_W4_SEC   }
+/* BTA_HH_GATT_ENC_CMPL_EVT */   ,{BTA_HH_GATT_ENC_CMPL, BTA_HH_W4_SEC   }
+};
+#endif
+
+/* type for state table */
+typedef const UINT8 (*tBTA_HH_ST_TBL)[BTA_HH_NUM_COLS];
+
+/* state table */
+const tBTA_HH_ST_TBL bta_hh_st_tbl[] =
+{
+    bta_hh_st_idle,
+    bta_hh_st_w4_conn,
+    bta_hh_st_connected
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+    ,bta_hh_st_w4_sec
+#endif
+};
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_HH_CB  bta_hh_cb;
+#endif
+/*****************************************************************************
+** Static functions
+*****************************************************************************/
+#if BTA_HH_DEBUG == TRUE
+static char *bta_hh_evt_code(tBTA_HH_INT_EVT evt_code);
+static char *bta_hh_state_code(tBTA_HH_STATE state_code);
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_hh_sm_execute
+**
+** Description      State machine event handling function for HID Host
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16 event, tBTA_HH_DATA * p_data)
+{
+    tBTA_HH_ST_TBL  state_table;
+    UINT8           action;
+    tBTA_HH         cback_data;
+    tBTA_HH_EVT     cback_event = 0;
+#if BTA_HH_DEBUG == TRUE
+    tBTA_HH_STATE   in_state ;
+    UINT16          debug_event = event;
+#endif
+
+    memset(&cback_data, 0, sizeof(tBTA_HH));
+
+    /* handle exception, no valid control block was found */
+    if (!p_cb)
+    {
+        /* BTA HH enabled already? otherwise ignore the event although it's bad*/
+        if (bta_hh_cb.p_cback != NULL)
+        {
+            switch (event)
+            {
+            /* no control block available for new connection */
+            case BTA_HH_API_OPEN_EVT:
+                cback_event = BTA_HH_OPEN_EVT;
+                /* build cback data */
+                bdcpy(cback_data.conn.bda, ((tBTA_HH_API_CONN *)p_data)->bd_addr);
+                cback_data.conn.status  = BTA_HH_ERR_DB_FULL;
+                cback_data.conn.handle  = BTA_HH_INVALID_HANDLE;
+                break;
+            /* DB full, BTA_HhAddDev */
+            case BTA_HH_API_MAINT_DEV_EVT:
+                cback_event = p_data->api_maintdev.sub_event;
+
+                if (p_data->api_maintdev.sub_event == BTA_HH_ADD_DEV_EVT)
+                {
+                    bdcpy(cback_data.dev_info.bda, p_data->api_maintdev.bda);
+                    cback_data.dev_info.status    = BTA_HH_ERR_DB_FULL;
+                    cback_data.dev_info.handle    = BTA_HH_INVALID_HANDLE;
+                }
+                else
+                {
+                    cback_data.dev_info.status    = BTA_HH_ERR_HDL;
+                    cback_data.dev_info.handle    = (UINT8)p_data->api_maintdev.hdr.layer_specific;
+                }
+                break;
+            case BTA_HH_API_WRITE_DEV_EVT:
+                cback_event = (p_data->api_sndcmd.t_type - BTA_HH_FST_BTE_TRANS_EVT) +
+                        BTA_HH_FST_TRANS_CB_EVT;
+                if (p_data->api_sndcmd.p_data != NULL)
+                {
+                    GKI_freebuf(p_data->api_sndcmd.p_data);
+                }
+                if (p_data->api_sndcmd.t_type == HID_TRANS_SET_PROTOCOL ||
+                    p_data->api_sndcmd.t_type == HID_TRANS_SET_REPORT ||
+                    p_data->api_sndcmd.t_type == HID_TRANS_SET_IDLE)
+                {
+                    cback_data.dev_status.status = BTA_HH_ERR_HDL;
+                    cback_data.dev_status.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific;
+                }
+                else if (p_data->api_sndcmd.t_type != HID_TRANS_DATA &&
+                    p_data->api_sndcmd.t_type != HID_TRANS_CONTROL)
+                {
+                    cback_data.hs_data.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific;
+                    cback_data.hs_data.status = BTA_HH_ERR_HDL;
+                    /* hs_data.rsp_data will be all zero, which is not valid value */
+                }
+                else if (p_data->api_sndcmd.t_type == HID_TRANS_CONTROL &&
+                         p_data->api_sndcmd.param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG)
+                {
+                    cback_data.status = BTA_HH_ERR_HDL;
+                    cback_event = BTA_HH_VC_UNPLUG_EVT;
+                }
+                else
+                    cback_event = 0;
+                break;
+
+            case BTA_HH_API_CLOSE_EVT:
+                cback_event = BTA_HH_CLOSE_EVT;
+
+                cback_data.dev_status.status = BTA_HH_ERR_HDL;
+                cback_data.dev_status.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific;
+                break;
+
+            default:
+                /* invalid handle, call bad API event */
+                APPL_TRACE_ERROR("wrong device handle: [%d]", p_data->hdr.layer_specific);
+                /* Free the callback buffer now */
+                if (p_data != NULL && p_data->hid_cback.p_data != NULL)
+                {
+                    GKI_freebuf(p_data->hid_cback.p_data);
+                    p_data->hid_cback.p_data = NULL;
+                }
+                break;
+            }
+           if (cback_event)
+               (* bta_hh_cb.p_cback)(cback_event, &cback_data);
+        }
+    }
+    /* corresponding CB is found, go to state machine */
+    else
+    {
+#if BTA_HH_DEBUG == TRUE
+        in_state = p_cb->state;
+        APPL_TRACE_EVENT("bta_hh_sm_execute: State 0x%02x [%s], Event [%s]",
+                          in_state, bta_hh_state_code(in_state),
+                          bta_hh_evt_code(debug_event));
+#endif
+
+        if ((p_cb->state == BTA_HH_NULL_ST) || (p_cb->state >= BTA_HH_INVALID_ST))
+        {
+            APPL_TRACE_ERROR("bta_hh_sm_execute: Invalid state State = 0x%x, Event = %d",
+                              p_cb->state,event);
+            return;
+        }
+        state_table = bta_hh_st_tbl[p_cb->state - 1];
+
+        event &= 0xff;
+
+        p_cb->state = state_table[event][BTA_HH_NEXT_STATE] ;
+
+        if ((action = state_table[event][BTA_HH_ACTION]) != BTA_HH_IGNORE)
+        {
+            (*bta_hh_action[action])(p_cb, p_data);
+        }
+
+#if BTA_HH_DEBUG == TRUE
+        if (in_state != p_cb->state)
+        {
+            APPL_TRACE_DEBUG("HH State Change: [%s] -> [%s] after Event [%s]",
+                          bta_hh_state_code(in_state),
+                          bta_hh_state_code(p_cb->state),
+                          bta_hh_evt_code(debug_event));
+        }
+#endif
+    }
+
+    return;
+}
+/*******************************************************************************
+**
+** Function         bta_hh_hdl_event
+**
+** Description      HID host main event handling function.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN bta_hh_hdl_event(BT_HDR *p_msg)
+{
+    UINT8           index = BTA_HH_IDX_INVALID;
+    tBTA_HH_DEV_CB *p_cb = NULL;
+
+    switch (p_msg->event)
+    {
+        case BTA_HH_API_ENABLE_EVT:
+            bta_hh_api_enable((tBTA_HH_DATA *) p_msg);
+            break;
+
+        case BTA_HH_API_DISABLE_EVT:
+            bta_hh_api_disable();
+            break;
+
+        case BTA_HH_DISC_CMPL_EVT:          /* disable complete */
+            bta_hh_disc_cmpl();
+            break;
+
+        default:
+            /* all events processed in state machine need to find corresponding
+                CB before proceed */
+            if (p_msg->event == BTA_HH_API_OPEN_EVT)
+            {
+                index = bta_hh_find_cb(((tBTA_HH_API_CONN *)p_msg)->bd_addr);
+            }
+            else if (p_msg->event == BTA_HH_API_MAINT_DEV_EVT)
+            {
+                /* if add device */
+                if (((tBTA_HH_MAINT_DEV *)p_msg)->sub_event == BTA_HH_ADD_DEV_EVT)
+                {
+                    index = bta_hh_find_cb(((tBTA_HH_MAINT_DEV *)p_msg)->bda);
+                }
+                else /* else remove device by handle */
+                {
+                    index = bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific);
+// btla-specific ++
+                    /* If BT disable is done while the HID device is connected and Link_Key uses unauthenticated combination
+                      * then we can get into a situation where remove_bonding is called with the index set to 0 (without getting
+                      * cleaned up). Only when VIRTUAL_UNPLUG is called do we cleanup the index and make it MAX_KNOWN.
+                      * So if REMOVE_DEVICE is called and in_use is FALSE then we should treat this as a NULL p_cb. Hence we
+                      * force the index to be IDX_INVALID
+                      */
+                    if ((index != BTA_HH_IDX_INVALID) &&
+                        (bta_hh_cb.kdev[index].in_use == FALSE)) {
+                        index = BTA_HH_IDX_INVALID;
+                    }
+// btla-specific --
+                }
+            }
+            else if (p_msg->event == BTA_HH_INT_OPEN_EVT)
+            {
+                index = bta_hh_find_cb(((tBTA_HH_CBACK_DATA *)p_msg)->addr);
+            }
+            else
+                index = bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific);
+
+            if (index != BTA_HH_IDX_INVALID)
+                p_cb = &bta_hh_cb.kdev[index];
+
+#if BTA_HH_DEBUG
+            APPL_TRACE_DEBUG("bta_hh_hdl_event:: handle = %d dev_cb[%d] ", p_msg->layer_specific, index);
+#endif
+            bta_hh_sm_execute(p_cb, p_msg->event, (tBTA_HH_DATA *) p_msg);
+    }
+    return (TRUE);
+}
+
+/*****************************************************************************
+**  Debug Functions
+*****************************************************************************/
+#if BTA_HH_DEBUG
+/*******************************************************************************
+**
+** Function         bta_hh_evt_code
+**
+** Description
+**
+** Returns          void
+**
+*******************************************************************************/
+static char *bta_hh_evt_code(tBTA_HH_INT_EVT evt_code)
+{
+  switch(evt_code)
+    {
+    case BTA_HH_API_DISABLE_EVT:
+        return "BTA_HH_API_DISABLE_EVT";
+    case BTA_HH_API_ENABLE_EVT:
+        return "BTA_HH_API_ENABLE_EVT";
+    case BTA_HH_API_OPEN_EVT:
+        return "BTA_HH_API_OPEN_EVT";
+    case BTA_HH_API_CLOSE_EVT:
+        return "BTA_HH_API_CLOSE_EVT";
+    case BTA_HH_INT_OPEN_EVT:
+        return "BTA_HH_INT_OPEN_EVT";
+    case BTA_HH_INT_CLOSE_EVT:
+        return "BTA_HH_INT_CLOSE_EVT";
+    case BTA_HH_INT_HANDSK_EVT:
+        return "BTA_HH_INT_HANDSK_EVT";
+    case BTA_HH_INT_DATA_EVT:
+        return "BTA_HH_INT_DATA_EVT";
+    case BTA_HH_INT_CTRL_DATA:
+        return "BTA_HH_INT_CTRL_DATA";
+    case BTA_HH_API_WRITE_DEV_EVT:
+        return "BTA_HH_API_WRITE_DEV_EVT";
+    case BTA_HH_SDP_CMPL_EVT:
+        return "BTA_HH_SDP_CMPL_EVT";
+    case BTA_HH_DISC_CMPL_EVT:
+        return "BTA_HH_DISC_CMPL_EVT";
+    case BTA_HH_API_MAINT_DEV_EVT:
+        return "BTA_HH_API_MAINT_DEV_EVT";
+    case BTA_HH_API_GET_DSCP_EVT:
+        return "BTA_HH_API_GET_DSCP_EVT";
+    case BTA_HH_OPEN_CMPL_EVT:
+        return "BTA_HH_OPEN_CMPL_EVT";
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+    case BTA_HH_GATT_CLOSE_EVT:
+        return "BTA_HH_GATT_CLOSE_EVT";
+    case BTA_HH_GATT_OPEN_EVT:
+        return "BTA_HH_GATT_OPEN_EVT";
+    case BTA_HH_START_ENC_EVT:
+        return "BTA_HH_START_ENC_EVT";
+    case BTA_HH_ENC_CMPL_EVT:
+        return "BTA_HH_ENC_CMPL_EVT";
+    case BTA_HH_GATT_READ_CHAR_CMPL_EVT:
+        return "BTA_HH_GATT_READ_CHAR_CMPL_EVT";
+    case BTA_HH_GATT_WRITE_CHAR_CMPL_EVT:
+        return "BTA_HH_GATT_WRITE_CHAR_CMPL_EVT";
+    case BTA_HH_GATT_READ_DESCR_CMPL_EVT:
+        return "BTA_HH_GATT_READ_DESCR_CMPL_EVT";
+    case BTA_HH_GATT_WRITE_DESCR_CMPL_EVT:
+        return "BTA_HH_GATT_WRITE_DESCR_CMPL_EVT";
+#endif
+    default:
+        return "unknown HID Host event code";
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_state_code
+**
+** Description      get string representation of HID host state code.
+**
+** Returns          void
+**
+*******************************************************************************/
+static char *bta_hh_state_code(tBTA_HH_STATE state_code)
+{
+    switch (state_code)
+    {
+    case BTA_HH_NULL_ST:
+        return"BTA_HH_NULL_ST";
+    case BTA_HH_IDLE_ST:
+        return "BTA_HH_IDLE_ST";
+    case BTA_HH_W4_CONN_ST:
+        return "BTA_HH_W4_CONN_ST";
+    case BTA_HH_CONN_ST:
+        return "BTA_HH_CONN_ST";
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+    case BTA_HH_W4_SEC:
+        return "BTA_HH_W4_SEC";
+#endif
+    default:
+        return "unknown HID Host state";
+    }
+}
+
+#endif  /* Debug Functions */
+
+#endif /* BTA_HH_INCLUDED */

+ 539 - 0
components/bt/bluedroid/bta/hh/bta_hh_utils.c

@@ -0,0 +1,539 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2005-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+#include <string.h>
+
+#include "bt_target.h"
+#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
+
+
+#include "bta_hh_int.h"
+
+/* if SSR max latency is not defined by remote device, set the default value
+   as half of the link supervision timeout */
+#define BTA_HH_GET_DEF_SSR_MAX_LAT(x)   ((x)>> 1)
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+#define BTA_HH_KB_CTRL_MASK         0x11
+#define BTA_HH_KB_SHIFT_MASK        0x22
+#define BTA_HH_KB_ALT_MASK          0x44
+#define BTA_HH_KB_GUI_MASK          0x88
+
+#define BTA_HH_KB_CAPS_LOCK      0x39           /* caps lock */
+#define BTA_HH_KB_NUM_LOCK       0x53           /* num lock */
+
+
+#define BTA_HH_MAX_RPT_CHARS    8
+
+static const UINT8 bta_hh_mod_key_mask[BTA_HH_MOD_MAX_KEY] =
+{
+    BTA_HH_KB_CTRL_MASK,
+    BTA_HH_KB_SHIFT_MASK,
+    BTA_HH_KB_ALT_MASK,
+    BTA_HH_KB_GUI_MASK
+};
+
+
+/*******************************************************************************
+**
+** Function         bta_hh_find_cb
+**
+** Description      Find best available control block according to BD address.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+UINT8  bta_hh_find_cb(BD_ADDR bda)
+{
+    UINT8 xx;
+
+    /* See how many active devices there are. */
+    for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++)
+    {
+        /* check if any active/known devices is a match */
+        if ((!bdcmp (bda, bta_hh_cb.kdev[xx].addr) &&
+              bdcmp(bda, bd_addr_null) != 0) )
+        {
+#if BTA_HH_DEBUG
+            APPL_TRACE_DEBUG("found kdev_cb[%d] hid_handle = %d ", xx,
+                                bta_hh_cb.kdev[xx].hid_handle)
+#endif
+            return xx;
+        }
+#if BTA_HH_DEBUG
+        else
+            APPL_TRACE_DEBUG("in_use ? [%d] kdev[%d].hid_handle = %d state = [%d]",
+                            bta_hh_cb.kdev[xx].in_use, xx,
+                            bta_hh_cb.kdev[xx].hid_handle,
+                            bta_hh_cb.kdev[xx].state);
+#endif
+    }
+
+    /* if no active device match, find a spot for it */
+    for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++)
+    {
+        if (!bta_hh_cb.kdev[xx].in_use)
+        {
+            bdcpy(bta_hh_cb.kdev[xx].addr, bda);
+            break;
+        }
+    }
+    /* If device list full, report BTA_HH_IDX_INVALID */
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG("bta_hh_find_cb:: index = %d while max = %d",
+                        xx, BTA_HH_MAX_DEVICE);
+#endif
+
+    if (xx == BTA_HH_MAX_DEVICE)
+        xx = BTA_HH_IDX_INVALID;
+
+    return xx;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_clean_up_kdev
+**
+** Description      Clean up device control block when device is removed from
+**                  manitainace list, and update control block index map.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_clean_up_kdev(tBTA_HH_DEV_CB *p_cb)
+{
+    UINT8 index;
+
+    if (p_cb->hid_handle != BTA_HH_INVALID_HANDLE )
+    {
+#if BTA_HH_LE_INCLUDED == TRUE
+        if (p_cb->is_le_device)
+            bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = BTA_HH_IDX_INVALID;
+        else
+#endif
+            bta_hh_cb.cb_index[p_cb->hid_handle] = BTA_HH_IDX_INVALID;
+    }
+
+    /* reset device control block */
+    index = p_cb->index;                        /* Preserve index for this control block */
+
+    /* Free buffer for report descriptor info */
+    utl_freebuf((void **)&p_cb->dscp_info.descriptor.dsc_list);
+
+    memset(p_cb, 0, sizeof (tBTA_HH_DEV_CB));   /* Reset control block */
+
+    p_cb->index = index;                        /* Restore index for this control block */
+    p_cb->state      = BTA_HH_IDLE_ST;
+    p_cb->hid_handle = BTA_HH_INVALID_HANDLE;
+
+}
+/*******************************************************************************
+**
+** Function         bta_hh_update_di_info
+**
+** Description      Maintain a known device list for BTA HH.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_update_di_info(tBTA_HH_DEV_CB *p_cb, UINT16 vendor_id, UINT16 product_id,
+                           UINT16 version, UINT8 flag)
+{
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG("vendor_id = 0x%2x product_id = 0x%2x version = 0x%2x",
+                        vendor_id, product_id, version);
+#endif
+    p_cb->dscp_info.vendor_id     =   vendor_id;
+    p_cb->dscp_info.product_id    =   product_id;
+    p_cb->dscp_info.version       =   version;
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+    p_cb->dscp_info.flag          =   flag;
+#else
+    UNUSED(flag);
+#endif
+}
+/*******************************************************************************
+**
+** Function         bta_hh_add_device_to_list
+**
+** Description      Maintain a known device list for BTA HH.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_add_device_to_list(tBTA_HH_DEV_CB *p_cb, UINT8 handle,
+                               UINT16 attr_mask,
+                               tHID_DEV_DSCP_INFO *p_dscp_info,
+                               UINT8 sub_class,
+                               UINT16 ssr_max_latency,
+                               UINT16 ssr_min_tout,
+                               UINT8 app_id)
+{
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG("subclass = 0x%2x", sub_class);
+#endif
+
+    p_cb->hid_handle = handle;
+    p_cb->in_use = TRUE;
+    p_cb->attr_mask = attr_mask;
+
+    p_cb->sub_class = sub_class;
+    p_cb->app_id    = app_id;
+
+    p_cb->dscp_info.ssr_max_latency = ssr_max_latency;
+    p_cb->dscp_info.ssr_min_tout    = ssr_min_tout;
+
+    /* store report descriptor info */
+    if ( p_dscp_info)
+    {
+        utl_freebuf((void **)&p_cb->dscp_info.descriptor.dsc_list);
+
+        if (p_dscp_info->dl_len &&
+        (p_cb->dscp_info.descriptor.dsc_list =
+            (UINT8 *)GKI_getbuf(p_dscp_info->dl_len)) != NULL)
+        {
+            p_cb->dscp_info.descriptor.dl_len = p_dscp_info->dl_len;
+            memcpy(p_cb->dscp_info.descriptor.dsc_list, p_dscp_info->dsc_list,
+                    p_dscp_info->dl_len);
+        }
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_tod_spt
+**
+** Description      Check to see if this type of device is supported
+**
+** Returns
+**
+*******************************************************************************/
+BOOLEAN bta_hh_tod_spt(tBTA_HH_DEV_CB *p_cb,UINT8 sub_class)
+{
+    UINT8    xx;
+    UINT8    cod = (sub_class >> 2); /* lower two bits are reserved */
+
+    for (xx = 0 ; xx < p_bta_hh_cfg->max_devt_spt; xx ++)
+    {
+        if (cod == (UINT8) p_bta_hh_cfg->p_devt_list[xx].tod)
+        {
+            p_cb->app_id = p_bta_hh_cfg->p_devt_list[xx].app_id;
+#if BTA_HH_DEBUG
+            APPL_TRACE_EVENT("bta_hh_tod_spt sub_class:0x%x supported", sub_class);
+#endif
+            return TRUE;
+        }
+    }
+#if BTA_HH_DEBUG
+            APPL_TRACE_EVENT("bta_hh_tod_spt sub_class:0x%x NOT supported", sub_class);
+#endif
+    return FALSE;
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hh_parse_keybd_rpt
+**
+** Description      This utility function parse a boot mode keyboard report.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_parse_keybd_rpt(tBTA_HH_BOOT_RPT *p_kb_data, UINT8 *p_report,
+                            UINT16 report_len)
+{
+    tBTA_HH_KB_CB       *p_kb = &bta_hh_cb.kb_cb;
+    tBTA_HH_KEYBD_RPT   *p_data = &p_kb_data->data_rpt.keybd_rpt;
+
+    UINT8        this_char, ctl_shift;
+    UINT16       xx, yy, key_idx = 0;
+    UINT8        this_report[BTA_HH_MAX_RPT_CHARS];
+
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG("bta_hh_parse_keybd_rpt:  (report=%p, report_len=%d) called",
+            p_report, report_len);
+#endif
+
+    if (report_len < 2)
+        return;
+
+    ctl_shift = *p_report++;
+    report_len--;
+
+    if (report_len > BTA_HH_MAX_RPT_CHARS)
+        report_len = BTA_HH_MAX_RPT_CHARS;
+
+    memset (this_report, 0, BTA_HH_MAX_RPT_CHARS);
+    memset (p_data, 0, sizeof(tBTA_HH_KEYBD_RPT));
+    memcpy (this_report, p_report, report_len);
+
+    /* Take care of shift, control, GUI and alt, modifier keys  */
+    for (xx = 0; xx < BTA_HH_MOD_MAX_KEY; xx ++ )
+    {
+        if (ctl_shift & bta_hh_mod_key_mask[xx])
+        {
+            APPL_TRACE_DEBUG("Mod Key[%02x] pressed", bta_hh_mod_key_mask[xx] );
+            p_kb->mod_key[xx] = TRUE;
+        }
+        else if (p_kb->mod_key[xx])
+        {
+            p_kb->mod_key[xx] = FALSE;
+        }
+        /* control key flag is set */
+        p_data->mod_key[xx]       = p_kb->mod_key[xx];
+    }
+
+    /***************************************************************************/
+    /*  First step is to remove all characters we saw in the last report       */
+    /***************************************************************************/
+    for (xx = 0; xx < report_len; xx++)
+    {
+        for (yy = 0; yy < BTA_HH_MAX_RPT_CHARS; yy++)
+        {
+            if (this_report[xx] == p_kb->last_report[yy])
+            {
+                this_report[xx] = 0;
+            }
+        }
+    }
+    /***************************************************************************/
+    /*  Now, process all the characters in the report, up to 6 keycodes        */
+    /***************************************************************************/
+    for (xx = 0; xx < report_len; xx++)
+    {
+#if BTA_HH_DEBUG
+        APPL_TRACE_DEBUG("this_char = %02x", this_report[xx]);
+#endif
+        if ((this_char = this_report[xx]) == 0)
+            continue;
+        /* take the key code as the report data */
+        if (this_report[xx] == BTA_HH_KB_CAPS_LOCK)
+            p_kb->caps_lock = p_kb->caps_lock ? FALSE : TRUE;
+        else if (this_report[xx] == BTA_HH_KB_NUM_LOCK)
+            p_kb->num_lock = p_kb->num_lock ? FALSE : TRUE;
+        else
+            p_data->this_char[key_idx ++] = this_char;
+
+#if BTA_HH_DEBUG
+        APPL_TRACE_DEBUG("found keycode %02x ",  this_report[xx]);
+#endif
+        p_data->caps_lock   = p_kb->caps_lock;
+        p_data->num_lock      = p_kb->num_lock;
+    }
+
+    memset (p_kb->last_report, 0, BTA_HH_MAX_RPT_CHARS);
+    memcpy (p_kb->last_report, p_report, report_len);
+
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_parse_mice_rpt
+**
+** Description      This utility function parse a boot mode mouse report.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_parse_mice_rpt(tBTA_HH_BOOT_RPT *p_mice_data, UINT8 *p_report,
+                           UINT16 report_len)
+{
+    tBTA_HH_MICE_RPT   *p_data = &p_mice_data->data_rpt.mice_rpt;
+#if BTA_HH_DEBUG
+    UINT8       xx;
+
+    APPL_TRACE_DEBUG("bta_hh_parse_mice_rpt:  bta_keybd_rpt_rcvd(report=%p, \
+                report_len=%d) called", p_report, report_len);
+#endif
+
+    if (report_len < 3)
+        return;
+
+    if (report_len > BTA_HH_MAX_RPT_CHARS)
+        report_len = BTA_HH_MAX_RPT_CHARS;
+
+#if BTA_HH_DEBUG
+    for (xx = 0; xx < report_len; xx++)
+    {
+        APPL_TRACE_DEBUG("this_char = %02x", p_report[xx]);
+    }
+#endif
+
+    /* only first bytes lower 3 bits valid */
+    p_data->mouse_button     = (p_report[0] & 0x07);
+
+    /* x displacement */
+    p_data->delta_x     = p_report[1];
+
+    /* y displacement */
+    p_data->delta_y     = p_report[2];
+
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG("mice button: 0x%2x", p_data->mouse_button);
+    APPL_TRACE_DEBUG("mice move: x = %d y = %d", p_data->delta_x,
+                        p_data->delta_y );
+#endif
+
+    return;
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_read_ssr_param
+**
+** Description      Read the SSR Parameter for the remote device
+**
+** Returns          tBTA_HH_STATUS  operation status
+**
+*******************************************************************************/
+tBTA_HH_STATUS bta_hh_read_ssr_param(BD_ADDR bd_addr, UINT16 *p_max_ssr_lat, UINT16 *p_min_ssr_tout)
+{
+    tBTA_HH_STATUS  status = BTA_HH_ERR;
+    tBTA_HH_CB  *p_cb = &bta_hh_cb;
+    UINT8       i;
+    UINT16      ssr_max_latency;
+    for (i = 0; i < BTA_HH_MAX_KNOWN; i ++)
+    {
+        if (memcmp(p_cb->kdev[i].addr, bd_addr, BD_ADDR_LEN) == 0)
+        {
+
+            /* if remote device does not have HIDSSRHostMaxLatency attribute in SDP,
+            set SSR max latency default value here.  */
+            if (p_cb->kdev[i].dscp_info.ssr_max_latency == HID_SSR_PARAM_INVALID)
+            {
+                /* The default is calculated as half of link supervision timeout.*/
+
+                BTM_GetLinkSuperTout(p_cb->kdev[i].addr, &ssr_max_latency) ;
+                ssr_max_latency = BTA_HH_GET_DEF_SSR_MAX_LAT(ssr_max_latency);
+
+                /* per 1.1 spec, if the newly calculated max latency is greater than
+                BTA_HH_SSR_MAX_LATENCY_DEF which is 500ms, use BTA_HH_SSR_MAX_LATENCY_DEF */
+                if (ssr_max_latency > BTA_HH_SSR_MAX_LATENCY_DEF)
+                    ssr_max_latency = BTA_HH_SSR_MAX_LATENCY_DEF;
+
+                * p_max_ssr_lat  = ssr_max_latency;
+            }
+            else
+                * p_max_ssr_lat  = p_cb->kdev[i].dscp_info.ssr_max_latency;
+
+            if (p_cb->kdev[i].dscp_info.ssr_min_tout == HID_SSR_PARAM_INVALID)
+                * p_min_ssr_tout = BTA_HH_SSR_MIN_TOUT_DEF;
+            else
+                * p_min_ssr_tout = p_cb->kdev[i].dscp_info.ssr_min_tout;
+
+            status           = BTA_HH_OK;
+
+            break;
+        }
+    }
+
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_cleanup_disable
+**
+** Description      when disable finished, cleanup control block and send callback
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_cleanup_disable(tBTA_HH_STATUS status)
+{
+    UINT8   xx;
+    /* free buffer in CB holding report descriptors */
+    for(xx = 0; xx < BTA_HH_MAX_DEVICE; xx ++)
+    {
+        utl_freebuf((void **)&bta_hh_cb.kdev[xx].dscp_info.descriptor.dsc_list);
+    }
+    utl_freebuf((void **)&bta_hh_cb.p_disc_db);
+
+    (* bta_hh_cb.p_cback)(BTA_HH_DISABLE_EVT, (tBTA_HH *)&status);
+    /* all connections are down, no waiting for diconnect */
+    memset(&bta_hh_cb, 0, sizeof(tBTA_HH_CB));
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_dev_handle_to_cb_idx
+**
+** Description      convert a HID device handle to the device control block index.
+**
+**
+** Returns          UINT8: index of the device control block.
+**
+*******************************************************************************/
+UINT8 bta_hh_dev_handle_to_cb_idx(UINT8 dev_handle)
+{
+    UINT8 index = BTA_HH_IDX_INVALID;
+
+#if BTA_HH_LE_INCLUDED == TRUE
+    if (BTA_HH_IS_LE_DEV_HDL(dev_handle))
+    {
+        if (BTA_HH_IS_LE_DEV_HDL_VALID(dev_handle))
+            index = bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(dev_handle)];
+#if BTA_HH_DEBUG == TRUE
+        APPL_TRACE_DEBUG("bta_hh_dev_handle_to_cb_idx dev_handle = %d index = %d", dev_handle, index);
+#endif
+    }
+    else
+#endif
+        /* regular HID device checking */
+        if (dev_handle < BTA_HH_MAX_KNOWN )
+        index = bta_hh_cb.cb_index[dev_handle];
+
+    return index;
+
+}
+#if BTA_HH_DEBUG
+/*******************************************************************************
+**
+** Function         bta_hh_trace_dev_db
+**
+** Description      Check to see if this type of device is supported
+**
+** Returns
+**
+*******************************************************************************/
+void bta_hh_trace_dev_db(void)
+{
+    UINT8    xx;
+
+    APPL_TRACE_DEBUG("bta_hh_trace_dev_db:: Device DB list********************");
+
+    for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++)
+    {
+        APPL_TRACE_DEBUG("kdev[%d] in_use[%d]  handle[%d] ",xx,
+            bta_hh_cb.kdev[xx].in_use, bta_hh_cb.kdev[xx].hid_handle);
+
+        APPL_TRACE_DEBUG("\t\t\t attr_mask[%04x] state [%d] sub_class[%02x] index = %d",
+            bta_hh_cb.kdev[xx].attr_mask, bta_hh_cb.kdev[xx].state,
+            bta_hh_cb.kdev[xx].sub_class, bta_hh_cb.kdev[xx].index);
+    }
+    APPL_TRACE_DEBUG("*********************************************************");
+}
+#endif
+#endif /* HL_INCLUDED */

+ 2389 - 0
components/bt/bluedroid/bta/include/bta_api.h

@@ -0,0 +1,2389 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2014 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the public interface file for BTA, Broadcom's Bluetooth
+ *  application layer for mobile phones.
+ *
+ ******************************************************************************/
+#ifndef BTA_API_H
+#define BTA_API_H
+
+#include "bt_target.h"
+#include "bt_types.h"
+#include "btm_api.h"
+// #include "uipc_msg.h"
+
+#if BLE_INCLUDED == TRUE
+#include "btm_ble_api.h"
+#endif
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+
+/* Status Return Value */
+#define BTA_SUCCESS             0           /* Successful operation. */
+#define BTA_FAILURE             1           /* Generic failure. */
+#define BTA_PENDING             2           /* API cannot be completed right now */
+#define BTA_BUSY                3
+#define BTA_NO_RESOURCES        4
+#define BTA_WRONG_MODE          5
+
+typedef UINT8 tBTA_STATUS;
+
+/*
+ * Service ID
+ *
+ * NOTES: When you add a new Service ID for BTA AND require to change the value of BTA_MAX_SERVICE_ID,
+ *        make sure that the correct security ID of the new service from Security service definitions (btm_api.h)
+ *        should be added to bta_service_id_to_btm_srv_id_lkup_tbl table in bta_dm_act.c.
+ */
+
+#define BTA_RES_SERVICE_ID      0           /* Reserved */
+#define BTA_SPP_SERVICE_ID      1           /* Serial port profile. */
+#define BTA_DUN_SERVICE_ID      2           /* Dial-up networking profile. */
+#define BTA_A2DP_SOURCE_SERVICE_ID      3   /* A2DP Source profile. */
+#define BTA_LAP_SERVICE_ID      4           /* LAN access profile. */
+#define BTA_HSP_SERVICE_ID      5           /* Headset profile. */
+#define BTA_HFP_SERVICE_ID      6           /* Hands-free profile. */
+#define BTA_OPP_SERVICE_ID      7           /* Object push  */
+#define BTA_FTP_SERVICE_ID      8           /* File transfer */
+#define BTA_CTP_SERVICE_ID      9           /* Cordless Terminal */
+#define BTA_ICP_SERVICE_ID      10          /* Intercom Terminal */
+#define BTA_SYNC_SERVICE_ID     11          /* Synchronization */
+#define BTA_BPP_SERVICE_ID      12          /* Basic printing profile */
+#define BTA_BIP_SERVICE_ID      13          /* Basic Imaging profile */
+#define BTA_PANU_SERVICE_ID     14          /* PAN User */
+#define BTA_NAP_SERVICE_ID      15          /* PAN Network access point */
+#define BTA_GN_SERVICE_ID       16          /* PAN Group Ad-hoc networks */
+#define BTA_SAP_SERVICE_ID      17          /* SIM Access profile */
+#define BTA_A2DP_SINK_SERVICE_ID        18  /* A2DP Sink */
+#define BTA_AVRCP_SERVICE_ID    19          /* A/V remote control */
+#define BTA_HID_SERVICE_ID      20          /* HID */
+#define BTA_VDP_SERVICE_ID      21          /* Video distribution */
+#define BTA_PBAP_SERVICE_ID     22          /* PhoneBook Access Server*/
+#define BTA_HSP_HS_SERVICE_ID   23          /* HFP HS role */
+#define BTA_HFP_HS_SERVICE_ID   24          /* HSP HS role */
+#define BTA_MAP_SERVICE_ID      25          /* Message Access Profile */
+#define BTA_MN_SERVICE_ID       26          /* Message Notification Service */
+#define BTA_HDP_SERVICE_ID      27          /* Health Device Profile */
+#define BTA_PCE_SERVICE_ID      28          /* PhoneBook Access Client*/
+#define BTA_SDP_SERVICE_ID      29          /* SDP Search*/
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+/* BLE profile service ID */
+#define BTA_BLE_SERVICE_ID      30          /* GATT profile */
+
+// btla-specific ++
+#define BTA_USER_SERVICE_ID     31          /* User requested UUID */
+
+#define BTA_MAX_SERVICE_ID      32
+// btla-specific --
+#else
+#define BTA_USER_SERVICE_ID     30          /* User requested UUID */
+#define BTA_MAX_SERVICE_ID      31
+#endif
+/* service IDs (BTM_SEC_SERVICE_FIRST_EMPTY + 1) to (BTM_SEC_MAX_SERVICES - 1)
+ * are used by BTA JV */
+#define BTA_FIRST_JV_SERVICE_ID     (BTM_SEC_SERVICE_FIRST_EMPTY + 1)
+#define BTA_LAST_JV_SERVICE_ID      (BTM_SEC_MAX_SERVICES - 1)
+
+typedef UINT8 tBTA_SERVICE_ID;
+
+/* Service ID Mask */
+#define BTA_RES_SERVICE_MASK        0x00000001  /* Reserved */
+#define BTA_SPP_SERVICE_MASK        0x00000002  /* Serial port profile. */
+#define BTA_DUN_SERVICE_MASK        0x00000004  /* Dial-up networking profile. */
+#define BTA_FAX_SERVICE_MASK        0x00000008  /* Fax profile. */
+#define BTA_LAP_SERVICE_MASK        0x00000010  /* LAN access profile. */
+#define BTA_HSP_SERVICE_MASK        0x00000020  /* HSP AG role. */
+#define BTA_HFP_SERVICE_MASK        0x00000040  /* HFP AG role */
+#define BTA_OPP_SERVICE_MASK        0x00000080  /* Object push  */
+#define BTA_FTP_SERVICE_MASK        0x00000100  /* File transfer */
+#define BTA_CTP_SERVICE_MASK        0x00000200  /* Cordless Terminal */
+#define BTA_ICP_SERVICE_MASK        0x00000400  /* Intercom Terminal */
+#define BTA_SYNC_SERVICE_MASK       0x00000800  /* Synchronization */
+#define BTA_BPP_SERVICE_MASK        0x00001000  /* Print server */
+#define BTA_BIP_SERVICE_MASK        0x00002000  /* Basic Imaging */
+#define BTA_PANU_SERVICE_MASK       0x00004000  /* PAN User */
+#define BTA_NAP_SERVICE_MASK        0x00008000  /* PAN Network access point */
+#define BTA_GN_SERVICE_MASK         0x00010000  /* PAN Group Ad-hoc networks */
+#define BTA_SAP_SERVICE_MASK        0x00020000  /* PAN Group Ad-hoc networks */
+#define BTA_A2DP_SERVICE_MASK       0x00040000  /* Advanced audio distribution */
+#define BTA_AVRCP_SERVICE_MASK      0x00080000  /* A/V remote control */
+#define BTA_HID_SERVICE_MASK        0x00100000  /* HID */
+#define BTA_VDP_SERVICE_MASK        0x00200000  /* Video distribution */
+#define BTA_PBAP_SERVICE_MASK       0x00400000  /* Phone Book Server */
+#define BTA_HSP_HS_SERVICE_MASK     0x00800000  /* HFP HS role */
+#define BTA_HFP_HS_SERVICE_MASK     0x01000000  /* HSP HS role */
+#define BTA_MAS_SERVICE_MASK        0x02000000  /* Message Access Profile */
+#define BTA_MN_SERVICE_MASK         0x04000000  /* Message Notification Profile */
+#define BTA_HL_SERVICE_MASK         0x08000000  /* Health Device Profile */
+#define BTA_PCE_SERVICE_MASK        0x10000000  /* Phone Book Client */
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+#define BTA_BLE_SERVICE_MASK        0x20000000  /* GATT based service */
+// btla-specific ++
+#define BTA_USER_SERVICE_MASK       0x40000000  /* Message Notification Profile */
+// btla-specific --
+#else
+// btla-specific ++
+#define BTA_USER_SERVICE_MASK       0x20000000  /* Message Notification Profile */
+// btla-specific --
+#endif
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+#define BTA_ALL_SERVICE_MASK        0x3FFFFFFF  /* All services supported by BTA. */
+#else
+#define BTA_ALL_SERVICE_MASK        0x1FFFFFFF  /* All services supported by BTA. */
+#endif
+
+typedef UINT32 tBTA_SERVICE_MASK;
+
+/* extended service mask, including mask with one or more GATT UUID */
+typedef struct
+{
+    tBTA_SERVICE_MASK   srvc_mask;
+    UINT8               num_uuid;
+    tBT_UUID            *p_uuid;
+}tBTA_SERVICE_MASK_EXT;
+
+/* Security Setting Mask */
+#define BTA_SEC_NONE            BTM_SEC_NONE                                         /* No security. */
+#define BTA_SEC_AUTHORIZE       (BTM_SEC_IN_AUTHORIZE )                              /* Authorization required (only needed for out going connection )*/
+#define BTA_SEC_AUTHENTICATE    (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_OUT_AUTHENTICATE) /* Authentication required. */
+#define BTA_SEC_ENCRYPT         (BTM_SEC_IN_ENCRYPT | BTM_SEC_OUT_ENCRYPT)           /* Encryption required. */
+#define BTA_SEC_MODE4_LEVEL4    (BTM_SEC_MODE4_LEVEL4)                               /* Mode 4 level 4 service, i.e. incoming/outgoing MITM and P-256 encryption */
+#define BTA_SEC_MITM            (BTM_SEC_IN_MITM | BTM_SEC_OUT_MITM)                 /* Man-In-The_Middle protection */
+#define BTA_SEC_IN_16_DIGITS    (BTM_SEC_IN_MIN_16_DIGIT_PIN)                        /* Min 16 digit for pin code */
+
+typedef UINT16 tBTA_SEC;
+
+/* Ignore for Discoverable, Connectable, Pairable and Connectable Paired only device modes */
+#define BTA_DM_IGNORE           0x00FF
+
+/* Ignore for Discoverable, Connectable only for LE modes */
+#define BTA_DM_LE_IGNORE           0xFF00
+
+#define BTA_APP_ID_PAN_MULTI    0xFE    /* app id for pan multiple connection */
+#define BTA_ALL_APP_ID          0xFF
+
+/* Discoverable Modes */
+#define BTA_DM_NON_DISC         BTM_NON_DISCOVERABLE        /* Device is not discoverable. */
+#define BTA_DM_GENERAL_DISC     BTM_GENERAL_DISCOVERABLE    /* General discoverable. */
+#define BTA_DM_LIMITED_DISC     BTM_LIMITED_DISCOVERABLE    /* Limited discoverable. */
+#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+#define BTA_DM_BLE_NON_DISCOVERABLE        BTM_BLE_NON_DISCOVERABLE        /* Device is not LE discoverable */
+#define BTA_DM_BLE_GENERAL_DISCOVERABLE    BTM_BLE_GENERAL_DISCOVERABLE    /* Device is LE General discoverable */
+#define BTA_DM_BLE_LIMITED_DISCOVERABLE    BTM_BLE_LIMITED_DISCOVERABLE    /* Device is LE Limited discoverable */
+#endif
+typedef UINT16 tBTA_DM_DISC;        /* this discoverability mode is a bit mask among BR mode and LE mode */
+
+/* Connectable Modes */
+#define BTA_DM_NON_CONN         BTM_NON_CONNECTABLE         /* Device is not connectable. */
+#define BTA_DM_CONN             BTM_CONNECTABLE             /* Device is connectable. */
+#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+#define BTA_DM_BLE_NON_CONNECTABLE      BTM_BLE_NON_CONNECTABLE     /* Device is LE non-connectable. */
+#define BTA_DM_BLE_CONNECTABLE          BTM_BLE_CONNECTABLE         /* Device is LE connectable. */
+#endif
+
+// btla-specific ++
+typedef UINT16 tBTA_DM_CONN;
+
+#define BTA_TRANSPORT_UNKNOWN   0
+#define BTA_TRANSPORT_BR_EDR    BT_TRANSPORT_BR_EDR
+#define BTA_TRANSPORT_LE        BT_TRANSPORT_LE
+typedef tBT_TRANSPORT tBTA_TRANSPORT;
+
+/* Pairable Modes */
+#define BTA_DM_PAIRABLE         1
+#define BTA_DM_NON_PAIRABLE     0
+
+/* Connectable Paired Only Mode */
+#define BTA_DM_CONN_ALL         0
+#define BTA_DM_CONN_PAIRED      1
+
+/* Inquiry Modes */
+#define BTA_DM_INQUIRY_NONE     BTM_INQUIRY_NONE            /*No BR inquiry. */
+#define BTA_DM_GENERAL_INQUIRY  BTM_GENERAL_INQUIRY         /* Perform general inquiry. */
+#define BTA_DM_LIMITED_INQUIRY  BTM_LIMITED_INQUIRY         /* Perform limited inquiry. */
+
+#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+#define BTA_BLE_INQUIRY_NONE    BTM_BLE_INQUIRY_NONE
+#define BTA_BLE_GENERAL_INQUIRY BTM_BLE_GENERAL_INQUIRY      /* Perform LE general inquiry. */
+#define BTA_BLE_LIMITED_INQUIRY BTM_BLE_LIMITED_INQUIRY      /* Perform LE limited inquiry. */
+#endif
+typedef UINT8 tBTA_DM_INQ_MODE;
+
+/* Inquiry Filter Type */
+#define BTA_DM_INQ_CLR          BTM_CLR_INQUIRY_FILTER          /* Clear inquiry filter. */
+#define BTA_DM_INQ_DEV_CLASS    BTM_FILTER_COND_DEVICE_CLASS    /* Filter on device class. */
+#define BTA_DM_INQ_BD_ADDR      BTM_FILTER_COND_BD_ADDR         /* Filter on a specific  BD address. */
+
+typedef UINT8 tBTA_DM_INQ_FILT;
+
+/* Authorize Response */
+#define BTA_DM_AUTH_PERM        0      /* Authorized for future connections to the service */
+#define BTA_DM_AUTH_TEMP        1      /* Authorized for current connection only */
+#define BTA_DM_NOT_AUTH         2      /* Not authorized for the service */
+
+typedef UINT8 tBTA_AUTH_RESP;
+
+/* M/S preferred roles */
+#define BTA_ANY_ROLE          0x00
+#define BTA_MASTER_ROLE_PREF  0x01
+#define BTA_MASTER_ROLE_ONLY  0x02
+#define BTA_SLAVE_ROLE_ONLY   0x03     /* Used for PANU only, skip role switch to master */
+
+typedef UINT8 tBTA_PREF_ROLES;
+
+enum
+{
+
+    BTA_DM_NO_SCATTERNET,        /* Device doesn't support scatternet, it might
+                                    support "role switch during connection" for
+                                    an incoming connection, when it already has
+                                    another connection in master role */
+    BTA_DM_PARTIAL_SCATTERNET,   /* Device supports partial scatternet. It can have
+                                    simulateous connection in Master and Slave roles
+                                    for short period of time */
+    BTA_DM_FULL_SCATTERNET       /* Device can have simultaneous connection in master
+                                    and slave roles */
+
+};
+
+
+/* Inquiry filter device class condition */
+typedef struct
+{
+    DEV_CLASS       dev_class;        /* device class of interest */
+    DEV_CLASS       dev_class_mask;   /* mask to determine the bits of device class of interest */
+} tBTA_DM_COD_COND;
+
+
+/* Inquiry Filter Condition */
+typedef union
+{
+    BD_ADDR              bd_addr;            /* BD address of  device to filter. */
+    tBTA_DM_COD_COND     dev_class_cond;     /* Device class filter condition */
+} tBTA_DM_INQ_COND;
+
+/* Inquiry Parameters */
+typedef struct
+{
+    tBTA_DM_INQ_MODE    mode;           /* Inquiry mode, limited or general. */
+    UINT8               duration;       /* Inquiry duration in 1.28 sec units. */
+    UINT8               max_resps;      /* Maximum inquiry responses.  Set to zero for unlimited responses. */
+    BOOLEAN             report_dup;     /* report duplicated inquiry response with higher RSSI value */
+    tBTA_DM_INQ_FILT    filter_type;    /* Filter condition type. */
+    tBTA_DM_INQ_COND    filter_cond;    /* Filter condition data. */
+#if (defined(BTA_HOST_INTERLEAVE_SEARCH) && BTA_HOST_INTERLEAVE_SEARCH == TRUE)
+    UINT8               intl_duration[4];/*duration array storing the interleave scan's time portions*/
+#endif
+} tBTA_DM_INQ;
+
+typedef struct
+{
+    UINT8   bta_dm_eir_min_name_len;        /* minimum length of local name when it is shortened */
+#if (BTA_EIR_CANNED_UUID_LIST == TRUE)
+    UINT8   bta_dm_eir_uuid16_len;          /* length of 16-bit UUIDs */
+    UINT8  *bta_dm_eir_uuid16;              /* 16-bit UUIDs */
+#else
+    UINT32  uuid_mask[BTM_EIR_SERVICE_ARRAY_SIZE]; /* mask of UUID list in EIR */
+#endif
+    INT8   *bta_dm_eir_inq_tx_power;        /* Inquiry TX power         */
+    UINT8   bta_dm_eir_flag_len;            /* length of flags in bytes */
+    UINT8  *bta_dm_eir_flags;               /* flags for EIR */
+    UINT8   bta_dm_eir_manufac_spec_len;    /* length of manufacturer specific in bytes */
+    UINT8  *bta_dm_eir_manufac_spec;        /* manufacturer specific */
+    UINT8   bta_dm_eir_additional_len;      /* length of additional data in bytes */
+    UINT8  *bta_dm_eir_additional;          /* additional data */
+} tBTA_DM_EIR_CONF;
+
+#if BLE_INCLUDED == TRUE
+/* ADV data flag bit definition used for BTM_BLE_AD_TYPE_FLAG */
+#define BTA_BLE_LIMIT_DISC_FLAG     BTM_BLE_LIMIT_DISC_FLAG
+#define BTA_BLE_GEN_DISC_FLAG       BTM_BLE_GEN_DISC_FLAG
+#define BTA_BLE_BREDR_NOT_SPT       BTM_BLE_BREDR_NOT_SPT
+#define BTA_BLE_DMT_CONTROLLER_SPT  BTM_BLE_DMT_CONTROLLER_SPT
+#define BTA_BLE_DMT_HOST_SPT        BTM_BLE_DMT_HOST_SPT
+#define BTA_BLE_NON_LIMIT_DISC_FLAG BTM_BLE_NON_LIMIT_DISC_FLAG
+#define BTA_BLE_ADV_FLAG_MASK       BTM_BLE_ADV_FLAG_MASK
+#define BTA_BLE_LIMIT_DISC_MASK     BTM_BLE_LIMIT_DISC_MASK
+
+/* ADV data bit mask */
+#define BTA_BLE_AD_BIT_DEV_NAME        BTM_BLE_AD_BIT_DEV_NAME
+#define BTA_BLE_AD_BIT_FLAGS           BTM_BLE_AD_BIT_FLAGS
+#define BTA_BLE_AD_BIT_MANU            BTM_BLE_AD_BIT_MANU
+#define BTA_BLE_AD_BIT_TX_PWR          BTM_BLE_AD_BIT_TX_PWR
+#define BTA_BLE_AD_BIT_INT_RANGE       BTM_BLE_AD_BIT_INT_RANGE
+#define BTA_BLE_AD_BIT_SERVICE         BTM_BLE_AD_BIT_SERVICE
+#define BTA_BLE_AD_BIT_APPEARANCE      BTM_BLE_AD_BIT_APPEARANCE
+#define BTA_BLE_AD_BIT_PROPRIETARY     BTM_BLE_AD_BIT_PROPRIETARY
+#define BTA_DM_BLE_AD_BIT_SERVICE_SOL     BTM_BLE_AD_BIT_SERVICE_SOL
+#define BTA_DM_BLE_AD_BIT_SERVICE_DATA    BTM_BLE_AD_BIT_SERVICE_DATA
+#define BTA_DM_BLE_AD_BIT_SIGN_DATA       BTM_BLE_AD_BIT_SIGN_DATA
+#define BTA_DM_BLE_AD_BIT_SERVICE_128SOL  BTM_BLE_AD_BIT_SERVICE_128SOL
+#define BTA_DM_BLE_AD_BIT_PUBLIC_ADDR     BTM_BLE_AD_BIT_PUBLIC_ADDR
+#define BTA_DM_BLE_AD_BIT_RANDOM_ADDR     BTM_BLE_AD_BIT_RANDOM_ADDR
+#define BTA_DM_BLE_AD_BIT_SERVICE_128     BTM_BLE_AD_BIT_SERVICE_128      /*128-bit Service UUIDs*/
+
+typedef  tBTM_BLE_AD_MASK  tBTA_BLE_AD_MASK;
+
+/* slave preferred connection interval range */
+typedef struct
+{
+    UINT16  low;
+    UINT16  hi;
+
+}tBTA_BLE_INT_RANGE;
+
+/* Service tag supported in the device */
+typedef struct
+{
+    UINT8       num_service;
+    BOOLEAN     list_cmpl;
+    UINT16      *p_uuid;
+}tBTA_BLE_SERVICE;
+
+
+typedef struct
+{
+    UINT8       len;
+    UINT8      *p_val;
+}tBTA_BLE_MANU;
+
+typedef struct
+{
+    UINT8       adv_type;
+    UINT8       len;
+    UINT8       *p_val;     /* number of len byte */
+}tBTA_BLE_PROP_ELEM;
+
+/* vendor proprietary adv type */
+typedef struct
+{
+    UINT8                   num_elem;
+    tBTA_BLE_PROP_ELEM      *p_elem;
+}tBTA_BLE_PROPRIETARY;
+
+typedef struct
+{
+    tBT_UUID    service_uuid;
+    UINT8       len;
+    UINT8      *p_val;
+}tBTA_BLE_SERVICE_DATA;
+
+typedef tBTM_BLE_128SERVICE tBTA_BLE_128SERVICE;
+typedef tBTM_BLE_32SERVICE  tBTA_BLE_32SERVICE;
+
+typedef struct
+{
+    tBTA_BLE_INT_RANGE      int_range;          /* slave prefered conn interval range */
+    tBTA_BLE_MANU           *p_manu;            /* manufacturer data */
+    tBTA_BLE_SERVICE        *p_services;        /* 16 bits services */
+    tBTA_BLE_128SERVICE     *p_services_128b;   /* 128 bits service */
+    tBTA_BLE_32SERVICE      *p_service_32b;     /* 32 bits Service UUID */
+    tBTA_BLE_SERVICE        *p_sol_services;    /* 16 bits services Solicitation UUIDs */
+    tBTA_BLE_32SERVICE      *p_sol_service_32b; /* List of 32 bit Service Solicitation UUIDs */
+    tBTA_BLE_128SERVICE     *p_sol_service_128b;/* List of 128 bit Service Solicitation UUIDs */
+    tBTA_BLE_PROPRIETARY    *p_proprietary;     /* proprietary data */
+    tBTA_BLE_SERVICE_DATA   *p_service_data;    /* service data */
+    UINT16                  appearance;         /* appearance data */
+    UINT8                   flag;
+    UINT8                   tx_power;
+}tBTA_BLE_ADV_DATA;
+
+typedef void (tBTA_SET_ADV_DATA_CMPL_CBACK) (tBTA_STATUS status);
+
+/* advertising channel map */
+#define BTA_BLE_ADV_CHNL_37 BTM_BLE_ADV_CHNL_37
+#define BTA_BLE_ADV_CHNL_38 BTM_BLE_ADV_CHNL_38
+#define BTA_BLE_ADV_CHNL_39 BTM_BLE_ADV_CHNL_39
+typedef tBTM_BLE_ADV_CHNL_MAP tBTA_BLE_ADV_CHNL_MAP; /* use as a bit mask */
+
+/* advertising filter policy */
+typedef tBTM_BLE_AFP   tBTA_BLE_AFP;
+
+/* adv event type */
+#define BTA_BLE_CONNECT_EVT         BTM_BLE_CONNECT_EVT     /* Connectable undirected advertising */
+#define BTA_BLE_CONNECT_DIR_EVT     BTM_BLE_CONNECT_DIR_EVT /* Connectable directed advertising */
+#define BTA_BLE_DISCOVER_EVT        BTM_BLE_DISCOVER_EVT    /* Scannable undirected advertising */
+#define BTA_BLE_NON_CONNECT_EVT     BTM_BLE_NON_CONNECT_EVT /* Non connectable undirected advertising */
+typedef UINT8 tBTA_BLE_ADV_EVT;
+
+/* adv tx power level */
+#define BTA_BLE_ADV_TX_POWER_MIN        0           /* minimum tx power */
+#define BTA_BLE_ADV_TX_POWER_LOW        1           /* low tx power     */
+#define BTA_BLE_ADV_TX_POWER_MID        2           /* middle tx power  */
+#define BTA_BLE_ADV_TX_POWER_UPPER      3           /* upper tx power   */
+#define BTA_BLE_ADV_TX_POWER_MAX        4           /* maximum tx power */
+typedef UINT8 tBTA_BLE_ADV_TX_POWER;
+
+/* advertising instance parameters */
+typedef struct
+{
+    UINT16                  adv_int_min;            /* minimum adv interval */
+    UINT16                  adv_int_max;            /* maximum adv interval */
+    tBTA_BLE_ADV_EVT        adv_type;               /* adv event type */
+    tBTA_BLE_ADV_CHNL_MAP   channel_map;            /* adv channel map */
+    tBTA_BLE_AFP            adv_filter_policy;      /* advertising filter policy */
+    tBTA_BLE_ADV_TX_POWER   tx_power;               /* adv tx power */
+}tBTA_BLE_ADV_PARAMS;
+
+/* These are the fields returned in each device adv packet.  It
+** is returned in the results callback if registered.
+*/
+typedef struct
+{
+    UINT8               conn_mode;
+    tBTA_BLE_AD_MASK    ad_mask;        /* mask of the valid adv data field */
+    UINT8               flag;
+    UINT8               tx_power_level;
+    UINT8               remote_name_len;
+    UINT8               *p_remote_name;
+    tBTA_BLE_SERVICE    service;
+} tBTA_BLE_INQ_DATA;
+
+enum
+{
+    BTA_BLE_BATCH_SCAN_MODE_PASS = 1,
+    BTA_BLE_BATCH_SCAN_MODE_ACTI = 2,
+    BTA_BLE_BATCH_SCAN_MODE_PASS_ACTI = 3
+};
+typedef UINT8 tBTA_BLE_BATCH_SCAN_MODE;
+
+enum
+{
+    BTA_BLE_DISCARD_OLD_ITEMS=0,
+    BTA_BLE_DISCARD_LOWER_RSSI_ITEMS=1
+};
+typedef UINT8 tBTA_BLE_DISCARD_RULE;
+
+enum
+{
+    BTA_BLE_ADV_SEEN_FIRST_TIME=0,
+    BTA_BLE_ADV_TRACKING_TIMEOUT=1
+};
+typedef UINT8 tBTA_BLE_ADV_CHANGE_REASON;
+
+enum
+{
+    BTA_BLE_BATCH_SCAN_ENB_EVT      = 1,
+    BTA_BLE_BATCH_SCAN_CFG_STRG_EVT = 2,
+    BTA_BLE_BATCH_SCAN_DATA_EVT     = 3,
+    BTA_BLE_BATCH_SCAN_THRES_EVT    = 4,
+    BTA_BLE_BATCH_SCAN_PARAM_EVT    = 5,
+    BTA_BLE_BATCH_SCAN_DIS_EVT      = 6
+};
+typedef tBTM_BLE_BATCH_SCAN_EVT tBTA_BLE_BATCH_SCAN_EVT;
+
+typedef tBTM_BLE_TRACK_ADV_ACTION tBTA_BLE_TRACK_ADV_ACTION;
+#endif
+
+/* BLE customer specific feature function type definitions */
+/* data type used on customer specific feature for RSSI monitoring */
+#define BTA_BLE_RSSI_ALERT_HI        0
+#define BTA_BLE_RSSI_ALERT_RANGE     1
+#define BTA_BLE_RSSI_ALERT_LO        2
+typedef UINT8 tBTA_DM_BLE_RSSI_ALERT_TYPE;
+
+#define BTA_BLE_RSSI_ALERT_NONE         BTM_BLE_RSSI_ALERT_NONE         /*    (0) */
+#define BTA_BLE_RSSI_ALERT_HI_BIT       BTM_BLE_RSSI_ALERT_HI_BIT       /*    (1) */
+#define BTA_BLE_RSSI_ALERT_RANGE_BIT    BTM_BLE_RSSI_ALERT_RANGE_BIT    /*    (1 << 1) */
+#define BTA_BLE_RSSI_ALERT_LO_BIT       BTM_BLE_RSSI_ALERT_LO_BIT       /*    (1 << 2) */
+typedef UINT8     tBTA_DM_BLE_RSSI_ALERT_MASK;
+
+
+typedef void (tBTA_DM_BLE_RSSI_CBACK) (BD_ADDR bd_addr, tBTA_DM_BLE_RSSI_ALERT_TYPE alert_type, INT8 rssi);
+
+/* max number of filter spot for different filter type */
+#define BTA_DM_BLE_MAX_UUID_FILTER     BTM_BLE_MAX_UUID_FILTER    /* 8 */
+#define BTA_DM_BLE_MAX_ADDR_FILTER     BTM_BLE_MAX_ADDR_FILTER    /* 8 */
+#define BTA_DM_BLE_PF_STR_COND_MAX     BTM_BLE_PF_STR_COND_MAX    /* 4    apply to manu data , or local name */
+#define BTA_DM_BLE_PF_STR_LEN_MAX      BTM_BLE_PF_STR_LEN_MAX     /* match for first 20 bytes */
+
+#define BTA_DM_BLE_PF_LOGIC_OR              0
+#define BTA_DM_BLE_PF_LOGIC_AND             1
+typedef UINT8 tBTA_DM_BLE_PF_LOGIC_TYPE;
+
+enum
+{
+    BTA_DM_BLE_SCAN_COND_ADD,
+    BTA_DM_BLE_SCAN_COND_DELETE,
+    BTA_DM_BLE_SCAN_COND_CLEAR = 2
+};
+typedef UINT8 tBTA_DM_BLE_SCAN_COND_OP;
+
+/* ADV payload filtering vendor specific call event */
+enum
+{
+    BTA_BLE_SCAN_PF_ENABLE_EVT = 7,
+    BTA_BLE_SCAN_PF_COND_EVT
+};
+
+/* filter selection bit index  */
+#define BTA_DM_BLE_PF_ADDR_FILTER          BTM_BLE_PF_ADDR_FILTER
+#define BTA_DM_BLE_PF_SRVC_DATA            BTM_BLE_PF_SRVC_DATA
+#define BTA_DM_BLE_PF_SRVC_UUID            BTM_BLE_PF_SRVC_UUID
+#define BTA_DM_BLE_PF_SRVC_SOL_UUID        BTM_BLE_PF_SRVC_SOL_UUID
+#define BTA_DM_BLE_PF_LOCAL_NAME           BTM_BLE_PF_LOCAL_NAME
+#define BTA_DM_BLE_PF_MANU_DATA            BTM_BLE_PF_MANU_DATA
+#define BTA_DM_BLE_PF_SRVC_DATA_PATTERN    BTM_BLE_PF_SRVC_DATA_PATTERN
+#define BTA_DM_BLE_PF_TYPE_ALL             BTM_BLE_PF_TYPE_ALL
+#define BTA_DM_BLE_PF_TYPE_MAX             BTM_BLE_PF_TYPE_MAX
+typedef UINT8   tBTA_DM_BLE_PF_COND_TYPE;
+
+typedef union
+{
+      UINT16              uuid16_mask;
+      UINT32              uuid32_mask;
+      UINT8               uuid128_mask[LEN_UUID_128];
+}tBTA_DM_BLE_PF_COND_MASK;
+
+typedef struct
+{
+    tBLE_BD_ADDR                *p_target_addr;     /* target address, if NULL, generic UUID filter */
+    tBT_UUID                    uuid;           /* UUID condition */
+    tBTA_DM_BLE_PF_LOGIC_TYPE   cond_logic;    /* AND/OR */
+    tBTA_DM_BLE_PF_COND_MASK    *p_uuid_mask;           /* UUID condition mask, if NULL, match exact as UUID condition */
+}tBTA_DM_BLE_PF_UUID_COND;
+
+typedef struct
+{
+    UINT8                   data_len;       /* <= 20 bytes */
+    UINT8                   *p_data;
+}tBTA_DM_BLE_PF_LOCAL_NAME_COND;
+
+typedef struct
+{
+    UINT16                  company_id;     /* company ID */
+    UINT8                   data_len;       /* <= 20 bytes */
+    UINT8                   *p_pattern;
+    UINT16                  company_id_mask; /* UUID value mask */
+    UINT8                   *p_pattern_mask; /* Manufacturer data matching mask, same length
+                                                as data pattern, set to all 0xff, match exact data */
+}tBTA_DM_BLE_PF_MANU_COND;
+
+typedef struct
+{
+    UINT16                  uuid;     /* service ID */
+    UINT8                   data_len;       /* <= 20 bytes */
+    UINT8                   *p_pattern;
+    UINT8                   *p_pattern_mask; /* Service data matching mask, same length
+                                                as data pattern, set to all 0xff, match exact data */
+}tBTA_DM_BLE_PF_SRVC_PATTERN_COND;
+
+typedef union
+{
+    tBLE_BD_ADDR                            target_addr;
+    tBTA_DM_BLE_PF_LOCAL_NAME_COND             local_name; /* lcoal name filtering */
+    tBTA_DM_BLE_PF_MANU_COND                   manu_data;  /* manufactuer data filtering */
+    tBTA_DM_BLE_PF_UUID_COND                   srvc_uuid;  /* service UUID filtering */
+    tBTA_DM_BLE_PF_UUID_COND                   solicitate_uuid;   /* solicitated service UUID filtering */
+    tBTA_DM_BLE_PF_SRVC_PATTERN_COND           srvc_data;      /* service data pattern */
+}tBTA_DM_BLE_PF_COND_PARAM;
+
+typedef UINT8 tBTA_DM_BLE_PF_FILT_INDEX;
+typedef UINT8 tBTA_DM_BLE_PF_AVBL_SPACE;
+
+typedef INT8 tBTA_DM_RSSI_VALUE;
+typedef UINT8 tBTA_DM_LINK_QUALITY_VALUE;
+
+
+typedef UINT8 tBTA_SIG_STRENGTH_MASK;
+
+
+/* Security Callback Events */
+#define BTA_DM_ENABLE_EVT               0       /* Enable Event */
+#define BTA_DM_DISABLE_EVT              1       /* Disable Event */
+#define BTA_DM_PIN_REQ_EVT              2       /* PIN request. */
+#define BTA_DM_AUTH_CMPL_EVT            3       /* Authentication complete indication. */
+#define BTA_DM_AUTHORIZE_EVT            4       /* Authorization request. */
+#define BTA_DM_LINK_UP_EVT              5       /* Connection UP event */
+#define BTA_DM_LINK_DOWN_EVT            6       /* Connection DOWN event */
+#define BTA_DM_SIG_STRENGTH_EVT         7       /* Signal strength for bluetooth connection */
+#define BTA_DM_BUSY_LEVEL_EVT           8       /* System busy level */
+#define BTA_DM_BOND_CANCEL_CMPL_EVT     9       /* Bond cancel complete indication */
+#define BTA_DM_SP_CFM_REQ_EVT           10      /* Simple Pairing User Confirmation request. */
+#define BTA_DM_SP_KEY_NOTIF_EVT         11      /* Simple Pairing Passkey Notification */
+#define BTA_DM_SP_RMT_OOB_EVT           12      /* Simple Pairing Remote OOB Data request. */
+#define BTA_DM_SP_KEYPRESS_EVT          13      /* Key press notification event. */
+#define BTA_DM_ROLE_CHG_EVT             14      /* Role Change event. */
+#define BTA_DM_BLE_KEY_EVT              15      /* BLE SMP key event for peer device keys */
+#define BTA_DM_BLE_SEC_REQ_EVT          16      /* BLE SMP security request */
+#define BTA_DM_BLE_PASSKEY_NOTIF_EVT    17      /* SMP passkey notification event */
+#define BTA_DM_BLE_PASSKEY_REQ_EVT      18      /* SMP passkey request event */
+#define BTA_DM_BLE_OOB_REQ_EVT          19      /* SMP OOB request event */
+#define BTA_DM_BLE_LOCAL_IR_EVT         20      /* BLE local IR event */
+#define BTA_DM_BLE_LOCAL_ER_EVT         21      /* BLE local ER event */
+#define BTA_DM_BLE_NC_REQ_EVT           22      /* SMP Numeric Comparison request event */
+// btla-specific ++
+#define BTA_DM_SP_RMT_OOB_EXT_EVT       23      /* Simple Pairing Remote OOB Extended Data request. */
+#define BTA_DM_BLE_AUTH_CMPL_EVT        24      /* BLE Auth complete */
+// btla-specific --
+#define BTA_DM_DEV_UNPAIRED_EVT         25
+#define BTA_DM_HW_ERROR_EVT             26      /* BT Chip H/W error */
+#define BTA_DM_LE_FEATURES_READ         27      /* Cotroller specific LE features are read */
+#define BTA_DM_ENER_INFO_READ           28      /* Energy info read */
+typedef UINT8 tBTA_DM_SEC_EVT;
+
+/* Structure associated with BTA_DM_ENABLE_EVT */
+typedef struct
+{
+    tBTA_STATUS    status;
+} tBTA_DM_ENABLE;
+
+/* Structure associated with BTA_DM_PIN_REQ_EVT */
+typedef struct
+{
+    /* Note: First 3 data members must be, bd_addr, dev_class, and bd_name in order */
+    BD_ADDR         bd_addr;            /* BD address peer device. */
+    DEV_CLASS       dev_class;          /* Class of Device */
+    BD_NAME         bd_name;            /* Name of peer device. */
+    BOOLEAN         min_16_digit;       /* TRUE if the pin returned must be at least 16 digits */
+} tBTA_DM_PIN_REQ;
+
+/* BLE related definition */
+
+#define BTA_DM_AUTH_FAIL_BASE                   (HCI_ERR_MAX_ERR + 10)
+#define BTA_DM_AUTH_CONVERT_SMP_CODE(x)        (BTA_DM_AUTH_FAIL_BASE + (x))
+#define BTA_DM_AUTH_SMP_PASSKEY_FAIL             BTA_DM_AUTH_CONVERT_SMP_CODE (SMP_PASSKEY_ENTRY_FAIL)
+#define BTA_DM_AUTH_SMP_OOB_FAIL                (BTA_DM_AUTH_FAIL_BASE + SMP_OOB_FAIL)
+#define BTA_DM_AUTH_SMP_PAIR_AUTH_FAIL          (BTA_DM_AUTH_FAIL_BASE + SMP_PAIR_AUTH_FAIL)
+#define BTA_DM_AUTH_SMP_CONFIRM_VALUE_FAIL      (BTA_DM_AUTH_FAIL_BASE + SMP_CONFIRM_VALUE_ERR)
+#define BTA_DM_AUTH_SMP_PAIR_NOT_SUPPORT        (BTA_DM_AUTH_FAIL_BASE + SMP_PAIR_NOT_SUPPORT)
+#define BTA_DM_AUTH_SMP_ENC_KEY_SIZE            (BTA_DM_AUTH_FAIL_BASE + SMP_ENC_KEY_SIZE)
+#define BTA_DM_AUTH_SMP_INVALID_CMD             (BTA_DM_AUTH_FAIL_BASE + SMP_INVALID_CMD)
+#define BTA_DM_AUTH_SMP_UNKNOWN_ERR             (BTA_DM_AUTH_FAIL_BASE + SMP_PAIR_FAIL_UNKNOWN)
+#define BTA_DM_AUTH_SMP_REPEATED_ATTEMPT        (BTA_DM_AUTH_FAIL_BASE + SMP_REPEATED_ATTEMPTS)
+#define BTA_DM_AUTH_SMP_INVALID_PARAMETERS      (BTA_DM_AUTH_FAIL_BASE + SMP_INVALID_PARAMETERS)
+#define BTA_DM_AUTH_SMP_INTERNAL_ERR            (BTA_DM_AUTH_FAIL_BASE + SMP_PAIR_INTERNAL_ERR)
+#define BTA_DM_AUTH_SMP_UNKNOWN_IO              (BTA_DM_AUTH_FAIL_BASE + SMP_UNKNOWN_IO_CAP)
+#define BTA_DM_AUTH_SMP_INIT_FAIL               (BTA_DM_AUTH_FAIL_BASE + SMP_INIT_FAIL)
+#define BTA_DM_AUTH_SMP_CONFIRM_FAIL            (BTA_DM_AUTH_FAIL_BASE + SMP_CONFIRM_FAIL)
+#define BTA_DM_AUTH_SMP_BUSY                    (BTA_DM_AUTH_FAIL_BASE + SMP_BUSY)
+#define BTA_DM_AUTH_SMP_ENC_FAIL                (BTA_DM_AUTH_FAIL_BASE + SMP_ENC_FAIL)
+#define BTA_DM_AUTH_SMP_RSP_TIMEOUT             (BTA_DM_AUTH_FAIL_BASE + SMP_RSP_TIMEOUT)
+
+/* connection parameter boundary value and dummy value */
+#define BTA_DM_BLE_SCAN_INT_MIN          BTM_BLE_SCAN_INT_MIN
+#define BTA_DM_BLE_SCAN_INT_MAX          BTM_BLE_SCAN_INT_MAX
+#define BTA_DM_BLE_SCAN_WIN_MIN          BTM_BLE_SCAN_WIN_MIN
+#define BTA_DM_BLE_SCAN_WIN_MAX          BTM_BLE_SCAN_WIN_MAX
+#define BTA_DM_BLE_CONN_INT_MIN          BTM_BLE_CONN_INT_MIN
+#define BTA_DM_BLE_CONN_INT_MAX          BTM_BLE_CONN_INT_MAX
+#define BTA_DM_BLE_CONN_LATENCY_MAX      BTM_BLE_CONN_LATENCY_MAX
+#define BTA_DM_BLE_CONN_SUP_TOUT_MIN     BTM_BLE_CONN_SUP_TOUT_MIN
+#define BTA_DM_BLE_CONN_SUP_TOUT_MAX     BTM_BLE_CONN_SUP_TOUT_MAX
+#define BTA_DM_BLE_CONN_PARAM_UNDEF      BTM_BLE_CONN_PARAM_UNDEF  /* use this value when a specific value not to be overwritten */
+
+
+#define BTA_LE_KEY_PENC      BTM_LE_KEY_PENC  /* encryption information of peer device */
+#define BTA_LE_KEY_PID       BTM_LE_KEY_PID   /* identity key of the peer device */
+#define BTA_LE_KEY_PCSRK     BTM_LE_KEY_PCSRK   /* peer SRK */
+#define BTA_LE_KEY_LENC      BTM_LE_KEY_LENC        /* master role security information:div */
+#define BTA_LE_KEY_LID       BTM_LE_KEY_LID         /* master device ID key */
+#define BTA_LE_KEY_LCSRK     BTM_LE_KEY_LCSRK        /* local CSRK has been deliver to peer */
+typedef UINT8 tBTA_LE_KEY_TYPE; /* can be used as a bit mask */
+
+
+typedef tBTM_LE_PENC_KEYS  tBTA_LE_PENC_KEYS ;
+typedef tBTM_LE_PCSRK_KEYS tBTA_LE_PCSRK_KEYS;
+typedef tBTM_LE_LENC_KEYS  tBTA_LE_LENC_KEYS  ;
+typedef tBTM_LE_LCSRK_KEYS tBTA_LE_LCSRK_KEYS ;
+typedef tBTM_LE_PID_KEYS   tBTA_LE_PID_KEYS ;
+
+typedef union
+{
+    tBTA_LE_PENC_KEYS   penc_key;       /* received peer encryption key */
+    tBTA_LE_PCSRK_KEYS  psrk_key;       /* received peer device SRK */
+    tBTA_LE_PID_KEYS    pid_key;        /* peer device ID key */
+    tBTA_LE_LENC_KEYS   lenc_key;       /* local encryption reproduction keys LTK = = d1(ER,DIV,0)*/
+    tBTA_LE_LCSRK_KEYS  lcsrk_key;      /* local device CSRK = d1(ER,DIV,1)*/
+    tBTA_LE_PID_KEYS    lid_key;        /* local device ID key for the particular remote */
+}tBTA_LE_KEY_VALUE;
+
+#define BTA_BLE_LOCAL_KEY_TYPE_ID         1
+#define BTA_BLE_LOCAL_KEY_TYPE_ER         2
+typedef UINT8 tBTA_DM_BLE_LOCAL_KEY_MASK;
+
+typedef struct
+{
+    BT_OCTET16       ir;
+    BT_OCTET16       irk;
+    BT_OCTET16       dhk;
+}tBTA_BLE_LOCAL_ID_KEYS;
+
+#define BTA_DM_SEC_GRANTED              BTA_SUCCESS
+#define BTA_DM_SEC_PAIR_NOT_SPT         BTA_DM_AUTH_SMP_PAIR_NOT_SUPPORT
+#define BTA_DM_SEC_REP_ATTEMPTS         BTA_DM_AUTH_SMP_REPEATED_ATTEMPT
+typedef UINT8 tBTA_DM_BLE_SEC_GRANT;
+
+
+#define BTA_DM_BLE_ONN_NONE             BTM_BLE_CONN_NONE
+#define BTA_DM_BLE_CONN_AUTO            BTM_BLE_CONN_AUTO
+#define BTA_DM_BLE_CONN_SELECTIVE       BTM_BLE_CONN_SELECTIVE
+typedef UINT8 tBTA_DM_BLE_CONN_TYPE;
+
+typedef BOOLEAN (tBTA_DM_BLE_SEL_CBACK)(BD_ADDR random_bda, UINT8 *p_remote_name);
+
+/* Structure associated with BTA_DM_BLE_SEC_REQ_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;        /* peer address */
+    BD_NAME         bd_name;        /* peer device name */
+} tBTA_DM_BLE_SEC_REQ;
+
+typedef struct
+{
+    BD_ADDR                 bd_addr;        /* peer address */
+    tBTM_LE_KEY_TYPE        key_type;
+    tBTM_LE_KEY_VALUE       *p_key_value;
+}tBTA_DM_BLE_KEY;
+
+/* Structure associated with BTA_DM_AUTH_CMPL_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;            /* BD address peer device. */
+    BD_NAME         bd_name;            /* Name of peer device. */
+    BOOLEAN         key_present;        /* Valid link key value in key element */
+    LINK_KEY        key;                /* Link key associated with peer device. */
+    UINT8           key_type;           /* The type of Link Key */
+    BOOLEAN         success;            /* TRUE of authentication succeeded, FALSE if failed. */
+    UINT8           fail_reason;        /* The HCI reason/error code for when success=FALSE */
+    tBLE_ADDR_TYPE  addr_type;          /* Peer device address type */
+    tBT_DEVICE_TYPE dev_type;
+} tBTA_DM_AUTH_CMPL;
+
+
+/* Structure associated with BTA_DM_AUTHORIZE_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;            /* BD address peer device. */
+    BD_NAME         bd_name;            /* Name of peer device. */
+    tBTA_SERVICE_ID service;            /* Service ID to authorize. */
+// btla-specific ++
+    DEV_CLASS      dev_class;
+// btla-specific --
+} tBTA_DM_AUTHORIZE;
+
+/* Structure associated with BTA_DM_LINK_UP_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;            /* BD address peer device. */
+#if BLE_INCLUDED == TRUE
+    tBTA_TRANSPORT  link_type;
+#endif
+} tBTA_DM_LINK_UP;
+
+/* Structure associated with BTA_DM_LINK_DOWN_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;            /* BD address peer device. */
+    UINT8           status;             /* connection open/closed */
+    BOOLEAN         is_removed;         /* TRUE if device is removed when link is down */
+#if BLE_INCLUDED == TRUE
+    tBTA_TRANSPORT  link_type;
+#endif
+} tBTA_DM_LINK_DOWN;
+
+/* Structure associated with BTA_DM_ROLE_CHG_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;            /* BD address peer device. */
+    UINT8           new_role;           /* the new connection role */
+} tBTA_DM_ROLE_CHG;
+
+/* Structure associated with BTA_DM_BUSY_LEVEL_EVT */
+typedef struct
+{
+    UINT8           level;     /* when paging or inquiring, level is 10.
+                                    Otherwise, the number of ACL links */
+    UINT8           level_flags; /* indicates individual flags */
+} tBTA_DM_BUSY_LEVEL;
+
+#define BTA_IO_CAP_OUT      BTM_IO_CAP_OUT      /* 0 DisplayOnly */
+#define BTA_IO_CAP_IO       BTM_IO_CAP_IO       /* 1 DisplayYesNo */
+#define BTA_IO_CAP_IN       BTM_IO_CAP_IN       /* 2 KeyboardOnly */
+#define BTA_IO_CAP_NONE     BTM_IO_CAP_NONE     /* 3 NoInputNoOutput */
+#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
+#define BTA_IO_CAP_KBDISP   BTM_IO_CAP_KBDISP   /* 4 Keyboard display */
+#endif
+typedef tBTM_IO_CAP     tBTA_IO_CAP;
+
+#define BTA_AUTH_SP_NO    BTM_AUTH_SP_NO      /* 0 MITM Protection Not Required - Single Profile/non-bonding
+                                                Numeric comparison with automatic accept allowed */
+#define BTA_AUTH_SP_YES   BTM_AUTH_SP_YES     /* 1 MITM Protection Required - Single Profile/non-bonding
+                                                Use IO Capabilities to determine authentication procedure */
+#define BTA_AUTH_AP_NO    BTM_AUTH_AP_NO      /* 2 MITM Protection Not Required - All Profiles/dedicated bonding
+                                                Numeric comparison with automatic accept allowed */
+#define BTA_AUTH_AP_YES   BTM_AUTH_AP_YES     /* 3 MITM Protection Required - All Profiles/dedicated bonding
+                                                Use IO Capabilities to determine authentication procedure */
+#define BTA_AUTH_SPGB_NO  BTM_AUTH_SPGB_NO    /* 4 MITM Protection Not Required - Single Profiles/general bonding
+                                                Numeric comparison with automatic accept allowed */
+#define BTA_AUTH_SPGB_YES BTM_AUTH_SPGB_YES   /* 5 MITM Protection Required - Single Profiles/general bonding
+                                                Use IO Capabilities to determine authentication procedure */
+typedef tBTM_AUTH_REQ   tBTA_AUTH_REQ;
+
+#define BTA_AUTH_DD_BOND    BTM_AUTH_DD_BOND  /* 2 this bit is set for dedicated bonding */
+#define BTA_AUTH_GEN_BOND   BTM_AUTH_SPGB_NO  /* 4 this bit is set for general bonding */
+#define BTA_AUTH_BONDS      BTM_AUTH_BONDS    /* 6 the general/dedicated bonding bits  */
+
+#define BTA_LE_AUTH_NO_BOND    BTM_LE_AUTH_REQ_NO_BOND  /* 0*/
+#define BTA_LE_AUTH_BOND       BTM_LE_AUTH_REQ_BOND     /* 1 << 0 */
+#define BTA_LE_AUTH_REQ_MITM   BTM_LE_AUTH_REQ_MITM    /* 1 << 2 */
+
+#define BTA_LE_AUTH_REQ_SC_ONLY         BTM_LE_AUTH_REQ_SC_ONLY         /* 1 << 3 */
+#define BTA_LE_AUTH_REQ_SC_BOND         BTM_LE_AUTH_REQ_SC_BOND      /* 1001 */
+#define BTA_LE_AUTH_REQ_SC_MITM         BTM_LE_AUTH_REQ_SC_MITM      /* 1100 */
+#define BTA_LE_AUTH_REQ_SC_MITM_BOND    BTM_LE_AUTH_REQ_SC_MITM_BOND /* 1101 */
+typedef tBTM_LE_AUTH_REQ       tBTA_LE_AUTH_REQ;       /* combination of the above bit pattern */
+
+#define BTA_OOB_NONE        BTM_OOB_NONE
+#define BTA_OOB_PRESENT     BTM_OOB_PRESENT
+#if BTM_OOB_INCLUDED == TRUE
+#define BTA_OOB_UNKNOWN     BTM_OOB_UNKNOWN
+#endif
+typedef tBTM_OOB_DATA   tBTA_OOB_DATA;
+
+/* Structure associated with BTA_DM_SP_CFM_REQ_EVT */
+typedef struct
+{
+    /* Note: First 3 data members must be, bd_addr, dev_class, and bd_name in order */
+    BD_ADDR         bd_addr;        /* peer address */
+    DEV_CLASS       dev_class;      /* peer CoD */
+    BD_NAME         bd_name;        /* peer device name */
+    UINT32          num_val;        /* the numeric value for comparison. If just_works, do not show this number to UI */
+    BOOLEAN         just_works;     /* TRUE, if "Just Works" association model */
+    tBTA_AUTH_REQ   loc_auth_req;   /* Authentication required for local device */
+    tBTA_AUTH_REQ   rmt_auth_req;   /* Authentication required for peer device */
+    tBTA_IO_CAP     loc_io_caps;    /* IO Capabilities of local device */
+    tBTA_AUTH_REQ   rmt_io_caps;    /* IO Capabilities of remote device */
+} tBTA_DM_SP_CFM_REQ;
+
+enum
+{
+    BTA_SP_KEY_STARTED,         /* passkey entry started */
+    BTA_SP_KEY_ENTERED,         /* passkey digit entered */
+    BTA_SP_KEY_ERASED,          /* passkey digit erased */
+    BTA_SP_KEY_CLEARED,         /* passkey cleared */
+    BTA_SP_KEY_COMPLT           /* passkey entry completed */
+};
+typedef UINT8   tBTA_SP_KEY_TYPE;
+
+/* Structure associated with BTA_DM_SP_KEYPRESS_EVT */
+typedef struct
+{
+    BD_ADDR             bd_addr;        /* peer address */
+    tBTA_SP_KEY_TYPE   notif_type;
+}tBTA_DM_SP_KEY_PRESS;
+
+/* Structure associated with BTA_DM_SP_KEY_NOTIF_EVT */
+typedef struct
+{
+    /* Note: First 3 data members must be, bd_addr, dev_class, and bd_name in order */
+    BD_ADDR         bd_addr;        /* peer address */
+    DEV_CLASS       dev_class;      /* peer CoD */
+    BD_NAME         bd_name;        /* peer device name */
+    UINT32          passkey;        /* the numeric value for comparison. If just_works, do not show this number to UI */
+} tBTA_DM_SP_KEY_NOTIF;
+
+/* Structure associated with BTA_DM_SP_RMT_OOB_EVT */
+typedef struct
+{
+    /* Note: First 3 data members must be, bd_addr, dev_class, and bd_name in order */
+    BD_ADDR         bd_addr;        /* peer address */
+    DEV_CLASS       dev_class;      /* peer CoD */
+    BD_NAME         bd_name;        /* peer device name */
+} tBTA_DM_SP_RMT_OOB;
+
+/* Structure associated with BTA_DM_BOND_CANCEL_CMPL_EVT */
+typedef struct
+{
+    tBTA_STATUS     result;    /* TRUE of bond cancel succeeded, FALSE if failed. */
+} tBTA_DM_BOND_CANCEL_CMPL;
+
+/* Union of all security callback structures */
+typedef union
+{
+    tBTA_DM_ENABLE      enable;         /* BTA enabled */
+    tBTA_DM_PIN_REQ     pin_req;        /* PIN request. */
+    tBTA_DM_AUTH_CMPL   auth_cmpl;      /* Authentication complete indication. */
+    tBTA_DM_AUTHORIZE   authorize;      /* Authorization request. */
+    tBTA_DM_LINK_UP     link_up;       /* ACL connection down event */
+    tBTA_DM_LINK_DOWN   link_down;       /* ACL connection down event */
+    tBTA_DM_BUSY_LEVEL  busy_level;     /* System busy level */
+    tBTA_DM_SP_CFM_REQ  cfm_req;        /* user confirm request */
+    tBTA_DM_SP_KEY_NOTIF key_notif;     /* passkey notification */
+    tBTA_DM_SP_RMT_OOB  rmt_oob;        /* remote oob */
+    tBTA_DM_BOND_CANCEL_CMPL bond_cancel_cmpl; /* Bond Cancel Complete indication */
+    tBTA_DM_SP_KEY_PRESS   key_press;   /* key press notification event */
+    tBTA_DM_ROLE_CHG     role_chg;       /* role change event */
+    tBTA_DM_BLE_SEC_REQ  ble_req;        /* BLE SMP related request */
+    tBTA_DM_BLE_KEY      ble_key;        /* BLE SMP keys used when pairing */
+    tBTA_BLE_LOCAL_ID_KEYS  ble_id_keys;  /* IR event */
+    BT_OCTET16              ble_er;       /* ER event data */
+} tBTA_DM_SEC;
+
+/* Security callback */
+typedef void (tBTA_DM_SEC_CBACK)(tBTA_DM_SEC_EVT event, tBTA_DM_SEC *p_data);
+
+#define BTA_BLE_MULTI_ADV_ILLEGAL 0
+
+/* multi adv callback event */
+#define BTA_BLE_MULTI_ADV_ENB_EVT           1
+#define BTA_BLE_MULTI_ADV_DISABLE_EVT       2
+#define BTA_BLE_MULTI_ADV_PARAM_EVT         3
+#define BTA_BLE_MULTI_ADV_DATA_EVT          4
+
+typedef UINT8 tBTA_BLE_MULTI_ADV_EVT;
+
+/* multi adv callback */
+typedef void (tBTA_BLE_MULTI_ADV_CBACK)(tBTA_BLE_MULTI_ADV_EVT event,
+                                        UINT8 inst_id, void *p_ref, tBTA_STATUS status);
+typedef UINT32 tBTA_DM_BLE_REF_VALUE;
+
+#define BTA_DM_BLE_PF_ENABLE_EVT       BTM_BLE_PF_ENABLE
+#define BTA_DM_BLE_PF_CONFIG_EVT       BTM_BLE_PF_CONFIG
+typedef UINT8 tBTA_DM_BLE_PF_EVT;
+
+#define BTA_DM_BLE_PF_ENABLE       1
+#define BTA_DM_BLE_PF_CONFIG       2
+typedef UINT8 tBTA_DM_BLE_PF_ACTION;
+
+/* Config callback */
+typedef void (tBTA_DM_BLE_PF_CFG_CBACK) (tBTA_DM_BLE_PF_ACTION action,
+                                         tBTA_DM_BLE_PF_COND_TYPE cfg_cond,
+                                         tBTA_DM_BLE_PF_AVBL_SPACE avbl_space, tBTA_STATUS status,
+                                         tBTA_DM_BLE_REF_VALUE ref_value);
+/* Param callback */
+typedef void (tBTA_DM_BLE_PF_PARAM_CBACK) (UINT8 action_type, tBTA_DM_BLE_PF_AVBL_SPACE avbl_space,
+                                           tBTA_DM_BLE_REF_VALUE ref_value, tBTA_STATUS status);
+
+/* Status callback */
+typedef void (tBTA_DM_BLE_PF_STATUS_CBACK) (UINT8 action, tBTA_STATUS status,
+                                            tBTA_DM_BLE_REF_VALUE ref_value);
+
+
+#define BTA_DM_BLE_PF_BRDCAST_ADDR_FILT  1
+#define BTA_DM_BLE_PF_SERV_DATA_CHG_FILT 2
+#define BTA_DM_BLE_PF_SERV_UUID          4
+#define BTA_DM_BLE_PF_SERV_SOLC_UUID     8
+#define BTA_DM_BLE_PF_LOC_NAME_CHECK    16
+#define BTA_DM_BLE_PF_MANUF_NAME_CHECK  32
+#define BTA_DM_BLE_PF_SERV_DATA_CHECK   64
+typedef UINT16 tBTA_DM_BLE_PF_FEAT_SEL;
+
+#define BTA_DM_BLE_PF_LIST_LOGIC_OR   1
+#define BTA_DM_BLE_PF_LIST_LOGIC_AND  2
+typedef UINT16 tBTA_DM_BLE_PF_LIST_LOGIC_TYPE;
+
+#define BTA_DM_BLE_PF_FILT_LOGIC_OR   0
+#define BTA_DM_BLE_PF_FILT_LOGIC_AND  1
+typedef UINT16 tBTA_DM_BLE_PF_FILT_LOGIC_TYPE;
+
+typedef UINT8  tBTA_DM_BLE_PF_RSSI_THRESHOLD;
+typedef UINT8  tBTA_DM_BLE_PF_DELIVERY_MODE;
+typedef UINT16 tBTA_DM_BLE_PF_TIMEOUT;
+typedef UINT8  tBTA_DM_BLE_PF_TIMEOUT_CNT;
+typedef UINT16 tBTA_DM_BLE_PF_ADV_TRACK_ENTRIES;
+
+typedef struct
+{
+    tBTA_DM_BLE_PF_FEAT_SEL feat_seln;
+    tBTA_DM_BLE_PF_LIST_LOGIC_TYPE list_logic_type;
+    tBTA_DM_BLE_PF_FILT_LOGIC_TYPE filt_logic_type;
+    tBTA_DM_BLE_PF_RSSI_THRESHOLD  rssi_high_thres;
+    tBTA_DM_BLE_PF_RSSI_THRESHOLD  rssi_low_thres;
+    tBTA_DM_BLE_PF_DELIVERY_MODE dely_mode;
+    tBTA_DM_BLE_PF_TIMEOUT found_timeout;
+    tBTA_DM_BLE_PF_TIMEOUT lost_timeout;
+    tBTA_DM_BLE_PF_TIMEOUT_CNT found_timeout_cnt;
+    tBTA_DM_BLE_PF_ADV_TRACK_ENTRIES num_of_tracking_entries;
+} tBTA_DM_BLE_PF_FILT_PARAMS;
+
+/* Search callback events */
+#define BTA_DM_INQ_RES_EVT              0       /* Inquiry result for a peer device. */
+#define BTA_DM_INQ_CMPL_EVT             1       /* Inquiry complete. */
+#define BTA_DM_DISC_RES_EVT             2       /* Discovery result for a peer device. */
+#define BTA_DM_DISC_BLE_RES_EVT         3       /* Discovery result for BLE GATT based servoce on a peer device. */
+#define BTA_DM_DISC_CMPL_EVT            4       /* Discovery complete. */
+#define BTA_DM_DI_DISC_CMPL_EVT         5       /* Discovery complete. */
+#define BTA_DM_SEARCH_CANCEL_CMPL_EVT   6       /* Search cancelled */
+
+typedef UINT8 tBTA_DM_SEARCH_EVT;
+
+#define BTA_DM_INQ_RES_IGNORE_RSSI      BTM_INQ_RES_IGNORE_RSSI /* 0x7f RSSI value not supplied (ignore it) */
+
+/* Structure associated with BTA_DM_INQ_RES_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;                /* BD address peer device. */
+    DEV_CLASS       dev_class;              /* Device class of peer device. */
+    BOOLEAN         remt_name_not_required; /* Application sets this flag if it already knows the name of the device */
+                                            /* If the device name is known to application BTA skips the remote name request */
+    BOOLEAN         is_limited;             /* TRUE, if the limited inquiry bit is set in the CoD */
+    INT8            rssi;                   /* The rssi value */
+    UINT8           *p_eir;                 /* received EIR */
+#if (BLE_INCLUDED == TRUE)
+    UINT8               inq_result_type;
+    UINT8               ble_addr_type;
+    tBTM_BLE_EVT_TYPE   ble_evt_type;
+    tBT_DEVICE_TYPE     device_type;
+    UINT8               flag;
+#endif
+
+} tBTA_DM_INQ_RES;
+
+/* Structure associated with BTA_DM_INQ_CMPL_EVT */
+typedef struct
+{
+    UINT8           num_resps;          /* Number of inquiry responses. */
+} tBTA_DM_INQ_CMPL;
+
+/* Structure associated with BTA_DM_DI_DISC_CMPL_EVT */
+typedef struct
+{
+    BD_ADDR             bd_addr;        /* BD address peer device. */
+    UINT8               num_record;     /* Number of DI record */
+    tBTA_STATUS         result;
+} tBTA_DM_DI_DISC_CMPL;
+
+/* Structure associated with BTA_DM_DISC_RES_EVT */
+typedef struct
+{
+    BD_ADDR             bd_addr;        /* BD address peer device. */
+    BD_NAME             bd_name;        /* Name of peer device. */
+    tBTA_SERVICE_MASK   services;       /* Services found on peer device. */
+// btla-specific ++
+    UINT8           *   p_raw_data;     /* Raw data for discovery DB */
+    UINT32              raw_data_size;  /* size of raw data */
+    tBT_DEVICE_TYPE     device_type;    /* device type in case it is BLE device */
+    UINT32              num_uuids;
+    UINT8               *p_uuid_list;
+// btla-specific --
+    tBTA_STATUS         result;
+} tBTA_DM_DISC_RES;
+
+/* Structure associated with tBTA_DM_DISC_BLE_RES */
+typedef struct
+{
+    BD_ADDR             bd_addr;        /* BD address peer device. */
+    BD_NAME             bd_name;        /* Name of peer device. */
+    tBT_UUID            service;        /* GATT based Services UUID found on peer device. */
+} tBTA_DM_DISC_BLE_RES;
+
+
+/* Union of all search callback structures */
+typedef union
+{
+    tBTA_DM_INQ_RES     inq_res;        /* Inquiry result for a peer device. */
+    tBTA_DM_INQ_CMPL    inq_cmpl;       /* Inquiry complete. */
+    tBTA_DM_DISC_RES    disc_res;       /* Discovery result for a peer device. */
+    tBTA_DM_DISC_BLE_RES    disc_ble_res;   /* discovery result for GATT based service */
+    tBTA_DM_DI_DISC_CMPL    di_disc;        /* DI discovery result for a peer device */
+
+} tBTA_DM_SEARCH;
+
+/* Search callback */
+typedef void (tBTA_DM_SEARCH_CBACK)(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data);
+
+/* Execute call back */
+typedef void (tBTA_DM_EXEC_CBACK) (void * p_param);
+
+/* Encryption callback*/
+typedef void (tBTA_DM_ENCRYPT_CBACK) (BD_ADDR bd_addr, tBTA_TRANSPORT transport, tBTA_STATUS result);
+
+#if BLE_INCLUDED == TRUE
+#define BTA_DM_BLE_SEC_NONE         BTM_BLE_SEC_NONE
+#define BTA_DM_BLE_SEC_ENCRYPT      BTM_BLE_SEC_ENCRYPT
+#define BTA_DM_BLE_SEC_NO_MITM      BTM_BLE_SEC_ENCRYPT_NO_MITM
+#define BTA_DM_BLE_SEC_MITM         BTM_BLE_SEC_ENCRYPT_MITM
+typedef tBTM_BLE_SEC_ACT            tBTA_DM_BLE_SEC_ACT;
+
+typedef tBTM_BLE_TX_TIME_MS         tBTA_DM_BLE_TX_TIME_MS;
+typedef tBTM_BLE_RX_TIME_MS         tBTA_DM_BLE_RX_TIME_MS;
+typedef tBTM_BLE_IDLE_TIME_MS       tBTA_DM_BLE_IDLE_TIME_MS;
+typedef tBTM_BLE_ENERGY_USED        tBTA_DM_BLE_ENERGY_USED;
+
+#define BTA_DM_CONTRL_UNKNOWN 0       /* Unknown state */
+#define BTA_DM_CONTRL_ACTIVE  1       /* ACL link on, SCO link ongoing, sniff mode */
+#define BTA_DM_CONTRL_SCAN    2       /* Scan state - paging/inquiry/trying to connect*/
+#define BTA_DM_CONTRL_IDLE    3       /* Idle state - page scan, LE advt, inquiry scan */
+
+typedef UINT8 tBTA_DM_CONTRL_STATE;
+
+typedef UINT8 tBTA_DM_BLE_ADV_STATE;
+typedef UINT8 tBTA_DM_BLE_ADV_INFO_PRESENT;
+typedef UINT8 tBTA_DM_BLE_RSSI_VALUE;
+typedef UINT16 tBTA_DM_BLE_ADV_INFO_TIMESTAMP;
+
+typedef tBTM_BLE_TRACK_ADV_DATA tBTA_DM_BLE_TRACK_ADV_DATA;
+
+typedef void (tBTA_BLE_SCAN_THRESHOLD_CBACK)(tBTA_DM_BLE_REF_VALUE ref_value);
+
+typedef void (tBTA_BLE_SCAN_REP_CBACK) (tBTA_DM_BLE_REF_VALUE ref_value, UINT8 report_format,
+                                        UINT8 num_records, UINT16 data_len,
+                                        UINT8* p_rep_data, tBTA_STATUS status);
+
+typedef void (tBTA_BLE_SCAN_SETUP_CBACK) (tBTA_BLE_BATCH_SCAN_EVT evt,
+                                          tBTA_DM_BLE_REF_VALUE ref_value,
+                                          tBTA_STATUS status);
+
+typedef void (tBTA_BLE_TRACK_ADV_CMPL_CBACK)(int action, tBTA_STATUS status,
+                                             tBTA_DM_BLE_PF_AVBL_SPACE avbl_space,
+                                             tBTA_DM_BLE_REF_VALUE ref_value);
+
+typedef void (tBTA_BLE_TRACK_ADV_CBACK)(tBTA_DM_BLE_TRACK_ADV_DATA *p_adv_data);
+
+typedef void (tBTA_BLE_ENERGY_INFO_CBACK)(tBTA_DM_BLE_TX_TIME_MS tx_time,
+                                          tBTA_DM_BLE_RX_TIME_MS rx_time,
+                                          tBTA_DM_BLE_IDLE_TIME_MS idle_time,
+                                          tBTA_DM_BLE_ENERGY_USED  energy_used,
+                                          tBTA_DM_CONTRL_STATE ctrl_state,
+                                          tBTA_STATUS status);
+
+#else
+typedef UINT8                       tBTA_DM_BLE_SEC_ACT;
+#endif
+
+/* Maximum service name length */
+#define BTA_SERVICE_NAME_LEN    35
+#define BTA_SERVICE_DESP_LEN    BTA_SERVICE_NAME_LEN
+#define BTA_PROVIDER_NAME_LEN   BTA_SERVICE_NAME_LEN
+
+
+/* link policy masks  */
+#define BTA_DM_LP_SWITCH        HCI_ENABLE_MASTER_SLAVE_SWITCH
+#define BTA_DM_LP_HOLD          HCI_ENABLE_HOLD_MODE
+#define BTA_DM_LP_SNIFF         HCI_ENABLE_SNIFF_MODE
+#define BTA_DM_LP_PARK          HCI_ENABLE_PARK_MODE
+typedef UINT16 tBTA_DM_LP_MASK;
+
+/* power mode actions  */
+#define BTA_DM_PM_NO_ACTION    0x00       /* no change to the current pm setting */
+#define BTA_DM_PM_PARK         0x10       /* prefers park mode */
+#define BTA_DM_PM_SNIFF        0x20       /* prefers sniff mode */
+#define BTA_DM_PM_SNIFF1       0x21       /* prefers sniff1 mode */
+#define BTA_DM_PM_SNIFF2       0x22       /* prefers sniff2 mode */
+#define BTA_DM_PM_SNIFF3       0x23       /* prefers sniff3 mode */
+#define BTA_DM_PM_SNIFF4       0x24       /* prefers sniff4 mode */
+#define BTA_DM_PM_SNIFF5       0x25       /* prefers sniff5 mode */
+#define BTA_DM_PM_SNIFF6       0x26       /* prefers sniff6 mode */
+#define BTA_DM_PM_SNIFF7       0x27       /* prefers sniff7 mode */
+#define BTA_DM_PM_SNIFF_USER0  0x28       /* prefers user-defined sniff0 mode (testtool only) */
+#define BTA_DM_PM_SNIFF_USER1  0x29       /* prefers user-defined sniff1 mode (testtool only) */
+#define BTA_DM_PM_ACTIVE       0x40       /* prefers active mode */
+#define BTA_DM_PM_RETRY        0x80       /* retry power mode based on current settings */
+#define BTA_DM_PM_SUSPEND      0x04       /* prefers suspend mode */
+#define BTA_DM_PM_NO_PREF      0x01       /* service has no prefernce on power mode setting. eg. connection to service got closed */
+
+typedef UINT8 tBTA_DM_PM_ACTION;
+
+/* index to bta_dm_ssr_spec */
+#define BTA_DM_PM_SSR0          0
+#define BTA_DM_PM_SSR1          1       /* BTA_DM_PM_SSR1 will be dedicated for
+                                        HH SSR setting entry, no other profile can use it */
+#define BTA_DM_PM_SSR2          2
+#define BTA_DM_PM_SSR3          3
+#define BTA_DM_PM_SSR4          4
+#define BTA_DM_PM_SSR5          5
+#define BTA_DM_PM_SSR6          6
+
+#define BTA_DM_PM_NUM_EVTS      9
+
+#ifndef BTA_DM_PM_PARK_IDX
+#define BTA_DM_PM_PARK_IDX      5 /* the actual index to bta_dm_pm_md[] for PARK mode */
+#endif
+
+#ifndef BTA_DM_PM_SNIFF_A2DP_IDX
+#define BTA_DM_PM_SNIFF_A2DP_IDX      BTA_DM_PM_SNIFF
+#endif
+
+#ifndef BTA_DM_PM_SNIFF_HD_IDLE_IDX
+#define BTA_DM_PM_SNIFF_HD_IDLE_IDX   BTA_DM_PM_SNIFF2
+#endif
+
+#ifndef BTA_DM_PM_SNIFF_SCO_OPEN_IDX
+#define BTA_DM_PM_SNIFF_SCO_OPEN_IDX  BTA_DM_PM_SNIFF3
+#endif
+
+#ifndef BTA_DM_PM_SNIFF_HD_ACTIVE_IDX
+#define BTA_DM_PM_SNIFF_HD_ACTIVE_IDX BTA_DM_PM_SNIFF4
+#endif
+
+#ifndef BTA_DM_PM_SNIFF_HH_OPEN_IDX
+#define BTA_DM_PM_SNIFF_HH_OPEN_IDX BTA_DM_PM_SNIFF2
+#endif
+
+#ifndef BTA_DM_PM_SNIFF_HH_ACTIVE_IDX
+#define BTA_DM_PM_SNIFF_HH_ACTIVE_IDX BTA_DM_PM_SNIFF2
+#endif
+
+#ifndef BTA_DM_PM_SNIFF_HH_IDLE_IDX
+#define BTA_DM_PM_SNIFF_HH_IDLE_IDX BTA_DM_PM_SNIFF2
+#endif
+
+
+#ifndef BTA_DM_PM_HH_OPEN_DELAY
+#define BTA_DM_PM_HH_OPEN_DELAY 30000
+#endif
+
+#ifndef BTA_DM_PM_HH_ACTIVE_DELAY
+#define BTA_DM_PM_HH_ACTIVE_DELAY 30000
+#endif
+
+#ifndef BTA_DM_PM_HH_IDLE_DELAY
+#define BTA_DM_PM_HH_IDLE_DELAY 30000
+#endif
+
+/* The Sniff Parameters defined below must be ordered from highest
+ * latency (biggest interval) to lowest latency.  If there is a conflict
+ * among the connected services the setting with the lowest latency will
+ * be selected.  If a device should override a sniff parameter then it
+ * must insure that order is maintained.
+ */
+#ifndef BTA_DM_PM_SNIFF_MAX
+#define BTA_DM_PM_SNIFF_MAX      800
+#define BTA_DM_PM_SNIFF_MIN      400
+#define BTA_DM_PM_SNIFF_ATTEMPT  4
+#define BTA_DM_PM_SNIFF_TIMEOUT  1
+#endif
+
+#ifndef BTA_DM_PM_SNIFF1_MAX
+#define BTA_DM_PM_SNIFF1_MAX     400
+#define BTA_DM_PM_SNIFF1_MIN     200
+#define BTA_DM_PM_SNIFF1_ATTEMPT 4
+#define BTA_DM_PM_SNIFF1_TIMEOUT 1
+#endif
+
+#ifndef BTA_DM_PM_SNIFF2_MAX
+#define BTA_DM_PM_SNIFF2_MAX     180
+#define BTA_DM_PM_SNIFF2_MIN     150
+#define BTA_DM_PM_SNIFF2_ATTEMPT 4
+#define BTA_DM_PM_SNIFF2_TIMEOUT 1
+#endif
+
+#ifndef BTA_DM_PM_SNIFF3_MAX
+#define BTA_DM_PM_SNIFF3_MAX     150
+#define BTA_DM_PM_SNIFF3_MIN     50
+#define BTA_DM_PM_SNIFF3_ATTEMPT 4
+#define BTA_DM_PM_SNIFF3_TIMEOUT 1
+#endif
+
+#ifndef BTA_DM_PM_SNIFF4_MAX
+#define BTA_DM_PM_SNIFF4_MAX     54
+#define BTA_DM_PM_SNIFF4_MIN     30
+#define BTA_DM_PM_SNIFF4_ATTEMPT 4
+#define BTA_DM_PM_SNIFF4_TIMEOUT 1
+#endif
+
+#ifndef BTA_DM_PM_SNIFF5_MAX
+#define BTA_DM_PM_SNIFF5_MAX     36
+#define BTA_DM_PM_SNIFF5_MIN     30
+#define BTA_DM_PM_SNIFF5_ATTEMPT 2
+#define BTA_DM_PM_SNIFF5_TIMEOUT 0
+#endif
+
+#ifndef BTA_DM_PM_PARK_MAX
+#define BTA_DM_PM_PARK_MAX       800
+#define BTA_DM_PM_PARK_MIN       400
+#define BTA_DM_PM_PARK_ATTEMPT   0
+#define BTA_DM_PM_PARK_TIMEOUT   0
+#endif
+
+
+/* Switch callback events */
+#define BTA_DM_SWITCH_CMPL_EVT      0       /* Completion of the Switch API */
+
+typedef UINT8 tBTA_DM_SWITCH_EVT;
+typedef void (tBTA_DM_SWITCH_CBACK)(tBTA_DM_SWITCH_EVT event, tBTA_STATUS status);
+
+/* Audio routing out configuration */
+#define BTA_DM_ROUTE_NONE       0x00    /* No Audio output */
+#define BTA_DM_ROUTE_DAC        0x01    /* routing over analog output */
+#define BTA_DM_ROUTE_I2S        0x02    /* routing over digital (I2S) output */
+#define BTA_DM_ROUTE_BT_MONO    0x04    /* routing over SCO */
+#define BTA_DM_ROUTE_BT_STEREO  0x08    /* routing over BT Stereo */
+#define BTA_DM_ROUTE_HOST       0x10    /* routing over Host */
+#define BTA_DM_ROUTE_FMTX       0x20    /* routing over FMTX */
+#define BTA_DM_ROUTE_FMRX       0x40    /* routing over FMRX */
+#define BTA_DM_ROUTE_BTSNK      0x80    /* routing over BT SNK */
+
+typedef UINT8 tBTA_DM_ROUTE_PATH;
+
+
+/* Device Identification (DI) data structure
+*/
+/* Used to set the DI record */
+typedef tSDP_DI_RECORD          tBTA_DI_RECORD;
+/* Used to get the DI record */
+typedef tSDP_DI_GET_RECORD      tBTA_DI_GET_RECORD;
+/* SDP discovery database */
+typedef tSDP_DISCOVERY_DB       tBTA_DISCOVERY_DB;
+
+#ifndef         BTA_DI_NUM_MAX
+#define         BTA_DI_NUM_MAX       3
+#endif
+
+/* Device features mask definitions */
+#define BTA_FEATURE_BYTES_PER_PAGE  BTM_FEATURE_BYTES_PER_PAGE
+#define BTA_EXT_FEATURES_PAGE_MAX   BTM_EXT_FEATURES_PAGE_MAX
+/* ACL type
+*/
+#define BTA_DM_LINK_TYPE_BR_EDR    0x01
+#define BTA_DM_LINK_TYPE_LE        0x02
+#define BTA_DM_LINK_TYPE_ALL       0xFF
+typedef UINT8 tBTA_DM_LINK_TYPE;
+
+#define IMMEDIATE_DELY_MODE  0x00
+#define ONFOUND_DELY_MODE    0x01
+#define BATCH_DELY_MODE      0x02
+#define ALLOW_ALL_FILTER     0x00
+#define LOWEST_RSSI_VALUE     129
+
+/*****************************************************************************
+**  External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function         BTA_EnableBluetooth
+**
+** Description      This function initializes BTA and prepares BTA and the
+**                  Bluetooth protocol stack for use.  This function is
+**                  typically called at startup or when Bluetooth services
+**                  are required by the phone.  This function must be called
+**                  before calling any other API function.
+**
+**
+** Returns          BTA_SUCCESS if successful.
+**                  BTA_FAIL if internal failure.
+**
+*******************************************************************************/
+extern tBTA_STATUS BTA_EnableBluetooth(tBTA_DM_SEC_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_DisableBluetooth
+**
+** Description      This function disables BTA and the Bluetooth protocol
+**                  stack.  It is called when BTA is no longer being used
+**                  by any application in the system.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+extern tBTA_STATUS BTA_DisableBluetooth(void);
+
+/*******************************************************************************
+**
+** Function         BTA_EnableTestMode
+**
+** Description      Enables bluetooth device under test mode
+**
+**
+** Returns          tBTA_STATUS
+**
+*******************************************************************************/
+extern tBTA_STATUS BTA_EnableTestMode(void);
+
+/*******************************************************************************
+**
+** Function         BTA_DisableTestMode
+**
+** Description      Disable bluetooth device under test mode
+**
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_DisableTestMode(void);
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetDeviceName
+**
+** Description      This function sets the Bluetooth name of the local device.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmSetDeviceName(char *p_name);
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetVisibility
+**
+** Description      This function sets the Bluetooth connectable,discoverable,
+**                  pairable and conn paired only modesmodes of the local device.
+**                  This controls whether other Bluetooth devices can find and connect to
+**                  the local device.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmSetVisibility(tBTA_DM_DISC disc_mode, tBTA_DM_CONN conn_mode, UINT8 pairable_mode, UINT8 conn_filter);
+
+/*******************************************************************************
+**
+** Function         BTA_DmSearch
+**
+** Description      This function searches for peer Bluetooth devices.  It
+**                  first performs an inquiry; for each device found from the
+**                  inquiry it gets the remote name of the device.  If
+**                  parameter services is nonzero, service discovery will be
+**                  performed on each device for the services specified.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmSearch(tBTA_DM_INQ *p_dm_inq, tBTA_SERVICE_MASK services,
+                         tBTA_DM_SEARCH_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_DmSearchCancel
+**
+** Description      This function cancels a search that has been initiated
+**                  by calling BTA_DmSearch().
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmSearchCancel(void);
+
+/*******************************************************************************
+**
+** Function         BTA_DmDiscover
+**
+** Description      This function performs service discovery for the services
+**                  of a particular peer device.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmDiscover(BD_ADDR bd_addr, tBTA_SERVICE_MASK services,
+                           tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search);
+
+// btla-specific ++
+/*******************************************************************************
+**
+** Function         BTA_DmDiscoverUUID
+**
+** Description      This function performs service discovery for the services
+**                  of a particular peer device.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmDiscoverUUID(BD_ADDR bd_addr, tSDP_UUID *uuid,
+                               tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search);
+
+/*******************************************************************************
+**
+** Function         BTA_DmGetCachedRemoteName
+**
+** Description      Retieve cached remote name if available
+**
+** Returns          BTA_SUCCESS if cached name was retrieved
+**                  BTA_FAILURE if cached name is not available
+**
+*******************************************************************************/
+tBTA_STATUS BTA_DmGetCachedRemoteName(BD_ADDR remote_device, UINT8 **pp_cached_name);
+// btla-specific --
+
+/*******************************************************************************
+**
+** Function         BTA_DmBond
+**
+** Description      This function initiates a bonding procedure with a peer
+**                  device.  The bonding procedure enables authentication
+**                  and optionally encryption on the Bluetooth link.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmBond(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBondByTransport
+**
+** Description      This function initiates a bonding procedure with a peer
+**                  device by designated transport.  The bonding procedure enables
+**                  authentication and optionally encryption on the Bluetooth link.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmBondByTransport(BD_ADDR bd_addr, tBTA_TRANSPORT transport);
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmBondCancel
+**
+** Description      This function cancels a bonding procedure with a peer
+**                  device.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmBondCancel(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function         BTA_DmPinReply
+**
+** Description      This function provides a PIN when one is requested by DM
+**                  during a bonding procedure.  The application should call
+**                  this function after the security callback is called with
+**                  a BTA_DM_PIN_REQ_EVT.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmPinReply(BD_ADDR bd_addr, BOOLEAN accept, UINT8 pin_len,
+                           UINT8 *p_pin);
+
+#if (BTM_OOB_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         BTA_DmLocalOob
+**
+** Description      This function retrieves the OOB data from local controller.
+**                  The result is reported by bta_dm_co_loc_oob().
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmLocalOob(void);
+#endif /* BTM_OOB_INCLUDED */
+
+/*******************************************************************************
+**
+** Function         BTA_DmConfirm
+**
+** Description      This function accepts or rejects the numerical value of the
+**                  Simple Pairing process on BTA_DM_SP_CFM_REQ_EVT
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmConfirm(BD_ADDR bd_addr, BOOLEAN accept);
+
+/*******************************************************************************
+**
+** Function         BTA_DmAddDevice
+**
+** Description      This function adds a device to the security database list
+**                  of peer devices. This function would typically be called
+**                  at system startup to initialize the security database with
+**                  known peer devices.  This is a direct execution function
+**                  that may lock task scheduling on some platforms.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmAddDevice(BD_ADDR bd_addr, DEV_CLASS dev_class,
+                            LINK_KEY link_key, tBTA_SERVICE_MASK trusted_mask,
+                            BOOLEAN is_trusted, UINT8 key_type,
+                            tBTA_IO_CAP io_cap, UINT8 pin_length);
+
+/*******************************************************************************
+**
+** Function         BTA_DmRemoveDevice
+**
+** Description      This function removes a device from the security database.
+**                  This is a direct execution function that may lock task
+**                  scheduling on some platforms.
+**
+**
+** Returns          BTA_SUCCESS if successful.
+**                  BTA_FAIL if operation failed.
+**
+*******************************************************************************/
+extern tBTA_STATUS BTA_DmRemoveDevice(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function         BTA_GetEirService
+**
+** Description      This function is called to get BTA service mask from EIR.
+**
+** Parameters       p_eir - pointer of EIR significant part
+**                  p_services - return the BTA service mask
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_GetEirService( UINT8 *p_eir, tBTA_SERVICE_MASK *p_services );
+
+/*******************************************************************************
+**
+** Function         BTA_DmGetConnectionState
+**
+** Description      Returns whether the remote device is currently connected.
+**
+** Returns          0 if the device is NOT connected.
+**
+*******************************************************************************/
+extern UINT16 BTA_DmGetConnectionState( BD_ADDR bd_addr );
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetLocalDiRecord
+**
+** Description      This function adds a DI record to the local SDP database.
+**
+** Returns          BTA_SUCCESS if record set sucessfully, otherwise error code.
+**
+*******************************************************************************/
+extern tBTA_STATUS BTA_DmSetLocalDiRecord( tBTA_DI_RECORD *p_device_info,
+                                           UINT32 *p_handle );
+
+/*******************************************************************************
+**
+**
+** Function         BTA_DmCloseACL
+**
+** Description      This function force to close an ACL connection and remove the
+**                  device from the security database list of known devices.
+**
+** Parameters:      bd_addr       - Address of the peer device
+**                  remove_dev    - remove device or not after link down
+**                  transport     - which transport to close
+
+**
+** Returns          void.
+**
+*******************************************************************************/
+extern void BTA_DmCloseACL(BD_ADDR bd_addr, BOOLEAN remove_dev, tBTA_TRANSPORT transport);
+
+/*******************************************************************************
+**
+** Function         bta_dmexecutecallback
+**
+** Description      This function will request BTA to execute a call back in the context of BTU task
+**                  This API was named in lower case because it is only intended
+**                  for the internal customers(like BTIF).
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void bta_dmexecutecallback (tBTA_DM_EXEC_CBACK* p_callback, void * p_param);
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         BTA_DmPcmInitSamples
+**
+** Description      initialize the down sample converter.
+**
+**                  src_sps: original samples per second (source audio data)
+**                            (ex. 44100, 48000)
+**                  bits: number of bits per pcm sample (16)
+**                  n_channels: number of channels (i.e. mono(1), stereo(2)...)
+**
+** Returns          none
+**
+*******************************************************************************/
+extern void BTA_DmPcmInitSamples (UINT32 src_sps, UINT32 bits, UINT32 n_channels);
+
+/**************************************************************************************
+** Function         BTA_DmPcmResample
+**
+** Description      Down sampling utility to convert higher sampling rate into 8K/16bits
+**                  PCM samples.
+**
+** Parameters       p_src: pointer to the buffer where the original sampling PCM
+**                              are stored.
+**                  in_bytes:  Length of the input PCM sample buffer in byte.
+**                  p_dst:      pointer to the buffer which is to be used to store
+**                              the converted PCM samples.
+**
+**
+** Returns          INT32: number of samples converted.
+**
+**************************************************************************************/
+extern INT32 BTA_DmPcmResample (void *p_src, UINT32 in_bytes, void *p_dst);
+#endif
+
+#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+/* BLE related API functions */
+/*******************************************************************************
+**
+** Function         BTA_DmBleSecurityGrant
+**
+** Description      Grant security request access.
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  res              - security grant status.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmBleSecurityGrant(BD_ADDR bd_addr, tBTA_DM_BLE_SEC_GRANT res);
+
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleSetBgConnType
+**
+** Description      This function is called to set BLE connectable mode for a
+**                  peripheral device.
+**
+** Parameters       bg_conn_type: it can be auto connection, or selective connection.
+**                  p_select_cback: callback function when selective connection procedure
+**                              is being used.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmBleSetBgConnType(tBTA_DM_BLE_CONN_TYPE bg_conn_type, tBTA_DM_BLE_SEL_CBACK *p_select_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBlePasskeyReply
+**
+** Description      Send BLE SMP passkey reply.
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  accept           - passkey entry sucessful or declined.
+**                  passkey          - passkey value, must be a 6 digit number,
+**                                     can be lead by 0.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmBlePasskeyReply(BD_ADDR bd_addr, BOOLEAN accept, UINT32 passkey);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleConfirmReply
+**
+** Description      Send BLE SMP SC user confirmation reply.
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  accept           - numbers to compare are the same or different.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmBleConfirmReply(BD_ADDR bd_addr, BOOLEAN accept);
+
+/*******************************************************************************
+**
+** Function         BTA_DmAddBleDevice
+**
+** Description      Add a BLE device.  This function will be normally called
+**                  during host startup to restore all required information
+**                  for a LE device stored in the NVRAM.
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  dev_type         - Remote device's device type.
+**                  addr_type        - LE device address type.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmAddBleDevice(BD_ADDR bd_addr, tBLE_ADDR_TYPE addr_type,
+                               tBT_DEVICE_TYPE dev_type);
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmAddBleKey
+**
+** Description      Add/modify LE device information.  This function will be
+**                  normally called during host startup to restore all required
+**                  information stored in the NVRAM.
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  p_le_key         - LE key values.
+**                  key_type         - LE SMP key type.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmAddBleKey (BD_ADDR bd_addr,
+                             tBTA_LE_KEY_VALUE *p_le_key,
+                             tBTA_LE_KEY_TYPE key_type);
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetBlePrefConnParams
+**
+** Description      This function is called to set the preferred connection
+**                  parameters when default connection parameter is not desired.
+**
+** Parameters:      bd_addr          - BD address of the peripheral
+**                  min_conn_int     - minimum preferred connection interval
+**                  max_conn_int     - maximum preferred connection interval
+**                  slave_latency    - preferred slave latency
+**                  supervision_tout - preferred supervision timeout
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmSetBlePrefConnParams(BD_ADDR bd_addr,
+                                       UINT16 min_conn_int, UINT16 max_conn_int,
+                                       UINT16 slave_latency, UINT16 supervision_tout );
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetBleConnScanParams
+**
+** Description      This function is called to set scan parameters used in
+**                  BLE connection request
+**
+** Parameters:      scan_interval    - scan interval
+**                  scan_window      - scan window
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmSetBleConnScanParams(UINT32 scan_interval,
+                                       UINT32 scan_window);
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetBleScanParams
+**
+** Description      This function is called to set scan parameters
+**
+** Parameters:      client_if - Client IF
+**                  scan_interval - scan interval
+**                  scan_window - scan window
+**                  scan_mode - scan mode
+**                  scan_param_setup_status_cback - Set scan param status callback
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmSetBleScanParams(tGATT_IF client_if, UINT32 scan_interval,
+                                   UINT32 scan_window, tBLE_SCAN_MODE scan_mode,
+                                   tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_status_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetBleAdvParams
+**
+** Description      This function sets the advertising parameters BLE functionality.
+**                  It is to be called when device act in peripheral or broadcaster
+**                  role.
+**
+** Parameters:      adv_int_min    - adv interval minimum
+**                  adv_int_max    - adv interval max
+**                  p_dir_bda      - directed adv initator address
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmSetBleAdvParams (UINT16 adv_int_min, UINT16 adv_int_max,
+                                   tBLE_BD_ADDR *p_dir_bda);
+/*******************************************************************************
+**
+** Function         BTA_DmSearchExt
+**
+** Description      This function searches for peer Bluetooth devices. It performs
+**                  an inquiry and gets the remote name for devices. Service
+**                  discovery is done if services is non zero
+**
+** Parameters       p_dm_inq: inquiry conditions
+**                  services: if service is not empty, service discovery will be done.
+**                            for all GATT based service condition, put num_uuid, and
+**                            p_uuid is the pointer to the list of UUID values.
+**                  p_cback: callback functino when search is completed.
+**
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmSearchExt(tBTA_DM_INQ *p_dm_inq, tBTA_SERVICE_MASK_EXT *p_services,
+                            tBTA_DM_SEARCH_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_DmDiscoverExt
+**
+** Description      This function does service discovery for services of a
+**                  peer device. When services.num_uuid is 0, it indicates all
+**                  GATT based services are to be searched; other wise a list of
+**                  UUID of interested services should be provided through
+**                  services.p_uuid.
+**
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmDiscoverExt(BD_ADDR bd_addr, tBTA_SERVICE_MASK_EXT *p_services,
+                              tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search);
+
+/*******************************************************************************
+**
+** Function         BTA_DmDiscoverByTransport
+**
+** Description      This function does service discovery on particular transport
+**                  for services of a
+**                  peer device. When services.num_uuid is 0, it indicates all
+**                  GATT based services are to be searched; other wise a list of
+**                  UUID of interested services should be provided through
+**                  p_services->p_uuid.
+**
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmDiscoverByTransport(BD_ADDR bd_addr, tBTA_SERVICE_MASK_EXT *p_services,
+                                      tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search,
+                                      tBTA_TRANSPORT transport);
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetEncryption
+**
+** Description      This function is called to ensure that connection is
+**                  encrypted.  Should be called only on an open connection.
+**                  Typically only needed for connections that first want to
+**                  bring up unencrypted links, then later encrypt them.
+**
+** Parameters:      bd_addr       - Address of the peer device
+**                  transport     - transport of the link to be encruypted
+**                  p_callback    - Pointer to callback function to indicat the
+**                                  link encryption status
+**                  sec_act       - This is the security action to indicate
+**                                  what knid of BLE security level is required for
+**                                  the BLE link if the BLE is supported
+**                                  Note: This parameter is ignored for the BR/EDR link
+**                                        or the BLE is not supported
+**
+** Returns          void
+**
+**
+*******************************************************************************/
+extern void BTA_DmSetEncryption(BD_ADDR bd_addr, tBTA_TRANSPORT transport,
+                                tBTA_DM_ENCRYPT_CBACK *p_callback,
+                                tBTA_DM_BLE_SEC_ACT sec_act);
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleObserve
+**
+** Description      This procedure keep the device listening for advertising
+**                  events from a broadcast device.
+**
+** Parameters       start: start or stop observe.
+**                  duration : Duration of the scan. Continuous scan if 0 is passed
+**                  p_results_cb: Callback to be called with scan results
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmBleObserve(BOOLEAN start, UINT8 duration,
+                             tBTA_DM_SEARCH_CBACK *p_results_cb);
+
+extern void BTA_DmSetRandAddress(BD_ADDR rand_addr);
+
+#endif
+
+#if BLE_INCLUDED == TRUE
+// btla-specific --
+/*******************************************************************************
+**
+** Function         BTA_DmBleConfigLocalPrivacy
+**
+** Description      Enable/disable privacy on the local device
+**
+** Parameters:      privacy_enable   - enable/disabe privacy on remote device.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmBleConfigLocalPrivacy(BOOLEAN privacy_enable);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleEnableRemotePrivacy
+**
+** Description      Enable/disable privacy on a remote device
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  privacy_enable   - enable/disabe privacy on remote device.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmBleEnableRemotePrivacy(BD_ADDR bd_addr, BOOLEAN privacy_enable);
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleSetAdvConfig
+**
+** Description      This function is called to override the BTA default ADV parameters.
+**
+** Parameters       Pointer to User defined ADV data structure
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_DmBleSetAdvConfig (tBTA_BLE_AD_MASK data_mask,
+                                   tBTA_BLE_ADV_DATA *p_adv_cfg,
+                                   tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleSetScanRsp
+**
+** Description      This function is called to override the BTA scan response.
+**
+** Parameters       Pointer to User defined ADV data structure
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_DmBleSetScanRsp (tBTA_BLE_AD_MASK data_mask,
+                                 tBTA_BLE_ADV_DATA *p_adv_cfg,
+                                 tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleBroadcast
+**
+** Description      This function starts or stops LE broadcasting.
+**
+** Parameters       start: start or stop broadcast.
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_DmBleBroadcast (BOOLEAN start);
+
+
+/*******************************************************************************
+**
+** Function         BTA_BleEnableAdvInstance
+**
+** Description      This function enables the Multi ADV instance feature
+**
+** Parameters       p_params Pointer to ADV param user defined structure
+**                  p_cback  Pointer to Multi ADV callback structure
+**                  p_ref - Reference pointer
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_BleEnableAdvInstance (tBTA_BLE_ADV_PARAMS *p_params,
+                                tBTA_BLE_MULTI_ADV_CBACK *p_cback,void *p_ref);
+
+/*******************************************************************************
+**
+** Function         BTA_BleUpdateAdvInstParam
+**
+** Description      This function updates the Multi ADV instance params
+**
+** Parameters       inst_id Instance ID
+**                  p_params Pointer to ADV param user defined structure
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_BleUpdateAdvInstParam (UINT8 inst_id,
+                                tBTA_BLE_ADV_PARAMS *p_params);
+
+/*******************************************************************************
+**
+** Function         BTA_BleCfgAdvInstData
+**
+** Description      This function is called to configure the ADV instance data
+**
+** Parameters       inst_id - Instance ID
+**                  is_scan_rsp - Boolean value Scan response
+**                  Pointer to User defined ADV data structure
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp,
+                                tBTA_BLE_AD_MASK data_mask, tBTA_BLE_ADV_DATA *p_data);
+
+/*******************************************************************************
+**
+** Function         BTA_BleDisableAdvInstance
+**
+** Description      This function is called to disable the ADV instance
+**
+** Parameters       inst_id - Instance ID to be disabled
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_BleDisableAdvInstance(UINT8 inst_id);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleUpdateConnectionParams
+**
+** Description      Update connection parameters, can only be used when connection is up.
+**
+** Parameters:      bd_addr   - BD address of the peer
+**                  min_int   -     minimum connection interval, [0x0004~ 0x4000]
+**                  max_int   -     maximum connection interval, [0x0004~ 0x4000]
+**                  latency   -     slave latency [0 ~ 500]
+**                  timeout   -     supervision timeout [0x000a ~ 0xc80]
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmBleUpdateConnectionParams(BD_ADDR bd_addr, UINT16 min_int,
+                                   UINT16 max_int, UINT16 latency, UINT16 timeout);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleSetDataLength
+**
+** Description      This function is to set maximum LE data packet size
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmBleSetDataLength(BD_ADDR remote_device, UINT16 tx_data_length);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleSetStorageParams
+**
+** Description      This function is called to set the storage parameters
+**
+** Parameters       batch_scan_full_max -Max storage space (in %) allocated to full scanning
+**                  batch_scan_trunc_max -Max storage space (in %) allocated to truncated scanning
+**                  batch_scan_notify_threshold - Setup notification level based on total space
+**                  consumed by both pools. Setting it to 0 will disable threshold notification
+**                  p_setup_cback - Setup callback
+**                  p_thres_cback - Threshold callback
+**                  p_rep_cback - Reports callback
+**                  ref_value - Reference value
+**
+** Returns           None
+**
+*******************************************************************************/
+extern void BTA_DmBleSetStorageParams(UINT8 batch_scan_full_max,
+                                         UINT8 batch_scan_trunc_max,
+                                         UINT8 batch_scan_notify_threshold,
+                                         tBTA_BLE_SCAN_SETUP_CBACK *p_setup_cback,
+                                         tBTA_BLE_SCAN_THRESHOLD_CBACK *p_thres_cback,
+                                         tBTA_BLE_SCAN_REP_CBACK* p_rep_cback,
+                                         tBTA_DM_BLE_REF_VALUE ref_value);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleEnableBatchScan
+**
+** Description      This function is called to enable the batch scan
+**
+** Parameters       scan_mode -Batch scan mode
+**                  scan_interval - Scan interval
+**                  scan_window - Scan window
+**                  discard_rule -Discard rules
+**                  addr_type - Address type
+**                  ref_value - Reference value
+**
+** Returns           None
+**
+*******************************************************************************/
+extern void BTA_DmBleEnableBatchScan(tBTA_BLE_BATCH_SCAN_MODE scan_mode,
+                                         UINT32 scan_interval, UINT32 scan_window,
+                                         tBTA_BLE_DISCARD_RULE discard_rule,
+                                         tBLE_ADDR_TYPE        addr_type,
+                                         tBTA_DM_BLE_REF_VALUE ref_value);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleReadScanReports
+**
+** Description      This function is called to read the batch scan reports
+**
+** Parameters       scan_mode -Batch scan mode
+**                  ref_value - Reference value
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_DmBleReadScanReports(tBTA_BLE_BATCH_SCAN_MODE scan_type,
+                                             tBTA_DM_BLE_REF_VALUE ref_value);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleDisableBatchScan
+**
+** Description      This function is called to disable the batch scanning
+**
+** Parameters       ref_value - Reference value
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_DmBleDisableBatchScan(tBTA_DM_BLE_REF_VALUE ref_value);
+
+/*******************************************************************************
+**
+** Function         BTA_DmEnableScanFilter
+**
+** Description      This function is called to enable the adv data payload filter
+**
+** Parameters       action - enable or disable the APCF feature
+**                  p_cmpl_cback - Command completed callback
+**                  ref_value - Reference value
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmEnableScanFilter(UINT8 action,
+                                        tBTA_DM_BLE_PF_STATUS_CBACK *p_cmpl_cback,
+                                        tBTA_DM_BLE_REF_VALUE ref_value);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleScanFilterSetup
+**
+** Description      This function is called to setup the filter params
+**
+** Parameters       p_target: enable the filter condition on a target device; if NULL
+**                  filt_index - Filter index
+**                  p_filt_params -Filter parameters
+**                  ref_value - Reference value
+**                  action - Add, delete or clear
+**                  p_cmpl_back - Command completed callback
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmBleScanFilterSetup(UINT8 action,
+                                                   tBTA_DM_BLE_PF_FILT_INDEX filt_index,
+                                                   tBTA_DM_BLE_PF_FILT_PARAMS *p_filt_params,
+                                                   tBLE_BD_ADDR *p_target,
+                                                   tBTA_DM_BLE_PF_PARAM_CBACK *p_cmpl_cback,
+                                                   tBTA_DM_BLE_REF_VALUE ref_value);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleCfgFilterCondition
+**
+** Description      This function is called to configure the adv data payload filter
+**                  condition.
+**
+** Parameters       action: to read/write/clear
+**                  cond_type: filter condition type
+**                  filt_index - Filter index
+**                  p_cond: filter condition parameter
+**                  p_cmpl_back - Command completed callback
+**                  ref_value - Reference value
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmBleCfgFilterCondition(tBTA_DM_BLE_SCAN_COND_OP action,
+                                                 tBTA_DM_BLE_PF_COND_TYPE cond_type,
+                                                 tBTA_DM_BLE_PF_FILT_INDEX filt_index,
+                                                 tBTA_DM_BLE_PF_COND_PARAM *p_cond,
+                                                 tBTA_DM_BLE_PF_CFG_CBACK *p_cmpl_cback,
+                                                 tBTA_DM_BLE_REF_VALUE ref_value);
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleTrackAdvertiser
+**
+** Description      This function is called to track the advertiser
+**
+** Parameters    ref_value - Reference value
+**               p_track_adv_cback - ADV callback
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_DmBleTrackAdvertiser(tBTA_DM_BLE_REF_VALUE ref_value,
+                            tBTA_BLE_TRACK_ADV_CBACK *p_track_adv_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleGetEnergyInfo
+**
+** Description      This function is called to obtain the energy info
+**
+** Parameters       p_cmpl_cback - Command complete callback
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmBleGetEnergyInfo(tBTA_BLE_ENERGY_INFO_CBACK *p_cmpl_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_BrcmInit
+**
+** Description      This function initializes Broadcom specific VS handler in BTA
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_VendorInit  (void);
+
+/*******************************************************************************
+**
+** Function         BTA_BrcmCleanup
+**
+** Description      This function frees up Broadcom specific VS specific dynamic memory
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_VendorCleanup (void);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_API_H */

+ 80 - 0
components/bt/bluedroid/bta/include/bta_dm_ci.h

@@ -0,0 +1,80 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2006-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the interface file for device mananger call-in functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_DM_CI_H
+#define BTA_DM_CI_H
+
+#include "bta_api.h"
+
+/*****************************************************************************
+**  Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_dm_ci_io_req
+**
+** Description      This function must be called in response to function
+**                  bta_dm_co_io_req(), if *p_oob_data is set to BTA_OOB_UNKNOWN
+**                  by bta_dm_co_io_req().
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void bta_dm_ci_io_req(BD_ADDR bd_addr, tBTA_IO_CAP io_cap,
+                                     tBTA_OOB_DATA oob_data, tBTA_AUTH_REQ auth_req);
+
+/*******************************************************************************
+**
+** Function         bta_dm_ci_rmt_oob
+**
+** Description      This function must be called in response to function
+**                  bta_dm_co_rmt_oob() to provide the OOB data associated
+**                  with the remote device.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void bta_dm_ci_rmt_oob(BOOLEAN accept, BD_ADDR bd_addr,
+                              BT_OCTET16 c, BT_OCTET16 r);
+/*******************************************************************************
+**
+** Function         bta_dm_sco_ci_data_ready
+**
+** Description      This function sends an event to indicating that the phone
+**                  has SCO data ready..
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void bta_dm_sco_ci_data_ready(UINT16 event, UINT16 sco_handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 274 - 0
components/bt/bluedroid/bta/include/bta_dm_co.h

@@ -0,0 +1,274 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2006-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the interface file for device mananger callout functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_DM_CO_H
+#define BTA_DM_CO_H
+
+#include "bta_sys.h"
+
+
+#ifndef BTA_SCO_OUT_PKT_SIZE
+    #define BTA_SCO_OUT_PKT_SIZE    BTM_SCO_DATA_SIZE_MAX
+#endif
+
+#define BTA_SCO_CODEC_PCM       0       /* used for regular SCO */
+#define BTA_SCO_CODEC_SBC       1       /* used for WBS */
+typedef UINT8   tBTA_SCO_CODEC_TYPE;
+
+#define BTA_DM_SCO_SAMP_RATE_8K     8000
+#define BTA_DM_SCO_SAMP_RATE_16K    16000
+
+/* SCO codec information */
+typedef struct
+{
+    tBTA_SCO_CODEC_TYPE   codec_type;
+}tBTA_CODEC_INFO;
+
+#define BTA_DM_SCO_ROUTE_PCM	BTM_SCO_ROUTE_PCM
+#define BTA_DM_SCO_ROUTE_HCI	BTM_SCO_ROUTE_HCI
+
+typedef tBTM_SCO_ROUTE_TYPE tBTA_DM_SCO_ROUTE_TYPE;
+
+
+/*****************************************************************************
+**  Function Declarations
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function         bta_dm_co_io_req
+**
+** Description      This callout function is executed by DM to get IO capabilities
+**                  of the local device for the Simple Pairing process
+**
+** Parameters       bd_addr  - The peer device
+**                  *p_io_cap - The local Input/Output capabilities
+**                  *p_oob_data - TRUE, if OOB data is available for the peer device.
+**                  *p_auth_req - TRUE, if MITM protection is required.
+**
+** Returns          void.
+**
+*******************************************************************************/
+extern void bta_dm_co_io_req(BD_ADDR bd_addr, tBTA_IO_CAP *p_io_cap,
+                             tBTA_OOB_DATA *p_oob_data, tBTA_AUTH_REQ *p_auth_req,
+                             BOOLEAN is_orig);
+
+/*******************************************************************************
+**
+** Function         bta_dm_co_io_rsp
+**
+** Description      This callout function is executed by DM to report IO capabilities
+**                  of the peer device for the Simple Pairing process
+**
+** Parameters       bd_addr  - The peer device
+**                  io_cap - The remote Input/Output capabilities
+**                  oob_data - TRUE, if OOB data is available for the peer device.
+**                  auth_req - TRUE, if MITM protection is required.
+**
+** Returns          void.
+**
+*******************************************************************************/
+extern void bta_dm_co_io_rsp(BD_ADDR bd_addr, tBTA_IO_CAP io_cap,
+                             tBTA_OOB_DATA oob_data, tBTA_AUTH_REQ auth_req);
+
+/*******************************************************************************
+**
+** Function         bta_dm_co_lk_upgrade
+**
+** Description      This callout function is executed by DM to check if the
+**                  platform wants allow link key upgrade
+**
+** Parameters       bd_addr  - The peer device
+**                  *p_upgrade - TRUE, if link key upgrade is desired.
+**
+** Returns          void.
+**
+*******************************************************************************/
+extern void  bta_dm_co_lk_upgrade(BD_ADDR bd_addr, BOOLEAN *p_upgrade );
+
+/*******************************************************************************
+**
+** Function         bta_dm_co_loc_oob
+**
+** Description      This callout function is executed by DM to report the OOB
+**                  data of the local device for the Simple Pairing process
+**
+** Parameters       valid - TRUE, if the local OOB data is retrieved from LM
+**                  c     - Simple Pairing Hash C
+**                  r     - Simple Pairing Randomnizer R
+**
+** Returns          void.
+**
+*******************************************************************************/
+extern void bta_dm_co_loc_oob(BOOLEAN valid, BT_OCTET16 c, BT_OCTET16 r);
+
+/*******************************************************************************
+**
+** Function         bta_dm_co_rmt_oob
+**
+** Description      This callout function is executed by DM to request the OOB
+**                  data for the remote device for the Simple Pairing process
+**
+** Parameters       bd_addr  - The peer device
+**
+** Returns          void.
+**
+*******************************************************************************/
+extern void bta_dm_co_rmt_oob(BD_ADDR bd_addr);
+
+/*****************************************************************************
+**  SCO over HCI Function Declarations
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function         bta_dm_sco_co_init
+**
+** Description      This function can be used by the phone to initialize audio
+**                  codec or for other initialization purposes before SCO connection
+**                  is opened.
+**
+**
+** Returns          Void.
+**
+*******************************************************************************/
+extern tBTA_DM_SCO_ROUTE_TYPE bta_dm_sco_co_init(UINT32 rx_bw, UINT32 tx_bw,
+                                                 tBTA_CODEC_INFO *p_codec_info, UINT8 app_id);
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_sco_co_open
+**
+** Description      This function is executed when a SCO connection is open.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void bta_dm_sco_co_open(UINT16 handle, UINT8 pkt_size, UINT16 event);
+
+/*******************************************************************************
+**
+** Function         bta_dm_sco_co_close
+**
+** Description      This function is called when a SCO connection is closed
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void bta_dm_sco_co_close(void);
+
+/*******************************************************************************
+**
+** Function         bta_dm_sco_co_out_data
+**
+** Description      This function is called to send SCO data over HCI.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void bta_dm_sco_co_out_data(BT_HDR  **p_buf);
+
+/*******************************************************************************
+**
+** Function         bta_dm_sco_co_in_data
+**
+** Description      This function is called to send incoming SCO data to application.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void bta_dm_sco_co_in_data(BT_HDR  *p_buf, tBTM_SCO_DATA_FLAG status);
+
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_co_ble_io_req
+**
+** Description      This callout function is executed by DM to get BLE IO capabilities
+**                  before SMP pairing gets going.
+**
+** Parameters       bd_addr  - The peer device
+**                  *p_io_cap - The local Input/Output capabilities
+**                  *p_oob_data - TRUE, if OOB data is available for the peer device.
+**                  *p_auth_req -  Auth request setting (Bonding and MITM required or not)
+**                  *p_max_key_size - max key size local device supported.
+**                  *p_init_key - initiator keys.
+**                  *p_resp_key - responder keys.
+**
+** Returns          void.
+**
+*******************************************************************************/
+extern void bta_dm_co_ble_io_req(BD_ADDR bd_addr,  tBTA_IO_CAP *p_io_cap,
+                                 tBTA_OOB_DATA *p_oob_data,
+                                 tBTA_LE_AUTH_REQ *p_auth_req,
+                                 UINT8 *p_max_key_size,
+                                 tBTA_LE_KEY_TYPE *p_init_key,
+                                 tBTA_LE_KEY_TYPE  *p_resp_key );
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_co_ble_local_key_reload
+**
+** Description      This callout function is to load the local BLE keys if available
+**                  on the device.
+**
+** Parameters       none
+**
+** Returns          void.
+**
+*******************************************************************************/
+extern void bta_dm_co_ble_load_local_keys (tBTA_DM_BLE_LOCAL_KEY_MASK *p_key_mask, BT_OCTET16 er,
+                                           tBTA_BLE_LOCAL_ID_KEYS *p_id_keys);
+
+// btla-specific ++
+/*******************************************************************************
+**
+** Function         bta_dm_co_ble_io_req
+**
+** Description      This callout function is executed by DM to get BLE IO capabilities
+**                  before SMP pairing gets going.
+**
+** Parameters       bd_addr  - The peer device
+**                  *p_io_cap - The local Input/Output capabilities
+**                  *p_oob_data - TRUE, if OOB data is available for the peer device.
+**                  *p_auth_req -  Auth request setting (Bonding and MITM required or not)
+**                  *p_max_key_size - max key size local device supported.
+**                  *p_init_key - initiator keys.
+**                  *p_resp_key - responder keys.
+**
+** Returns          void.
+**
+*******************************************************************************/
+extern void bta_dm_co_ble_io_req(BD_ADDR bd_addr,  tBTA_IO_CAP *p_io_cap,
+                                 tBTA_OOB_DATA *p_oob_data,
+                                 tBTA_LE_AUTH_REQ *p_auth_req,
+                                 UINT8 *p_max_key_size,
+                                 tBTA_LE_KEY_TYPE *p_init_key,
+                                 tBTA_LE_KEY_TYPE  *p_resp_key );
+// btla-specific --
+
+#endif

+ 1411 - 0
components/bt/bluedroid/bta/include/bta_gatt_api.h

@@ -0,0 +1,1411 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2013 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the public interface file for BTA GATT.
+ *
+ ******************************************************************************/
+
+#ifndef BTA_GATT_API_H
+#define BTA_GATT_API_H
+
+#include "bta_api.h"
+#include "gatt_api.h"
+
+#ifndef     BTA_GATT_INCLUDED
+#warning BTA_GATT_INCLUDED not defined
+#define     BTA_GATT_INCLUDED     FALSE
+#endif
+
+#if ((BLE_INCLUDED == FALSE) && (BTA_GATT_INCLUDED == TRUE))
+#undef BTA_GATT_INCLUDED
+#define BTA_GATT_INCLUDED        FALSE
+#endif
+
+
+#ifndef     BTA_GATT_DEBUG
+#define     BTA_GATT_DEBUG       FALSE
+#endif
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+/**************************
+**  Common Definitions
+***************************/
+/* GATT ID */
+typedef struct
+{
+    tBT_UUID    uuid;           /* uuid of the attribute */
+    UINT8       inst_id;        /* instance ID */
+} __attribute__((packed)) tBTA_GATT_ID;
+
+/* Success code and error codes */
+#define  BTA_GATT_OK                        GATT_SUCCESS
+#define  BTA_GATT_INVALID_HANDLE            GATT_INVALID_HANDLE                /* 0x0001 */
+#define  BTA_GATT_READ_NOT_PERMIT           GATT_READ_NOT_PERMIT               /* 0x0002 */
+#define  BTA_GATT_WRITE_NOT_PERMIT          GATT_WRITE_NOT_PERMIT              /* 0x0003 */
+#define  BTA_GATT_INVALID_PDU               GATT_INVALID_PDU                   /* 0x0004 */
+#define  BTA_GATT_INSUF_AUTHENTICATION      GATT_INSUF_AUTHENTICATION          /* 0x0005 */
+#define  BTA_GATT_REQ_NOT_SUPPORTED         GATT_REQ_NOT_SUPPORTED             /* 0x0006 */
+#define  BTA_GATT_INVALID_OFFSET            GATT_INVALID_OFFSET                /* 0x0007 */
+#define  BTA_GATT_INSUF_AUTHORIZATION       GATT_INSUF_AUTHORIZATION           /* 0x0008 */
+#define  BTA_GATT_PREPARE_Q_FULL            GATT_PREPARE_Q_FULL                /* 0x0009 */
+#define  BTA_GATT_NOT_FOUND                 GATT_NOT_FOUND                     /* 0x000a */
+#define  BTA_GATT_NOT_LONG                  GATT_NOT_LONG                      /* 0x000b */
+#define  BTA_GATT_INSUF_KEY_SIZE            GATT_INSUF_KEY_SIZE                /* 0x000c */
+#define  BTA_GATT_INVALID_ATTR_LEN          GATT_INVALID_ATTR_LEN              /* 0x000d */
+#define  BTA_GATT_ERR_UNLIKELY              GATT_ERR_UNLIKELY                  /* 0x000e */
+#define  BTA_GATT_INSUF_ENCRYPTION          GATT_INSUF_ENCRYPTION              /* 0x000f */
+#define  BTA_GATT_UNSUPPORT_GRP_TYPE        GATT_UNSUPPORT_GRP_TYPE            /* 0x0010 */
+#define  BTA_GATT_INSUF_RESOURCE            GATT_INSUF_RESOURCE                /* 0x0011 */
+
+
+#define  BTA_GATT_NO_RESOURCES              GATT_NO_RESOURCES                  /* 0x80 */
+#define  BTA_GATT_INTERNAL_ERROR            GATT_INTERNAL_ERROR                /* 0x81 */
+#define  BTA_GATT_WRONG_STATE               GATT_WRONG_STATE                   /* 0x82 */
+#define  BTA_GATT_DB_FULL                   GATT_DB_FULL                       /* 0x83 */
+#define  BTA_GATT_BUSY                      GATT_BUSY                          /* 0x84 */
+#define  BTA_GATT_ERROR                     GATT_ERROR                         /* 0x85 */
+#define  BTA_GATT_CMD_STARTED               GATT_CMD_STARTED                   /* 0x86 */
+#define  BTA_GATT_ILLEGAL_PARAMETER         GATT_ILLEGAL_PARAMETER             /* 0x87 */
+#define  BTA_GATT_PENDING                   GATT_PENDING                       /* 0x88 */
+#define  BTA_GATT_AUTH_FAIL                 GATT_AUTH_FAIL                     /* 0x89 */
+#define  BTA_GATT_MORE                      GATT_MORE                          /* 0x8a */
+#define  BTA_GATT_INVALID_CFG               GATT_INVALID_CFG                   /* 0x8b */
+#define  BTA_GATT_SERVICE_STARTED           GATT_SERVICE_STARTED               /* 0x8c */
+#define  BTA_GATT_ENCRYPED_MITM             GATT_ENCRYPED_MITM                 /* GATT_SUCCESS */
+#define  BTA_GATT_ENCRYPED_NO_MITM          GATT_ENCRYPED_NO_MITM              /* 0x8d */
+#define  BTA_GATT_NOT_ENCRYPTED             GATT_NOT_ENCRYPTED                 /* 0x8e */
+#define  BTA_GATT_CONGESTED                 GATT_CONGESTED                     /* 0x8f */
+
+#define  BTA_GATT_DUP_REG                   0x90                               /* 0x90 */
+#define  BTA_GATT_ALREADY_OPEN              0x91                               /* 0x91 */
+#define  BTA_GATT_CANCEL                    0x92                               /* 0x92 */
+
+                                             /* 0xE0 ~ 0xFC reserved for future use */
+#define  BTA_GATT_CCC_CFG_ERR                GATT_CCC_CFG_ERR     /* 0xFD Client Characteristic Configuration Descriptor Improperly Configured */
+#define  BTA_GATT_PRC_IN_PROGRESS            GATT_PRC_IN_PROGRESS /* 0xFE Procedure Already in progress */
+#define  BTA_GATT_OUT_OF_RANGE               GATT_OUT_OF_RANGE    /* 0xFFAttribute value out of range */
+
+typedef UINT8 tBTA_GATT_STATUS;
+
+#define BTA_GATT_INVALID_CONN_ID   GATT_INVALID_CONN_ID
+
+
+/* Client callback function events */
+#define BTA_GATTC_REG_EVT           0   /* GATT client is registered. */
+#define BTA_GATTC_DEREG_EVT         1   /* GATT client deregistered event */
+#define BTA_GATTC_OPEN_EVT          2   /* GATTC open request status  event */
+#define BTA_GATTC_READ_CHAR_EVT     3   /* GATT read characteristic event */
+#define BTA_GATTC_WRITE_CHAR_EVT    4   /* GATT write characteristic or char descriptor event */
+#define BTA_GATTC_CLOSE_EVT         5   /* GATTC  close request status event */
+#define BTA_GATTC_SEARCH_CMPL_EVT   6   /* GATT discovery complete event */
+#define BTA_GATTC_SEARCH_RES_EVT    7   /* GATT discovery result event */
+#define BTA_GATTC_READ_DESCR_EVT    8   /* GATT read characterisitc descriptor event */
+#define BTA_GATTC_WRITE_DESCR_EVT   9   /* GATT write characteristic descriptor event */
+#define BTA_GATTC_NOTIF_EVT         10  /* GATT attribute notification event */
+#define BTA_GATTC_PREP_WRITE_EVT    11  /* GATT prepare write  event */
+#define BTA_GATTC_EXEC_EVT          12  /* execute write complete event */
+#define BTA_GATTC_ACL_EVT           13  /* ACL up event */
+#define BTA_GATTC_CANCEL_OPEN_EVT   14  /* cancel open event */
+#define BTA_GATTC_SRVC_CHG_EVT      15  /* service change event */
+#define BTA_GATTC_LISTEN_EVT        16  /* listen event */
+#define BTA_GATTC_ENC_CMPL_CB_EVT   17  /* encryption complete callback event */
+#define BTA_GATTC_CFG_MTU_EVT       18  /* configure MTU complete event */
+#define BTA_GATTC_ADV_DATA_EVT      19  /* ADV data event */
+#define BTA_GATTC_MULT_ADV_ENB_EVT  20  /* Enable Multi ADV event */
+#define BTA_GATTC_MULT_ADV_UPD_EVT  21  /* Update parameter event */
+#define BTA_GATTC_MULT_ADV_DATA_EVT 22  /* Multi ADV data event */
+#define BTA_GATTC_MULT_ADV_DIS_EVT  23  /* Disable Multi ADV event */
+#define BTA_GATTC_CONGEST_EVT       24  /* Congestion event */
+#define BTA_GATTC_BTH_SCAN_ENB_EVT  25 /* Enable batch scan event */
+#define BTA_GATTC_BTH_SCAN_CFG_EVT  26 /* Config storage event */
+#define BTA_GATTC_BTH_SCAN_RD_EVT   27 /* Batch scan reports read event */
+#define BTA_GATTC_BTH_SCAN_THR_EVT  28 /* Batch scan threshold event */
+#define BTA_GATTC_BTH_SCAN_PARAM_EVT 29 /* Batch scan param event */
+#define BTA_GATTC_BTH_SCAN_DIS_EVT  30 /* Disable batch scan event */
+#define BTA_GATTC_SCAN_FLT_CFG_EVT  31 /* Scan filter config event */
+#define BTA_GATTC_SCAN_FLT_PARAM_EVT 32 /* Param filter event */
+#define BTA_GATTC_SCAN_FLT_STATUS_EVT 33 /* Filter status event */
+#define BTA_GATTC_ADV_VSC_EVT         34 /* ADV VSC event */
+
+typedef UINT8 tBTA_GATTC_EVT;
+
+typedef tGATT_IF tBTA_GATTC_IF;
+
+typedef struct
+{
+    UINT16              unit;       /* as UUIUD defined by SIG */
+    UINT16              descr;       /* as UUID as defined by SIG */
+    tGATT_FORMAT        format;
+    INT8                exp;
+    UINT8               name_spc;   /* The name space of the description */
+}tBTA_GATT_CHAR_PRES;
+
+#define BTA_GATT_CLT_CONFIG_NONE               GATT_CLT_CONFIG_NONE         /* 0x0000    */
+#define BTA_GATT_CLT_CONFIG_NOTIFICATION       GATT_CLT_CONFIG_NOTIFICATION /* 0x0001 */
+#define BTA_GATT_CLT_CONFIG_INDICATION         GATT_CLT_CONFIG_INDICATION   /* 0x0002 */
+typedef UINT16  tBTA_GATT_CLT_CHAR_CONFIG;
+
+/* characteristic descriptor: server configuration value
+*/
+#define BTA_GATT_SVR_CONFIG_NONE            GATT_SVR_CONFIG_NONE            /* 0x0000 */
+#define BTA_GATT_SVR_CONFIG_BROADCAST       GATT_SVR_CONFIG_BROADCAST       /*  0x0001 */
+typedef UINT16  tBTA_GATT_SVR_CHAR_CONFIG;
+
+/* Characteristic Aggregate Format attribute value
+*/
+#define BTA_GATT_AGGR_HANDLE_NUM_MAX        10
+typedef struct
+{
+    UINT8                   num_handle;
+    UINT16                  handle_list[BTA_GATT_AGGR_HANDLE_NUM_MAX];
+} tBTA_GATT_CHAR_AGGRE;
+typedef tGATT_VALID_RANGE           tBTA_GATT_VALID_RANGE;
+
+typedef struct
+{
+    UINT16  len;
+    UINT8   *p_value;
+}tBTA_GATT_UNFMT;
+
+#define BTA_GATT_MAX_ATTR_LEN       GATT_MAX_ATTR_LEN
+
+#define BTA_GATTC_TYPE_WRITE             GATT_WRITE
+#define BTA_GATTC_TYPE_WRITE_NO_RSP      GATT_WRITE_NO_RSP
+typedef UINT8 tBTA_GATTC_WRITE_TYPE;
+
+#define BTA_GATT_CONN_UNKNOWN                   0
+#define BTA_GATT_CONN_L2C_FAILURE               GATT_CONN_L2C_FAILURE         /* general l2cap resource failure */
+#define BTA_GATT_CONN_TIMEOUT                   GATT_CONN_TIMEOUT             /* 0x08 connection timeout  */
+#define BTA_GATT_CONN_TERMINATE_PEER_USER       GATT_CONN_TERMINATE_PEER_USER /* 0x13 connection terminate by peer user  */
+#define BTA_GATT_CONN_TERMINATE_LOCAL_HOST      GATT_CONN_TERMINATE_LOCAL_HOST/* 0x16 connectionterminated by local host  */
+#define BTA_GATT_CONN_FAIL_ESTABLISH            GATT_CONN_FAIL_ESTABLISH      /* 0x03E connection fail to establish  */
+#define BTA_GATT_CONN_LMP_TIMEOUT               GATT_CONN_LMP_TIMEOUT          /* 0x22 connection fail for LMP response tout */
+#define BTA_GATT_CONN_CANCEL                    GATT_CONN_CANCEL               /* 0x0100 L2CAP connection cancelled  */
+#define BTA_GATT_CONN_NONE                      0x0101                          /* 0x0101 no connection to cancel  */
+typedef UINT16 tBTA_GATT_REASON;
+
+typedef struct
+{
+    tBTA_GATT_ID        id;
+    BOOLEAN             is_primary;
+}tBTA_GATT_SRVC_ID;
+
+typedef struct
+{
+    tBTA_GATT_SRVC_ID       srvc_id;
+    tBTA_GATT_ID            char_id;
+}tBTA_GATTC_CHAR_ID;
+
+typedef struct
+{
+    tBTA_GATTC_CHAR_ID      char_id;
+    tBTA_GATT_ID            descr_id;
+}tBTA_GATTC_CHAR_DESCR_ID;
+
+typedef struct
+{
+    tBTA_GATT_SRVC_ID       srvc_id;
+    tBTA_GATT_SRVC_ID       incl_svc_id;
+}tBTA_GATTC_INCL_SVC_ID;
+
+#define     BTA_GATT_TYPE_CHAR          0
+#define     BTA_GATT_TYPE_CHAR_DESCR    1
+typedef UINT8 tBTA_GATT_ID_TYPE;
+
+typedef struct
+{
+    tBTA_GATT_ID_TYPE               id_type;
+    union
+    {
+        tBTA_GATTC_CHAR_ID         char_id;
+        tBTA_GATTC_CHAR_DESCR_ID   char_descr_id;
+
+    }                       id_value;
+}tBTA_GATTC_ATTR_ID;
+
+#define BTA_GATTC_MULTI_MAX    GATT_MAX_READ_MULTI_HANDLES
+
+typedef struct
+{
+    UINT8                       num_attr;
+    tBTA_GATTC_ATTR_ID          id_list[BTA_GATTC_MULTI_MAX];
+
+}tBTA_GATTC_MULTI;
+
+#define BTA_GATT_AUTH_REQ_NONE           GATT_AUTH_REQ_NONE
+#define BTA_GATT_AUTH_REQ_NO_MITM        GATT_AUTH_REQ_NO_MITM            /* unauthenticated encryption */
+#define BTA_GATT_AUTH_REQ_MITM           GATT_AUTH_REQ_MITM               /* authenticated encryption */
+#define BTA_GATT_AUTH_REQ_SIGNED_NO_MITM GATT_AUTH_REQ_SIGNED_NO_MITM
+#define BTA_GATT_AUTH_REQ_SIGNED_MITM    GATT_AUTH_REQ_SIGNED_MITM
+
+typedef tGATT_AUTH_REQ tBTA_GATT_AUTH_REQ;
+
+enum
+{
+    BTA_GATTC_ATTR_TYPE_INCL_SRVC,
+    BTA_GATTC_ATTR_TYPE_CHAR,
+    BTA_GATTC_ATTR_TYPE_CHAR_DESCR,
+    BTA_GATTC_ATTR_TYPE_SRVC
+};
+typedef UINT8 tBTA_GATTC_ATTR_TYPE;
+
+
+typedef struct
+{
+    tBT_UUID    uuid;
+    UINT16      s_handle;
+    UINT16      e_handle;   /* used for service only */
+    UINT8       attr_type;
+    UINT8       id;
+    UINT8       prop;       /* used when attribute type is characteristic */
+    BOOLEAN     is_primary; /* used when attribute type is service */
+}tBTA_GATTC_NV_ATTR;
+
+/* callback data structure */
+typedef struct
+{
+    tBTA_GATT_STATUS    status;
+    tBTA_GATTC_IF       client_if;
+// btla-specific ++
+    tBT_UUID            app_uuid;
+// btla-specific --
+}tBTA_GATTC_REG;
+
+typedef struct
+{
+    UINT8                       num_pres_fmt;   /* number of presentation format aggregated*/
+    tBTA_GATTC_CHAR_DESCR_ID    pre_format[BTA_GATTC_MULTI_MAX];
+}tBTA_GATT_CHAR_AGGRE_VALUE;
+
+typedef union
+{
+    tBTA_GATT_CHAR_AGGRE_VALUE      aggre_value;
+    tBTA_GATT_UNFMT                 unformat;
+
+}tBTA_GATT_READ_VAL;
+
+typedef struct
+{
+    UINT16              conn_id;
+    tBTA_GATT_STATUS    status;
+    tBTA_GATT_SRVC_ID   srvc_id;
+    tBTA_GATT_ID        char_id;
+    tBTA_GATT_ID        descr_type;
+    tBTA_GATT_READ_VAL  *p_value;
+}tBTA_GATTC_READ;
+
+typedef struct
+{
+    UINT16              conn_id;
+    tBTA_GATT_STATUS    status;
+    tBTA_GATT_SRVC_ID   srvc_id;
+    tBTA_GATT_ID        char_id;
+    tBTA_GATT_ID        descr_type;
+}tBTA_GATTC_WRITE;
+
+typedef struct
+{
+    UINT16              conn_id;
+    tBTA_GATT_STATUS    status;
+}tBTA_GATTC_EXEC_CMPL;
+
+typedef struct
+{
+    UINT16              conn_id;
+    tBTA_GATT_STATUS    status;
+}tBTA_GATTC_SEARCH_CMPL;
+
+typedef struct
+{
+    UINT16              conn_id;
+    tBTA_GATT_SRVC_ID   service_uuid;
+}tBTA_GATTC_SRVC_RES;
+
+typedef struct
+{
+    UINT16              conn_id;
+    tBTA_GATT_STATUS    status;
+    UINT16              mtu;
+}tBTA_GATTC_CFG_MTU;
+
+typedef struct
+{
+    tBTA_GATT_STATUS    status;
+    UINT16              conn_id;
+    tBTA_GATTC_IF       client_if;
+    BD_ADDR             remote_bda;
+    tBTA_TRANSPORT      transport;
+    UINT16              mtu;
+}tBTA_GATTC_OPEN;
+
+typedef struct
+{
+    tBTA_GATT_STATUS    status;
+    UINT16              conn_id;
+    tBTA_GATTC_IF       client_if;
+    BD_ADDR             remote_bda;
+    tBTA_GATT_REASON    reason;         /* disconnect reason code, not useful when connect event is reported */
+}tBTA_GATTC_CLOSE;
+
+typedef struct
+{
+    UINT16              conn_id;
+    BD_ADDR             bda;
+    tBTA_GATTC_CHAR_ID  char_id;
+    tBTA_GATT_ID        descr_type;
+    UINT16              len;
+    UINT8               value[BTA_GATT_MAX_ATTR_LEN];
+    BOOLEAN             is_notify;
+}tBTA_GATTC_NOTIFY;
+
+typedef struct
+{
+    UINT16 conn_id;
+    BOOLEAN congested; /* congestion indicator */
+}tBTA_GATTC_CONGEST;
+
+// btla-specific ++
+typedef struct
+{
+    tBTA_GATT_STATUS        status;
+    tBTA_GATTC_IF           client_if;
+    UINT16                  conn_id;
+    BD_ADDR                 remote_bda;
+}tBTA_GATTC_OPEN_CLOSE;
+// btla-specific --
+
+typedef struct
+{
+    tBTA_GATTC_IF       client_if;
+    BD_ADDR             remote_bda;
+}tBTA_GATTC_ENC_CMPL_CB;
+
+typedef union
+{
+    tBTA_GATT_STATUS        status;
+
+    tBTA_GATTC_SEARCH_CMPL  search_cmpl;          /* discovery complete */
+    tBTA_GATTC_SRVC_RES     srvc_res;          /* discovery result */
+    tBTA_GATTC_REG          reg_oper;              /* registration data */
+    tBTA_GATTC_OPEN         open;
+    tBTA_GATTC_CLOSE        close;
+    tBTA_GATTC_READ         read;             /* read attribute/descriptor data */
+    tBTA_GATTC_WRITE        write;            /* write complete data */
+    tBTA_GATTC_EXEC_CMPL    exec_cmpl;       /*  execute complete */
+    tBTA_GATTC_NOTIFY       notify;           /* notification/indication event data */
+    tBTA_GATTC_ENC_CMPL_CB  enc_cmpl;
+    BD_ADDR                 remote_bda;     /* service change event */
+    tBTA_GATTC_CFG_MTU      cfg_mtu;        /* configure MTU operation */
+    tBTA_GATTC_CONGEST      congest;
+} tBTA_GATTC;
+
+/* GATTC enable callback function */
+typedef void (tBTA_GATTC_ENB_CBACK)(tBTA_GATT_STATUS status);
+
+/* Client callback function */
+typedef void (tBTA_GATTC_CBACK)(tBTA_GATTC_EVT event, tBTA_GATTC *p_data);
+
+
+/* GATT Server Data Structure */
+/* Server callback function events */
+#define BTA_GATTS_REG_EVT                               0
+#define BTA_GATTS_READ_EVT                              GATTS_REQ_TYPE_READ         /* 1 */
+#define BTA_GATTS_WRITE_EVT                             GATTS_REQ_TYPE_WRITE        /* 2 */
+#define BTA_GATTS_EXEC_WRITE_EVT                        GATTS_REQ_TYPE_WRITE_EXEC   /* 3 */
+#define BTA_GATTS_MTU_EVT                               GATTS_REQ_TYPE_MTU          /* 4 */
+#define BTA_GATTS_CONF_EVT                              GATTS_REQ_TYPE_CONF         /* 5 */
+#define BTA_GATTS_DEREG_EVT                             6
+#define BTA_GATTS_CREATE_EVT                            7
+#define BTA_GATTS_ADD_INCL_SRVC_EVT                     8
+#define BTA_GATTS_ADD_CHAR_EVT                          9
+#define BTA_GATTS_ADD_CHAR_DESCR_EVT                    10
+#define BTA_GATTS_DELELTE_EVT                           11
+#define BTA_GATTS_START_EVT                             12
+#define BTA_GATTS_STOP_EVT                              13
+#define BTA_GATTS_CONNECT_EVT                           14
+#define BTA_GATTS_DISCONNECT_EVT                        15
+#define BTA_GATTS_OPEN_EVT                              16
+#define BTA_GATTS_CANCEL_OPEN_EVT                       17
+#define BTA_GATTS_CLOSE_EVT                             18
+#define BTA_GATTS_LISTEN_EVT                            19
+#define BTA_GATTS_CONGEST_EVT                           20
+
+typedef UINT8  tBTA_GATTS_EVT;
+typedef tGATT_IF tBTA_GATTS_IF;
+
+/* Attribute permissions
+*/
+#define BTA_GATT_PERM_READ              GATT_PERM_READ              /* bit 0 -  0x0001 */
+#define BTA_GATT_PERM_READ_ENCRYPTED    GATT_PERM_READ_ENCRYPTED    /* bit 1 -  0x0002 */
+#define BTA_GATT_PERM_READ_ENC_MITM     GATT_PERM_READ_ENC_MITM     /* bit 2 -  0x0004 */
+#define BTA_GATT_PERM_WRITE             GATT_PERM_WRITE             /* bit 4 -  0x0010 */
+#define BTA_GATT_PERM_WRITE_ENCRYPTED   GATT_PERM_WRITE_ENCRYPTED   /* bit 5 -  0x0020 */
+#define BTA_GATT_PERM_WRITE_ENC_MITM    GATT_PERM_WRITE_ENC_MITM    /* bit 6 -  0x0040 */
+#define BTA_GATT_PERM_WRITE_SIGNED      GATT_PERM_WRITE_SIGNED      /* bit 7 -  0x0080 */
+#define BTA_GATT_PERM_WRITE_SIGNED_MITM GATT_PERM_WRITE_SIGNED_MITM /* bit 8 -  0x0100 */
+typedef UINT16 tBTA_GATT_PERM;
+
+#define BTA_GATTS_INVALID_APP   0xff
+
+#define BTA_GATTS_INVALID_IF    0
+
+/* definition of characteristic properties */
+#define BTA_GATT_CHAR_PROP_BIT_BROADCAST    GATT_CHAR_PROP_BIT_BROADCAST    /* 0x01 */
+#define BTA_GATT_CHAR_PROP_BIT_READ         GATT_CHAR_PROP_BIT_READ    /* 0x02 */
+#define BTA_GATT_CHAR_PROP_BIT_WRITE_NR     GATT_CHAR_PROP_BIT_WRITE_NR    /* 0x04 */
+#define BTA_GATT_CHAR_PROP_BIT_WRITE        GATT_CHAR_PROP_BIT_WRITE       /* 0x08 */
+#define BTA_GATT_CHAR_PROP_BIT_NOTIFY       GATT_CHAR_PROP_BIT_NOTIFY      /* 0x10 */
+#define BTA_GATT_CHAR_PROP_BIT_INDICATE     GATT_CHAR_PROP_BIT_INDICATE    /* 0x20 */
+#define BTA_GATT_CHAR_PROP_BIT_AUTH         GATT_CHAR_PROP_BIT_AUTH        /* 0x40 */
+#define BTA_GATT_CHAR_PROP_BIT_EXT_PROP     GATT_CHAR_PROP_BIT_EXT_PROP    /* 0x80 */
+typedef UINT8 tBTA_GATT_CHAR_PROP;
+
+#ifndef BTA_GATTC_CHAR_DESCR_MAX
+#define BTA_GATTC_CHAR_DESCR_MAX        7
+#endif
+
+/***********************  NV callback Data Definitions   **********************
+*/
+typedef struct
+{
+    tBT_UUID app_uuid128;
+    tBT_UUID svc_uuid;
+    UINT16   svc_inst;
+    UINT16   s_handle;
+    UINT16   e_handle;
+    BOOLEAN  is_primary;      /* primary service or secondary */
+} tBTA_GATTS_HNDL_RANGE;
+
+#define BTA_GATTS_SRV_CHG_CMD_ADD_CLIENT       GATTS_SRV_CHG_CMD_ADD_CLIENT
+#define BTA_GATTS_SRV_CHG_CMD_UPDATE_CLIENT    GATTS_SRV_CHG_CMD_UPDATE_CLIENT
+#define BTA_GATTS_SRV_CHG_CMD_REMOVE_CLIENT    GATTS_SRV_CHG_CMD_REMOVE_CLIENT
+#define BTA_GATTS_SRV_CHG_CMD_READ_NUM_CLENTS  GATTS_SRV_CHG_CMD_READ_NUM_CLENTS
+#define BTA_GATTS_SRV_CHG_CMD_READ_CLENT       GATTS_SRV_CHG_CMD_READ_CLENT
+typedef tGATTS_SRV_CHG_CMD tBTA_GATTS_SRV_CHG_CMD;
+
+typedef tGATTS_SRV_CHG     tBTA_GATTS_SRV_CHG;
+typedef tGATTS_SRV_CHG_REQ tBTA_GATTS_SRV_CHG_REQ;
+typedef tGATTS_SRV_CHG_RSP tBTA_GATTS_SRV_CHG_RSP;
+
+#define BTA_GATT_TRANSPORT_LE       GATT_TRANSPORT_LE
+#define BTA_GATT_TRANSPORT_BR_EDR   GATT_TRANSPORT_BR_EDR
+#define BTA_GATT_TRANSPORT_LE_BR_EDR    GATT_TRANSPORT_LE_BR_EDR
+typedef UINT8 tBTA_GATT_TRANSPORT;
+
+/* attribute value */
+typedef tGATT_VALUE tBTA_GATT_VALUE;
+
+/* attribute response data */
+typedef tGATTS_RSP tBTA_GATTS_RSP;
+
+/* attribute request data from the client */
+#define BTA_GATT_PREP_WRITE_CANCEL   0x00
+#define BTA_GATT_PREP_WRITE_EXEC     0x01
+typedef tGATT_EXEC_FLAG tBTA_GATT_EXEC_FLAG;
+
+/* read request always based on UUID */
+typedef tGATT_READ_REQ tTA_GBATT_READ_REQ;
+
+/* write request data */
+typedef tGATT_WRITE_REQ tBTA_GATT_WRITE_REQ;
+
+/* callback data for server access request from client */
+typedef tGATTS_DATA tBTA_GATTS_REQ_DATA;
+
+typedef struct
+{
+    tBTA_GATT_STATUS    status;
+    BD_ADDR             remote_bda;
+    UINT32              trans_id;
+    UINT16              conn_id;
+    tBTA_GATTS_REQ_DATA *p_data;
+}tBTA_GATTS_REQ;
+
+typedef struct
+{
+    tBTA_GATTS_IF       server_if;
+    tBTA_GATT_STATUS    status;
+// btla-specific ++
+    tBT_UUID            uuid;
+// btla-specific --
+}tBTA_GATTS_REG_OPER;
+
+
+typedef struct
+{
+    tBTA_GATTS_IF       server_if;
+    UINT16              service_id;
+// btla-specific ++
+    UINT16              svc_instance;
+    BOOLEAN             is_primary;
+    tBTA_GATT_STATUS    status;
+    tBT_UUID            uuid;
+// btla-specific --
+}tBTA_GATTS_CREATE;
+
+typedef struct
+{
+    tBTA_GATTS_IF       server_if;
+    UINT16              service_id;
+    UINT16              attr_id;
+    tBTA_GATT_STATUS    status;
+// btla-specific ++
+    tBT_UUID            char_uuid;
+// btla-specific --
+}tBTA_GATTS_ADD_RESULT;
+
+typedef struct
+{
+    tBTA_GATTS_IF       server_if;
+    UINT16              service_id;
+    tBTA_GATT_STATUS    status;
+}tBTA_GATTS_SRVC_OPER;
+
+
+typedef struct
+{
+    tBTA_GATTS_IF       server_if;
+    BD_ADDR             remote_bda;
+    UINT16              conn_id;
+    tBTA_GATT_REASON    reason; /* report disconnect reason */
+    tBTA_GATT_TRANSPORT transport;
+}tBTA_GATTS_CONN;
+
+typedef struct
+{
+    UINT16 conn_id;
+    BOOLEAN congested; /* report channel congestion indicator */
+}tBTA_GATTS_CONGEST;
+
+typedef struct
+{
+    UINT16 conn_id; /* connection ID */
+    tBTA_GATT_STATUS status; /* notification/indication status */
+}tBTA_GATTS_CONF;
+
+/* GATTS callback data */
+typedef union
+{
+    tBTA_GATTS_REG_OPER     reg_oper;
+    tBTA_GATTS_CREATE       create;
+    tBTA_GATTS_SRVC_OPER    srvc_oper;
+    tBTA_GATT_STATUS        status;      /* BTA_GATTS_LISTEN_EVT */
+    tBTA_GATTS_ADD_RESULT   add_result;  /* add included service: BTA_GATTS_ADD_INCL_SRVC_EVT
+                                           add char : BTA_GATTS_ADD_CHAR_EVT
+                                           add char descriptor: BTA_GATTS_ADD_CHAR_DESCR_EVT */
+    tBTA_GATTS_REQ          req_data;
+    tBTA_GATTS_CONN         conn;       /* BTA_GATTS_CONN_EVT */
+    tBTA_GATTS_CONGEST      congest;    /* BTA_GATTS_CONGEST_EVT callback data */
+    tBTA_GATTS_CONF         confirm;    /* BTA_GATTS_CONF_EVT callback data */
+}tBTA_GATTS;
+
+/* GATTS enable callback function */
+typedef void (tBTA_GATTS_ENB_CBACK)(tBTA_GATT_STATUS status);
+
+/* Server callback function */
+typedef void (tBTA_GATTS_CBACK)(tBTA_GATTS_EVT event,  tBTA_GATTS *p_data);
+
+/*****************************************************************************
+**  External Function Declarations
+*****************************************************************************/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**************************
+**  Client Functions
+***************************/
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_Disable
+**
+** Description      This function is called to disable the GATTC module
+**
+** Parameters       None.
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_GATTC_Disable(void);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_AppRegister
+**
+** Description      This function is called to register application callbacks
+**                    with BTA GATTC module.
+**
+** Parameters       p_app_uuid - applicaiton UUID
+**                  p_client_cb - pointer to the application callback function.
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_GATTC_AppRegister(tBT_UUID *p_app_uuid, tBTA_GATTC_CBACK *p_client_cb);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_AppDeregister
+**
+** Description      This function is called to deregister an application
+**                  from BTA GATTC module.
+**
+** Parameters       client_if - client interface identifier.
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_GATTC_AppDeregister (tBTA_GATTC_IF client_if);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_Open
+**
+** Description      Open a direct connection or add a background auto connection
+**                  bd address
+**
+** Parameters       client_if: server interface.
+**                  remote_bda: remote device BD address.
+**                  is_direct: direct connection or background auto connection
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_GATTC_Open(tBTA_GATTC_IF client_if, BD_ADDR remote_bda,
+                           BOOLEAN is_direct, tBTA_GATT_TRANSPORT transport);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_CancelOpen
+**
+** Description      Open a direct connection or add a background auto connection
+**                  bd address
+**
+** Parameters       client_if: server interface.
+**                  remote_bda: remote device BD address.
+**                  is_direct: direct connection or background auto connection
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_GATTC_CancelOpen(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, BOOLEAN is_direct);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_Close
+**
+** Description      Close a connection to a GATT server.
+**
+** Parameters       conn_id: connectino ID to be closed.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_GATTC_Close(UINT16 conn_id);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_ServiceSearchRequest
+**
+** Description      This function is called to request a GATT service discovery
+**                    on a GATT server. This function report service search result
+**                  by a callback event, and followed by a service search complete
+**                  event.
+**
+** Parameters       conn_id: connection ID.
+**                  p_srvc_uuid: a UUID of the service application is interested in.
+**                              If Null, discover for all services.
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_GATTC_ServiceSearchRequest(UINT16 conn_id, tBT_UUID *p_srvc_uuid);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetFirstChar
+**
+** Description      This function is called to find the first charatceristic of the
+**                  service on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_srvc_id: the service ID of which the characteristic is belonged to.
+**                  p_char_uuid_cond: Characteristic UUID, if NULL find the first available
+**                               characteristic.
+**                  p_char_result: output parameter which will store the GATT
+**                                  characteristic ID.
+**                  p_property: output parameter to carry the characteristic property.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+extern tBTA_GATT_STATUS  BTA_GATTC_GetFirstChar (UINT16              conn_id,
+                                                 tBTA_GATT_SRVC_ID   *p_srvc_id,
+                                                 tBT_UUID            *p_char_uuid_cond,
+                                                 tBTA_GATTC_CHAR_ID  *p_char_result,
+                                                 tBTA_GATT_CHAR_PROP *p_property);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetNextChar
+**
+** Description      This function is called to find the next charatceristic of the
+**                  service on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_start_char_id: start the characteristic search from the next record
+**                           after the one identified by char_id.
+**                  p_char_uuid_cond: Characteristic UUID, if NULL find the first available
+**                               characteristic.
+**                  p_char_result: output parameter which will store the GATT
+**                                  characteristic ID.
+**                  p_property: output parameter, characteristic property.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+extern tBTA_GATT_STATUS  BTA_GATTC_GetNextChar (UINT16 conn_id,
+                                                tBTA_GATTC_CHAR_ID  *p_start_char_id,
+                                                tBT_UUID            *p_char_uuid_cond,
+                                                tBTA_GATTC_CHAR_ID  *p_char_result,
+                                                tBTA_GATT_CHAR_PROP *p_property);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetFirstCharDescr
+**
+** Description      This function is called to find the first charatceristic descriptor of the
+**                  charatceristic on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_char_id: the characteristic ID of which the descriptor is belonged to.
+**                  p_descr_uuid_cond: Characteristic Descr UUID, if NULL find the first available
+**                               characteristic.
+**                  p_descr_result: output parameter which will store the GATT
+**                                  characteristic descriptor ID.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+extern tBTA_GATT_STATUS  BTA_GATTC_GetFirstCharDescr (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id,
+                                                      tBT_UUID *p_descr_uuid_cond,
+                                                      tBTA_GATTC_CHAR_DESCR_ID *p_descr_result);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetNextCharDescr
+**
+** Description      This function is called to find the next charatceristic of the
+**                  service on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_start_descr_id: start the characteristic search from the next record
+**                           after the one identified by p_start_descr_id.
+**                  p_descr_uuid_cond: Characteristic descriptor UUID, if NULL find
+**                               the first available characteristic descriptor.
+**                  p_descr_result: output parameter which will store the GATT
+**                                  characteristic descriptor ID.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+extern tBTA_GATT_STATUS  BTA_GATTC_GetNextCharDescr (UINT16 conn_id,
+                                                     tBTA_GATTC_CHAR_DESCR_ID *p_start_descr_id,
+                                                     tBT_UUID           *p_descr_uuid_cond,
+                                                     tBTA_GATTC_CHAR_DESCR_ID *p_descr_result);
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetFirstIncludedService
+**
+** Description      This function is called to find the first included service of the
+**                  service on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_srvc_id: the service ID of which the included service is belonged to.
+**                  p_uuid_cond: include service UUID, if NULL find the first available
+**                               included service.
+**                  p_result: output parameter which will store the GATT ID
+**                              of the included service found.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+extern tBTA_GATT_STATUS  BTA_GATTC_GetFirstIncludedService(UINT16 conn_id,
+                                                           tBTA_GATT_SRVC_ID    *p_srvc_id,
+                                                           tBT_UUID               *p_uuid_cond,
+                                                           tBTA_GATTC_INCL_SVC_ID *p_result);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetNextIncludedService
+**
+** Description      This function is called to find the next included service of the
+**                  service on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_start_id: start the search from the next record
+**                                  after the one identified by p_start_id.
+**                  p_uuid_cond: Included service UUID, if NULL find the first available
+**                               included service.
+**                  p_result: output parameter which will store the GATT ID
+**                              of the included service found.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+extern tBTA_GATT_STATUS  BTA_GATTC_GetNextIncludedService(UINT16 conn_id,
+                                                          tBTA_GATTC_INCL_SVC_ID *p_start_id,
+                                                          tBT_UUID             *p_uuid_cond,
+                                                          tBTA_GATTC_INCL_SVC_ID *p_result);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_ReadCharacteristic
+**
+** Description      This function is called to read a service's characteristics of
+**                    the given characteritisc ID.
+**
+** Parameters       conn_id - connectino ID.
+**                    p_char_id - characteritic ID to read.
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_GATTC_ReadCharacteristic (UINT16 conn_id,
+                                          tBTA_GATTC_CHAR_ID *p_char_id,
+                                          tBTA_GATT_AUTH_REQ auth_req);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_ReadCharDescr
+**
+** Description      This function is called to read a characteristics descriptor.
+**
+** Parameters       conn_id - connection ID.
+**                    p_char_descr_id - characteritic descriptor ID to read.
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_GATTC_ReadCharDescr (UINT16 conn_id,
+                                     tBTA_GATTC_CHAR_DESCR_ID *p_char_descr_id,
+                                     tBTA_GATT_AUTH_REQ auth_req);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_WriteCharValue
+**
+** Description      This function is called to write characteristic value.
+**
+** Parameters       conn_id - connection ID.
+**                    p_char_id - characteristic ID to write.
+**                    write_type - type of write.
+**                  len: length of the data to be written.
+**                  p_value - the value to be written.
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_GATTC_WriteCharValue (UINT16 conn_id,
+                                      tBTA_GATTC_CHAR_ID *p_char_id,
+                                      tBTA_GATTC_WRITE_TYPE  write_type,
+                                      UINT16 len,
+                                      UINT8 *p_value,
+                                      tBTA_GATT_AUTH_REQ auth_req);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_WriteCharDescr
+**
+** Description      This function is called to write characteristic descriptor value.
+**
+** Parameters       conn_id - connection ID
+**                    p_char_descr_id - characteristic descriptor ID to write.
+**                    write_type - type of write.
+**                  p_value - the value to be written.
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_GATTC_WriteCharDescr (UINT16 conn_id,
+                                      tBTA_GATTC_CHAR_DESCR_ID *p_char_descr_id,
+                                      tBTA_GATTC_WRITE_TYPE  write_type,
+                                      tBTA_GATT_UNFMT   *p_data,
+                                      tBTA_GATT_AUTH_REQ auth_req);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_SendIndConfirm
+**
+** Description      This function is called to send handle value confirmation.
+**
+** Parameters       conn_id - connection ID.
+**                    p_char_id - characteristic ID to confrim.
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_GATTC_SendIndConfirm (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_RegisterForNotifications
+**
+** Description      This function is called to register for notification of a service.
+**
+** Parameters       client_if   - client interface.
+**                  remote_bda  - target GATT server.
+**                  p_char_id   - pointer to GATT characteristic ID.
+**
+** Returns          OK if registration succeed, otherwise failed.
+**
+*******************************************************************************/
+extern tBTA_GATT_STATUS BTA_GATTC_RegisterForNotifications (tBTA_GATTC_IF      client_if,
+                                                            BD_ADDR            remote_bda,
+                                                            tBTA_GATTC_CHAR_ID *p_char_id);
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_DeregisterForNotifications
+**
+** Description      This function is called to de-register for notification of a servbice.
+**
+** Parameters       client_if - client interface.
+**                  remote_bda - target GATT server.
+**                  p_char_id - pointer to a GATT characteristic ID.
+**
+** Returns          OK if deregistration succeed, otherwise failed.
+**
+*******************************************************************************/
+extern tBTA_GATT_STATUS BTA_GATTC_DeregisterForNotifications (tBTA_GATTC_IF      client_if,
+                                                              BD_ADDR            remote_bda,
+                                                              tBTA_GATTC_CHAR_ID *p_char_id);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_PrepareWrite
+**
+** Description      This function is called to prepare write a characteristic value.
+**
+** Parameters       conn_id - connection ID.
+**                    p_char_id - GATT characteritic ID of the service.
+**                  offset - offset of the write value.
+**                  len: length of the data to be written.
+**                  p_value - the value to be written.
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_GATTC_PrepareWrite  (UINT16 conn_id,
+                                     tBTA_GATTC_CHAR_ID *p_char_id,
+                                     UINT16 offset,
+                                     UINT16 len,
+                                     UINT8 *p_value,
+                                     tBTA_GATT_AUTH_REQ auth_req);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_ExecuteWrite
+**
+** Description      This function is called to execute write a prepare write sequence.
+**
+** Parameters       conn_id - connection ID.
+**                    is_execute - execute or cancel.
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_GATTC_ExecuteWrite  (UINT16 conn_id, BOOLEAN is_execute);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_ReadMultiple
+**
+** Description      This function is called to read multiple characteristic or
+**                  characteristic descriptors.
+**
+** Parameters       conn_id - connectino ID.
+**                    p_read_multi - read multiple parameters.
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_GATTC_ReadMultiple(UINT16 conn_id, tBTA_GATTC_MULTI *p_read_multi,
+                                   tBTA_GATT_AUTH_REQ auth_req);
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_Refresh
+**
+** Description      Refresh the server cache of the remote device
+**
+** Parameters       remote_bda: remote device BD address.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_GATTC_Refresh(BD_ADDR remote_bda);
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_Listen
+**
+** Description      Start advertisement to listen for connection request.
+**
+** Parameters       client_if: server interface.
+**                  start: to start or stop listening for connection
+**                  remote_bda: remote device BD address, if listen to all device
+**                              use NULL.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_GATTC_Listen(tBTA_GATTC_IF client_if, BOOLEAN start, BD_ADDR_PTR target_bda);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_Broadcast
+**
+** Description      Start broadcasting (non-connectable advertisements)
+**
+** Parameters       client_if: client interface.
+**                  start: to start or stop listening for connection
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_GATTC_Broadcast(tBTA_GATTC_IF client_if, BOOLEAN start);
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_ConfigureMTU
+**
+** Description      Configure the MTU size in the GATT channel. This can be done
+**                  only once per connection.
+**
+** Parameters       conn_id: connection ID.
+**                  mtu: desired MTU size to use.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_GATTC_ConfigureMTU (UINT16 conn_id, UINT16 mtu);
+
+/*******************************************************************************
+**  BTA GATT Server API
+********************************************************************************/
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_Init
+**
+** Description      This function is called to initalize GATTS module
+**
+** Parameters       None
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_GATTS_Init();
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_Disable
+**
+** Description      This function is called to disable GATTS module
+**
+** Parameters       None.
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_GATTS_Disable(void);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_AppRegister
+**
+** Description      This function is called to register application callbacks
+**                    with BTA GATTS module.
+**
+** Parameters       p_app_uuid - applicaiton UUID
+**                  p_cback - pointer to the application callback function.
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_GATTS_AppRegister(tBT_UUID *p_app_uuid, tBTA_GATTS_CBACK *p_cback);
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_AppDeregister
+**
+** Description      De-register with BTA GATT Server.
+**
+** Parameters       server_if: server interface
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_GATTS_AppDeregister(tBTA_GATTS_IF server_if);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_CreateService
+**
+** Description      Create a service. When service creation is done, a callback
+**                  event BTA_GATTS_CREATE_SRVC_EVT is called to report status
+**                  and service ID to the profile. The service ID obtained in
+**                  the callback function needs to be used when adding included
+**                  service and characteristics/descriptors into the service.
+**
+** Parameters       server_if: server interface.
+**                  p_service_uuid: service UUID.
+**                  inst: instance ID number of this service.
+**                  num_handle: numble of handle requessted for this service.
+**                  is_primary: is this service a primary one or not.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_GATTS_CreateService(tBTA_GATTS_IF server_if, tBT_UUID *p_service_uuid,
+                                    UINT8 inst, UINT16 num_handle, BOOLEAN is_primary);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_AddIncludeService
+**
+** Description      This function is called to add an included service. After included
+**                  service is included, a callback event BTA_GATTS_ADD_INCL_SRVC_EVT
+**                  is reported the included service ID.
+**
+** Parameters       service_id: service ID to which this included service is to
+**                              be added.
+**                  included_service_id: the service ID to be included.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_GATTS_AddIncludeService(UINT16 service_id, UINT16 included_service_id);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_AddCharacteristic
+**
+** Description      This function is called to add a characteristic into a service.
+**
+** Parameters       service_id: service ID to which this included service is to
+**                              be added.
+**                  p_char_uuid : Characteristic UUID.
+**                  perm      : Characteristic value declaration attribute permission.
+**                  property  : Characteristic Properties
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_GATTS_AddCharacteristic (UINT16 service_id,  tBT_UUID   *p_char_uuid,
+                                         tBTA_GATT_PERM perm, tBTA_GATT_CHAR_PROP property);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_AddCharDescriptor
+**
+** Description      This function is called to add characteristic descriptor. When
+**                  it's done, a callback event BTA_GATTS_ADD_DESCR_EVT is called
+**                  to report the status and an ID number for this descriptor.
+**
+** Parameters       service_id: service ID to which this charatceristic descriptor is to
+**                              be added.
+**                  perm: descriptor access permission.
+**                  p_descr_uuid: descriptor UUID.
+**                  p_descr_params: descriptor value if it's read only descriptor.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+extern void BTA_GATTS_AddCharDescriptor (UINT16 service_id,
+                                         tBTA_GATT_PERM perm,
+                                         tBT_UUID  * p_descr_uuid);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_DeleteService
+**
+** Description      This function is called to delete a service. When this is done,
+**                  a callback event BTA_GATTS_DELETE_EVT is report with the status.
+**
+** Parameters       service_id: service_id to be deleted.
+**
+** Returns          returns none.
+**
+*******************************************************************************/
+extern void  BTA_GATTS_DeleteService(UINT16 service_id);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_StartService
+**
+** Description      This function is called to start a service.
+**
+** Parameters       service_id: the service ID to be started.
+**                  sup_transport: supported trasnport.
+**
+** Returns          None.
+**
+*******************************************************************************/
+extern void  BTA_GATTS_StartService(UINT16 service_id, tBTA_GATT_TRANSPORT sup_transport);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_StopService
+**
+** Description      This function is called to stop a service.
+**
+** Parameters       service_id - service to be topped.
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_GATTS_StopService(UINT16 service_id);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_HandleValueIndication
+**
+** Description      This function is called to read a characteristics descriptor.
+**
+** Parameters       conn_id - connection identifier.
+**					attr_id - attribute ID to indicate.
+**                  data_len - indicate data length.
+**                  p_data: data to indicate.
+**                  need_confirm - if this indication expects a confirmation or not.
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_GATTS_HandleValueIndication (UINT16 conn_id, UINT16 attr_id,
+                                             UINT16 data_len,
+                                             UINT8 *p_data,
+                                             BOOLEAN need_confirm);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_SendRsp
+**
+** Description      This function is called to send a response to a request.
+**
+** Parameters       conn_id - connection identifier.
+**                  trans_id - transaction ID.
+**                  status - response status
+**                  p_msg - response data.
+**
+** Returns          None
+**
+*******************************************************************************/
+extern void BTA_GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id,
+                               tBTA_GATT_STATUS status, tBTA_GATTS_RSP *p_msg);
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_Open
+**
+** Description      Open a direct open connection or add a background auto connection
+**                  bd address
+**
+** Parameters       server_if: server interface.
+**                  remote_bda: remote device BD address.
+**                  is_direct: direct connection or background auto connection
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_GATTS_Open(tBTA_GATTS_IF server_if, BD_ADDR remote_bda,
+                           BOOLEAN is_direct, tBTA_GATT_TRANSPORT transport);
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_CancelOpen
+**
+** Description      Cancel a direct open connection or remove a background auto connection
+**                  bd address
+**
+** Parameters       server_if: server interface.
+**                  remote_bda: remote device BD address.
+**                  is_direct: direct connection or background auto connection
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_GATTS_CancelOpen(tBTA_GATTS_IF server_if, BD_ADDR remote_bda, BOOLEAN is_direct);
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_Close
+**
+** Description      Close a connection  a remote device.
+**
+** Parameters       conn_id: connectino ID to be closed.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_GATTS_Close(UINT16 conn_id);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_Listen
+**
+** Description      Start advertisement to listen for connection request for a
+**                  GATT server
+**
+** Parameters       server_if: server interface.
+**                  start: to start or stop listening for connection
+**                  remote_bda: remote device BD address, if listen to all device
+**                              use NULL.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_GATTS_Listen(tBTA_GATTS_IF server_if, BOOLEAN start,
+                             BD_ADDR_PTR target_bda);
+
+
+#ifdef __cplusplus
+
+}
+#endif
+
+
+#endif /* BTA_GATT_API_H */

+ 119 - 0
components/bt/bluedroid/bta/include/bta_gattc_ci.h

@@ -0,0 +1,119 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the interface file for GATT call-in functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_GATTC_CI_H
+#define BTA_GATTC_CI_H
+
+#include "bta_gatt_api.h"
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+
+/* Open Complete Event */
+typedef struct
+{
+    BT_HDR            hdr;
+    tBTA_GATT_STATUS  status;
+} tBTA_GATTC_CI_EVT;
+
+#define BTA_GATTC_NV_LOAD_MAX   10
+
+/* Read Ready Event */
+typedef struct
+{
+    BT_HDR              hdr;
+    tBTA_GATT_STATUS    status;
+    UINT16              num_attr;
+    tBTA_GATTC_NV_ATTR  attr[BTA_GATTC_NV_LOAD_MAX];
+} tBTA_GATTC_CI_LOAD;
+
+
+/*****************************************************************************
+**  Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_gattc_ci_cache_open
+**
+** Description      This function sends an event to indicate server cache open
+**                  completed.
+**
+** Parameters       server_bda - server BDA of this cache.
+**                  status - BTA_GATT_OK if full buffer of data,
+**                           BTA_GATT_FAIL if an error has occurred.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void bta_gattc_ci_cache_open(BD_ADDR server_bda, UINT16 evt,
+                                            tBTA_GATT_STATUS status, UINT16 conn_id);
+
+/*******************************************************************************
+**
+** Function         bta_gattc_ci_cache_load
+**
+** Description      This function sends an event to BTA indicating the phone has
+**                  load the servere cache and ready to send it to the stack.
+**
+** Parameters       server_bda - server BDA of this cache.
+**                  num_bytes_read - number of bytes read into the buffer
+**                      specified in the read callout-function.
+**                  status - BTA_GATT_OK if full buffer of data,
+**                           BTA_GATT_FAIL if an error has occurred.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void bta_gattc_ci_cache_load(BD_ADDR server_bda, UINT16 evt,
+                                    UINT16 num_attr, tBTA_GATTC_NV_ATTR *p_atrr,
+                                    tBTA_GATT_STATUS status, UINT16 conn_id);
+
+/*******************************************************************************
+**
+** Function         bta_gattc_ci_save
+**
+** Description      This function sends an event to BTA indicating the phone has
+**                  save the server cache.
+**
+** Parameters       server_bda - server BDA of this cache.
+**                  status - BTA_GATT_OK if full buffer of data,
+**                           BTA_GATT_FAIL if an error has occurred.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void bta_gattc_ci_cache_save(BD_ADDR server_bda, UINT16 evt,
+                                    tBTA_GATT_STATUS status, UINT16 conn_id);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_GATTC_CI_H */

+ 114 - 0
components/bt/bluedroid/bta/include/bta_gattc_co.h

@@ -0,0 +1,114 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the interface file for BTA GATT client call-out functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_GATTC_CO_H
+#define BTA_GATTC_CO_H
+
+#include "bta_gatt_api.h"
+
+/*******************************************************************************
+**
+** Function         bta_gattc_co_cache_open
+**
+** Description      This callout function is executed by GATTC when a GATT server
+**                  cache is ready to be sent.
+**
+** Parameter        server_bda: server bd address of this cache belongs to
+**                  evt: call in event to be passed in when cache open is done.
+**                  conn_id: connection ID of this cache operation attach to.
+**                  to_save: open cache to save or to load.
+**
+** Returns          void.
+**
+*******************************************************************************/
+extern void bta_gattc_co_cache_open(BD_ADDR server_bda, UINT16 evt,
+                                            UINT16 conn_id, BOOLEAN to_save);
+
+/*******************************************************************************
+**
+** Function         bta_gattc_co_cache_close
+**
+** Description      This callout function is executed by GATTC when a GATT server
+**                  cache is written completely.
+**
+** Parameter        server_bda: server bd address of this cache belongs to
+**                  conn_id: connection ID of this cache operation attach to.
+**
+** Returns          void.
+**
+*******************************************************************************/
+extern void bta_gattc_co_cache_close(BD_ADDR server_bda, UINT16 conn_id);
+
+/*******************************************************************************
+**
+** Function         bta_gattc_co_cache_save
+**
+** Description      This callout function is executed by GATT when a server cache
+**                  is available to save.
+**
+** Parameter        server_bda: server bd address of this cache belongs to
+**                  evt: call in event to be passed in when cache save is done.
+**                  num_attr: number of attribute to be save.
+**                  p_attr: pointer to the list of attributes to save.
+**                  attr_index: starting attribute index of the save operation.
+**                  conn_id: connection ID of this cache operation attach to.
+** Returns
+**
+*******************************************************************************/
+extern void bta_gattc_co_cache_save(BD_ADDR server_bda, UINT16 evt,
+                                    UINT16 num_attr, tBTA_GATTC_NV_ATTR *p_attr,
+                                    UINT16 attr_index, UINT16 conn_id);
+
+/*******************************************************************************
+**
+** Function         bta_gattc_co_cache_load
+**
+** Description      This callout function is executed by GATT when server cache
+**                  is required to load.
+**
+** Parameter        server_bda: server bd address of this cache belongs to
+**                  evt: call in event to be passed in when cache save is done.
+**                  num_attr: number of attribute to be save.
+**                  attr_index: starting attribute index of the save operation.
+**                  conn_id: connection ID of this cache operation attach to.
+** Returns
+**
+*******************************************************************************/
+extern void bta_gattc_co_cache_load(BD_ADDR server_bda, UINT16 evt,
+                                    UINT16 start_index, UINT16 conn_id);
+
+/*******************************************************************************
+**
+** Function         bta_gattc_co_cache_reset
+**
+** Description      This callout function is executed by GATTC to reset cache in
+**                  application
+**
+** Parameter        server_bda: server bd address of this cache belongs to
+**
+** Returns          void.
+**
+*******************************************************************************/
+extern void bta_gattc_co_cache_reset(BD_ADDR server_bda);
+
+#endif /* BTA_GATT_CO_H */

+ 554 - 0
components/bt/bluedroid/bta/include/bta_gattc_int.h

@@ -0,0 +1,554 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the private file for the file transfer client (FTC).
+ *
+ ******************************************************************************/
+#ifndef BTA_GATTC_INT_H
+#define BTA_GATTC_INT_H
+
+#include "bt_target.h"
+#include "bta_sys.h"
+#include "bta_gatt_api.h"
+#include "bta_gattc_ci.h"
+#include "bta_gattc_co.h"
+
+#include "gki.h"
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+enum
+{
+    BTA_GATTC_API_OPEN_EVT   = BTA_SYS_EVT_START(BTA_ID_GATTC),
+    BTA_GATTC_INT_OPEN_FAIL_EVT,
+    BTA_GATTC_API_CANCEL_OPEN_EVT,
+    BTA_GATTC_INT_CANCEL_OPEN_OK_EVT,
+
+    BTA_GATTC_API_READ_EVT,
+    BTA_GATTC_API_WRITE_EVT,
+    BTA_GATTC_API_EXEC_EVT,
+    BTA_GATTC_API_CFG_MTU_EVT,
+
+    BTA_GATTC_API_CLOSE_EVT,
+
+    BTA_GATTC_API_SEARCH_EVT,
+    BTA_GATTC_API_CONFIRM_EVT,
+    BTA_GATTC_API_READ_MULTI_EVT,
+    BTA_GATTC_API_REFRESH_EVT,
+
+    BTA_GATTC_INT_CONN_EVT,
+    BTA_GATTC_INT_DISCOVER_EVT,
+    BTA_GATTC_DISCOVER_CMPL_EVT,
+    BTA_GATTC_OP_CMPL_EVT,
+    BTA_GATTC_INT_DISCONN_EVT,
+
+    /* for cache loading/saving */
+    BTA_GATTC_START_CACHE_EVT,
+    BTA_GATTC_CI_CACHE_OPEN_EVT,
+    BTA_GATTC_CI_CACHE_LOAD_EVT,
+    BTA_GATTC_CI_CACHE_SAVE_EVT,
+
+    BTA_GATTC_INT_START_IF_EVT,
+    BTA_GATTC_API_REG_EVT,
+    BTA_GATTC_API_DEREG_EVT,
+    BTA_GATTC_API_LISTEN_EVT,
+    BTA_GATTC_API_BROADCAST_EVT,
+    BTA_GATTC_API_DISABLE_EVT,
+    BTA_GATTC_ENC_CMPL_EVT
+};
+typedef UINT16 tBTA_GATTC_INT_EVT;
+
+/* max client application GATTC can support */
+#ifndef     BTA_GATTC_CL_MAX
+#define     BTA_GATTC_CL_MAX    8 // 32
+#endif
+
+/* max known devices GATTC can support */
+#ifndef     BTA_GATTC_KNOWN_SR_MAX
+#define     BTA_GATTC_KNOWN_SR_MAX    5 // 10
+#endif
+
+#define BTA_GATTC_CONN_MAX      GATT_MAX_PHY_CHANNEL
+
+#ifndef BTA_GATTC_CLCB_MAX
+    #define BTA_GATTC_CLCB_MAX      GATT_CL_MAX_LCB
+#endif
+
+#define BTA_GATTC_WRITE_PREPARE          GATT_WRITE_PREPARE
+
+
+/* internal strucutre for GATTC register API  */
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBT_UUID                app_uuid;
+    tBTA_GATTC_CBACK        *p_cback;
+}tBTA_GATTC_API_REG;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_GATTC_IF           client_if;
+}tBTA_GATTC_INT_START_IF;
+
+typedef tBTA_GATTC_INT_START_IF tBTA_GATTC_API_DEREG;
+typedef tBTA_GATTC_INT_START_IF tBTA_GATTC_INT_DEREG;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    BD_ADDR                 remote_bda;
+    tBTA_GATTC_IF           client_if;
+    BOOLEAN                 is_direct;
+    tBTA_TRANSPORT          transport;
+} tBTA_GATTC_API_OPEN;
+
+typedef tBTA_GATTC_API_OPEN tBTA_GATTC_API_CANCEL_OPEN;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_GATT_AUTH_REQ      auth_req;
+    tBTA_GATT_SRVC_ID       srvc_id;
+    tBTA_GATT_ID            char_id;
+    tBTA_GATT_ID            *p_descr_type;
+} tBTA_GATTC_API_READ;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_GATT_AUTH_REQ      auth_req;
+    tBTA_GATT_SRVC_ID       srvc_id;
+    tBTA_GATT_ID            char_id;
+    tBTA_GATT_ID            *p_descr_type;
+    tBTA_GATTC_WRITE_TYPE   write_type;
+    UINT16                  offset;
+    UINT16                  len;
+    UINT8                   *p_value;
+}tBTA_GATTC_API_WRITE;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    BOOLEAN                 is_execute;
+}tBTA_GATTC_API_EXEC;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_GATT_SRVC_ID       srvc_id;
+    tBTA_GATT_ID            char_id;
+} tBTA_GATTC_API_CONFIRM;
+
+typedef tGATT_CL_COMPLETE tBTA_GATTC_CMPL;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    UINT8                   op_code;
+    tGATT_STATUS            status;
+    tBTA_GATTC_CMPL         *p_cmpl;
+}tBTA_GATTC_OP_CMPL;
+
+typedef struct
+{
+    BT_HDR              hdr;
+    tBT_UUID            *p_srvc_uuid;
+}tBTA_GATTC_API_SEARCH;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_GATT_AUTH_REQ      auth_req;
+    UINT8                   num_attr;
+    tBTA_GATTC_ATTR_ID      *p_id_list;
+}tBTA_GATTC_API_READ_MULTI;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    BD_ADDR_PTR             remote_bda;
+    tBTA_GATTC_IF           client_if;
+    BOOLEAN                 start;
+} tBTA_GATTC_API_LISTEN;
+
+
+typedef struct
+{
+    BT_HDR              hdr;
+    UINT16              mtu;
+}tBTA_GATTC_API_CFG_MTU;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    BD_ADDR                 remote_bda;
+    tBTA_GATTC_IF           client_if;
+    UINT8                   role;
+    tBT_TRANSPORT           transport;
+    tGATT_DISCONN_REASON    reason;
+}tBTA_GATTC_INT_CONN;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    BD_ADDR                 remote_bda;
+    tBTA_GATTC_IF           client_if;
+}tBTA_GATTC_ENC_CMPL;
+
+typedef union
+{
+    BT_HDR                      hdr;
+    tBTA_GATTC_API_REG          api_reg;
+    tBTA_GATTC_API_DEREG        api_dereg;
+    tBTA_GATTC_API_OPEN         api_conn;
+    tBTA_GATTC_API_CANCEL_OPEN  api_cancel_conn;
+    tBTA_GATTC_API_READ         api_read;
+    tBTA_GATTC_API_SEARCH       api_search;
+    tBTA_GATTC_API_WRITE        api_write;
+    tBTA_GATTC_API_CONFIRM      api_confirm;
+    tBTA_GATTC_API_EXEC         api_exec;
+    tBTA_GATTC_API_READ_MULTI   api_read_multi;
+    tBTA_GATTC_API_CFG_MTU      api_mtu;
+    tBTA_GATTC_OP_CMPL          op_cmpl;
+    tBTA_GATTC_CI_EVT           ci_open;
+    tBTA_GATTC_CI_EVT           ci_save;
+    tBTA_GATTC_CI_LOAD          ci_load;
+    tBTA_GATTC_INT_CONN         int_conn;
+    tBTA_GATTC_ENC_CMPL         enc_cmpl;
+
+    tBTA_GATTC_INT_START_IF     int_start_if;
+    tBTA_GATTC_INT_DEREG        int_dereg;
+    /* if peripheral role is supported */
+    tBTA_GATTC_API_LISTEN       api_listen;
+
+} tBTA_GATTC_DATA;
+
+
+/* GATT server cache on the client */
+typedef union
+{
+    UINT8               uuid128[LEN_UUID_128];
+    UINT16              uuid16;
+}tBTA_GATTC_UUID;
+
+typedef struct gattc_attr_cache
+{
+    tBTA_GATTC_UUID         *p_uuid;
+    struct                  gattc_attr_cache *p_next;
+    UINT16                  uuid_len;
+    UINT16                  attr_handle;
+    UINT8                   inst_id;
+    tBTA_GATT_CHAR_PROP     property; /* if characteristic, it is char property;
+                                         if included service, flag primary,
+                                         if descriptor, not used */
+    tBTA_GATTC_ATTR_TYPE    attr_type;
+// btla-specific ++
+} __attribute__((packed)) tBTA_GATTC_CACHE_ATTR;
+// btla-specific --
+
+typedef struct gattc_svc_cache
+{
+    tBTA_GATT_SRVC_ID       service_uuid;
+    tBTA_GATTC_CACHE_ATTR   *p_attr;
+    tBTA_GATTC_CACHE_ATTR   *p_last_attr;
+    UINT16                  s_handle;
+    UINT16                  e_handle;
+    struct                  gattc_svc_cache *p_next;
+    tBTA_GATTC_CACHE_ATTR   *p_cur_char;
+// btla-specific ++
+} __attribute__((packed)) tBTA_GATTC_CACHE;
+// btla-specific --
+
+typedef struct
+{
+    tBT_UUID            uuid;
+    UINT16              s_handle;
+    UINT16              e_handle;
+    BOOLEAN             is_primary;
+    UINT8               srvc_inst_id;
+    tBTA_GATT_CHAR_PROP property;
+}tBTA_GATTC_ATTR_REC;
+
+
+#define BTA_GATTC_MAX_CACHE_CHAR    40
+#define BTA_GATTC_ATTR_LIST_SIZE    (BTA_GATTC_MAX_CACHE_CHAR * sizeof(tBTA_GATTC_ATTR_REC))
+
+#ifndef BTA_GATTC_CACHE_SRVR_SIZE
+    #define BTA_GATTC_CACHE_SRVR_SIZE   600
+#endif
+
+enum
+{
+    BTA_GATTC_IDLE_ST = 0,      /* Idle  */
+    BTA_GATTC_W4_CONN_ST,       /* Wait for connection -  (optional) */
+    BTA_GATTC_CONN_ST,          /* connected state */
+    BTA_GATTC_DISCOVER_ST       /* discover is in progress */
+};
+typedef UINT8 tBTA_GATTC_STATE;
+
+typedef struct
+{
+    BOOLEAN             in_use;
+    BD_ADDR             server_bda;
+    BOOLEAN             connected;
+
+#define BTA_GATTC_SERV_IDLE     0
+#define BTA_GATTC_SERV_LOAD     1
+#define BTA_GATTC_SERV_SAVE     2
+#define BTA_GATTC_SERV_DISC     3
+#define BTA_GATTC_SERV_DISC_ACT 4
+
+    UINT8               state;
+
+    tBTA_GATTC_CACHE    *p_srvc_cache;
+    tBTA_GATTC_CACHE    *p_cur_srvc;
+    BUFFER_Q            cache_buffer;   /* buffer queue used for storing the cache data */
+    UINT8               *p_free;        /* starting point to next available byte */
+    UINT16              free_byte;      /* number of available bytes in server cache buffer */
+    UINT8               update_count;   /* indication received */
+    UINT8               num_clcb;       /* number of associated CLCB */
+
+
+    tBTA_GATTC_ATTR_REC *p_srvc_list;
+    UINT8               cur_srvc_idx;
+    UINT8               cur_char_idx;
+    UINT8               next_avail_idx;
+    UINT8               total_srvc;
+    UINT8               total_char;
+
+    UINT8               srvc_hdl_chg;   /* service handle change indication pending */
+    UINT16              attr_index;     /* cahce NV saving/loading attribute index */
+
+    UINT16              mtu;
+} tBTA_GATTC_SERV;
+
+#ifndef BTA_GATTC_NOTIF_REG_MAX
+#define BTA_GATTC_NOTIF_REG_MAX     15
+#endif
+
+typedef struct
+{
+    BOOLEAN             in_use;
+    BD_ADDR             remote_bda;
+    tBTA_GATTC_CHAR_ID  char_id;
+}tBTA_GATTC_NOTIF_REG;
+
+typedef struct
+{
+    tBTA_GATTC_CBACK        *p_cback;
+    BOOLEAN                 in_use;
+    tBTA_GATTC_IF           client_if;      /* client interface with BTE stack for this application */
+    UINT8                   num_clcb;       /* number of associated CLCB */
+    BOOLEAN                 dereg_pending;
+    tBT_UUID                app_uuid;
+    tBTA_GATTC_NOTIF_REG    notif_reg[BTA_GATTC_NOTIF_REG_MAX];
+}tBTA_GATTC_RCB;
+
+/* client channel is a mapping between a BTA client(cl_id) and a remote BD address */
+typedef struct
+{
+    UINT16              bta_conn_id;    /* client channel ID, unique for clcb */
+    BD_ADDR             bda;
+    tBTA_TRANSPORT      transport;      /* channel transport */
+    tBTA_GATTC_RCB      *p_rcb;         /* pointer to the registration CB */
+    tBTA_GATTC_SERV     *p_srcb;    /* server cache CB */
+    tBTA_GATTC_DATA     *p_q_cmd;   /* command in queue waiting for execution */
+
+#define BTA_GATTC_NO_SCHEDULE       0
+#define BTA_GATTC_DISC_WAITING      0x01
+#define BTA_GATTC_REQ_WAITING       0x10
+
+    UINT8               auto_update; /* auto update is waiting */
+    BOOLEAN             disc_active;
+    BOOLEAN             in_use;
+    tBTA_GATTC_STATE    state;
+    tBTA_GATT_STATUS    status;
+    UINT16              reason;
+} tBTA_GATTC_CLCB;
+
+/* back ground connection tracking information */
+#if GATT_MAX_APPS <= 8
+typedef UINT8 tBTA_GATTC_CIF_MASK ;
+#elif GATT_MAX_APPS <= 16
+typedef UINT16 tBTA_GATTC_CIF_MASK;
+#elif GATT_MAX_APPS <= 32
+typedef UINT32 tBTA_GATTC_CIF_MASK;
+#endif
+
+typedef struct
+{
+    BOOLEAN                 in_use;
+    BD_ADDR                 remote_bda;
+    tBTA_GATTC_CIF_MASK     cif_mask;
+    tBTA_GATTC_CIF_MASK     cif_adv_mask;
+
+}tBTA_GATTC_BG_TCK;
+
+typedef struct
+{
+    BOOLEAN             in_use;
+    BD_ADDR             remote_bda;
+}tBTA_GATTC_CONN;
+
+enum
+{
+   BTA_GATTC_STATE_DISABLED,
+   BTA_GATTC_STATE_ENABLING,
+   BTA_GATTC_STATE_ENABLED,
+   BTA_GATTC_STATE_DISABLING
+};
+
+typedef struct
+{
+    UINT8             state;
+
+    tBTA_GATTC_CONN     conn_track[BTA_GATTC_CONN_MAX];
+    tBTA_GATTC_BG_TCK   bg_track[BTA_GATTC_KNOWN_SR_MAX];
+    tBTA_GATTC_RCB      cl_rcb[BTA_GATTC_CL_MAX];
+
+    tBTA_GATTC_CLCB     clcb[BTA_GATTC_CLCB_MAX];
+    tBTA_GATTC_SERV     known_server[BTA_GATTC_KNOWN_SR_MAX];
+
+    tSDP_DISCOVERY_DB   *p_sdp_db;
+    UINT16              sdp_conn_id;
+}tBTA_GATTC_CB;
+
+/*****************************************************************************
+**  Global data
+*****************************************************************************/
+
+/* GATTC control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_GATTC_CB  bta_gattc_cb;
+#else
+extern tBTA_GATTC_CB *bta_gattc_cb_ptr;
+#define bta_gattc_cb (*bta_gattc_cb_ptr)
+#endif
+
+/*****************************************************************************
+**  Function prototypes
+*****************************************************************************/
+extern BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg);
+extern BOOLEAN bta_gattc_sm_execute(tBTA_GATTC_CLCB *p_clcb, UINT16 event, tBTA_GATTC_DATA *p_data);
+
+/* function processed outside SM */
+extern void bta_gattc_disable(tBTA_GATTC_CB *p_cb);
+extern void bta_gattc_register(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_start_if(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_process_api_open (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
+extern void bta_gattc_process_api_open_cancel (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
+extern void bta_gattc_deregister(tBTA_GATTC_CB *p_cb, tBTA_GATTC_RCB  *p_clreg);
+extern void bta_gattc_process_enc_cmpl(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg);
+
+/* function within state machine */
+extern void bta_gattc_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_open_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_open_error(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+
+extern void bta_gattc_cancel_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_cancel_open_ok(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_cancel_open_error(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+
+extern void bta_gattc_conn(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+
+extern void bta_gattc_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_close_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_disc_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+
+extern void bta_gattc_start_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_read(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_write(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_q_cmd(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_search(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_confirm(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_execute(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_read_multi(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_ci_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_ci_load(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_ci_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_ci_save(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_cache_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_ignore_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_restart_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA * p_msg);
+extern void bta_gattc_init_bk_conn(tBTA_GATTC_API_OPEN *p_data, tBTA_GATTC_RCB *p_clreg);
+extern void bta_gattc_cancel_bk_conn(tBTA_GATTC_API_CANCEL_OPEN *p_data);
+extern void bta_gattc_send_open_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS status,
+                                       BD_ADDR remote_bda, UINT16 conn_id, tBTA_TRANSPORT transport,  UINT16 mtu);
+extern void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
+extern void bta_gattc_cfg_mtu(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+#if BLE_INCLUDED == TRUE
+extern void bta_gattc_listen(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
+extern void bta_gattc_broadcast(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
+#endif
+/* utility functions */
+extern tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_cif (UINT8 client_if, BD_ADDR remote_bda, tBTA_TRANSPORT transport);
+extern tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_conn_id (UINT16 conn_id);
+extern tBTA_GATTC_CLCB * bta_gattc_clcb_alloc(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, tBTA_TRANSPORT transport);
+extern void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb);
+extern tBTA_GATTC_CLCB * bta_gattc_find_alloc_clcb(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, tBTA_TRANSPORT transport);
+extern tBTA_GATTC_RCB * bta_gattc_cl_get_regcb(UINT8 client_if);
+extern tBTA_GATTC_SERV * bta_gattc_find_srcb(BD_ADDR bda);
+extern tBTA_GATTC_SERV * bta_gattc_srcb_alloc(BD_ADDR bda);
+extern tBTA_GATTC_SERV * bta_gattc_find_scb_by_cid (UINT16 conn_id);
+extern tBTA_GATTC_CLCB * bta_gattc_find_int_conn_clcb(tBTA_GATTC_DATA *p_msg);
+extern tBTA_GATTC_CLCB * bta_gattc_find_int_disconn_clcb(tBTA_GATTC_DATA *p_msg);
+
+extern BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+
+extern UINT16 bta_gattc_id2handle(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_SRVC_ID *p_service_id, tBTA_GATT_ID *p_char_id, tBTA_GATT_ID *p_descr_uuid);
+extern BOOLEAN bta_gattc_handle2id(tBTA_GATTC_SERV *p_srcb, UINT16 handle, tBTA_GATT_SRVC_ID *service_id, tBTA_GATT_ID *char_id, tBTA_GATT_ID *p_type);
+extern BOOLEAN bta_gattc_uuid_compare (tBT_UUID *p_src, tBT_UUID *p_tar, BOOLEAN is_precise);
+extern void bta_gattc_pack_attr_uuid(tBTA_GATTC_CACHE_ATTR   *p_attr, tBT_UUID *p_uuid);
+extern BOOLEAN bta_gattc_check_notif_registry(tBTA_GATTC_RCB  *p_clreg, tBTA_GATTC_SERV *p_srcb, tBTA_GATTC_NOTIFY  *p_notify);
+extern tBTA_GATT_STATUS bta_gattc_pack_read_cb_data(tBTA_GATTC_SERV *p_srcb, tBT_UUID *p_descr_uuid, tGATT_VALUE *p_attr, tBTA_GATT_READ_VAL *p_value);
+extern BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR_PTR remote_bda, BOOLEAN add, BOOLEAN is_listen);
+extern BOOLEAN bta_gattc_check_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR remote_bda, UINT8 role);
+extern UINT8 bta_gattc_num_reg_app(void);
+extern void bta_gattc_clear_notif_registration(UINT16 conn_id);
+extern tBTA_GATTC_SERV * bta_gattc_find_srvr_cache(BD_ADDR bda);
+extern BOOLEAN bta_gattc_charid_compare(tBTA_GATTC_CHAR_ID *p_src, tBTA_GATTC_CHAR_ID *p_tar);
+extern BOOLEAN bta_gattc_srvcid_compare(tBTA_GATT_SRVC_ID *p_src, tBTA_GATT_SRVC_ID *p_tar);
+extern void bta_gattc_cpygattid(tBTA_GATT_ID *p_des, tBTA_GATT_ID *p_src);
+
+/* discovery functions */
+extern void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES *p_data);
+extern void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status);
+extern tBTA_GATT_STATUS bta_gattc_discover_procedure(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type);
+extern tBTA_GATT_STATUS bta_gattc_discover_pri_service(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type);
+extern void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID *p_uuid);
+extern tBTA_GATT_STATUS bta_gattc_query_cache(UINT16 conn_id, UINT8 query_type, tBTA_GATT_SRVC_ID *p_srvc_id,
+                                              tBTA_GATT_ID *p_start_rec,tBT_UUID *p_uuid_cond,
+                                              tBTA_GATT_ID *p_output, void *p_param);
+extern tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb);
+extern void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srcv, UINT16 num_attr, tBTA_GATTC_NV_ATTR *p_attr, UINT16 attr_index);
+extern BOOLEAN bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id);
+
+
+extern tBTA_GATTC_CONN * bta_gattc_conn_alloc(BD_ADDR remote_bda);
+extern tBTA_GATTC_CONN * bta_gattc_conn_find(BD_ADDR remote_bda);
+extern tBTA_GATTC_CONN * bta_gattc_conn_find_alloc(BD_ADDR remote_bda);
+extern BOOLEAN bta_gattc_conn_dealloc(BD_ADDR remote_bda);
+
+#endif /* BTA_GATTC_INT_H */

+ 81 - 0
components/bt/bluedroid/bta/include/bta_gatts_co.h

@@ -0,0 +1,81 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2010-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the interface file for BTA GATT server call-out functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_GATTS_CO_H
+#define BTA_GATTS_CO_H
+
+#include "bta_gatt_api.h"
+
+/*******************************************************************************
+**
+** Function         bta_gatts_co_update_handle_range
+**
+** Description      This callout function is executed by GATTS when a GATT server
+**                  handle range ios to be added or removed.
+**
+** Parameter        is_add: true is to add a handle range; otherwise is to delete.
+**                  p_hndl_range: handle range.
+**
+** Returns          void.
+**
+*******************************************************************************/
+extern void bta_gatts_co_update_handle_range(BOOLEAN is_add, tBTA_GATTS_HNDL_RANGE *p_hndl_range);
+
+/*******************************************************************************
+**
+** Function         bta_gatts_co_srv_chg
+**
+** Description      This call-out is to read/write/remove service change related
+**                  informaiton. The request consists of the cmd and p_req and the
+**                  response is returned in p_rsp
+**
+** Parameter        cmd - request command
+**                  p_req - request paramters
+**                  p_rsp - response data for the request
+**
+** Returns          TRUE - if the request is processed successfully and
+**                         the response is returned in p_rsp.
+**                  FASLE - if the request can not be processed
+**
+*******************************************************************************/
+extern BOOLEAN bta_gatts_co_srv_chg(tBTA_GATTS_SRV_CHG_CMD cmd,
+                                    tBTA_GATTS_SRV_CHG_REQ *p_req,
+                                    tBTA_GATTS_SRV_CHG_RSP *p_rsp);
+
+/*******************************************************************************
+**
+** Function         bta_gatts_co_load_handle_range
+**
+** Description      This callout function is executed by GATTS when a GATT server
+**                  handle range is requested to be loaded from NV.
+**
+** Parameter
+**
+** Returns          void.
+**
+*******************************************************************************/
+extern  BOOLEAN bta_gatts_co_load_handle_range(UINT8 index,
+                                               tBTA_GATTS_HNDL_RANGE *p_handle);
+
+
+#endif /* BTA_GATTS_CO_H */

+ 260 - 0
components/bt/bluedroid/bta/include/bta_gatts_int.h

@@ -0,0 +1,260 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the private file for the BTA GATT server.
+ *
+ ******************************************************************************/
+#ifndef BTA_GATTS_INT_H
+#define BTA_GATTS_INT_H
+
+#include "bt_target.h"
+#include "bta_sys.h"
+#include "bta_gatt_api.h"
+#include "gatt_api.h"
+
+#include "gki.h"
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+enum
+{
+    BTA_GATTS_API_REG_EVT  = BTA_SYS_EVT_START(BTA_ID_GATTS),
+    BTA_GATTS_INT_START_IF_EVT,
+    BTA_GATTS_API_DEREG_EVT,
+    BTA_GATTS_API_CREATE_SRVC_EVT,
+    BTA_GATTS_API_INDICATION_EVT,
+
+    BTA_GATTS_API_ADD_INCL_SRVC_EVT,
+    BTA_GATTS_API_ADD_CHAR_EVT,
+    BTA_GATTS_API_ADD_DESCR_EVT,
+    BTA_GATTS_API_DEL_SRVC_EVT,
+    BTA_GATTS_API_START_SRVC_EVT,
+    BTA_GATTS_API_STOP_SRVC_EVT,
+    BTA_GATTS_API_RSP_EVT,
+    BTA_GATTS_API_OPEN_EVT,
+    BTA_GATTS_API_CANCEL_OPEN_EVT,
+    BTA_GATTS_API_CLOSE_EVT,
+    BTA_GATTS_API_LISTEN_EVT,
+    BTA_GATTS_API_DISABLE_EVT
+};
+typedef UINT16 tBTA_GATTS_INT_EVT;
+
+/* max number of application allowed on device */
+#define BTA_GATTS_MAX_APP_NUM   GATT_MAX_SR_PROFILES
+
+/* max number of services allowed in the device */
+#define BTA_GATTS_MAX_SRVC_NUM   GATT_MAX_SR_PROFILES
+
+/* internal strucutre for GATTC register API  */
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBT_UUID                app_uuid;
+    tBTA_GATTS_CBACK        *p_cback;
+}tBTA_GATTS_API_REG;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_GATTS_IF           server_if;
+}tBTA_GATTS_INT_START_IF;
+
+typedef tBTA_GATTS_INT_START_IF tBTA_GATTS_API_DEREG;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_GATTS_IF           server_if;
+    tBT_UUID                service_uuid;
+    UINT16                  num_handle;
+    UINT8                   inst;
+    BOOLEAN                 is_pri;
+
+} tBTA_GATTS_API_CREATE_SRVC;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBT_UUID                char_uuid;
+    tBTA_GATT_PERM          perm;
+    tBTA_GATT_CHAR_PROP     property;
+
+}tBTA_GATTS_API_ADD_CHAR;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    UINT16                  included_service_id;
+
+}tBTA_GATTS_API_ADD_INCL_SRVC;
+
+typedef struct
+{
+    BT_HDR                      hdr;
+    tBT_UUID                    descr_uuid;
+    tBTA_GATT_PERM              perm;
+}tBTA_GATTS_API_ADD_DESCR;
+
+typedef struct
+{
+    BT_HDR  hdr;
+    UINT16  attr_id;
+    UINT16  len;
+    BOOLEAN need_confirm;
+    UINT8   value[BTA_GATT_MAX_ATTR_LEN];
+}tBTA_GATTS_API_INDICATION;
+
+typedef struct
+{
+    BT_HDR              hdr;
+    UINT32              trans_id;
+    tBTA_GATT_STATUS    status;
+    tBTA_GATTS_RSP      *p_rsp;
+}tBTA_GATTS_API_RSP;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_GATT_TRANSPORT     transport;
+}tBTA_GATTS_API_START;
+
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    BD_ADDR                 remote_bda;
+    tBTA_GATTS_IF           server_if;
+    BOOLEAN                 is_direct;
+    tBTA_GATT_TRANSPORT     transport;
+
+}tBTA_GATTS_API_OPEN;
+
+typedef tBTA_GATTS_API_OPEN tBTA_GATTS_API_CANCEL_OPEN;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    BD_ADDR_PTR             remote_bda;
+    tBTA_GATTS_IF           server_if;
+    BOOLEAN                 start;
+} tBTA_GATTS_API_LISTEN;
+
+typedef union
+{
+    BT_HDR                          hdr;
+    tBTA_GATTS_API_REG              api_reg;
+    tBTA_GATTS_API_DEREG            api_dereg;
+    tBTA_GATTS_API_CREATE_SRVC      api_create_svc;
+    tBTA_GATTS_API_ADD_INCL_SRVC    api_add_incl_srvc;
+    tBTA_GATTS_API_ADD_CHAR         api_add_char;
+    tBTA_GATTS_API_ADD_DESCR        api_add_char_descr;
+    tBTA_GATTS_API_START            api_start;
+    tBTA_GATTS_API_INDICATION       api_indicate;
+    tBTA_GATTS_API_RSP              api_rsp;
+    tBTA_GATTS_API_OPEN             api_open;
+    tBTA_GATTS_API_CANCEL_OPEN      api_cancel_open;
+
+    tBTA_GATTS_INT_START_IF         int_start_if;
+    /* if peripheral role is supported */
+    tBTA_GATTS_API_LISTEN           api_listen;
+} tBTA_GATTS_DATA;
+
+/* application registration control block */
+typedef struct
+{
+    BOOLEAN             in_use;
+    tBT_UUID            app_uuid;
+    tBTA_GATTS_CBACK    *p_cback;
+    tBTA_GATTS_IF        gatt_if;
+}tBTA_GATTS_RCB;
+
+/* service registration control block */
+typedef struct
+{
+    tBT_UUID    service_uuid;   /* service UUID */
+    UINT16      service_id;     /* service handle */
+    UINT8       inst_num;       /* instance ID */
+    UINT8       rcb_idx;
+    UINT8       idx;            /* self index of serviec CB */
+    BOOLEAN     in_use;
+
+}tBTA_GATTS_SRVC_CB;
+
+
+/* GATT server control block */
+typedef struct
+{
+    BOOLEAN             enabled;
+    tBTA_GATTS_RCB      rcb[BTA_GATTS_MAX_APP_NUM];
+    tBTA_GATTS_SRVC_CB  srvc_cb[BTA_GATTS_MAX_SRVC_NUM];
+}tBTA_GATTS_CB;
+
+
+
+/*****************************************************************************
+**  Global data
+*****************************************************************************/
+
+/* GATTC control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_GATTS_CB  bta_gatts_cb;
+#else
+extern tBTA_GATTS_CB *bta_gatts_cb_ptr;
+    #define bta_gatts_cb (*bta_gatts_cb_ptr)
+#endif
+
+/*****************************************************************************
+**  Function prototypes
+*****************************************************************************/
+extern BOOLEAN bta_gatts_hdl_event(BT_HDR *p_msg);
+
+extern void bta_gatts_api_disable(tBTA_GATTS_CB *p_cb);
+extern void bta_gatts_api_enable(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_data);
+extern void bta_gatts_register(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
+extern void bta_gatts_start_if(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
+extern void bta_gatts_deregister(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
+extern void bta_gatts_create_srvc(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_add_include_srvc(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_add_char(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_add_char_descr(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_delete_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_start_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_stop_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
+
+extern void bta_gatts_send_rsp(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_indicate_handle (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
+
+
+extern void bta_gatts_open (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_cancel_open (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_close (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_listen(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
+
+extern BOOLEAN bta_gatts_uuid_compare(tBT_UUID tar, tBT_UUID src);
+extern tBTA_GATTS_RCB *bta_gatts_find_app_rcb_by_app_if(tBTA_GATTS_IF server_if);
+extern UINT8 bta_gatts_find_app_rcb_idx_by_app_if(tBTA_GATTS_CB *p_cb, tBTA_GATTS_IF server_if);
+extern UINT8 bta_gatts_alloc_srvc_cb(tBTA_GATTS_CB *p_cb, UINT8 rcb_idx);
+extern tBTA_GATTS_SRVC_CB * bta_gatts_find_srvc_cb_by_srvc_id(tBTA_GATTS_CB *p_cb, UINT16 service_id);
+extern tBTA_GATTS_SRVC_CB * bta_gatts_find_srvc_cb_by_attr_id(tBTA_GATTS_CB *p_cb, UINT16 attr_id);
+
+
+#endif /* BTA_GATTS_INT_H */
+

+ 558 - 0
components/bt/bluedroid/bta/include/bta_hh_api.h

@@ -0,0 +1,558 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2002-2012 Broadcom Corporation
+ *
+ *  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 BTA_HH_API_H
+#define BTA_HH_API_H
+
+#include "bta_api.h"
+#include "hidh_api.h"
+
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+#include "gatt_api.h"
+#endif
+
+/*****************************************************************************
+**  Constants and Type Definitions
+*****************************************************************************/
+#ifndef BTA_HH_DEBUG
+#define BTA_HH_DEBUG    TRUE
+#endif
+
+#ifndef BTA_HH_SSR_MAX_LATENCY_DEF
+#define BTA_HH_SSR_MAX_LATENCY_DEF  800 /* 500 ms*/
+#endif
+
+#ifndef BTA_HH_SSR_MIN_TOUT_DEF
+#define BTA_HH_SSR_MIN_TOUT_DEF     2
+#endif
+
+/* BTA HID Host callback events */
+#define BTA_HH_ENABLE_EVT       0       /* HH enabled */
+#define BTA_HH_DISABLE_EVT      1       /* HH disabled */
+#define BTA_HH_OPEN_EVT         2       /* connection opened */
+#define BTA_HH_CLOSE_EVT        3       /* connection closed */
+#define BTA_HH_GET_RPT_EVT      4       /* BTA_HhGetReport callback */
+#define BTA_HH_SET_RPT_EVT      5       /* BTA_HhSetReport callback */
+#define BTA_HH_GET_PROTO_EVT    6       /* BTA_GetProtoMode callback */
+#define BTA_HH_SET_PROTO_EVT    7       /* BTA_HhSetProtoMode callback */
+#define BTA_HH_GET_IDLE_EVT     8       /* BTA_HhGetIdle comes callback */
+#define BTA_HH_SET_IDLE_EVT     9       /* BTA_HhSetIdle finish callback */
+#define BTA_HH_GET_DSCP_EVT     10      /* Get report descriptor */
+#define BTA_HH_ADD_DEV_EVT      11      /* Add Device callback */
+#define BTA_HH_RMV_DEV_EVT      12      /* remove device finished */
+#define BTA_HH_VC_UNPLUG_EVT    13      /* virtually unplugged */
+#define BTA_HH_DATA_EVT         15
+#define BTA_HH_API_ERR_EVT      16      /* API error is caught */
+#define BTA_HH_UPDATE_SCPP_EVT  17       /* update scan paramter complete */
+
+typedef UINT16 tBTA_HH_EVT;
+
+/* application ID(none-zero) for each type of device */
+#define BTA_HH_APP_ID_MI            1
+#define BTA_HH_APP_ID_KB            2
+#define BTA_HH_APP_ID_RMC           3
+#define BTA_HH_APP_ID_3DSG          4
+#define BTA_HH_APP_ID_JOY           5
+#define BTA_HH_APP_ID_GPAD          6
+#define BTA_HH_APP_ID_LE            0xff
+
+/* defined the minimum offset */
+#define BTA_HH_MIN_OFFSET       L2CAP_MIN_OFFSET+1
+
+/* HID_HOST_MAX_DEVICES can not exceed 15 for th design of BTA HH */
+#define BTA_HH_IDX_INVALID      0xff
+#define BTA_HH_MAX_KNOWN        HID_HOST_MAX_DEVICES
+
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+/* GATT_MAX_PHY_CHANNEL can not exceed 14 for the design of BTA HH */
+#define BTA_HH_LE_MAX_KNOWN     GATT_MAX_PHY_CHANNEL
+#define BTA_HH_MAX_DEVICE        (HID_HOST_MAX_DEVICES + GATT_MAX_PHY_CHANNEL)
+#else
+#define BTA_HH_MAX_DEVICE       HID_HOST_MAX_DEVICES
+#endif
+/* invalid device handle */
+#define BTA_HH_INVALID_HANDLE   0xff
+
+/* type of protocol mode */
+#define BTA_HH_PROTO_RPT_MODE                   (0x00)
+#define BTA_HH_PROTO_BOOT_MODE                  (0x01)
+#define BTA_HH_PROTO_UNKNOWN                    (0xff)
+typedef UINT8   tBTA_HH_PROTO_MODE;
+
+enum
+{
+    BTA_HH_KEYBD_RPT_ID  =               1,
+    BTA_HH_MOUSE_RPT_ID
+};
+typedef UINT8 tBTA_HH_BOOT_RPT_ID;
+
+/* type of devices, bit mask */
+#define BTA_HH_DEVT_UNKNOWN      0x00
+#define BTA_HH_DEVT_JOS          0x01           /* joy stick */
+#define BTA_HH_DEVT_GPD          0x02           /* game pad */
+#define BTA_HH_DEVT_RMC          0x03           /* remote control */
+#define BTA_HH_DEVT_SED          0x04           /* sensing device */
+#define BTA_HH_DEVT_DGT          0x05           /* Digitizer tablet */
+#define BTA_HH_DEVT_CDR          0x06           /* card reader */
+#define BTA_HH_DEVT_KBD          0x10           /* keyboard */
+#define BTA_HH_DEVT_MIC          0x20           /* pointing device */
+#define BTA_HH_DEVT_COM          0x30           /* Combo keyboard/pointing */
+#define BTA_HH_DEVT_OTHER        0x80
+typedef UINT8  tBTA_HH_DEVT;
+
+enum
+{
+    BTA_HH_OK,
+    BTA_HH_HS_HID_NOT_READY,    /* handshake error : device not ready */
+    BTA_HH_HS_INVALID_RPT_ID,   /* handshake error : invalid report ID */
+    BTA_HH_HS_TRANS_NOT_SPT,    /* handshake error : transaction not spt */
+    BTA_HH_HS_INVALID_PARAM,    /* handshake error : invalid paremter */
+    BTA_HH_HS_ERROR,            /* handshake error : unspecified HS error */
+    BTA_HH_ERR,                 /* general BTA HH error */
+    BTA_HH_ERR_SDP,             /* SDP error */
+    BTA_HH_ERR_PROTO,           /* SET_Protocol error,
+                                    only used in BTA_HH_OPEN_EVT callback */
+
+    BTA_HH_ERR_DB_FULL,         /* device database full error, used in
+                                   BTA_HH_OPEN_EVT/BTA_HH_ADD_DEV_EVT */
+    BTA_HH_ERR_TOD_UNSPT,       /* type of device not supported */
+    BTA_HH_ERR_NO_RES,          /* out of system resources */
+    BTA_HH_ERR_AUTH_FAILED,     /* authentication fail */
+    BTA_HH_ERR_HDL,
+    BTA_HH_ERR_SEC
+};
+typedef UINT8 tBTA_HH_STATUS;
+
+
+#define BTA_HH_VIRTUAL_CABLE           HID_VIRTUAL_CABLE
+#define BTA_HH_NORMALLY_CONNECTABLE    HID_NORMALLY_CONNECTABLE
+#define BTA_HH_RECONN_INIT             HID_RECONN_INIT
+#define BTA_HH_SDP_DISABLE             HID_SDP_DISABLE
+#define BTA_HH_BATTERY_POWER           HID_BATTERY_POWER
+#define BTA_HH_REMOTE_WAKE             HID_REMOTE_WAKE
+#define BTA_HH_SUP_TOUT_AVLBL          HID_SUP_TOUT_AVLBL
+#define BTA_HH_SEC_REQUIRED             HID_SEC_REQUIRED
+typedef UINT16 tBTA_HH_ATTR_MASK;
+
+/* supported type of device and corresponding application ID */
+typedef struct
+{
+    tBTA_HH_DEVT        tod;        /* type of device               */
+    UINT8               app_id;     /* corresponding application ID */
+}tBTA_HH_SPT_TOD;
+
+/* configuration struct */
+typedef struct
+{
+    UINT8                max_devt_spt; /* max number of types of devices spt */
+    tBTA_HH_SPT_TOD     *p_devt_list;  /* supported types of device list     */
+    UINT16               sdp_db_size;
+}tBTA_HH_CFG;
+
+enum
+{
+    BTA_HH_RPTT_RESRV,      /* reserved         */
+    BTA_HH_RPTT_INPUT,      /* input report     */
+    BTA_HH_RPTT_OUTPUT,     /* output report    */
+    BTA_HH_RPTT_FEATURE     /* feature report   */
+};
+typedef UINT8 tBTA_HH_RPT_TYPE;
+
+/* HID_CONTROL operation code used in BTA_HhSendCtrl()
+*/
+enum
+{
+    BTA_HH_CTRL_NOP         = 0 + HID_PAR_CONTROL_NOP ,/* mapping from BTE */
+    BTA_HH_CTRL_HARD_RESET,                            /* hard reset       */
+    BTA_HH_CTRL_SOFT_RESET,                            /* soft reset       */
+    BTA_HH_CTRL_SUSPEND,                               /* enter suspend    */
+    BTA_HH_CTRL_EXIT_SUSPEND,                          /* exit suspend     */
+    BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG                   /* virtual unplug   */
+};
+typedef UINT8 tBTA_HH_TRANS_CTRL_TYPE;
+
+typedef tHID_DEV_DSCP_INFO tBTA_HH_DEV_DESCR;
+
+#define BTA_HH_SSR_PARAM_INVALID       HID_SSR_PARAM_INVALID
+
+/* id DI is not existing in remote device, vendor_id in tBTA_HH_DEV_DSCP_INFO will be set to 0xffff */
+#define BTA_HH_VENDOR_ID_INVALID       0xffff
+
+
+/* report descriptor information */
+typedef struct
+{
+    UINT16              vendor_id;      /* vendor ID */
+    UINT16              product_id;     /* product ID */
+    UINT16              version;        /* version */
+    UINT16              ssr_max_latency;    /* SSR max latency, BTA_HH_SSR_PARAM_INVALID if unknown */
+    UINT16              ssr_min_tout;       /* SSR min timeout, BTA_HH_SSR_PARAM_INVALID if unknown */
+    UINT8               ctry_code;      /*Country Code.*/
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+#define BTA_HH_LE_REMOTE_WAKE       0x01
+#define BTA_HH_LE_NORMAL_CONN       0x02
+
+    UINT8               flag;
+#endif
+    tBTA_HH_DEV_DESCR   descriptor;
+}tBTA_HH_DEV_DSCP_INFO;
+
+/* callback event data for BTA_HH_OPEN_EVT */
+typedef struct
+{
+    BD_ADDR         bda;                /* HID device bd address    */
+    tBTA_HH_STATUS  status;             /* operation status         */
+    UINT8           handle;             /* device handle            */
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+    BOOLEAN         le_hid;             /* is LE devices? */
+    BOOLEAN         scps_supported;     /* scan parameter service supported */
+#endif
+
+} tBTA_HH_CONN;
+
+typedef tBTA_HH_CONN tBTA_HH_DEV_INFO;
+
+/* callback event data */
+typedef struct
+{
+    tBTA_HH_STATUS              status;     /* operation status         */
+    UINT8                       handle;     /* device handle            */
+} tBTA_HH_CBDATA;
+
+enum
+{
+    BTA_HH_MOD_CTRL_KEY,
+    BTA_HH_MOD_SHFT_KEY,
+    BTA_HH_MOD_ALT_KEY,
+    BTA_HH_MOD_GUI_KEY,
+    BTA_HH_MOD_MAX_KEY
+};
+
+/* parsed boot mode keyboard report */
+typedef struct
+{
+    UINT8               this_char[6];       /* virtual key code     */
+    BOOLEAN             mod_key[BTA_HH_MOD_MAX_KEY];
+                                            /* ctrl, shift, Alt, GUI */
+                                            /* modifier key: is Shift key pressed */
+                                            /* modifier key: is Ctrl key pressed  */
+                                            /* modifier key: is Alt key pressed   */
+                                            /* modifier key: GUI up/down */
+    BOOLEAN             caps_lock;          /* is caps locked       */
+    BOOLEAN             num_lock;           /* is Num key pressed   */
+} tBTA_HH_KEYBD_RPT;
+
+/* parsed boot mode mouse report */
+typedef struct
+{
+    UINT8               mouse_button;       /* mouse button is clicked   */
+    INT8                delta_x;            /* displacement x            */
+    INT8                delta_y;            /* displacement y            */
+}tBTA_HH_MICE_RPT;
+
+/* parsed Boot report */
+typedef struct
+{
+    tBTA_HH_BOOT_RPT_ID dev_type;           /* type of device report */
+    union
+    {
+        tBTA_HH_KEYBD_RPT   keybd_rpt;      /* keyboard report      */
+        tBTA_HH_MICE_RPT    mice_rpt;       /* mouse report         */
+    }                   data_rpt;
+} tBTA_HH_BOOT_RPT;
+
+/* handshake data */
+typedef struct
+{
+    tBTA_HH_STATUS  status;                 /* handshake status */
+    UINT8           handle;                 /* device handle    */
+    union
+    {
+        tBTA_HH_PROTO_MODE      proto_mode; /* GET_PROTO_EVT :protocol mode */
+        BT_HDR                  *p_rpt_data;   /* GET_RPT_EVT   : report data  */
+        UINT8                   idle_rate;  /* GET_IDLE_EVT  : idle rate    */
+    }               rsp_data;
+
+}tBTA_HH_HSDATA;
+
+/* union of data associated with HD callback */
+typedef union
+{
+    tBTA_HH_DEV_INFO        dev_info;           /* BTA_HH_ADD_DEV_EVT, BTA_HH_RMV_DEV_EVT   */
+    tBTA_HH_CONN            conn;               /* BTA_HH_OPEN_EVT      */
+    tBTA_HH_CBDATA          dev_status;         /* BTA_HH_CLOSE_EVT,
+                                                   BTA_HH_SET_PROTO_EVT
+                                                   BTA_HH_SET_RPT_EVT
+                                                   BTA_HH_SET_IDLE_EVT
+                                                   BTA_HH_UPDATE_SCPP_EVT */
+
+    tBTA_HH_STATUS          status;             /* BTA_HH_ENABLE_EVT */
+    tBTA_HH_DEV_DSCP_INFO   dscp_info;          /* BTA_HH_GET_DSCP_EVT */
+    tBTA_HH_HSDATA          hs_data;            /* GET_ transaction callback
+                                                   BTA_HH_GET_RPT_EVT
+                                                   BTA_HH_GET_PROTO_EVT
+                                                   BTA_HH_GET_IDLE_EVT */
+} tBTA_HH;
+
+/* BTA HH callback function */
+typedef void (tBTA_HH_CBACK) (tBTA_HH_EVT event, tBTA_HH *p_data);
+
+
+/*****************************************************************************
+**  External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function         BTA_HhRegister
+**
+** Description      This function enable HID host and registers HID-Host with
+**                  lower layers.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_HhEnable(tBTA_SEC sec_mask, tBTA_HH_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_HhDeregister
+**
+** Description      This function is called when the host is about power down.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_HhDisable(void);
+
+/*******************************************************************************
+**
+** Function         BTA_HhOpen
+**
+** Description      This function is called to start an inquiry and read SDP
+**                  record of responding devices; connect to a device if only
+**                  one active HID device is found.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_HhOpen (BD_ADDR dev_bda, tBTA_HH_PROTO_MODE mode,
+                        tBTA_SEC sec_mask);
+
+/*******************************************************************************
+**
+** Function         BTA_HhClose
+**
+** Description      This function disconnects the device.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_HhClose(UINT8 dev_handle);
+
+/*******************************************************************************
+**
+** Function         BTA_HhSetProtoMode
+**
+** Description      This function set the protocol mode at specified HID handle
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_HhSetProtoMode(UINT8 handle, tBTA_HH_PROTO_MODE t_type);
+
+/*******************************************************************************
+**
+** Function         BTA_HhGetProtoMode
+**
+** Description      This function get the protocol mode of a specified HID device.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_HhGetProtoMode(UINT8 dev_handle);
+/*******************************************************************************
+**
+** Function         BTA_HhSetReport
+**
+** Description      send SET_REPORT to device.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_HhSetReport(UINT8 dev_handle, tBTA_HH_RPT_TYPE r_type,
+                            BT_HDR *p_data);
+
+/*******************************************************************************
+**
+** Function         BTA_HhGetReport
+**
+** Description      Send a GET_REPORT to HID device.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_HhGetReport(UINT8 dev_handle, tBTA_HH_RPT_TYPE r_type,
+                            UINT8 rpt_id, UINT16 buf_size);
+/*******************************************************************************
+**
+** Function         BTA_HhSetIdle
+**
+** Description      send SET_IDLE to device.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_HhSetIdle(UINT8 dev_handle, UINT16 idle_rate);
+
+/*******************************************************************************
+**
+** Function         BTA_HhGetIdle
+**
+** Description      Send a GET_IDLE to HID device.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_HhGetIdle(UINT8 dev_handle);
+
+/*******************************************************************************
+**
+** Function         BTA_HhSendCtrl
+**
+** Description      Send HID_CONTROL request to a HID device.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_HhSendCtrl(UINT8 dev_handle,
+                           tBTA_HH_TRANS_CTRL_TYPE c_type);
+
+/*******************************************************************************
+**
+** Function         BTA_HhSetIdle
+**
+** Description      send SET_IDLE to device.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_HhSetIdle(UINT8 dev_handle, UINT16 idle_rate);
+
+
+/*******************************************************************************
+**
+** Function         BTA_HhGetIdle
+**
+** Description      Send a GET_IDLE from HID device.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_HhGetIdle(UINT8 dev_handle);
+
+/*******************************************************************************
+**
+** Function         BTA_HhSendData
+**
+** Description      Send DATA transaction to a HID device.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_HhSendData(UINT8 dev_handle, BD_ADDR dev_bda, BT_HDR  *p_buf);
+
+/*******************************************************************************
+**
+** Function         BTA_HhGetDscpInfo
+**
+** Description      Get report descriptor of the device
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_HhGetDscpInfo(UINT8 dev_handle);
+
+/*******************************************************************************
+** Function         BTA_HhAddDev
+**
+** Description      Add a virtually cabled device into HID-Host device list
+**                  to manage and assign a device handle for future API call,
+**                  host applciation call this API at start-up to initialize its
+**                  virtually cabled devices.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_HhAddDev(BD_ADDR bda, tBTA_HH_ATTR_MASK attr_mask,
+                         UINT8 sub_class, UINT8 app_id,
+                         tBTA_HH_DEV_DSCP_INFO dscp_info);
+/*******************************************************************************
+**
+** Function         BTA_HhRemoveDev
+**
+** Description      Remove a device from the HID host devices list.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_HhRemoveDev(UINT8 dev_handle );
+
+/*******************************************************************************
+**
+**              Parsing Utility Functions
+**
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function         BTA_HhParseBootRpt
+**
+** Description      This utility function parse a boot mode report.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_HhParseBootRpt(tBTA_HH_BOOT_RPT *p_data, UINT8 *p_report,
+                               UINT16 report_len);
+
+#if BTA_HH_LE_INCLUDED == TRUE
+/*******************************************************************************
+**
+** Function         BTA_HhUpdateLeScanParam
+**
+** Description      Update the scan paramteters if connected to a LE hid device as
+**                  report host.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_HhUpdateLeScanParam(UINT8 dev_handle, UINT16 scan_int, UINT16 scan_win);
+#endif
+/* test commands */
+extern void bta_hh_le_hid_read_rpt_clt_cfg(BD_ADDR bd_addr, UINT8 rpt_id);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* BTA_HH_API_H */

+ 133 - 0
components/bt/bluedroid/bta/include/bta_hh_co.h

@@ -0,0 +1,133 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2005-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the interface file for hid host call-out functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_HH_CO_H
+#define BTA_HH_CO_H
+
+#include "bta_hh_api.h"
+
+typedef struct
+{
+    UINT16              rpt_uuid;
+    UINT8               rpt_id;
+    tBTA_HH_RPT_TYPE    rpt_type;
+    UINT8               inst_id;
+    UINT8               prop;
+}tBTA_HH_RPT_CACHE_ENTRY;
+
+/*******************************************************************************
+**
+** Function         bta_hh_co_data
+**
+** Description      This callout function is executed by HH when data is received
+**                  in interupt channel.
+**
+**
+** Returns          void.
+**
+*******************************************************************************/
+extern void bta_hh_co_data(UINT8 dev_handle, UINT8 *p_rpt, UINT16 len,
+                           tBTA_HH_PROTO_MODE  mode, UINT8 sub_class,
+                           UINT8 ctry_code, BD_ADDR peer_addr, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_hh_co_open
+**
+** Description      This callout function is executed by HH when connection is
+**                  opened, and application may do some device specific
+**                  initialization.
+**
+** Returns          void.
+**
+*******************************************************************************/
+extern void bta_hh_co_open(UINT8 dev_handle, UINT8 sub_class,
+                           UINT16 attr_mask, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_hh_co_close
+**
+** Description      This callout function is executed by HH when connection is
+**                  closed, and device specific finalizatio nmay be needed.
+**
+** Returns          void.
+**
+*******************************************************************************/
+extern void bta_hh_co_close(UINT8 dev_handle, UINT8 app_id);
+
+#if (BLE_INCLUDED == TRUE && BTA_HH_LE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         bta_hh_le_co_rpt_info
+**
+** Description      This callout function is to convey the report information on
+**                  a HOGP device to the application. Application can save this
+**                  information in NV if device is bonded and load it back when
+**                  stack reboot.
+**
+** Parameters       remote_bda  - remote device address
+**                  p_entry     - report entry pointer
+**                  app_id      - application id
+**
+** Returns          void.
+**
+*******************************************************************************/
+extern void bta_hh_le_co_rpt_info(BD_ADDR remote_bda,
+                                          tBTA_HH_RPT_CACHE_ENTRY *p_entry,
+                                          UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_co_cache_load
+**
+** Description      This callout function is to request the application to load the
+**                  cached HOGP report if there is any. When cache reading is completed,
+**                  bta_hh_le_ci_cache_load() is called by the application.
+**
+** Parameters       remote_bda  - remote device address
+**                  p_num_rpt: number of cached report
+**                  app_id      - application id
+**
+** Returns          the acched report array
+**
+*******************************************************************************/
+extern tBTA_HH_RPT_CACHE_ENTRY *bta_hh_le_co_cache_load (BD_ADDR remote_bda,
+                                                                 UINT8 *p_num_rpt,
+                                                                 UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_hh_le_co_reset_rpt_cache
+**
+** Description      This callout function is to reset the HOGP device cache.
+**
+** Parameters       remote_bda  - remote device address
+**
+** Returns          none
+**
+*******************************************************************************/
+extern void bta_hh_le_co_reset_rpt_cache (BD_ADDR remote_bda, UINT8 app_id);
+
+#endif /* #if (BLE_INCLUDED == TRUE && BTA_HH_LE_INCLUDED == TRUE) */
+#endif /* BTA_HH_CO_H */

+ 287 - 0
components/bt/bluedroid/bta/include/bta_sys.h

@@ -0,0 +1,287 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the public interface file for the BTA system manager.
+ *
+ ******************************************************************************/
+#ifndef BTA_SYS_H
+#define BTA_SYS_H
+
+#include "bt_target.h"
+#include "gki.h"
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+
+/* vendor specific event handler function type */
+typedef BOOLEAN (tBTA_SYS_VS_EVT_HDLR)(UINT16 evt, void *p);
+
+/* event handler function type */
+typedef BOOLEAN (tBTA_SYS_EVT_HDLR)(BT_HDR *p_msg);
+
+/* disable function type */
+typedef void (tBTA_SYS_DISABLE)(void);
+
+
+/* HW modules */
+enum
+{
+    BTA_SYS_HW_BLUETOOTH,
+    BTA_SYS_HW_RT,
+
+    BTA_SYS_MAX_HW_MODULES
+};
+
+typedef UINT16 tBTA_SYS_HW_MODULE;
+
+#ifndef BTA_DM_NUM_JV_ID
+#define BTA_DM_NUM_JV_ID    2
+#endif
+
+/* SW sub-systems */
+#define BTA_ID_SYS          0            /* system manager */
+/* BLUETOOTH PART - from 0 to BTA_ID_BLUETOOTH_MAX */
+#define BTA_ID_DM           1            /* device manager */
+#define BTA_ID_DM_SEARCH    2            /* device manager search */
+#define BTA_ID_DM_SEC       3            /* device manager security */
+#define BTA_ID_DG           4            /* data gateway */
+#define BTA_ID_AG           5            /* audio gateway */
+#define BTA_ID_OPC          6            /* object push client */
+#define BTA_ID_OPS          7            /* object push server */
+#define BTA_ID_FTS          8            /* file transfer server */
+#define BTA_ID_CT           9            /* cordless telephony terminal */
+#define BTA_ID_FTC          10           /* file transfer client */
+#define BTA_ID_SS           11           /* synchronization server */
+#define BTA_ID_PR           12           /* Printer client */
+#define BTA_ID_BIC          13           /* Basic Imaging Client */
+#define BTA_ID_PAN          14           /* Personal Area Networking */
+#define BTA_ID_BIS          15           /* Basic Imaging Server */
+#define BTA_ID_ACC          16           /* Advanced Camera Client */
+#define BTA_ID_SC           17           /* SIM Card Access server */
+#define BTA_ID_AV           18           /* Advanced audio/video */
+#define BTA_ID_AVK          19           /* Audio/video sink */
+#define BTA_ID_HD           20           /* HID Device */
+#define BTA_ID_CG           21           /* Cordless Gateway */
+#define BTA_ID_BP           22           /* Basic Printing Client */
+#define BTA_ID_HH           23           /* Human Interface Device Host */
+#define BTA_ID_PBS          24           /* Phone Book Access Server */
+#define BTA_ID_PBC          25           /* Phone Book Access Client */
+#define BTA_ID_JV           26           /* Java */
+#define BTA_ID_HS           27           /* Headset */
+#define BTA_ID_MSE          28           /* Message Server Equipment */
+#define BTA_ID_MCE          29           /* Message Client Equipment */
+#define BTA_ID_HL           30           /* Health Device Profile*/
+#define BTA_ID_GATTC        31           /* GATT Client */
+#define BTA_ID_GATTS        32           /* GATT Client */
+#define BTA_ID_SDP          33           /* SDP Client */
+#define BTA_ID_BLUETOOTH_MAX   34        /* last BT profile */
+
+/* GENERIC */
+#define BTA_ID_PRM          38
+#define BTA_ID_SYSTEM       39           /* platform-specific */
+#define BTA_ID_SWRAP        40           /* Insight script wrapper */
+#define BTA_ID_MIP          41           /* Multicase Individual Polling */
+#define BTA_ID_RT           42           /* Audio Routing module: This module is always on. */
+
+
+/* JV */
+#define BTA_ID_JV1          44           /* JV1 */
+#define BTA_ID_JV2          45           /* JV2 */
+
+#define BTA_ID_MAX          (44 + BTA_DM_NUM_JV_ID)
+
+typedef UINT8 tBTA_SYS_ID;
+
+
+#define BTA_SYS_CONN_OPEN           0x00
+#define BTA_SYS_CONN_CLOSE          0x01
+#define BTA_SYS_APP_OPEN            0x02
+#define BTA_SYS_APP_CLOSE           0x03
+#define BTA_SYS_SCO_OPEN            0x04
+#define BTA_SYS_SCO_CLOSE           0x05
+#define BTA_SYS_CONN_IDLE           0x06
+#define BTA_SYS_CONN_BUSY           0x07
+
+/* for link policy */
+#define BTA_SYS_PLCY_SET            0x10 /* set the link policy to the given addr */
+#define BTA_SYS_PLCY_CLR            0x11 /* clear the link policy to the given addr */
+#define BTA_SYS_PLCY_DEF_SET        0x12 /* set the default link policy */
+#define BTA_SYS_PLCY_DEF_CLR        0x13 /* clear the default link policy */
+#define BTA_SYS_ROLE_CHANGE         0x14 /* role change */
+
+typedef UINT8 tBTA_SYS_CONN_STATUS;
+
+/* Bitmask of sys features */
+#define BTA_SYS_FEAT_PCM2           0x0001
+#define BTA_SYS_FEAT_PCM2_MASTER    0x0002
+
+/* tBTA_PREF_ROLES */
+typedef UINT8 tBTA_SYS_PREF_ROLES;
+
+/* conn callback for role / low power manager*/
+typedef void (tBTA_SYS_CONN_CBACK)(tBTA_SYS_CONN_STATUS status,UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+
+/* conn callback for role / low power manager*/
+typedef void (tBTA_SYS_SSR_CFG_CBACK)(UINT8 id, UINT8 app_id, UINT16 latency, UINT16 tout);
+
+#if (BTA_EIR_CANNED_UUID_LIST != TRUE)
+/* eir callback for adding/removeing UUID */
+typedef void (tBTA_SYS_EIR_CBACK)(UINT16 uuid16, BOOLEAN adding);
+#endif
+
+/* registration structure */
+typedef struct
+{
+    tBTA_SYS_EVT_HDLR   *evt_hdlr;
+    tBTA_SYS_DISABLE    *disable;
+} tBTA_SYS_REG;
+
+/* data type to send events to BTA SYS HW manager */
+typedef struct
+{
+    BT_HDR                hdr;
+    tBTA_SYS_HW_MODULE   hw_module;
+} tBTA_SYS_HW_MSG;
+
+/*****************************************************************************
+**  Global data
+*****************************************************************************/
+
+/* trace level */
+extern UINT8 appl_trace_level;
+
+/*****************************************************************************
+**  Macros
+*****************************************************************************/
+
+/* Calculate start of event enumeration; id is top 8 bits of event */
+#define BTA_SYS_EVT_START(id)       ((id) << 8)
+
+/*****************************************************************************
+**  events for BTA SYS HW manager
+*****************************************************************************/
+
+/* events sent to SYS HW manager - must be kept synchronized with tables in bta_sys_main.c */
+enum
+{
+    /* device manager local device API events */
+    BTA_SYS_API_ENABLE_EVT = BTA_SYS_EVT_START(BTA_ID_SYS),
+    BTA_SYS_EVT_ENABLED_EVT,
+    BTA_SYS_EVT_STACK_ENABLED_EVT,
+    BTA_SYS_API_DISABLE_EVT,
+    BTA_SYS_EVT_DISABLED_EVT,
+    BTA_SYS_ERROR_EVT,
+
+    BTA_SYS_MAX_EVT
+};
+
+
+
+/* SYS HW status events - returned by SYS HW manager to other modules. */
+enum
+{
+    BTA_SYS_HW_OFF_EVT,
+    BTA_SYS_HW_ON_EVT,
+    BTA_SYS_HW_STARTING_EVT,
+    BTA_SYS_HW_STOPPING_EVT,
+    BTA_SYS_HW_ERROR_EVT
+
+};
+typedef UINT8 tBTA_SYS_HW_EVT;
+
+/* HW enable callback type */
+typedef void (tBTA_SYS_HW_CBACK)(tBTA_SYS_HW_EVT status);
+
+/*****************************************************************************
+**  Function declarations
+*****************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void bta_sys_init(void);
+extern void bta_sys_free(void);
+extern void bta_sys_event(BT_HDR *p_msg);
+extern void bta_sys_set_trace_level(UINT8 level);
+extern void bta_sys_register(UINT8 id, const tBTA_SYS_REG *p_reg);
+extern void bta_sys_deregister(UINT8 id);
+extern BOOLEAN bta_sys_is_register(UINT8 id);
+extern UINT16 bta_sys_get_sys_features(void);
+extern void bta_sys_sendmsg(void *p_msg);
+extern void bta_sys_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout_ms);
+extern void bta_sys_stop_timer(TIMER_LIST_ENT *p_tle);
+extern void bta_sys_disable(tBTA_SYS_HW_MODULE module);
+extern UINT32 bta_sys_get_remaining_ticks(TIMER_LIST_ENT *p_target_tle);
+
+extern void bta_sys_hw_register( tBTA_SYS_HW_MODULE module, tBTA_SYS_HW_CBACK *cback);
+extern void bta_sys_hw_unregister( tBTA_SYS_HW_MODULE module );
+
+
+extern void bta_sys_rm_register(tBTA_SYS_CONN_CBACK * p_cback);
+extern void bta_sys_pm_register(tBTA_SYS_CONN_CBACK * p_cback);
+
+extern void bta_sys_policy_register(tBTA_SYS_CONN_CBACK * p_cback);
+extern void bta_sys_sco_register(tBTA_SYS_CONN_CBACK * p_cback);
+
+
+extern void bta_sys_conn_open(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_conn_close(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_app_open(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_app_close(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_sco_open(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_sco_close(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_sco_use(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_sco_unuse(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_idle(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_busy(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+
+#if (BTM_SSR_INCLUDED == TRUE)
+extern void bta_sys_ssr_cfg_register(tBTA_SYS_SSR_CFG_CBACK * p_cback);
+extern void bta_sys_chg_ssr_config (UINT8 id, UINT8 app_id, UINT16 max_latency, UINT16 min_tout);
+#endif
+
+extern void bta_sys_role_chg_register(tBTA_SYS_CONN_CBACK * p_cback);
+extern void bta_sys_notify_role_chg(BD_ADDR_PTR p_bda, UINT8 new_role, UINT8 hci_status);
+extern void bta_sys_collision_register(UINT8 bta_id, tBTA_SYS_CONN_CBACK *p_cback);
+extern void bta_sys_notify_collision (BD_ADDR_PTR p_bda);
+
+#if (BTA_EIR_CANNED_UUID_LIST != TRUE)
+extern void bta_sys_eir_register(tBTA_SYS_EIR_CBACK * p_cback);
+extern void bta_sys_add_uuid(UINT16 uuid16);
+extern void bta_sys_remove_uuid(UINT16 uuid16);
+#else
+#define bta_sys_eir_register(ut)
+#define bta_sys_add_uuid(ut)
+#define bta_sys_remove_uuid(ut)
+#endif
+
+extern void bta_sys_set_policy (UINT8 id, UINT8 policy, BD_ADDR peer_addr);
+extern void bta_sys_clear_policy (UINT8 id, UINT8 policy, BD_ADDR peer_addr);
+extern void bta_sys_set_default_policy (UINT8 id, UINT8 policy);
+extern void bta_sys_clear_default_policy (UINT8 id, UINT8 policy);
+extern BOOLEAN bta_sys_vs_hdl(UINT16 evt, void *p);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_SYS_H */

+ 170 - 0
components/bt/bluedroid/bta/include/utl.h

@@ -0,0 +1,170 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  Basic utility functions.
+ *
+ ******************************************************************************/
+#ifndef UTL_H
+#define UTL_H
+
+#include "bt_types.h"
+// #include "bt_utils.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+/*** class of device settings ***/
+#define BTA_UTL_SET_COD_MAJOR_MINOR     0x01
+#define BTA_UTL_SET_COD_SERVICE_CLASS   0x02 /* only set the bits in the input */
+#define BTA_UTL_CLR_COD_SERVICE_CLASS   0x04
+#define BTA_UTL_SET_COD_ALL             0x08 /* take service class as the input (may clear some set bits!!) */
+#define BTA_UTL_INIT_COD                0x0a
+
+/*****************************************************************************
+**  Type Definitions
+*****************************************************************************/
+
+/** for utl_set_device_class() **/
+typedef struct
+{
+    UINT8       minor;
+    UINT8       major;
+    UINT16      service;
+} tBTA_UTL_COD;
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*****************************************************************************
+**  External Function Declarations
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function         utl_str2int
+**
+** Description      This utility function converts a character string to an
+**                  integer.  Acceptable values in string are 0-9.  If invalid
+**                  string or string value too large, -1 is returned.
+**
+**
+** Returns          Integer value or -1 on error.
+**
+*******************************************************************************/
+extern INT16 utl_str2int(const char *p_s);
+
+/*******************************************************************************
+**
+** Function         utl_strucmp
+**
+** Description      This utility function compares two strings in uppercase.
+**                  String p_s must be uppercase.  String p_t is converted to
+**                  uppercase if lowercase.  If p_s ends first, the substring
+**                  match is counted as a match.
+**
+**
+** Returns          0 if strings match, nonzero otherwise.
+**
+*******************************************************************************/
+extern int utl_strucmp(const char *p_s, const char *p_t);
+
+/*******************************************************************************
+**
+** Function         utl_itoa
+**
+** Description      This utility function converts a UINT16 to a string.  The
+**                  string is NULL-terminated.  The length of the string is
+**                  returned.
+**
+**
+** Returns          Length of string.
+**
+*******************************************************************************/
+extern UINT8 utl_itoa(UINT16 i, char *p_s);
+
+/*******************************************************************************
+**
+** Function         utl_freebuf
+**
+** Description      This function calls GKI_freebuf to free the buffer passed
+**                  in, if buffer pointer is not NULL, and also initializes
+**                  buffer pointer to NULL.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+extern void utl_freebuf(void **p);
+
+/*******************************************************************************
+**
+** Function         utl_set_device_class
+**
+** Description      This function updates the local Device Class.
+**
+** Parameters:
+**                  p_cod   - Pointer to the device class to set to
+**
+**                  cmd     - the fields of the device class to update.
+**                            BTA_UTL_SET_COD_MAJOR_MINOR, - overwrite major, minor class
+**                            BTA_UTL_SET_COD_SERVICE_CLASS - set the bits in the input
+**                            BTA_UTL_CLR_COD_SERVICE_CLASS - clear the bits in the input
+**                            BTA_UTL_SET_COD_ALL - overwrite major, minor, set the bits in service class
+**                            BTA_UTL_INIT_COD - overwrite major, minor, and service class
+**
+** Returns          TRUE if successful, Otherwise FALSE
+**
+*******************************************************************************/
+extern BOOLEAN utl_set_device_class(tBTA_UTL_COD *p_cod, UINT8 cmd);
+
+/*******************************************************************************
+**
+** Function         utl_isintstr
+**
+** Description      This utility function checks if the given string is an
+**                  integer string or not
+**
+**
+** Returns          TRUE if successful, Otherwise FALSE
+**
+*******************************************************************************/
+extern BOOLEAN utl_isintstr(const char *p_s);
+
+/*******************************************************************************
+**
+** Function         utl_isdialstr
+**
+** Description      This utility function checks if the given string contains
+**                  only dial digits or not
+**
+**
+** Returns          TRUE if successful, Otherwise FALSE
+**
+*******************************************************************************/
+extern BOOLEAN utl_isdialstr(const char *p_s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UTL_H */

+ 598 - 0
components/bt/bluedroid/bta/sys/bta_sys_conn.c

@@ -0,0 +1,598 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  Routes connection status callbacks from various sub systems to DM
+ *
+ ******************************************************************************/
+
+#include <stddef.h>
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_sys_int.h"
+#include "gki.h"
+#include "utl.h"
+
+/*******************************************************************************
+**
+** Function         bta_sys_rm_register
+**
+** Description      Called by BTA DM to register role management callbacks
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_rm_register(tBTA_SYS_CONN_CBACK * p_cback)
+{
+    bta_sys_cb.prm_cb = p_cback;
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_policy_register
+**
+** Description      Called by BTA DM to register link policy change callbacks
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_policy_register(tBTA_SYS_CONN_CBACK * p_cback)
+{
+    bta_sys_cb.p_policy_cb = p_cback;
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_role_chg_register
+**
+** Description      Called by BTA AV to register role change callbacks
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_role_chg_register(tBTA_SYS_CONN_CBACK * p_cback)
+{
+    bta_sys_cb.p_role_cb = p_cback;
+}
+/*******************************************************************************
+**
+** Function         bta_sys_ssr_cfg_register
+**
+** Description      Called by BTA DM to register SSR configuration callback
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+#if (BTM_SSR_INCLUDED == TRUE)
+void bta_sys_ssr_cfg_register(tBTA_SYS_SSR_CFG_CBACK * p_cback)
+{
+    bta_sys_cb.p_ssr_cb = p_cback;
+}
+#endif
+/*******************************************************************************
+**
+** Function         bta_sys_role_chg_register
+**
+** Description      Called by BTA AV to register role change callbacks
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_notify_role_chg(BD_ADDR_PTR p_bda, UINT8 new_role, UINT8 hci_status)
+{
+    if (bta_sys_cb.p_role_cb)
+    {
+        bta_sys_cb.p_role_cb(BTA_SYS_ROLE_CHANGE, new_role, hci_status, p_bda);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_collision_register
+**
+** Description      Called by any BTA module to register for collision event.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_collision_register(UINT8 bta_id, tBTA_SYS_CONN_CBACK *p_cback)
+{
+    UINT8 index;
+
+    for (index = 0; index < MAX_COLLISION_REG; index++)
+    {
+        if ((bta_sys_cb.colli_reg.id[index] == bta_id) ||
+            (bta_sys_cb.colli_reg.id[index] == 0))
+        {
+            bta_sys_cb.colli_reg.id[index] = bta_id;
+            bta_sys_cb.colli_reg.p_coll_cback[index] = p_cback;
+            return;
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_notify_collision
+**
+** Description      Called by BTA DM to notify collision event.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_notify_collision (BD_ADDR_PTR p_bda)
+{
+    UINT8 index;
+
+    for (index = 0; index < MAX_COLLISION_REG; index++)
+    {
+        if ((bta_sys_cb.colli_reg.id[index] != 0) &&
+            (bta_sys_cb.colli_reg.p_coll_cback[index] != NULL))
+        {
+            bta_sys_cb.colli_reg.p_coll_cback[index] (0, BTA_ID_SYS, 0, p_bda);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_sco_register
+**
+** Description      Called by BTA AV to register sco connection change callbacks
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_sco_register(tBTA_SYS_CONN_CBACK * p_cback)
+{
+    bta_sys_cb.p_sco_cb = p_cback;
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_pm_register
+**
+** Description      Called by BTA DM to register power management callbacks
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_pm_register(tBTA_SYS_CONN_CBACK * p_cback)
+{
+    bta_sys_cb.ppm_cb = p_cback;
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_conn_open
+**
+** Description      Called by BTA subsystems when a connection is made to
+**                  the service
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_conn_open(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+    if(bta_sys_cb.prm_cb)
+    {
+
+        bta_sys_cb.prm_cb(BTA_SYS_CONN_OPEN, id, app_id, peer_addr);
+
+    }
+
+    if(bta_sys_cb.ppm_cb)
+    {
+
+        bta_sys_cb.ppm_cb(BTA_SYS_CONN_OPEN, id, app_id, peer_addr);
+
+    }
+}
+
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_conn_close
+**
+** Description      Called by BTA subsystems when a connection to the service
+**                  is closed
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_conn_close(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+    if(bta_sys_cb.prm_cb)
+    {
+
+        bta_sys_cb.prm_cb(BTA_SYS_CONN_CLOSE, id, app_id, peer_addr);
+
+    }
+
+    if(bta_sys_cb.ppm_cb)
+    {
+
+        bta_sys_cb.ppm_cb(BTA_SYS_CONN_CLOSE, id, app_id, peer_addr);
+
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_app_open
+**
+** Description      Called by BTA subsystems when application initiates connection
+**                  to a peer device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_app_open(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+    if(bta_sys_cb.ppm_cb)
+    {
+        bta_sys_cb.ppm_cb(BTA_SYS_APP_OPEN, id, app_id, peer_addr);
+    }
+}
+
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_app_close
+**
+** Description      Called by BTA subsystems when application initiates close
+**                  of connection to peer device
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_app_close(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+    if(bta_sys_cb.ppm_cb)
+    {
+        bta_sys_cb.ppm_cb(BTA_SYS_APP_CLOSE, id, app_id, peer_addr);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_sco_open
+**
+** Description      Called by BTA subsystems when sco connection for that service
+**                  is open
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_sco_open(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+    /* AG triggers p_sco_cb by bta_sys_sco_use. */
+    if((id != BTA_ID_AG) && (bta_sys_cb.p_sco_cb))
+    {
+        /* without querying BTM_GetNumScoLinks() */
+        bta_sys_cb.p_sco_cb(BTA_SYS_SCO_OPEN, 1, app_id, peer_addr);
+    }
+
+    if(bta_sys_cb.ppm_cb)
+    {
+        bta_sys_cb.ppm_cb(BTA_SYS_SCO_OPEN, id, app_id, peer_addr);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_sco_close
+**
+** Description      Called by BTA subsystems when sco connection for that service
+**                  is closed
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_sco_close(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+    UINT8 num_sco_links;
+
+    if((id != BTA_ID_AG) && (bta_sys_cb.p_sco_cb))
+    {
+        num_sco_links = BTM_GetNumScoLinks();
+        bta_sys_cb.p_sco_cb(BTA_SYS_SCO_CLOSE, num_sco_links, app_id, peer_addr);
+    }
+
+    if(bta_sys_cb.ppm_cb)
+    {
+        bta_sys_cb.ppm_cb(BTA_SYS_SCO_CLOSE, id, app_id, peer_addr);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_sco_use
+**
+** Description      Called by BTA subsystems when that service needs to use sco.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_sco_use(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+    UNUSED(id);
+
+    /* AV streaming need to be suspended before SCO is connected. */
+    if(bta_sys_cb.p_sco_cb)
+    {
+        /* without querying BTM_GetNumScoLinks() */
+        bta_sys_cb.p_sco_cb(BTA_SYS_SCO_OPEN, 1, app_id, peer_addr);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_sco_unuse
+**
+** Description      Called by BTA subsystems when sco connection for that service
+**                  is no longer needed.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_sco_unuse(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+    UINT8 num_sco_links;
+    UNUSED(id);
+
+    if((bta_sys_cb.p_sco_cb))
+    {
+        num_sco_links = BTM_GetNumScoLinks();
+        bta_sys_cb.p_sco_cb(BTA_SYS_SCO_CLOSE, num_sco_links, app_id, peer_addr);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_sys_chg_ssr_config
+**
+** Description      Called by BTA subsystems to indicate that the given app SSR setting
+**                  need to be changed.
+**
+** Returns          void
+**
+*******************************************************************************/
+#if (BTM_SSR_INCLUDED == TRUE)
+void bta_sys_chg_ssr_config (UINT8 id, UINT8 app_id, UINT16 max_latency, UINT16 min_tout)
+{
+    if(bta_sys_cb.p_ssr_cb)
+    {
+        bta_sys_cb.p_ssr_cb(id, app_id, max_latency, min_tout);
+    }
+}
+#endif
+/*******************************************************************************
+**
+** Function         bta_sys_set_policy
+**
+** Description      Called by BTA subsystems to indicate that the given link
+**                  policy to peer device should be set
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_set_policy (UINT8 id, UINT8 policy, BD_ADDR peer_addr)
+{
+    if(bta_sys_cb.p_policy_cb)
+    {
+        bta_sys_cb.p_policy_cb(BTA_SYS_PLCY_SET, id, policy, peer_addr);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_clear_policy
+**
+** Description      Called by BTA subsystems to indicate that the given link
+**                  policy to peer device should be clear
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_clear_policy (UINT8 id, UINT8 policy, BD_ADDR peer_addr)
+{
+    if(bta_sys_cb.p_policy_cb)
+    {
+        bta_sys_cb.p_policy_cb(BTA_SYS_PLCY_CLR, id, policy, peer_addr);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_set_default_policy
+**
+** Description      Called by BTA subsystems to indicate that the given default
+**                  link policy should be set
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_set_default_policy (UINT8 id, UINT8 policy)
+{
+    if(bta_sys_cb.p_policy_cb)
+    {
+        bta_sys_cb.p_policy_cb(BTA_SYS_PLCY_DEF_SET, id, policy, NULL);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_clear_default_policy
+**
+** Description      Called by BTA subsystems to indicate that the given default
+**                  link policy should be clear
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_clear_default_policy (UINT8 id, UINT8 policy)
+{
+    if(bta_sys_cb.p_policy_cb)
+    {
+        bta_sys_cb.p_policy_cb(BTA_SYS_PLCY_DEF_CLR, id, policy, NULL);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_idle
+**
+** Description      Called by BTA subsystems to indicate that the connection to
+**                  peer device is idle
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_idle(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+
+    if(bta_sys_cb.prm_cb)
+    {
+
+        bta_sys_cb.prm_cb(BTA_SYS_CONN_IDLE, id, app_id, peer_addr);
+
+    }
+
+    if(bta_sys_cb.ppm_cb)
+    {
+
+        bta_sys_cb.ppm_cb(BTA_SYS_CONN_IDLE, id, app_id, peer_addr);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_busy
+**
+** Description      Called by BTA subsystems to indicate that the connection to
+**                  peer device is busy
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_busy(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+    if(bta_sys_cb.prm_cb)
+    {
+
+        bta_sys_cb.prm_cb(BTA_SYS_CONN_BUSY, id, app_id, peer_addr);
+
+    }
+
+    if(bta_sys_cb.ppm_cb)
+    {
+
+        bta_sys_cb.ppm_cb(BTA_SYS_CONN_BUSY, id, app_id, peer_addr);
+
+    }
+}
+
+#if (BTA_EIR_CANNED_UUID_LIST != TRUE)
+/*******************************************************************************
+**
+** Function         bta_sys_eir_register
+**
+** Description      Called by BTA DM to register EIR utility function that can be
+**                  used by the other BTA modules to add/remove UUID.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_eir_register(tBTA_SYS_EIR_CBACK * p_cback)
+{
+    bta_sys_cb.eir_cb = p_cback;
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_add_uuid
+**
+** Description      Called by BTA subsystems to indicate to DM that new service
+**                  class UUID is added.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_add_uuid(UINT16 uuid16)
+{
+    if(bta_sys_cb.eir_cb)
+    {
+        bta_sys_cb.eir_cb(uuid16, TRUE );
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_remove_uuid
+**
+** Description      Called by BTA subsystems to indicate to DM that the service
+**                  class UUID is removed.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_remove_uuid(UINT16 uuid16)
+{
+    if(bta_sys_cb.eir_cb)
+    {
+        bta_sys_cb.eir_cb(uuid16, FALSE);
+    }
+}
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_sys_vs_hdl
+**
+** Description      Called by BTA subsystems to execute a VS event handler function
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN bta_sys_vs_hdl(UINT16 evt, void *p)
+{
+    if (bta_sys_cb.p_vs_evt_hdlr)
+        return (*bta_sys_cb.p_vs_evt_hdlr)(evt, p);
+
+    return FALSE;
+}
+

+ 754 - 0
components/bt/bluedroid/bta/sys/bta_sys_main.c

@@ -0,0 +1,754 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the main implementation file for the BTA system manager.
+ *
+ ******************************************************************************/
+#define LOG_TAG "bt_bta_sys_main"
+
+// #include <assert.h>
+#include <string.h>
+
+#include "alarm.h"
+#include "thread.h"
+#include "btm_api.h"
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_sys_int.h"
+
+#include "fixed_queue.h"
+#include "gki.h"
+#include "hash_map.h"
+#include "osi.h"
+#include "hash_functions.h"
+// #include "osi/include/log.h"
+// #include "osi/include/thread.h"
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+#include "bta_ar_api.h"
+#endif
+#include "utl.h"
+
+
+/* system manager control block definition */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_SYS_CB bta_sys_cb;
+#endif
+
+fixed_queue_t *btu_bta_alarm_queue;
+static hash_map_t *bta_alarm_hash_map;
+static const size_t BTA_ALARM_HASH_MAP_SIZE = 17;
+static pthread_mutex_t bta_alarm_lock;
+// extern thread_t *bt_workqueue_thread;
+
+/* trace level */
+/* TODO Bluedroid - Hard-coded trace levels -  Needs to be configurable */
+UINT8 appl_trace_level = BT_TRACE_LEVEL_WARNING; //APPL_INITIAL_TRACE_LEVEL;
+UINT8 btif_trace_level = BT_TRACE_LEVEL_WARNING;
+
+// Communication queue between btu_task and bta.
+extern fixed_queue_t *btu_bta_msg_queue;
+void btu_bta_alarm_ready(fixed_queue_t *queue);
+
+static const tBTA_SYS_REG bta_sys_hw_reg =
+{
+    bta_sys_sm_execute,
+    NULL
+};
+
+
+/* type for action functions */
+typedef void (*tBTA_SYS_ACTION)(tBTA_SYS_HW_MSG *p_data);
+
+/* action function list */
+const tBTA_SYS_ACTION bta_sys_action[] =
+{
+    /* device manager local device API events - cf bta_sys.h for events */
+    bta_sys_hw_api_enable,             /* 0  BTA_SYS_HW_API_ENABLE_EVT    */
+    bta_sys_hw_evt_enabled,           /* 1  BTA_SYS_HW_EVT_ENABLED_EVT */
+    bta_sys_hw_evt_stack_enabled,       /* 2  BTA_SYS_HW_EVT_STACK_ENABLED_EVT */
+    bta_sys_hw_api_disable,             /* 3  BTA_SYS_HW_API_DISABLE_EVT     */
+    bta_sys_hw_evt_disabled,           /* 4  BTA_SYS_HW_EVT_DISABLED_EVT  */
+    bta_sys_hw_error                        /* 5   BTA_SYS_HW_ERROR_EVT  */
+};
+
+/* state machine action enumeration list */
+enum
+{
+    /* device manager local device API events */
+    BTA_SYS_HW_API_ENABLE,
+    BTA_SYS_HW_EVT_ENABLED,
+    BTA_SYS_HW_EVT_STACK_ENABLED,
+    BTA_SYS_HW_API_DISABLE,
+    BTA_SYS_HW_EVT_DISABLED,
+    BTA_SYS_HW_ERROR
+};
+
+#define BTA_SYS_NUM_ACTIONS  (BTA_SYS_MAX_EVT & 0x00ff)
+#define BTA_SYS_IGNORE       BTA_SYS_NUM_ACTIONS
+
+/* state table information */
+#define BTA_SYS_ACTIONS              2       /* number of actions */
+#define BTA_SYS_NEXT_STATE           2       /* position of next state */
+#define BTA_SYS_NUM_COLS             3       /* number of columns in state tables */
+
+
+/* state table for OFF state */
+const UINT8 bta_sys_hw_off[][BTA_SYS_NUM_COLS] =
+{
+/* Event                    Action 1               Action 2             Next State */
+/* API_ENABLE    */  {BTA_SYS_HW_API_ENABLE,    BTA_SYS_IGNORE,     BTA_SYS_HW_STARTING},
+/* EVT_ENABLED   */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_STARTING},
+/* STACK_ENABLED */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_ON},
+/* API_DISABLE   */  {BTA_SYS_HW_EVT_DISABLED,  BTA_SYS_IGNORE,     BTA_SYS_HW_OFF},
+/* EVT_DISABLED  */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_OFF},
+/* EVT_ERROR     */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_OFF}
+};
+
+const UINT8 bta_sys_hw_starting[][BTA_SYS_NUM_COLS] =
+{
+/* Event                    Action 1                   Action 2               Next State */
+/* API_ENABLE    */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_STARTING}, /* wait for completion event */
+/* EVT_ENABLED   */  {BTA_SYS_HW_EVT_ENABLED,       BTA_SYS_IGNORE,         BTA_SYS_HW_STARTING},
+/* STACK_ENABLED */  {BTA_SYS_HW_EVT_STACK_ENABLED, BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
+/* API_DISABLE   */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_STOPPING}, /* successive disable/enable: change state wait for completion to disable */
+/* EVT_DISABLED  */  {BTA_SYS_HW_EVT_DISABLED,      BTA_SYS_HW_API_ENABLE,  BTA_SYS_HW_STARTING}, /* successive enable/disable: notify, then restart HW */
+/* EVT_ERROR */      {BTA_SYS_HW_ERROR,             BTA_SYS_IGNORE,         BTA_SYS_HW_ON}
+};
+
+const UINT8 bta_sys_hw_on[][BTA_SYS_NUM_COLS] =
+{
+/* Event                    Action 1                   Action 2               Next State */
+/* API_ENABLE    */  {BTA_SYS_HW_API_ENABLE,        BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
+/* EVT_ENABLED   */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
+/* STACK_ENABLED */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
+/* API_DISABLE   */  {BTA_SYS_HW_API_DISABLE,       BTA_SYS_IGNORE,         BTA_SYS_HW_ON}, /* don't change the state here, as some other modules might be active */
+/* EVT_DISABLED */   {BTA_SYS_HW_ERROR,             BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
+/* EVT_ERROR */      {BTA_SYS_HW_ERROR,             BTA_SYS_IGNORE,         BTA_SYS_HW_ON}
+};
+
+const UINT8 bta_sys_hw_stopping[][BTA_SYS_NUM_COLS] =
+{
+/* Event                    Action 1                   Action 2               Next State */
+/* API_ENABLE    */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_STARTING}, /* change state, and wait for completion event to enable */
+/* EVT_ENABLED   */  {BTA_SYS_HW_EVT_ENABLED,       BTA_SYS_IGNORE,         BTA_SYS_HW_STOPPING}, /* successive enable/disable: finish the enable before disabling */
+/* STACK_ENABLED */  {BTA_SYS_HW_EVT_STACK_ENABLED, BTA_SYS_HW_API_DISABLE, BTA_SYS_HW_STOPPING}, /* successive enable/disable: notify, then stop */
+/* API_DISABLE   */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_STOPPING}, /* wait for completion event */
+/* EVT_DISABLED  */  {BTA_SYS_HW_EVT_DISABLED,      BTA_SYS_IGNORE,         BTA_SYS_HW_OFF},
+/* EVT_ERROR     */  {BTA_SYS_HW_API_DISABLE,       BTA_SYS_IGNORE,         BTA_SYS_HW_STOPPING}
+};
+
+typedef const UINT8 (*tBTA_SYS_ST_TBL)[BTA_SYS_NUM_COLS];
+
+/* state table */
+const tBTA_SYS_ST_TBL bta_sys_st_tbl[] = {
+    bta_sys_hw_off,
+    bta_sys_hw_starting,
+    bta_sys_hw_on,
+    bta_sys_hw_stopping
+};
+
+/*******************************************************************************
+**
+** Function         bta_sys_init
+**
+** Description      BTA initialization; called from task initialization.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_init(void)
+{
+    memset(&bta_sys_cb, 0, sizeof(tBTA_SYS_CB));
+    
+    pthread_mutex_init(&bta_alarm_lock, NULL);
+
+    bta_alarm_hash_map = hash_map_new(BTA_ALARM_HASH_MAP_SIZE,
+            hash_function_pointer, NULL, (data_free_fn)osi_alarm_free, NULL);
+    btu_bta_alarm_queue = fixed_queue_new(SIZE_MAX);
+
+    fixed_queue_register_dequeue(btu_bta_alarm_queue,
+				 btu_bta_alarm_ready);
+
+    appl_trace_level = APPL_INITIAL_TRACE_LEVEL;
+
+    /* register BTA SYS message handler */
+    bta_sys_register( BTA_ID_SYS,  &bta_sys_hw_reg);
+
+    /* register for BTM notifications */
+    BTM_RegisterForDeviceStatusNotif ((tBTM_DEV_STATUS_CB*)&bta_sys_hw_btm_cback );
+
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+    bta_ar_init();
+#endif
+
+}
+
+void bta_sys_free(void) {
+    fixed_queue_free(btu_bta_alarm_queue, NULL);
+    hash_map_free(bta_alarm_hash_map);
+    pthread_mutex_destroy(&bta_alarm_lock);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_sm_execute
+**
+** Description      State machine event handling function for DM
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN bta_sys_sm_execute(BT_HDR *p_msg)
+{
+    BOOLEAN freebuf = TRUE;
+    tBTA_SYS_ST_TBL      state_table;
+    UINT8               action;
+    int                 i;
+
+    APPL_TRACE_EVENT("bta_sys_sm_execute state:%d, event:0x%x",  bta_sys_cb.state, p_msg->event);
+
+    /* look up the state table for the current state */
+    state_table = bta_sys_st_tbl[bta_sys_cb.state];
+    /* update state */
+    bta_sys_cb.state = state_table[p_msg->event & 0x00ff][BTA_SYS_NEXT_STATE];
+
+    /* execute action functions */
+    for (i = 0; i < BTA_SYS_ACTIONS; i++)
+    {
+        if ((action = state_table[p_msg->event & 0x00ff][i]) != BTA_SYS_IGNORE)
+        {
+            (*bta_sys_action[action])( (tBTA_SYS_HW_MSG*) p_msg);
+        }
+        else
+        {
+            break;
+        }
+    }
+    return freebuf;
+
+}
+
+
+void bta_sys_hw_register( tBTA_SYS_HW_MODULE module, tBTA_SYS_HW_CBACK *cback)
+{
+    bta_sys_cb.sys_hw_cback[module]=cback;
+}
+
+
+void bta_sys_hw_unregister( tBTA_SYS_HW_MODULE module )
+{
+    bta_sys_cb.sys_hw_cback[module]=NULL;
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_hw_btm_cback
+**
+** Description     This function is registered by BTA SYS to BTM in order to get status notifications
+**
+**
+** Returns
+**
+*******************************************************************************/
+void bta_sys_hw_btm_cback( tBTM_DEV_STATUS status )
+{
+
+    tBTA_SYS_HW_MSG *sys_event;
+
+    APPL_TRACE_DEBUG(" bta_sys_hw_btm_cback was called with parameter: %i" , status );
+
+    /* send a message to BTA SYS */
+    if ((sys_event = (tBTA_SYS_HW_MSG *) GKI_getbuf(sizeof(tBTA_SYS_HW_MSG))) != NULL)
+    {
+        if (status == BTM_DEV_STATUS_UP)
+            sys_event->hdr.event = BTA_SYS_EVT_STACK_ENABLED_EVT;
+        else if (status == BTM_DEV_STATUS_DOWN)
+            sys_event->hdr.event = BTA_SYS_ERROR_EVT;
+        else
+        {
+            /* BTM_DEV_STATUS_CMD_TOUT is ignored for now. */
+            GKI_freebuf (sys_event);
+            sys_event = NULL;
+        }
+
+        if (sys_event)
+        {
+            bta_sys_sendmsg(sys_event);
+        }
+    }
+    else
+    {
+        APPL_TRACE_DEBUG("ERROR bta_sys_hw_btm_cback couldn't send msg" );
+    }
+}
+
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_hw_error
+**
+** Description     In case the HW device stops answering... Try to turn it off, then re-enable all
+**                      previously active SW modules.
+**
+** Returns          success or failure
+**
+*******************************************************************************/
+void bta_sys_hw_error(tBTA_SYS_HW_MSG *p_sys_hw_msg)
+{
+    UINT8 module_index;
+    UNUSED(p_sys_hw_msg);
+
+    APPL_TRACE_DEBUG("%s", __FUNCTION__);
+
+    for (module_index = 0; module_index < BTA_SYS_MAX_HW_MODULES; module_index++)
+    {
+        if( bta_sys_cb.sys_hw_module_active &  ((UINT32)1 << module_index )) {
+            switch( module_index)
+                {
+                case BTA_SYS_HW_BLUETOOTH:
+                   /* Send BTA_SYS_HW_ERROR_EVT to DM */
+                   if (bta_sys_cb.sys_hw_cback[module_index] != NULL)
+                       bta_sys_cb.sys_hw_cback[module_index] (BTA_SYS_HW_ERROR_EVT);
+                    break;
+                default:
+                    /* not yet supported */
+                    break;
+                }
+        }
+    }
+}
+
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_hw_enable
+**
+** Description     this function is called after API enable and HW has been turned on
+**
+**
+** Returns          success or failure
+**
+*******************************************************************************/
+
+void bta_sys_hw_api_enable( tBTA_SYS_HW_MSG *p_sys_hw_msg )
+{
+    if ((!bta_sys_cb.sys_hw_module_active) && (bta_sys_cb.state != BTA_SYS_HW_ON))
+    {
+        /* register which HW module was turned on */
+        bta_sys_cb.sys_hw_module_active |=  ((UINT32)1 << p_sys_hw_msg->hw_module );
+
+        tBTA_SYS_HW_MSG *p_msg;
+        if ((p_msg = (tBTA_SYS_HW_MSG *) GKI_getbuf(sizeof(tBTA_SYS_HW_MSG))) != NULL)
+        {
+            p_msg->hdr.event = BTA_SYS_EVT_ENABLED_EVT;
+            p_msg->hw_module = p_sys_hw_msg->hw_module;
+
+            bta_sys_sendmsg(p_msg);
+        }
+    }
+    else
+    {
+        /* register which HW module was turned on */
+        bta_sys_cb.sys_hw_module_active |=  ((UINT32)1 << p_sys_hw_msg->hw_module );
+
+        /* HW already in use, so directly notify the caller */
+        if (bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module ]!= NULL )
+            bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module ](  BTA_SYS_HW_ON_EVT   );
+    }
+
+    APPL_TRACE_EVENT ("bta_sys_hw_api_enable for %d, active modules 0x%04X",
+                    p_sys_hw_msg->hw_module, bta_sys_cb.sys_hw_module_active);
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_hw_disable
+**
+** Description     if no other module is using the HW, this function will call ( if defined ) a user-macro to turn off the HW
+**
+**
+** Returns          success or failure
+**
+*******************************************************************************/
+void bta_sys_hw_api_disable(tBTA_SYS_HW_MSG *p_sys_hw_msg)
+{
+    APPL_TRACE_DEBUG("bta_sys_hw_api_disable for %d, active modules: 0x%04X",
+        p_sys_hw_msg->hw_module, bta_sys_cb.sys_hw_module_active );
+
+    /* make sure the related SW blocks were stopped */
+    bta_sys_disable( p_sys_hw_msg->hw_module );
+
+
+    /* register which module we turn off */
+    bta_sys_cb.sys_hw_module_active &=  ~((UINT32)1 << p_sys_hw_msg->hw_module );
+
+
+    /* if there are still some SW modules using the HW, just provide an answer to the calling */
+    if( bta_sys_cb.sys_hw_module_active != 0  )
+    {
+        /*  if there are still some SW modules using the HW,  directly notify the caller */
+        if( bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module ]!= NULL )
+            bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module ](  BTA_SYS_HW_OFF_EVT   );
+    }
+    else
+    {
+        /* manually update the state of our system */
+        bta_sys_cb.state = BTA_SYS_HW_STOPPING;
+
+        tBTA_SYS_HW_MSG *p_msg;
+        if ((p_msg = (tBTA_SYS_HW_MSG *) GKI_getbuf(sizeof(tBTA_SYS_HW_MSG))) != NULL)
+        {
+            p_msg->hdr.event = BTA_SYS_EVT_DISABLED_EVT;
+            p_msg->hw_module = p_sys_hw_msg->hw_module;
+
+            bta_sys_sendmsg(p_msg);
+        }
+    }
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_hw_event_enabled
+**
+** Description
+**
+**
+** Returns          success or failure
+**
+*******************************************************************************/
+void bta_sys_hw_evt_enabled(tBTA_SYS_HW_MSG *p_sys_hw_msg)
+{
+    APPL_TRACE_EVENT("bta_sys_hw_evt_enabled for %i", p_sys_hw_msg->hw_module);
+    BTM_DeviceReset( NULL );
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_hw_event_disabled
+**
+** Description
+**
+**
+** Returns          success or failure
+**
+*******************************************************************************/
+void bta_sys_hw_evt_disabled(tBTA_SYS_HW_MSG *p_sys_hw_msg)
+{
+    UINT8 hw_module_index;
+
+    APPL_TRACE_DEBUG("bta_sys_hw_evt_disabled - module 0x%X", p_sys_hw_msg->hw_module);
+
+    for (hw_module_index = 0; hw_module_index < BTA_SYS_MAX_HW_MODULES; hw_module_index++)
+    {
+        if (bta_sys_cb.sys_hw_cback[hw_module_index] != NULL)
+            bta_sys_cb.sys_hw_cback[hw_module_index] (BTA_SYS_HW_OFF_EVT);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_hw_event_stack_enabled
+**
+** Description     we receive this event once the SW side is ready ( stack, FW download,... ),
+**                       i.e. we can really start using the device. So notify the app.
+**
+** Returns          success or failure
+**
+*******************************************************************************/
+void bta_sys_hw_evt_stack_enabled(tBTA_SYS_HW_MSG *p_sys_hw_msg)
+{
+    UINT8 hw_module_index;
+    UNUSED(p_sys_hw_msg);
+
+    APPL_TRACE_DEBUG(" bta_sys_hw_evt_stack_enabled!notify the callers");
+
+    for (hw_module_index = 0; hw_module_index < BTA_SYS_MAX_HW_MODULES; hw_module_index++ )
+    {
+        if (bta_sys_cb.sys_hw_cback[hw_module_index] != NULL)
+            bta_sys_cb.sys_hw_cback[hw_module_index] (BTA_SYS_HW_ON_EVT);
+    }
+}
+
+
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_event
+**
+** Description      BTA event handler; called from task event handler.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_event(BT_HDR *p_msg)
+{
+    UINT8       id;
+    BOOLEAN     freebuf = TRUE;
+
+    APPL_TRACE_EVENT("BTA got event 0x%x", p_msg->event);
+
+    /* get subsystem id from event */
+    id = (UINT8) (p_msg->event >> 8);
+
+    /* verify id and call subsystem event handler */
+    if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL))
+    {
+        freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);
+    }
+    else
+    {
+        APPL_TRACE_WARNING("BTA got unregistered event id %d", id);
+    }
+
+    if (freebuf)
+    {
+        GKI_freebuf(p_msg);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_register
+**
+** Description      Called by other BTA subsystems to register their event
+**                  handler.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_register(UINT8 id, const tBTA_SYS_REG *p_reg)
+{
+    bta_sys_cb.reg[id] = (tBTA_SYS_REG *) p_reg;
+    bta_sys_cb.is_reg[id] = TRUE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_deregister
+**
+** Description      Called by other BTA subsystems to de-register
+**                  handler.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_deregister(UINT8 id)
+{
+    bta_sys_cb.is_reg[id] = FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_is_register
+**
+** Description      Called by other BTA subsystems to get registeration
+**                  status.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN bta_sys_is_register(UINT8 id)
+{
+    return bta_sys_cb.is_reg[id];
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_sendmsg
+**
+** Description      Send a GKI message to BTA.  This function is designed to
+**                  optimize sending of messages to BTA.  It is called by BTA
+**                  API functions and call-in functions.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_sendmsg(void *p_msg)
+{
+    // There is a race condition that occurs if the stack is shut down while
+    // there is a procedure in progress that can schedule a task via this
+    // message queue. This causes |btu_bta_msg_queue| to get cleaned up before
+    // it gets used here; hence we check for NULL before using it.
+    if (btu_bta_msg_queue) {
+        fixed_queue_enqueue(btu_bta_msg_queue, p_msg);
+        //ke_event_set(KE_EVENT_BTU_TASK_THREAD);
+        btu_task_post();
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_start_timer
+**
+** Description      Start a protocol timer for the specified amount
+**                  of time in milliseconds.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_alarm_cb(void *data) {
+  assert(data != NULL);
+  TIMER_LIST_ENT *p_tle = (TIMER_LIST_ENT *)data;
+
+  fixed_queue_enqueue(btu_bta_alarm_queue, p_tle);
+}
+
+void bta_sys_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout_ms) {
+  assert(p_tle != NULL);
+
+  // Get the alarm for this p_tle.
+  pthread_mutex_lock(&bta_alarm_lock);
+  if (!hash_map_has_key(bta_alarm_hash_map, p_tle)) {
+    hash_map_set(bta_alarm_hash_map, p_tle, osi_alarm_new("bta_sys", bta_alarm_cb, p_tle, 0));
+  }
+  pthread_mutex_unlock(&bta_alarm_lock);
+
+ osi_alarm_t *alarm = hash_map_get(bta_alarm_hash_map, p_tle);
+  if (alarm == NULL) {
+    LOG_ERROR("%s unable to create alarm.", __func__);
+    return;
+  }
+
+  p_tle->event = type;
+  p_tle->ticks = timeout_ms;
+  //osi_alarm_set(alarm, (period_ms_t)timeout_ms, bta_alarm_cb, p_tle);
+ osi_alarm_set(alarm, (period_ms_t)timeout_ms);
+}
+
+bool hash_iter_ro_cb(hash_map_entry_t *hash_map_entry, void *context)
+{
+   osi_alarm_t *alarm = (osi_alarm_t *)hash_map_entry->data;
+    period_ms_t *p_remaining_ms = (period_ms_t*)context;
+    *p_remaining_ms +=osi_alarm_get_remaining_ms(alarm);
+    return true;
+}
+
+UINT32 bta_sys_get_remaining_ticks(TIMER_LIST_ENT *p_target_tle)
+{
+    period_ms_t remaining_ms = 0;
+    pthread_mutex_lock(&bta_alarm_lock);
+    // Get the alarm for this p_tle
+    hash_map_foreach(bta_alarm_hash_map, hash_iter_ro_cb, &remaining_ms);
+    pthread_mutex_unlock(&bta_alarm_lock);
+    return remaining_ms;
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_stop_timer
+**
+** Description      Stop a BTA timer.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_stop_timer(TIMER_LIST_ENT *p_tle) {
+  assert(p_tle != NULL);
+
+ osi_alarm_t *alarm = hash_map_get(bta_alarm_hash_map, p_tle);
+  if (alarm == NULL) {
+    LOG_DEBUG("%s expected alarm was not in bta alarm hash map.", __func__);
+    return;
+  }
+ osi_alarm_cancel(alarm);
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_disable
+**
+** Description      For each registered subsystem execute its disable function.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_disable(tBTA_SYS_HW_MODULE module)
+{
+    int bta_id = 0;
+    int bta_id_max = 0;
+
+    APPL_TRACE_DEBUG("bta_sys_disable: module %i", module);
+
+    switch( module )
+    {
+        case BTA_SYS_HW_BLUETOOTH:
+            bta_id = BTA_ID_DM;
+            bta_id_max = BTA_ID_BLUETOOTH_MAX;
+            break;
+        default:
+            APPL_TRACE_WARNING("bta_sys_disable: unkown module");
+            return;
+    }
+
+    for ( ; bta_id <= bta_id_max; bta_id++)
+    {
+        if (bta_sys_cb.reg[bta_id] != NULL)
+        {
+            if (bta_sys_cb.is_reg[bta_id] == TRUE  &&  bta_sys_cb.reg[bta_id]->disable != NULL)
+            {
+                (*bta_sys_cb.reg[bta_id]->disable)();
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_set_trace_level
+**
+** Description      Set trace level for BTA
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_set_trace_level(UINT8 level)
+{
+    appl_trace_level = level;
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_get_sys_features
+**
+** Description      Returns sys_features to other BTA modules.
+**
+** Returns          sys_features
+**
+*******************************************************************************/
+UINT16 bta_sys_get_sys_features (void)
+{
+    return bta_sys_cb.sys_features;
+}

+ 104 - 0
components/bt/bluedroid/bta/sys/include/bta_sys_int.h

@@ -0,0 +1,104 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the private interface file for the BTA system manager.
+ *
+ ******************************************************************************/
+#ifndef BTA_SYS_INT_H
+#define BTA_SYS_INT_H
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+
+/*****************************************************************************
+**  state table
+*****************************************************************************/
+
+/* SYS HW state */
+enum
+{
+    BTA_SYS_HW_OFF,
+    BTA_SYS_HW_STARTING,
+    BTA_SYS_HW_ON,
+    BTA_SYS_HW_STOPPING
+};
+typedef UINT8 tBTA_SYS_HW_STATE;
+
+/* Collision callback */
+#define MAX_COLLISION_REG   5
+
+typedef struct
+{
+    UINT8                   id[MAX_COLLISION_REG];
+    tBTA_SYS_CONN_CBACK     *p_coll_cback[MAX_COLLISION_REG];
+} tBTA_SYS_COLLISION;
+
+/* system manager control block */
+typedef struct
+{
+    tBTA_SYS_REG            *reg[BTA_ID_MAX];       /* registration structures */
+    BOOLEAN                 is_reg[BTA_ID_MAX];     /* registration structures */
+    tBTA_SYS_HW_STATE state;
+    tBTA_SYS_HW_CBACK *sys_hw_cback[BTA_SYS_MAX_HW_MODULES];    /* enable callback for each HW modules */
+    UINT32                  sys_hw_module_active;   /* bitmask of all active modules */
+    UINT16                  sys_features;           /* Bitmask of sys features */
+
+    tBTA_SYS_CONN_CBACK     *prm_cb;                 /* role management callback registered by DM */
+    tBTA_SYS_CONN_CBACK     *ppm_cb;                 /* low power management callback registered by DM */
+    tBTA_SYS_CONN_CBACK     *p_policy_cb;            /* link policy change callback registered by DM */
+    tBTA_SYS_CONN_CBACK     *p_sco_cb;               /* SCO connection change callback registered by AV */
+    tBTA_SYS_CONN_CBACK     *p_role_cb;              /* role change callback registered by AV */
+    tBTA_SYS_COLLISION      colli_reg;               /* collision handling module */
+#if (BTA_EIR_CANNED_UUID_LIST != TRUE)
+    tBTA_SYS_EIR_CBACK      *eir_cb;                /* add/remove UUID into EIR */
+#endif
+#if (BTM_SSR_INCLUDED == TRUE)
+    tBTA_SYS_SSR_CFG_CBACK      *p_ssr_cb;
+#endif
+    /* VS event handler */
+    tBTA_SYS_VS_EVT_HDLR   *p_vs_evt_hdlr;
+
+} tBTA_SYS_CB;
+
+/*****************************************************************************
+**  Global variables
+*****************************************************************************/
+
+/* system manager control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_SYS_CB bta_sys_cb;
+#else
+extern tBTA_SYS_CB *bta_sys_cb_ptr;
+#define bta_sys_cb (*bta_sys_cb_ptr)
+#endif
+
+/* functions used for BTA SYS HW state machine */
+void bta_sys_hw_btm_cback( tBTM_DEV_STATUS status );
+void bta_sys_hw_error(tBTA_SYS_HW_MSG *p_sys_hw_msg);
+void bta_sys_hw_api_enable( tBTA_SYS_HW_MSG *p_sys_hw_msg );
+void bta_sys_hw_api_disable(tBTA_SYS_HW_MSG *p_sys_hw_msg);
+void bta_sys_hw_evt_enabled(tBTA_SYS_HW_MSG *p_sys_hw_msg);
+void bta_sys_hw_evt_disabled(tBTA_SYS_HW_MSG *p_sys_hw_msg);
+void bta_sys_hw_evt_stack_enabled(tBTA_SYS_HW_MSG *p_sys_hw_msg);
+
+BOOLEAN bta_sys_sm_execute(BT_HDR *p_msg);
+
+#endif /* BTA_SYS_INT_H */

+ 299 - 0
components/bt/bluedroid/bta/sys/utl.c

@@ -0,0 +1,299 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This file contains utility functions.
+ *
+ ******************************************************************************/
+#include <stddef.h>
+#include "utl.h"
+#include "gki.h"
+#include "btm_api.h"
+
+/*******************************************************************************
+**
+** Function         utl_str2int
+**
+** Description      This utility function converts a character string to an
+**                  integer.  Acceptable values in string are 0-9.  If invalid
+**                  string or string value too large, -1 is returned.  Leading
+**                  spaces are skipped.
+**
+**
+** Returns          Integer value or -1 on error.
+**
+*******************************************************************************/
+INT16 utl_str2int(const char *p_s)
+{
+    INT32   val = 0;
+
+    for (;*p_s == ' ' && *p_s != 0; p_s++);
+
+    if (*p_s == 0) return -1;
+
+    for (;;)
+    {
+        if ((*p_s < '0') || (*p_s > '9')) return -1;
+
+        val += (INT32) (*p_s++ - '0');
+
+        if (val > 32767) return -1;
+
+        if (*p_s == 0)
+        {
+            return (INT16) val;
+        }
+        else
+        {
+            val *= 10;
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         utl_strucmp
+**
+** Description      This utility function compares two strings in uppercase.
+**                  String p_s must be uppercase.  String p_t is converted to
+**                  uppercase if lowercase.  If p_s ends first, the substring
+**                  match is counted as a match.
+**
+**
+** Returns          0 if strings match, nonzero otherwise.
+**
+*******************************************************************************/
+int utl_strucmp(const char *p_s, const char *p_t)
+{
+    char c;
+
+    while (*p_s && *p_t)
+    {
+        c = *p_t++;
+        if (c >= 'a' && c <= 'z')
+        {
+            c -= 0x20;
+        }
+        if (*p_s++ != c)
+        {
+            return -1;
+        }
+    }
+    /* if p_t hit null first, no match */
+    if (*p_t == 0 && *p_s != 0)
+    {
+        return 1;
+    }
+    /* else p_s hit null first, count as match */
+    else
+    {
+        return 0;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         utl_itoa
+**
+** Description      This utility function converts a UINT16 to a string.  The
+**                  string is NULL-terminated.  The length of the string is
+**                  returned;
+**
+**
+** Returns          Length of string.
+**
+*******************************************************************************/
+UINT8 utl_itoa(UINT16 i, char *p_s)
+{
+    UINT16  j, k;
+    char    *p = p_s;
+    BOOLEAN fill = FALSE;
+
+    if (i == 0)
+    {
+        /* take care of zero case */
+        *p++ = '0';
+    }
+    else
+    {
+        for(j = 10000; j > 0; j /= 10)
+        {
+            k = i / j;
+            i %= j;
+            if (k > 0 || fill)
+            {
+              *p++ = k + '0';
+              fill = TRUE;
+            }
+        }
+    }
+    *p = 0;
+    return (UINT8) (p - p_s);
+}
+
+/*******************************************************************************
+**
+** Function         utl_freebuf
+**
+** Description      This function calls GKI_freebuf to free the buffer passed
+**                  in, if buffer pointer is not NULL, and also initializes
+**                  buffer pointer to NULL.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void utl_freebuf(void **p)
+{
+    if (*p != NULL)
+    {
+        GKI_freebuf(*p);
+        *p = NULL;
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         utl_set_device_class
+**
+** Description      This function updates the local Device Class.
+**
+** Parameters:
+**                  p_cod   - Pointer to the device class to set to
+**
+**                  cmd     - the fields of the device class to update.
+**                            BTA_UTL_SET_COD_MAJOR_MINOR, - overwrite major, minor class
+**                            BTA_UTL_SET_COD_SERVICE_CLASS - set the bits in the input
+**                            BTA_UTL_CLR_COD_SERVICE_CLASS - clear the bits in the input
+**                            BTA_UTL_SET_COD_ALL - overwrite major, minor, set the bits in service class
+**                            BTA_UTL_INIT_COD - overwrite major, minor, and service class
+**
+** Returns          TRUE if successful, Otherwise FALSE
+**
+*******************************************************************************/
+BOOLEAN utl_set_device_class(tBTA_UTL_COD *p_cod, UINT8 cmd)
+{
+    UINT8 *dev;
+    UINT16 service;
+    UINT8  minor, major;
+    DEV_CLASS dev_class;
+
+    dev = BTM_ReadDeviceClass();
+    BTM_COD_SERVICE_CLASS( service, dev );
+    BTM_COD_MINOR_CLASS(minor, dev );
+    BTM_COD_MAJOR_CLASS(major, dev );
+
+    switch(cmd)
+    {
+    case BTA_UTL_SET_COD_MAJOR_MINOR:
+        minor = p_cod->minor & BTM_COD_MINOR_CLASS_MASK;
+        major = p_cod->major & BTM_COD_MAJOR_CLASS_MASK;
+        break;
+
+    case BTA_UTL_SET_COD_SERVICE_CLASS:
+        /* clear out the bits that is not SERVICE_CLASS bits */
+        p_cod->service &= BTM_COD_SERVICE_CLASS_MASK;
+        service = service | p_cod->service;
+        break;
+
+    case BTA_UTL_CLR_COD_SERVICE_CLASS:
+        p_cod->service &= BTM_COD_SERVICE_CLASS_MASK;
+        service = service & (~p_cod->service);
+        break;
+
+    case BTA_UTL_SET_COD_ALL:
+        minor = p_cod->minor & BTM_COD_MINOR_CLASS_MASK;
+        major = p_cod->major & BTM_COD_MAJOR_CLASS_MASK;
+        p_cod->service &= BTM_COD_SERVICE_CLASS_MASK;
+        service = service | p_cod->service;
+        break;
+
+    case BTA_UTL_INIT_COD:
+        minor = p_cod->minor & BTM_COD_MINOR_CLASS_MASK;
+        major = p_cod->major & BTM_COD_MAJOR_CLASS_MASK;
+        service = p_cod->service & BTM_COD_SERVICE_CLASS_MASK;
+        break;
+
+    default:
+        return FALSE;
+    }
+
+    /* convert the fields into the device class type */
+    FIELDS_TO_COD(dev_class, minor, major, service);
+
+    if (BTM_SetDeviceClass(dev_class) == BTM_SUCCESS)
+        return TRUE;
+
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         utl_isintstr
+**
+** Description      This utility function checks if the given string is an
+**                  integer string or not
+**
+**
+** Returns          TRUE if successful, Otherwise FALSE
+**
+*******************************************************************************/
+BOOLEAN utl_isintstr(const char *p_s)
+{
+    UINT16 i = 0;
+
+    for(i=0; p_s[i] != 0; i++)
+    {
+        if(((p_s[i] < '0') || (p_s[i] > '9')) && (p_s[i] != ';'))
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function         utl_isdialstr
+**
+** Description      This utility function checks if the given string contains
+**                  only dial digits or not
+**
+**
+** Returns          TRUE if successful, Otherwise FALSE
+**
+*******************************************************************************/
+BOOLEAN utl_isdialstr(const char *p_s)
+{
+    UINT16 i = 0;
+
+    for(i=0; p_s[i] != 0; i++)
+    {
+        if(!(((p_s[i] >= '0') && (p_s[i] <= '9'))
+            || (p_s[i] == '*') || (p_s[i] == '+') || (p_s[i] == '#') || (p_s[i] == ';')
+            || ((p_s[i] >= 'A') && (p_s[i] <= 'C'))
+            || ((p_s[i] == 'p') || (p_s[i] == 'P')
+            || (p_s[i] == 'w') || (p_s[i] == 'W'))))
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+

+ 107 - 0
components/bt/bluedroid/btcore/bdaddr.c

@@ -0,0 +1,107 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include "bt_trace.h"
+#include "bdaddr.h"
+
+static inline bool ets_isxdigit(char c) {
+  if ((c >= '0') && (c <= '9'))
+    return true;
+  if ((c >= 'a') && (c <= 'f'))
+    return true;
+  return ((c >= 'A') && (c <= 'F'));
+}
+
+bool bdaddr_is_empty(const bt_bdaddr_t *addr) {
+  assert(addr != NULL);
+
+  uint8_t zero[sizeof(bt_bdaddr_t)] = { 0 };
+  return memcmp(addr, &zero, sizeof(bt_bdaddr_t)) == 0;
+}
+
+bool bdaddr_equals(const bt_bdaddr_t *first, const bt_bdaddr_t *second) {
+  assert(first != NULL);
+  assert(second != NULL);
+
+  return memcmp(first, second, sizeof(bt_bdaddr_t)) == 0;
+}
+
+bt_bdaddr_t *bdaddr_copy(bt_bdaddr_t *dest, const bt_bdaddr_t *src) {
+  assert(dest != NULL);
+  assert(src != NULL);
+
+  return (bt_bdaddr_t *)memcpy(dest, src, sizeof(bt_bdaddr_t));
+}
+
+const char *bdaddr_to_string(const bt_bdaddr_t *addr, char *string, size_t size) {
+  assert(addr != NULL);
+  assert(string != NULL);
+
+  if (size < 18)
+    return NULL;
+
+  const uint8_t *ptr = addr->address;
+  sprintf(string, "%02x:%02x:%02x:%02x:%02x:%02x",
+           ptr[0], ptr[1], ptr[2],
+           ptr[3], ptr[4], ptr[5]);
+  return string;
+}
+
+bool string_is_bdaddr(const char *string) {
+  assert(string != NULL);
+
+  size_t len = strlen(string);
+  if (len != 17)
+    return false;
+
+  for (size_t i = 0; i < len; ++i) {
+    // Every 3rd char must be ':'.
+    if (((i + 1) % 3) == 0 && string[i] != ':')
+      return false;
+
+    // All other chars must be a hex digit.
+    if (((i + 1) % 3) != 0 && !ets_isxdigit(string[i]))
+      return false;
+  }
+  return true;
+}
+
+bool string_to_bdaddr(const char *string, bt_bdaddr_t *addr) {
+  assert(string != NULL);
+  assert(addr != NULL);
+
+  bt_bdaddr_t new_addr;
+  uint8_t *ptr = new_addr.address;
+  bool ret = sscanf(string, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
+      &ptr[0], &ptr[1], &ptr[2], &ptr[3], &ptr[4], &ptr[5]) == 6;
+
+  if (ret)
+    memcpy(addr, &new_addr, sizeof(bt_bdaddr_t));
+
+  return ret;
+}
+
+hash_index_t hash_function_bdaddr(const void *key) {
+  hash_index_t hash = 5381;
+  const char *bytes = (const char *)key;
+  for (size_t i = 0; i < sizeof(bt_bdaddr_t); ++i)
+    hash = ((hash << 5) + hash) + bytes[i];
+  return hash;
+}

+ 63 - 0
components/bt/bluedroid/btcore/include/bdaddr.h

@@ -0,0 +1,63 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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 _BDADDR_H_
+#define _BDADDR_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#include "bt_defs.h"
+#include "hash_map.h"
+
+// Note: the string representation of a bdaddr is expected to have the format
+// xx:xx:xx:xx:xx:xx
+// where each 'x' is a hex digit. The API presented in this header will accept
+// both uppercase and lowercase digits but will only ever produce lowercase
+// digits.
+
+// Returns true if |addr| is the empty address (00:00:00:00:00:00).
+// |addr| may not be NULL.
+bool bdaddr_is_empty(const bt_bdaddr_t *addr);
+
+// Returns true if |first| and |second| refer to the same address. Neither
+// may be NULL.
+bool bdaddr_equals(const bt_bdaddr_t *first, const bt_bdaddr_t *second);
+
+// Returns destination bdaddr |dest| after copying |src| to |dest|.
+// |dest| and |src| must not be NULL.
+bt_bdaddr_t *bdaddr_copy(bt_bdaddr_t *dest, const bt_bdaddr_t *src);
+
+// Makes a string representation of |addr| and places it into |string|. |size|
+// refers to the size of |string|'s buffer and must be >= 18. On success, this
+// function returns |string|, otherwise it returns NULL. Neither |addr| nor |string|
+// may be NULL.
+const char *bdaddr_to_string(const bt_bdaddr_t *addr, char *string, size_t size);
+
+// Returns true if |string| represents a Bluetooth address. |string| may not be NULL.
+bool string_is_bdaddr(const char *string);
+
+// Converts |string| to bt_bdaddr_t and places it in |addr|. If |string| does not
+// represent a Bluetooth address, |addr| is not modified and this function returns
+// false. Otherwise, it returns true. Neither |string| nor |addr| may be NULL.
+bool string_to_bdaddr(const char *string, bt_bdaddr_t *addr);
+
+// A hash function tailored for bdaddrs.
+hash_index_t hash_function_bdaddr(const void *key);
+
+#endif

+ 29 - 0
components/bt/bluedroid/btcore/include/device_features.h

@@ -0,0 +1,29 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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 _DEVICE_FEATURES_H_
+#define _DEVICE_FEATURES_H_
+
+#include <stdint.h>
+
+// Represents a page of device feature enabled/disabled bits returned
+// by the local controller. See the bluetooth spec for bit indexes.
+typedef struct {
+  uint8_t as_array[8];
+} bt_device_features_t;
+
+#endif /*_DEVICE_FEATURES_H_*/

+ 30 - 0
components/bt/bluedroid/btcore/include/event_mask.h

@@ -0,0 +1,30 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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 _EVENT_MASK_H_
+#define _EVENT_MASK_H_
+
+#include <stdint.h>
+
+// Represents a mask which can be used to tell the controller which
+// HCI events the stack wishes to be informed about. See the bluetooth
+// spec for more information on what each bit means.
+typedef struct {
+  uint8_t as_array[8];
+} bt_event_mask_t;
+
+#endif /*_EVENT_MASK_H_*/

+ 31 - 0
components/bt/bluedroid/btcore/include/version.h

@@ -0,0 +1,31 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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 _VERSION_H_
+#define _VERSION_H_
+
+#include <stdint.h>
+
+typedef struct {
+  uint8_t hci_version;
+  uint16_t hci_revision;
+  uint8_t lmp_version;
+  uint16_t manufacturer;
+  uint16_t lmp_subversion;
+} bt_version_t;
+
+#endif /*_VERSION_H_*/

+ 464 - 0
components/bt/bluedroid/btif/bta_dm_co.c

@@ -0,0 +1,464 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_dm_co.h"
+#include "bta_dm_ci.h"
+#if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE)
+#include "bt_utils.h"
+#if (BTM_OOB_INCLUDED == TRUE)
+#include "btif_dm.h"
+#endif
+#endif /* #if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE) */
+#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
+#include "bte_appl.h"
+
+tBTE_APPL_CFG bte_appl_cfg =
+{
+#if SMP_INCLUDED == TRUE
+    BTA_LE_AUTH_REQ_SC_MITM_BOND, // Authentication requirements
+#else
+    BTM_AUTH_SPGB_YES,            // Authentication requirements
+#endif
+    BTM_LOCAL_IO_CAPS_BLE,
+    BTM_BLE_INITIATOR_KEY_SIZE,
+    BTM_BLE_RESPONDER_KEY_SIZE,
+    BTM_BLE_MAX_KEY_SIZE
+};
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_dm_co_get_compress_memory
+**
+** Description      This callout function is executed by DM to get memory for compression
+
+** Parameters       id  -  BTA SYS ID
+**                  memory_p - memory return by callout
+**                  memory_size - memory size
+**
+** Returns          TRUE for success, FALSE for fail.
+**
+*******************************************************************************/
+BOOLEAN bta_dm_co_get_compress_memory(tBTA_SYS_ID id, UINT8 **memory_p, UINT32 *memory_size)
+{
+    UNUSED(id);
+    UNUSED(memory_p);
+    UNUSED(memory_size);
+    return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_co_io_req
+**
+** Description      This callout function is executed by DM to get IO capabilities
+**                  of the local device for the Simple Pairing process
+**
+** Parameters       bd_addr  - The peer device
+**                  *p_io_cap - The local Input/Output capabilities
+**                  *p_oob_data - TRUE, if OOB data is available for the peer device.
+**                  *p_auth_req - TRUE, if MITM protection is required.
+**
+** Returns          void.
+**
+*******************************************************************************/
+void bta_dm_co_io_req(BD_ADDR bd_addr, tBTA_IO_CAP *p_io_cap, tBTA_OOB_DATA *p_oob_data,
+                      tBTA_AUTH_REQ *p_auth_req, BOOLEAN is_orig)
+{
+    UNUSED(bd_addr);
+#if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE)
+#if (BTM_OOB_INCLUDED == TRUE)
+    btif_dm_set_oob_for_io_req(p_oob_data);
+#endif
+    btif_dm_proc_io_req(bd_addr, p_io_cap, p_oob_data, p_auth_req, is_orig);
+#else
+    LOG_ERROR("bta_dm_co_io_req: func not ported\n");
+#endif /* #if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE) */
+    BTIF_TRACE_DEBUG("bta_dm_co_io_req *p_oob_data = %d", *p_oob_data);
+    BTIF_TRACE_DEBUG("bta_dm_co_io_req *p_io_cap = %d", *p_io_cap);
+    BTIF_TRACE_DEBUG("bta_dm_co_io_req *p_auth_req = %d", *p_auth_req);
+    BTIF_TRACE_DEBUG("bta_dm_co_io_req is_orig = %d", is_orig);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_co_io_rsp
+**
+** Description      This callout function is executed by DM to report IO capabilities
+**                  of the peer device for the Simple Pairing process
+**
+** Parameters       bd_addr  - The peer device
+**                  io_cap - The remote Input/Output capabilities
+**                  oob_data - TRUE, if OOB data is available for the peer device.
+**                  auth_req - TRUE, if MITM protection is required.
+**
+** Returns          void.
+**
+*******************************************************************************/
+void bta_dm_co_io_rsp(BD_ADDR bd_addr, tBTA_IO_CAP io_cap,
+                      tBTA_OOB_DATA oob_data, tBTA_AUTH_REQ auth_req)
+{
+#if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE)
+    btif_dm_proc_io_rsp(bd_addr, io_cap, oob_data, auth_req);
+#else
+    LOG_ERROR("bta_dm_co_io_rsp: func not ported\n");
+#endif /* #if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE) */
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_co_lk_upgrade
+**
+** Description      This callout function is executed by DM to check if the
+**                  platform wants allow link key upgrade
+**
+** Parameters       bd_addr  - The peer device
+**                  *p_upgrade - TRUE, if link key upgrade is desired.
+**
+** Returns          void.
+**
+*******************************************************************************/
+void  bta_dm_co_lk_upgrade(BD_ADDR bd_addr, BOOLEAN *p_upgrade )
+{
+    UNUSED(bd_addr);
+    UNUSED(p_upgrade);
+}
+
+#if (BTM_OOB_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         bta_dm_co_loc_oob
+**
+** Description      This callout function is executed by DM to report the OOB
+**                  data of the local device for the Simple Pairing process
+**
+** Parameters       valid - TRUE, if the local OOB data is retrieved from LM
+**                  c     - Simple Pairing Hash C
+**                  r     - Simple Pairing Randomnizer R
+**
+** Returns          void.
+**
+*******************************************************************************/
+void bta_dm_co_loc_oob(BOOLEAN valid, BT_OCTET16 c, BT_OCTET16 r)
+{
+#if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE)
+    BTIF_TRACE_DEBUG("bta_dm_co_loc_oob, valid = %d", valid);
+#ifdef BTIF_DM_OOB_TEST
+    btif_dm_proc_loc_oob(valid, c, r);
+#endif
+#else
+    LOG_ERROR("bta_dm_co_loc_oob: func not ported\n");
+#endif /* #if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE) */
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_co_rmt_oob
+**
+** Description      This callout function is executed by DM to request the OOB
+**                  data for the remote device for the Simple Pairing process
+**                  Need to call bta_dm_ci_rmt_oob() in response
+**
+** Parameters       bd_addr  - The peer device
+**
+** Returns          void.
+**
+*******************************************************************************/
+void bta_dm_co_rmt_oob(BD_ADDR bd_addr)
+{
+    BT_OCTET16 p_c;
+    BT_OCTET16 p_r;
+    BOOLEAN result = FALSE;
+
+#ifdef BTIF_DM_OOB_TEST
+#if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE)
+    result = btif_dm_proc_rmt_oob(bd_addr, p_c, p_r);
+#else
+    LOG_ERROR("bta_dm_rmt_oob: func not ported\n");
+#endif /* #if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE) */
+#endif
+
+    BTIF_TRACE_DEBUG("bta_dm_co_rmt_oob: result=%d",result);
+    bta_dm_ci_rmt_oob(result, bd_addr, p_c, p_r);
+}
+
+#endif /* BTM_OOB_INCLUDED */
+
+
+// REMOVE FOR BLUEDROID ?
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE ) && (BTM_SCO_INCLUDED == TRUE)
+#if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         btui_sco_codec_callback
+**
+** Description      Callback for btui codec.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void btui_sco_codec_callback(UINT16 event, UINT16 sco_handle)
+{
+    bta_dm_sco_ci_data_ready(event, sco_handle);
+}
+/*******************************************************************************
+**
+** Function         bta_dm_sco_co_init
+**
+** Description      This function can be used by the phone to initialize audio
+**                  codec or for other initialization purposes before SCO connection
+**                  is opened.
+**
+**
+** Returns          tBTA_DM_SCO_ROUTE_TYPE: SCO routing configuration type.
+**
+*******************************************************************************/
+tBTA_DM_SCO_ROUTE_TYPE bta_dm_sco_co_init(UINT32 rx_bw, UINT32 tx_bw,
+                                          tBTA_CODEC_INFO * p_codec_type, UINT8 app_id)
+{
+    tBTM_SCO_ROUTE_TYPE route = BTA_DM_SCO_ROUTE_PCM;
+
+    BTIF_TRACE_DEBUG("bta_dm_sco_co_init");
+
+    /* set up SCO routing configuration if SCO over HCI app ID is used and run time
+        configuration is set to SCO over HCI */
+    /* HS invoke this call-out */
+    if (
+#if (BTA_HS_INCLUDED == TRUE ) && (BTA_HS_INCLUDED == TRUE)
+       (app_id == BTUI_DM_SCO_4_HS_APP_ID && btui_cfg.hs_sco_over_hci) ||
+#endif
+       /* AG invoke this call-out */
+       (app_id != BTUI_DM_SCO_4_HS_APP_ID && btui_cfg.ag_sco_over_hci ))
+    {
+        route = btui_cb.sco_hci = BTA_DM_SCO_ROUTE_HCI;
+    }
+    /* no codec is is used for the SCO data */
+    if (p_codec_type->codec_type == BTA_SCO_CODEC_PCM && route == BTA_DM_SCO_ROUTE_HCI)
+    {
+        /* initialize SCO codec */
+        if (!btui_sco_codec_init(rx_bw, tx_bw))
+        {
+            BTIF_TRACE_ERROR("codec initialization exception!");
+        }
+    }
+
+    return route;
+}
+
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_sco_co_open
+**
+** Description      This function is executed when a SCO connection is open.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_sco_co_open(UINT16 handle, UINT8 pkt_size, UINT16 event)
+{
+    tBTUI_SCO_CODEC_CFG cfg;
+
+    if (btui_cb.sco_hci)
+    {
+        BTIF_TRACE_DEBUG("bta_dm_sco_co_open handle:%d pkt_size:%d", handle, pkt_size);
+        /* use dedicated SCO buffer pool for SCO TX data */
+        cfg.pool_id = HCI_SCO_POOL_ID;
+        cfg.p_cback = btui_sco_codec_callback;
+        cfg.pkt_size = pkt_size;
+        cfg.cb_event = event;
+        /* open and start the codec */
+        btui_sco_codec_open(&cfg);
+        btui_sco_codec_start(handle);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_sco_co_close
+**
+** Description      This function is called when a SCO connection is closed
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_sco_co_close(void)
+{
+    if (btui_cb.sco_hci)
+    {
+        BTIF_TRACE_DEBUG("bta_dm_sco_co_close close codec");
+        /* close sco codec */
+        btui_sco_codec_close();
+
+        btui_cb.sco_hci = FALSE;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_sco_co_in_data
+**
+** Description      This function is called to send incoming SCO data to application.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_sco_co_in_data(BT_HDR  *p_buf)
+{
+    if (btui_cfg.sco_use_mic)
+        btui_sco_codec_inqdata (p_buf);
+    else
+        GKI_freebuf(p_buf);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_sco_co_out_data
+**
+** Description      This function is called to send SCO data over HCI.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_sco_co_out_data(BT_HDR  **p_buf)
+{
+    btui_sco_codec_readbuf(p_buf);
+}
+
+#endif /* #if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE) */
+#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE ) && (BTM_SCO_INCLUDED == TRUE)*/
+
+
+#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         bta_dm_co_le_io_key_req
+**
+** Description      This callout function is executed by DM to get BLE key information
+**                  before SMP pairing gets going.
+**
+** Parameters       bd_addr  - The peer device
+**                  *p_max_key_size - max key size local device supported.
+**                  *p_init_key - initiator keys.
+**                  *p_resp_key - responder keys.
+**
+** Returns          void.
+**
+*******************************************************************************/
+void bta_dm_co_le_io_key_req(BD_ADDR bd_addr, UINT8 *p_max_key_size,
+                             tBTA_LE_KEY_TYPE *p_init_key,
+                             tBTA_LE_KEY_TYPE  *p_resp_key )
+{
+    UNUSED(bd_addr);
+    BTIF_TRACE_ERROR("##################################");
+    BTIF_TRACE_ERROR("bta_dm_co_le_io_key_req: only setting max size to 16");
+    BTIF_TRACE_ERROR("##################################");
+    *p_max_key_size = 16;
+    *p_init_key = *p_resp_key =
+                  (BTA_LE_KEY_PENC|BTA_LE_KEY_PID|BTA_LE_KEY_PCSRK|BTA_LE_KEY_LENC|BTA_LE_KEY_LID|BTA_LE_KEY_LCSRK);
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_co_ble_local_key_reload
+**
+** Description      This callout function is to load the local BLE keys if available
+**                  on the device.
+**
+** Parameters       none
+**
+** Returns          void.
+**
+*******************************************************************************/
+void bta_dm_co_ble_load_local_keys(tBTA_DM_BLE_LOCAL_KEY_MASK *p_key_mask, BT_OCTET16 er,
+                                   tBTA_BLE_LOCAL_ID_KEYS *p_id_keys)
+{
+#if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE)
+    BTIF_TRACE_DEBUG("##################################");
+    BTIF_TRACE_DEBUG("bta_dm_co_ble_load_local_keys:  Load local keys if any are persisted");
+    BTIF_TRACE_DEBUG("##################################");
+    btif_dm_get_ble_local_keys( p_key_mask, er, p_id_keys);
+#else
+    LOG_ERROR("bta_dm_co_ble_load_local_keys: func not ported\n");
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_co_ble_io_req
+**
+** Description      This callout function is executed by DM to get BLE IO capabilities
+**                  before SMP pairing gets going.
+**
+** Parameters       bd_addr  - The peer device
+**                  *p_io_cap - The local Input/Output capabilities
+**                  *p_oob_data - TRUE, if OOB data is available for the peer device.
+**                  *p_auth_req -  Auth request setting (Bonding and MITM required or not)
+**                  *p_max_key_size - max key size local device supported.
+**                  *p_init_key - initiator keys.
+**                  *p_resp_key - responder keys.
+**
+** Returns          void.
+**
+*******************************************************************************/
+void bta_dm_co_ble_io_req(BD_ADDR bd_addr,  tBTA_IO_CAP *p_io_cap,
+                          tBTA_OOB_DATA *p_oob_data,
+                          tBTA_LE_AUTH_REQ *p_auth_req,
+                          UINT8 *p_max_key_size,
+                          tBTA_LE_KEY_TYPE *p_init_key,
+                          tBTA_LE_KEY_TYPE  *p_resp_key )
+{
+    UNUSED(bd_addr);
+    /* if OOB is not supported, this call-out function does not need to do anything
+     * otherwise, look for the OOB data associated with the address and set *p_oob_data accordingly
+     * If the answer can not be obtained right away,
+     * set *p_oob_data to BTA_OOB_UNKNOWN and call bta_dm_ci_io_req() when the answer is available */
+
+    *p_oob_data = FALSE;
+
+    /* *p_auth_req by default is FALSE for devices with NoInputNoOutput; TRUE for other devices. */
+
+    if (bte_appl_cfg.ble_auth_req)
+        *p_auth_req = bte_appl_cfg.ble_auth_req | (bte_appl_cfg.ble_auth_req & 0x04) | ((*p_auth_req) & 0x04);
+
+    if (bte_appl_cfg.ble_io_cap <=4)
+        *p_io_cap = bte_appl_cfg.ble_io_cap;
+
+    if (bte_appl_cfg.ble_init_key <= BTM_BLE_INITIATOR_KEY_SIZE)
+        *p_init_key = bte_appl_cfg.ble_init_key;
+
+    if (bte_appl_cfg.ble_resp_key <= BTM_BLE_RESPONDER_KEY_SIZE)
+        *p_resp_key = bte_appl_cfg.ble_resp_key;
+
+    if (bte_appl_cfg.ble_max_key_size > 7 && bte_appl_cfg.ble_max_key_size <= 16)
+        *p_max_key_size = bte_appl_cfg.ble_max_key_size;
+}
+
+
+#endif
+

+ 217 - 0
components/bt/bluedroid/btif/bta_gattc_co.c

@@ -0,0 +1,217 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+#ifdef  BT_SUPPORT_NVM
+#include <stdio.h>
+#include <unistd.h>
+#endif /* BT_SUPPORT_NVM */
+
+#include "gki.h"
+#include "bta_gattc_co.h"
+#include "bta_gattc_ci.h"
+// #include "btif_util.h"
+#include "btm_int.h"
+
+#if( defined BLE_INCLUDED ) && (BLE_INCLUDED == TRUE)
+#if( defined BTA_GATT_INCLUDED ) && (BTA_GATT_INCLUDED == TRUE)
+
+#define GATT_CACHE_PREFIX "/data/misc/bluedroid/gatt_cache_"
+
+#ifdef BT_SUPPORT_NVM
+static FILE* sCacheFD = 0;
+
+static void getFilename(char *buffer, BD_ADDR bda)
+{
+    sprintf(buffer, "%s%02x%02x%02x%02x%02x%02x", GATT_CACHE_PREFIX
+        , bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
+}
+
+static void cacheClose()
+{
+    if (sCacheFD != 0)
+    {
+        fclose(sCacheFD);
+        sCacheFD = 0;
+    }
+}
+
+static bool cacheOpen(BD_ADDR bda, bool to_save)
+{
+    char fname[255] = {0};
+    getFilename(fname, bda);
+
+    cacheClose();
+    sCacheFD = fopen(fname, to_save ? "w" : "r");
+
+    return (sCacheFD != 0);
+}
+
+static void cacheReset(BD_ADDR bda)
+{
+    char fname[255] = {0};
+    getFilename(fname, bda);
+    unlink(fname);
+}
+
+#endif /* BT_SUPPORT_NVM */
+/*****************************************************************************
+**  Function Declarations
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function         bta_gattc_co_cache_open
+**
+** Description      This callout function is executed by GATTC when a GATT server
+**                  cache is ready to be sent.
+**
+** Parameter        server_bda: server bd address of this cache belongs to
+**                  evt: call in event to be passed in when cache open is done.
+**                  conn_id: connection ID of this cache operation attach to.
+**                  to_save: open cache to save or to load.
+**
+** Returns          void.
+**
+*******************************************************************************/
+void bta_gattc_co_cache_open(BD_ADDR server_bda, UINT16 evt, UINT16 conn_id, BOOLEAN to_save)
+{
+#ifdef BT_SUPPORT_NVM
+    /* open NV cache and send call in */
+    tBTA_GATT_STATUS    status = BTA_GATT_OK;
+    if (!btm_sec_is_a_bonded_dev(server_bda) || !cacheOpen(server_bda, to_save))
+        status = BTA_GATT_ERROR;
+
+    BTIF_TRACE_DEBUG("%s() - status=%d", __FUNCTION__, status);
+    bta_gattc_ci_cache_open(server_bda, evt, status, conn_id);
+#else
+    bta_gattc_ci_cache_open(server_bda, evt, BTA_GATT_ERROR, conn_id);
+#endif /* BT_SUPPORT_NVM */
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_co_cache_load
+**
+** Description      This callout function is executed by GATT when server cache
+**                  is required to load.
+**
+** Parameter        server_bda: server bd address of this cache belongs to
+**                  evt: call in event to be passed in when cache save is done.
+**                  num_attr: number of attribute to be save.
+**                  attr_index: starting attribute index of the save operation.
+**                  conn_id: connection ID of this cache operation attach to.
+** Returns
+**
+*******************************************************************************/
+void bta_gattc_co_cache_load(BD_ADDR server_bda, UINT16 evt, UINT16 start_index, UINT16 conn_id)
+{
+    UINT16              num_attr = 0;
+    tBTA_GATTC_NV_ATTR  attr[BTA_GATTC_NV_LOAD_MAX];
+    tBTA_GATT_STATUS    status = BTA_GATT_ERROR;
+#ifdef BT_SUPPORT_NVM
+    if (sCacheFD && (0 == fseek(sCacheFD, start_index * sizeof(tBTA_GATTC_NV_ATTR), SEEK_SET)))
+    {
+        num_attr = fread(attr, sizeof(tBTA_GATTC_NV_ATTR), BTA_GATTC_NV_LOAD_MAX, sCacheFD);
+        status = (num_attr < BTA_GATTC_NV_LOAD_MAX ? BTA_GATT_OK : BTA_GATT_MORE);
+    }
+    BTIF_TRACE_DEBUG("%s() - sCacheFD=%p, start_index=%d, read=%d, status=%d",
+        __FUNCTION__, sCacheFD, start_index, num_attr, status);
+#endif /* BT_SUPPORT_NVM */
+
+    bta_gattc_ci_cache_load(server_bda, evt, num_attr, attr, status, conn_id);
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_co_cache_save
+**
+** Description      This callout function is executed by GATT when a server cache
+**                  is available to save.
+**
+** Parameter        server_bda: server bd address of this cache belongs to
+**                  evt: call in event to be passed in when cache save is done.
+**                  num_attr: number of attribute to be save.
+**                  p_attr: pointer to the list of attributes to save.
+**                  attr_index: starting attribute index of the save operation.
+**                  conn_id: connection ID of this cache operation attach to.
+** Returns
+**
+*******************************************************************************/
+void bta_gattc_co_cache_save (BD_ADDR server_bda, UINT16 evt, UINT16 num_attr,
+                              tBTA_GATTC_NV_ATTR *p_attr_list, UINT16 attr_index, UINT16 conn_id)
+{
+    tBTA_GATT_STATUS    status = BTA_GATT_OK;
+    UNUSED(attr_index);
+#ifdef BT_SUPPORT_NVM
+    if (sCacheFD != 0)
+    {
+        int num = fwrite(p_attr_list, sizeof(tBTA_GATTC_NV_ATTR), num_attr, sCacheFD);
+        BTIF_TRACE_DEBUG("%s() wrote %d", __FUNCTION__, num);
+    }
+#endif /* BT_SUPPORT_NVM */
+    bta_gattc_ci_cache_save(server_bda, evt, status, conn_id);
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_co_cache_close
+**
+** Description      This callout function is executed by GATTC when a GATT server
+**                  cache is written completely.
+**
+** Parameter        server_bda: server bd address of this cache belongs to
+**                  conn_id: connection ID of this cache operation attach to.
+**
+** Returns          void.
+**
+*******************************************************************************/
+void bta_gattc_co_cache_close(BD_ADDR server_bda, UINT16 conn_id)
+{
+    UNUSED(server_bda);
+    UNUSED(conn_id);
+#ifdef BT_SUPPORT_NVM
+    cacheClose();
+#endif /* BT_SUPPORT_NVM */
+    /* close NV when server cache is done saving or loading,
+       does not need to do anything for now on Insight */
+
+    BTIF_TRACE_DEBUG("%s()", __FUNCTION__);
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_co_cache_reset
+**
+** Description      This callout function is executed by GATTC to reset cache in
+**                  application
+**
+** Parameter        server_bda: server bd address of this cache belongs to
+**
+** Returns          void.
+**
+*******************************************************************************/
+void bta_gattc_co_cache_reset(BD_ADDR server_bda)
+{
+    BTIF_TRACE_DEBUG("%s()", __FUNCTION__);
+#ifdef BT_SUPPORT_NVM
+    cacheReset(server_bda);
+#endif /* BT_SUPPORT_NVM */
+}
+
+#endif /* #if( defined BLE_INCLUDED ) && (BLE_INCLUDED == TRUE) */
+#endif /* #if( defined BTA_GATT_INCLUDED ) && (BTA_GATT_INCLUDED == TRUE) */
+

+ 170 - 0
components/bt/bluedroid/btif/bta_gatts_co.c

@@ -0,0 +1,170 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#include "bta_api.h"
+
+#if( defined BLE_INCLUDED ) && (BLE_INCLUDED == TRUE)
+#if( defined BTA_GATT_INCLUDED ) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <stdlib.h>
+#include <string.h>
+#include "gki.h"
+#include "bta_gatts_co.h"
+// #include "btif_util.h"
+
+#if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE)
+/*****************************************************************************
+**  Local type definitions
+*****************************************************************************/
+
+#define BTIF_GATTS_MAX_SRV_CHG_CLT_SIZE 50
+
+typedef struct
+{
+    BOOLEAN             enable;
+    UINT8               num_clients;
+    tBTA_GATTS_SRV_CHG  srv_chg[BTIF_GATTS_MAX_SRV_CHG_CLT_SIZE];
+} __attribute__((packed)) btif_gatts_srv_chg_cb_t;
+
+/*****************************************************************************
+**  Static variables
+*****************************************************************************/
+
+static btif_gatts_srv_chg_cb_t btif_gatts_srv_chg_cb;
+
+/*****************************************************************************
+**  Static functions
+*****************************************************************************/
+
+static void btif_gatts_check_init(void)
+{
+    btif_gatts_srv_chg_cb_t *p_cb= &btif_gatts_srv_chg_cb;
+
+    if (!p_cb->enable)
+    {
+       memset(p_cb, 0, sizeof(btif_gatts_srv_chg_cb_t));
+       p_cb->enable = TRUE;
+    }
+}
+
+/*****************************************************************************
+**  Externally called functions
+*****************************************************************************/
+
+void btif_gatts_add_bonded_dev_from_nv(BD_ADDR bda)
+{
+    btif_gatts_srv_chg_cb_t *p_cb= &btif_gatts_srv_chg_cb;
+    BOOLEAN                 found = FALSE;
+    UINT8                   i;
+
+    btif_gatts_check_init();
+
+    for (i=0; i != p_cb->num_clients; ++i)
+    {
+        if (!memcmp(p_cb->srv_chg[i].bda,  bda, sizeof(BD_ADDR)))
+        {
+            found = TRUE;
+            break;
+        }
+    }
+
+    if (!found)
+    {
+        if (p_cb->num_clients < BTIF_GATTS_MAX_SRV_CHG_CLT_SIZE)
+        {
+            bdcpy(p_cb->srv_chg[p_cb->num_clients].bda, bda);
+            p_cb->srv_chg[p_cb->num_clients].srv_changed = FALSE;
+            p_cb->num_clients++;
+        }
+    }
+}
+
+#endif /* #if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE) */
+/*****************************************************************************
+**  Call-out functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function         bta_gatts_co_update_handle_range
+**
+** Description      This callout function is executed by GATTS when a GATT server
+**                  handle range ios to be added or removed.
+**
+** Parameter        is_add: true is to add a handle range; otherwise is to delete.
+**                  p_hndl_range: handle range.
+**
+** Returns          void.
+**
+*******************************************************************************/
+void bta_gatts_co_update_handle_range(BOOLEAN is_add, tBTA_GATTS_HNDL_RANGE *p_hndl_range)
+{
+    UNUSED(is_add);
+    UNUSED(p_hndl_range);
+}
+
+/*******************************************************************************
+**
+** Function         bta_gatts_co_srv_chg
+**
+** Description      This call-out is to read/write/remove service change related
+**                  informaiton. The request consists of the cmd and p_req and the
+**                  response is returned in p_rsp
+**
+** Parameter        cmd - request command
+**                  p_req - request paramters
+**                  p_rsp - response data for the request
+**
+** Returns          TRUE - if the request is processed successfully and
+**                         the response is returned in p_rsp.
+**                  FASLE - if the request can not be processed
+**
+*******************************************************************************/
+BOOLEAN bta_gatts_co_srv_chg(tBTA_GATTS_SRV_CHG_CMD cmd,
+                             tBTA_GATTS_SRV_CHG_REQ *p_req,
+                             tBTA_GATTS_SRV_CHG_RSP *p_rsp)
+{
+    UNUSED(cmd);
+    UNUSED(p_req);
+    UNUSED(p_rsp);
+
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gatts_co_load_handle_range
+**
+** Description      This callout function is executed by GATTS when a GATT server
+**                  handle range is requested to be loaded from NV.
+**
+** Parameter
+**
+** Returns          void.
+**
+*******************************************************************************/
+BOOLEAN bta_gatts_co_load_handle_range(UINT8 index,
+                                       tBTA_GATTS_HNDL_RANGE *p_handle_range)
+{
+    UNUSED(index);
+    UNUSED(p_handle_range);
+
+    return FALSE;
+}
+#endif
+#endif

+ 589 - 0
components/bt/bluedroid/device/controller.c

@@ -0,0 +1,589 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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.
+ *
+ ******************************************************************************/
+#include <stdbool.h>
+#include "bt_trace.h"
+#include "bdaddr.h"
+#include "bt_types.h"
+#include "controller.h"
+#include "event_mask.h"
+#include "hcimsgs.h"
+#include "hci_layer.h"
+#include "hci_packet_factory.h"
+#include "hci_packet_parser.h"
+#include "btm_ble_api.h"
+#include "version.h"
+
+//#include "bluedroid_test.h" /*FOr Test Case*/
+const bt_event_mask_t BLE_EVENT_MASK = { "\x00\x00\x00\x00\x00\x00\x06\x7f" };
+
+#if (BLE_INCLUDED)
+const bt_event_mask_t CLASSIC_EVENT_MASK = { HCI_DUMO_EVENT_MASK_EXT };
+#else
+const bt_event_mask_t CLASSIC_EVENT_MASK = { HCI_LISBON_EVENT_MASK_EXT };
+#endif
+
+// TODO(zachoverflow): factor out into common module
+const uint8_t SCO_HOST_BUFFER_SIZE = 0xff;
+
+#define HCI_SUPPORTED_COMMANDS_ARRAY_SIZE 64
+#define MAX_FEATURES_CLASSIC_PAGE_COUNT 3
+#define BLE_SUPPORTED_STATES_SIZE         8
+#define BLE_SUPPORTED_FEATURES_SIZE       8
+
+static const hci_t *hci;
+static const hci_packet_factory_t *packet_factory;
+static const hci_packet_parser_t *packet_parser;
+
+static bt_bdaddr_t address;
+static bt_version_t bt_version;
+
+static uint8_t supported_commands[HCI_SUPPORTED_COMMANDS_ARRAY_SIZE];
+static bt_device_features_t features_classic[MAX_FEATURES_CLASSIC_PAGE_COUNT];
+static uint8_t last_features_classic_page_index;
+
+static uint16_t acl_data_size_classic;
+static uint16_t acl_data_size_ble;
+static uint16_t acl_buffer_count_classic;
+static uint8_t acl_buffer_count_ble;
+
+static uint8_t ble_white_list_size;
+static uint8_t ble_resolving_list_max_size;
+static uint8_t ble_supported_states[BLE_SUPPORTED_STATES_SIZE];
+static bt_device_features_t features_ble;
+static uint16_t ble_suggested_default_data_length;
+
+static bool readable;
+static bool ble_supported;
+static bool simple_pairing_supported;
+static bool secure_connections_supported;
+
+devctl_reset_callback reset_cb;
+static uint8_t page_number = 0;
+static void devctl_hdl_cmd_complete(BT_HDR *response, void *context) {
+  BT_HDR *command = NULL;
+  command_opcode_t opcode;
+  uint8_t *stream = response->data + response->offset;
+
+  STREAM_SKIP_UINT16(stream);      //skip event_code and total length field
+  STREAM_SKIP_UINT8(stream);       //skip command_credits field
+  STREAM_TO_UINT16(opcode, stream);
+
+  switch (opcode) {
+  case HCI_RESET:
+    packet_parser->parse_generic_command_complete(response);
+    command = packet_factory->make_read_buffer_size();
+    break;
+  case HCI_READ_BUFFER_SIZE:
+    packet_parser->parse_read_buffer_size_response(
+        response, &acl_data_size_classic, &acl_buffer_count_classic);
+    command = packet_factory->make_host_buffer_size(
+        L2CAP_MTU_SIZE, SCO_HOST_BUFFER_SIZE, L2CAP_HOST_FC_ACL_BUFS, 10);
+    break;
+  case HCI_HOST_BUFFER_SIZE:
+    packet_parser->parse_generic_command_complete(response);
+    command = packet_factory->make_read_local_version_info();
+    break;
+  case HCI_READ_LOCAL_VERSION_INFO:
+    packet_parser->parse_read_local_version_info_response(response, &bt_version);
+    command = packet_factory->make_read_bd_addr();
+    break;
+  case HCI_READ_BD_ADDR:
+    packet_parser->parse_read_bd_addr_response(response, &address);
+    command = packet_factory->make_read_local_supported_commands();
+    break;
+  case HCI_READ_LOCAL_SUPPORTED_CMDS:
+    packet_parser->parse_read_local_supported_commands_response(
+        response, supported_commands, HCI_SUPPORTED_COMMANDS_ARRAY_SIZE);
+    page_number = 0;
+    command = packet_factory->make_read_local_extended_features(page_number);
+    break;
+  case HCI_READ_LOCAL_EXT_FEATURES:
+    if (response) {
+      packet_parser->parse_read_local_extended_features_response(
+	  response, &page_number,&last_features_classic_page_index,
+	  features_classic, MAX_FEATURES_CLASSIC_PAGE_COUNT);
+      response = NULL;
+      page_number++;
+    }
+    if (1 == page_number) {
+      simple_pairing_supported = HCI_SIMPLE_PAIRING_SUPPORTED(features_classic[0].as_array);
+      if (simple_pairing_supported) {
+	command = packet_factory->make_write_simple_pairing_mode(HCI_SP_MODE_ENABLED);
+	break;
+      }
+      // BLOCK_BEGIN
+#if (BLE_INCLUDED == TRUE)
+      if (HCI_LE_SPT_SUPPORTED(features_classic[0].as_array)) {
+	uint8_t simultaneous_le_host = HCI_SIMUL_LE_BREDR_SUPPORTED(features_classic[0].as_array) ? BTM_BLE_SIMULTANEOUS_HOST : 0;
+	command = packet_factory->make_ble_write_host_support(BTM_BLE_HOST_SUPPORT, simultaneous_le_host);
+	break;
+      }
+#endif
+    }
+
+    if (page_number <= last_features_classic_page_index &&
+	page_number < MAX_FEATURES_CLASSIC_PAGE_COUNT) {
+      command = packet_factory->make_read_local_extended_features(page_number);
+      break;
+    } else {
+#if (SC_MODE_INCLUDED == TRUE)
+      secure_connections_supported = HCI_SC_CTRLR_SUPPORTED(features_classic[2].as_array);
+      if (secure_connections_supported) {
+	command = packet_factory->make_write_secure_connections_host_support(HCI_SC_MODE_ENABLED);
+	break;
+      }
+#endif
+#if (BLE_INCLUDED == TRUE)
+      ble_supported = last_features_classic_page_index >= 1 && HCI_LE_HOST_SUPPORTED(features_classic[1].as_array);
+      if (ble_supported) {
+	// Request the ble white list size next
+	command = packet_factory->make_ble_read_white_list_size();
+	break;
+      }
+#endif
+      if (simple_pairing_supported) {
+	command = packet_factory->make_set_event_mask(&CLASSIC_EVENT_MASK);
+	break;
+      }
+    }
+    // BLOCK_END
+
+  case HCI_WRITE_SIMPLE_PAIRING_MODE:
+    if (response) {
+      packet_parser->parse_generic_command_complete(response);
+      response = NULL;
+    }
+      // BLOCK_BEGIN
+#if (BLE_INCLUDED == TRUE)
+     if (HCI_LE_SPT_SUPPORTED(features_classic[0].as_array)) {
+	uint8_t simultaneous_le_host = HCI_SIMUL_LE_BREDR_SUPPORTED(features_classic[0].as_array) ? BTM_BLE_SIMULTANEOUS_HOST : 0;
+	command = packet_factory->make_ble_write_host_support(BTM_BLE_HOST_SUPPORT, simultaneous_le_host);
+	break;
+      }
+#endif
+    if (page_number <= last_features_classic_page_index &&
+	page_number < MAX_FEATURES_CLASSIC_PAGE_COUNT) {
+      command = packet_factory->make_read_local_extended_features(page_number);
+      break;
+    } else {
+#if (SC_MODE_INCLUDED == TRUE)
+      secure_connections_supported = HCI_SC_CTRLR_SUPPORTED(features_classic[2].as_array);
+      if (secure_connections_supported) {
+	command = packet_factory->make_write_secure_connections_host_support(HCI_SC_MODE_ENABLED);
+	break;
+      }
+#endif
+#if (BLE_INCLUDED == TRUE)
+      ble_supported = last_features_classic_page_index >= 1 && HCI_LE_HOST_SUPPORTED(features_classic[1].as_array);
+      if (ble_supported) {
+	// Request the ble white list size next
+	command = packet_factory->make_ble_read_white_list_size();
+	break;
+      }
+#endif
+      if (simple_pairing_supported) {
+	command = packet_factory->make_set_event_mask(&CLASSIC_EVENT_MASK);
+	break;
+      }
+    }
+
+#if (SC_MODE_INCLUDED == TRUE)
+    case HCI_WRITE_SECURE_CONNS_SUPPORT:
+      if (response) {
+        packet_parser->parse_generic_command_complete(response);
+        response = NULL;
+      }
+#if (BLE_INCLUDED == TRUE)
+      ble_supported = last_features_classic_page_index >= 1 && HCI_LE_HOST_SUPPORTED(features_classic[1].as_array);
+      if (ble_supported) {
+	// Request the ble white list size next
+	command = packet_factory->make_ble_read_white_list_size();
+	break;
+      }
+#endif /* (BLE_INCLUDED == TRUE) */
+      if (simple_pairing_supported) {
+	command = packet_factory->make_set_event_mask(&CLASSIC_EVENT_MASK);
+	break;
+      }
+#endif /* (SC_MODE_INCLUDED == TRUE) */
+
+#if (BLE_INCLUDED == TRUE)
+  case HCI_WRITE_LE_HOST_SUPPORT:
+    if (response) {
+      packet_parser->parse_generic_command_complete(response);
+      response = NULL;
+    }
+    if (page_number <= last_features_classic_page_index &&
+	page_number < MAX_FEATURES_CLASSIC_PAGE_COUNT) {
+      command = packet_factory->make_read_local_extended_features(page_number);
+      break;
+    } else {
+#if (SC_MODE_INCLUDED == TRUE)
+      secure_connections_supported = HCI_SC_CTRLR_SUPPORTED(features_classic[2].as_array);
+      if (secure_connections_supported) {
+	command = packet_factory->make_write_secure_connections_host_support(HCI_SC_MODE_ENABLED);
+	break;
+      }
+#endif
+      ble_supported = last_features_classic_page_index >= 1 && HCI_LE_HOST_SUPPORTED(features_classic[1].as_array);
+      if (ble_supported) {
+	// Request the ble white list size next
+	command = packet_factory->make_ble_read_white_list_size();
+	break;
+      }
+      if (simple_pairing_supported) {
+	command = packet_factory->make_set_event_mask(&CLASSIC_EVENT_MASK);
+	break;
+      }
+    }
+  case HCI_BLE_READ_WHITE_LIST_SIZE:
+    if (response) {
+      packet_parser->parse_ble_read_white_list_size_response(response, &ble_white_list_size);
+      response = NULL;
+    }
+    if (ble_supported) {
+      // Request the ble buffer size next
+      command = packet_factory->make_ble_read_buffer_size();
+      break;
+    }
+  // Fall Through if no next command generated
+  case HCI_BLE_READ_BUFFER_SIZE:
+    if (response) {
+      packet_parser->parse_ble_read_buffer_size_response(
+          response, &acl_data_size_ble, &acl_buffer_count_ble);
+      response = NULL;
+    }
+    // Response of 0 indicates ble has the same buffer size as classic
+    if (acl_data_size_ble == 0)
+      acl_data_size_ble = acl_data_size_classic;
+    if (ble_supported) {
+      // Request the ble supported states next
+      command = packet_factory->make_ble_read_supported_states();
+      break;
+    }
+    // Fall Through if no next command generated
+  case HCI_BLE_READ_SUPPORTED_STATES:
+    if (response) {
+      packet_parser->parse_ble_read_supported_states_response(
+            response, ble_supported_states, sizeof(ble_supported_states));
+      response = NULL;
+    }
+
+    if (ble_supported) {
+      // Request the ble supported features next
+      command = packet_factory->make_ble_read_local_supported_features();
+      break;
+    }
+    // Fall Through if no next command generated
+  case HCI_BLE_READ_LOCAL_SPT_FEAT:
+    if (response) {
+      packet_parser->parse_ble_read_local_supported_features_response(
+            response, &features_ble);
+      response = NULL;
+    }
+
+    if (ble_supported &&
+	HCI_LE_ENHANCED_PRIVACY_SUPPORTED(features_ble.as_array)) {
+      command = packet_factory->make_ble_read_resolving_list_size();
+      break;
+    }
+  case HCI_BLE_READ_RESOLVING_LIST_SIZE:
+    if (response) {
+      packet_parser->parse_ble_read_resolving_list_size_response(
+            response, &ble_resolving_list_max_size);
+      response = NULL;
+    }
+
+    if (ble_supported &&
+	HCI_LE_DATA_LEN_EXT_SUPPORTED(features_ble.as_array)) {
+      command = packet_factory->make_ble_read_suggested_default_data_length();
+      break;
+    }
+  case HCI_BLE_READ_DEFAULT_DATA_LENGTH:
+    if (response) {
+      packet_parser->parse_ble_read_suggested_default_data_length_response(
+            response, &ble_suggested_default_data_length);
+      response = NULL;
+    }
+
+    if (ble_supported) {
+      // Set the ble event mask next
+      command = packet_factory->make_ble_set_event_mask(&BLE_EVENT_MASK);
+      break;
+    }
+  case HCI_BLE_SET_EVENT_MASK:
+    if (response) {
+      packet_parser->parse_generic_command_complete(response);
+      response = NULL;
+    }
+    if (simple_pairing_supported) {
+      command = packet_factory->make_set_event_mask(&CLASSIC_EVENT_MASK);
+      break;
+    }
+#endif
+  case HCI_SET_EVENT_MASK:
+    if (response) {
+      packet_parser->parse_generic_command_complete(response);
+      response = command = NULL;
+    }
+    //At this point, Reset Thread should be completed well.
+    readable = true;
+    page_number = 0;
+    if (reset_cb)
+      reset_cb();
+
+    break;
+  default:
+    LOG_ERROR("%s: No available opcode matched.", __func__);
+    break;
+  }
+
+  if (command)
+    hci->transmit_command(command, devctl_hdl_cmd_complete, NULL, NULL);
+}
+
+// Interface functions
+static void devctl_reset(devctl_reset_callback reset_callback) {
+  reset_cb = reset_callback;
+  BT_HDR *command = packet_factory->make_read_buffer_size();
+  //BT_HDR *command = packet_factory->make_reset();
+  LOG_ERROR("Device Control Send Device Read Buffer Size Command\n");
+  page_number = 0;
+  if (command)
+    hci->transmit_command(command, devctl_hdl_cmd_complete, NULL, NULL);
+}
+
+static void devctl_shutdown(void) {
+  reset_cb = NULL;
+  readable = false;
+}
+
+static bool get_is_ready(void) {
+  return readable;
+}
+
+static const bt_bdaddr_t *get_address(void) {
+  assert(readable);
+  return &address;
+}
+
+static const bt_version_t *get_bt_version(void) {
+  assert(readable);
+  return &bt_version;
+}
+
+// TODO(zachoverflow): hide inside, move decoder inside too
+static const bt_device_features_t *get_features_classic(int index) {
+  assert(readable);
+  assert(index < MAX_FEATURES_CLASSIC_PAGE_COUNT);
+  return &features_classic[index];
+}
+
+static uint8_t get_last_features_classic_index(void) {
+  assert(readable);
+  return last_features_classic_page_index;
+}
+
+static const bt_device_features_t *get_features_ble(void) {
+  assert(readable);
+  assert(ble_supported);
+  return &features_ble;
+}
+
+static const uint8_t *get_ble_supported_states(void) {
+  assert(readable);
+  assert(ble_supported);
+  return ble_supported_states;
+}
+
+static bool supports_simple_pairing(void) {
+  assert(readable);
+  return simple_pairing_supported;
+}
+
+static bool supports_secure_connections(void) {
+  assert(readable);
+  return secure_connections_supported;
+}
+
+static bool supports_simultaneous_le_bredr(void) {
+  assert(readable);
+  return HCI_SIMUL_LE_BREDR_SUPPORTED(features_classic[0].as_array);
+}
+
+static bool supports_reading_remote_extended_features(void) {
+  assert(readable);
+  return HCI_READ_REMOTE_EXT_FEATURES_SUPPORTED(supported_commands);
+}
+
+static bool supports_interlaced_inquiry_scan(void) {
+  assert(readable);
+  return HCI_LMP_INTERLACED_INQ_SCAN_SUPPORTED(features_classic[0].as_array);
+}
+
+static bool supports_rssi_with_inquiry_results(void) {
+  assert(readable);
+  return HCI_LMP_INQ_RSSI_SUPPORTED(features_classic[0].as_array);
+}
+
+static bool supports_extended_inquiry_response(void) {
+  assert(readable);
+  return HCI_EXT_INQ_RSP_SUPPORTED(features_classic[0].as_array);
+}
+
+static bool supports_master_slave_role_switch(void) {
+  assert(readable);
+  return HCI_SWITCH_SUPPORTED(features_classic[0].as_array);
+}
+
+static bool supports_ble(void) {
+  assert(readable);
+  return ble_supported;
+}
+
+static bool supports_ble_privacy(void) {
+  assert(readable);
+  assert(ble_supported);
+  return HCI_LE_ENHANCED_PRIVACY_SUPPORTED(features_ble.as_array);
+}
+
+static bool supports_ble_packet_extension(void) {
+  assert(readable);
+  assert(ble_supported);
+  return HCI_LE_DATA_LEN_EXT_SUPPORTED(features_ble.as_array);
+}
+
+static bool supports_ble_connection_parameters_request(void) {
+  assert(readable);
+  assert(ble_supported);
+  return HCI_LE_CONN_PARAM_REQ_SUPPORTED(features_ble.as_array);
+}
+
+static uint16_t get_acl_data_size_classic(void) {
+  assert(readable);
+  return acl_data_size_classic;
+}
+
+static uint16_t get_acl_data_size_ble(void) {
+  assert(readable);
+  assert(ble_supported);
+  return acl_data_size_ble;
+}
+
+static uint16_t get_acl_packet_size_classic(void) {
+  assert(readable);
+  return acl_data_size_classic + HCI_DATA_PREAMBLE_SIZE;
+}
+
+static uint16_t get_acl_packet_size_ble(void) {
+  assert(readable);
+  return acl_data_size_ble + HCI_DATA_PREAMBLE_SIZE;
+}
+
+static uint16_t get_ble_suggested_default_data_length(void) {
+  assert(readable);
+  assert(ble_supported);
+  return ble_suggested_default_data_length;
+}
+
+static uint16_t get_acl_buffer_count_classic(void) {
+  assert(readable);
+  return acl_buffer_count_classic;
+}
+
+static uint8_t get_acl_buffer_count_ble(void) {
+  assert(readable);
+  assert(ble_supported);
+  return acl_buffer_count_ble;
+}
+
+static uint8_t get_ble_white_list_size(void) {
+  assert(readable);
+  assert(ble_supported);
+  return ble_white_list_size;
+}
+
+static uint8_t get_ble_resolving_list_max_size(void) {
+  assert(readable);
+  assert(ble_supported);
+  return ble_resolving_list_max_size;
+}
+
+static void set_ble_resolving_list_max_size(int resolving_list_max_size) {
+  assert(readable);
+  assert(ble_supported);
+  ble_resolving_list_max_size = resolving_list_max_size;
+}
+
+static const controller_t interface = {
+  devctl_reset,
+  devctl_shutdown,
+  get_is_ready,
+
+  get_address,
+  get_bt_version,
+
+  get_features_classic,
+  get_last_features_classic_index,
+
+  get_features_ble,
+  get_ble_supported_states,
+
+  supports_simple_pairing,
+  supports_secure_connections,
+  supports_simultaneous_le_bredr,
+  supports_reading_remote_extended_features,
+  supports_interlaced_inquiry_scan,
+  supports_rssi_with_inquiry_results,
+  supports_extended_inquiry_response,
+  supports_master_slave_role_switch,
+
+  supports_ble,
+  supports_ble_packet_extension,
+  supports_ble_connection_parameters_request,
+  supports_ble_privacy,
+
+  get_acl_data_size_classic,
+  get_acl_data_size_ble,
+
+  get_acl_packet_size_classic,
+  get_acl_packet_size_ble,
+  get_ble_suggested_default_data_length,
+
+  get_acl_buffer_count_classic,
+  get_acl_buffer_count_ble,
+
+  get_ble_white_list_size,
+
+  get_ble_resolving_list_max_size,
+  set_ble_resolving_list_max_size
+};
+
+const controller_t *controller_get_interface() {
+  static bool loaded = false;
+  if (!loaded) {
+    loaded = true;
+
+    hci = hci_layer_get_interface();
+    packet_factory = hci_packet_factory_get_interface();
+    packet_parser = hci_packet_parser_get_interface();
+  }
+
+  return &interface;
+}
+

+ 87 - 0
components/bt/bluedroid/device/include/controller.h

@@ -0,0 +1,87 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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 _CONTROLLER_H_
+#define _CONTROLLER_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "bt_target.h"
+#include "bdaddr.h"
+#include "device_features.h"
+#include "hci_layer.h"
+#include "hci_packet_factory.h"
+#include "hci_packet_parser.h"
+
+typedef void (*devctl_reset_callback)(void);
+
+typedef struct controller_t {
+  void (*devctl_reset)(devctl_reset_callback reset_callback);
+  void (*devctl_shutdown)(void);
+  bool (*get_is_ready)(void);
+
+  const bt_bdaddr_t *(*get_address)(void);
+  const bt_version_t *(*get_bt_version)(void);
+
+  const bt_device_features_t *(*get_features_classic)(int index);
+
+  uint8_t (*get_last_features_classic_index)(void);
+
+  const bt_device_features_t *(*get_features_ble)(void);
+  const uint8_t *(*get_ble_supported_states)(void);
+
+  bool (*supports_simple_pairing)(void);
+  bool (*supports_secure_connections)(void);
+  bool (*supports_simultaneous_le_bredr)(void);
+  bool (*supports_reading_remote_extended_features)(void);
+  bool (*supports_interlaced_inquiry_scan)(void);
+  bool (*supports_rssi_with_inquiry_results)(void);
+  bool (*supports_extended_inquiry_response)(void);
+  bool (*supports_master_slave_role_switch)(void);
+
+  bool (*supports_ble)(void);
+  bool (*supports_ble_packet_extension)(void);
+  bool (*supports_ble_connection_parameters_request)(void);
+  bool (*supports_ble_privacy)(void);
+
+  // Get the cached acl data sizes for the controller.
+  uint16_t (*get_acl_data_size_classic)(void);
+  uint16_t (*get_acl_data_size_ble)(void);
+
+  // Get the cached acl packet sizes for the controller.
+  // This is a convenience function for the respective
+  // acl data size + size of the acl header.
+  uint16_t (*get_acl_packet_size_classic)(void);
+  uint16_t (*get_acl_packet_size_ble)(void);
+
+  uint16_t (*get_ble_default_data_packet_length)(void);
+
+  // Get the number of acl packets the controller can buffer.
+  uint16_t (*get_acl_buffer_count_classic)(void);
+  uint8_t (*get_acl_buffer_count_ble)(void);
+
+  uint8_t (*get_ble_white_list_size)(void);
+
+  uint8_t (*get_ble_resolving_list_max_size)(void);
+  void (*set_ble_resolving_list_max_size)(int resolving_list_max_size);
+} controller_t;
+
+const controller_t *controller_get_interface();
+
+#endif /*_CONTROLLER_H_*/

+ 44 - 0
components/bt/bluedroid/device/include/interop.h

@@ -0,0 +1,44 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2015 Google, Inc.
+ *
+ *  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 _INTEROP_H_
+#define _INTEROP_H_
+
+#include <stdbool.h>
+#include "bt_defs.h"
+
+typedef enum {
+  // Disable secure connections
+  // This is for pre BT 4.1/2 devices that do not handle secure mode
+  // very well.
+  INTEROP_DISABLE_LE_SECURE_CONNECTIONS,
+
+  // Some devices have proven problematic during the pairing process, often
+  // requiring multiple retries to complete pairing. To avoid degrading the user
+  // experience for those devices, automatically re-try pairing if page
+  // timeouts are received during pairing.
+  INTEROP_AUTO_RETRY_PAIRING
+} interop_feature_t;
+
+// Check if a given |addr| matches a known interoperability workaround as identified
+// by the |interop_feature_t| enum. This API is used for simple address based lookups
+// where more information is not available. No look-ups or random address resolution
+// is performed on |addr|.
+bool interop_match(const interop_feature_t feature, const bt_bdaddr_t *addr);
+
+#endif /*_INTEROP_H_*/

+ 50 - 0
components/bt/bluedroid/device/include/interop_database.h

@@ -0,0 +1,50 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2015 Google, Inc.
+ *
+ *  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 _INTEROP_DATABASE_H_
+#define _INTEROP_DATABASE_H_
+
+#include "interop.h"
+
+typedef struct {
+  bt_bdaddr_t addr;
+  uint8_t len;
+  interop_feature_t feature;
+} interop_entry_t;
+
+static const interop_entry_t interop_database[] = {
+  // Nexus Remote (Spike)
+  // Note: May affect other Asus brand devices
+  {{0x08, 0x62, 0x66,       0,0,0}, 3, INTEROP_DISABLE_LE_SECURE_CONNECTIONS},
+  {{0x38, 0x2c, 0x4a, 0xc9,   0,0}, 4, INTEROP_DISABLE_LE_SECURE_CONNECTIONS},
+  {{0x38, 0x2c, 0x4a, 0xe6,   0,0}, 4, INTEROP_DISABLE_LE_SECURE_CONNECTIONS},
+  {{0x54, 0xa0, 0x50, 0xd9,   0,0}, 4, INTEROP_DISABLE_LE_SECURE_CONNECTIONS},
+  {{0xac, 0x9e, 0x17,       0,0,0}, 3, INTEROP_DISABLE_LE_SECURE_CONNECTIONS},
+  {{0xf0, 0x79, 0x59,       0,0,0}, 3, INTEROP_DISABLE_LE_SECURE_CONNECTIONS},
+
+  // Motorola Key Link
+  {{0x1c, 0x96, 0x5a,       0,0,0}, 3, INTEROP_DISABLE_LE_SECURE_CONNECTIONS},
+
+  // Flic smart button
+  {{0x80, 0xe4, 0xda, 0x70,   0,0}, 4, INTEROP_DISABLE_LE_SECURE_CONNECTIONS},
+
+  // BMW car kits (Harman/Becker)
+  {{0x9c, 0xdf, 0x03,       0,0,0}, 3, INTEROP_AUTO_RETRY_PAIRING}
+};
+
+#endif /*_INTEROP_DATABASE_H_*/

+ 56 - 0
components/bt/bluedroid/device/interop.c

@@ -0,0 +1,56 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2015 Google, Inc.
+ *
+ *  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.
+ *
+ ******************************************************************************/
+/*
+#define LOG_TAG "bt_device_interop"
+*/
+#include <string.h> // For memcmp
+#include "bt_trace.h"
+#include "bdaddr.h"
+#include "interop.h"
+#include "interop_database.h"
+
+#define CASE_RETURN_STR(const) case const: return #const;
+
+static const char* interop_feature_string(const interop_feature_t feature) {
+  switch (feature) {
+    CASE_RETURN_STR(INTEROP_DISABLE_LE_SECURE_CONNECTIONS)
+    CASE_RETURN_STR(INTEROP_AUTO_RETRY_PAIRING)
+  }
+
+  return "UNKNOWN";
+}
+
+// Interface functions
+
+bool interop_match(const interop_feature_t feature, const bt_bdaddr_t *addr) {
+  assert(addr);
+
+  const size_t db_size = sizeof(interop_database) / sizeof(interop_entry_t);
+
+  for (size_t i = 0; i != db_size; ++i) {
+    if (feature == interop_database[i].feature &&
+        memcmp(addr, &interop_database[i].addr, interop_database[i].len) == 0) {
+      char bdstr[20] = {0};
+      LOG_WARN("%s() Device %s is a match for interop workaround %s", __func__,
+          bdaddr_to_string(addr, bdstr, sizeof(bdstr)), interop_feature_string(feature));
+      return true;
+    }
+  }
+
+  return false;
+}

+ 563 - 0
components/bt/bluedroid/gki/gki_buffer.c

@@ -0,0 +1,563 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 1999-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#include "bt_trace.h"
+#include "allocator.h"
+#include "gki_int.h"
+
+#define ALIGN_POOL(pl_size)  ( (((pl_size) + 3) / sizeof(UINT32)) * sizeof(UINT32))
+#define BUFFER_HDR_SIZE     (sizeof(BUFFER_HDR_T))                  /* Offset past header */
+#define BUFFER_PADDING_SIZE (sizeof(BUFFER_HDR_T) + sizeof(UINT32)) /* Header + Magic Number */
+#define MAGIC_NO            0xDDBADDBA
+
+#define BUF_STATUS_FREE     0
+#define BUF_STATUS_UNLINKED 1
+#define BUF_STATUS_QUEUED   2
+
+/*******************************************************************************
+**
+** Function         gki_init_free_queue
+**
+** Description      Internal function called at startup to initialize a free
+**                  queue. It is called once for each free queue.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void gki_init_free_queue (UINT8 id, UINT16 size, UINT16 total, void *p_mem)
+{
+    UINT16           i;
+    UINT16           act_size;
+    BUFFER_HDR_T    *hdr;
+    BUFFER_HDR_T    *hdr1 = NULL;
+    UINT32          *magic;
+    INT32            tempsize = size;
+    tGKI_COM_CB     *p_cb = &gki_cb.com;
+
+    /* Ensure an even number of longwords */
+    tempsize = (INT32)ALIGN_POOL(size);
+    act_size = (UINT16)(tempsize + BUFFER_PADDING_SIZE);
+
+    /* Remember pool start and end addresses */
+    if(p_mem)
+    {
+        p_cb->pool_start[id] = (UINT8 *)p_mem;
+        p_cb->pool_end[id]   = (UINT8 *)p_mem + (act_size * total);
+    }
+
+    p_cb->pool_size[id]  = act_size;
+
+    p_cb->freeq[id].size      = (UINT16) tempsize;
+    p_cb->freeq[id].total     = total;
+    p_cb->freeq[id].cur_cnt   = 0;
+    p_cb->freeq[id].max_cnt   = 0;
+
+    /* Initialize  index table */
+    if(p_mem)
+    {
+        hdr = (BUFFER_HDR_T *)p_mem;
+        p_cb->freeq[id]._p_first = hdr;
+        for (i = 0; i < total; i++)
+        {
+            hdr->q_id    = id;
+            hdr->status  = BUF_STATUS_FREE;
+            magic        = (UINT32 *)((UINT8 *)hdr + BUFFER_HDR_SIZE + tempsize);
+            *magic       = MAGIC_NO;
+            hdr1         = hdr;
+            hdr          = (BUFFER_HDR_T *)((UINT8 *)hdr + act_size);
+            hdr1->p_next = hdr;
+        }
+        hdr1->p_next = NULL;
+        p_cb->freeq[id]._p_last = hdr1;
+    }
+}
+
+void gki_buffer_cleanup(void)
+{
+    UINT8   i;
+    tGKI_COM_CB *p_cb = &gki_cb.com;
+
+    for (i=0; i < GKI_NUM_FIXED_BUF_POOLS; i++)
+    {
+        if ( 0 < p_cb->freeq[i].max_cnt )
+        {
+            osi_free(p_cb->pool_start[i]);
+
+            p_cb->freeq[i].cur_cnt   = 0;
+            p_cb->freeq[i].max_cnt   = 0;
+            p_cb->freeq[i]._p_first   = NULL;
+            p_cb->freeq[i]._p_last    = NULL;
+
+            p_cb->pool_start[i] = NULL;
+            p_cb->pool_end[i]   = NULL;
+            p_cb->pool_size[i]  = 0;
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         gki_buffer_init
+**
+** Description      Called once internally by GKI at startup to initialize all
+**                  buffers and free buffer pools.
+**
+** Returns          void
+**
+*******************************************************************************/
+void gki_buffer_init(void)
+{
+    static const struct {
+      uint16_t size;
+      uint16_t count;
+    } buffer_info[GKI_NUM_FIXED_BUF_POOLS] = {
+      { GKI_BUF0_SIZE, GKI_BUF0_MAX },
+      { GKI_BUF1_SIZE, GKI_BUF1_MAX },
+      { GKI_BUF2_SIZE, GKI_BUF2_MAX },
+      { GKI_BUF3_SIZE, GKI_BUF3_MAX },
+      { GKI_BUF4_SIZE, GKI_BUF4_MAX },
+      { GKI_BUF5_SIZE, GKI_BUF5_MAX },
+      { GKI_BUF6_SIZE, GKI_BUF6_MAX },
+      { GKI_BUF7_SIZE, GKI_BUF7_MAX },
+      { GKI_BUF8_SIZE, GKI_BUF8_MAX },
+      { GKI_BUF9_SIZE, GKI_BUF9_MAX },
+    };
+
+    tGKI_COM_CB *p_cb = &gki_cb.com;
+
+    for (int i = 0; i < GKI_NUM_TOTAL_BUF_POOLS; i++)
+    {
+        p_cb->pool_start[i] = NULL;
+        p_cb->pool_end[i]   = NULL;
+        p_cb->pool_size[i]  = 0;
+
+        p_cb->freeq[i]._p_first = 0;
+        p_cb->freeq[i]._p_last  = 0;
+        p_cb->freeq[i].size    = 0;
+        p_cb->freeq[i].total   = 0;
+        p_cb->freeq[i].cur_cnt = 0;
+        p_cb->freeq[i].max_cnt = 0;
+    }
+
+    /* Use default from target.h */
+    p_cb->pool_access_mask = GKI_DEF_BUFPOOL_PERM_MASK;
+
+    for (int i = 0; i < GKI_NUM_FIXED_BUF_POOLS; ++i) {
+      gki_init_free_queue(i, buffer_info[i].size, buffer_info[i].count, NULL);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         GKI_init_q
+**
+** Description      Called by an application to initialize a buffer queue.
+**
+** Returns          void
+**
+*******************************************************************************/
+void GKI_init_q (BUFFER_Q *p_q)
+{
+    p_q->_p_first = p_q->_p_last = NULL;
+    p_q->_count = 0;
+}
+
+/*******************************************************************************
+**
+** Function         GKI_getbuf
+**
+** Description      Called by an application to get a free buffer which
+**                  is of size greater or equal to the requested size.
+**
+**                  Note: This routine only takes buffers from public pools.
+**                        It will not use any buffers from pools
+**                        marked GKI_RESTRICTED_POOL.
+**
+** Parameters       size - (input) number of bytes needed.
+**
+** Returns          A pointer to the buffer, or NULL if none available
+**
+*******************************************************************************/
+void *GKI_getbuf (UINT16 size)
+{
+  BUFFER_HDR_T *header = osi_malloc(size + BUFFER_HDR_SIZE);
+  header->status  = BUF_STATUS_UNLINKED;
+  header->p_next  = NULL;
+  header->Type    = 0;
+  header->size = size;
+
+  return header + 1;
+}
+
+
+/*******************************************************************************
+**
+** Function         GKI_getpoolbuf
+**
+** Description      Called by an application to get a free buffer from
+**                  a specific buffer pool.
+**
+**                  Note: If there are no more buffers available from the pool,
+**                        the public buffers are searched for an available buffer.
+**
+** Parameters       pool_id - (input) pool ID to get a buffer out of.
+**
+** Returns          A pointer to the buffer, or NULL if none available
+**
+*******************************************************************************/
+void *GKI_getpoolbuf (UINT8 pool_id)
+{
+  return GKI_getbuf(gki_cb.com.pool_size[pool_id]);
+}
+
+/*******************************************************************************
+**
+** Function         GKI_freebuf
+**
+** Description      Called by an application to return a buffer to the free pool.
+**
+** Parameters       p_buf - (input) address of the beginning of a buffer.
+**
+** Returns          void
+**
+*******************************************************************************/
+void GKI_freebuf (void *p_buf)
+{
+  osi_free((BUFFER_HDR_T *)p_buf - 1);
+}
+
+
+/*******************************************************************************
+**
+** Function         GKI_get_buf_size
+**
+** Description      Called by an application to get the size of a buffer.
+**
+** Parameters       p_buf - (input) address of the beginning of a buffer.
+**
+** Returns          the size of the buffer
+**
+*******************************************************************************/
+UINT16 GKI_get_buf_size (void *p_buf)
+{
+  BUFFER_HDR_T *header = (BUFFER_HDR_T *)p_buf - 1;
+  return header->size;
+}
+
+/*******************************************************************************
+**
+** Function         GKI_enqueue
+**
+** Description      Enqueue a buffer at the tail of the queue
+**
+** Parameters:      p_q  -  (input) pointer to a queue.
+**                  p_buf - (input) address of the buffer to enqueue
+**
+** Returns          void
+**
+*******************************************************************************/
+void GKI_enqueue (BUFFER_Q *p_q, void *p_buf)
+{
+    BUFFER_HDR_T *p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
+    assert(p_hdr->status == BUF_STATUS_UNLINKED);
+
+    GKI_disable();
+
+    /* Since the queue is exposed (C vs C++), keep the pointers in exposed format */
+    if (p_q->_p_last)
+    {
+        BUFFER_HDR_T *_p_last_hdr = (BUFFER_HDR_T *)((UINT8 *)p_q->_p_last - BUFFER_HDR_SIZE);
+        _p_last_hdr->p_next = p_hdr;
+    }
+    else
+        p_q->_p_first = p_buf;
+
+    p_q->_p_last = p_buf;
+    p_q->_count++;
+
+    p_hdr->p_next = NULL;
+    p_hdr->status = BUF_STATUS_QUEUED;
+
+    GKI_enable();
+}
+
+/*******************************************************************************
+**
+** Function         GKI_dequeue
+**
+** Description      Dequeues a buffer from the head of a queue
+**
+** Parameters:      p_q  - (input) pointer to a queue.
+**
+** Returns          NULL if queue is empty, else buffer
+**
+*******************************************************************************/
+void *GKI_dequeue (BUFFER_Q *p_q)
+{
+    BUFFER_HDR_T    *p_hdr;
+
+    GKI_disable();
+
+    if (!p_q || !p_q->_count)
+    {
+        GKI_enable();
+        return (NULL);
+    }
+
+    p_hdr = (BUFFER_HDR_T *)((UINT8 *)p_q->_p_first - BUFFER_HDR_SIZE);
+
+    /* Keep buffers such that GKI header is invisible
+    */
+    if (p_hdr->p_next)
+        p_q->_p_first = ((UINT8 *)p_hdr->p_next + BUFFER_HDR_SIZE);
+    else
+    {
+        p_q->_p_first = NULL;
+        p_q->_p_last  = NULL;
+    }
+
+    p_q->_count--;
+
+    p_hdr->p_next = NULL;
+    p_hdr->status = BUF_STATUS_UNLINKED;
+
+    GKI_enable();
+
+    return ((UINT8 *)p_hdr + BUFFER_HDR_SIZE);
+}
+
+/*******************************************************************************
+**
+** Function         GKI_remove_from_queue
+**
+** Description      Dequeue a buffer from the middle of the queue
+**
+** Parameters:      p_q  - (input) pointer to a queue.
+**                  p_buf - (input) address of the buffer to enqueue
+**
+** Returns          NULL if queue is empty, else buffer
+**
+*******************************************************************************/
+void *GKI_remove_from_queue (BUFFER_Q *p_q, void *p_buf)
+{
+    BUFFER_HDR_T    *p_prev;
+    BUFFER_HDR_T    *p_buf_hdr;
+
+    GKI_disable();
+
+    if (p_buf == p_q->_p_first)
+    {
+        GKI_enable();
+        return (GKI_dequeue (p_q));
+    }
+
+    p_buf_hdr = (BUFFER_HDR_T *)((UINT8 *)p_buf - BUFFER_HDR_SIZE);
+    p_prev    = (BUFFER_HDR_T *)((UINT8 *)p_q->_p_first - BUFFER_HDR_SIZE);
+
+    for ( ; p_prev; p_prev = p_prev->p_next)
+    {
+        /* If the previous points to this one, move the pointers around */
+        if (p_prev->p_next == p_buf_hdr)
+        {
+            p_prev->p_next = p_buf_hdr->p_next;
+
+            /* If we are removing the last guy in the queue, update _p_last */
+            if (p_buf == p_q->_p_last)
+                p_q->_p_last = p_prev + 1;
+
+            /* One less in the queue */
+            p_q->_count--;
+
+            /* The buffer is now unlinked */
+            p_buf_hdr->p_next = NULL;
+            p_buf_hdr->status = BUF_STATUS_UNLINKED;
+
+            GKI_enable();
+            return (p_buf);
+        }
+    }
+
+    GKI_enable();
+    return (NULL);
+}
+
+/*******************************************************************************
+**
+** Function         GKI_getfirst
+**
+** Description      Return a pointer to the first buffer in a queue
+**
+** Parameters:      p_q  - (input) pointer to a queue.
+**
+** Returns          NULL if queue is empty, else buffer address
+**
+*******************************************************************************/
+void *GKI_getfirst (BUFFER_Q *p_q)
+{
+    return (p_q->_p_first);
+}
+
+/*******************************************************************************
+**
+** Function         GKI_getlast
+**
+** Description      Return a pointer to the last buffer in a queue
+**
+** Parameters:      p_q  - (input) pointer to a queue.
+**
+** Returns          NULL if queue is empty, else buffer address
+**
+*******************************************************************************/
+void *GKI_getlast (BUFFER_Q *p_q)
+{
+    return (p_q->_p_last);
+}
+
+/*******************************************************************************
+**
+** Function         GKI_getnext
+**
+** Description      Return a pointer to the next buffer in a queue
+**
+** Parameters:      p_buf  - (input) pointer to the buffer to find the next one from.
+**
+** Returns          NULL if no more buffers in the queue, else next buffer address
+**
+*******************************************************************************/
+void *GKI_getnext (void *p_buf)
+{
+    BUFFER_HDR_T    *p_hdr;
+
+    p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
+
+    if (p_hdr->p_next)
+        return ((UINT8 *)p_hdr->p_next + BUFFER_HDR_SIZE);
+    else
+        return (NULL);
+}
+
+/*******************************************************************************
+**
+** Function         GKI_queue_is_empty
+**
+** Description      Check the status of a queue.
+**
+** Parameters:      p_q  - (input) pointer to a queue.
+**
+** Returns          TRUE if queue is empty, else FALSE
+**
+*******************************************************************************/
+BOOLEAN GKI_queue_is_empty(BUFFER_Q *p_q)
+{
+    return ((BOOLEAN) (p_q->_count == 0));
+}
+
+UINT16 GKI_queue_length(BUFFER_Q *p_q)
+{
+    return p_q->_count;
+}
+
+/*******************************************************************************
+**
+** Function         GKI_poolcount
+**
+** Description      Called by an application to get the total number of buffers
+**                  in the specified buffer pool.
+**
+** Parameters       pool_id - (input) pool ID to get the free count of.
+**
+** Returns          the total number of buffers in the pool
+**
+*******************************************************************************/
+UINT16 GKI_poolcount (UINT8 pool_id)
+{
+    if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
+        return (0);
+
+    return (gki_cb.com.freeq[pool_id].total);
+}
+
+/*******************************************************************************
+**
+** Function         GKI_poolfreecount
+**
+** Description      Called by an application to get the number of free buffers
+**                  in the specified buffer pool.
+**
+** Parameters       pool_id - (input) pool ID to get the free count of.
+**
+** Returns          the number of free buffers in the pool
+**
+*******************************************************************************/
+UINT16 GKI_poolfreecount (UINT8 pool_id)
+{
+    FREE_QUEUE_T  *Q;
+
+    if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
+        return (0);
+
+    Q  = &gki_cb.com.freeq[pool_id];
+
+    return ((UINT16)(Q->total - Q->cur_cnt));
+}
+
+/*******************************************************************************
+**
+** Function         GKI_get_pool_bufsize
+**
+** Description      Called by an application to get the size of buffers in a pool
+**
+** Parameters       Pool ID.
+**
+** Returns          the size of buffers in the pool
+**
+*******************************************************************************/
+UINT16 GKI_get_pool_bufsize (UINT8 pool_id)
+{
+    if (pool_id < GKI_NUM_TOTAL_BUF_POOLS)
+        return (gki_cb.com.freeq[pool_id].size);
+
+    return (0);
+}
+
+/*******************************************************************************
+**
+** Function         GKI_poolutilization
+**
+** Description      Called by an application to get the buffer utilization
+**                  in the specified buffer pool.
+**
+** Parameters       pool_id - (input) pool ID to get the free count of.
+**
+** Returns          % of buffers used from 0 to 100
+**
+*******************************************************************************/
+UINT16 GKI_poolutilization (UINT8 pool_id)
+{
+    FREE_QUEUE_T  *Q;
+
+    if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
+        return (100);
+
+    Q  = &gki_cb.com.freeq[pool_id];
+
+    if (Q->total == 0)
+        return (100);
+
+    return ((Q->cur_cnt * 100) / Q->total);
+}

+ 62 - 0
components/bt/bluedroid/gki/gki_ulinux.c

@@ -0,0 +1,62 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+#include <string.h>
+#include "bt_trace.h"
+#include "gki_int.h"
+#include "osi.h"
+#include "osi_arch.h"
+#include "alarm.h"
+#include "bt_defs.h"
+
+tGKI_CB gki_cb;
+
+int gki_init(void) {
+  memset(&gki_cb, 0, sizeof(gki_cb));
+
+  //pthread_mutexattr_t attr;
+  //pthread_mutexattr_init(&attr);
+  //pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
+  pthread_mutex_init(&gki_cb.lock, NULL);//&attr);
+
+  gki_buffer_init();
+  return 0;
+}
+
+void gki_clean_up(void) {
+  gki_buffer_cleanup();
+
+  pthread_mutex_destroy(&gki_cb.lock);
+}
+
+UINT32 GKI_get_os_tick_count(void) {
+  return osi_alarm_now();
+}
+
+// Sleep the calling thread unconditionally for |timeout_ms| milliseconds.
+void GKI_delay(UINT32 timeout_ms) {
+  osi_delay_ms(timeout_ms);
+  /*TODO:*/
+}
+
+void GKI_enable(void) {
+  pthread_mutex_unlock(&gki_cb.lock);
+}
+
+void GKI_disable(void) {
+  pthread_mutex_lock(&gki_cb.lock);
+}

+ 101 - 0
components/bt/bluedroid/gki/include/gki.h

@@ -0,0 +1,101 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 1999-2012 Broadcom Corporation
+ *
+ *  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 _GKI_H_
+#define _GKI_H_
+
+#include "bt_target.h"
+#include "bt_types.h"
+
+//static const char GKI_MODULE[] = "gki_module";
+
+/* Timer list entry callback type
+*/
+typedef void (TIMER_CBACK)(void *p_tle);
+#ifndef TIMER_PARAM_TYPE
+#define TIMER_PARAM_TYPE    UINT32
+#endif
+/* Define a timer list entry
+*/
+typedef struct _tle
+{
+    struct _tle  *p_next;
+    struct _tle  *p_prev;
+    TIMER_CBACK  *p_cback;
+    INT32         ticks;
+    INT32         ticks_initial;
+    TIMER_PARAM_TYPE   param;
+    TIMER_PARAM_TYPE   data;
+    UINT16        event;
+    UINT8         in_use;
+} TIMER_LIST_ENT;
+
+/***********************************************************************
+** This queue is a general purpose buffer queue, for application use.
+*/
+typedef struct
+{
+    void    *_p_first;
+    void    *_p_last;
+    UINT16   _count;
+} BUFFER_Q;
+
+#define GKI_PUBLIC_POOL         0       /* General pool accessible to GKI_getbuf() */
+#define GKI_RESTRICTED_POOL     1       /* Inaccessible pool to GKI_getbuf() */
+
+/***********************************************************************
+** Function prototypes
+*/
+
+/* To get and release buffers, change owner and get size
+*/
+void    GKI_freebuf (void *);
+void   *GKI_getbuf (UINT16);
+UINT16  GKI_get_buf_size (void *);
+void   *GKI_getpoolbuf (UINT8);
+UINT16  GKI_poolcount (UINT8);
+UINT16  GKI_poolfreecount (UINT8);
+UINT16  GKI_poolutilization (UINT8);
+
+
+/* User buffer queue management
+*/
+void   *GKI_dequeue  (BUFFER_Q *);
+void    GKI_enqueue (BUFFER_Q *, void *);
+void   *GKI_getfirst (BUFFER_Q *);
+void   *GKI_getlast (BUFFER_Q *);
+void   *GKI_getnext (void *);
+void    GKI_init_q (BUFFER_Q *);
+UINT16  GKI_queue_length(BUFFER_Q *);
+BOOLEAN GKI_queue_is_empty(BUFFER_Q *);
+void   *GKI_remove_from_queue (BUFFER_Q *, void *);
+UINT16  GKI_get_pool_bufsize (UINT8);
+
+/* Timer management
+*/
+void    GKI_delay(UINT32);
+
+/* Disable Interrupts, Enable Interrupts
+*/
+void    GKI_enable(void);
+void    GKI_disable(void);
+
+/* os timer operation */
+UINT32 GKI_get_os_tick_count(void);
+
+#endif /*_GKI_H_*/

+ 68 - 0
components/bt/bluedroid/gki/include/gki_common.h

@@ -0,0 +1,68 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 1999-2012 Broadcom Corporation
+ *
+ *  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 _GKI_COMMON_H_
+#define _GKI_COMMON_H_
+
+#include "gki.h"
+
+typedef struct _buffer_hdr
+{
+	struct _buffer_hdr *p_next;   /* next buffer in the queue */
+	UINT8   q_id;                 /* id of the queue */
+	UINT8   status;               /* FREE, UNLINKED or QUEUED */
+	UINT8   Type;
+        UINT16  size;
+} BUFFER_HDR_T;
+
+typedef struct _free_queue
+{
+	BUFFER_HDR_T *_p_first;      /* first buffer in the queue */
+	BUFFER_HDR_T *_p_last;       /* last buffer in the queue */
+	UINT16		 size;             /* size of the buffers in the pool */
+	UINT16		 total;            /* toatal number of buffers */
+	UINT16		 cur_cnt;          /* number of  buffers currently allocated */
+	UINT16		 max_cnt;          /* maximum number of buffers allocated at any time */
+} FREE_QUEUE_T;
+
+/* Put all GKI variables into one control block
+*/
+typedef struct
+{
+    /* Define the buffer pool management variables
+    */
+    FREE_QUEUE_T    freeq[GKI_NUM_TOTAL_BUF_POOLS];
+
+    UINT16   pool_buf_size[GKI_NUM_TOTAL_BUF_POOLS];
+
+    /* Define the buffer pool start addresses
+    */
+    UINT8   *pool_start[GKI_NUM_TOTAL_BUF_POOLS];   /* array of pointers to the start of each buffer pool */
+    UINT8   *pool_end[GKI_NUM_TOTAL_BUF_POOLS];     /* array of pointers to the end of each buffer pool */
+    UINT16   pool_size[GKI_NUM_TOTAL_BUF_POOLS];    /* actual size of the buffers in a pool */
+
+    /* Define the buffer pool access control variables */
+    UINT16      pool_access_mask;                   /* Bits are set if the corresponding buffer pool is a restricted pool */
+} tGKI_COM_CB;
+
+/* Internal GKI function prototypes
+*/
+void      gki_buffer_init(void);
+void      gki_buffer_cleanup(void);
+
+#endif /*_GKI_COMMON_H_*/

+ 35 - 0
components/bt/bluedroid/gki/include/gki_int.h

@@ -0,0 +1,35 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 1999-2012 Broadcom Corporation
+ *
+ *  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 _GKI_INT_H_
+#define _GKI_INT_H_
+
+//#include <pthread.h>
+#include "bt_defs.h"
+
+#include "gki_common.h"
+
+typedef struct
+{
+    pthread_mutex_t lock;
+    tGKI_COM_CB com;
+} tGKI_CB;
+
+extern tGKI_CB  gki_cb;
+
+#endif /*_GKI_INT_H_*/

+ 33 - 0
components/bt/bluedroid/hci/buffer_allocator.c

@@ -0,0 +1,33 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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.
+ *
+ ******************************************************************************/
+#include "buffer_allocator.h"
+#include "gki.h"
+
+// TODO(zachoverflow): move the assertion into GKI_getbuf in the future
+static void *buffer_alloc(size_t size) {
+  return GKI_getbuf((uint16_t)size);
+}
+
+static const allocator_t interface = {
+  buffer_alloc,
+  GKI_freebuf
+};
+
+const allocator_t *buffer_allocator_get_interface() {
+  return &interface;
+}

+ 288 - 0
components/bt/bluedroid/hci/hci_hal_h4.c

@@ -0,0 +1,288 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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.
+ *
+ ******************************************************************************/
+#include <string.h>
+#include "bt_defs.h"
+#include "bt_trace.h"
+#include "bt_types.h"
+#include "buffer_allocator.h"
+#include "fixed_queue.h"
+#include "hci_hal.h"
+#include "hci_internals.h"
+#include "hci_layer.h"
+
+#include "thread.h"
+
+#define HCI_HAL_SERIAL_BUFFER_SIZE 1026
+#define HCI_BLE_EVENT 0x3e
+#define PACKET_TYPE_TO_INBOUND_INDEX(type) ((type) - 2)
+#define PACKET_TYPE_TO_INDEX(type) ((type) - 1)
+
+
+static const uint8_t preamble_sizes[] = {
+  HCI_COMMAND_PREAMBLE_SIZE,
+  HCI_ACL_PREAMBLE_SIZE,
+  HCI_SCO_PREAMBLE_SIZE,
+  HCI_EVENT_PREAMBLE_SIZE
+};
+
+static const uint16_t outbound_event_types[] = {
+  MSG_HC_TO_STACK_HCI_ERR,
+  MSG_HC_TO_STACK_HCI_ACL,
+  MSG_HC_TO_STACK_HCI_SCO,
+  MSG_HC_TO_STACK_HCI_EVT
+};
+
+typedef struct {
+  const allocator_t *allocator;
+  size_t buffer_size;
+  fixed_queue_t *rx_q;
+} hci_hal_env_t;
+
+
+static hci_hal_env_t hci_hal_env;
+static const hci_hal_t interface;
+static const hci_hal_callbacks_t *callbacks;
+static const vhci_host_callback_t vhci_host_cb;
+
+static xTaskHandle xHciH4TaskHandle;
+static xQueueHandle xHciH4Queue;
+
+static void host_send_pkt_available_cb(void);
+static int host_recv_pkt_cb(uint8_t *data, uint16_t len);
+
+static void hci_hal_h4_rx_handler(void *arg);
+static void event_uart_has_bytes(fixed_queue_t *queue);
+
+
+static void hci_hal_env_init(
+    size_t buffer_size,
+    size_t max_buffer_count) {
+  assert(buffer_size > 0);
+  assert(max_buffer_count > 0);
+
+  hci_hal_env.allocator = buffer_allocator_get_interface();
+  hci_hal_env.buffer_size = buffer_size;
+
+  hci_hal_env.rx_q = fixed_queue_new(max_buffer_count);
+  if (hci_hal_env.rx_q)
+    fixed_queue_register_dequeue(hci_hal_env.rx_q, event_uart_has_bytes);
+  else
+    LOG_ERROR("%s unable to create rx queue.", __func__);
+
+  return;
+}
+
+static void hci_hal_env_deinit(void) {
+  fixed_queue_free(hci_hal_env.rx_q, hci_hal_env.allocator->free);
+}
+
+static bool hal_open(const hci_hal_callbacks_t *upper_callbacks) {
+  assert(upper_callbacks != NULL);
+  callbacks = upper_callbacks;
+
+  hci_hal_env_init(HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX);
+  
+  xHciH4Queue = xQueueCreate(3, sizeof(void *));
+  xTaskCreate(hci_hal_h4_rx_handler, "HciH4T", 4096+2048, NULL, configMAX_PRIORITIES - 3, &xHciH4TaskHandle);
+
+  //register vhci host cb
+  API_vhci_host_register_callback(&vhci_host_cb);
+
+
+  return true;
+
+error:
+  interface.close();
+  return false;
+}
+
+static void hal_close() {
+  hci_hal_env_deinit();
+ 
+  /* delete task and queue */ 
+  vTaskDelete(xHciH4TaskHandle);
+  vQueueDelete(xHciH4Queue);
+}
+
+/**
+ * Function: transmit_data -TX data to low-layer
+ * It is ported from Bluedroid source code, so it is not
+ * needed to use write() to send data.
+ * TODO: Just use firmware API to send data.
+ */
+static uint16_t transmit_data(serial_data_type_t type,
+                              uint8_t *data, uint16_t length)
+{
+  uint8_t previous_byte;
+
+  assert(data != NULL);
+  assert(length > 0);
+
+  if (type < DATA_TYPE_COMMAND || type > DATA_TYPE_SCO) {
+    LOG_ERROR("%s invalid data type: %d", __func__, type);
+    return 0;
+  }
+
+  // Write the signal byte right before the data
+  --data;
+  previous_byte = *data;
+  *(data) = type;
+  ++length;
+
+  BTTRC_DUMP_BUFFER("Transmit Pkt", data, length);
+
+  // TX Data to target
+  API_vhci_host_send_packet(data, length);
+
+  // Be nice and restore the old value of that byte
+  *(data) = previous_byte;
+
+  return length - 1;
+}
+
+// Internal functions
+static void hci_hal_h4_rx_handler(void *arg) {
+    TaskEvt_t *e;
+
+    for (;;) {
+        if (pdTRUE == xQueueReceive(xHciH4Queue, &e, (portTickType)portMAX_DELAY)) {
+            if (e->sig == 0xff) {  
+                fixed_queue_process(hci_hal_env.rx_q);
+            }
+            osi_free(e);
+        }
+    }
+}
+
+void hci_hal_h4_task_post(void)
+{
+    TaskEvt_t *evt = (TaskEvt_t *)osi_malloc(sizeof(TaskEvt_t));
+    if (evt == NULL)
+        return;
+
+    evt->sig = 0xff;
+    evt->par = 0;
+
+    if (xQueueSend(xHciH4Queue, &evt, 10/portTICK_RATE_MS) != pdTRUE) {
+            ets_printf("xHciH4Queue failed\n");
+    }
+}
+
+static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet) {
+  uint8_t type, hdr_size;
+  uint16_t length;
+  uint8_t *stream = packet->data + packet->offset;
+
+  if (!packet)
+    return;
+  STREAM_TO_UINT8(type, stream);
+  packet->offset++;
+  packet->len--;
+  if (type == HCI_BLE_EVENT) {
+    uint8_t len;
+    STREAM_TO_UINT8(len, stream);
+    LOG_ERROR("Workround stream corrupted during LE SCAN: pkt_len=%d ble_event_len=%d",
+              packet->len, len);
+    hci_hal_env.allocator->free(packet);
+    return;
+  }
+  if (type < DATA_TYPE_ACL || type > DATA_TYPE_EVENT) {
+    LOG_ERROR("%d Unknown HCI message type. Dropping this byte 0x%x,"
+              " min %x, max %x", __func__, type,
+              DATA_TYPE_ACL, DATA_TYPE_EVENT);
+    hci_hal_env.allocator->free(packet);
+    return;
+  }
+  hdr_size = preamble_sizes[type - 1];
+  if (packet->len < hdr_size) {
+    LOG_ERROR("Wrong packet length type=%s pkt_len=%d hdr_len=%d",
+              type, packet->len, hdr_size);
+    hci_hal_env.allocator->free(packet);
+    return;
+  }
+  if (type == DATA_TYPE_ACL) {
+    stream += hdr_size - 2;
+    STREAM_TO_UINT16(length, stream);
+  } else {
+    stream += hdr_size - 1;
+    STREAM_TO_UINT8(length, stream);
+  }
+
+  if ((length + hdr_size) != packet->len) {
+    LOG_ERROR("Wrong packet length type=%d hdr_len=%d pd_len=%d "
+              "pkt_len=%d", type, hdr_size, length, packet->len);
+    hci_hal_env.allocator->free(packet);
+    return;
+  }
+
+  packet->event = outbound_event_types[PACKET_TYPE_TO_INDEX(type)];
+  callbacks->packet_ready(packet);
+}
+
+static void event_uart_has_bytes(fixed_queue_t *queue) {
+  BT_HDR *packet;
+  while (!fixed_queue_is_empty(queue)) {
+    packet = fixed_queue_dequeue(queue);
+    hci_hal_h4_hdl_rx_packet(packet);
+  }
+}
+
+static void host_send_pkt_available_cb(void) {
+  //Controller rx cache buffer is ready for receiving new host packet
+  //Just Call Host main thread task to process pending packets.
+  hci_host_task_post();
+}
+
+static int host_recv_pkt_cb(uint8_t *data, uint16_t len) {
+  //Target has packet to host, malloc new buffer for packet
+  BT_HDR *pkt;
+  size_t pkt_size;
+
+  pkt_size = BT_HDR_SIZE + len;
+  pkt = (BT_HDR *)hci_hal_env.allocator->alloc(pkt_size);
+  if (!pkt) {
+    LOG_ERROR("%s couldn't aquire memory for inbound data buffer.", __func__);
+    return -1;
+  }
+  pkt->offset = 0;
+  pkt->len = len;
+  pkt->layer_specific = 0;
+  memcpy(pkt->data, data, len);
+  fixed_queue_enqueue(hci_hal_env.rx_q, pkt);
+  hci_hal_h4_task_post();
+
+  BTTRC_DUMP_BUFFER("Recv Pkt", pkt->data, len);
+
+  return 0;
+}
+
+static const vhci_host_callback_t vhci_host_cb = {
+  .notify_host_send_available = host_send_pkt_available_cb,
+  .notify_host_recv = host_recv_pkt_cb,
+};
+
+static const hci_hal_t interface = {
+  hal_open,
+  hal_close,
+  transmit_data,
+};
+
+const hci_hal_t *hci_hal_h4_get_interface() {
+  return &interface;
+}
+

+ 574 - 0
components/bt/bluedroid/hci/hci_layer.c

@@ -0,0 +1,574 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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.
+ *
+ ******************************************************************************/
+#include <string.h>
+
+#include "bt_defs.h"
+#include "bt_trace.h"
+#include "hcidefs.h"
+#include "hcimsgs.h"
+#include "bt_vendor_lib.h"
+#include "hci_internals.h"
+#include "hci_hal.h"
+#include "hci_layer.h"
+#include "allocator.h"
+#include "packet_fragmenter.h"
+#include "buffer_allocator.h"
+#include "list.h"
+#include "alarm.h"
+#include "thread.h"
+
+typedef struct {
+  uint16_t opcode;
+  command_complete_cb complete_callback;
+  command_status_cb status_callback;
+  void *context;
+  uint32_t sent_time;
+  BT_HDR *command;
+} waiting_command_t;
+
+typedef struct {
+  bool timer_is_set;
+ osi_alarm_t *command_response_timer;
+  list_t *commands_pending_response;
+  pthread_mutex_t commands_pending_response_lock;
+} command_waiting_response_t;
+
+typedef struct {
+  int command_credits;
+  fixed_queue_t *command_queue;
+  fixed_queue_t *packet_queue;
+
+  // The hand-off point for data going to a higher layer, set by the higher layer
+  fixed_queue_t *upwards_data_queue;
+
+  command_waiting_response_t cmd_waiting_q;
+
+/*
+  non_repeating_timer_t *command_response_timer;
+  list_t *commands_pending_response;
+  pthread_mutex_t commands_pending_response_lock;
+*/
+} hci_host_env_t;
+
+// Using a define here, because it can be stringified for the property lookup
+static const uint32_t COMMAND_PENDING_TIMEOUT = 8000;
+
+// Our interface
+static bool interface_created;
+static hci_t interface;
+static hci_host_env_t hci_host_env;
+
+static xTaskHandle  xHciHostTaskHandle;
+static xQueueHandle xHciHostQueue;
+
+static bool hci_host_startup_flag;
+
+// Modules we import and callbacks we export
+static const allocator_t *buffer_allocator;
+static const hci_hal_t *hal;
+static const hci_hal_callbacks_t hal_callbacks;
+static const packet_fragmenter_t *packet_fragmenter;
+static const packet_fragmenter_callbacks_t packet_fragmenter_callbacks;
+
+static int hci_layer_init_env(void);
+static void hci_layer_deinit_env(void);
+static void hci_host_thread_handler(void *arg);
+static int hci_send_async_command(bt_vendor_opcode_t opcode, void *param);
+static void event_finish_startup(void *context);
+static void firmware_config_callback(bool success);
+static void event_postload(void);
+static void sco_config_callback(bool success);
+static void event_command_ready(fixed_queue_t *queue);
+static void event_packet_ready(fixed_queue_t *queue);
+static void restart_comamnd_waiting_response_timer(
+            command_waiting_response_t *cmd_wait_q,
+            bool tigger_by_sending_command);
+static void command_timed_out(void *context);
+static void hal_says_packet_ready(BT_HDR *packet);
+static bool filter_incoming_event(BT_HDR *packet);
+static serial_data_type_t event_to_data_type(uint16_t event);
+static waiting_command_t *get_waiting_command(command_opcode_t opcode);
+static void dispatch_reassembled(BT_HDR *packet);
+
+// Module lifecycle functions
+int hci_start_up(void) {
+  if (hci_layer_init_env())
+    goto error;
+
+  xHciHostQueue = xQueueCreate(3, sizeof(void *));
+  xTaskCreate(hci_host_thread_handler, "HciHostT", (4096+2048), NULL, configMAX_PRIORITIES - 3, &xHciHostTaskHandle);
+
+  packet_fragmenter->init(&packet_fragmenter_callbacks);
+  hal->open(&hal_callbacks);
+  
+  hci_host_startup_flag = true;
+  return 0;
+error:
+  hci_shut_down();
+  return -1;
+}
+
+void hci_shut_down(void) {
+  hci_host_startup_flag  = false;
+  hci_layer_deinit_env();
+
+  packet_fragmenter->cleanup();
+
+  //low_power_manager->cleanup();
+  hal->close();
+  vTaskDelete(xHciHostTaskHandle);
+  vQueueDelete(xHciHostQueue);
+}
+
+
+void hci_host_task_post(void)
+{
+    if (hci_host_startup_flag == false)
+        return;
+
+    TaskEvt_t *evt = (TaskEvt_t *)osi_malloc(sizeof(TaskEvt_t));
+    if (evt == NULL)
+        return;
+
+    evt->sig = 0xff;
+    evt->par = 0;
+
+    if (xQueueSend(xHciHostQueue, &evt, 10/portTICK_RATE_MS) != pdTRUE) {
+            ets_printf("xHciHostQueue failed\n");
+    }
+}
+
+static int hci_layer_init_env(void)
+{
+  command_waiting_response_t *cmd_wait_q;
+
+  // The host is only allowed to send at most one command initially,
+  // as per the Bluetooth spec, Volume 2, Part E, 4.4 (Command Flow Control)
+  // This value can change when you get a command complete or command status event.
+  hci_host_env.command_credits = 1;
+  hci_host_env.command_queue = fixed_queue_new(SIZE_MAX);
+  if (hci_host_env.command_queue)
+    fixed_queue_register_dequeue(hci_host_env.command_queue, event_command_ready);
+  else {
+    LOG_ERROR("%s unable to create pending command queue.", __func__);
+    return -1;
+  }
+
+  hci_host_env.packet_queue = fixed_queue_new(SIZE_MAX);
+  if (hci_host_env.packet_queue)
+    fixed_queue_register_dequeue(hci_host_env.packet_queue, event_packet_ready);  
+  else {
+    LOG_ERROR("%s unable to create pending packet queue.", __func__);
+    return -1;
+  }
+
+  // Init Commands waiting response list and timer
+  cmd_wait_q = &hci_host_env.cmd_waiting_q;
+  cmd_wait_q->timer_is_set = false;
+  cmd_wait_q->commands_pending_response = list_new(NULL);
+  if (!cmd_wait_q->commands_pending_response) {
+    LOG_ERROR("%s unable to create list for commands pending response.", __func__);
+    return -1;
+  }
+  pthread_mutex_init(&cmd_wait_q->commands_pending_response_lock, NULL);
+  cmd_wait_q->command_response_timer = osi_alarm_new("cmd_rsp_to", command_timed_out, cmd_wait_q, COMMAND_PENDING_TIMEOUT);
+  if (!cmd_wait_q->command_response_timer) {
+    LOG_ERROR("%s unable to create command response timer.", __func__);
+    return -1;
+  }
+
+  return 0;
+}
+
+static void hci_layer_deinit_env(void)
+{
+  command_waiting_response_t *cmd_wait_q;
+
+  if (hci_host_env.command_queue)
+    fixed_queue_free(hci_host_env.command_queue, osi_free);
+  if (hci_host_env.packet_queue)
+    fixed_queue_free(hci_host_env.packet_queue, buffer_allocator->free);
+
+  cmd_wait_q = &hci_host_env.cmd_waiting_q;
+  list_free(cmd_wait_q->commands_pending_response);
+  pthread_mutex_destroy(&cmd_wait_q->commands_pending_response_lock);
+ osi_alarm_free(cmd_wait_q->command_response_timer);
+  cmd_wait_q->command_response_timer = NULL;
+}
+
+static void hci_host_thread_handler(void *arg)
+{
+  /*
+   * Previous task handles RX queue and two TX Queues, Since there is
+   * a RX Thread Task in H4 layer which receives packet from driver layer. 
+   * Now HCI Host Task has been optimized to only process TX Queue
+   * including command and data queue. And command queue has high priority,
+   * All packets will be directly copied to single queue in driver layer with
+   * H4 type header added (1 byte).
+   */
+
+    TaskEvt_t *e;
+
+    for (;;) {
+        if (pdTRUE == xQueueReceive(xHciHostQueue, &e, (portTickType)portMAX_DELAY)) {
+
+            if (e->sig == 0xff) {
+                if (API_vhci_host_check_send_available()) {
+                    /*Now Target only allowed one packet per TX*/
+                    BT_HDR *pkt = packet_fragmenter->fragment_current_packet();
+                    if (pkt != NULL) {
+                        packet_fragmenter->fragment_and_dispatch(pkt);
+                    } else {
+                        if (!fixed_queue_is_empty(hci_host_env.command_queue) &&
+                                hci_host_env.command_credits > 0)
+                            fixed_queue_process(hci_host_env.command_queue);
+                        else if (!fixed_queue_is_empty(hci_host_env.packet_queue))
+                            fixed_queue_process(hci_host_env.packet_queue);
+                    }
+                }
+            }
+        }
+        osi_free(e);
+    }
+}
+
+static void set_data_queue(fixed_queue_t *queue) {
+  hci_host_env.upwards_data_queue = queue;
+}
+
+static void transmit_command(
+    BT_HDR *command,
+    command_complete_cb complete_callback,
+    command_status_cb status_callback,
+    void *context) {
+  uint8_t *stream;
+  waiting_command_t *wait_entry = osi_calloc(sizeof(waiting_command_t));
+  if (!wait_entry) {
+    LOG_ERROR("%s couldn't allocate space for wait entry.", __func__);
+    return;
+  }
+
+  stream = command->data + command->offset;
+  STREAM_TO_UINT16(wait_entry->opcode, stream);
+  wait_entry->complete_callback = complete_callback;
+  wait_entry->status_callback = status_callback;
+  wait_entry->command = command;
+  wait_entry->context = context;
+
+  // Store the command message type in the event field
+  // in case the upper layer didn't already
+  command->event = MSG_STACK_TO_HC_HCI_CMD;
+  LOG_DEBUG("HCI Enqueue Comamnd opcode=0x%x\n", wait_entry->opcode);
+  BTTRC_DUMP_BUFFER(NULL, command->data + command->offset, command->len);
+
+  fixed_queue_enqueue(hci_host_env.command_queue, wait_entry);
+  hci_host_task_post();
+}
+
+static void transmit_downward(uint16_t type, void *data) {
+  BT_HDR *tmp = (BT_HDR *)data;
+  if (type == MSG_STACK_TO_HC_HCI_CMD) {
+    transmit_command((BT_HDR *)data, NULL, NULL, NULL);
+    LOG_WARN("%s legacy transmit of command. Use transmit_command instead.\n", __func__);
+  } else {
+    fixed_queue_enqueue(hci_host_env.packet_queue, data);
+  }
+  //ke_event_set(KE_EVENT_HCI_HOST_THREAD);
+  hci_host_task_post();
+}
+
+// Postload functions
+static void event_postload(void) {
+  if (hci_send_async_command(BT_VND_OP_SCO_CFG, NULL) == -1) {
+    // If couldn't configure sco, we won't get the sco configuration callback
+    // so go pretend to do it now
+    sco_config_callback(false);
+
+  }
+}
+
+static void sco_config_callback(UNUSED_ATTR bool success) {
+  LOG_INFO("%s postload finished.", __func__);
+}
+
+// Command/packet transmitting functions
+
+static void event_command_ready(fixed_queue_t *queue) {
+  waiting_command_t *wait_entry = NULL;
+  command_waiting_response_t *cmd_wait_q = &hci_host_env.cmd_waiting_q;
+
+  wait_entry = fixed_queue_dequeue(queue);
+  hci_host_env.command_credits--;
+
+  // Move it to the list of commands awaiting response
+  pthread_mutex_lock(&cmd_wait_q->commands_pending_response_lock);
+  //ets_printf("%s\n", __func__);
+  list_append(cmd_wait_q->commands_pending_response, wait_entry);
+  pthread_mutex_unlock(&cmd_wait_q->commands_pending_response_lock);
+
+  // Send it off
+  packet_fragmenter->fragment_and_dispatch(wait_entry->command);
+
+  wait_entry->sent_time = osi_alarm_now();
+  restart_comamnd_waiting_response_timer(cmd_wait_q, true);
+}
+
+static void event_packet_ready(fixed_queue_t *queue) {
+  BT_HDR *packet = (BT_HDR *)fixed_queue_dequeue(queue);
+  // The queue may be the command queue or the packet queue, we don't care
+
+  packet_fragmenter->fragment_and_dispatch(packet);
+}
+
+// Callback for the fragmenter to send a fragment
+static void transmit_fragment(BT_HDR *packet, bool send_transmit_finished) {
+  uint16_t event = packet->event & MSG_EVT_MASK;
+  serial_data_type_t type = event_to_data_type(event);
+
+  hal->transmit_data(type, packet->data + packet->offset, packet->len);
+
+  if (event != MSG_STACK_TO_HC_HCI_CMD && send_transmit_finished)
+    buffer_allocator->free(packet);
+}
+
+static void fragmenter_transmit_finished(BT_HDR *packet, bool all_fragments_sent) {
+  if (all_fragments_sent) {
+    buffer_allocator->free(packet);
+  } else {
+    // This is kind of a weird case, since we're dispatching a partially sent packet
+    // up to a higher layer.
+    // TODO(zachoverflow): rework upper layer so this isn't necessary.
+    dispatch_reassembled(packet);
+    //data_dispatcher_dispatch(interface.event_dispatcher, packet->event & MSG_EVT_MASK, packet);
+  }
+}
+
+static void restart_comamnd_waiting_response_timer(
+             command_waiting_response_t *cmd_wait_q,
+             bool tigger_by_sending_command)
+{
+  uint32_t timeout;
+  waiting_command_t *wait_entry;
+  if (!cmd_wait_q)
+    return;
+
+  if (cmd_wait_q->timer_is_set) {
+    if (tigger_by_sending_command)
+      return;
+
+    //Cancel Previous command timeout timer setted when sending command
+   osi_alarm_cancel(cmd_wait_q->command_response_timer);
+    cmd_wait_q->timer_is_set = false;
+  }
+
+  pthread_mutex_lock(&cmd_wait_q->commands_pending_response_lock);
+  wait_entry = (list_is_empty(cmd_wait_q->commands_pending_response) ?
+                NULL : list_front(cmd_wait_q->commands_pending_response));
+  pthread_mutex_unlock(&cmd_wait_q->commands_pending_response_lock);
+
+  if (wait_entry == NULL)
+    return;
+
+  timeout =osi_alarm_time_diff(osi_alarm_now(), wait_entry->sent_time);
+  timeout =osi_alarm_time_diff(COMMAND_PENDING_TIMEOUT, timeout);
+  timeout = (timeout <= COMMAND_PENDING_TIMEOUT) ? timeout : COMMAND_PENDING_TIMEOUT;
+
+ osi_alarm_set(cmd_wait_q->command_response_timer, timeout);
+  cmd_wait_q->timer_is_set = true;
+}
+
+static void command_timed_out(void *context) {
+  command_waiting_response_t *cmd_wait_q = (command_waiting_response_t *)context;
+  waiting_command_t *wait_entry;
+
+  pthread_mutex_lock(&cmd_wait_q->commands_pending_response_lock);
+  wait_entry = (list_is_empty(cmd_wait_q->commands_pending_response) ?
+                NULL : list_front(cmd_wait_q->commands_pending_response));
+  pthread_mutex_unlock(&cmd_wait_q->commands_pending_response_lock);
+
+  if (wait_entry == NULL)
+    LOG_ERROR("%s with no commands pending response", __func__);
+  else
+    // We shouldn't try to recover the stack from this command timeout.
+    // If it's caused by a software bug, fix it. If it's a hardware bug, fix it.
+    LOG_ERROR("%s hci layer timeout waiting for response to a command. opcode: 0x%x", __func__, wait_entry->opcode);
+}
+
+// Event/packet receiving functions
+static void hal_says_packet_ready(BT_HDR *packet) {
+  if (packet->event != MSG_HC_TO_STACK_HCI_EVT) {
+    packet_fragmenter->reassemble_and_dispatch(packet);
+  } else if (!filter_incoming_event(packet)) {
+    dispatch_reassembled(packet);
+  }
+}
+
+// Returns true if the event was intercepted and should not proceed to
+// higher layers. Also inspects an incoming event for interesting
+// information, like how many commands are now able to be sent.
+static bool filter_incoming_event(BT_HDR *packet) {
+  waiting_command_t *wait_entry = NULL;
+  uint8_t *stream = packet->data + packet->offset;
+  uint8_t event_code;
+  command_opcode_t opcode;
+
+  STREAM_TO_UINT8(event_code, stream);
+  STREAM_SKIP_UINT8(stream); // Skip the parameter total length field
+
+  LOG_DEBUG("Receive packet event_code=0x%x\n", event_code);
+
+  if (event_code == HCI_COMMAND_COMPLETE_EVT) {
+    STREAM_TO_UINT8(hci_host_env.command_credits, stream);
+    STREAM_TO_UINT16(opcode, stream);
+
+    wait_entry = get_waiting_command(opcode);
+    if (!wait_entry)
+      LOG_WARN("%s command complete event with no matching command. opcode: 0x%x.", __func__, opcode);
+    else if (wait_entry->complete_callback)
+      wait_entry->complete_callback(packet, wait_entry->context);
+
+    goto intercepted;
+  } else if (event_code == HCI_COMMAND_STATUS_EVT) {
+    uint8_t status;
+    STREAM_TO_UINT8(status, stream);
+    STREAM_TO_UINT8(hci_host_env.command_credits, stream);
+    STREAM_TO_UINT16(opcode, stream);
+
+    // If a command generates a command status event, it won't be getting a command complete event
+
+    wait_entry = get_waiting_command(opcode);
+    if (!wait_entry)
+      LOG_WARN("%s command status event with no matching command. opcode: 0x%x", __func__, opcode);
+    else if (wait_entry->status_callback)
+      wait_entry->status_callback(status, wait_entry->command, wait_entry->context);
+
+    goto intercepted;
+  }
+
+  return false;
+intercepted:
+  /*Tell HCI Host Task to continue TX Pending commands*/
+  if (hci_host_env.command_credits &&
+      !fixed_queue_is_empty(hci_host_env.command_queue))
+    hci_host_task_post();
+    //ke_event_set(KE_EVENT_HCI_HOST_THREAD);
+
+  restart_comamnd_waiting_response_timer(&hci_host_env.cmd_waiting_q, false);
+
+  if (wait_entry) {
+    // If it has a callback, it's responsible for freeing the packet
+    if (event_code == HCI_COMMAND_STATUS_EVT ||
+        !wait_entry->complete_callback)
+      buffer_allocator->free(packet);
+
+    // If it has a callback, it's responsible for freeing the command
+    if (event_code == HCI_COMMAND_COMPLETE_EVT || !wait_entry->status_callback)
+      buffer_allocator->free(wait_entry->command);
+
+    osi_free(wait_entry);
+  } else {
+    buffer_allocator->free(packet);
+  }
+
+  return true;
+}
+
+// Callback for the fragmenter to dispatch up a completely reassembled packet
+static void dispatch_reassembled(BT_HDR *packet) {
+  // Events should already have been dispatched before this point
+
+  if (hci_host_env.upwards_data_queue) {
+    fixed_queue_enqueue(hci_host_env.upwards_data_queue, packet);
+    btu_task_post();
+    //Tell Up-layer received packet.
+  } else {
+    LOG_DEBUG("%s had no queue to place upwards data packet in. Dropping it on the floor.", __func__);
+    buffer_allocator->free(packet);
+  }
+}
+
+// Misc internal functions
+
+// TODO(zachoverflow): we seem to do this a couple places, like the HCI inject module. #centralize
+static serial_data_type_t event_to_data_type(uint16_t event) {
+  if (event == MSG_STACK_TO_HC_HCI_ACL)
+    return DATA_TYPE_ACL;
+  else if (event == MSG_STACK_TO_HC_HCI_SCO)
+    return DATA_TYPE_SCO;
+  else if (event == MSG_STACK_TO_HC_HCI_CMD)
+    return DATA_TYPE_COMMAND;
+  else
+    LOG_ERROR("%s invalid event type, could not translate 0x%x", __func__, event);
+
+  return 0;
+}
+
+static waiting_command_t *get_waiting_command(command_opcode_t opcode) {
+  command_waiting_response_t *cmd_wait_q = &hci_host_env.cmd_waiting_q;
+  pthread_mutex_lock(&cmd_wait_q->commands_pending_response_lock);
+
+  for (const list_node_t *node = list_begin(cmd_wait_q->commands_pending_response);
+      node != list_end(cmd_wait_q->commands_pending_response);
+      node = list_next(node)) {
+    waiting_command_t *wait_entry = list_node(node);
+    //ets_printf("wait_entry %08x\n", wait_entry);
+    if (!wait_entry || wait_entry->opcode != opcode)
+      continue;
+
+    list_remove(cmd_wait_q->commands_pending_response, wait_entry);
+
+    pthread_mutex_unlock(&cmd_wait_q->commands_pending_response_lock);
+    return wait_entry;
+  }
+
+  pthread_mutex_unlock(&cmd_wait_q->commands_pending_response_lock);
+  return NULL;
+}
+
+static int hci_send_async_command(bt_vendor_opcode_t opcode, void *param)
+{
+}
+
+static void init_layer_interface() {
+  if (!interface_created) {
+    interface.set_data_queue = set_data_queue;
+    interface.transmit_command = transmit_command;
+    interface.transmit_downward = transmit_downward;
+    interface_created = true;
+  }
+}
+
+static const hci_hal_callbacks_t hal_callbacks = {
+  hal_says_packet_ready
+};
+
+static const packet_fragmenter_callbacks_t packet_fragmenter_callbacks = {
+  transmit_fragment,
+  dispatch_reassembled,
+  fragmenter_transmit_finished
+};
+
+const hci_t *hci_layer_get_interface() {
+  buffer_allocator = buffer_allocator_get_interface();
+  hal = hci_hal_h4_get_interface();
+  packet_fragmenter = packet_fragmenter_get_interface();
+
+  init_layer_interface();
+  return &interface;
+}
+

+ 202 - 0
components/bt/bluedroid/hci/hci_packet_factory.c

@@ -0,0 +1,202 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#include "bt_defs.h"
+
+#include "allocator.h"
+#include "bt_types.h"
+#include "buffer_allocator.h"
+#include "hcidefs.h"
+#include "hcimsgs.h"
+#include "hci_internals.h"
+#include "hci_layer.h"
+#include "hci_packet_factory.h"
+
+static const allocator_t *buffer_allocator;
+
+static BT_HDR *make_packet(size_t data_size);
+static BT_HDR *make_command_no_params(uint16_t opcode);
+static BT_HDR *make_command(uint16_t opcode, size_t parameter_size, uint8_t **stream_out);
+
+// Interface functions
+
+static BT_HDR *make_reset(void) {
+  return make_command_no_params(HCI_RESET);
+}
+
+static BT_HDR *make_read_buffer_size(void) {
+  return make_command_no_params(HCI_READ_BUFFER_SIZE);
+}
+
+static BT_HDR *make_host_buffer_size(uint16_t acl_size, uint8_t sco_size, uint16_t acl_count, uint16_t sco_count) {
+  uint8_t *stream;
+  const uint8_t parameter_size = 2 + 1 + 2 + 2; // from each of the parameters
+  BT_HDR *packet = make_command(HCI_HOST_BUFFER_SIZE, parameter_size, &stream);
+
+  UINT16_TO_STREAM(stream, acl_size);
+  UINT8_TO_STREAM(stream, sco_size);
+  UINT16_TO_STREAM(stream, acl_count);
+  UINT16_TO_STREAM(stream, sco_count);
+  return packet;
+}
+
+static BT_HDR *make_read_local_version_info(void) {
+  return make_command_no_params(HCI_READ_LOCAL_VERSION_INFO);
+}
+
+static BT_HDR *make_read_bd_addr(void) {
+  return make_command_no_params(HCI_READ_BD_ADDR);
+}
+
+static BT_HDR *make_read_local_supported_commands(void) {
+  return make_command_no_params(HCI_READ_LOCAL_SUPPORTED_CMDS);
+}
+
+static BT_HDR *make_read_local_extended_features(uint8_t page_number) {
+  uint8_t *stream;
+  const uint8_t parameter_size = 1;
+  BT_HDR *packet = make_command(HCI_READ_LOCAL_EXT_FEATURES, parameter_size, &stream);
+
+  UINT8_TO_STREAM(stream, page_number);
+  return packet;
+}
+
+static BT_HDR *make_write_simple_pairing_mode(uint8_t mode) {
+  uint8_t *stream;
+  const uint8_t parameter_size = 1;
+  BT_HDR *packet = make_command(HCI_WRITE_SIMPLE_PAIRING_MODE, parameter_size, &stream);
+
+  UINT8_TO_STREAM(stream, mode);
+  return packet;
+}
+
+static BT_HDR *make_write_secure_connections_host_support(uint8_t mode) {
+  uint8_t *stream;
+  const uint8_t parameter_size = 1;
+  BT_HDR *packet = make_command(HCI_WRITE_SECURE_CONNS_SUPPORT, parameter_size, &stream);
+
+  UINT8_TO_STREAM(stream, mode);
+  return packet;
+}
+
+static BT_HDR *make_set_event_mask(const bt_event_mask_t *event_mask) {
+  uint8_t *stream;
+  uint8_t parameter_size = sizeof(bt_event_mask_t);
+  BT_HDR *packet = make_command(HCI_SET_EVENT_MASK, parameter_size, &stream);
+
+  ARRAY8_TO_STREAM(stream, event_mask->as_array);
+  return packet;
+}
+
+static BT_HDR *make_ble_write_host_support(uint8_t supported_host, uint8_t simultaneous_host) {
+  uint8_t *stream;
+  const uint8_t parameter_size = 1 + 1;
+  BT_HDR *packet = make_command(HCI_WRITE_LE_HOST_SUPPORT, parameter_size, &stream);
+
+  UINT8_TO_STREAM(stream, supported_host);
+  UINT8_TO_STREAM(stream, simultaneous_host);
+  return packet;
+}
+
+static BT_HDR *make_ble_read_white_list_size(void) {
+  return make_command_no_params(HCI_BLE_READ_WHITE_LIST_SIZE);
+}
+
+static BT_HDR *make_ble_read_buffer_size(void) {
+  return make_command_no_params(HCI_BLE_READ_BUFFER_SIZE);
+}
+
+static BT_HDR *make_ble_read_supported_states(void) {
+  return make_command_no_params(HCI_BLE_READ_SUPPORTED_STATES);
+}
+
+static BT_HDR *make_ble_read_local_supported_features(void) {
+  return make_command_no_params(HCI_BLE_READ_LOCAL_SPT_FEAT);
+}
+
+static BT_HDR *make_ble_read_resolving_list_size(void) {
+  return make_command_no_params(HCI_BLE_READ_RESOLVING_LIST_SIZE);
+}
+
+static BT_HDR *make_ble_read_suggested_default_data_length(void) {
+    return make_command_no_params(HCI_BLE_READ_DEFAULT_DATA_LENGTH);
+}
+
+static BT_HDR *make_ble_set_event_mask(const bt_event_mask_t *event_mask) {
+  uint8_t *stream;
+  uint8_t parameter_size = sizeof(bt_event_mask_t);
+  BT_HDR *packet = make_command(HCI_BLE_SET_EVENT_MASK, parameter_size, &stream);
+
+  ARRAY8_TO_STREAM(stream, event_mask->as_array);
+  return packet;
+}
+
+// Internal functions
+
+static BT_HDR *make_command_no_params(uint16_t opcode) {
+  return make_command(opcode, 0, NULL);
+}
+
+static BT_HDR *make_command(uint16_t opcode, size_t parameter_size, uint8_t **stream_out) {
+  BT_HDR *packet = make_packet(HCI_COMMAND_PREAMBLE_SIZE + parameter_size);
+
+  uint8_t *stream = packet->data;
+  UINT16_TO_STREAM(stream, opcode);
+  UINT8_TO_STREAM(stream, parameter_size);
+
+  if (stream_out != NULL)
+    *stream_out = stream;
+
+  return packet;
+}
+
+static BT_HDR *make_packet(size_t data_size) {
+  BT_HDR *ret = (BT_HDR *)buffer_allocator->alloc(sizeof(BT_HDR) + data_size);
+  assert(ret);
+  ret->event = 0;
+  ret->offset = 0;
+  ret->layer_specific = 0;
+  ret->len = data_size;
+  return ret;
+}
+
+static const hci_packet_factory_t interface = {
+  make_reset,
+  make_read_buffer_size,
+  make_host_buffer_size,
+  make_read_local_version_info,
+  make_read_bd_addr,
+  make_read_local_supported_commands,
+  make_read_local_extended_features,
+  make_write_simple_pairing_mode,
+  make_write_secure_connections_host_support,
+  make_set_event_mask,
+  make_ble_write_host_support,
+  make_ble_read_white_list_size,
+  make_ble_read_buffer_size,
+  make_ble_read_supported_states,
+  make_ble_read_local_supported_features,
+  make_ble_read_resolving_list_size,
+  make_ble_read_suggested_default_data_length,
+  make_ble_set_event_mask
+};
+
+const hci_packet_factory_t *hci_packet_factory_get_interface() {
+  buffer_allocator = buffer_allocator_get_interface();
+  return &interface;
+}

+ 243 - 0
components/bt/bluedroid/hci/hci_packet_parser.c

@@ -0,0 +1,243 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#include "bt_defs.h"
+
+#include "buffer_allocator.h"
+#include "bt_types.h"
+#include "hcimsgs.h"
+#include "hci_layer.h"
+#include "hci_packet_parser.h"
+
+static const command_opcode_t NO_OPCODE_CHECKING = 0;
+
+static const allocator_t *buffer_allocator;
+
+static uint8_t *read_command_complete_header(
+  BT_HDR *response,
+  command_opcode_t expected_opcode,
+  size_t minimum_bytes_after);
+
+static void parse_generic_command_complete(BT_HDR *response) {
+  read_command_complete_header(response, NO_OPCODE_CHECKING, 0 /* bytes after */);
+
+  buffer_allocator->free(response);
+}
+
+static void parse_read_buffer_size_response(
+    BT_HDR *response,
+    uint16_t *data_size_ptr,
+    uint16_t *acl_buffer_count_ptr) {
+
+  uint8_t *stream = read_command_complete_header(response, HCI_READ_BUFFER_SIZE, 5 /* bytes after */);
+  assert(stream != NULL);
+  STREAM_TO_UINT16(*data_size_ptr, stream);
+  STREAM_SKIP_UINT8(stream); // skip the sco packet length
+  STREAM_TO_UINT16(*acl_buffer_count_ptr, stream);
+
+  buffer_allocator->free(response);
+}
+
+static void parse_read_local_version_info_response(
+    BT_HDR *response,
+    bt_version_t *bt_version) {
+
+  uint8_t *stream = read_command_complete_header(response, HCI_READ_LOCAL_VERSION_INFO, 8 /* bytes after */);
+  assert(stream != NULL);
+  STREAM_TO_UINT8(bt_version->hci_version, stream);
+  STREAM_TO_UINT16(bt_version->hci_revision, stream);
+  STREAM_TO_UINT8(bt_version->lmp_version, stream);
+  STREAM_TO_UINT16(bt_version->manufacturer, stream);
+  STREAM_TO_UINT16(bt_version->lmp_subversion, stream);
+
+  buffer_allocator->free(response);
+}
+
+static void parse_read_bd_addr_response(
+    BT_HDR *response,
+    bt_bdaddr_t *address_ptr) {
+
+  uint8_t *stream = read_command_complete_header(response, HCI_READ_BD_ADDR, sizeof(bt_bdaddr_t) /* bytes after */);
+  assert(stream != NULL);
+  STREAM_TO_BDADDR(address_ptr->address, stream);
+
+  buffer_allocator->free(response);
+}
+
+static void parse_read_local_supported_commands_response(
+    BT_HDR *response,
+    uint8_t *supported_commands_ptr,
+    size_t supported_commands_length) {
+
+  uint8_t *stream = read_command_complete_header(response, HCI_READ_LOCAL_SUPPORTED_CMDS, supported_commands_length /* bytes after */);
+  assert(stream != NULL);
+  STREAM_TO_ARRAY(supported_commands_ptr, stream, (int)supported_commands_length);
+
+  buffer_allocator->free(response);
+}
+
+static void parse_read_local_extended_features_response(
+    BT_HDR *response,
+    uint8_t *page_number_ptr,
+    uint8_t *max_page_number_ptr,
+    bt_device_features_t *feature_pages,
+    size_t feature_pages_count) {
+
+  uint8_t *stream = read_command_complete_header(response, HCI_READ_LOCAL_EXT_FEATURES, 2 + sizeof(bt_device_features_t) /* bytes after */);
+  if (stream != NULL) {
+    STREAM_TO_UINT8(*page_number_ptr, stream);
+    STREAM_TO_UINT8(*max_page_number_ptr, stream);
+
+    assert(*page_number_ptr < feature_pages_count);
+    STREAM_TO_ARRAY(feature_pages[*page_number_ptr].as_array, stream, (int)sizeof(bt_device_features_t));
+  } else {
+    LOG_ERROR("%s() - WARNING: READING EXTENDED FEATURES FAILED. "
+                "THIS MAY INDICATE A FIRMWARE/CONTROLLER ISSUE.", __func__);
+  }
+
+  buffer_allocator->free(response);
+}
+
+static void parse_ble_read_white_list_size_response(
+    BT_HDR *response,
+    uint8_t *white_list_size_ptr) {
+
+  uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_WHITE_LIST_SIZE, 1 /* byte after */);
+  assert(stream != NULL);
+  STREAM_TO_UINT8(*white_list_size_ptr, stream);
+
+  buffer_allocator->free(response);
+}
+
+static void parse_ble_read_buffer_size_response(
+    BT_HDR *response,
+    uint16_t *data_size_ptr,
+    uint8_t *acl_buffer_count_ptr) {
+
+  uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_BUFFER_SIZE, 3 /* bytes after */);
+  assert(stream != NULL);
+  STREAM_TO_UINT16(*data_size_ptr, stream);
+  STREAM_TO_UINT8(*acl_buffer_count_ptr, stream);
+
+  buffer_allocator->free(response);
+}
+
+static void parse_ble_read_supported_states_response(
+    BT_HDR *response,
+    uint8_t *supported_states,
+    size_t supported_states_size) {
+
+  uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_SUPPORTED_STATES, supported_states_size /* bytes after */);
+  assert(stream != NULL);
+  STREAM_TO_ARRAY(supported_states, stream, (int)supported_states_size);
+
+  buffer_allocator->free(response);
+}
+
+static void parse_ble_read_local_supported_features_response(
+    BT_HDR *response,
+    bt_device_features_t *supported_features) {
+
+  uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_LOCAL_SPT_FEAT, sizeof(bt_device_features_t) /* bytes after */);
+  assert(stream != NULL);
+  STREAM_TO_ARRAY(supported_features->as_array, stream, (int)sizeof(bt_device_features_t));
+
+  buffer_allocator->free(response);
+}
+
+static void parse_ble_read_resolving_list_size_response(
+    BT_HDR *response,
+    uint8_t *resolving_list_size_ptr) {
+
+  uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_RESOLVING_LIST_SIZE, 1 /* bytes after */);
+  STREAM_TO_UINT8(*resolving_list_size_ptr, stream);
+
+  buffer_allocator->free(response);
+}
+
+static void parse_ble_read_suggested_default_data_length_response(
+    BT_HDR *response,
+    uint16_t *ble_default_packet_length_ptr) {
+
+  uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_DEFAULT_DATA_LENGTH, 2 /* bytes after */);
+  STREAM_TO_UINT8(*ble_default_packet_length_ptr, stream);
+
+  buffer_allocator->free(response);
+}
+
+// Internal functions
+
+static uint8_t *read_command_complete_header(
+    BT_HDR *response,
+    command_opcode_t expected_opcode,
+    size_t minimum_bytes_after) {
+
+  uint8_t *stream = response->data + response->offset;
+
+  // Read the event header
+  uint8_t event_code;
+  uint8_t parameter_length;
+  STREAM_TO_UINT8(event_code, stream);
+  STREAM_TO_UINT8(parameter_length, stream);
+
+  const size_t parameter_bytes_we_read_here = 4;
+
+  // Check the event header values against what we expect
+  assert(event_code == HCI_COMMAND_COMPLETE_EVT);
+  assert(parameter_length >= (parameter_bytes_we_read_here + minimum_bytes_after));
+
+  // Read the command complete header
+  command_opcode_t opcode;
+  uint8_t status;
+  STREAM_SKIP_UINT8(stream); // skip the number of hci command packets field
+  STREAM_TO_UINT16(opcode, stream);
+
+  // Check the command complete header values against what we expect
+  if (expected_opcode != NO_OPCODE_CHECKING) {
+    assert(opcode == expected_opcode);
+  }
+
+  // Assume the next field is the status field
+  STREAM_TO_UINT8(status, stream);
+
+  if (status != HCI_SUCCESS)
+    return NULL;
+
+  return stream;
+}
+
+static const hci_packet_parser_t interface = {
+  parse_generic_command_complete,
+  parse_read_buffer_size_response,
+  parse_read_local_version_info_response,
+  parse_read_bd_addr_response,
+  parse_read_local_supported_commands_response,
+  parse_read_local_extended_features_response,
+  parse_ble_read_white_list_size_response,
+  parse_ble_read_buffer_size_response,
+  parse_ble_read_supported_states_response,
+  parse_ble_read_local_supported_features_response,
+  parse_ble_read_resolving_list_size_response,
+  parse_ble_read_suggested_default_data_length_response
+};
+
+const hci_packet_parser_t *hci_packet_parser_get_interface() {
+  buffer_allocator = buffer_allocator_get_interface();
+  return &interface;
+}
+

+ 362 - 0
components/bt/bluedroid/hci/include/bt_vendor_lib.h

@@ -0,0 +1,362 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ *  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_VENDOR_LIB_H
+#define BT_VENDOR_LIB_H
+
+#include <stdint.h>
+//#include <sys/cdefs.h>
+//#include <sys/types.h>
+
+/** Struct types */
+
+
+/** Typedefs and defines */
+
+/** Vendor specific operations OPCODE */
+typedef enum {
+/*  [operation]
+ *      Power on or off the BT Controller.
+ *  [input param]
+ *      A pointer to int type with content of bt_vendor_power_state_t.
+ *      Typecasting conversion: (int *) param.
+ *  [return]
+ *      0 - default, don't care.
+ *  [callback]
+ *      None.
+ */
+    BT_VND_OP_POWER_CTRL,
+
+/*  [operation]
+ *      Perform any vendor specific initialization or configuration
+ *      on the BT Controller. This is called before stack initialization.
+ *  [input param]
+ *      None.
+ *  [return]
+ *      0 - default, don't care.
+ *  [callback]
+ *      Must call fwcfg_cb to notify the stack of the completion of vendor
+ *      specific initialization once it has been done.
+ */
+    BT_VND_OP_FW_CFG,
+
+/*  [operation]
+ *      Perform any vendor specific SCO/PCM configuration on the BT Controller.
+ *      This is called after stack initialization.
+ *  [input param]
+ *      None.
+ *  [return]
+ *      0 - default, don't care.
+ *  [callback]
+ *      Must call scocfg_cb to notify the stack of the completion of vendor
+ *      specific SCO configuration once it has been done.
+ */
+    BT_VND_OP_SCO_CFG,
+
+/*  [operation]
+ *      Open UART port on where the BT Controller is attached.
+ *      This is called before stack initialization.
+ *  [input param]
+ *      A pointer to int array type for open file descriptors.
+ *      The mapping of HCI channel to fd slot in the int array is given in
+ *      bt_vendor_hci_channels_t.
+ *      And, it requires the vendor lib to fill up the content before returning
+ *      the call.
+ *      Typecasting conversion: (int (*)[]) param.
+ *  [return]
+ *      Numbers of opened file descriptors.
+ *      Valid number:
+ *          1 - CMD/EVT/ACL-In/ACL-Out via the same fd (e.g. UART)
+ *          2 - CMD/EVT on one fd, and ACL-In/ACL-Out on the other fd
+ *          4 - CMD, EVT, ACL-In, ACL-Out are on their individual fd
+ *  [callback]
+ *      None.
+ */
+    BT_VND_OP_USERIAL_OPEN,
+
+/*  [operation]
+ *      Close the previously opened UART port.
+ *  [input param]
+ *      None.
+ *  [return]
+ *      0 - default, don't care.
+ *  [callback]
+ *      None.
+ */
+    BT_VND_OP_USERIAL_CLOSE,
+
+/*  [operation]
+ *      Get the LPM idle timeout in milliseconds.
+ *      The stack uses this information to launch a timer delay before it
+ *      attempts to de-assert LPM WAKE signal once downstream HCI packet
+ *      has been delivered.
+ *  [input param]
+ *      A pointer to uint32_t type which is passed in by the stack. And, it
+ *      requires the vendor lib to fill up the content before returning
+ *      the call.
+ *      Typecasting conversion: (uint32_t *) param.
+ *  [return]
+ *      0 - default, don't care.
+ *  [callback]
+ *      None.
+ */
+    BT_VND_OP_GET_LPM_IDLE_TIMEOUT,
+
+/*  [operation]
+ *      Enable or disable LPM mode on BT Controller.
+ *  [input param]
+ *      A pointer to uint8_t type with content of bt_vendor_lpm_mode_t.
+ *      Typecasting conversion: (uint8_t *) param.
+ *  [return]
+ *      0 - default, don't care.
+ *  [callback]
+ *      Must call lpm_cb to notify the stack of the completion of LPM
+ *      disable/enable process once it has been done.
+ */
+    BT_VND_OP_LPM_SET_MODE,
+
+/*  [operation]
+ *      Assert or Deassert LPM WAKE on BT Controller.
+ *  [input param]
+ *      A pointer to uint8_t type with content of bt_vendor_lpm_wake_state_t.
+ *      Typecasting conversion: (uint8_t *) param.
+ *  [return]
+ *      0 - default, don't care.
+ *  [callback]
+ *      None.
+ */
+    BT_VND_OP_LPM_WAKE_SET_STATE,
+
+/*  [operation]
+ *      Perform any vendor specific commands related to audio state changes.
+ *  [input param]
+ *      a pointer to bt_vendor_op_audio_state_t indicating what audio state is
+ *      set.
+ *  [return]
+ *      0 - default, don't care.
+ *  [callback]
+ *      None.
+ */
+    BT_VND_OP_SET_AUDIO_STATE,
+
+/*  [operation]
+ *      The epilog call to the vendor module so that it can perform any
+ *      vendor-specific processes (e.g. send a HCI_RESET to BT Controller)
+ *      before the caller calls for cleanup().
+ *  [input param]
+ *      None.
+ *  [return]
+ *      0 - default, don't care.
+ *  [callback]
+ *      Must call epilog_cb to notify the stack of the completion of vendor
+ *      specific epilog process once it has been done.
+ */
+    BT_VND_OP_EPILOG,
+} bt_vendor_opcode_t;
+
+/** Power on/off control states */
+typedef enum {
+    BT_VND_PWR_OFF,
+    BT_VND_PWR_ON,
+}  bt_vendor_power_state_t;
+
+/** Define HCI channel identifier in the file descriptors array
+    used in BT_VND_OP_USERIAL_OPEN operation.
+ */
+typedef enum {
+    CH_CMD,     // HCI Command channel
+    CH_EVT,     // HCI Event channel
+    CH_ACL_OUT, // HCI ACL downstream channel
+    CH_ACL_IN,  // HCI ACL upstream channel
+
+    CH_MAX      // Total channels
+}  bt_vendor_hci_channels_t;
+
+/** LPM disable/enable request */
+typedef enum {
+    BT_VND_LPM_DISABLE,
+    BT_VND_LPM_ENABLE,
+} bt_vendor_lpm_mode_t;
+
+/** LPM WAKE set state request */
+typedef enum {
+    BT_VND_LPM_WAKE_ASSERT,
+    BT_VND_LPM_WAKE_DEASSERT,
+} bt_vendor_lpm_wake_state_t;
+
+/** Callback result values */
+typedef enum {
+    BT_VND_OP_RESULT_SUCCESS,
+    BT_VND_OP_RESULT_FAIL,
+} bt_vendor_op_result_t;
+
+/** audio (SCO) state changes triggering VS commands for configuration */
+typedef struct {
+    uint16_t    handle;
+    uint16_t    peer_codec;
+    uint16_t    state;
+} bt_vendor_op_audio_state_t;
+
+/*
+ * Bluetooth Host/Controller Vendor callback structure.
+ */
+
+/* vendor initialization/configuration callback */
+typedef void (*cfg_result_cb)(bt_vendor_op_result_t result);
+
+/* datapath buffer allocation callback (callout)
+ *
+ *  Vendor lib needs to request a buffer through the alloc callout function
+ *  from HCI lib if the buffer is for constructing a HCI Command packet which
+ *  will be sent through xmit_cb to BT Controller.
+ *
+ *  For each buffer allocation, the requested size needs to be big enough to
+ *  accommodate the below header plus a complete HCI packet --
+ *      typedef struct
+ *      {
+ *          uint16_t          event;
+ *          uint16_t          len;
+ *          uint16_t          offset;
+ *          uint16_t          layer_specific;
+ *      } HC_BT_HDR;
+ *
+ *  HCI lib returns a pointer to the buffer where Vendor lib should use to
+ *  construct a HCI command packet as below format:
+ *
+ *  --------------------------------------------
+ *  |  HC_BT_HDR  |  HCI command               |
+ *  --------------------------------------------
+ *  where
+ *      HC_BT_HDR.event = 0x2000;
+ *      HC_BT_HDR.len = Length of HCI command;
+ *      HC_BT_HDR.offset = 0;
+ *      HC_BT_HDR.layer_specific = 0;
+ *
+ *  For example, a HCI_RESET Command will be formed as
+ *  ------------------------
+ *  |  HC_BT_HDR  |03|0c|00|
+ *  ------------------------
+ *  with
+ *      HC_BT_HDR.event = 0x2000;
+ *      HC_BT_HDR.len = 3;
+ *      HC_BT_HDR.offset = 0;
+ *      HC_BT_HDR.layer_specific = 0;
+ */
+typedef void* (*malloc_cb)(int size);
+
+/* datapath buffer deallocation callback (callout) */
+typedef void (*mdealloc_cb)(void *p_buf);
+
+/* define callback of the cmd_xmit_cb
+ *
+ *  The callback function which HCI lib will call with the return of command
+ *  complete packet. Vendor lib is responsible for releasing the buffer passed
+ *  in at the p_mem parameter by calling dealloc callout function.
+ */
+typedef void (*tINT_CMD_CBACK)(void *p_mem);
+
+/* hci command packet transmit callback (callout)
+ *
+ *  Vendor lib calls xmit_cb callout function in order to send a HCI Command
+ *  packet to BT Controller. The buffer carrying HCI Command packet content
+ *  needs to be first allocated through the alloc callout function.
+ *  HCI lib will release the buffer for Vendor lib once it has delivered the
+ *  packet content to BT Controller.
+ *
+ *  Vendor lib needs also provide a callback function (p_cback) which HCI lib
+ *  will call with the return of command complete packet.
+ *
+ *  The opcode parameter gives the HCI OpCode (combination of OGF and OCF) of
+ *  HCI Command packet. For example, opcode = 0x0c03 for the HCI_RESET command
+ *  packet.
+ */
+typedef uint8_t (*cmd_xmit_cb)(uint16_t opcode, void *p_buf, tINT_CMD_CBACK p_cback);
+
+typedef struct {
+    /** set to sizeof(bt_vendor_callbacks_t) */
+    size_t         size;
+
+    /*
+     * Callback and callout functions have implemented in HCI libray
+     * (libbt-hci.so).
+     */
+
+    /* notifies caller result of firmware configuration request */
+    cfg_result_cb  fwcfg_cb;
+
+    /* notifies caller result of sco configuration request */
+    cfg_result_cb  scocfg_cb;
+
+    /* notifies caller result of lpm enable/disable */
+    cfg_result_cb  lpm_cb;
+
+    /* notifies the result of codec setting */
+    cfg_result_cb audio_state_cb;
+
+    /* buffer allocation request */
+    malloc_cb   alloc;
+
+    /* buffer deallocation request */
+    mdealloc_cb dealloc;
+
+    /* hci command packet transmit request */
+    cmd_xmit_cb xmit_cb;
+
+    /* notifies caller completion of epilog process */
+    cfg_result_cb epilog_cb;
+} bt_vendor_callbacks_t;
+
+/*
+ * Bluetooth Host/Controller VENDOR Interface
+ */
+typedef struct {
+    /** Set to sizeof(bt_vndor_interface_t) */
+    size_t          size;
+
+    /*
+     * Functions need to be implemented in Vendor libray (libbt-vendor.so).
+     */
+
+    /**
+     * Caller will open the interface and pass in the callback routines
+     * to the implemenation of this interface.
+     */
+    int   (*init)(const bt_vendor_callbacks_t* p_cb, unsigned char *local_bdaddr);
+
+    /**  Vendor specific operations */
+    int (*op)(bt_vendor_opcode_t opcode, void *param);
+
+    /** Closes the interface */
+    void  (*cleanup)(void);
+} bt_vendor_interface_t;
+
+
+/*
+ * External shared lib functions/data
+ */
+
+/* Entry point of DLib --
+ *      Vendor library needs to implement the body of bt_vendor_interface_t
+ *      structure and uses the below name as the variable name. HCI library
+ *      will use this symbol name to get address of the object through the
+ *      dlsym call.
+ */
+//extern const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE;
+
+#endif /* BT_VENDOR_LIB_H */
+

+ 25 - 0
components/bt/bluedroid/hci/include/buffer_allocator.h

@@ -0,0 +1,25 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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 _BUFFER_ALLOCATOR_H_
+
+#include "allocator.h"
+
+const allocator_t *buffer_allocator_get_interface();
+
+#endif /*_BUFFER_ALLOCATOR_H_*/

+ 85 - 0
components/bt/bluedroid/hci/include/hci_hal.h

@@ -0,0 +1,85 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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 _HCI_HAL_H_
+#define _HCI_HAL_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "bt_types.h"
+
+typedef enum {
+  DATA_TYPE_COMMAND = 1,
+  DATA_TYPE_ACL     = 2,
+  DATA_TYPE_SCO     = 3,
+  DATA_TYPE_EVENT   = 4
+} serial_data_type_t;
+
+typedef void (*packet_ready_cb)(BT_HDR *packet);
+
+typedef struct {
+  // Called when the HAL detects inbound data.
+  // Data |type| may be ACL, SCO, or EVENT.
+  // Executes in the context of the thread supplied to |init|.
+  packet_ready_cb packet_ready;
+
+  /*
+  // Called when the HAL detects inbound astronauts named Dave.
+  // HAL will deny all requests to open the pod bay doors after this.
+  dave_ready_cb dave_ready;
+  */
+} hci_hal_callbacks_t;
+
+typedef struct hci_hal_t {
+  // Initialize the HAL, with |upper_callbacks| and |upper_thread| to run in the context of.
+  //bool (*init)(const hci_hal_callbacks_t *upper_callbacks);
+
+  // Connect to the underlying hardware, and let data start flowing.
+  bool (*open)(const hci_hal_callbacks_t *upper_callbacks);
+  // Disconnect from the underlying hardware, and close the HAL.
+  // "Daisy, Daisy..."
+  void (*close)(void);
+
+  // Retrieve up to |max_size| bytes for ACL, SCO, or EVENT data packets into
+  // |buffer|, blocking until max_size bytes read if |block| is true.
+  // Only guaranteed to be correct in the context of a data_ready callback
+  // of the corresponding type.
+  //size_t (*read_data)(serial_data_type_t type, uint8_t *buffer, size_t max_size);
+  // The upper layer must call this to notify the HAL that it has finished
+  // reading a packet of the specified |type|. Underlying implementations that
+  // use shared channels for multiple data types depend on this to know when
+  // to reinterpret the data stream.
+  //void (*packet_finished)(serial_data_type_t type);
+  // Transmit COMMAND, ACL, or SCO data packets.
+  // |data| may not be NULL. |length| must be greater than zero.
+  //
+  // IMPORTANT NOTE:
+  // Depending on the underlying implementation, the byte right
+  // before the beginning of |data| may be borrowed during this call
+  // and then restored to its original value.
+  // This is safe in the bluetooth context, because there is always a buffer
+  // header that prefixes data you're sending.
+  uint16_t (*transmit_data)(serial_data_type_t type, uint8_t *data, uint16_t length);
+} hci_hal_t;
+
+
+// Gets the correct hal implementation, as compiled for.
+const hci_hal_t *hci_hal_h4_get_interface(void);
+
+#endif /* _HCI_HAL_H */

+ 31 - 0
components/bt/bluedroid/hci/include/hci_internals.h

@@ -0,0 +1,31 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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 _HCI_INTERNALS_H_
+#define _HCI_INTERNALS_H_
+
+// 2 bytes for opcode, 1 byte for parameter length (Volume 2, Part E, 5.4.1)
+#define HCI_COMMAND_PREAMBLE_SIZE 3
+// 2 bytes for handle, 2 bytes for data length (Volume 2, Part E, 5.4.2)
+#define HCI_ACL_PREAMBLE_SIZE 4
+// 2 bytes for handle, 1 byte for data length (Volume 2, Part E, 5.4.3)
+#define HCI_SCO_PREAMBLE_SIZE 3
+// 1 byte for event code, 1 byte for parameter length (Volume 2, Part E, 5.4.4)
+#define HCI_EVENT_PREAMBLE_SIZE 2
+
+#endif /* _HCI_INTERNALS_H_ */

+ 101 - 0
components/bt/bluedroid/hci/include/hci_layer.h

@@ -0,0 +1,101 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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 _HCI_LAYER_H_
+#define _HCI_LAYER_H_
+
+#include "bt_types.h"
+#include "allocator.h"
+#include "fixed_queue.h"
+#include "osi.h"
+
+///// LEGACY DEFINITIONS /////
+
+/* Message event mask across Host/Controller lib and stack */
+#define MSG_EVT_MASK                    0xFF00 /* eq. BT_EVT_MASK */
+#define MSG_SUB_EVT_MASK                0x00FF /* eq. BT_SUB_EVT_MASK */
+
+/* Message event ID passed from Host/Controller lib to stack */
+#define MSG_HC_TO_STACK_HCI_ERR        0x1300 /* eq. BT_EVT_TO_BTU_HCIT_ERR */
+#define MSG_HC_TO_STACK_HCI_ACL        0x1100 /* eq. BT_EVT_TO_BTU_HCI_ACL */
+#define MSG_HC_TO_STACK_HCI_SCO        0x1200 /* eq. BT_EVT_TO_BTU_HCI_SCO */
+#define MSG_HC_TO_STACK_HCI_EVT        0x1000 /* eq. BT_EVT_TO_BTU_HCI_EVT */
+#define MSG_HC_TO_STACK_L2C_SEG_XMIT   0x1900 /* eq. BT_EVT_TO_BTU_L2C_SEG_XMIT */
+
+/* Message event ID passed from stack to vendor lib */
+#define MSG_STACK_TO_HC_HCI_ACL        0x2100 /* eq. BT_EVT_TO_LM_HCI_ACL */
+#define MSG_STACK_TO_HC_HCI_SCO        0x2200 /* eq. BT_EVT_TO_LM_HCI_SCO */
+#define MSG_STACK_TO_HC_HCI_CMD        0x2000 /* eq. BT_EVT_TO_LM_HCI_CMD */
+
+/* Local Bluetooth Controller ID for BR/EDR */
+#define LOCAL_BR_EDR_CONTROLLER_ID      0
+
+///// END LEGACY DEFINITIONS /////
+
+typedef struct hci_hal_t hci_hal_t;
+//typedef struct btsnoop_t btsnoop_t;
+typedef struct controller_t controller_t;
+//typedef struct hci_inject_t hci_inject_t;
+typedef struct packet_fragmenter_t packet_fragmenter_t;
+//typedef struct vendor_t vendor_t;
+//typedef struct low_power_manager_t low_power_manager_t;
+
+//typedef unsigned char * bdaddr_t;
+typedef uint16_t command_opcode_t;
+
+/*
+typedef enum {
+  LPM_DISABLE,
+  LPM_ENABLE,
+  LPM_WAKE_ASSERT,
+  LPM_WAKE_DEASSERT
+} low_power_command_t;
+*/
+
+typedef void (*command_complete_cb)(BT_HDR *response, void *context);
+typedef void (*command_status_cb)(uint8_t status, BT_HDR *command, void *context);
+
+typedef struct hci_t {
+  // Send a low power command, if supported and the low power manager is enabled.
+  //void (*send_low_power_command)(low_power_command_t command);
+
+  // Do the postload sequence (call after the rest of the BT stack initializes).
+  void (*do_postload)(void);
+
+  // Set the queue to receive ACL data in
+  void (*set_data_queue)(fixed_queue_t *queue);
+
+  // Send a command through the HCI layer
+  void (*transmit_command)(
+      BT_HDR *command,
+      command_complete_cb complete_callback,
+      command_status_cb status_cb,
+      void *context
+  );
+
+  // Send some data downward through the HCI layer
+  void (*transmit_downward)(uint16_t type, void *data);
+} hci_t;
+
+const hci_t *hci_layer_get_interface();
+
+int hci_start_up(void);
+void hci_shut_down(void);
+
+
+#endif /* _HCI_LAYER_H_ */

+ 48 - 0
components/bt/bluedroid/hci/include/hci_packet_factory.h

@@ -0,0 +1,48 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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 _HCI_PACKET_FACTORY_H_
+#define _HCI_PACKET_FACTORY_H_
+
+#include "bt_types.h"
+#include "event_mask.h"
+
+typedef struct {
+  BT_HDR *(*make_reset)(void);
+  BT_HDR *(*make_read_buffer_size)(void);
+  BT_HDR *(*make_host_buffer_size)(uint16_t acl_size, uint8_t sco_size, uint16_t acl_count, uint16_t sco_count);
+  BT_HDR *(*make_read_local_version_info)(void);
+  BT_HDR *(*make_read_bd_addr)(void);
+  BT_HDR *(*make_read_local_supported_commands)(void);
+  BT_HDR *(*make_read_local_extended_features)(uint8_t page_number);
+  BT_HDR *(*make_write_simple_pairing_mode)(uint8_t mode);
+  BT_HDR *(*make_write_secure_connections_host_support)(uint8_t mode);
+  BT_HDR *(*make_set_event_mask)(const bt_event_mask_t *event_mask);
+  BT_HDR *(*make_ble_write_host_support)(uint8_t supported_host, uint8_t simultaneous_host);
+  BT_HDR *(*make_ble_read_white_list_size)(void);
+  BT_HDR *(*make_ble_read_buffer_size)(void);
+  BT_HDR *(*make_ble_read_supported_states)(void);
+  BT_HDR *(*make_ble_read_local_supported_features)(void);
+  BT_HDR *(*make_ble_read_resolving_list_size)(void);
+  BT_HDR *(*make_ble_read_suggested_default_data_length)(void);
+  BT_HDR *(*make_ble_set_event_mask)(const bt_event_mask_t *event_mask);
+} hci_packet_factory_t;
+
+const hci_packet_factory_t *hci_packet_factory_get_interface();
+
+#endif /*_HCI_PACKET_FACTORY_H_*/

+ 99 - 0
components/bt/bluedroid/hci/include/hci_packet_parser.h

@@ -0,0 +1,99 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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 _HCI_PACKET_PARSER_H_
+#define _HCI_PACKET_PARSER_H_
+
+#include <stdint.h>
+
+#include "allocator.h"
+#include "bdaddr.h"
+#include "bt_types.h"
+#include "device_features.h"
+//#include "features.h"
+#include "version.h"
+
+typedef struct {
+  void (*parse_generic_command_complete)(BT_HDR *response);
+
+  void (*parse_read_buffer_size_response)(
+    BT_HDR *response,
+    uint16_t *data_size_ptr,
+    uint16_t *acl_buffer_count_ptr
+  );
+
+  void (*parse_read_local_version_info_response)(
+    BT_HDR *response,
+    bt_version_t *bt_version_ptr
+  );
+
+  void (*parse_read_bd_addr_response)(
+    BT_HDR *response,
+    bt_bdaddr_t *address_ptr
+  );
+
+  void (*parse_read_local_supported_commands_response)(
+    BT_HDR *response,
+    uint8_t *supported_commands_ptr,
+    size_t supported_commands_length
+  );
+
+  void (*parse_read_local_extended_features_response)(
+    BT_HDR *response,
+    uint8_t *page_number_ptr,
+    uint8_t *max_page_number_ptr,
+    bt_device_features_t *feature_pages,
+    size_t feature_pages_count
+  );
+
+  void (*parse_ble_read_white_list_size_response)(
+    BT_HDR *response,
+    uint8_t *white_list_size_ptr
+  );
+
+  void (*parse_ble_read_buffer_size_response)(
+    BT_HDR *response,
+    uint16_t *data_size_ptr,
+    uint8_t *acl_buffer_count_ptr
+  );
+
+  void (*parse_ble_read_supported_states_response)(
+    BT_HDR *response,
+    uint8_t *supported_states,
+    size_t supported_states_size
+  );
+
+  void (*parse_ble_read_local_supported_features_response)(
+    BT_HDR *response,
+    bt_device_features_t *supported_features
+  );
+
+  void (*parse_ble_read_resolving_list_size_response) (
+    BT_HDR *response,
+    uint8_t *resolving_list_size_ptr
+  );
+
+  void (*parse_ble_read_suggested_default_data_length_response)(
+    BT_HDR *response,
+    uint16_t *ble_default_packet_length_ptr
+  );
+} hci_packet_parser_t;
+
+const hci_packet_parser_t *hci_packet_parser_get_interface();
+
+#endif /*_HCI_PACKET_PARSER_H_*/

+ 62 - 0
components/bt/bluedroid/hci/include/packet_fragmenter.h

@@ -0,0 +1,62 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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 _PACKET_FRAGMENTER_H_
+#define _PACKET_FRAGMENTER_H_
+
+#include "allocator.h"
+#include "bt_types.h"
+#include "hci_layer.h"
+
+typedef void (*transmit_finished_cb)(BT_HDR *packet, bool all_fragments_sent);
+typedef void (*packet_reassembled_cb)(BT_HDR *packet);
+typedef void (*packet_fragmented_cb)(BT_HDR *packet, bool send_transmit_finished);
+
+typedef struct {
+  // Called for every packet fragment.
+  packet_fragmented_cb fragmented;
+
+  // Called for every completely reassembled packet.
+  packet_reassembled_cb reassembled;
+
+  // Called when the fragmenter finishes sending all requested fragments,
+  // but the packet has not been entirely sent.
+  transmit_finished_cb transmit_finished;
+} packet_fragmenter_callbacks_t;
+
+typedef struct packet_fragmenter_t {
+  // Initialize the fragmenter, specifying the |result_callbacks|.
+  void (*init)(const packet_fragmenter_callbacks_t *result_callbacks);
+
+  // Release all resources associated with the fragmenter.
+  void (*cleanup)(void);
+
+  // CHeck if Current fragmenter is ongoing
+  BT_HDR *(*fragment_current_packet)(void);
+
+  // Fragments |packet| if necessary and hands off everything to the fragmented callback.
+  void (*fragment_and_dispatch)(BT_HDR *packet);
+  // If |packet| is a complete packet, forwards to the reassembled callback. Otherwise
+  // holds onto it until all fragments arrive, at which point the reassembled callback is called
+  // with the reassembled data.
+  void (*reassemble_and_dispatch)(BT_HDR *packet);
+} packet_fragmenter_t;
+
+const packet_fragmenter_t *packet_fragmenter_get_interface();
+
+#endif /* _PACKET_FRAGMENTER_H_ */

+ 225 - 0
components/bt/bluedroid/hci/packet_fragmenter.c

@@ -0,0 +1,225 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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.
+ *
+ ******************************************************************************/
+#include <string.h>
+#include "bt_trace.h"
+#include "bt_defs.h"
+#include "controller.h"
+#include "buffer_allocator.h"
+#include "hci_internals.h"
+#include "hci_layer.h"
+#include "packet_fragmenter.h"
+
+#include "hash_map.h"
+#include "hash_functions.h"
+
+
+
+#define APPLY_CONTINUATION_FLAG(handle) (((handle) & 0xCFFF) | 0x1000)
+#define APPLY_START_FLAG(handle) (((handle) & 0xCFFF) | 0x2000)
+#define SUB_EVENT(event) ((event) & MSG_SUB_EVT_MASK)
+#define GET_BOUNDARY_FLAG(handle) (((handle) >> 12) & 0x0003)
+
+#define HANDLE_MASK 0x0FFF
+#define START_PACKET_BOUNDARY 2
+#define CONTINUATION_PACKET_BOUNDARY 1
+#define L2CAP_HEADER_SIZE       4
+
+// TODO(zachoverflow): find good value for this
+#define NUMBER_OF_BUCKETS 42
+
+// Our interface and callbacks
+static const packet_fragmenter_t interface;
+static const allocator_t *buffer_allocator;
+static const controller_t *controller;
+static const packet_fragmenter_callbacks_t *callbacks;
+static hash_map_t *partial_packets;
+static BT_HDR *current_fragment_packet;
+
+static void init(const packet_fragmenter_callbacks_t *result_callbacks) {
+  current_fragment_packet = NULL;
+  callbacks = result_callbacks;
+  partial_packets = hash_map_new(NUMBER_OF_BUCKETS, hash_function_naive, NULL, NULL, NULL);
+}
+
+static void cleanup() {
+  if (partial_packets)
+    hash_map_free(partial_packets);
+}
+
+static BT_HDR *fragment_get_current_packet() {
+  return current_fragment_packet;
+}
+
+static void fragment_and_dispatch(BT_HDR *packet) {
+  uint16_t continuation_handle, current_pkt_size;
+  uint16_t max_data_size, max_packet_size, remaining_length;
+  uint16_t event = packet->event & MSG_EVT_MASK;
+  uint8_t *stream = packet->data + packet->offset;
+
+  assert(packet != NULL);
+
+  // We only fragment ACL packets
+  if (event != MSG_STACK_TO_HC_HCI_ACL) {
+    callbacks->fragmented(packet, true);
+    return;
+  }
+
+  max_data_size =
+    SUB_EVENT(packet->event) == LOCAL_BR_EDR_CONTROLLER_ID ?
+      controller->get_acl_data_size_classic() :
+      controller->get_acl_data_size_ble();
+
+  max_packet_size = max_data_size + HCI_ACL_PREAMBLE_SIZE;
+  remaining_length = packet->len;
+
+  STREAM_TO_UINT16(continuation_handle, stream);
+  continuation_handle = APPLY_CONTINUATION_FLAG(continuation_handle);
+  if (remaining_length > max_packet_size) {
+    current_fragment_packet = packet;
+    UINT16_TO_STREAM(stream, max_packet_size);
+    packet->len = max_packet_size;
+    callbacks->fragmented(packet, false);
+    packet->offset += max_data_size;
+    remaining_length -= max_data_size;
+    packet->len = remaining_length;
+
+    // Write the ACL header for the next fragment
+    stream = packet->data + packet->offset;
+    UINT16_TO_STREAM(stream, continuation_handle);
+    UINT16_TO_STREAM(stream, remaining_length - HCI_ACL_PREAMBLE_SIZE);
+
+    // Apparently L2CAP can set layer_specific to a max number of segments to transmit
+    if (packet->layer_specific) {
+      packet->layer_specific--;
+      if (packet->layer_specific == 0) {
+        packet->event = MSG_HC_TO_STACK_L2C_SEG_XMIT;
+        callbacks->transmit_finished(packet, false);
+        return;
+      }
+    }
+  } else {
+    current_fragment_packet = NULL;
+    callbacks->fragmented(packet, true);
+  }
+}
+
+static void reassemble_and_dispatch(BT_HDR *packet) {
+  if ((packet->event & MSG_EVT_MASK) == MSG_HC_TO_STACK_HCI_ACL) {
+    uint8_t *stream = packet->data + packet->offset;
+    uint16_t handle;
+    uint16_t l2cap_length;
+    uint16_t acl_length;
+    uint8_t boundary_flag;
+    BT_HDR *partial_packet;
+
+    STREAM_TO_UINT16(handle, stream);
+    STREAM_TO_UINT16(acl_length, stream);
+    STREAM_TO_UINT16(l2cap_length, stream);
+
+    assert(acl_length == packet->len - HCI_ACL_PREAMBLE_SIZE);
+
+    boundary_flag = GET_BOUNDARY_FLAG(handle);
+    handle = handle & HANDLE_MASK;
+
+    partial_packet = (BT_HDR *)hash_map_get(partial_packets, (void *)(uintptr_t)handle);
+
+    if (boundary_flag == START_PACKET_BOUNDARY) {
+      uint16_t full_length;
+      if (partial_packet) {
+        LOG_WARN("%s found unfinished packet for handle with start packet. Dropping old.", __func__);
+
+        hash_map_erase(partial_packets, (void *)(uintptr_t)handle);
+        buffer_allocator->free(partial_packet);
+      }
+
+      full_length = l2cap_length + L2CAP_HEADER_SIZE + HCI_ACL_PREAMBLE_SIZE;
+      if (full_length <= packet->len) {
+        if (full_length < packet->len)
+          LOG_WARN("%s found l2cap full length %d less than the hci length %d.", __func__, l2cap_length, packet->len);
+
+        callbacks->reassembled(packet);
+        return;
+      }
+
+      partial_packet = (BT_HDR *)buffer_allocator->alloc(full_length + sizeof(BT_HDR));
+      partial_packet->event = packet->event;
+      partial_packet->len = full_length;
+      partial_packet->offset = packet->len;
+
+      memcpy(partial_packet->data, packet->data, packet->len);
+
+      // Update the ACL data size to indicate the full expected length
+      stream = partial_packet->data;
+      STREAM_SKIP_UINT16(stream); // skip the handle
+      UINT16_TO_STREAM(stream, full_length - HCI_ACL_PREAMBLE_SIZE);
+
+      hash_map_set(partial_packets, (void *)(uintptr_t)handle, partial_packet);
+      // Free the old packet buffer, since we don't need it anymore
+      buffer_allocator->free(packet);
+    } else {
+      uint16_t projected_offset;
+      if (!partial_packet) {
+        LOG_WARN("%s got continuation for unknown packet. Dropping it.", __func__);
+        buffer_allocator->free(packet);
+        return;
+      }
+
+      packet->offset = HCI_ACL_PREAMBLE_SIZE;
+      projected_offset = partial_packet->offset + (packet->len - HCI_ACL_PREAMBLE_SIZE);
+      if (projected_offset > partial_packet->len) { // len stores the expected length
+        LOG_WARN("%s got packet which would exceed expected length of %d. Truncating.", __func__, partial_packet->len);
+        packet->len = partial_packet->len - partial_packet->offset;
+        projected_offset = partial_packet->len;
+      }
+
+      memcpy(
+        partial_packet->data + partial_packet->offset,
+        packet->data + packet->offset,
+        packet->len - packet->offset
+      );
+
+      // Free the old packet buffer, since we don't need it anymore
+      buffer_allocator->free(packet);
+      partial_packet->offset = projected_offset;
+
+      if (partial_packet->offset == partial_packet->len) {
+        hash_map_erase(partial_packets, (void *)(uintptr_t)handle);
+        partial_packet->offset = 0;
+        callbacks->reassembled(partial_packet);
+      }
+    }
+  } else {
+    callbacks->reassembled(packet);
+  }
+}
+
+static const packet_fragmenter_t interface = {
+  init,
+  cleanup,
+
+  fragment_get_current_packet,
+  fragment_and_dispatch,
+  reassemble_and_dispatch
+};
+
+const packet_fragmenter_t *packet_fragmenter_get_interface() {
+  controller = controller_get_interface();
+  buffer_allocator = buffer_allocator_get_interface();
+  return &interface;
+}
+

+ 31 - 0
components/bt/bluedroid/include/bt_common_types.h

@@ -0,0 +1,31 @@
+
+
+
+
+#ifndef _BT_COMMON_TYPES_H_
+#define _BT_COMMON_TYPES_H_
+
+#include "bt_defs.h"
+#include "thread.h"
+
+
+extern xQueueHandle xBtaApp1Queue;
+extern xTaskHandle xBtaApp1TaskHandle;
+
+typedef struct {
+    uint8_t client_if;
+    uint8_t filt_index;
+    uint8_t advertiser_state;
+    uint8_t advertiser_info_present;
+    uint8_t addr_type;
+    uint8_t tx_power;
+    int8_t rssi_value;
+    uint16_t time_stamp;
+    bt_bdaddr_t bd_addr;
+    uint8_t adv_pkt_len;
+    uint8_t *p_adv_pkt_data;
+    uint8_t scan_rsp_len;
+    uint8_t *p_scan_rsp_data;
+} btgatt_track_adv_info_t;
+
+#endif

+ 90 - 0
components/bt/bluedroid/include/bt_defs.h

@@ -0,0 +1,90 @@
+/**
+ * bt_defs.h    Defines useful API for whole Bluedroid
+ * 
+ */
+#ifndef _BT_DEFS_H_
+#define _BT_DEFS_H_
+
+#include <stdlib.h>
+#include <stdint.h>
+#include "bt_trace.h"
+
+#include "osi_arch.h"
+
+#define UNUSED(x)                   (void)(x)
+
+#ifndef SIZE_MAX
+#define SIZE_MAX                    128
+#endif
+/*Timer Related Defination*/
+
+#define alarm_timer_t               uint32_t
+#define alarm_timer_setfn(timer, cb, data)           \
+do {                                                 \
+} while (0)
+#define alarm_timer_arm(timer, to, periodic)         \
+do {                                                 \
+} while (0)
+#define alarm_timer_disarm(timer)                    \
+do {                                                 \
+} while (0)
+#define alarm_timer_now()             (0)
+
+
+/*Thread and locker related defination*/
+#define RTOS_SUPPORT
+#ifdef RTOS_SUPPORT
+#define pthread_mutex_t               osi_mutex_t
+#define pthread_mutex_init(mutex, a)  osi_mutex_new(mutex)
+#define pthread_mutex_destroy(mutex)  osi_mutex_free(mutex)
+#define pthread_mutex_lock            osi_mutex_lock
+#define pthread_mutex_unlock          osi_mutex_unlock
+#else
+#define pthread_mutex_t               uint8_t
+#define pthread_mutex_init(x1, x2)    
+#define pthread_mutex_destroy(mutex)  
+#define pthread_mutex_lock(mutex)     
+#define pthread_mutex_unlock(mutex)   
+#endif
+
+
+/*Bluetooth Address*/
+typedef struct {
+  uint8_t address[6];
+} __attribute__ ((__packed__)) bt_bdaddr_t;
+
+
+#ifndef CPU_LITTLE_ENDIAN
+#define CPU_LITTLE_ENDIAN
+#endif
+
+inline uint16_t swap_byte_16(uint16_t x) {
+  return (((x & 0x00ffU) << 8) |
+          ((x & 0xff00U) >> 8));
+}
+
+inline uint32_t swap_byte_32(uint32_t x) {
+  return (((x & 0x000000ffUL) << 24) |
+          ((x & 0x0000ff00UL) << 8) |
+          ((x & 0x00ff0000UL) >> 8) |
+          ((x & 0xff000000UL) >> 24));
+}
+
+inline uint16_t ntohs(uint16_t x) {
+#ifdef CPU_LITTLE_ENDIAN
+  return swap_byte_16(x);
+#else
+  return x;
+#endif
+}
+
+typedef struct vhci_host_callback {
+    void (*notify_host_send_available)(void);
+    int (*notify_host_recv)(uint8_t *data, uint16_t len);
+} vhci_host_callback_t;
+
+bool API_vhci_host_check_send_available(void);
+void API_vhci_host_send_packet(uint8_t *data, uint16_t len);
+void API_vhci_host_register_callback(const vhci_host_callback_t *callback);
+
+#endif /* _BT_DEFS_H_ */

+ 1769 - 0
components/bt/bluedroid/include/bt_target.h

@@ -0,0 +1,1769 @@
+/******************************************************************************
+ *
+ *  Copyright (c) 2014 The Android Open Source Project
+ *  Copyright (C) 1999-2012 Broadcom Corporation
+ *
+ *  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_TARGET_H
+#define BT_TARGET_H
+
+#ifndef BUILDCFG
+#define BUILDCFG
+#endif
+
+/*
+#if !defined(HAS_BDROID_BUILDCFG) && !defined(HAS_NO_BDROID_BUILDCFG)
+#error "An Android.mk file did not include bdroid_CFLAGS and possibly not bdorid_C_INCLUDES"
+#endif
+*/
+
+#ifdef HAS_BDROID_BUILDCFG
+#include "bdroid_buildcfg.h"
+#endif
+
+#include "bt_types.h"   /* This must be defined AFTER buildcfg.h */
+
+/* Include common GKI definitions used by this platform */
+#include "gki_target.h"
+#include "dyn_mem.h"    /* defines static and/or dynamic memory for components */
+
+//------------------Added from bdroid_buildcfg.h---------------------
+#ifndef L2CAP_EXTFEA_SUPPORTED_MASK
+#define L2CAP_EXTFEA_SUPPORTED_MASK (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE | L2CAP_EXTFEA_NO_CRC | L2CAP_EXTFEA_FIXED_CHNLS)
+#endif
+
+#ifndef BTUI_OPS_FORMATS
+#define BTUI_OPS_FORMATS (BTA_OP_VCARD21_MASK | BTA_OP_ANY_MASK)
+#endif
+
+#ifndef BTA_RFC_MTU_SIZE
+#define BTA_RFC_MTU_SIZE (L2CAP_MTU_SIZE-L2CAP_MIN_OFFSET-RFCOMM_DATA_OVERHEAD)
+#endif
+
+#ifndef SBC_NO_PCM_CPY_OPTION
+#define SBC_NO_PCM_CPY_OPTION FALSE
+#endif
+
+#ifndef BT_APP_DEMO
+#define BT_APP_DEMO TRUE
+#endif
+
+#ifndef BTIF_INCLUDED
+#define BTIF_INCLUDED FALSE
+#endif
+
+#ifndef BTA_INCLUDED
+#define BTA_INCLUDED TRUE
+#endif
+
+#ifndef BTA_PAN_INCLUDED
+#define BTA_PAN_INCLUDED FALSE//TRUE
+#endif
+
+#ifndef BTA_HH_INCLUDED
+#define BTA_HH_INCLUDED FALSE//TRUE
+#endif
+
+#ifndef BTA_HH_ROLE
+#define BTA_HH_ROLE BTA_MASTER_ROLE_PREF
+#endif
+
+#ifndef BTA_HH_LE_INCLUDED
+#define BTA_HH_LE_INCLUDED FALSE//TRUE
+#endif
+
+#ifndef BTA_AR_INCLUDED
+#define BTA_AR_INCLUDED FALSE//TRUE
+#endif
+
+#ifndef BTA_AV_INCLUDED
+#define BTA_AV_INCLUDED FALSE//TRUE
+#endif
+
+#ifndef BTA_AV_SINK_INCLUDED
+#define BTA_AV_SINK_INCLUDED FALSE//FALSE
+#endif
+
+#ifndef BTA_DISABLE_DELAY
+#define BTA_DISABLE_DELAY 200 /* in milliseconds */
+#endif
+
+// If the next wakeup time is less than this threshold, we should acquire
+// a wakelock instead of setting a wake alarm so we're not bouncing in
+// and out of suspend frequently.
+// in millisecond
+// TODO(zachoverflow): reinstate in alarm code
+#ifndef GKI_TIMER_INTERVAL_FOR_WAKELOCK
+#define GKI_TIMER_INTERVAL_FOR_WAKELOCK 3000
+#endif
+
+#ifndef BTA_SYS_TIMER_PERIOD
+#define BTA_SYS_TIMER_PERIOD  100
+#endif
+
+#ifndef SBC_FOR_EMBEDDED_LINUX
+#define SBC_FOR_EMBEDDED_LINUX TRUE
+#endif
+
+#ifndef AVDT_VERSION
+#define AVDT_VERSION  0x0102
+#endif
+
+#ifndef BTA_AG_AT_MAX_LEN
+#define BTA_AG_AT_MAX_LEN  512
+#endif
+
+#ifndef BTA_AVRCP_FF_RW_SUPPORT
+#define BTA_AVRCP_FF_RW_SUPPORT FALSE//TRUE
+#endif
+
+#ifndef BTA_AG_SCO_PKT_TYPES
+#define BTA_AG_SCO_PKT_TYPES  (BTM_SCO_LINK_ONLY_MASK | BTM_SCO_PKT_TYPES_MASK_EV3 |  BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | BTM_SCO_PKT_TYPES_MASK_NO_3_EV5)
+#endif
+
+#ifndef BTA_AV_RET_TOUT
+#define BTA_AV_RET_TOUT 15
+#endif
+
+#ifndef PORCHE_PAIRING_CONFLICT
+#define PORCHE_PAIRING_CONFLICT  TRUE
+#endif
+
+#ifndef BTA_AV_CO_CP_SCMS_T
+#define BTA_AV_CO_CP_SCMS_T  FALSE//FALSE
+#endif
+
+/* This feature is used to eanble interleaved scan*/
+#ifndef BTA_HOST_INTERLEAVE_SEARCH
+#define BTA_HOST_INTERLEAVE_SEARCH FALSE//FALSE
+#endif
+
+#ifndef BT_USE_TRACES
+#define BT_USE_TRACES  TRUE
+#endif
+
+#ifndef BT_TRACE_BTIF
+#define BT_TRACE_BTIF  TRUE
+#endif
+
+#ifndef BT_TRACE_VERBOSE
+#define BT_TRACE_VERBOSE  FALSE
+#endif
+
+#ifndef BTA_DM_SDP_DB_SIZE
+#define BTA_DM_SDP_DB_SIZE  8000
+#endif
+
+#ifndef HL_INCLUDED
+#define HL_INCLUDED  TRUE
+#endif
+
+#ifndef AG_VOICE_SETTINGS
+#define AG_VOICE_SETTINGS  HCI_DEFAULT_VOICE_SETTINGS
+#endif
+
+#ifndef BTIF_DM_OOB_TEST
+#define BTIF_DM_OOB_TEST  FALSE//TRUE
+#endif
+
+// How long to wait before activating sniff mode after entering the
+// idle state for FTS, OPS connections
+#ifndef BTA_FTS_OPS_IDLE_TO_SNIFF_DELAY_MS
+#define BTA_FTS_OPS_IDLE_TO_SNIFF_DELAY_MS 7000
+#endif
+
+//------------------End added from bdroid_buildcfg.h---------------------
+
+
+/******************************************************************************
+**
+** GKI Buffer Pools
+**
+******************************************************************************/
+
+/* Receives HCI events from the lower-layer. */
+#ifndef HCI_CMD_POOL_ID
+#define HCI_CMD_POOL_ID             GKI_POOL_ID_2
+#endif
+
+#ifndef HCI_CMD_POOL_BUF_SIZE
+#define HCI_CMD_POOL_BUF_SIZE       GKI_BUF2_SIZE
+#endif
+
+/* Receives ACL data packets from thelower-layer. */
+#ifndef HCI_ACL_POOL_ID
+#define HCI_ACL_POOL_ID             GKI_POOL_ID_3
+#endif
+
+/* Maximum number of buffers available for ACL receive data. */
+#ifndef HCI_ACL_BUF_MAX
+#define HCI_ACL_BUF_MAX             GKI_BUF3_MAX
+#endif
+
+/* Receives SCO data packets from the lower-layer. */
+#ifndef HCI_SCO_POOL_ID
+#define HCI_SCO_POOL_ID             GKI_POOL_ID_6
+#endif
+
+/* Sends SDP data packets. */
+#ifndef SDP_POOL_ID
+#define SDP_POOL_ID                 3
+#endif
+
+/* Sends RFCOMM command packets. */
+#ifndef RFCOMM_CMD_POOL_ID
+#define RFCOMM_CMD_POOL_ID          GKI_POOL_ID_2
+#endif
+
+/* Sends RFCOMM data packets. */
+#ifndef RFCOMM_DATA_POOL_ID
+#define RFCOMM_DATA_POOL_ID         GKI_POOL_ID_3
+#endif
+
+#ifndef RFCOMM_DATA_POOL_BUF_SIZE
+#define RFCOMM_DATA_POOL_BUF_SIZE   GKI_BUF3_SIZE
+#endif
+
+/* Sends L2CAP packets to the peer and HCI messages to the controller. */
+#ifndef L2CAP_CMD_POOL_ID
+#define L2CAP_CMD_POOL_ID           GKI_POOL_ID_2
+#endif
+
+/* Sends L2CAP segmented packets in ERTM mode */
+#ifndef L2CAP_FCR_TX_POOL_ID
+#define L2CAP_FCR_TX_POOL_ID        HCI_ACL_POOL_ID
+#endif
+
+/* Receives L2CAP segmented packets in ERTM mode */
+#ifndef L2CAP_FCR_RX_POOL_ID
+#define L2CAP_FCR_RX_POOL_ID        HCI_ACL_POOL_ID
+#endif
+
+/* Number of ACL buffers to assign to LE
+   if the HCI buffer pool is shared with BR/EDR */
+#ifndef L2C_DEF_NUM_BLE_BUF_SHARED
+#define L2C_DEF_NUM_BLE_BUF_SHARED      1
+#endif
+
+/* Used by BTM when it sends HCI commands to the controller. */
+#ifndef BTM_CMD_POOL_ID
+#define BTM_CMD_POOL_ID             GKI_POOL_ID_2
+#endif
+
+#ifndef OBX_LRG_DATA_POOL_SIZE
+#define OBX_LRG_DATA_POOL_SIZE      GKI_BUF4_SIZE
+#endif
+
+#ifndef OBX_LRG_DATA_POOL_ID
+#define OBX_LRG_DATA_POOL_ID        GKI_POOL_ID_4
+#endif
+/* Used to send data to L2CAP. */
+#ifndef GAP_DATA_POOL_ID
+#define GAP_DATA_POOL_ID            GKI_POOL_ID_3
+#endif
+
+#ifndef SPP_DB_SIZE
+#define SPP_DB_SIZE                 GKI_BUF3_SIZE
+#endif
+
+/* BNEP data and protocol messages. */
+#ifndef BNEP_POOL_ID
+#define BNEP_POOL_ID                GKI_POOL_ID_3
+#endif
+
+/* RPC pool for temporary trace message buffers. */
+#ifndef RPC_SCRATCH_POOL_ID
+#define RPC_SCRATCH_POOL_ID         GKI_POOL_ID_2
+#endif
+
+/* AVDTP pool for protocol messages */
+#ifndef AVDT_CMD_POOL_ID
+#define AVDT_CMD_POOL_ID            GKI_POOL_ID_2
+#endif
+
+/* AVDTP pool size for media packets in case of fragmentation */
+#ifndef AVDT_DATA_POOL_SIZE
+#define AVDT_DATA_POOL_SIZE         GKI_BUF3_SIZE
+#endif
+
+#ifndef PAN_POOL_ID
+#define PAN_POOL_ID                 GKI_POOL_ID_3
+/* Maximum amount of the shared buffer to allocate for PAN */
+#define PAN_POOL_MAX                (GKI_BUF3_MAX / 4)
+#endif
+
+/* AVCTP pool for protocol messages */
+#ifndef AVCT_CMD_POOL_ID
+#define AVCT_CMD_POOL_ID            GKI_POOL_ID_1
+#endif
+
+/* AVRCP pool for protocol messages */
+#ifndef AVRC_CMD_POOL_ID
+#define AVRC_CMD_POOL_ID            GKI_POOL_ID_1
+#endif
+
+/* AVRCP pool size for protocol messages */
+#ifndef AVRC_CMD_POOL_SIZE
+#define AVRC_CMD_POOL_SIZE          GKI_BUF1_SIZE
+#endif
+
+/* AVRCP Metadata pool for protocol messages */
+#ifndef AVRC_META_CMD_POOL_ID
+#define AVRC_META_CMD_POOL_ID       GKI_POOL_ID_2
+#endif
+
+/* AVRCP Metadata pool size for protocol messages */
+#ifndef AVRC_META_CMD_POOL_SIZE
+#define AVRC_META_CMD_POOL_SIZE     GKI_BUF2_SIZE
+#endif
+
+
+/* AVRCP buffer size for browsing channel messages */
+#ifndef AVRC_BROWSE_POOL_SIZE
+#define AVRC_BROWSE_POOL_SIZE     GKI_MAX_BUF_SIZE
+#endif
+
+#ifndef BTA_HL_LRG_DATA_POOL_ID
+#define BTA_HL_LRG_DATA_POOL_ID        GKI_POOL_ID_7
+#endif
+
+/* GATT Server Database pool ID */
+#ifndef GATT_DB_POOL_ID
+#define GATT_DB_POOL_ID                 GKI_POOL_ID_8
+#endif
+
+/* GATT Data sending buffer pool ID, use default ACL pool for fix channel data */
+#ifndef GATT_BUF_POOL_ID
+#define GATT_BUF_POOL_ID                HCI_ACL_POOL_ID
+#endif
+
+/******************************************************************************
+**
+** Lower Layer Interface
+**
+******************************************************************************/
+
+/* Macro for allocating buffer for HCI commands */
+#ifndef HCI_GET_CMD_BUF
+#if (!defined(HCI_USE_VARIABLE_SIZE_CMD_BUF) || (HCI_USE_VARIABLE_SIZE_CMD_BUF == FALSE))
+/* Allocate fixed-size buffer from HCI_CMD_POOL (default case) */
+#define HCI_GET_CMD_BUF(paramlen)    ((BT_HDR *)GKI_getpoolbuf (HCI_CMD_POOL_ID))
+#else
+/* Allocate smallest possible buffer (for platforms with limited RAM) */
+#define HCI_GET_CMD_BUF(paramlen)    ((BT_HDR *)GKI_getbuf ((UINT16)(BT_HDR_SIZE + HCIC_PREAMBLE_SIZE + (paramlen))))
+#endif
+#endif  /* HCI_GET_CMD_BUF */
+
+/******************************************************************************
+**
+** HCI Services (H4)
+**
+******************************************************************************/
+
+/* Use 2 second for low-resolution systems, override to 1 for high-resolution systems */
+#ifndef BT_1SEC_TIMEOUT
+#define BT_1SEC_TIMEOUT             (2)
+#endif
+
+/* Quick Timer */
+/* if L2CAP_FCR_INCLUDED is TRUE then it should have 100 millisecond resolution */
+/* if none of them is included then QUICK_TIMER_TICKS_PER_SEC is set to 0 to exclude quick timer */
+#ifndef QUICK_TIMER_TICKS_PER_SEC
+#define QUICK_TIMER_TICKS_PER_SEC   10       /* 100ms timer */
+#endif
+
+/******************************************************************************
+**
+** BTM
+**
+******************************************************************************/
+
+/* Cancel Inquiry on incoming SSP */
+#ifndef BTM_NO_SSP_ON_INQUIRY
+#define BTM_NO_SSP_ON_INQUIRY       FALSE
+#endif
+
+/* Includes SCO if TRUE */
+#ifndef BTM_SCO_INCLUDED
+#define BTM_SCO_INCLUDED            TRUE       /* TRUE includes SCO code */
+#endif
+
+/* Includes SCO if TRUE */
+#ifndef BTM_SCO_HCI_INCLUDED
+#define BTM_SCO_HCI_INCLUDED            FALSE       /* TRUE includes SCO over HCI code */
+#endif
+
+/* Includes WBS if TRUE */
+#ifndef BTM_WBS_INCLUDED
+#define BTM_WBS_INCLUDED            FALSE       /* TRUE includes WBS code */
+#endif
+
+/*  This is used to work around a controller bug that doesn't like Disconnect
+**  issued while there is a role switch in progress
+*/
+#ifndef BTM_DISC_DURING_RS
+#define BTM_DISC_DURING_RS TRUE
+#endif
+
+/**************************
+** Initial SCO TX credit
+*************************/
+/* max TX SCO data packet size */
+#ifndef BTM_SCO_DATA_SIZE_MAX
+#define BTM_SCO_DATA_SIZE_MAX       240
+#endif
+
+/* The size in bytes of the BTM inquiry database. 40 As Default */
+#ifndef BTM_INQ_DB_SIZE
+#define BTM_INQ_DB_SIZE             32
+#endif
+
+/* The default scan mode */
+#ifndef BTM_DEFAULT_SCAN_TYPE
+#define BTM_DEFAULT_SCAN_TYPE       BTM_SCAN_TYPE_INTERLACED
+#endif
+
+/* Should connections to unknown devices be allowed when not discoverable? */
+#ifndef BTM_ALLOW_CONN_IF_NONDISCOVER
+#define BTM_ALLOW_CONN_IF_NONDISCOVER   TRUE
+#endif
+
+/* Sets the Page_Scan_Window:  the length of time that the device is performing a page scan. */
+#ifndef BTM_DEFAULT_CONN_WINDOW
+#define BTM_DEFAULT_CONN_WINDOW     0x0012
+#endif
+
+/* Sets the Page_Scan_Activity:  the interval between the start of two consecutive page scans. */
+#ifndef BTM_DEFAULT_CONN_INTERVAL
+#define BTM_DEFAULT_CONN_INTERVAL   0x0800
+#endif
+
+/* When automatic inquiry scan is enabled, this sets the inquiry scan window. */
+#ifndef BTM_DEFAULT_DISC_WINDOW
+#define BTM_DEFAULT_DISC_WINDOW     0x0012
+#endif
+
+/* When automatic inquiry scan is enabled, this sets the inquiry scan interval. */
+#ifndef BTM_DEFAULT_DISC_INTERVAL
+#define BTM_DEFAULT_DISC_INTERVAL   0x0800
+#endif
+
+/* Default class of device
+* {SERVICE_CLASS, MAJOR_CLASS, MINOR_CLASS}
+*
+* SERVICE_CLASS:0x5A (Bit17 -Networking,Bit19 - Capturing,Bit20 -Object Transfer,Bit22 -Telephony)
+* MAJOR_CLASS:0x02 - PHONE
+* MINOR_CLASS:0x0C - SMART_PHONE
+*
+*/
+#ifndef BTA_DM_COD
+#define BTA_DM_COD {0x5A, 0x02, 0x0C}
+#endif
+
+/* The number of SCO links. */
+#ifndef BTM_MAX_SCO_LINKS
+#define BTM_MAX_SCO_LINKS           3
+#endif
+
+/* The preferred type of SCO links (2-eSCO, 0-SCO). */
+#ifndef BTM_DEFAULT_SCO_MODE
+#define BTM_DEFAULT_SCO_MODE        2
+#endif
+
+/* The number of security records for peer devices. 100 AS Default*/
+#ifndef BTM_SEC_MAX_DEVICE_RECORDS
+#define BTM_SEC_MAX_DEVICE_RECORDS  8 // 100
+#endif
+
+/* The number of security records for services. 32 AS Default*/
+#ifndef BTM_SEC_MAX_SERVICE_RECORDS
+#define BTM_SEC_MAX_SERVICE_RECORDS 8 // 32
+#endif
+
+/* If True, force a retrieval of remote device name for each bond in case it's changed */
+#ifndef BTM_SEC_FORCE_RNR_FOR_DBOND
+#define BTM_SEC_FORCE_RNR_FOR_DBOND  FALSE
+#endif
+
+/* Maximum device name length used in btm database. Up to 248*/
+#ifndef BTM_MAX_REM_BD_NAME_LEN
+#define BTM_MAX_REM_BD_NAME_LEN     64
+#endif
+
+/* Maximum local device name length stored btm database.
+  '0' disables storage of the local name in BTM */
+#ifndef BTM_MAX_LOC_BD_NAME_LEN
+#define BTM_MAX_LOC_BD_NAME_LEN     64
+#endif
+
+/* Fixed Default String. When this is defined as null string, the device's
+ * product model name is used as the default local name.
+ */
+#ifndef BTM_DEF_LOCAL_NAME
+#define BTM_DEF_LOCAL_NAME      ""
+#endif
+
+/* Maximum service name stored with security authorization (0 if not needed) */
+#ifndef BTM_SEC_SERVICE_NAME_LEN
+#define BTM_SEC_SERVICE_NAME_LEN    BT_MAX_SERVICE_NAME_LEN
+#endif
+
+/* Maximum length of the service name. */
+#ifndef BT_MAX_SERVICE_NAME_LEN
+#define BT_MAX_SERVICE_NAME_LEN     21
+#endif
+
+/* ACL buffer size in HCI Host Buffer Size command. */
+#ifndef BTM_ACL_BUF_SIZE
+#define BTM_ACL_BUF_SIZE            0
+#endif
+
+/* The maximum number of clients that can register with the power manager. */
+#ifndef BTM_MAX_PM_RECORDS
+#define BTM_MAX_PM_RECORDS          2
+#endif
+
+/* This is set to show debug trace messages for the power manager. */
+#ifndef BTM_PM_DEBUG
+#define BTM_PM_DEBUG                FALSE
+#endif
+
+/* This is set to TRUE if link is to be unparked due to BTM_CreateSCO API. */
+#ifndef BTM_SCO_WAKE_PARKED_LINK
+#define BTM_SCO_WAKE_PARKED_LINK    TRUE
+#endif
+
+/* If the user does not respond to security process requests within this many seconds,
+ * a negative response would be sent automatically.
+ * 30 is LMP response timeout value */
+#ifndef BTM_SEC_TIMEOUT_VALUE
+#define BTM_SEC_TIMEOUT_VALUE           35
+#endif
+
+/* Maximum number of callbacks that can be registered using BTM_RegisterForVSEvents */
+#ifndef BTM_MAX_VSE_CALLBACKS
+#define BTM_MAX_VSE_CALLBACKS           3
+#endif
+
+/******************************************
+**    Lisbon Features
+*******************************************/
+/* This is set to TRUE if the FEC is required for EIR packet. */
+#ifndef BTM_EIR_DEFAULT_FEC_REQUIRED
+#define BTM_EIR_DEFAULT_FEC_REQUIRED    TRUE
+#endif
+
+/* The IO capability of the local device (for Simple Pairing) */
+#ifndef BTM_LOCAL_IO_CAPS
+#define BTM_LOCAL_IO_CAPS               BTM_IO_CAP_IO
+#endif
+
+#ifndef BTM_LOCAL_IO_CAPS_BLE
+#define BTM_LOCAL_IO_CAPS_BLE           BTM_IO_CAP_KBDISP
+#endif
+
+/* The default MITM Protection Requirement (for Simple Pairing)
+ * Possible values are BTM_AUTH_SP_YES or BTM_AUTH_SP_NO */
+#ifndef BTM_DEFAULT_AUTH_REQ
+#define BTM_DEFAULT_AUTH_REQ            BTM_AUTH_SP_NO
+#endif
+
+/* The default MITM Protection Requirement for dedicated bonding using Simple Pairing
+ * Possible values are BTM_AUTH_AP_YES or BTM_AUTH_AP_NO */
+#ifndef BTM_DEFAULT_DD_AUTH_REQ
+#define BTM_DEFAULT_DD_AUTH_REQ            BTM_AUTH_AP_YES
+#endif
+
+/* Include Out-of-Band implementation for Simple Pairing */
+#ifndef BTM_OOB_INCLUDED
+#define BTM_OOB_INCLUDED                TRUE
+#endif
+
+/* TRUE to include Sniff Subrating */
+#ifndef BTM_SSR_INCLUDED
+#define BTM_SSR_INCLUDED                TRUE
+#endif
+
+/*************************
+** End of Lisbon Features
+**************************/
+
+/* 4.1/4.2 secure connections feature */
+#ifndef SC_MODE_INCLUDED
+#define SC_MODE_INCLUDED                TRUE
+#endif
+
+/* Used for conformance testing ONLY */
+#ifndef BTM_BLE_CONFORMANCE_TESTING
+#define BTM_BLE_CONFORMANCE_TESTING           FALSE
+#endif
+
+/******************************************************************************
+**
+** L2CAP
+**
+******************************************************************************/
+
+#ifndef L2CAP_CLIENT_INCLUDED
+#define L2CAP_CLIENT_INCLUDED FALSE
+#endif
+
+
+/* The maximum number of simultaneous links that L2CAP can support. Up to 7*/
+#ifndef MAX_ACL_CONNECTIONS
+#define MAX_L2CAP_LINKS             3
+#else
+#define MAX_L2CAP_LINKS             MAX_ACL_CONNECTIONS
+#endif
+
+/* The maximum number of simultaneous channels that L2CAP can support. Up to 16*/
+#ifndef MAX_L2CAP_CHANNELS
+#define MAX_L2CAP_CHANNELS          8
+#endif
+
+/* The maximum number of simultaneous applications that can register with L2CAP. */
+#ifndef MAX_L2CAP_CLIENTS
+#define MAX_L2CAP_CLIENTS           8
+#endif
+
+/* The number of seconds of link inactivity before a link is disconnected. */
+#ifndef L2CAP_LINK_INACTIVITY_TOUT
+#define L2CAP_LINK_INACTIVITY_TOUT  4
+#endif
+
+/* The number of seconds of link inactivity after bonding before a link is disconnected. */
+#ifndef L2CAP_BONDING_TIMEOUT
+#define L2CAP_BONDING_TIMEOUT       3
+#endif
+
+/* The time from the HCI connection complete to disconnect if no channel is established. */
+#ifndef L2CAP_LINK_STARTUP_TOUT
+#define L2CAP_LINK_STARTUP_TOUT     60
+#endif
+
+/* The L2CAP MTU; must be in accord with the HCI ACL pool size. */
+#ifndef L2CAP_MTU_SIZE
+#define L2CAP_MTU_SIZE              1691
+#endif
+
+/* The L2CAP MPS over Bluetooth; must be in accord with the FCR tx pool size and ACL down buffer size. */
+#ifndef L2CAP_MPS_OVER_BR_EDR
+#define L2CAP_MPS_OVER_BR_EDR       1010
+#endif
+
+/* If host flow control enabled, this is the number of buffers the controller can have unacknowledged. */
+#ifndef L2CAP_HOST_FC_ACL_BUFS
+#define L2CAP_HOST_FC_ACL_BUFS      20
+#endif
+
+/* This is set to enable L2CAP to  take the ACL link out of park mode when ACL data is to be sent. */
+#ifndef L2CAP_WAKE_PARKED_LINK
+#define L2CAP_WAKE_PARKED_LINK      TRUE
+#endif
+
+/* Whether link wants to be the master or the slave. */
+#ifndef L2CAP_DESIRED_LINK_ROLE
+#define L2CAP_DESIRED_LINK_ROLE     HCI_ROLE_SLAVE
+#endif
+
+/* Include Non-Flushable Packet Boundary Flag feature of Lisbon */
+#ifndef L2CAP_NON_FLUSHABLE_PB_INCLUDED
+#define L2CAP_NON_FLUSHABLE_PB_INCLUDED     TRUE
+#endif
+
+/* Minimum number of ACL credit for high priority link */
+#ifndef L2CAP_HIGH_PRI_MIN_XMIT_QUOTA
+#define L2CAP_HIGH_PRI_MIN_XMIT_QUOTA       5
+#endif
+
+/* used for monitoring HCI ACL credit management */
+#ifndef L2CAP_HCI_FLOW_CONTROL_DEBUG
+#define L2CAP_HCI_FLOW_CONTROL_DEBUG        TRUE
+#endif
+
+/* Used for calculating transmit buffers off of */
+#ifndef L2CAP_NUM_XMIT_BUFFS
+#define L2CAP_NUM_XMIT_BUFFS                HCI_ACL_BUF_MAX
+#endif
+
+/* Unicast Connectionless Data */
+#ifndef L2CAP_UCD_INCLUDED
+#define L2CAP_UCD_INCLUDED                  FALSE
+#endif
+
+/* Unicast Connectionless Data MTU */
+#ifndef L2CAP_UCD_MTU
+#define L2CAP_UCD_MTU                       L2CAP_MTU_SIZE
+#endif
+
+/* Unicast Connectionless Data Idle Timeout */
+#ifndef L2CAP_UCD_IDLE_TIMEOUT
+#define L2CAP_UCD_IDLE_TIMEOUT              2
+#endif
+
+/* Unicast Connectionless Data Idle Timeout */
+#ifndef L2CAP_UCD_CH_PRIORITY
+#define L2CAP_UCD_CH_PRIORITY               L2CAP_CHNL_PRIORITY_MEDIUM
+#endif
+
+/* Used for features using fixed channels; set to zero if no fixed channels supported (BLE, etc.) */
+/* Excluding L2CAP signaling channel and UCD */
+#ifndef L2CAP_NUM_FIXED_CHNLS
+#define L2CAP_NUM_FIXED_CHNLS               32
+#endif
+
+/* First fixed channel supported */
+#ifndef L2CAP_FIRST_FIXED_CHNL
+#define L2CAP_FIRST_FIXED_CHNL              4
+#endif
+
+#ifndef L2CAP_LAST_FIXED_CHNL
+#define L2CAP_LAST_FIXED_CHNL           (L2CAP_FIRST_FIXED_CHNL + L2CAP_NUM_FIXED_CHNLS - 1)
+#endif
+
+/* Round Robin service channels in link */
+#ifndef L2CAP_ROUND_ROBIN_CHANNEL_SERVICE
+#define L2CAP_ROUND_ROBIN_CHANNEL_SERVICE   TRUE
+#endif
+
+/* Used for calculating transmit buffers off of */
+#ifndef L2CAP_NUM_XMIT_BUFFS
+#define L2CAP_NUM_XMIT_BUFFS                HCI_ACL_BUF_MAX
+#endif
+
+/* used for monitoring eL2CAP data flow */
+#ifndef L2CAP_ERTM_STATS
+#define L2CAP_ERTM_STATS                    FALSE
+#endif
+
+/* Used for conformance testing ONLY:  When TRUE lets scriptwrapper overwrite info response */
+#ifndef L2CAP_CONFORMANCE_TESTING
+#define L2CAP_CONFORMANCE_TESTING           FALSE
+#endif
+
+/*
+ * Max bytes per connection to buffer locally before dropping the
+ * connection if local client does not receive it  - default is 1MB
+ */
+#ifndef L2CAP_MAX_RX_BUFFER
+#define L2CAP_MAX_RX_BUFFER                 0x100000
+#endif
+
+
+#ifndef TIMER_PARAM_TYPE
+#define TIMER_PARAM_TYPE    UINT32
+#endif
+
+/******************************************************************************
+**
+** BLE
+**
+******************************************************************************/
+
+#ifndef BLE_INCLUDED
+#define BLE_INCLUDED            TRUE
+#endif
+
+#ifndef BLE_ANDROID_CONTROLLER_SCAN_FILTER
+#define BLE_ANDROID_CONTROLLER_SCAN_FILTER            TRUE
+#endif
+
+#ifndef LOCAL_BLE_CONTROLLER_ID
+#define LOCAL_BLE_CONTROLLER_ID         (1)
+#endif
+
+/*
+ * Toggles support for general LE privacy features such as remote address
+ * resolution, local address rotation etc.
+ */
+#ifndef BLE_PRIVACY_SPT
+#define BLE_PRIVACY_SPT         TRUE
+#endif
+
+/*
+ * Enables or disables support for local privacy (ex. address rotation)
+ */
+#ifndef BLE_LOCAL_PRIVACY_ENABLED
+#define BLE_LOCAL_PRIVACY_ENABLED         TRUE
+#endif
+
+/*
+ * Toggles support for vendor specific extensions such as RPA offloading,
+ * feature discovery, multi-adv etc.
+ */
+#ifndef BLE_VND_INCLUDED
+#define BLE_VND_INCLUDED        FALSE
+#endif
+
+#ifndef BTM_BLE_ADV_TX_POWER
+#define BTM_BLE_ADV_TX_POWER {-21, -15, -7, 1, 9}
+#endif
+
+
+#ifndef BLE_BATCH_SCAN_INCLUDED
+#define BLE_BATCH_SCAN_INCLUDED  TRUE
+#endif
+
+/******************************************************************************
+**
+** ATT/GATT Protocol/Profile Settings
+**
+******************************************************************************/
+#ifndef GATT_INCLUDED
+#if BLE_INCLUDED == TRUE
+#define GATT_INCLUDED TRUE
+#else
+#define GATT_INCLUDED FALSE
+#endif
+#endif
+
+#ifndef BTA_GATT_INCLUDED
+#if BLE_INCLUDED == TRUE
+#define BTA_GATT_INCLUDED TRUE
+#else
+#define BTA_GATT_INCLUDED FALSE
+#endif
+#endif
+
+#if BTA_GATT_INCLUDED == TRUE && BLE_INCLUDED == FALSE
+#error "can't have GATT without BLE"
+#endif
+
+#ifndef BLE_LLT_INCLUDED
+#define BLE_LLT_INCLUDED    TRUE
+#endif
+
+#ifndef ATT_INCLUDED
+#define ATT_INCLUDED         TRUE
+#endif
+
+#ifndef ATT_DEBUG
+#define ATT_DEBUG           FALSE//TRUE
+#endif
+
+#ifndef BLE_PERIPHERAL_MODE_SUPPORT
+#define BLE_PERIPHERAL_MODE_SUPPORT  TRUE
+#endif
+
+#ifndef BLE_DELAY_REQUEST_ENC
+/* This flag is to work around IPHONE problem, We need to wait for iPhone ready
+   before send encryption request to iPhone */
+#define BLE_DELAY_REQUEST_ENC        FALSE
+#endif
+
+#ifndef GAP_TRANSPORT_SUPPORTED
+#define GAP_TRANSPORT_SUPPORTED      GATT_TRANSPORT_LE_BR_EDR
+#endif
+
+#ifndef GATTP_TRANSPORT_SUPPORTED
+#define GATTP_TRANSPORT_SUPPORTED    GATT_TRANSPORT_LE_BR_EDR
+#endif
+
+#ifndef GATT_MAX_SR_PROFILES
+#define GATT_MAX_SR_PROFILES        8 /* max is 32 */
+#endif
+
+#ifndef GATT_MAX_APPS
+#define GATT_MAX_APPS            8 /* MAX is 32 note: 2 apps used internally GATT and GAP */
+#endif
+
+#ifndef GATT_MAX_PHY_CHANNEL
+#define GATT_MAX_PHY_CHANNEL        7
+#endif
+
+/* Used for conformance testing ONLY */
+#ifndef GATT_CONFORMANCE_TESTING
+#define GATT_CONFORMANCE_TESTING           FALSE
+#endif
+
+/* number of background connection device allowence, ideally to be the same as WL size
+*/
+#ifndef GATT_MAX_BG_CONN_DEV
+#define GATT_MAX_BG_CONN_DEV        8 /*MAX is 32*/
+#endif
+
+/******************************************************************************
+**
+** SMP
+**
+******************************************************************************/
+#ifndef SMP_INCLUDED
+#if BLE_INCLUDED == TRUE
+#define SMP_INCLUDED         TRUE
+#else
+#define SMP_INCLUDED         FALSE
+#endif
+#endif
+
+#if SMP_INCLUDED == TRUE && BLE_INCLUDED == FALSE
+#error "can't have SMP without BLE"
+#endif
+
+#ifndef SMP_DEBUG
+#define SMP_DEBUG            FALSE
+#endif
+
+#ifndef SMP_DEFAULT_AUTH_REQ
+#define SMP_DEFAULT_AUTH_REQ    SMP_AUTH_NB_ENC_ONLY
+#endif
+
+#ifndef SMP_MAX_ENC_KEY_SIZE
+#define SMP_MAX_ENC_KEY_SIZE    16
+#endif
+
+#ifndef SMP_MIN_ENC_KEY_SIZE
+#define SMP_MIN_ENC_KEY_SIZE    7
+#endif
+
+/* minimum link timeout after SMP pairing is done, leave room for key exchange
+   and racing condition for the following service connection.
+   Prefer greater than 0 second, and no less than default inactivity link idle
+   timer(L2CAP_LINK_INACTIVITY_TOUT) in l2cap) */
+#ifndef SMP_LINK_TOUT_MIN
+#if (L2CAP_LINK_INACTIVITY_TOUT > 0)
+#define SMP_LINK_TOUT_MIN               L2CAP_LINK_INACTIVITY_TOUT
+#else
+#define SMP_LINK_TOUT_MIN               2
+#endif
+#endif
+/******************************************************************************
+**
+** SDP
+**
+******************************************************************************/
+
+#ifndef SDP_INCLUDED
+#define SDP_INCLUDED                TRUE
+#endif
+
+/* This is set to enable SDP server functionality. */
+#ifndef SDP_SERVER_ENABLED
+#if SDP_INCLUDED == TRUE
+#define SDP_SERVER_ENABLED          TRUE
+#else
+#define SDP_SERVER_ENABLED          FALSE
+#endif
+#endif
+
+/* This is set to enable SDP client functionality. */
+#ifndef SDP_CLIENT_ENABLED
+#if SDP_INCLUDED == TRUE
+#define SDP_CLIENT_ENABLED          TRUE
+#else
+#define SDP_CLIENT_ENABLED          FALSE
+#endif
+#endif
+
+/* The maximum number of SDP records the server can support. */
+#ifndef SDP_MAX_RECORDS
+#define SDP_MAX_RECORDS             15  /*max is 30*/
+#endif
+
+/* The maximum number of attributes in each record. */
+#ifndef SDP_MAX_REC_ATTR
+#define SDP_MAX_REC_ATTR            25
+#endif
+
+#ifndef SDP_MAX_PAD_LEN
+#define SDP_MAX_PAD_LEN             600
+#endif
+
+/* The maximum length, in bytes, of an attribute. */
+#ifndef SDP_MAX_ATTR_LEN
+#define SDP_MAX_ATTR_LEN            400
+#endif
+
+/* The maximum number of attribute filters supported by SDP databases. */
+#ifndef SDP_MAX_ATTR_FILTERS
+#define SDP_MAX_ATTR_FILTERS        15
+#endif
+
+/* The maximum number of UUID filters supported by SDP databases. */
+#ifndef SDP_MAX_UUID_FILTERS
+#define SDP_MAX_UUID_FILTERS        3
+#endif
+
+/* The maximum number of record handles retrieved in a search. */
+#ifndef SDP_MAX_DISC_SERVER_RECS
+#define SDP_MAX_DISC_SERVER_RECS    21
+#endif
+
+/* The size of a scratchpad buffer, in bytes, for storing the response to an attribute request. */
+#ifndef SDP_MAX_LIST_BYTE_COUNT
+#define SDP_MAX_LIST_BYTE_COUNT     4096
+#endif
+
+/* The maximum number of parameters in an SDP protocol element. */
+#ifndef SDP_MAX_PROTOCOL_PARAMS
+#define SDP_MAX_PROTOCOL_PARAMS     2
+#endif
+
+/* The maximum number of simultaneous client and server connections. */
+#ifndef SDP_MAX_CONNECTIONS
+#define SDP_MAX_CONNECTIONS         2 // 4
+#endif
+
+/* The MTU size for the L2CAP configuration. */
+#ifndef SDP_MTU_SIZE
+#define SDP_MTU_SIZE                672
+#endif
+
+/* The flush timeout for the L2CAP configuration. */
+#ifndef SDP_FLUSH_TO
+#define SDP_FLUSH_TO                0xFFFF
+#endif
+
+/* The name for security authorization. */
+#ifndef SDP_SERVICE_NAME
+#define SDP_SERVICE_NAME            "Service Discovery"
+#endif
+
+/* The security level for BTM. */
+#ifndef SDP_SECURITY_LEVEL
+#define SDP_SECURITY_LEVEL          BTM_SEC_NONE
+#endif
+
+/******************************************************************************
+**
+** RFCOMM
+**
+******************************************************************************/
+#ifndef RFCOMM_INCLUDED
+#define RFCOMM_INCLUDED             FALSE
+#endif
+
+/* The maximum number of ports supported. */
+#ifndef MAX_RFC_PORTS
+#define MAX_RFC_PORTS               16 /*max is 30*/
+#endif
+
+/* The maximum simultaneous links to different devices. */
+#ifndef MAX_ACL_CONNECTIONS
+#define MAX_BD_CONNECTIONS          3 /*max is 7*/
+#else
+#define MAX_BD_CONNECTIONS          MAX_ACL_CONNECTIONS
+#endif
+
+/* The port receive queue low watermark level, in bytes. */
+#ifndef PORT_RX_LOW_WM
+#define PORT_RX_LOW_WM              (BTA_RFC_MTU_SIZE * PORT_RX_BUF_LOW_WM)
+#endif
+
+/* The port receive queue high watermark level, in bytes. */
+#ifndef PORT_RX_HIGH_WM
+#define PORT_RX_HIGH_WM             (BTA_RFC_MTU_SIZE * PORT_RX_BUF_HIGH_WM)
+#endif
+
+/* The port receive queue critical watermark level, in bytes. */
+#ifndef PORT_RX_CRITICAL_WM
+#define PORT_RX_CRITICAL_WM         (BTA_RFC_MTU_SIZE * PORT_RX_BUF_CRITICAL_WM)
+#endif
+
+/* The port receive queue low watermark level, in number of buffers. */
+#ifndef PORT_RX_BUF_LOW_WM
+#define PORT_RX_BUF_LOW_WM          4
+#endif
+
+/* The port receive queue high watermark level, in number of buffers. */
+#ifndef PORT_RX_BUF_HIGH_WM
+#define PORT_RX_BUF_HIGH_WM         10
+#endif
+
+/* The port receive queue critical watermark level, in number of buffers. */
+#ifndef PORT_RX_BUF_CRITICAL_WM
+#define PORT_RX_BUF_CRITICAL_WM     15
+#endif
+
+/* The port transmit queue high watermark level, in bytes. */
+#ifndef PORT_TX_HIGH_WM
+#define PORT_TX_HIGH_WM             (BTA_RFC_MTU_SIZE * PORT_TX_BUF_HIGH_WM)
+#endif
+
+/* The port transmit queue critical watermark level, in bytes. */
+#ifndef PORT_TX_CRITICAL_WM
+#define PORT_TX_CRITICAL_WM         (BTA_RFC_MTU_SIZE * PORT_TX_BUF_CRITICAL_WM)
+#endif
+
+/* The port transmit queue high watermark level, in number of buffers. */
+#ifndef PORT_TX_BUF_HIGH_WM
+#define PORT_TX_BUF_HIGH_WM         10
+#endif
+
+/* The port transmit queue high watermark level, in number of buffers. */
+#ifndef PORT_TX_BUF_CRITICAL_WM
+#define PORT_TX_BUF_CRITICAL_WM     15
+#endif
+
+/* The RFCOMM multiplexer preferred flow control mechanism. */
+#ifndef PORT_FC_DEFAULT
+#define PORT_FC_DEFAULT             PORT_FC_CREDIT
+#endif
+
+/* The maximum number of credits receiver sends to peer when using credit-based flow control. */
+#ifndef PORT_CREDIT_RX_MAX
+#define PORT_CREDIT_RX_MAX          16
+#endif
+
+/* The credit low watermark level. */
+#ifndef PORT_CREDIT_RX_LOW
+#define PORT_CREDIT_RX_LOW          8
+#endif
+
+/* if application like BTA, Java or script test engine is running on other than BTU thread, */
+/* PORT_SCHEDULE_LOCK shall be defined as GKI_sched_lock() or GKI_disable() */
+#ifndef PORT_SCHEDULE_LOCK
+#define PORT_SCHEDULE_LOCK          GKI_disable()
+#endif
+
+/* if application like BTA, Java or script test engine is running on other than BTU thread, */
+/* PORT_SCHEDULE_LOCK shall be defined as GKI_sched_unlock() or GKI_enable() */
+#ifndef PORT_SCHEDULE_UNLOCK
+#define PORT_SCHEDULE_UNLOCK        GKI_enable()
+#endif
+
+/******************************************************************************
+**
+** OBEX
+**
+******************************************************************************/
+#define OBX_14_INCLUDED             FALSE
+
+/* The maximum number of registered servers. */
+#ifndef OBX_NUM_SERVERS
+#define OBX_NUM_SERVERS             12
+#endif
+
+/* The maximum number of active clients. */
+#ifndef OBX_NUM_CLIENTS
+#define OBX_NUM_CLIENTS             8
+#endif
+
+/* This option is application when OBX_14_INCLUDED=TRUE
+   Pool ID where to reassemble the SDU.
+   This Pool will allow buffers to be used that are larger than
+   the L2CAP_MAX_MTU. */
+#ifndef OBX_USER_RX_POOL_ID
+#define OBX_USER_RX_POOL_ID     OBX_LRG_DATA_POOL_ID
+#endif
+
+/* This option is application when OBX_14_INCLUDED=TRUE
+   Pool ID where to hold the SDU.
+   This Pool will allow buffers to be used that are larger than
+   the L2CAP_MAX_MTU. */
+#ifndef OBX_USER_TX_POOL_ID
+#define OBX_USER_TX_POOL_ID     OBX_LRG_DATA_POOL_ID
+#endif
+
+/* This option is application when OBX_14_INCLUDED=TRUE
+GKI Buffer Pool ID used to hold MPS segments during SDU reassembly
+*/
+#ifndef OBX_FCR_RX_POOL_ID
+#define OBX_FCR_RX_POOL_ID      HCI_ACL_POOL_ID
+#endif
+
+/* This option is application when OBX_14_INCLUDED=TRUE
+GKI Buffer Pool ID used to hold MPS segments used in (re)transmissions.
+L2CAP_DEFAULT_ERM_POOL_ID is specified to use the HCI ACL data pool.
+Note:  This pool needs to have enough buffers to hold two times the window size negotiated
+ in the L2CA_SetFCROptions (2 * tx_win_size)  to allow for retransmissions.
+ The size of each buffer must be able to hold the maximum MPS segment size passed in
+ L2CA_SetFCROptions plus BT_HDR (8) + HCI preamble (4) + L2CAP_MIN_OFFSET (11 - as of BT 2.1 + EDR Spec).
+*/
+#ifndef OBX_FCR_TX_POOL_ID
+#define OBX_FCR_TX_POOL_ID      HCI_ACL_POOL_ID
+#endif
+
+/* This option is application when OBX_14_INCLUDED=TRUE
+Size of the transmission window when using enhanced retransmission mode. Not used
+in basic and streaming modes. Range: 1 - 63
+*/
+#ifndef OBX_FCR_OPT_TX_WINDOW_SIZE_BR_EDR
+#define OBX_FCR_OPT_TX_WINDOW_SIZE_BR_EDR       20
+#endif
+
+/* This option is application when OBX_14_INCLUDED=TRUE
+Number of transmission attempts for a single I-Frame before taking
+Down the connection. Used In ERTM mode only. Value is Ignored in basic and
+Streaming modes.
+Range: 0, 1-0xFF
+0 - infinite retransmissions
+1 - single transmission
+*/
+#ifndef OBX_FCR_OPT_MAX_TX_B4_DISCNT
+#define OBX_FCR_OPT_MAX_TX_B4_DISCNT    20
+#endif
+
+/* This option is application when OBX_14_INCLUDED=TRUE
+Retransmission Timeout
+Range: Minimum 2000 (2 secs) on BR/EDR when supporting PBF.
+ */
+#ifndef OBX_FCR_OPT_RETX_TOUT
+#define OBX_FCR_OPT_RETX_TOUT           2000
+#endif
+
+/* This option is application when OBX_14_INCLUDED=TRUE
+Monitor Timeout
+Range: Minimum 12000 (12 secs) on BR/EDR when supporting PBF.
+*/
+#ifndef OBX_FCR_OPT_MONITOR_TOUT
+#define OBX_FCR_OPT_MONITOR_TOUT        12000
+#endif
+
+/* This option is application when OBX_14_INCLUDED=TRUE
+Maximum PDU payload size.
+Suggestion: The maximum amount of data that will fit into a 3-DH5 packet.
+Range: 2 octets
+*/
+#ifndef OBX_FCR_OPT_MAX_PDU_SIZE
+#define OBX_FCR_OPT_MAX_PDU_SIZE        L2CAP_MPS_OVER_BR_EDR
+#endif
+
+
+/******************************************************************************
+**
+** BNEP
+**
+******************************************************************************/
+
+#ifndef BNEP_INCLUDED
+#define BNEP_INCLUDED               FALSE//TRUE
+#endif
+
+/* BNEP status API call is used mainly to get the L2CAP handle */
+#ifndef BNEP_SUPPORTS_STATUS_API
+#define BNEP_SUPPORTS_STATUS_API            FALSE//TRUE
+#endif
+
+/*
+** When BNEP connection changes roles after the connection is established
+** we will do an authentication check again on the new role
+*/
+#ifndef BNEP_DO_AUTH_FOR_ROLE_SWITCH
+#define BNEP_DO_AUTH_FOR_ROLE_SWITCH        FALSE//TRUE
+#endif
+
+
+/* Maximum number of protocol filters supported. */
+#ifndef BNEP_MAX_PROT_FILTERS
+#define BNEP_MAX_PROT_FILTERS       5
+#endif
+
+/* Maximum number of multicast filters supported. */
+#ifndef BNEP_MAX_MULTI_FILTERS
+#define BNEP_MAX_MULTI_FILTERS      5
+#endif
+
+/* Minimum MTU size. */
+#ifndef BNEP_MIN_MTU_SIZE
+#define BNEP_MIN_MTU_SIZE           L2CAP_MTU_SIZE
+#endif
+
+/* Preferred MTU size. */
+#ifndef BNEP_MTU_SIZE
+#define BNEP_MTU_SIZE               BNEP_MIN_MTU_SIZE
+#endif
+
+/* Maximum number of buffers allowed in transmit data queue. */
+#ifndef BNEP_MAX_XMITQ_DEPTH
+#define BNEP_MAX_XMITQ_DEPTH        20
+#endif
+
+/* Maximum number BNEP of connections supported. */
+#ifndef BNEP_MAX_CONNECTIONS
+#define BNEP_MAX_CONNECTIONS        7
+#endif
+
+
+/******************************************************************************
+**
+** AVDTP
+**
+******************************************************************************/
+
+#ifndef AVDT_INCLUDED
+#define AVDT_INCLUDED               FALSE//TRUE
+#endif
+
+/* Include reporting capability in AVDTP */
+#ifndef AVDT_REPORTING
+#define AVDT_REPORTING              FALSE//TRUE
+#endif
+
+/* Include multiplexing capability in AVDTP */
+#ifndef AVDT_MULTIPLEXING
+#define AVDT_MULTIPLEXING           FALSE//TRUE
+#endif
+
+/* Number of simultaneous links to different peer devices. */
+#ifndef AVDT_NUM_LINKS
+#define AVDT_NUM_LINKS              2
+#endif
+
+/* Number of simultaneous stream endpoints. */
+#ifndef AVDT_NUM_SEPS
+#define AVDT_NUM_SEPS               3
+#endif
+
+/* Number of transport channels setup per media stream(audio or video) */
+#ifndef AVDT_NUM_CHANNELS
+
+#if AVDT_REPORTING == TRUE
+/* signaling, media and reporting channels */
+#define AVDT_NUM_CHANNELS   3
+#else
+/* signaling and media channels */
+#define AVDT_NUM_CHANNELS   2
+#endif  // AVDT_REPORTING
+
+#endif  // AVDT_NUM_CHANNELS
+
+/* Number of transport channels setup by AVDT for all media streams
+ * AVDT_NUM_CHANNELS * Number of simultaneous streams.
+ */
+#ifndef AVDT_NUM_TC_TBL
+#define AVDT_NUM_TC_TBL             6
+#endif
+
+/* Maximum size in bytes of the codec capabilities information element. */
+#ifndef AVDT_CODEC_SIZE
+#define AVDT_CODEC_SIZE             10
+#endif
+
+/* Maximum size in bytes of the content protection information element. */
+#ifndef AVDT_PROTECT_SIZE
+#define AVDT_PROTECT_SIZE           90
+#endif
+
+/* Maximum number of GKI buffers in the fragment queue (for video frames).
+ * Must be less than the number of buffers in the buffer pool of size AVDT_DATA_POOL_SIZE */
+#ifndef AVDT_MAX_FRAG_COUNT
+#define AVDT_MAX_FRAG_COUNT         15
+#endif
+
+/******************************************************************************
+**
+** PAN
+**
+******************************************************************************/
+
+#ifndef PAN_INCLUDED
+#define PAN_INCLUDED                     FALSE//TRUE
+#endif
+
+/* This will enable the PANU role */
+#ifndef PAN_SUPPORTS_ROLE_PANU
+#define PAN_SUPPORTS_ROLE_PANU              FALSE//TRUE
+#endif
+
+/* This will enable the GN role */
+#ifndef PAN_SUPPORTS_ROLE_GN
+#define PAN_SUPPORTS_ROLE_GN                FALSE//TRUE
+#endif
+
+/* This will enable the NAP role */
+#ifndef PAN_SUPPORTS_ROLE_NAP
+#define PAN_SUPPORTS_ROLE_NAP               FALSE//TRUE
+#endif
+
+/* This is just for debugging purposes */
+#ifndef PAN_SUPPORTS_DEBUG_DUMP
+#define PAN_SUPPORTS_DEBUG_DUMP             FALSE//TRUE
+#endif
+
+/* Maximum number of PAN connections allowed */
+#ifndef MAX_PAN_CONNS
+#define MAX_PAN_CONNS                    7
+#endif
+
+/* Default service name for NAP role */
+#ifndef PAN_NAP_DEFAULT_SERVICE_NAME
+#define PAN_NAP_DEFAULT_SERVICE_NAME    "Network Access Point Service"
+#endif
+
+/* Default service name for GN role */
+#ifndef PAN_GN_DEFAULT_SERVICE_NAME
+#define PAN_GN_DEFAULT_SERVICE_NAME     "Group Network Service"
+#endif
+
+/* Default service name for PANU role */
+#ifndef PAN_PANU_DEFAULT_SERVICE_NAME
+#define PAN_PANU_DEFAULT_SERVICE_NAME   "PAN User Service"
+#endif
+
+/* Default description for NAP role service */
+#ifndef PAN_NAP_DEFAULT_DESCRIPTION
+#define PAN_NAP_DEFAULT_DESCRIPTION     "NAP"
+#endif
+
+/* Default description for GN role service */
+#ifndef PAN_GN_DEFAULT_DESCRIPTION
+#define PAN_GN_DEFAULT_DESCRIPTION      "GN"
+#endif
+
+/* Default description for PANU role service */
+#ifndef PAN_PANU_DEFAULT_DESCRIPTION
+#define PAN_PANU_DEFAULT_DESCRIPTION    "PANU"
+#endif
+
+/* Default Security level for PANU role. */
+#ifndef PAN_PANU_SECURITY_LEVEL
+#define PAN_PANU_SECURITY_LEVEL          0
+#endif
+
+/* Default Security level for GN role. */
+#ifndef PAN_GN_SECURITY_LEVEL
+#define PAN_GN_SECURITY_LEVEL            0
+#endif
+
+/* Default Security level for NAP role. */
+#ifndef PAN_NAP_SECURITY_LEVEL
+#define PAN_NAP_SECURITY_LEVEL           0
+#endif
+
+/******************************************************************************
+**
+** GAP
+**
+******************************************************************************/
+
+#ifndef GAP_INCLUDED
+#define GAP_INCLUDED                TRUE
+#endif
+
+/* This is set to enable use of GAP L2CAP connections. */
+#ifndef GAP_CONN_INCLUDED
+#if GAP_INCLUDED == TRUE
+#define GAP_CONN_INCLUDED           TRUE
+#else
+#define GAP_CONN_INCLUDED           FALSE
+#endif
+#endif
+
+/* This is set to enable posting event for data write */
+#ifndef GAP_CONN_POST_EVT_INCLUDED
+#define GAP_CONN_POST_EVT_INCLUDED  FALSE
+#endif
+
+/* The maximum number of simultaneous GAP L2CAP connections. */
+#ifndef GAP_MAX_CONNECTIONS
+#define GAP_MAX_CONNECTIONS         10 // 30
+#endif
+
+/* keep the raw data received from SDP server in database. */
+#ifndef SDP_RAW_DATA_INCLUDED
+#define SDP_RAW_DATA_INCLUDED       TRUE
+#endif
+
+/* Inquiry duration in 1.28 second units. */
+#ifndef SDP_DEBUG
+#define SDP_DEBUG                   TRUE
+#endif
+
+/******************************************************************************
+**
+** HID
+**
+******************************************************************************/
+
+#ifndef HID_DEV_SUBCLASS
+#define HID_DEV_SUBCLASS            COD_MINOR_POINTING
+#endif
+
+#ifndef HID_CONTROL_POOL_ID
+#define HID_CONTROL_POOL_ID             2
+#endif
+
+#ifndef HID_INTERRUPT_POOL_ID
+#define HID_INTERRUPT_POOL_ID           2
+#endif
+
+/*************************************************************************
+** Definitions for Both HID-Host & Device
+*/
+#ifndef HID_MAX_SVC_NAME_LEN
+#define HID_MAX_SVC_NAME_LEN  32
+#endif
+
+#ifndef HID_MAX_SVC_DESCR_LEN
+#define HID_MAX_SVC_DESCR_LEN 32
+#endif
+
+#ifndef HID_MAX_PROV_NAME_LEN
+#define HID_MAX_PROV_NAME_LEN 32
+#endif
+
+/*************************************************************************
+** Definitions for HID-Host
+*/
+#ifndef  HID_HOST_INCLUDED
+#define HID_HOST_INCLUDED           FALSE//TRUE
+#endif
+
+#ifndef HID_HOST_MAX_DEVICES
+#define HID_HOST_MAX_DEVICES        7
+#endif
+
+#ifndef HID_HOST_MTU
+#define HID_HOST_MTU                640
+#endif
+
+#ifndef HID_HOST_FLUSH_TO
+#define HID_HOST_FLUSH_TO                 0xffff
+#endif
+
+#ifndef HID_HOST_MAX_CONN_RETRY
+#define HID_HOST_MAX_CONN_RETRY     (3) 
+#endif
+
+#ifndef HID_HOST_REPAGE_WIN
+#define HID_HOST_REPAGE_WIN          (2)
+#endif
+
+/*************************************************************************
+ * A2DP Definitions
+ */
+#ifndef A2D_INCLUDED
+#define A2D_INCLUDED            FALSE//TRUE
+#endif
+
+/******************************************************************************
+**
+** AVCTP
+**
+******************************************************************************/
+
+/* Number of simultaneous ACL links to different peer devices. */
+#ifndef AVCT_NUM_LINKS
+#define AVCT_NUM_LINKS              2
+#endif
+
+/* Number of simultaneous AVCTP connections. */
+#ifndef AVCT_NUM_CONN
+#define AVCT_NUM_CONN               3
+#endif
+
+/******************************************************************************
+**
+** AVRCP
+**
+******************************************************************************/
+#ifndef AVRC_INCLUDED
+#define AVRC_INCLUDED               FALSE
+#endif
+
+#ifndef AVRC_METADATA_INCLUDED
+#if AVRC_INCLUDED == TRUE
+#define AVRC_METADATA_INCLUDED      TRUE
+#else
+#define AVRC_METADATA_INCLUDED      FALSE
+#endif
+#endif
+
+#ifndef AVRC_ADV_CTRL_INCLUDED
+#if AVRC_INCLUDED == TRUE
+#define AVRC_ADV_CTRL_INCLUDED      TRUE
+#else
+#define AVRC_ADV_CTRL_INCLUDED      FALSE
+#endif
+#endif
+
+#ifndef AVRC_CTLR_INCLUDED
+#if AVRC_INCLUDED == TRUE
+#define AVRC_CTLR_INCLUDED          TRUE
+#else
+#define AVRC_CTLR_INCLUDED          FALSE
+#endif
+#endif
+
+/******************************************************************************
+**
+** MCAP
+**
+******************************************************************************/
+#ifndef MCA_INCLUDED
+#define MCA_INCLUDED                FALSE
+#endif
+
+/* The MTU size for the L2CAP configuration on control channel. 48 is the minimal */
+#ifndef MCA_CTRL_MTU
+#define MCA_CTRL_MTU    60
+#endif
+
+/* The maximum number of registered MCAP instances. */
+#ifndef MCA_NUM_REGS
+#define MCA_NUM_REGS    12
+#endif
+
+/* The maximum number of control channels (to difference devices) per registered MCAP instances. */
+#ifndef MCA_NUM_LINKS
+#define MCA_NUM_LINKS   3
+#endif
+
+/* The maximum number of MDEP (including HDP echo) per registered MCAP instances. */
+#ifndef MCA_NUM_DEPS
+#define MCA_NUM_DEPS    13
+#endif
+
+/* The maximum number of MDL link per control channel. */
+#ifndef MCA_NUM_MDLS
+#define MCA_NUM_MDLS    4
+#endif
+
+/* Pool ID where to reassemble the SDU. */
+#ifndef MCA_USER_RX_POOL_ID
+#define MCA_USER_RX_POOL_ID     HCI_ACL_POOL_ID
+#endif
+
+/* Pool ID where to hold the SDU. */
+#ifndef MCA_USER_TX_POOL_ID
+#define MCA_USER_TX_POOL_ID     HCI_ACL_POOL_ID
+#endif
+
+/*
+GKI Buffer Pool ID used to hold MPS segments during SDU reassembly
+*/
+#ifndef MCA_FCR_RX_POOL_ID
+#define MCA_FCR_RX_POOL_ID      HCI_ACL_POOL_ID
+#endif
+
+/*
+GKI Buffer Pool ID used to hold MPS segments used in (re)transmissions.
+L2CAP_DEFAULT_ERM_POOL_ID is specified to use the HCI ACL data pool.
+Note:  This pool needs to have enough buffers to hold two times the window size negotiated
+ in the tL2CAP_FCR_OPTIONS (2 * tx_win_size)  to allow for retransmissions.
+ The size of each buffer must be able to hold the maximum MPS segment size passed in
+ tL2CAP_FCR_OPTIONS plus BT_HDR (8) + HCI preamble (4) + L2CAP_MIN_OFFSET (11 - as of BT 2.1 + EDR Spec).
+*/
+#ifndef MCA_FCR_TX_POOL_ID
+#define MCA_FCR_TX_POOL_ID      HCI_ACL_POOL_ID
+#endif
+
+/* MCAP control channel FCR Option:
+Size of the transmission window when using enhanced retransmission mode.
+1 is defined by HDP specification for control channel.
+*/
+#ifndef MCA_FCR_OPT_TX_WINDOW_SIZE
+#define MCA_FCR_OPT_TX_WINDOW_SIZE      1
+#endif
+
+/* MCAP control channel FCR Option:
+Number of transmission attempts for a single I-Frame before taking
+Down the connection. Used In ERTM mode only. Value is Ignored in basic and
+Streaming modes.
+Range: 0, 1-0xFF
+0 - infinite retransmissions
+1 - single transmission
+*/
+#ifndef MCA_FCR_OPT_MAX_TX_B4_DISCNT
+#define MCA_FCR_OPT_MAX_TX_B4_DISCNT    20
+#endif
+
+/* MCAP control channel FCR Option: Retransmission Timeout
+The AVRCP specification set a value in the range of 300 - 2000 ms
+Timeout (in msecs) to detect Lost I-Frames. Only used in Enhanced retransmission mode.
+Range: Minimum 2000 (2 secs) when supporting PBF.
+ */
+#ifndef MCA_FCR_OPT_RETX_TOUT
+#define MCA_FCR_OPT_RETX_TOUT           2000
+#endif
+
+/* MCAP control channel FCR Option: Monitor Timeout
+The AVRCP specification set a value in the range of 300 - 2000 ms
+Timeout (in msecs) to detect Lost S-Frames. Only used in Enhanced retransmission mode.
+Range: Minimum 12000 (12 secs) when supporting PBF.
+*/
+#ifndef MCA_FCR_OPT_MONITOR_TOUT
+#define MCA_FCR_OPT_MONITOR_TOUT        12000
+#endif
+
+/* MCAP control channel FCR Option: Maximum PDU payload size.
+The maximum number of payload octets that the local device can receive in a single PDU.
+*/
+#ifndef MCA_FCR_OPT_MPS_SIZE
+#define MCA_FCR_OPT_MPS_SIZE            1000
+#endif
+
+/* Shared transport */
+#ifndef NFC_SHARED_TRANSPORT_ENABLED
+#define NFC_SHARED_TRANSPORT_ENABLED    FALSE
+#endif
+
+/******************************************************************************
+**
+** Sleep Mode (Low Power Mode)
+**
+******************************************************************************/
+
+#ifndef HCILP_INCLUDED
+#define HCILP_INCLUDED                  FALSE//TRUE
+#endif
+
+/******************************************************************************
+**
+** APPL - Application Task
+**
+******************************************************************************/
+
+#define L2CAP_FEATURE_REQ_ID      73
+#define L2CAP_FEATURE_RSP_ID     173
+
+/******************************************************************************
+**
+** BTA
+**
+******************************************************************************/
+/* BTA EIR canned UUID list (default is dynamic) */
+#ifndef BTA_EIR_CANNED_UUID_LIST
+#define BTA_EIR_CANNED_UUID_LIST FALSE
+#endif
+
+/* Number of supported customer UUID in EIR */
+#ifndef BTA_EIR_SERVER_NUM_CUSTOM_UUID
+#define BTA_EIR_SERVER_NUM_CUSTOM_UUID     8
+#endif
+
+/* CHLD override for bluedroid */
+#ifndef BTA_AG_CHLD_VAL_ECC
+#define BTA_AG_CHLD_VAL_ECC  "(0,1,1x,2,2x,3)"
+#endif
+
+#ifndef BTA_AG_CHLD_VAL
+#define BTA_AG_CHLD_VAL  "(0,1,2,3)"
+#endif
+
+/* Set the CIND to match HFP 1.5 */
+#ifndef BTA_AG_CIND_INFO
+#define BTA_AG_CIND_INFO "(\"call\",(0,1)),(\"callsetup\",(0-3)),(\"service\",(0-1)),(\"signal\",(0-5)),(\"roam\",(0,1)),(\"battchg\",(0-5)),(\"callheld\",(0-2))"
+#endif
+
+#ifndef BTA_DM_AVOID_A2DP_ROLESWITCH_ON_INQUIRY
+#define BTA_DM_AVOID_A2DP_ROLESWITCH_ON_INQUIRY FALSE//TRUE
+#endif
+
+/******************************************************************************
+**
+** Tracing:  Include trace header file here.
+**
+******************************************************************************/
+
+/* Enable/disable BTSnoop memory logging */
+#ifndef BTSNOOP_MEM
+#define BTSNOOP_MEM FALSE//TRUE
+#endif
+
+#include "bt_trace.h"
+
+#endif /* BT_TARGET_H */

+ 462 - 0
components/bt/bluedroid/include/bt_trace.h

@@ -0,0 +1,462 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 1999-2012 Broadcom Corporation
+ *
+ *  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_TRACE_H_
+#define _BT_TRACE_H_
+
+#include "bt_types.h"
+
+#include "rom/ets_sys.h"
+//extern void ets_printf(const char *fmt, ...);
+
+#define assert(x)	do { if (!(x)) ets_printf("bt host error %s %u\n", __FILE__, __LINE__); } while (0)
+
+inline void trc_dump_buffer(uint8_t *prefix, uint8_t *data, uint16_t len)
+{
+  uint16_t i;
+
+  if (!data || !len)
+    return;
+
+  if (prefix)
+    ets_printf("%s:\t", prefix);
+
+  for (i = 0; i < len; i++) {
+    ets_printf(" %02x", *(data + i));
+    if (!((i + 1) & 0xf))
+      ets_printf("\n");
+  }
+  ets_printf("\n");
+}
+
+#ifdef BTTRC_DUMP_BUFFER
+#define BTTRC_DUMP_BUFFER(_prefix, _data, _len) trc_dump_buffer(_data, _len)
+#else
+#define BTTRC_DUMP_BUFFER(_prefix, _data, _len)
+#endif
+
+//static const char BTE_LOGMSG_MODULE[] = "bte_logmsg_module";
+
+/* BTrgs);E tracing IDs for debug purposes */
+/* LayerIDs for stack */
+#define BTTRC_ID_STK_GKI                   1
+#define BTTRC_ID_STK_BTU                   2
+#define BTTRC_ID_STK_HCI                   3
+#define BTTRC_ID_STK_L2CAP                 4
+#define BTTRC_ID_STK_RFCM_MX               5
+#define BTTRC_ID_STK_RFCM_PRT              6
+#define BTTRC_ID_STK_OBEX_C                7
+#define BTTRC_ID_STK_OBEX_S                8
+#define BTTRC_ID_STK_AVCT                  9
+#define BTTRC_ID_STK_AVDT                  10
+#define BTTRC_ID_STK_AVRC                  11
+#define BTTRC_ID_STK_BIC                   12
+#define BTTRC_ID_STK_BIS                   13
+#define BTTRC_ID_STK_BNEP                  14
+#define BTTRC_ID_STK_BPP                   15
+#define BTTRC_ID_STK_BTM_ACL               16
+#define BTTRC_ID_STK_BTM_PM                17
+#define BTTRC_ID_STK_BTM_DEV_CTRL          18
+#define BTTRC_ID_STK_BTM_SVC_DSC           19
+#define BTTRC_ID_STK_BTM_INQ               20
+#define BTTRC_ID_STK_BTM_SCO               21
+#define BTTRC_ID_STK_BTM_SEC               22
+#define BTTRC_ID_STK_HID                   24
+#define BTTRC_ID_STK_HSP2                  25
+#define BTTRC_ID_STK_CTP                   26
+#define BTTRC_ID_STK_FTC                   27
+#define BTTRC_ID_STK_FTS                   28
+#define BTTRC_ID_STK_GAP                   29
+#define BTTRC_ID_STK_HCRP                  31
+#define BTTRC_ID_STK_ICP                   32
+#define BTTRC_ID_STK_OPC                   33
+#define BTTRC_ID_STK_OPS                   34
+#define BTTRC_ID_STK_PAN                   35
+#define BTTRC_ID_STK_SAP                   36
+#define BTTRC_ID_STK_SDP                   37
+#define BTTRC_ID_STK_SLIP                  38
+#define BTTRC_ID_STK_SPP                   39
+#define BTTRC_ID_STK_TCS                   40
+#define BTTRC_ID_STK_VDP                   41
+#define BTTRC_ID_STK_MCAP                  42
+#define BTTRC_ID_STK_GATT                  43
+#define BTTRC_ID_STK_SMP                   44
+#define BTTRC_ID_STK_NFC                   45
+#define BTTRC_ID_STK_NCI                   46
+#define BTTRC_ID_STK_IDEP                  47
+#define BTTRC_ID_STK_NDEP                  48
+#define BTTRC_ID_STK_LLCP                  49
+#define BTTRC_ID_STK_RW                    50
+#define BTTRC_ID_STK_CE                    51
+#define BTTRC_ID_STK_SNEP                  52
+#define BTTRC_ID_STK_NDEF                  53
+
+/* LayerIDs for BTA */
+#define BTTRC_ID_BTA_ACC                   55         /* Advanced Camera Client */
+#define BTTRC_ID_BTA_AG                    56         /* audio gateway */
+#define BTTRC_ID_BTA_AV                    57         /* Advanced audio */
+#define BTTRC_ID_BTA_BIC                   58         /* Basic Imaging Client */
+#define BTTRC_ID_BTA_BIS                   59         /* Basic Imaging Server */
+#define BTTRC_ID_BTA_BP                    60         /* Basic Printing Client */
+#define BTTRC_ID_BTA_CG                    61
+#define BTTRC_ID_BTA_CT                    62         /* cordless telephony terminal */
+#define BTTRC_ID_BTA_DG                    63         /* data gateway */
+#define BTTRC_ID_BTA_DM                    64         /* device manager */
+#define BTTRC_ID_BTA_DM_SRCH               65         /* device manager search */
+#define BTTRC_ID_BTA_DM_SEC                66         /* device manager security */
+#define BTTRC_ID_BTA_FM                    67
+#define BTTRC_ID_BTA_FTC                   68         /* file transfer client */
+#define BTTRC_ID_BTA_FTS                   69         /* file transfer server */
+#define BTTRC_ID_BTA_HIDH                  70
+#define BTTRC_ID_BTA_HIDD                  71
+#define BTTRC_ID_BTA_JV                    72
+#define BTTRC_ID_BTA_OPC                   73         /* object push client */
+#define BTTRC_ID_BTA_OPS                   74         /* object push server */
+#define BTTRC_ID_BTA_PAN                   75         /* Personal Area Networking */
+#define BTTRC_ID_BTA_PR                    76         /* Printer client */
+#define BTTRC_ID_BTA_SC                    77         /* SIM Card Access server */
+#define BTTRC_ID_BTA_SS                    78         /* synchronization server */
+#define BTTRC_ID_BTA_SYS                   79         /* system manager */
+#define BTTRC_ID_AVDT_SCB                  80         /* avdt scb */
+#define BTTRC_ID_AVDT_CCB                  81         /* avdt ccb */
+
+// btla-specific ++
+/* LayerIDs added for BTL-A. Probably should modify bte_logmsg.c in future. */
+#define BTTRC_ID_STK_RFCOMM                82
+#define BTTRC_ID_STK_RFCOMM_DATA           83
+#define BTTRC_ID_STK_OBEX                  84
+#define BTTRC_ID_STK_A2D                   85
+#define BTTRC_ID_STK_BIP                   86
+
+/* LayerIDs for BT APP */
+#define BTTRC_ID_BTAPP                     87
+#define BTTRC_ID_BT_PROTOCOL               88         /* this is a temporary solution to allow dynamic
+                                                         enable/disable of BT_PROTOCOL_TRACE */
+#define BTTRC_ID_MAX_ID                    BTTRC_ID_BT_PROTOCOL
+// btla-specific --
+#define BTTRC_ID_ALL_LAYERS                0xFF       /* all trace layers */
+/* Parameter datatypes used in Trace APIs */
+#define BTTRC_PARAM_UINT8                  1
+#define BTTRC_PARAM_UINT16                 2
+#define BTTRC_PARAM_UINT32                 3
+
+/* Enables or disables verbose trace information. */
+#ifndef BT_TRACE_VERBOSE
+#define BT_TRACE_VERBOSE    FALSE
+#endif
+
+/* Enables or disables all trace messages. */
+#ifndef BT_USE_TRACES
+#define BT_USE_TRACES       TRUE
+#endif
+
+/******************************************************************************
+**
+** Trace Levels
+**
+** The following values may be used for different levels:
+**      BT_TRACE_LEVEL_NONE    0        * No trace messages to be generated
+**      BT_TRACE_LEVEL_ERROR   1        * Error condition trace messages
+**      BT_TRACE_LEVEL_WARNING 2        * Warning condition trace messages
+**      BT_TRACE_LEVEL_API     3        * API traces
+**      BT_TRACE_LEVEL_EVENT   4        * Debug messages for events
+**      BT_TRACE_LEVEL_DEBUG   5        * Debug messages (general)
+******************************************************************************/
+
+// btla-specific ++
+/* Core Stack default trace levels */
+#ifndef HCI_INITIAL_TRACE_LEVEL
+#define HCI_INITIAL_TRACE_LEVEL             BT_TRACE_LEVEL_WARNING
+#endif
+
+#ifndef BTM_INITIAL_TRACE_LEVEL
+#define BTM_INITIAL_TRACE_LEVEL             BT_TRACE_LEVEL_WARNING
+#endif
+
+#ifndef L2CAP_INITIAL_TRACE_LEVEL
+#define L2CAP_INITIAL_TRACE_LEVEL           BT_TRACE_LEVEL_WARNING
+#endif
+
+#ifndef RFCOMM_INITIAL_TRACE_LEVEL
+#define RFCOMM_INITIAL_TRACE_LEVEL          BT_TRACE_LEVEL_WARNING
+#endif
+
+#ifndef SDP_INITIAL_TRACE_LEVEL
+#define SDP_INITIAL_TRACE_LEVEL             BT_TRACE_LEVEL_WARNING
+#endif
+
+#ifndef GAP_INITIAL_TRACE_LEVEL
+#define GAP_INITIAL_TRACE_LEVEL             BT_TRACE_LEVEL_WARNING
+#endif
+
+#ifndef BNEP_INITIAL_TRACE_LEVEL
+#define BNEP_INITIAL_TRACE_LEVEL            BT_TRACE_LEVEL_WARNING
+#endif
+
+#ifndef PAN_INITIAL_TRACE_LEVEL
+#define PAN_INITIAL_TRACE_LEVEL             BT_TRACE_LEVEL_WARNING
+#endif
+
+#ifndef A2D_INITIAL_TRACE_LEVEL
+#define A2D_INITIAL_TRACE_LEVEL             BT_TRACE_LEVEL_WARNING
+#endif
+
+#ifndef AVDT_INITIAL_TRACE_LEVEL
+#define AVDT_INITIAL_TRACE_LEVEL            BT_TRACE_LEVEL_WARNING
+#endif
+
+#ifndef AVCT_INITIAL_TRACE_LEVEL
+#define AVCT_INITIAL_TRACE_LEVEL            BT_TRACE_LEVEL_WARNING
+#endif
+
+#ifndef AVRC_INITIAL_TRACE_LEVEL
+#define AVRC_INITIAL_TRACE_LEVEL            BT_TRACE_LEVEL_WARNING
+#endif
+
+#ifndef MCA_INITIAL_TRACE_LEVEL
+#define MCA_INITIAL_TRACE_LEVEL             BT_TRACE_LEVEL_WARNING
+#endif
+
+#ifndef HID_INITIAL_TRACE_LEVEL
+#define HID_INITIAL_TRACE_LEVEL             BT_TRACE_LEVEL_WARNING
+#endif
+
+#ifndef APPL_INITIAL_TRACE_LEVEL
+#define APPL_INITIAL_TRACE_LEVEL            BT_TRACE_LEVEL_WARNING
+#endif
+
+#ifndef BT_TRACE_APPL
+#define BT_TRACE_APPL   BT_USE_TRACES
+#endif
+
+#ifndef GATT_INITIAL_TRACE_LEVEL
+#define GATT_INITIAL_TRACE_LEVEL             BT_TRACE_LEVEL_WARNING
+#endif
+
+#ifndef SMP_INITIAL_TRACE_LEVEL
+#define SMP_INITIAL_TRACE_LEVEL             BT_TRACE_LEVEL_WARNING
+#endif
+// btla-specific --
+
+/* Define common tracing for all */
+#define LOG_LEVEL_ERROR		1
+#define LOG_LEVEL_WARN		2
+#define LOG_LEVEL_INFO		3
+#define LOG_LEVEL_DEBUG		4
+#define LOG_LEVEL_VERBOSE	5
+#ifndef LOG_LEVEL
+#define LOG_LEVEL	LOG_LEVEL_DEBUG
+#endif
+#define LOG_ERROR(fmt, args...)			do {if (LOG_LEVEL >= LOG_LEVEL_ERROR) ets_printf(fmt,## args);} while(0)
+#define LOG_WARN(fmt, args...)			do {if (LOG_LEVEL >= LOG_LEVEL_WARN) ets_printf(fmt,## args);} while(0)
+#define LOG_INFO(fmt, args...)			do {if (LOG_LEVEL >= LOG_LEVEL_INFO) ets_printf(fmt,## args);} while(0)
+#define LOG_DEBUG(fmt, args...)			do {if (LOG_LEVEL >= LOG_LEVEL_DEBUG) ets_printf(fmt,## args);} while(0)
+#define LOG_VERBOSE(fmt, args...)		do {if (LOG_LEVEL >= LOG_LEVEL_VERBOSE) ets_printf(fmt,## args);} while(0)
+
+/* Define tracing for the HCI unit
+*/
+#define HCI_TRACE_ERROR(fmt, args...)		{if (btu_cb.trace_level >= BT_TRACE_LEVEL_ERROR) ets_printf(fmt,## args);}
+#define HCI_TRACE_WARNING(fmt, args...)		{if (btu_cb.trace_level >= BT_TRACE_LEVEL_WARNING) ets_printf(fmt,## args);}
+#define HCI_TRACE_EVENT(fmt, args...)		{if (btu_cb.trace_level >= BT_TRACE_LEVEL_EVENT) ets_printf(fmt,## args);}
+#define HCI_TRACE_DEBUG(fmt, args...)		{if (btu_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) ets_printf(fmt,## args);}
+
+/* Define tracing for BTM
+*/
+#define BTM_TRACE_ERROR(fmt, args...)		{if (btm_cb.trace_level >= BT_TRACE_LEVEL_ERROR) ets_printf(fmt, ## args);}
+#define BTM_TRACE_WARNING(fmt, args...)		{if (btm_cb.trace_level >= BT_TRACE_LEVEL_WARNING) ets_printf(fmt, ## args);}
+#define BTM_TRACE_API(fmt, args...)		{if (btm_cb.trace_level >= BT_TRACE_LEVEL_API) ets_printf(fmt, ## args);}
+#define BTM_TRACE_EVENT(fmt, args...)		{if (btm_cb.trace_level >= BT_TRACE_LEVEL_EVENT) ets_printf(fmt, ## args);}
+#define BTM_TRACE_DEBUG(fmt, args...)		{if (btm_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) ets_printf(fmt, ## args);}
+
+/* Define tracing for the L2CAP unit
+*/
+#define L2CAP_TRACE_ERROR(fmt, args...)		{if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_ERROR) ets_printf(fmt, ## args);}
+#define L2CAP_TRACE_WARNING(fmt, args...)	{if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_WARNING) ets_printf(fmt, ## args);}
+#define L2CAP_TRACE_API(fmt, args...)		{if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_API) ets_printf(fmt, ## args);}
+#define L2CAP_TRACE_EVENT(fmt, args...)		{if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_EVENT) ets_printf(fmt, ## args);}
+#define L2CAP_TRACE_DEBUG(fmt, args...)		{if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_DEBUG) ets_printf(fmt, ## args);}
+
+/* Define tracing for the SDP unit
+*/
+#define SDP_TRACE_ERROR(fmt, args...)		{if (sdp_cb.trace_level >= BT_TRACE_LEVEL_ERROR) ets_printf(fmt, ## args);}
+#define SDP_TRACE_WARNING(fmt, args...)		{if (sdp_cb.trace_level >= BT_TRACE_LEVEL_WARNING) ets_printf(fmt, ## args);}
+#define SDP_TRACE_API(fmt, args...)		{if (sdp_cb.trace_level >= BT_TRACE_LEVEL_API) ets_printf(fmt, ## args);}
+#define SDP_TRACE_EVENT(fmt, args...)		{if (sdp_cb.trace_level >= BT_TRACE_LEVEL_EVENT) ets_printf(fmt, ## args);}
+#define SDP_TRACE_DEBUG(fmt, args...)		{if (sdp_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) ets_printf(fmt, ## args);}
+
+/* Define tracing for the RFCOMM unit
+*/
+#define RFCOMM_TRACE_ERROR(fmt, args...)	{if (rfc_cb.trace_level >= BT_TRACE_LEVEL_ERROR) ets_printf(fmt, ## args);}
+#define RFCOMM_TRACE_WARNING(fmt, args...)	{if (rfc_cb.trace_level >= BT_TRACE_LEVEL_WARNING) ets_printf(fmt, ## args);}
+#define RFCOMM_TRACE_API(fmt, args...)		{if (rfc_cb.trace_level >= BT_TRACE_LEVEL_API) ets_printf(fmt, ## args);}
+#define RFCOMM_TRACE_EVENT(fmt, args...)	{if (rfc_cb.trace_level >= BT_TRACE_LEVEL_EVENT) ets_printf(fmt, ## args);}
+#define RFCOMM_TRACE_DEBUG(fmt, args...)	{if (rfc_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) ets_printf(fmt, ## args);}
+
+/* Generic Access Profile traces */
+#define GAP_TRACE_ERROR(fmt, args...)		{if (gap_cb.trace_level >= BT_TRACE_LEVEL_ERROR) ets_printf(fmt, ## args);}
+#define GAP_TRACE_EVENT(fmt, args...)		{if (gap_cb.trace_level >= BT_TRACE_LEVEL_EVENT) ets_printf(fmt, ## args);}
+#define GAP_TRACE_API(fmt, args...)		{if (gap_cb.trace_level >= BT_TRACE_LEVEL_API) ets_printf(fmt, ## args);}
+#define GAP_TRACE_WARNING(fmt, args...)		{if (gap_cb.trace_level >= BT_TRACE_LEVEL_WARNING) ets_printf(fmt, ## args);}
+
+/* define traces for HID Host */
+#define HIDH_TRACE_ERROR(fmt, args...)		{if (hh_cb.trace_level >= BT_TRACE_LEVEL_ERROR) ets_printf(fmt, ## args);}
+#define HIDH_TRACE_WARNING(fmt, args...)	{if (hh_cb.trace_level >= BT_TRACE_LEVEL_WARNING) ets_printf(fmt, ## args);}
+#define HIDH_TRACE_API(fmt, args...)		{if (hh_cb.trace_level >= BT_TRACE_LEVEL_API) ets_printf(fmt, ## args);}
+#define HIDH_TRACE_EVENT(fmt, args...)		{if (hh_cb.trace_level >= BT_TRACE_LEVEL_EVENT) ets_printf(fmt, ## args);}
+#define HIDH_TRACE_DEBUG(fmt, args...)		{if (hh_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) ets_printf(fmt, ## args);}
+
+/* define traces for BNEP */
+
+#define BNEP_TRACE_ERROR(fmt, args...)		{if (bnep_cb.trace_level >= BT_TRACE_LEVEL_ERROR) ets_printf(fmt, ## args);}
+#define BNEP_TRACE_WARNING(fmt, args...)	{if (bnep_cb.trace_level >= BT_TRACE_LEVEL_WARNING) ets_printf(fmt, ## args);}
+#define BNEP_TRACE_API(fmt, args...)		{if (bnep_cb.trace_level >= BT_TRACE_LEVEL_API) ets_printf(fmt, ## args);}
+#define BNEP_TRACE_EVENT(fmt, args...)		{if (bnep_cb.trace_level >= BT_TRACE_LEVEL_EVENT) ets_printf(fmt, ## args);}
+#define BNEP_TRACE_DEBUG(fmt, args...)		{if (bnep_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) ets_printf(fmt, ## args);}
+
+/* define traces for PAN */
+
+#define PAN_TRACE_ERROR(fmt, args...)		{if (pan_cb.trace_level >= BT_TRACE_LEVEL_ERROR) ets_printf(fmt, ## args);}
+#define PAN_TRACE_WARNING(fmt, args...)		{if (pan_cb.trace_level >= BT_TRACE_LEVEL_WARNING) ets_printf(fmt, ## args);}
+#define PAN_TRACE_API(fmt, args...)		{if (pan_cb.trace_level >= BT_TRACE_LEVEL_API) ets_printf(fmt, ## args);}
+#define PAN_TRACE_EVENT(fmt, args...)		{if (pan_cb.trace_level >= BT_TRACE_LEVEL_EVENT) ets_printf(fmt, ## args);}
+#define PAN_TRACE_DEBUG(fmt, args...)		{if (pan_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) ets_printf(fmt, ## args);}
+
+/* Define tracing for the A2DP profile
+*/
+#define A2D_TRACE_ERROR(fmt, args...)		{if (a2d_cb.trace_level >= BT_TRACE_LEVEL_ERROR) ets_printf(fmt, ## args);}
+#define A2D_TRACE_WARNING(fmt, args...)		{if (a2d_cb.trace_level >= BT_TRACE_LEVEL_WARNING) ets_printf(fmt, ## args);}
+#define A2D_TRACE_EVENT(fmt, args...)		{if (a2d_cb.trace_level >= BT_TRACE_LEVEL_EVENT) ets_printf(fmt, ## args);}
+#define A2D_TRACE_DEBUG(fmt, args...)		{if (a2d_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) ets_printf(fmt, ## args);}
+#define A2D_TRACE_API(fmt, args...)		{if (a2d_cb.trace_level >= BT_TRACE_LEVEL_API) ets_printf(fmt, ## args);}
+
+/* AVDTP
+*/
+#define AVDT_TRACE_ERROR(fmt, args...)		{if (avdt_cb.trace_level >= BT_TRACE_LEVEL_ERROR) ets_printf(fmt, ## args);}
+#define AVDT_TRACE_WARNING(fmt, args...)	{if (avdt_cb.trace_level >= BT_TRACE_LEVEL_WARNING) ets_printf(fmt, ## args);}
+#define AVDT_TRACE_EVENT(fmt, args...)		{if (avdt_cb.trace_level >= BT_TRACE_LEVEL_EVENT) ets_printf(fmt, ## args);}
+#define AVDT_TRACE_DEBUG(fmt, args...)		{if (avdt_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) ets_printf(fmt, ## args);}
+#define AVDT_TRACE_API(fmt, args...)		{if (avdt_cb.trace_level >= BT_TRACE_LEVEL_API) ets_printf(fmt, ## args);}
+
+/* Define tracing for the AVCTP protocol
+*/
+#define AVCT_TRACE_ERROR(fmt, args...)		{if (avct_cb.trace_level >= BT_TRACE_LEVEL_ERROR) ets_printf(fmt, ## args);}
+#define AVCT_TRACE_WARNING(fmt, args...)	{if (avct_cb.trace_level >= BT_TRACE_LEVEL_WARNING) ets_printf(fmt, ## args);}
+#define AVCT_TRACE_EVENT(fmt, args...)		{if (avct_cb.trace_level >= BT_TRACE_LEVEL_EVENT) ets_printf(fmt, ## args);}
+#define AVCT_TRACE_DEBUG(fmt, args...)		{if (avct_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) ets_printf(fmt, ## args);}
+#define AVCT_TRACE_API(fmt, args...)		{if (avct_cb.trace_level >= BT_TRACE_LEVEL_API) ets_printf(fmt, ## args);}
+
+/* Define tracing for the AVRCP profile
+*/
+#define AVRC_TRACE_ERROR(fmt, args...)		{if (avrc_cb.trace_level >= BT_TRACE_LEVEL_ERROR) ets_printf(fmt, ## args);}
+#define AVRC_TRACE_WARNING(fmt, args...)	{if (avrc_cb.trace_level >= BT_TRACE_LEVEL_WARNING) ets_printf(fmt, ## args);}
+#define AVRC_TRACE_EVENT(fmt, args...)		{if (avrc_cb.trace_level >= BT_TRACE_LEVEL_EVENT) ets_printf(fmt, ## args);}
+#define AVRC_TRACE_DEBUG(fmt, args...)		{if (avrc_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) ets_printf(fmt, ## args);}
+#define AVRC_TRACE_API(fmt, args...)		{if (avrc_cb.trace_level >= BT_TRACE_LEVEL_API) ets_printf(fmt, ## args);}
+
+/* MCAP
+*/
+#define MCA_TRACE_ERROR(fmt, args...)		{if (mca_cb.trace_level >= BT_TRACE_LEVEL_ERROR) ets_printf(fmt, ## args);}
+#define MCA_TRACE_WARNING(fmt, args...)		{if (mca_cb.trace_level >= BT_TRACE_LEVEL_WARNING) ets_printf(fmt, ## args);}
+#define MCA_TRACE_EVENT(fmt, args...)		{if (mca_cb.trace_level >= BT_TRACE_LEVEL_EVENT) ets_printf(fmt, ## args);}
+#define MCA_TRACE_DEBUG(fmt, args...)		{if (mca_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) ets_printf(fmt, ## args);}
+#define MCA_TRACE_API(fmt, args...)		{if (mca_cb.trace_level >= BT_TRACE_LEVEL_API) ets_printf(fmt, ## args);}
+
+/* Define tracing for the ATT/GATT unit
+*/
+#define GATT_TRACE_ERROR(fmt, args...)		{if (gatt_cb.trace_level >= BT_TRACE_LEVEL_ERROR) ets_printf(fmt, ## args);}
+#define GATT_TRACE_WARNING(fmt, args...)	{if (gatt_cb.trace_level >= BT_TRACE_LEVEL_WARNING) ets_printf(fmt, ## args);}
+#define GATT_TRACE_API(fmt, args...)		{if (gatt_cb.trace_level >= BT_TRACE_LEVEL_API) ets_printf(fmt, ## args);}
+#define GATT_TRACE_EVENT(fmt, args...)		{if (gatt_cb.trace_level >= BT_TRACE_LEVEL_EVENT) ets_printf(fmt, ## args);}
+#define GATT_TRACE_DEBUG(fmt, args...)		{if (gatt_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) ets_printf(fmt, ## args);}
+
+/* Define tracing for the SMP unit
+*/
+#define SMP_TRACE_ERROR(fmt, args...)		{if (smp_cb.trace_level >= BT_TRACE_LEVEL_ERROR) ets_printf(fmt, ## args);}
+#define SMP_TRACE_WARNING(fmt, args...)		{if (smp_cb.trace_level >= BT_TRACE_LEVEL_WARNING) ets_printf(fmt, ## args);}
+#define SMP_TRACE_API(fmt, args...)		{if (smp_cb.trace_level >= BT_TRACE_LEVEL_API) ets_printf(fmt, ## args);}
+#define SMP_TRACE_EVENT(fmt, args...)		{if (smp_cb.trace_level >= BT_TRACE_LEVEL_EVENT) ets_printf(fmt, ## args);}
+#define SMP_TRACE_DEBUG(fmt, args...)		{if (smp_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) ets_printf(fmt, ## args);}
+
+extern UINT8 btif_trace_level;
+
+// define traces for application
+#define BTIF_TRACE_ERROR(fmt, args...)		{if (btif_trace_level >= BT_TRACE_LEVEL_ERROR) ets_printf(fmt, ## args);}
+#define BTIF_TRACE_WARNING(fmt, args...)	{if (btif_trace_level >= BT_TRACE_LEVEL_WARNING) ets_printf(fmt, ## args);}
+#define BTIF_TRACE_API(fmt, args...)		{if (btif_trace_level >= BT_TRACE_LEVEL_API) ets_printf(fmt, ## args);}
+#define BTIF_TRACE_EVENT(fmt, args...)		{if (btif_trace_level >= BT_TRACE_LEVEL_EVENT) ets_printf(fmt, ## args);}
+#define BTIF_TRACE_DEBUG(fmt, args...)		{if (btif_trace_level >= BT_TRACE_LEVEL_DEBUG) ets_printf(fmt, ## args);}
+#define BTIF_TRACE_VERBOSE(fmt, args...)	{if (btif_trace_level >= BT_TRACE_LEVEL_VERBOSE)ets_printf(fmt, ## args);}
+
+/* define traces for application */
+
+#define APPL_TRACE_ERROR(fmt, args...)		{if (appl_trace_level >= BT_TRACE_LEVEL_ERROR) ets_printf(fmt, ## args);}
+#define APPL_TRACE_WARNING(fmt, args...)	{if (appl_trace_level >= BT_TRACE_LEVEL_WARNING) ets_printf(fmt, ## args);}
+#define APPL_TRACE_API(fmt, args...)		{if (appl_trace_level >= BT_TRACE_LEVEL_API) ets_printf(fmt, ## args);}
+#define APPL_TRACE_EVENT(fmt, args...)		{if (appl_trace_level >= BT_TRACE_LEVEL_EVENT) ets_printf(fmt, ## args);}
+#define APPL_TRACE_DEBUG(fmt, args...)		{if (appl_trace_level >= BT_TRACE_LEVEL_DEBUG) ets_printf(fmt, ## args);}
+#define APPL_TRACE_VERBOSE(fmt, args...)	{if (appl_trace_level >= BT_TRACE_LEVEL_VERBOSE) ets_printf(fmt, ## args);}
+
+/* Simplified Trace Helper Macro
+*/
+#define bdld(fmt, args...) \
+    do{\
+        if((MY_LOG_LEVEL) >= BT_TRACE_LEVEL_DEBUG) \
+		ets_printf(fmt, ## args);		\
+    }while(0)
+
+#define bdlw(fmt, args...) \
+    do{\
+        if((MY_LOG_LEVEL) >= BT_TRACE_LEVEL_DEBUG) \
+		ets_printf(fmt, ## args);		\
+    }while(0)
+
+#define bdle(fmt, args...) \
+    do{\
+        if((MY_LOG_LEVEL) >= BT_TRACE_LEVEL_DEBUG) \
+		ets_printf(fmt, ## args);		\
+    }while(0)
+
+#define bdla(assert_if) \
+    do{\
+        if(((MY_LOG_LEVEL) >= BT_TRACE_LEVEL_ERROR) && !(assert_if)) \
+		ets_printf("%s: assert failed\n", #assert_if);		\
+    }while(0)
+
+typedef UINT8 tBTTRC_PARAM_TYPE;
+typedef UINT8 tBTTRC_LAYER_ID;
+typedef UINT8 tBTTRC_TYPE;
+
+typedef struct {
+    tBTTRC_LAYER_ID layer_id;
+    tBTTRC_TYPE     type;      /* TODO: use tBTTRC_TYPE instead of "classical level 0-5" */
+} tBTTRC_LEVEL;
+
+typedef UINT8 (tBTTRC_SET_TRACE_LEVEL)( UINT8 );
+
+typedef struct {
+    const tBTTRC_LAYER_ID         layer_id_start;
+    const tBTTRC_LAYER_ID         layer_id_end;
+    tBTTRC_SET_TRACE_LEVEL        *p_f;
+    const char                    *trc_name;
+    UINT8                         trace_level;
+} tBTTRC_FUNC_MAP;
+
+/* External declaration for appl_trace_level here to avoid to add the declaration in all the files using APPL_TRACExxx macros */
+extern UINT8 appl_trace_level;
+
+#endif /*_BT_TRACE_H_*/

+ 362 - 0
components/bt/bluedroid/include/bt_vendor_lib.h

@@ -0,0 +1,362 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ *  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_VENDOR_LIB_H
+#define BT_VENDOR_LIB_H
+
+#include <stdint.h>
+//#include <sys/cdefs.h>
+//#include <sys/types.h>
+
+/** Struct types */
+
+
+/** Typedefs and defines */
+
+/** Vendor specific operations OPCODE */
+typedef enum {
+/*  [operation]
+ *      Power on or off the BT Controller.
+ *  [input param]
+ *      A pointer to int type with content of bt_vendor_power_state_t.
+ *      Typecasting conversion: (int *) param.
+ *  [return]
+ *      0 - default, don't care.
+ *  [callback]
+ *      None.
+ */
+    BT_VND_OP_POWER_CTRL,
+
+/*  [operation]
+ *      Perform any vendor specific initialization or configuration
+ *      on the BT Controller. This is called before stack initialization.
+ *  [input param]
+ *      None.
+ *  [return]
+ *      0 - default, don't care.
+ *  [callback]
+ *      Must call fwcfg_cb to notify the stack of the completion of vendor
+ *      specific initialization once it has been done.
+ */
+    BT_VND_OP_FW_CFG,
+
+/*  [operation]
+ *      Perform any vendor specific SCO/PCM configuration on the BT Controller.
+ *      This is called after stack initialization.
+ *  [input param]
+ *      None.
+ *  [return]
+ *      0 - default, don't care.
+ *  [callback]
+ *      Must call scocfg_cb to notify the stack of the completion of vendor
+ *      specific SCO configuration once it has been done.
+ */
+    BT_VND_OP_SCO_CFG,
+
+/*  [operation]
+ *      Open UART port on where the BT Controller is attached.
+ *      This is called before stack initialization.
+ *  [input param]
+ *      A pointer to int array type for open file descriptors.
+ *      The mapping of HCI channel to fd slot in the int array is given in
+ *      bt_vendor_hci_channels_t.
+ *      And, it requires the vendor lib to fill up the content before returning
+ *      the call.
+ *      Typecasting conversion: (int (*)[]) param.
+ *  [return]
+ *      Numbers of opened file descriptors.
+ *      Valid number:
+ *          1 - CMD/EVT/ACL-In/ACL-Out via the same fd (e.g. UART)
+ *          2 - CMD/EVT on one fd, and ACL-In/ACL-Out on the other fd
+ *          4 - CMD, EVT, ACL-In, ACL-Out are on their individual fd
+ *  [callback]
+ *      None.
+ */
+    BT_VND_OP_USERIAL_OPEN,
+
+/*  [operation]
+ *      Close the previously opened UART port.
+ *  [input param]
+ *      None.
+ *  [return]
+ *      0 - default, don't care.
+ *  [callback]
+ *      None.
+ */
+    BT_VND_OP_USERIAL_CLOSE,
+
+/*  [operation]
+ *      Get the LPM idle timeout in milliseconds.
+ *      The stack uses this information to launch a timer delay before it
+ *      attempts to de-assert LPM WAKE signal once downstream HCI packet
+ *      has been delivered.
+ *  [input param]
+ *      A pointer to uint32_t type which is passed in by the stack. And, it
+ *      requires the vendor lib to fill up the content before returning
+ *      the call.
+ *      Typecasting conversion: (uint32_t *) param.
+ *  [return]
+ *      0 - default, don't care.
+ *  [callback]
+ *      None.
+ */
+    BT_VND_OP_GET_LPM_IDLE_TIMEOUT,
+
+/*  [operation]
+ *      Enable or disable LPM mode on BT Controller.
+ *  [input param]
+ *      A pointer to uint8_t type with content of bt_vendor_lpm_mode_t.
+ *      Typecasting conversion: (uint8_t *) param.
+ *  [return]
+ *      0 - default, don't care.
+ *  [callback]
+ *      Must call lpm_cb to notify the stack of the completion of LPM
+ *      disable/enable process once it has been done.
+ */
+    BT_VND_OP_LPM_SET_MODE,
+
+/*  [operation]
+ *      Assert or Deassert LPM WAKE on BT Controller.
+ *  [input param]
+ *      A pointer to uint8_t type with content of bt_vendor_lpm_wake_state_t.
+ *      Typecasting conversion: (uint8_t *) param.
+ *  [return]
+ *      0 - default, don't care.
+ *  [callback]
+ *      None.
+ */
+    BT_VND_OP_LPM_WAKE_SET_STATE,
+
+/*  [operation]
+ *      Perform any vendor specific commands related to audio state changes.
+ *  [input param]
+ *      a pointer to bt_vendor_op_audio_state_t indicating what audio state is
+ *      set.
+ *  [return]
+ *      0 - default, don't care.
+ *  [callback]
+ *      None.
+ */
+    BT_VND_OP_SET_AUDIO_STATE,
+
+/*  [operation]
+ *      The epilog call to the vendor module so that it can perform any
+ *      vendor-specific processes (e.g. send a HCI_RESET to BT Controller)
+ *      before the caller calls for cleanup().
+ *  [input param]
+ *      None.
+ *  [return]
+ *      0 - default, don't care.
+ *  [callback]
+ *      Must call epilog_cb to notify the stack of the completion of vendor
+ *      specific epilog process once it has been done.
+ */
+    BT_VND_OP_EPILOG,
+} bt_vendor_opcode_t;
+
+/** Power on/off control states */
+typedef enum {
+    BT_VND_PWR_OFF,
+    BT_VND_PWR_ON,
+}  bt_vendor_power_state_t;
+
+/** Define HCI channel identifier in the file descriptors array
+    used in BT_VND_OP_USERIAL_OPEN operation.
+ */
+typedef enum {
+    CH_CMD,     // HCI Command channel
+    CH_EVT,     // HCI Event channel
+    CH_ACL_OUT, // HCI ACL downstream channel
+    CH_ACL_IN,  // HCI ACL upstream channel
+
+    CH_MAX      // Total channels
+}  bt_vendor_hci_channels_t;
+
+/** LPM disable/enable request */
+typedef enum {
+    BT_VND_LPM_DISABLE,
+    BT_VND_LPM_ENABLE,
+} bt_vendor_lpm_mode_t;
+
+/** LPM WAKE set state request */
+typedef enum {
+    BT_VND_LPM_WAKE_ASSERT,
+    BT_VND_LPM_WAKE_DEASSERT,
+} bt_vendor_lpm_wake_state_t;
+
+/** Callback result values */
+typedef enum {
+    BT_VND_OP_RESULT_SUCCESS,
+    BT_VND_OP_RESULT_FAIL,
+} bt_vendor_op_result_t;
+
+/** audio (SCO) state changes triggering VS commands for configuration */
+typedef struct {
+    uint16_t    handle;
+    uint16_t    peer_codec;
+    uint16_t    state;
+} bt_vendor_op_audio_state_t;
+
+/*
+ * Bluetooth Host/Controller Vendor callback structure.
+ */
+
+/* vendor initialization/configuration callback */
+typedef void (*cfg_result_cb)(bt_vendor_op_result_t result);
+
+/* datapath buffer allocation callback (callout)
+ *
+ *  Vendor lib needs to request a buffer through the alloc callout function
+ *  from HCI lib if the buffer is for constructing a HCI Command packet which
+ *  will be sent through xmit_cb to BT Controller.
+ *
+ *  For each buffer allocation, the requested size needs to be big enough to
+ *  accommodate the below header plus a complete HCI packet --
+ *      typedef struct
+ *      {
+ *          uint16_t          event;
+ *          uint16_t          len;
+ *          uint16_t          offset;
+ *          uint16_t          layer_specific;
+ *      } HC_BT_HDR;
+ *
+ *  HCI lib returns a pointer to the buffer where Vendor lib should use to
+ *  construct a HCI command packet as below format:
+ *
+ *  --------------------------------------------
+ *  |  HC_BT_HDR  |  HCI command               |
+ *  --------------------------------------------
+ *  where
+ *      HC_BT_HDR.event = 0x2000;
+ *      HC_BT_HDR.len = Length of HCI command;
+ *      HC_BT_HDR.offset = 0;
+ *      HC_BT_HDR.layer_specific = 0;
+ *
+ *  For example, a HCI_RESET Command will be formed as
+ *  ------------------------
+ *  |  HC_BT_HDR  |03|0c|00|
+ *  ------------------------
+ *  with
+ *      HC_BT_HDR.event = 0x2000;
+ *      HC_BT_HDR.len = 3;
+ *      HC_BT_HDR.offset = 0;
+ *      HC_BT_HDR.layer_specific = 0;
+ */
+typedef void* (*malloc_cb)(int size);
+
+/* datapath buffer deallocation callback (callout) */
+typedef void (*mdealloc_cb)(void *p_buf);
+
+/* define callback of the cmd_xmit_cb
+ *
+ *  The callback function which HCI lib will call with the return of command
+ *  complete packet. Vendor lib is responsible for releasing the buffer passed
+ *  in at the p_mem parameter by calling dealloc callout function.
+ */
+typedef void (*tINT_CMD_CBACK)(void *p_mem);
+
+/* hci command packet transmit callback (callout)
+ *
+ *  Vendor lib calls xmit_cb callout function in order to send a HCI Command
+ *  packet to BT Controller. The buffer carrying HCI Command packet content
+ *  needs to be first allocated through the alloc callout function.
+ *  HCI lib will release the buffer for Vendor lib once it has delivered the
+ *  packet content to BT Controller.
+ *
+ *  Vendor lib needs also provide a callback function (p_cback) which HCI lib
+ *  will call with the return of command complete packet.
+ *
+ *  The opcode parameter gives the HCI OpCode (combination of OGF and OCF) of
+ *  HCI Command packet. For example, opcode = 0x0c03 for the HCI_RESET command
+ *  packet.
+ */
+typedef uint8_t (*cmd_xmit_cb)(uint16_t opcode, void *p_buf, tINT_CMD_CBACK p_cback);
+
+typedef struct {
+    /** set to sizeof(bt_vendor_callbacks_t) */
+    size_t         size;
+
+    /*
+     * Callback and callout functions have implemented in HCI libray
+     * (libbt-hci.so).
+     */
+
+    /* notifies caller result of firmware configuration request */
+    cfg_result_cb  fwcfg_cb;
+
+    /* notifies caller result of sco configuration request */
+    cfg_result_cb  scocfg_cb;
+
+    /* notifies caller result of lpm enable/disable */
+    cfg_result_cb  lpm_cb;
+
+    /* notifies the result of codec setting */
+    cfg_result_cb audio_state_cb;
+
+    /* buffer allocation request */
+    malloc_cb   alloc;
+
+    /* buffer deallocation request */
+    mdealloc_cb dealloc;
+
+    /* hci command packet transmit request */
+    cmd_xmit_cb xmit_cb;
+
+    /* notifies caller completion of epilog process */
+    cfg_result_cb epilog_cb;
+} bt_vendor_callbacks_t;
+
+/*
+ * Bluetooth Host/Controller VENDOR Interface
+ */
+typedef struct {
+    /** Set to sizeof(bt_vndor_interface_t) */
+    size_t          size;
+
+    /*
+     * Functions need to be implemented in Vendor libray (libbt-vendor.so).
+     */
+
+    /**
+     * Caller will open the interface and pass in the callback routines
+     * to the implemenation of this interface.
+     */
+    int   (*init)(const bt_vendor_callbacks_t* p_cb, unsigned char *local_bdaddr);
+
+    /**  Vendor specific operations */
+    int (*op)(bt_vendor_opcode_t opcode, void *param);
+
+    /** Closes the interface */
+    void  (*cleanup)(void);
+} bt_vendor_interface_t;
+
+
+/*
+ * External shared lib functions/data
+ */
+
+/* Entry point of DLib --
+ *      Vendor library needs to implement the body of bt_vendor_interface_t
+ *      structure and uses the below name as the variable name. HCI library
+ *      will use this symbol name to get address of the object through the
+ *      dlsym call.
+ */
+//extern const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE;
+
+#endif /* BT_VENDOR_LIB_H */
+

+ 118 - 0
components/bt/bluedroid/include/bte.h

@@ -0,0 +1,118 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2001-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  this file contains constants and definitions for the bte project
+ *
+ ******************************************************************************/
+#ifndef BTE_H
+#define BTE_H
+
+//#include <semaphore.h>
+//#include <signal.h>
+//#include <pthread.h>
+#include "bt_target.h"
+
+/* by default on shutdown, baudrate is reset 115kbits. this should NOT be need for platforms
+ * that kill BTE driver and remove/reset BT chip
+ */
+#ifndef BTE_RESET_BAUD_ON_BT_DISABLE
+#define BTE_RESET_BAUD_ON_BT_DISABLE TRUE
+#endif
+
+/* Target Modes (based on jumper settings on hardware [see user manual]) */
+enum
+{
+                            /* BTE                  BBY                     */
+                            /* J3   J4              SW3-3   SW3-2   SW3-1   */
+                            /* -------------------------------------------- */
+    BTE_MODE_SERIAL_APP,    /* OUT  OUT             OFF     OFF     OFF     Sample serial port application      */
+    BTE_MODE_APPL,    	    /* IN   OUT             OFF     OFF     ON      Target used with Tester through RPC */
+    BTE_MODE_RESERVED,      /* OUT  IN              OFF     ON      OFF     Reserved                            */
+    BTE_MODE_SAMPLE_APPS,   /* IN   IN              OFF     ON      ON      Sample applications (ICP/HSP)       */
+    BTE_MODE_DONGLE,        /* not yet supported    ON      OFF     OFF     Dongle mode                         */
+    BTE_MODE_APPL_PROTOCOL_TRACE, /* this is a fake mode do allow protocol tracing in application without rpc */
+    BTE_MODE_INVALID
+};
+
+extern volatile UINT8    bte_target_mode;    /* indicates the mode that the board is running in */
+
+/* Startup options */
+extern UINT32 bte_startup_options;                      /* Switch and jumper settings at startup */
+void bte_get_startup_options(UINT32 *p_options);        /* Platform specific function for getting startup options */
+
+#define BTE_OPTIONS_TARGET_MODE_MASK    0x00000007      /* bits 2-0 indicate target mode (QuickConnect: jp3 & jp4, BBY: SW3-1 & SW3-2)*/
+
+
+/****************************************************************************
+ * Definitions to define which type of application gets built
+ ****************************************************************************/
+#define BUILD_HCITOOL         FALSE
+#define BUILD_L2PING          FALSE
+
+
+#define LINUX_FM_DRIVER_INCLUDED		FALSE
+
+
+/* hcisu userial operations. should probably go into bt_types to avoid collisions! */
+#define BT_EVT_TO_HCISU_USERIAL_OP (0x0080 | BT_EVT_HCISU)
+/* operation for above hcisu event */
+#define BT_HCISU_USERIAL_OPEN (0)   /* open serial port calling USERIAL_Open() */
+#define BT_HCISU_USERIAL_CLOSE (1)  /* close userial port */
+/* options associated with close op */
+#define BT_HCISU_USERIAL_CL_NO_DIS_BT   0 /* do not touch bt_wake and power gpio */
+#define BT_HCISU_USERIAL_CL_DIS_BT      1 /* put power and bt_wake into defined off state to preserve
+                                             power */
+/* status codes for callback */
+/*
+#define BTE_HCISU_USERIAL_FAIL      0
+#define BTE_HCISU_USERIAL_OK        1
+typedef void (tUSERIAL_MSG_CBACK) (int status);
+typedef struct tHCISU_USERIAL_MSG_tag {
+    BT_HDR      hdr;
+    tUSERIAL_MSG_CBACK *p_cback;
+    UINT8       port;   // port number
+    UINT8       op;
+    UINT8       option; // option for operation. depends on operation
+} tHCISU_USERIAL_MSG;
+
+extern void bte_hcisu_userial_oper( tUSERIAL_MSG_CBACK *p_cback, UINT8 port, UINT8 op, UINT8 option );
+*/
+
+/* Pointer to function for sending HCI commands and data to the HCI tranport */
+extern int (*p_bte_hci_send)(UINT16 port, BT_HDR *p_msg);
+
+
+/* Protocol trace mask */
+extern UINT32 bte_proto_trace_mask;
+
+typedef struct tBAUD_REG_tag {
+    UINT8 DHBR;
+    UINT8 DLBR;
+    UINT8 ExplicitBaudRate0;
+    UINT8 ExplicitBaudRate1;
+    UINT8 ExplicitBaudRate2;
+    UINT8 ExplicitBaudRate3;
+} tBAUD_REG;
+
+#include "gki.h"
+
+extern const tBAUD_REG baud_rate_regs[];
+
+#endif  /* BTE_H */

+ 37 - 0
components/bt/bluedroid/include/bte_appl.h

@@ -0,0 +1,37 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2002-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the interface file for the bte application task
+ *
+ ******************************************************************************/
+
+#pragma once
+
+typedef struct {
+#if ((BLE_INCLUDED == TRUE) && (SMP_INCLUDED == TRUE))
+    UINT8   ble_auth_req;
+    UINT8   ble_io_cap;
+    UINT8   ble_init_key;
+    UINT8   ble_resp_key;
+    UINT8   ble_max_key_size;
+#endif
+} tBTE_APPL_CFG;
+
+extern tBTE_APPL_CFG bte_appl_cfg;

+ 244 - 0
components/bt/bluedroid/include/gki_target.h

@@ -0,0 +1,244 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 1999-2012 Broadcom Corporation
+ *
+ *  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 _GKI_TARGET_H_
+#define _GKI_TARGET_H_
+
+/******************************************************************************
+**
+** Buffer configuration
+**
+******************************************************************************/
+
+/* The size of the buffers in pool 0. */
+#ifndef GKI_BUF0_SIZE
+#define GKI_BUF0_SIZE               64
+#endif
+
+/* The number of buffers in buffer pool 0. */
+#ifndef GKI_BUF0_MAX
+#define GKI_BUF0_MAX                96
+#endif
+
+/* The ID of buffer pool 0. */
+#ifndef GKI_POOL_ID_0
+#define GKI_POOL_ID_0               0
+#endif
+
+/* The size of the buffers in pool 1. */
+#ifndef GKI_BUF1_SIZE
+#define GKI_BUF1_SIZE               288
+#endif
+
+/* The number of buffers in buffer pool 1. */
+#ifndef GKI_BUF1_MAX
+#define GKI_BUF1_MAX                52
+#endif
+
+/* The ID of buffer pool 1. */
+#ifndef GKI_POOL_ID_1
+#define GKI_POOL_ID_1               1
+#endif
+
+/* The size of the buffers in pool 2. */
+#ifndef GKI_BUF2_SIZE
+#define GKI_BUF2_SIZE               660
+#endif
+
+/* The number of buffers in buffer pool 2. */
+#ifndef GKI_BUF2_MAX
+#define GKI_BUF2_MAX                90
+#endif
+
+/* The ID of buffer pool 2. */
+#ifndef GKI_POOL_ID_2
+#define GKI_POOL_ID_2               2
+#endif
+
+/* The size of the buffers in pool 3. */
+#ifndef GKI_BUF3_SIZE
+#define GKI_BUF3_SIZE               (4096+16)
+#endif
+
+/* The number of buffers in buffer pool 3. */
+#ifndef GKI_BUF3_MAX
+#define GKI_BUF3_MAX                400
+#endif
+
+/* The ID of buffer pool 3. */
+#ifndef GKI_POOL_ID_3
+#define GKI_POOL_ID_3               3
+#endif
+
+/* The size of the largest PUBLIC fixed buffer in system. */
+#ifndef GKI_MAX_BUF_SIZE
+#define GKI_MAX_BUF_SIZE            GKI_BUF3_SIZE
+#endif
+
+/* The pool ID of the largest PUBLIC fixed buffer in system. */
+#ifndef GKI_MAX_BUF_SIZE_POOL_ID
+#define GKI_MAX_BUF_SIZE_POOL_ID    GKI_POOL_ID_3
+#endif
+
+/* Pool 4 is used for BluetoothSocket L2CAP connections */
+/* The size of the buffers in pool 4. */
+#ifndef GKI_BUF4_SIZE
+#define GKI_BUF4_SIZE               (8080+26)
+#endif
+
+/* The number of buffers in buffer pool 4. */
+#ifndef GKI_BUF4_MAX
+#define GKI_BUF4_MAX                (OBX_NUM_SERVERS + OBX_NUM_CLIENTS)
+#endif
+
+/* The ID of buffer pool 4. */
+#ifndef GKI_POOL_ID_4
+#define GKI_POOL_ID_4               4
+#endif
+
+/* The number of fixed GKI buffer pools.
+eL2CAP requires Pool ID 5
+If BTM_SCO_HCI_INCLUDED is FALSE, Pool ID 6 is unnecessary, otherwise set to 7
+If BTA_HL_INCLUDED is FALSE then Pool ID 7 is uncessary and set the following to 7, otherwise set to 8
+If BLE_INCLUDED is FALSE then Pool ID 8 is uncessary and set the following to 8, otherwise set to 9
+POOL_ID 9 is a public pool meant for large buffer needs such as SDP_DB
+*/
+#ifndef GKI_NUM_FIXED_BUF_POOLS
+#define GKI_NUM_FIXED_BUF_POOLS     10
+#endif
+
+/* The buffer pool usage mask. */
+#ifndef GKI_DEF_BUFPOOL_PERM_MASK
+/* Setting POOL_ID 9 as a public pool meant for large buffers such as SDP_DB */
+#define GKI_DEF_BUFPOOL_PERM_MASK   0xfdf0
+#endif
+
+/* The following is intended to be a reserved pool for L2CAP
+Flow control and retransmissions and intentionally kept out
+of order */
+
+/* The number of buffers in buffer pool 5. */
+#ifndef GKI_BUF5_MAX
+#define GKI_BUF5_MAX                64
+#endif
+
+/* The ID of buffer pool 5. */
+#ifndef GKI_POOL_ID_5
+#define GKI_POOL_ID_5               5
+#endif
+
+/* The size of the buffers in pool 5
+** Special pool used by L2CAP retransmissions only.  This size based on segment
+** that will fit into both DH5 and 2-DH3 packet types after accounting for GKI
+** header.  13 bytes of max headers allows us a 339 payload max. (in btui_app.txt)
+** Note: 748 used for insight scriptwrapper with CAT-2 scripts.
+*/
+#ifndef GKI_BUF5_SIZE
+#define GKI_BUF5_SIZE               748
+#endif
+
+/* The following is intended to be a reserved pool for SCO
+over HCI data and intentionally kept out of order */
+
+/* The ID of buffer pool 6. */
+#ifndef GKI_POOL_ID_6
+#define GKI_POOL_ID_6               6
+#endif
+
+/* The size of the buffers in pool 6,
+  BUF_SIZE = max SCO data 255 + sizeof(BT_HDR) = 8 + SCO packet header 3 + padding 2 = 268 */
+#ifndef GKI_BUF6_SIZE
+#define GKI_BUF6_SIZE               268
+#endif
+
+/* The number of buffers in buffer pool 6. */
+#ifndef GKI_BUF6_MAX
+#define GKI_BUF6_MAX                60
+#endif
+
+
+/* The following pool is a dedicated pool for HDP
+   If a shared pool is more desirable then
+   1. set BTA_HL_LRG_DATA_POOL_ID to the desired Gki Pool ID
+   2. make sure that the shared pool size is larger than 9472
+   3. adjust GKI_NUM_FIXED_BUF_POOLS accordingly since
+      POOL ID 7 is not needed
+*/
+
+/* The ID of buffer pool 7. */
+#ifndef GKI_POOL_ID_7
+#define GKI_POOL_ID_7               7
+#endif
+
+/* The size of the buffers in pool 7 */
+#ifndef GKI_BUF7_SIZE
+#define GKI_BUF7_SIZE               (10240 + 24)
+#endif
+
+/* The number of buffers in buffer pool 7. */
+#ifndef GKI_BUF7_MAX
+#define GKI_BUF7_MAX                2
+#endif
+
+/* The following pool is a dedicated pool for GATT
+   If a shared pool is more desirable then
+   1. set GATT_DB_POOL_ID to the desired Gki Pool ID
+   2. make sure that the shared pool size fit a common GATT database needs
+   3. adjust GKI_NUM_FIXED_BUF_POOLS accordingly since
+      POOL ID 8 is not needed
+*/
+
+/* The ID of buffer pool 8. */
+#ifndef GKI_POOL_ID_8
+#define GKI_POOL_ID_8               8
+#endif
+
+/* The size of the buffers in pool 8 */
+#ifndef GKI_BUF8_SIZE
+#define GKI_BUF8_SIZE               128
+#endif
+
+/* The number of buffers in buffer pool 8. */
+#ifndef GKI_BUF8_MAX
+#define GKI_BUF8_MAX                30
+#endif
+
+/* The following pool is  meant for large allocations such as SDP_DB */
+#ifndef GKI_POOL_ID_9
+#define GKI_POOL_ID_9              9
+#endif
+
+#ifndef GKI_BUF9_SIZE
+#define GKI_BUF9_SIZE            8192
+#endif
+
+#ifndef GKI_BUF9_MAX
+#define GKI_BUF9_MAX           5
+#endif
+
+/* The number of fixed and dynamic buffer pools */
+#ifndef GKI_NUM_TOTAL_BUF_POOLS
+#define GKI_NUM_TOTAL_BUF_POOLS     10
+#endif
+
+int gki_init(void);
+void gki_clean_up(void);
+
+//void LogMsg (UINT32 trace_set_mask, const char *fmt_str, ...);
+
+#endif /*_GKI_TARGET_H_*/

+ 216 - 0
components/bt/bluedroid/main/bte_init.c

@@ -0,0 +1,216 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2000-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This module contains the routines that initialize the stack components.
+ *  It must be called before the BTU task is started.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#include <string.h>
+
+/* Stack Configuation Related Init Definaton
+ * TODO: Now Just Unmask these defination until stack layer is OK
+ */
+
+#ifndef BTA_INCLUDED
+#define BTA_INCLUDED FALSE
+#endif
+
+#if (defined(RFCOMM_INCLUDED) && RFCOMM_INCLUDED == TRUE)
+// Include initialization functions definitions
+#include "port_api.h"
+#endif
+
+#if (defined(BNEP_INCLUDED) && BNEP_INCLUDED == TRUE)
+#include "bnep_api.h"
+#endif
+
+#if (defined(GAP_INCLUDED) && GAP_INCLUDED == TRUE)
+#include "gap_api.h"
+#endif
+
+#if (defined(PAN_INCLUDED) && PAN_INCLUDED == TRUE)
+#include "pan_api.h"
+#endif
+
+#if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE)
+#include "avrc_api.h"
+#endif
+
+#if (defined(A2D_INCLUDED) && A2D_INCLUDED == TRUE)
+#include "a2d_api.h"
+#endif
+
+#if (defined(HID_HOST_INCLUDED) && HID_HOST_INCLUDED == TRUE)
+#include "hidh_api.h"
+#endif
+
+#if (defined(MCA_INCLUDED) && MCA_INCLUDED == TRUE)
+#include "mca_api.h"
+#endif
+
+#if (defined(BLE_INCLUDED) && BLE_INCLUDED == TRUE)
+#include "gatt_api.h"
+#if (defined(SMP_INCLUDED) && SMP_INCLUDED == TRUE)
+#include "smp_api.h"
+#endif
+#endif
+
+//BTA Modules
+#if BTA_INCLUDED == TRUE && BTA_DYNAMIC_MEMORY == TRUE
+#include "bta_api.h"
+#include "bta_sys.h"
+
+#include "bta_ag_int.h"
+
+#if BTA_HS_INCLUDED == TRUE
+#include "bta_hs_int.h"
+#endif
+
+#include "bta_dm_int.h"
+
+#if BTA_AR_INCLUDED==TRUE
+#include "bta_ar_int.h"
+#endif
+#if BTA_AV_INCLUDED==TRUE
+#include "bta_av_int.h"
+#endif
+
+#if BTA_HH_INCLUDED==TRUE
+#include "bta_hh_int.h"
+#endif
+
+#if BTA_JV_INCLUDED==TRUE
+#include "bta_jv_int.h"
+tBTA_JV_CB *bta_jv_cb_ptr = NULL;
+#endif
+
+#if BTA_HL_INCLUDED == TRUE
+#include "bta_hl_int.h"
+#endif
+
+#if BTA_GATT_INCLUDED == TRUE
+#include "bta_gattc_int.h"
+#include "bta_gatts_int.h"
+#endif
+
+#if BTA_PAN_INCLUDED==TRUE
+#include "bta_pan_int.h"
+#endif
+
+#include "bta_sys_int.h"
+
+// control block for patch ram downloading
+#include "bta_prm_int.h"
+
+#endif // BTA_INCLUDED
+
+
+/*****************************************************************************
+**                          F U N C T I O N S                                *
+******************************************************************************/
+
+/*****************************************************************************
+**
+** Function         BTE_InitStack
+**
+** Description      Initialize control block memory for each component.
+**
+**                  Note: The core stack components must be called
+**                      before creating the BTU Task.  The rest of the
+**                      components can be initialized at a later time if desired
+**                      as long as the component's init function is called
+**                      before accessing any of its functions.
+**
+** Returns          void
+**
+******************************************************************************/
+void BTE_InitStack(void)
+{
+#if (defined(RFCOMM_INCLUDED) && RFCOMM_INCLUDED == TRUE)
+    //Initialize the optional stack components
+    RFCOMM_Init();
+#endif
+
+    //BNEP and its profiles
+#if (defined(BNEP_INCLUDED) && BNEP_INCLUDED == TRUE)
+    BNEP_Init();
+
+#if (defined(PAN_INCLUDED) && PAN_INCLUDED == TRUE)
+    PAN_Init();
+#endif  // PAN
+#endif  // BNEP Included
+
+
+    //AVDT and its profiles
+#if (defined(A2D_INCLUDED) && A2D_INCLUDED == TRUE)
+    A2D_Init();
+#endif  // AADP
+
+#if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE)
+    AVRC_Init();
+#endif
+
+#if (defined(GAP_INCLUDED) && GAP_INCLUDED == TRUE)
+    GAP_Init();
+#endif
+
+#if (defined(HID_HOST_INCLUDED) && HID_HOST_INCLUDED == TRUE)
+    HID_HostInit();
+#endif
+
+#if (defined(MCA_INCLUDED) && MCA_INCLUDED == TRUE)
+    MCA_Init();
+#endif
+
+    //BTA Modules
+#if (BTA_INCLUDED == TRUE && BTA_DYNAMIC_MEMORY == TRUE)
+    memset((void*)bta_sys_cb_ptr, 0, sizeof(tBTA_SYS_CB));
+    memset((void*)bta_dm_cb_ptr, 0, sizeof(tBTA_DM_CB));
+    memset((void*)bta_dm_search_cb_ptr, 0, sizeof(tBTA_DM_SEARCH_CB));
+    memset((void*)bta_dm_di_cb_ptr, 0, sizeof(tBTA_DM_DI_CB));
+    memset((void*)bta_prm_cb_ptr, 0, sizeof(tBTA_PRM_CB));
+    memset((void*)bta_ag_cb_ptr, 0, sizeof(tBTA_AG_CB));
+#if BTA_HS_INCLUDED == TRUE
+    memset((void*)bta_hs_cb_ptr, 0, sizeof(tBTA_HS_CB));
+#endif
+#if BTA_AR_INCLUDED==TRUE
+    memset((void *)bta_ar_cb_ptr, 0, sizeof(tBTA_AR_CB));
+#endif
+#if BTA_AV_INCLUDED==TRUE
+    memset((void *)bta_av_cb_ptr, 0, sizeof(tBTA_AV_CB));
+#endif
+#if BTA_HH_INCLUDED==TRUE
+    memset((void *)bta_hh_cb_ptr, 0, sizeof(tBTA_HH_CB));
+#endif
+#if BTA_HL_INCLUDED==TRUE
+    memset((void *)bta_hl_cb_ptr, 0, sizeof(tBTA_HL_CB));
+#endif
+#if BTA_GATT_INCLUDED==TRUE
+    memset((void *)bta_gattc_cb_ptr, 0, sizeof(tBTA_GATTC_CB));
+    memset((void *)bta_gatts_cb_ptr, 0, sizeof(tBTA_GATTS_CB));
+#endif
+#if BTA_PAN_INCLUDED==TRUE
+    memset((void *)bta_pan_cb_ptr, 0, sizeof(tBTA_PAN_CB));
+#endif
+
+#endif // BTA_INCLUDED == TRUE
+}

+ 324 - 0
components/bt/bluedroid/main/bte_main.c

@@ -0,0 +1,324 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  Filename:      bte_main.c
+ *
+ *  Description:   Contains BTE core stack initialization and shutdown code
+ *
+ ******************************************************************************/
+
+
+#include "bt_defs.h"
+#include "bte.h"
+#include "btu.h"
+#include "bt_trace.h"
+#include "osi.h"
+#include "alarm.h"
+#include "fixed_queue.h"
+#include "hash_map.h"
+#include "hash_functions.h"
+#include "controller.h"
+#include "hci_layer.h"
+
+#include "bt_app_common.h"
+//#include "bluedroid_test.h"
+/*
+#define LOG_TAG "bt_main"
+
+#include <cutils/properties.h>
+#include <fcntl.h>
+#include <hardware/bluetooth.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "osi/include/alarm.h"
+#include "bta_api.h"
+#include "bt_hci_bdroid.h"
+#include "bte.h"
+#include "btif_common.h"
+#include "btu.h"
+#include "btsnoop.h"
+#include "bt_utils.h"
+#include "btcore/include/counter.h"
+#include "btcore/include/module.h"
+#include "osi/include/fixed_queue.h"
+#include "osi/include/future.h"
+#include "gki.h"
+#include "osi/include/hash_functions.h"
+#include "osi/include/hash_map.h"
+#include "hci_layer.h"
+#include "osi/include/osi.h"
+#include "osi/include/log.h"
+#include "stack_config.h"
+#include "osi/include/thread.h"
+*/
+/*******************************************************************************
+**  Constants & Macros
+*******************************************************************************/
+
+/* Run-time configuration file for BLE*/
+/*
+#ifndef BTE_BLE_STACK_CONF_FILE
+#define BTE_BLE_STACK_CONF_FILE "/etc/bluetooth/ble_stack.conf"
+#endif
+*/
+/******************************************************************************
+**  Variables
+******************************************************************************/
+
+/*******************************************************************************
+**  Static variables
+*******************************************************************************/
+static const hci_t *hci;
+static void bte_main_enable(void);
+/*******************************************************************************
+**  Static functions
+*******************************************************************************/
+
+/*******************************************************************************
+**  Externs
+*******************************************************************************/
+//extern void bte_load_ble_conf(const char *p_path);
+fixed_queue_t *btu_hci_msg_queue;
+
+/******************************************************************************
+**
+** Function         bte_main_boot_entry
+**
+** Description      BTE MAIN API - Entry point for BTE chip/stack initialization
+**
+** Returns          None
+**
+******************************************************************************/
+void bte_main_boot_entry(void)
+{
+    if (gki_init())
+        LOG_ERROR("%s: Init GKI Module Failure.\n", __func__);
+
+    hci = hci_layer_get_interface();
+    if (!hci)
+      LOG_ERROR("%s could not get hci layer interface.\n", __func__);
+
+    btu_hci_msg_queue = fixed_queue_new(SIZE_MAX);
+    if (btu_hci_msg_queue == NULL) {
+      LOG_ERROR("%s unable to allocate hci message queue.\n", __func__);
+      return;
+    }
+
+    //Caution: No event dispatcher defined now in hci layer 
+    //data_dispatcher_register_default(hci->event_dispatcher, btu_hci_msg_queue);
+    hci->set_data_queue(btu_hci_msg_queue);
+
+    osi_alarm_init();
+
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+    //bte_load_ble_conf(BTE_BLE_STACK_CONF_FILE);
+#endif
+    //TODO: STACK CONFIG Module init
+    //module_init(get_module(STACK_CONFIG_MODULE));
+
+    // set up bt application task
+#if (defined(BT_APP_DEMO) && BT_APP_DEMO == TRUE)
+    bt_app1_task_start_up();
+    // bt_app_start_up();
+#endif
+
+    //Enbale HCI
+    bte_main_enable();
+
+    // LOG_ERROR("Test HCI Command\n");
+    // controller_get_interface()->devctl_reset(NULL);
+
+    //LOG_ERROR("Test bta_enable_bt\n");
+    //bt_test_bta_enable_bt();
+
+    //LOG_ERROR("Test ble_advertise\n");
+    //bt_test_ble_advertise();
+
+}
+
+/******************************************************************************
+**
+** Function         bte_main_shutdown
+**
+** Description      BTE MAIN API - Shutdown code for BTE chip/stack
+**
+** Returns          None
+**
+******************************************************************************/
+void bte_main_shutdown()
+{
+    //data_dispatcher_register_default(hci_layer_get_interface()->event_dispatcher, NULL);
+    hci->set_data_queue(NULL);
+    fixed_queue_free(btu_hci_msg_queue, NULL);
+
+    btu_hci_msg_queue = NULL;
+
+/*
+    module_clean_up(get_module(STACK_CONFIG_MODULE));
+
+    module_clean_up(get_module(COUNTER_MODULE));
+    module_clean_up(get_module(GKI_MODULE));
+*/
+
+    gki_clean_up();
+}
+
+/******************************************************************************
+**
+** Function         bte_main_enable
+**
+** Description      BTE MAIN API - Creates all the BTE tasks. Should be called
+**                  part of the Bluetooth stack enable sequence
+**
+** Returns          None
+**
+******************************************************************************/
+static void bte_main_enable(void)
+{
+    LOG_DEBUG("Enable HCI\n");
+    if (hci_start_up()) {
+        LOG_ERROR("Start HCI Host Layer Failure\n");
+        return;
+    }
+
+    //Now Test Case Not Supported BTU
+    LOG_ERROR("Startup BTU\n");
+    BTU_StartUp();
+}
+
+/******************************************************************************
+**
+** Function         bte_main_disable
+**
+** Description      BTE MAIN API - Destroys all the BTE tasks. Should be called
+**                  part of the Bluetooth stack disable sequence
+**
+** Returns          None
+**
+******************************************************************************/
+void bte_main_disable(void)
+{
+/*
+    APPL_TRACE_DEBUG("%s", __FUNCTION__);
+
+    module_shut_down(get_module(HCI_MODULE));
+    module_shut_down(get_module(BTSNOOP_MODULE));
+*/
+
+    hci_shut_down();
+
+    BTU_ShutDown();
+}
+
+/******************************************************************************
+**
+** Function         bte_main_postload_cfg
+**
+** Description      BTE MAIN API - Stack postload configuration
+**
+** Returns          None
+**
+******************************************************************************/
+void bte_main_postload_cfg(void)
+{
+    hci->do_postload();
+}
+
+#if (defined(HCILP_INCLUDED) && HCILP_INCLUDED == TRUE)
+/******************************************************************************
+**
+** Function         bte_main_enable_lpm
+**
+** Description      BTE MAIN API - Enable/Disable low power mode operation
+**
+** Returns          None
+**
+******************************************************************************/
+void bte_main_enable_lpm(BOOLEAN enable)
+{
+    /*Enable Low power ?*/
+    //hci->send_low_power_command(enable ? LPM_ENABLE : LPM_DISABLE);
+}
+
+/******************************************************************************
+**
+** Function         bte_main_lpm_allow_bt_device_sleep
+**
+** Description      BTE MAIN API - Allow BT controller goest to sleep
+**
+** Returns          None
+**
+******************************************************************************/
+void bte_main_lpm_allow_bt_device_sleep()
+{
+    /**/
+    //hci->send_low_power_command(LPM_WAKE_DEASSERT);
+}
+
+/******************************************************************************
+**
+** Function         bte_main_lpm_wake_bt_device
+**
+** Description      BTE MAIN API - Wake BT controller up if it is in sleep mode
+**
+** Returns          None
+**
+******************************************************************************/
+void bte_main_lpm_wake_bt_device()
+{
+    //hci->send_low_power_command(LPM_WAKE_ASSERT);
+}
+#endif  // HCILP_INCLUDED
+
+/******************************************************************************
+**
+** Function         bte_main_hci_send
+**
+** Description      BTE MAIN API - This function is called by the upper stack to
+**                  send an HCI message. The function displays a protocol trace
+**                  message (if enabled), and then calls the 'transmit' function
+**                  associated with the currently selected HCI transport
+**
+** Returns          None
+**
+******************************************************************************/
+void bte_main_hci_send (BT_HDR *p_msg, UINT16 event)
+{
+    UINT16 sub_event = event & BT_SUB_EVT_MASK;  /* local controller ID */
+
+    p_msg->event = event;
+
+    //counter_add("main.tx.packets", 1);
+    //counter_add("main.tx.bytes", p_msg->len);
+
+    if((sub_event == LOCAL_BR_EDR_CONTROLLER_ID) || \
+       (sub_event == LOCAL_BLE_CONTROLLER_ID))
+    {
+        hci->transmit_downward(event, p_msg);
+    }
+    else
+    {
+        //APPL_TRACE_ERROR("Invalid Controller ID. Discarding message.");
+        GKI_freebuf(p_msg);
+    }
+}

+ 12 - 0
components/bt/bluedroid/mk.sh

@@ -0,0 +1,12 @@
+#!/bin/bash
+
+FIND_F=component.mk
+MV_F=Makefile.backup
+
+for mkf in `find . -name "$FIND_F"`
+do
+	echo $mkf
+	mkf_n=`echo $mkf | sed -n "s/$FIND_F/$MV_F/p"`
+	echo $mkf_n
+	mv $mkf $mkf_n
+done

+ 184 - 0
components/bt/bluedroid/osi/alarm.c

@@ -0,0 +1,184 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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.
+ *
+ ******************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include "bt_defs.h"
+#include "bt_trace.h"
+#include "alarm.h"
+#include "allocator.h"
+#include "list.h"
+#include "thread.h"
+#include "freertos/FreeRTOSConfig.h"
+#include "freertos/xtensa_api.h"
+#include "rom/ets_sys.h"
+
+#define RTC_TIMER_TICKS_TO_MS(ticks)            ((ticks/625)<<1 + (ticks-(ticks/625)*625)/312)
+
+
+#define BT_ALARM_START_WAIT_TICKS	100
+#define BT_ALARM_STOP_WAIT_TICKS	100
+#define BT_ALARM_FREE_WAIT_TICKS	100
+#define BT_ALARM_CHG_PERIOD_WAIT_TICKS	100
+
+static struct alarm_t alarm_cbs[ALARM_CBS_NUM];
+
+void osi_alarm_init(void)
+{
+	memset(&alarm_cbs[0], 0x00, sizeof(alarm_cbs));
+}
+
+static struct alarm_t *alarm_cbs_lookfor_available(void)
+{
+	int i;
+
+	for (i = 0; i < ALARM_CBS_NUM; i++) {
+		if (alarm_cbs[i].alarm_hdl == NULL) { //available
+			ets_printf(">>>> %d %08x<<<<\n", i, &alarm_cbs[i]);
+			return &alarm_cbs[i];
+		}
+	}
+
+	return NULL;
+}
+
+static void alarm_cb_handler(TimerHandle_t xTimer)
+{
+	struct alarm_t *alarm;
+
+	ets_printf("*********************************************************\n");
+	if (!xTimer) {
+		ets_printf("TimerName: NULL\n");
+		return;
+	}
+
+	alarm = pvTimerGetTimerID(xTimer);
+	ets_printf("TimerID %08x, Name %s\n", alarm, pcTimerGetTimerName(xTimer));
+	if (alarm->cb) {
+		alarm->cb(alarm->cb_data);
+	}
+}
+
+osi_alarm_t *osi_alarm_new(char *alarm_name, osi_alarm_callback_t callback, void *data, period_ms_t timer_expire)
+{
+	struct alarm_t *timer_id;
+	TimerHandle_t t;
+
+	if (timer_expire == 0)
+		timer_expire = 1000;
+
+	/* TODO mutex lock */
+	timer_id = alarm_cbs_lookfor_available();
+	if (!timer_id) {
+		ets_printf("%s full\n", __func__);
+		return NULL;
+	}
+
+	t = xTimerCreate(alarm_name, timer_expire / portTICK_PERIOD_MS, pdFALSE, timer_id, alarm_cb_handler);
+	if (!t) {
+		ets_printf("%s error\n", __func__);
+		return NULL;
+	}
+
+	timer_id->alarm_hdl = t;
+	timer_id->cb = callback;
+	timer_id->cb_data = data;
+	/* TODO mutex unlock */
+
+	return timer_id;
+}
+
+int osi_alarm_free(osi_alarm_t *alarm)
+{
+	if (!alarm) {
+		ets_printf("%s null\n", __func__);
+		return -1;
+	}
+
+	if (xTimerDelete(alarm->alarm_hdl, BT_ALARM_FREE_WAIT_TICKS) != pdPASS) {
+		ets_printf("%s error\n", __func__);
+		return -2;
+	}
+
+	/* TODO mutex lock */
+	memset(alarm, 0x00, sizeof(osi_alarm_t));
+	/* TODO mutex unlock */
+
+	return 0;
+}
+
+
+int osi_alarm_set(osi_alarm_t *alarm, period_ms_t timeout) {
+	if (!alarm) {
+		ets_printf("%s null\n", __func__);
+		return -1;
+	}
+
+	if (xTimerChangePeriod(alarm->alarm_hdl, timeout / portTICK_PERIOD_MS, BT_ALARM_CHG_PERIOD_WAIT_TICKS) != pdPASS) {
+		ets_printf("%s chg period error\n", __func__);
+		return -2;
+	}
+
+	if (xTimerStart(alarm->alarm_hdl, BT_ALARM_START_WAIT_TICKS) != pdPASS) {
+		ets_printf("%s start error\n", __func__);
+		return -3;
+	}
+
+	return 0;
+}
+
+
+int osi_alarm_cancel(osi_alarm_t *alarm) {
+	if (!alarm) {
+		ets_printf("%s null\n", __func__);
+		return -1;
+	}
+
+	if (xTimerStop(alarm->alarm_hdl, BT_ALARM_STOP_WAIT_TICKS) != pdPASS) {
+		ets_printf("%s error\n", __func__);
+		return -2;
+	}
+
+	return 0;
+}
+
+static uint32_t alarm_current_tick(void) {
+  return xTaskGetTickCount();
+}
+
+// todo: this is not accurate
+// max return value: 0xffffffff / 312 = 13765920 = 0xD20D20
+period_ms_t osi_alarm_now(void) {
+  return RTC_TIMER_TICKS_TO_MS((alarm_current_tick()));
+}
+
+period_ms_t osi_alarm_get_remaining_ms(const osi_alarm_t *alarm)
+{
+	/* TODO: use FreeRTOS timer.c implement ??? */
+	return 0xffffffff;
+}
+
+// pre-condition: 0 <= t1, t2 <= 0xD20D20
+// return value: 0<= ret <=0XD20D20
+period_ms_t osi_alarm_time_diff(period_ms_t t1, period_ms_t t2) {
+#define MAX_ALARM_TIME_MS     (0xD20D20)
+  int32_t diff = (int32_t)(t1) - (int32_t)(t2);
+  if (diff < 0)
+    diff += MAX_ALARM_TIME_MS;
+  return (period_ms_t)diff;
+}

+ 58 - 0
components/bt/bluedroid/osi/allocator.c

@@ -0,0 +1,58 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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.
+ *
+ ******************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+
+#include "bt_defs.h"
+#include "allocator.h"
+
+extern void *pvPortZalloc(size_t size);
+extern void vPortFree(void *pv);
+
+char *osi_strdup(const char *str) {
+  size_t size = strlen(str) + 1;  // + 1 for the null terminator
+  char *new_string = (char *)calloc(1, size);
+
+  if (!new_string)
+    return NULL;
+
+  memcpy(new_string, str, size);
+  return new_string;
+}
+
+void *osi_malloc(size_t size) {
+  return calloc(1, size);
+}
+
+void *osi_calloc(size_t size) {
+  return calloc(1, size);
+}
+
+void osi_free(void *ptr) {
+  free(ptr);
+}
+
+const allocator_t allocator_malloc = {
+  osi_malloc,
+  osi_free
+};
+
+const allocator_t allocator_calloc = {
+  osi_calloc,
+  osi_free
+};

+ 96 - 0
components/bt/bluedroid/osi/buffer.c

@@ -0,0 +1,96 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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.
+ *
+ ******************************************************************************/
+#include <stdint.h>
+#include "bt_trace.h"
+#include "allocator.h"
+#include "buffer.h"
+#include "bt_defs.h"
+#include "bt_trace.h"
+
+struct buffer_t {
+  buffer_t *root;
+  size_t refcount;
+  size_t length;
+  uint8_t data[];
+};
+
+buffer_t *buffer_new(size_t size) {
+  assert(size > 0);
+
+  buffer_t *buffer = osi_malloc(sizeof(buffer_t) + size);
+  if (!buffer) {
+    LOG_ERROR("%s unable to allocate buffer of %zu bytes.", __func__, size);
+    return NULL;
+  }
+
+  buffer->root = buffer;
+  buffer->refcount = 1;
+  buffer->length = size;
+
+  return buffer;
+}
+
+buffer_t *buffer_new_ref(const buffer_t *buf) {
+  assert(buf != NULL);
+  return buffer_new_slice(buf, buf->length);
+}
+
+buffer_t *buffer_new_slice(const buffer_t *buf, size_t slice_size) {
+  assert(buf != NULL);
+  assert(slice_size > 0);
+  assert(slice_size <= buf->length);
+
+  buffer_t *ret = osi_calloc(sizeof(buffer_t));
+  if (!ret) {
+    LOG_ERROR("%s unable to allocate new buffer for slice of length %zu.", __func__, slice_size);
+    return NULL;
+  }
+
+  ret->root = buf->root;
+  ret->refcount = SIZE_MAX;
+  ret->length = slice_size;
+
+  ++buf->root->refcount;
+
+  return ret;
+}
+
+void buffer_free(buffer_t *buffer) {
+  if (!buffer)
+    return;
+
+  if (buffer->root != buffer) {
+    // We're a leaf node. Delete the root node if we're the last referent.
+    if (--buffer->root->refcount == 0)
+      osi_free(buffer->root);
+    osi_free(buffer);
+  } else if (--buffer->refcount == 0) {
+    // We're a root node. Roots are only deleted when their refcount goes to 0.
+    osi_free(buffer);
+  }
+}
+
+void *buffer_ptr(const buffer_t *buf) {
+  assert(buf != NULL);
+  return buf->root->data + buf->root->length - buf->length;
+}
+
+size_t buffer_length(const buffer_t *buf) {
+  assert(buf != NULL);
+  return buf->length;
+}

+ 187 - 0
components/bt/bluedroid/osi/fixed_queue.c

@@ -0,0 +1,187 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#include "bt_defs.h"
+#include "allocator.h"
+#include "fixed_queue.h"
+#include "list.h"
+#include "osi.h"
+#include "bt_trace.h"
+
+typedef struct fixed_queue_t {
+  
+  list_t *list;
+  //semaphore_t *enqueue_sem;
+  //semaphore_t *dequeue_sem;
+  pthread_mutex_t lock;
+  size_t capacity;
+
+  fixed_queue_cb dequeue_ready;
+/*
+  reactor_object_t *dequeue_object;
+  fixed_queue_cb dequeue_ready;
+  void *dequeue_context;
+*/
+} fixed_queue_t;
+
+//static void internal_dequeue_ready(void *context);
+
+fixed_queue_t *fixed_queue_new(size_t capacity) {
+  fixed_queue_t *ret = osi_calloc(sizeof(fixed_queue_t));
+  if (!ret)
+    goto error;
+
+  pthread_mutex_init(&ret->lock, NULL);
+  ret->capacity = capacity;
+
+  ret->list = list_new(NULL);
+  if (!ret->list)
+    goto error;
+
+/*
+  ret->enqueue_sem = semaphore_new(capacity);
+  if (!ret->enqueue_sem)
+    goto error;
+
+  ret->dequeue_sem = semaphore_new(0);
+  if (!ret->dequeue_sem)
+    goto error;
+*/
+  return ret;
+
+error:;
+  fixed_queue_free(ret, NULL);
+  return NULL;
+}
+
+void fixed_queue_free(fixed_queue_t *queue, fixed_queue_free_cb free_cb) {
+  const list_node_t *node;
+  if (!queue)
+    return;
+
+//  fixed_queue_unregister_dequeue(queue);
+
+  if (free_cb)
+    for (node = list_begin(queue->list); node != list_end(queue->list); node = list_next(node))
+      free_cb(list_node(node));
+
+  list_free(queue->list);
+//  semaphore_free(queue->enqueue_sem);
+//  semaphore_free(queue->dequeue_sem);
+  pthread_mutex_destroy(&queue->lock);
+  osi_free(queue);
+}
+
+bool fixed_queue_is_empty(fixed_queue_t *queue) {
+  bool is_empty = false;
+  assert(queue != NULL);
+
+  pthread_mutex_lock(&queue->lock);
+  is_empty = list_is_empty(queue->list);
+  pthread_mutex_unlock(&queue->lock);
+
+  return is_empty;
+}
+
+size_t fixed_queue_capacity(fixed_queue_t *queue) {
+  assert(queue != NULL);
+
+  return queue->capacity;
+}
+
+void fixed_queue_enqueue(fixed_queue_t *queue, void *data) {
+  assert(queue != NULL);
+  assert(data != NULL);
+
+//  semaphore_wait(queue->enqueue_sem);
+
+  pthread_mutex_lock(&queue->lock);
+
+  list_append(queue->list, data);
+  pthread_mutex_unlock(&queue->lock);
+
+//  semaphore_post(queue->dequeue_sem);
+}
+
+void *fixed_queue_dequeue(fixed_queue_t *queue) {
+  void *ret = NULL;
+  assert(queue != NULL);
+
+//  semaphore_wait(queue->dequeue_sem);
+
+  pthread_mutex_lock(&queue->lock);
+  ret = list_front(queue->list);
+  list_remove(queue->list, ret);
+  pthread_mutex_unlock(&queue->lock);
+
+//  semaphore_post(queue->enqueue_sem);
+
+  return ret;
+}
+
+/*
+void *fixed_queue_try_dequeue(fixed_queue_t *queue) {
+  void *ret = NULL;
+  assert(queue != NULL);
+
+  if (!semaphore_try_wait(queue->dequeue_sem))
+    return NULL;
+
+  pthread_mutex_lock(&queue->lock);
+  ret = list_front(queue->list);
+  list_remove(queue->list, ret);
+  pthread_mutex_unlock(&queue->lock);
+
+  semaphore_post(queue->enqueue_sem);
+
+  return ret;
+}
+
+int fixed_queue_get_dequeue_fd(const fixed_queue_t *queue) {
+  assert(queue != NULL);
+  return semaphore_get_fd(queue->dequeue_sem);
+}
+*/
+void fixed_queue_register_dequeue(fixed_queue_t *queue, fixed_queue_cb ready_cb) {
+  assert(queue != NULL);
+  assert(ready_cb != NULL);
+
+  queue->dequeue_ready = ready_cb;
+}
+
+void fixed_queue_unregister_dequeue(fixed_queue_t *queue) {
+  assert(queue != NULL);
+
+  queue->dequeue_ready = NULL;
+}
+
+void fixed_queue_process(fixed_queue_t *queue) {
+  if (queue == NULL)
+    return;
+
+  if (queue->dequeue_ready)
+    queue->dequeue_ready(queue);
+}
+/*
+static void internal_dequeue_ready(void *context) {
+  assert(context != NULL);
+
+  fixed_queue_t *queue = context;
+  queue->dequeue_ready(queue, queue->dequeue_context);
+}
+*/

+ 42 - 0
components/bt/bluedroid/osi/hash_functions.c

@@ -0,0 +1,42 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+
+#include "hash_functions.h"
+
+hash_index_t hash_function_naive(const void *key) {
+  return (hash_index_t)key;
+}
+
+hash_index_t hash_function_integer(const void *key) {
+  return ((hash_index_t)key) * 2654435761;
+}
+
+hash_index_t hash_function_pointer(const void *key) {
+  return ((hash_index_t)key) * 2654435761;
+}
+
+hash_index_t hash_function_string(const void *key) {
+  hash_index_t hash = 5381;
+  const char *name = (const char *)key;
+  size_t string_len = strlen(name);
+  for (size_t i = 0; i < string_len; ++i)
+    hash = ((hash << 5) + hash ) + name[i];
+  return hash;
+}

Некоторые файлы не были показаны из-за большого количества измененных файлов