Bluedroid stack dynamic allocation changes to optimise DRAM usage

Structures allocated dynamically:
tACL_CONN, tBTM_PM_MCB, tBTM_SEC_DEV_REC, tGATT_TCB, tGATT_CLCB, tL2C_LCB, tL2C_CCB, tSDP_RECORD
Total dynamic allocation size ~19KB.
Peak dram usage reduced by ~12KB when in BT classic + BLE scenario(1 a2dp sink + 1 BLE gatt server)
This commit is contained in:
sushant.chougule 2020-07-02 00:05:54 +05:30
parent ec661be38d
commit 0583a04969
30 changed files with 1035 additions and 815 deletions

View File

@ -34,6 +34,10 @@ bool list_is_empty(const list_t *list);
// |list| may not be NULL.
bool list_contains(const list_t *list, const void *data);
// Returns list_node which contains |data|, NULL otherwise.
// |list| may not be NULL.
list_node_t *list_get_node(const list_t *list, const void *data);
// Returns the length of the |list|. |list| may not be NULL.
size_t list_length(const list_t *list);

View File

@ -68,6 +68,21 @@ bool list_contains(const list_t *list, const void *data)
return false;
}
list_node_t *list_get_node(const list_t *list, const void *data)
{
assert(list != NULL);
assert(data != NULL);
list_node_t *p_node_ret = NULL;
for (list_node_t *node = list_begin(list); node != list_end(list); node = list_next(node)) {
if (list_node(node) == data) {
p_node_ret = node;
break;
}
}
return p_node_ret;
}
size_t list_length(const list_t *list)
{
assert(list != NULL);

View File

@ -46,6 +46,7 @@
#include "l2c_int.h"
#include "stack/hcidefs.h"
//#include "bt_utils.h"
#include "osi/list.h"
static void btm_read_remote_features (UINT16 handle);
static void btm_read_remote_ext_features (UINT16 handle, UINT8 page_number);
@ -71,6 +72,8 @@ void btm_acl_init (void)
btm_cb.btm_def_link_policy = 0;
btm_cb.p_bl_changed_cb = NULL;
#endif
btm_cb.p_acl_db_list = list_new(osi_free_func);
btm_cb.p_pm_mode_db_list = list_new(osi_free_func);
/* Initialize nonzero defaults */
btm_cb.btm_def_link_super_tout = HCI_DEFAULT_INACT_TOUT;
@ -90,49 +93,56 @@ void btm_acl_init (void)
** NULL if not found.
**
*******************************************************************************/
tACL_CONN *btm_bda_to_acl (BD_ADDR bda, tBT_TRANSPORT transport)
BOOLEAN btm_get_acl_db(void *p_acl_db_node, void *context)
{
tACL_CONN *p = &btm_cb.acl_db[0];
UINT16 xx;
if (bda) {
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p++) {
if ((p->in_use) && (!memcmp (p->remote_addr, bda, BD_ADDR_LEN))
tACL_CONN *p_acl_db =(tACL_CONN *)p_acl_db_node;
BOOLEAN ret = TRUE;
tACL_DB_PARAM *p_param = (tACL_DB_PARAM *)context;
switch(p_param->type) {
case ACL_DB_BDA:
{
UINT8 *p_bda = (UINT8 *)p_param->p_data1;
#if BLE_INCLUDED == TRUE
&& p->transport == transport
tBT_TRANSPORT transport = (tBT_TRANSPORT)(*((UINT8 *)p_param->p_data2));
#endif
) {
BTM_TRACE_DEBUG ("btm_bda_to_acl found\n");
return (p);
}
}
if (p_acl_db->in_use
&& !memcmp(p_bda, p_acl_db->remote_addr, BD_ADDR_LEN)
#if BLE_INCLUDED == TRUE
&& transport == p_acl_db->transport
#endif
) {
ret = FALSE;
}
break;
}
case ACL_DB_HANDLE:
{
UINT16 handle = (UINT16) *((UINT16 *)p_param->p_data1);
if (p_acl_db->in_use && handle == p_acl_db->hci_handle) {
ret = FALSE;
}
break;
}
default:
break;
}
/* If here, no BD Addr found */
return ((tACL_CONN *)NULL);
return ret;
}
/*******************************************************************************
**
** Function btm_handle_to_acl_index
**
** Description This function returns the FIRST acl_db entry for the passed hci_handle.
**
** Returns index to the acl_db or MAX_L2CAP_LINKS.
**
*******************************************************************************/
UINT8 btm_handle_to_acl_index (UINT16 hci_handle)
tACL_CONN *btm_bda_to_acl (BD_ADDR bda, tBT_TRANSPORT transport)
{
tACL_CONN *p = &btm_cb.acl_db[0];
UINT8 xx;
BTM_TRACE_DEBUG ("btm_handle_to_acl_index\n");
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p++) {
if ((p->in_use) && (p->hci_handle == hci_handle)) {
break;
}
tACL_CONN *p_acl_db = NULL;
list_node_t *p_node = NULL;
tACL_DB_PARAM acl_params;
acl_params.type = ACL_DB_BDA;
acl_params.p_data1 = (void *)bda;
acl_params.p_data2 = (void *)&transport;
p_node = list_foreach(btm_cb.p_acl_db_list, btm_get_acl_db, (void *)&acl_params);
if (p_node) {
p_acl_db = list_node(p_node);
}
/* If here, no BD Addr found */
return (xx);
return (p_acl_db);
}
/*******************************************************************************
@ -147,17 +157,21 @@ UINT8 btm_handle_to_acl_index (UINT16 hci_handle)
*******************************************************************************/
tACL_CONN *btm_handle_to_acl (UINT16 hci_handle)
{
tACL_CONN *p = &btm_cb.acl_db[0];
UINT8 xx;
BTM_TRACE_DEBUG ("btm_handle_to_acl_index\n");
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p++) {
if ((p->in_use) && (p->hci_handle == hci_handle)) {
return(p);
}
tACL_CONN *p_acl_db = NULL;
tACL_DB_PARAM acl_params;
list_node_t *p_node = NULL;
BTM_TRACE_DEBUG ("btm_handle_to_acl_index: %d\n", hci_handle);
acl_params.type = ACL_DB_HANDLE;
acl_params.p_data1 = (void *)&hci_handle;
acl_params.p_data2 = NULL;
p_node = list_foreach(btm_cb.p_acl_db_list, btm_get_acl_db, (void *)&acl_params);
if (p_node) {
p_acl_db = list_node(p_node);
}
/* If here, no BD Addr found */
return ((tACL_CONN *)NULL);
return (p_acl_db);
}
#if BLE_PRIVACY_SPT == TRUE
@ -228,7 +242,6 @@ void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, BD_NAME bdn,
{
tBTM_SEC_DEV_REC *p_dev_rec = NULL;
tACL_CONN *p;
UINT8 xx;
BTM_TRACE_DEBUG ("btm_acl_created hci_handle=%d link_role=%d transport=%d\n",
hci_handle, link_role, transport);
@ -247,8 +260,13 @@ void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, BD_NAME bdn,
}
/* Allocate acl_db entry */
for (xx = 0, p = &btm_cb.acl_db[0]; xx < MAX_L2CAP_LINKS; xx++, p++) {
if (!p->in_use) {
if (list_length(btm_cb.p_acl_db_list) >= MAX_L2CAP_LINKS) {
return;
}
else {
p = (tACL_CONN *)osi_malloc(sizeof(tACL_CONN));
if (p && list_append(btm_cb.p_acl_db_list, p)) {
memset(p, 0, sizeof(tACL_CONN));
p->in_use = TRUE;
p->hci_handle = hci_handle;
p->link_role = link_role;
@ -274,7 +292,10 @@ void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, BD_NAME bdn,
#endif
p->switch_role_state = BTM_ACL_SWKEY_STATE_IDLE;
btm_pm_sm_alloc(xx);
p->p_pm_mode_db = btm_pm_sm_alloc();
#if BTM_PM_DEBUG == TRUE
BTM_TRACE_DEBUG( "btm_pm_sm_alloc handle:%d st:%d", hci_handle, p->p_pm_mode_db->state);
#endif // BTM_PM_DEBUG
#if (CLASSIC_BT_INCLUDED == TRUE)
btm_sec_update_legacy_auth_state(p, BTM_ACL_LEGACY_AUTH_NONE);
@ -462,8 +483,12 @@ void btm_acl_removed (BD_ADDR bda, tBT_TRANSPORT transport)
}
#endif
list_remove(btm_cb.p_pm_mode_db_list, p->p_pm_mode_db);
/* Clear the ACL connection data */
memset(p, 0, sizeof(tACL_CONN));
if (list_remove(btm_cb.p_acl_db_list, p)) {
p = NULL;
}
}
}
@ -480,17 +505,16 @@ void btm_acl_removed (BD_ADDR bda, tBT_TRANSPORT transport)
*******************************************************************************/
void btm_acl_device_down (void)
{
tACL_CONN *p = &btm_cb.acl_db[0];
UINT16 xx;
tACL_CONN *p = NULL;
BTM_TRACE_DEBUG ("btm_acl_device_down\n");
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p++) {
if (p->in_use) {
BTM_TRACE_DEBUG ("hci_handle=%d HCI_ERR_HW_FAILURE \n", p->hci_handle );
l2c_link_hci_disc_comp (p->hci_handle, HCI_ERR_HW_FAILURE);
}
}
for (list_node_t *p_node = list_begin(btm_cb.p_acl_db_list); p_node; p_node = list_next(p_node)) {
p = list_node(p_node);
if (!p && p->in_use) {
BTM_TRACE_DEBUG ("hci_handle=%d HCI_ERR_HW_FAILURE \n", p->hci_handle );
l2c_link_hci_disc_comp (p->hci_handle, HCI_ERR_HW_FAILURE);
}
}
}
/*******************************************************************************
**
** Function btm_acl_update_busy_level
@ -730,20 +754,15 @@ tBTM_STATUS BTM_SwitchRole (BD_ADDR remote_bd_addr, UINT8 new_role, tBTM_CMPL_CB
void btm_acl_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable)
{
tACL_CONN *p;
UINT8 xx;
tBTM_SEC_DEV_REC *p_dev_rec;
tBTM_BL_ROLE_CHG_DATA evt;
BTM_TRACE_DEBUG ("btm_acl_encrypt_change handle=%d status=%d encr_enabl=%d\n",
handle, status, encr_enable);
xx = btm_handle_to_acl_index(handle);
/* don't assume that we can never get a bad hci_handle */
if (xx < MAX_L2CAP_LINKS) {
p = &btm_cb.acl_db[xx];
} else {
p = btm_handle_to_acl(handle);
if (p == NULL) {
return;
}
/* Process Role Switch if active */
if (p->switch_role_state == BTM_ACL_SWKEY_STATE_ENCRYPTION_OFF) {
/* if encryption turn off failed we still will try to switch role */
@ -913,44 +932,40 @@ void BTM_SetDefaultLinkPolicy (UINT16 settings)
*******************************************************************************/
void btm_read_remote_version_complete (UINT8 *p)
{
tACL_CONN *p_acl_cb = &btm_cb.acl_db[0];
tACL_CONN *p_acl_cb = NULL;
UINT8 status;
UINT16 handle;
int xx;
BTM_TRACE_DEBUG ("btm_read_remote_version_complete\n");
STREAM_TO_UINT8 (status, p);
STREAM_TO_UINT16 (handle, p);
/* Look up the connection by handle and copy features */
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_acl_cb++) {
if ((p_acl_cb->in_use) && (p_acl_cb->hci_handle == handle)) {
if (status == HCI_SUCCESS) {
STREAM_TO_UINT8 (p_acl_cb->lmp_version, p);
STREAM_TO_UINT16 (p_acl_cb->manufacturer, p);
STREAM_TO_UINT16 (p_acl_cb->lmp_subversion, p);
}
#if BLE_INCLUDED == TRUE
if (p_acl_cb->transport == BT_TRANSPORT_LE) {
if(p_acl_cb->link_role == HCI_ROLE_MASTER) {
if (HCI_LE_DATA_LEN_EXT_SUPPORTED(p_acl_cb->peer_le_features)) {
uint16_t data_length = controller_get_interface()->get_ble_default_data_packet_length();
uint16_t data_txtime = controller_get_interface()->get_ble_default_data_packet_txtime();
btsnd_hcic_ble_set_data_length(p_acl_cb->hci_handle, data_length, data_txtime);
}
l2cble_notify_le_connection (p_acl_cb->remote_addr);
} else {
//slave role, read remote feature
btsnd_hcic_ble_read_remote_feat(p_acl_cb->hci_handle);
}
}
#endif
break;
p_acl_cb = btm_handle_to_acl(handle);
if (p_acl_cb) {
if (status == HCI_SUCCESS) {
STREAM_TO_UINT8 (p_acl_cb->lmp_version, p);
STREAM_TO_UINT16 (p_acl_cb->manufacturer, p);
STREAM_TO_UINT16 (p_acl_cb->lmp_subversion, p);
}
#if BLE_INCLUDED == TRUE
if (p_acl_cb->transport == BT_TRANSPORT_LE) {
if(p_acl_cb->link_role == HCI_ROLE_MASTER) {
if (HCI_LE_DATA_LEN_EXT_SUPPORTED(p_acl_cb->peer_le_features)) {
uint16_t data_length = controller_get_interface()->get_ble_default_data_packet_length();
uint16_t data_txtime = controller_get_interface()->get_ble_default_data_packet_txtime();
btsnd_hcic_ble_set_data_length(p_acl_cb->hci_handle, data_length, data_txtime);
}
l2cble_notify_le_connection (p_acl_cb->remote_addr);
} else {
//slave role, read remote feature
btsnd_hcic_ble_read_remote_feat(p_acl_cb->hci_handle);
}
}
#endif
}
}
/*******************************************************************************
**
** Function btm_process_remote_ext_features
@ -1015,17 +1030,16 @@ void btm_process_remote_ext_features (tACL_CONN *p_acl_cb, UINT8 num_read_pages)
*******************************************************************************/
void btm_read_remote_features (UINT16 handle)
{
UINT8 acl_idx;
tACL_CONN *p_acl_cb;
BTM_TRACE_DEBUG("btm_read_remote_features() handle: %d\n", handle);
if ((acl_idx = btm_handle_to_acl_index(handle)) >= MAX_L2CAP_LINKS) {
p_acl_cb = btm_handle_to_acl(handle);
if (p_acl_cb == NULL) {
BTM_TRACE_ERROR("btm_read_remote_features handle=%d invalid\n", handle);
return;
return;
}
p_acl_cb = &btm_cb.acl_db[acl_idx];
p_acl_cb->num_read_pages = 0;
memset (p_acl_cb->peer_lmp_features, 0, sizeof(p_acl_cb->peer_lmp_features));
@ -1067,7 +1081,6 @@ void btm_read_remote_features_complete (UINT8 *p)
tACL_CONN *p_acl_cb;
UINT8 status;
UINT16 handle;
UINT8 acl_idx;
BTM_TRACE_DEBUG ("btm_read_remote_features_complete\n");
STREAM_TO_UINT8 (status, p);
@ -1079,13 +1092,12 @@ void btm_read_remote_features_complete (UINT8 *p)
STREAM_TO_UINT16 (handle, p);
if ((acl_idx = btm_handle_to_acl_index(handle)) >= MAX_L2CAP_LINKS) {
p_acl_cb = btm_handle_to_acl(handle);
if (p_acl_cb == NULL) {
BTM_TRACE_ERROR("btm_read_remote_features_complete handle=%d invalid\n", handle);
return;
return;
}
p_acl_cb = &btm_cb.acl_db[acl_idx];
/* Copy the received features page */
STREAM_TO_ARRAY(p_acl_cb->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0], p,
HCI_FEATURE_BYTES_PER_PAGE);
@ -1123,7 +1135,6 @@ void btm_read_remote_ext_features_complete (UINT8 *p)
tACL_CONN *p_acl_cb;
UINT8 page_num, max_page;
UINT16 handle;
UINT8 acl_idx;
BTM_TRACE_DEBUG ("btm_read_remote_ext_features_complete\n");
@ -1133,7 +1144,8 @@ void btm_read_remote_ext_features_complete (UINT8 *p)
STREAM_TO_UINT8 (max_page, p);
/* Validate parameters */
if ((acl_idx = btm_handle_to_acl_index(handle)) >= MAX_L2CAP_LINKS) {
p_acl_cb = btm_handle_to_acl(handle);
if (p_acl_cb == NULL) {
BTM_TRACE_ERROR("btm_read_remote_ext_features_complete handle=%d invalid\n", handle);
return;
}
@ -1143,7 +1155,6 @@ void btm_read_remote_ext_features_complete (UINT8 *p)
return;
}
p_acl_cb = &btm_cb.acl_db[acl_idx];
/* Copy the received features page */
STREAM_TO_ARRAY(p_acl_cb->peer_lmp_features[page_num], p, HCI_FEATURE_BYTES_PER_PAGE);
@ -1180,18 +1191,16 @@ void btm_read_remote_ext_features_complete (UINT8 *p)
void btm_read_remote_ext_features_failed (UINT8 status, UINT16 handle)
{
tACL_CONN *p_acl_cb;
UINT8 acl_idx;
BTM_TRACE_WARNING ("btm_read_remote_ext_features_failed (status 0x%02x) for handle %d\n",
status, handle);
if ((acl_idx = btm_handle_to_acl_index(handle)) >= MAX_L2CAP_LINKS) {
p_acl_cb = btm_handle_to_acl(handle);
if (p_acl_cb == NULL) {
BTM_TRACE_ERROR("btm_read_remote_ext_features_failed handle=%d invalid\n", handle);
return;
return;
}
p_acl_cb = &btm_cb.acl_db[acl_idx];
/* Process supported features only */
btm_process_remote_ext_features (p_acl_cb, 1);
@ -1363,12 +1372,7 @@ UINT16 BTM_GetNumAclLinks (void)
{
uint16_t num_acl = 0;
for (uint16_t i = 0; i < MAX_L2CAP_LINKS; ++i) {
if (btm_cb.acl_db[i].in_use) {
++num_acl;
}
}
num_acl = list_length(btm_cb.p_acl_db_list);
return num_acl;
}
@ -1427,12 +1431,14 @@ UINT16 BTM_GetHCIConnHandle (BD_ADDR remote_bda, tBT_TRANSPORT transport)
*******************************************************************************/
void btm_process_clk_off_comp_evt (UINT16 hci_handle, UINT16 clock_offset)
{
UINT8 xx;
tACL_CONN *p_acl_cb = NULL;
BTM_TRACE_DEBUG ("btm_process_clk_off_comp_evt\n");
/* Look up the connection by handle and set the current mode */
if ((xx = btm_handle_to_acl_index(hci_handle)) < MAX_L2CAP_LINKS) {
btm_cb.acl_db[xx].clock_offset = clock_offset;
p_acl_cb = btm_handle_to_acl(hci_handle);
if (p_acl_cb) {
p_acl_cb->clock_offset = clock_offset;
}
}
/*******************************************************************************
@ -1849,7 +1855,7 @@ tBTM_STATUS BTM_RegBusyLevelNotif (tBTM_BL_CHANGE_CB *p_cb, UINT8 *p_level,
*******************************************************************************/
tBTM_STATUS BTM_SetQoS (BD_ADDR bd, FLOW_SPEC *p_flow, tBTM_CMPL_CB *p_cb)
{
tACL_CONN *p = &btm_cb.acl_db[0];
tACL_CONN *p = NULL;
BTM_TRACE_API ("BTM_SetQoS: BdAddr: %02x%02x%02x%02x%02x%02x\n",
bd[0], bd[1], bd[2],
@ -2119,8 +2125,7 @@ void btm_read_tx_power_complete (UINT8 *p, BOOLEAN is_ble)
tBTM_CMPL_CB *p_cb = btm_cb.devcb.p_tx_power_cmpl_cb;
tBTM_TX_POWER_RESULTS results;
UINT16 handle;
tACL_CONN *p_acl_cb = &btm_cb.acl_db[0];
UINT16 index;
tACL_CONN *p_acl_cb = NULL;
BTM_TRACE_DEBUG ("btm_read_tx_power_complete\n");
btu_stop_timer (&btm_cb.devcb.tx_power_timer);
@ -2138,12 +2143,10 @@ void btm_read_tx_power_complete (UINT8 *p, BOOLEAN is_ble)
STREAM_TO_UINT8 (results.tx_power, p);
/* Search through the list of active channels for the correct BD Addr */
for (index = 0; index < MAX_L2CAP_LINKS; index++, p_acl_cb++) {
if ((p_acl_cb->in_use) && (handle == p_acl_cb->hci_handle)) {
memcpy (results.rem_bda, p_acl_cb->remote_addr, BD_ADDR_LEN);
break;
}
}
p_acl_cb = btm_handle_to_acl(handle);
if (p_acl_cb) {
memcpy (results.rem_bda, p_acl_cb->remote_addr, BD_ADDR_LEN);
}
}
#if BLE_INCLUDED == TRUE
else {
@ -2176,8 +2179,7 @@ void btm_read_rssi_complete (UINT8 *p)
tBTM_CMPL_CB *p_cb = btm_cb.devcb.p_rssi_cmpl_cb;
tBTM_RSSI_RESULTS results;
UINT16 handle;
tACL_CONN *p_acl_cb = &btm_cb.acl_db[0];
UINT16 index;
tACL_CONN *p_acl_cb = NULL;
BTM_TRACE_DEBUG ("btm_read_rssi_complete\n");
btu_stop_timer (&btm_cb.devcb.rssi_timer);
@ -2197,12 +2199,10 @@ void btm_read_rssi_complete (UINT8 *p)
results.rssi, results.hci_status);
/* Search through the list of active channels for the correct BD Addr */
for (index = 0; index < MAX_L2CAP_LINKS; index++, p_acl_cb++) {
if ((p_acl_cb->in_use) && (handle == p_acl_cb->hci_handle)) {
memcpy (results.rem_bda, p_acl_cb->remote_addr, BD_ADDR_LEN);
break;
}
}
p_acl_cb = btm_handle_to_acl(handle);
if (p_acl_cb) {
memcpy (results.rem_bda, p_acl_cb->remote_addr, BD_ADDR_LEN);
}
} else {
results.status = BTM_ERR_PROCESSING;
}
@ -2226,8 +2226,7 @@ void btm_read_link_quality_complete (UINT8 *p)
tBTM_CMPL_CB *p_cb = btm_cb.devcb.p_lnk_qual_cmpl_cb;
tBTM_LINK_QUALITY_RESULTS results;
UINT16 handle;
tACL_CONN *p_acl_cb = &btm_cb.acl_db[0];
UINT16 index;
tACL_CONN *p_acl_cb = NULL;
BTM_TRACE_DEBUG ("btm_read_link_quality_complete\n");
btu_stop_timer (&btm_cb.devcb.lnk_quality_timer);
@ -2247,12 +2246,10 @@ void btm_read_link_quality_complete (UINT8 *p)
results.link_quality, results.hci_status);
/* Search through the list of active channels for the correct BD Addr */
for (index = 0; index < MAX_L2CAP_LINKS; index++, p_acl_cb++) {
if ((p_acl_cb->in_use) && (handle == p_acl_cb->hci_handle)) {
memcpy (results.rem_bda, p_acl_cb->remote_addr, BD_ADDR_LEN);
break;
}
}
p_acl_cb = btm_handle_to_acl(handle);
if (p_acl_cb) {
memcpy (results.rem_bda, p_acl_cb->remote_addr, BD_ADDR_LEN);
}
} else {
results.status = BTM_ERR_PROCESSING;
}
@ -2553,3 +2550,16 @@ void btm_acl_chk_peer_pkt_type_support (tACL_CONN *p, UINT16 *p_pkt_type)
}
}
}
/*******************************************************************************
**
** Function btm_acl_free
**
** Description Free acl specific lists from btm control block
**
*******************************************************************************/
void btm_acl_free(void)
{
list_free(btm_cb.p_acl_db_list);
list_free(btm_cb.p_pm_mode_db_list);
}

View File

@ -74,7 +74,6 @@ BOOLEAN BTM_SecAddBleDevice (BD_ADDR bd_addr, BD_NAME bd_name, tBT_DEVICE_TYPE d
tBLE_ADDR_TYPE addr_type, UINT32 auth_mode)
{
tBTM_SEC_DEV_REC *p_dev_rec;
UINT8 i = 0;
tBTM_INQ_INFO *p_info = NULL;
BTM_TRACE_DEBUG ("BTM_SecAddBleDevice dev_type=0x%x", dev_type);
@ -85,10 +84,11 @@ BOOLEAN BTM_SecAddBleDevice (BD_ADDR bd_addr, BD_NAME bd_name, tBT_DEVICE_TYPE d
/* There is no device record, allocate one.
* If we can not find an empty spot for this one, let it fail. */
for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++) {
if (!(btm_cb.sec_dev_rec[i].sec_flags & BTM_SEC_IN_USE)) {
BTM_TRACE_DEBUG ("allocate a new dev rec idx=0x%x ", i );
p_dev_rec = &btm_cb.sec_dev_rec[i];
if (list_length(btm_cb.p_sec_dev_rec_list) < BTM_SEC_MAX_DEVICE_RECORDS) {
p_dev_rec = (tBTM_SEC_DEV_REC *)osi_malloc(sizeof(tBTM_SEC_DEV_REC));
if(p_dev_rec) {
list_append(btm_cb.p_sec_dev_rec_list, p_dev_rec);
BTM_TRACE_DEBUG ("allocate a new dev rec idx=0x%x\n", list_length(btm_cb.p_sec_dev_rec_list));
/* Mark this record as in use and initialize */
memset (p_dev_rec, 0, sizeof (tBTM_SEC_DEV_REC));
@ -104,7 +104,6 @@ BOOLEAN BTM_SecAddBleDevice (BD_ADDR bd_addr, BD_NAME bd_name, tBT_DEVICE_TYPE d
p_dev_rec->conn_params.slave_latency = BTM_BLE_CONN_PARAM_UNDEF;
BTM_TRACE_DEBUG ("hci_handl=0x%x ", p_dev_rec->ble_hci_handle );
break;
}
}
@ -312,18 +311,14 @@ void BTM_ReadConnectionAddr (BD_ADDR remote_bda, BD_ADDR local_conn_addr, tBLE_A
BOOLEAN BTM_IsBleConnection (UINT16 conn_handle)
{
#if (BLE_INCLUDED == TRUE)
UINT8 xx;
tACL_CONN *p;
BTM_TRACE_API ("BTM_IsBleConnection: conn_handle: %d", conn_handle);
xx = btm_handle_to_acl_index (conn_handle);
if (xx >= MAX_L2CAP_LINKS) {
p = btm_handle_to_acl(conn_handle);
if (!p) {
return FALSE;
}
p = &btm_cb.acl_db[xx];
return (p->transport == BT_TRANSPORT_LE);
#else
return FALSE;

View File

@ -236,17 +236,12 @@ void btm_gen_non_resolvable_private_addr (tBTM_BLE_ADDR_CBACK *p_cback, void *p)
static void btm_ble_resolve_address_cmpl(void)
{
tBTM_LE_RANDOM_CB *p_mgnt_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
tBTM_SEC_DEV_REC *p_dev_rec = NULL;
BTM_TRACE_EVENT ("btm_ble_resolve_address_cmpl p_mgnt_cb->index = %d", p_mgnt_cb->index);
if (p_mgnt_cb->index < BTM_SEC_MAX_DEVICE_RECORDS) {
p_dev_rec = &btm_cb.sec_dev_rec[p_mgnt_cb->index];
}
BTM_TRACE_EVENT ("btm_ble_resolve_address_cmpl p_mgnt_cb->p_dev_rec = 0x%08x", (uint32_t)p_mgnt_cb->p_dev_rec);
p_mgnt_cb->busy = FALSE;
(* p_mgnt_cb->p_resolve_cback)(p_dev_rec, p_mgnt_cb->p);
(* p_mgnt_cb->p_resolve_cback)(p_mgnt_cb->p_dev_rec, p_mgnt_cb->p);
}
/*******************************************************************************
**
@ -360,7 +355,7 @@ BOOLEAN btm_ble_addr_resolvable (BD_ADDR rpa, tBTM_SEC_DEV_REC *p_dev_rec)
** Returns None.
**
*******************************************************************************/
static BOOLEAN btm_ble_match_random_bda(UINT16 rec_index)
static BOOLEAN btm_ble_match_random_bda(tBTM_SEC_DEV_REC *p_dev_rec)
{
/* use the 3 MSB of bd address as prand */
@ -370,12 +365,10 @@ static BOOLEAN btm_ble_match_random_bda(UINT16 rec_index)
rand[1] = p_mgnt_cb->random_bda[1];
rand[2] = p_mgnt_cb->random_bda[0];
BTM_TRACE_EVENT("%s rec_index = %d", __func__, rec_index);
BTM_TRACE_EVENT("%s p_dev_rec = 0x%08x", __func__, (uint32_t)p_dev_rec);
if (rec_index < BTM_SEC_MAX_DEVICE_RECORDS) {
{
tSMP_ENC output;
tBTM_SEC_DEV_REC *p_dev_rec;
p_dev_rec = &btm_cb.sec_dev_rec[rec_index];
BTM_TRACE_DEBUG("sec_flags = %02x device_type = %d", p_dev_rec->sec_flags,
p_dev_rec->device_type);
@ -390,9 +383,6 @@ static BOOLEAN btm_ble_match_random_bda(UINT16 rec_index)
// not completed
return FALSE;
}
} else { /* no match found */
btm_ble_resolve_address_cmpl();
return TRUE;
}
}
#endif ///BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
@ -411,23 +401,26 @@ void btm_ble_resolve_random_addr(BD_ADDR random_bda, tBTM_BLE_RESOLVE_CBACK *p_c
{
#if (SMP_INCLUDED == TRUE)
tBTM_LE_RANDOM_CB *p_mgnt_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
list_node_t *p_node = NULL;
tBTM_SEC_DEV_REC *p_dev_rec = NULL;
BTM_TRACE_EVENT ("btm_ble_resolve_random_addr");
if ( !p_mgnt_cb->busy) {
p_mgnt_cb->p = p;
p_mgnt_cb->busy = TRUE;
p_mgnt_cb->index = 0;
p_mgnt_cb->p_dev_rec = NULL;
p_mgnt_cb->p_resolve_cback = p_cback;
memcpy(p_mgnt_cb->random_bda, random_bda, BD_ADDR_LEN);
/* start to resolve random address */
/* check for next security record */
while (TRUE) {
if (btm_ble_match_random_bda(p_mgnt_cb->index)) {
/* atch found or went through the list */
break;
}
p_mgnt_cb->index ++;
}
for (p_node = list_begin(btm_cb.p_sec_dev_rec_list); p_node; p_node = list_next(p_node)) {
p_dev_rec = list_node(p_node);
p_mgnt_cb->p_dev_rec = p_dev_rec;
if (btm_ble_match_random_bda(p_dev_rec)) {
break;
}
}
btm_ble_resolve_address_cmpl();
} else {
(*p_cback)(NULL, p);
}
@ -449,24 +442,23 @@ void btm_ble_resolve_random_addr(BD_ADDR random_bda, tBTM_BLE_RESOLVE_CBACK *p_c
tBTM_SEC_DEV_REC *btm_find_dev_by_identity_addr(BD_ADDR bd_addr, UINT8 addr_type)
{
#if BLE_PRIVACY_SPT == TRUE
UINT8 i;
tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i ++, p_dev_rec ++) {
if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE) &&
memcmp(p_dev_rec->ble.static_addr, bd_addr, BD_ADDR_LEN) == 0) {
if ((p_dev_rec->ble.static_addr_type & (~BLE_ADDR_TYPE_ID_BIT)) !=
(addr_type & (~BLE_ADDR_TYPE_ID_BIT))) {
BTM_TRACE_WARNING("%s find pseudo->random match with diff addr type: %d vs %d",
__func__, p_dev_rec->ble.static_addr_type, addr_type);
}
/* found the match */
return p_dev_rec;
}
tBTM_SEC_DEV_REC *p_dev_rec = NULL;
list_node_t *p_node = NULL;
tSecDevContext context;
context.type = SEC_DEV_ID_ADDR;
context.context.p_bd_addr = bd_addr;
context.free_check = FALSE;
p_node = list_foreach(btm_cb.p_sec_dev_rec_list, btm_find_sec_dev_in_list, &context);
if (p_node) {
p_dev_rec = list_node(p_node);
if ((p_dev_rec->ble.static_addr_type & (~BLE_ADDR_TYPE_ID_BIT)) !=
(addr_type & (~BLE_ADDR_TYPE_ID_BIT))) {
BTM_TRACE_WARNING("%s find pseudo->random match with diff addr type: %d vs %d",
__func__, p_dev_rec->ble.static_addr_type, addr_type);
}
}
return p_dev_rec;
#endif
return NULL;
}

View File

@ -1174,6 +1174,7 @@ static UINT8 btm_set_conn_mode_adv_init_addr(tBTM_BLE_INQ_CB *p_cb,
#if BLE_PRIVACY_SPT == TRUE
UINT8 i = BTM_SEC_MAX_DEVICE_RECORDS;
tBTM_SEC_DEV_REC *p_dev_rec;
list_node_t *p_node = NULL;
#endif ///BLE_PRIVACY_SPT == TRUE
evt_type = (p_cb->connectable_mode == BTM_BLE_NON_CONNECTABLE) ? \
((p_cb->scan_rsp) ? BTM_BLE_DISCOVER_EVT : BTM_BLE_NON_CONNECT_EVT )\
@ -1217,14 +1218,15 @@ static UINT8 btm_set_conn_mode_adv_init_addr(tBTM_BLE_INQ_CB *p_cb,
if ((btm_cb.ble_ctr_cb.privacy_mode == BTM_PRIVACY_1_2 && p_cb->afp != AP_SCAN_CONN_ALL) ||
btm_cb.ble_ctr_cb.privacy_mode == BTM_PRIVACY_MIXED) {
/* if enhanced privacy is required, set Identity address and matching IRK peer */
for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i ++) {
if ((btm_cb.sec_dev_rec[i].sec_flags & BTM_SEC_IN_USE) != 0 &&
(btm_cb.sec_dev_rec[i].ble.in_controller_list & BTM_RESOLVING_LIST_BIT) != 0) {
memcpy(p_peer_addr_ptr, btm_cb.sec_dev_rec[i].ble.static_addr, BD_ADDR_LEN);
*p_peer_addr_type = btm_cb.sec_dev_rec[i].ble.static_addr_type;
for (p_node = list_begin(btm_cb.p_sec_dev_rec_list); p_node; p_node = list_next(p_node)) {
p_dev_rec = list_node(p_node);
if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE) != 0 &&
(p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) != 0) {
memcpy(p_peer_addr_ptr, p_dev_rec->ble.static_addr, BD_ADDR_LEN);
*p_peer_addr_type = p_dev_rec->ble.static_addr_type;
break;
}
}
}
}
if (i != BTM_SEC_MAX_DEVICE_RECORDS) {
*p_own_addr_type = BLE_ADDR_RANDOM_ID;
@ -4130,10 +4132,9 @@ void btm_ble_timeout(TIMER_LIST_ENT *p_tle)
*******************************************************************************/
void btm_ble_read_remote_features_complete(UINT8 *p)
{
tACL_CONN *p_acl_cb = &btm_cb.acl_db[0];
tACL_CONN *p_acl_cb = NULL;
UINT16 handle;
UINT8 status;
int xx;
BTM_TRACE_EVENT ("btm_ble_read_remote_features_complete ");
@ -4145,8 +4146,9 @@ void btm_ble_read_remote_features_complete(UINT8 *p)
STREAM_TO_UINT16 (handle, p);
/* Look up the connection by handle and copy features */
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_acl_cb++) {
if ((p_acl_cb->in_use) && (p_acl_cb->hci_handle == handle)) {
p_acl_cb = btm_handle_to_acl(handle);
if (p_acl_cb) {
{
STREAM_TO_ARRAY(p_acl_cb->peer_le_features, p, BD_FEATURES_LEN);
#if BLE_INCLUDED == TRUE
/* In the original Bluedroid version, slave need to send LL_VERSION_IND(call btsnd_hcic_rmt_ver_req)
@ -4167,7 +4169,6 @@ void btm_ble_read_remote_features_complete(UINT8 *p)
}
}
#endif
break;
}
}
}

View File

@ -720,9 +720,9 @@ tBTM_STATUS BTM_BleDisableAdvInstance (UINT8 inst_id)
void btm_ble_multi_adv_vse_cback(UINT8 len, UINT8 *p)
{
UINT8 sub_event;
UINT8 adv_inst, idx;
UINT8 adv_inst;
UINT16 conn_handle;
tACL_CONN *p_acl_cb = NULL;
/* Check if this is a BLE RSSI vendor specific event */
STREAM_TO_UINT8(sub_event, p);
len--;
@ -733,11 +733,11 @@ void btm_ble_multi_adv_vse_cback(UINT8 len, UINT8 *p)
++p;
STREAM_TO_UINT16(conn_handle, p);
if ((idx = btm_handle_to_acl_index(conn_handle)) != MAX_L2CAP_LINKS) {
if ((p_acl_cb = btm_handle_to_acl(conn_handle)) != NULL) {
#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE &&
adv_inst <= BTM_BLE_MULTI_ADV_MAX && adv_inst != BTM_BLE_MULTI_ADV_DEFAULT_STD) {
memcpy(btm_cb.acl_db[idx].conn_addr, btm_multi_adv_cb.p_adv_inst[adv_inst - 1].rpa,
memcpy(p_acl_cb->conn_addr, btm_multi_adv_cb.p_adv_inst[adv_inst - 1].rpa,
BD_ADDR_LEN);
}
#endif

View File

@ -252,9 +252,12 @@ void btm_ble_clear_resolving_list_complete(UINT8 *p, UINT16 evt_len)
BTM_TRACE_DEBUG("%s resolving_list_avail_size=%d",
__func__, btm_cb.ble_ctr_cb.resolving_list_avail_size);
for (UINT8 i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; ++i) {
btm_cb.sec_dev_rec[i].ble.in_controller_list &= ~BTM_RESOLVING_LIST_BIT;
}
list_node_t *p_node = NULL;
tBTM_SEC_DEV_REC *p_dev_rec = NULL;
for (p_node = list_begin(btm_cb.p_sec_dev_rec_list); p_node; p_node = list_next(p_node)) {
p_dev_rec = list_node(p_node);
p_dev_rec->ble.in_controller_list &= ~BTM_RESOLVING_LIST_BIT;
}
}
}
@ -932,9 +935,11 @@ void btm_ble_enable_resolving_list_for_platform (UINT8 rl_mask)
return;
}
tBTM_SEC_DEV_REC *p_dev = &btm_cb.sec_dev_rec[0];
for (UINT8 i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i ++, p_dev ++) {
if ((p_dev->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) &&
tBTM_SEC_DEV_REC *p_dev = NULL;
list_node_t *p_node = NULL;
for (p_node = list_begin(btm_cb.p_sec_dev_rec_list); p_node; p_node = list_next(p_node)) {
p_dev = list_node(p_node);
if ((p_dev->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) &&
(p_dev->ble.in_controller_list & BTM_WHITE_LIST_BIT)) {
btm_ble_enable_resolving_list(rl_mask);
return;

View File

@ -72,10 +72,10 @@ BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
if (!p_dev_rec) {
/* There is no device record, allocate one.
* If we can not find an empty spot for this one, let it fail. */
for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++) {
if (!(btm_cb.sec_dev_rec[i].sec_flags & BTM_SEC_IN_USE)) {
p_dev_rec = &btm_cb.sec_dev_rec[i];
if (list_length(btm_cb.p_sec_dev_rec_list) < BTM_SEC_MAX_DEVICE_RECORDS) {
p_dev_rec = (tBTM_SEC_DEV_REC *)osi_malloc(sizeof(tBTM_SEC_DEV_REC));
if(p_dev_rec) {
list_append(btm_cb.p_sec_dev_rec_list, p_dev_rec);
/* Mark this record as in use and initialize */
memset (p_dev_rec, 0, sizeof (tBTM_SEC_DEV_REC));
p_dev_rec->sec_flags = BTM_SEC_IN_USE;
@ -88,7 +88,6 @@ BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
/* update conn params, use default value for background connection params */
memset(&p_dev_rec->conn_params, 0xff, sizeof(tBTM_LE_CONN_PRAMS));
#endif
break;
}
}
@ -96,7 +95,6 @@ BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
return (FALSE);
}
}
p_dev_rec->bond_type = BOND_TYPE_UNKNOWN; /* Default value */
p_dev_rec->timestamp = btm_cb.dev_rec_count++;
p_dev_rec->remote_secure_connection_previous_state = sc_support;
@ -240,6 +238,69 @@ char *BTM_SecReadDevName (BD_ADDR bd_addr)
return (p_name);
}
/*******************************************************************************
**
** Function btm_find_sec_dev_in_list
**
** Description Look for the record in the device database for the record
** with specified address
**
** Returns Pointer to the record or NULL
**
*******************************************************************************/
BOOLEAN btm_find_sec_dev_in_list (void *p_node_data, void *context)
{
tBTM_SEC_DEV_REC *p_sec_dev = (tBTM_SEC_DEV_REC *)p_node_data;
BOOLEAN ret = TRUE;
BOOLEAN dev_free = !(p_sec_dev->sec_flags & BTM_SEC_IN_USE);
tSecDevContext *p_context = (tSecDevContext *)context;
if (dev_free == p_context->free_check) {
switch (p_context->type) {
case SEC_DEV_BDA:
if (!memcmp(p_context->context.p_bd_addr, p_sec_dev->bd_addr, BD_ADDR_LEN)) {
ret = FALSE;
}
break;
case SEC_DEV_HDL:
if (p_context->context.handle == p_sec_dev->hci_handle
#if BLE_INCLUDED == TRUE
|| (p_context->context.handle == p_sec_dev->ble_hci_handle)
#endif
) {
ret = FALSE;
}
break;
#if BLE_PRIVACY_SPT == TRUE
case SEC_DEV_ID_ADDR:
if (!memcmp(p_context->context.p_bd_addr, p_sec_dev->ble.static_addr, BD_ADDR_LEN)) {
ret = FALSE;
}
break;
#endif //BLE_PRIVACY_SPT == TRUE
case SEC_DEV_BTDM_BDA:
if (!memcmp(p_context->context.p_bd_addr, p_sec_dev->bd_addr, BD_ADDR_LEN)) {
ret = FALSE;
}
#if BLE_INCLUDED == TRUE
// If a LE random address is looking for device record
if (!memcmp(p_sec_dev->ble.pseudo_addr, p_context->context.p_bd_addr, BD_ADDR_LEN)) {
ret = FALSE;
}
if (btm_ble_addr_resolvable(p_context->context.p_bd_addr, p_sec_dev)) {
ret = FALSE;
}
#endif
break;
default:
break;
}
}
return ret;
}
/*******************************************************************************
**
** Function btm_sec_alloc_dev
@ -254,50 +315,26 @@ tBTM_SEC_DEV_REC *btm_sec_alloc_dev (BD_ADDR bd_addr)
{
tBTM_SEC_DEV_REC *p_dev_rec = NULL;
tBTM_INQ_INFO *p_inq_info;
int i;
DEV_CLASS old_cod;
int i_new_entry = BTM_SEC_MAX_DEVICE_RECORDS;
int i_old_entry = BTM_SEC_MAX_DEVICE_RECORDS;
BTM_TRACE_EVENT ("btm_sec_alloc_dev\n");
for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++) {
/* look for old entry where device details are present */
if (!(btm_cb.sec_dev_rec[i].sec_flags & BTM_SEC_IN_USE) &&
(!memcmp (btm_cb.sec_dev_rec[i].bd_addr, bd_addr, BD_ADDR_LEN))) {
i_old_entry = i;
BTM_TRACE_EVENT ("btm_sec_alloc_dev old device found\n");
break;
}
}
for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++) {
if (!(btm_cb.sec_dev_rec[i].sec_flags & BTM_SEC_IN_USE)) {
i_new_entry = i;
break;
}
}
if (i_new_entry == BTM_SEC_MAX_DEVICE_RECORDS) {
p_dev_rec = btm_find_oldest_dev();
} else {
/* if the old device entry not present go with
new entry */
if (i_old_entry == BTM_SEC_MAX_DEVICE_RECORDS) {
p_dev_rec = &btm_cb.sec_dev_rec[i_new_entry];
/* Old devices which are not in use are deleted already */
/* Allocate new device or reuse the oldest device */
if (list_length(btm_cb.p_sec_dev_rec_list) < BTM_SEC_MAX_DEVICE_RECORDS) {
//Max number of devices is not exceeded, allocate new device
p_dev_rec = (tBTM_SEC_DEV_REC *)osi_malloc(sizeof(tBTM_SEC_DEV_REC));
if (p_dev_rec) {
list_append(btm_cb.p_sec_dev_rec_list, p_dev_rec);
} else {
p_dev_rec = &btm_cb.sec_dev_rec[i_old_entry];
memcpy (old_cod, p_dev_rec->dev_class, DEV_CLASS_LEN);
return NULL;
}
}
memset (p_dev_rec, 0, sizeof (tBTM_SEC_DEV_REC));
/* Retain the old COD for device */
if (i_old_entry != BTM_SEC_MAX_DEVICE_RECORDS) {
BTM_TRACE_EVENT ("btm_sec_alloc_dev restoring cod \n");
memcpy (p_dev_rec->dev_class, old_cod, DEV_CLASS_LEN);
else {
//Find and reuse the oldest device
p_dev_rec = btm_find_oldest_dev();
}
memset (p_dev_rec, 0, sizeof (tBTM_SEC_DEV_REC));
p_dev_rec->bond_type = BOND_TYPE_UNKNOWN; /* Default value */
p_dev_rec->sec_flags = BTM_SEC_IN_USE;
@ -374,6 +411,7 @@ void btm_sec_free_dev (tBTM_SEC_DEV_REC *p_dev_rec, tBT_TRANSPORT transport)
if(p_dev_rec->sec_flags == BTM_SEC_IN_USE) {
p_dev_rec->sec_flags = 0;
}
list_remove(btm_cb.p_sec_dev_rec_list, p_dev_rec);
}
/*******************************************************************************
@ -438,22 +476,19 @@ BOOLEAN btm_dev_support_switch (BD_ADDR bd_addr)
*******************************************************************************/
tBTM_SEC_DEV_REC *btm_find_dev_by_handle (UINT16 handle)
{
tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
int i;
tBTM_SEC_DEV_REC *p_dev_rec = NULL;
list_node_t *p_node = NULL;
tSecDevContext context;
context.type = SEC_DEV_HDL;
context.context.handle = handle;
context.free_check = FALSE;
for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++) {
if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE)
&& ((p_dev_rec->hci_handle == handle)
#if BLE_INCLUDED == TRUE
|| (p_dev_rec->ble_hci_handle == handle)
#endif
)) {
return (p_dev_rec);
}
p_node = list_foreach(btm_cb.p_sec_dev_rec_list, btm_find_sec_dev_in_list, &context);
if (p_node) {
p_dev_rec = list_node(p_node);
}
return (NULL);
return (p_dev_rec);
}
/*******************************************************************************
**
** Function btm_find_dev
@ -466,31 +501,19 @@ tBTM_SEC_DEV_REC *btm_find_dev_by_handle (UINT16 handle)
*******************************************************************************/
tBTM_SEC_DEV_REC *btm_find_dev(BD_ADDR bd_addr)
{
tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
if (bd_addr) {
for (uint8_t i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++) {
if (p_dev_rec->sec_flags & BTM_SEC_IN_USE) {
if (!memcmp (p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN)) {
return (p_dev_rec);
}
#if BLE_INCLUDED == TRUE
// If a LE random address is looking for device record
if (!memcmp(p_dev_rec->ble.pseudo_addr, bd_addr, BD_ADDR_LEN)) {
return (p_dev_rec);
}
if (btm_ble_addr_resolvable(bd_addr, p_dev_rec)) {
return (p_dev_rec);
}
#endif
}
}
if(bd_addr) {
list_node_t *p_node = NULL;
tSecDevContext context;
context.type = SEC_DEV_BTDM_BDA;
context.context.p_bd_addr = bd_addr;
context.free_check = FALSE;
p_node = list_foreach(btm_cb.p_sec_dev_rec_list, btm_find_sec_dev_in_list, &context);
if (p_node) {
return(list_node(p_node));
}
}
return (NULL);
}
/*******************************************************************************
**
** Function btm_consolidate_dev
@ -503,12 +526,13 @@ tBTM_SEC_DEV_REC *btm_find_dev(BD_ADDR bd_addr)
void btm_consolidate_dev(tBTM_SEC_DEV_REC *p_target_rec)
{
#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
tBTM_SEC_DEV_REC *p_dev_rec = NULL;
tBTM_SEC_DEV_REC temp_rec = *p_target_rec;
list_node_t *p_node = NULL;
BTM_TRACE_DEBUG("%s\n", __func__);
for (uint8_t i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++) {
for (p_node = list_begin(btm_cb.p_sec_dev_rec_list); p_node; p_node = list_next(p_node)) {
p_dev_rec = list_node(p_node);
if (p_target_rec != p_dev_rec && p_dev_rec->sec_flags & BTM_SEC_IN_USE) {
if (!memcmp (p_dev_rec->bd_addr, p_target_rec->bd_addr, BD_ADDR_LEN)) {
memcpy(p_target_rec, p_dev_rec, sizeof(tBTM_SEC_DEV_REC));
@ -522,9 +546,8 @@ void btm_consolidate_dev(tBTM_SEC_DEV_REC *p_target_rec)
p_target_rec->new_encryption_key_is_p256 = temp_rec.new_encryption_key_is_p256;
p_target_rec->no_smp_on_br = temp_rec.no_smp_on_br;
p_target_rec->bond_type = temp_rec.bond_type;
/* mark the combined record as unused */
p_dev_rec->sec_flags &= ~BTM_SEC_IN_USE;
p_dev_rec->bond_type = BOND_TYPE_UNKNOWN;
/* Remove the unused device from the list */
list_remove(btm_cb.p_sec_dev_rec_list, p_dev_rec);
break;
}
@ -533,9 +556,9 @@ void btm_consolidate_dev(tBTM_SEC_DEV_REC *p_target_rec)
if (memcmp(p_target_rec->ble.pseudo_addr, p_dev_rec->bd_addr, BD_ADDR_LEN) == 0) {
p_target_rec->ble.ble_addr_type = p_dev_rec->ble.ble_addr_type;
p_target_rec->device_type |= p_dev_rec->device_type;
p_dev_rec->sec_flags &= ~BTM_SEC_IN_USE;
p_dev_rec->bond_type = BOND_TYPE_UNKNOWN;
}
/* Remove the unused device from the list */
list_remove(btm_cb.p_sec_dev_rec_list, p_dev_rec);
}
break;
}
}
@ -578,13 +601,14 @@ tBTM_SEC_DEV_REC *btm_find_or_alloc_dev (BD_ADDR bd_addr)
*******************************************************************************/
tBTM_SEC_DEV_REC *btm_find_oldest_dev (void)
{
tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
tBTM_SEC_DEV_REC *p_oldest = p_dev_rec;
UINT32 ot = 0xFFFFFFFF;
int i;
tBTM_SEC_DEV_REC *p_dev_rec = NULL;
tBTM_SEC_DEV_REC *p_oldest = NULL;
list_node_t *p_node = NULL;
UINT32 ot = 0xFFFFFFFF;
/* First look for the non-paired devices for the oldest entry */
for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++) {
for (p_node = list_begin(btm_cb.p_sec_dev_rec_list); p_node; p_node = list_next(p_node)) {
p_dev_rec = list_node(p_node);
if (((p_dev_rec->sec_flags & BTM_SEC_IN_USE) == 0)
|| ((p_dev_rec->sec_flags & (BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LE_LINK_KEY_KNOWN)) != 0)) {
continue; /* Device is paired so skip it */
@ -601,8 +625,7 @@ tBTM_SEC_DEV_REC *btm_find_oldest_dev (void)
}
/* All devices are paired; find the oldest */
p_dev_rec = &btm_cb.sec_dev_rec[0];
for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++) {
for (p_node = list_begin(btm_cb.p_sec_dev_rec_list); p_node; p_node = list_next(p_node)) {
if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE) == 0) {
continue;
}
@ -614,7 +637,6 @@ tBTM_SEC_DEV_REC *btm_find_oldest_dev (void)
}
return (p_oldest);
}
/*******************************************************************************
**
** Function btm_get_bond_type_dev
@ -657,3 +679,27 @@ BOOLEAN btm_set_bond_type_dev(BD_ADDR bd_addr, tBTM_BOND_TYPE bond_type)
p_dev_rec->bond_type = bond_type;
return TRUE;
}
/*******************************************************************************
**
** Function btm_sec_dev_init
**
** Description Create new linked list for dynamic allocation on sec_dev_rec
**
*******************************************************************************/
void btm_sec_dev_init(void)
{
btm_cb.p_sec_dev_rec_list = list_new(osi_free_func);
}
/*******************************************************************************
**
** Function btm_sec_dev_free
**
** Description Delete sec_dev_rec list when btm_cb is being released
**
*******************************************************************************/
void btm_sec_dev_free(void)
{
list_free(btm_cb.p_sec_dev_rec_list);
}

View File

@ -145,8 +145,12 @@ static void reset_complete(void)
l2cu_device_reset ();
#if (SMP_INCLUDED == TRUE)
/* Clear current security state */
for (int devinx = 0; devinx < BTM_SEC_MAX_DEVICE_RECORDS; devinx++) {
btm_cb.sec_dev_rec[devinx].sec_state = BTM_SEC_STATE_IDLE;
{
list_node_t *p_node = NULL;
for (p_node = list_begin(btm_cb.p_sec_dev_rec_list); p_node; p_node = list_next(p_node)) {
tBTM_SEC_DEV_REC *p_dev_rec = (tBTM_SEC_DEV_REC *) list_node(p_node);
p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
}
}
#endif ///SMP_INCLUDED == TRUE
/* After the reset controller should restore all parameters to defaults. */

View File

@ -79,6 +79,7 @@ void btm_init (void)
btm_ble_lock_init();
btm_ble_sem_init();
#endif
btm_sec_dev_init();
}
@ -95,6 +96,8 @@ void btm_free(void)
{
fixed_queue_free(btm_cb.page_queue, osi_free_func);
fixed_queue_free(btm_cb.sec_pending_q, osi_free_func);
btm_acl_free();
btm_sec_dev_free();
#if BTM_DYNAMIC_MEMORY
FREE_AND_RESET(btm_cb_ptr);
#endif

View File

@ -44,7 +44,7 @@
#include "stack/hcidefs.h"
//#include "bt_utils.h"
//#include "osi/include/log.h"
#include "osi/allocator.h"
/*****************************************************************************/
/* to handle different modes */
/*****************************************************************************/
@ -76,8 +76,7 @@ const UINT8 btm_pm_md_comp_matrix[BTM_PM_NUM_SET_MODES * BTM_PM_NUM_SET_MODES] =
};
/* function prototype */
static int btm_pm_find_acl_ind(BD_ADDR remote_bda);
static tBTM_STATUS btm_pm_snd_md_req( UINT8 pm_id, int link_ind, tBTM_PM_PWR_MD *p_mode );
static tBTM_STATUS btm_pm_snd_md_req( UINT8 pm_id, UINT16 link_hdl, tBTM_PM_PWR_MD *p_mode );
#if (!CONFIG_BT_STACK_NO_LOG)
static const char *mode_to_string(tBTM_PM_MODE mode);
#endif
@ -174,11 +173,11 @@ tBTM_STATUS BTM_PmRegister (UINT8 mask, UINT8 *p_pm_id, tBTM_PM_STATUS_CBACK *p_
tBTM_STATUS BTM_SetPowerMode (UINT8 pm_id, BD_ADDR remote_bda, tBTM_PM_PWR_MD *p_mode)
{
UINT8 *p_features;
int ind, acl_ind;
int ind;
tBTM_PM_MCB *p_cb = NULL; /* per ACL link */
tBTM_PM_MODE mode;
int temp_pm_id;
tACL_CONN *p_acl_cb;
if (pm_id >= BTM_MAX_PM_RECORDS) {
pm_id = BTM_PM_SET_ONLY_ID;
@ -194,13 +193,8 @@ tBTM_STATUS BTM_SetPowerMode (UINT8 pm_id, BD_ADDR remote_bda, tBTM_PM_PWR_MD *p
/* take out the force bit */
mode = p_mode->mode & ~BTM_PM_MD_FORCE;
acl_ind = btm_pm_find_acl_ind(remote_bda);
if (acl_ind == MAX_L2CAP_LINKS) {
return (BTM_UNKNOWN_ADDR);
}
p_cb = &(btm_cb.pm_mode_db[acl_ind]);
p_acl_cb = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR);
p_cb = p_acl_cb->p_pm_mode_db;
if (mode != BTM_PM_MD_ACTIVE) {
/* check if the requested mode is supported */
ind = mode - BTM_PM_MD_HOLD; /* make it base 0 */
@ -228,9 +222,10 @@ tBTM_STATUS BTM_SetPowerMode (UINT8 pm_id, BD_ADDR remote_bda, tBTM_PM_PWR_MD *p
/* update mode database */
if ( ((pm_id != BTM_PM_SET_ONLY_ID) &&
(btm_cb.pm_reg_db[pm_id].mask & BTM_PM_REG_SET))
|| ((pm_id == BTM_PM_SET_ONLY_ID) && (btm_cb.pm_pend_link != MAX_L2CAP_LINKS)) ) {
|| ((pm_id == BTM_PM_SET_ONLY_ID)
&& (btm_cb.pm_pend_link_hdl != BTM_INVALID_HANDLE)) ) {
#if BTM_PM_DEBUG == TRUE
BTM_TRACE_DEBUG( "BTM_SetPowerMode: Saving cmd acl_ind %d temp_pm_id %d", acl_ind, temp_pm_id);
BTM_TRACE_DEBUG( "BTM_SetPowerMode: Saving cmd acl handle %d temp_pm_id %d", p_acl_cb->hci_handle, temp_pm_id);
#endif // BTM_PM_DEBUG
/* Make sure mask is set to BTM_PM_REG_SET */
btm_cb.pm_reg_db[temp_pm_id].mask |= BTM_PM_REG_SET;
@ -239,23 +234,23 @@ tBTM_STATUS BTM_SetPowerMode (UINT8 pm_id, BD_ADDR remote_bda, tBTM_PM_PWR_MD *p
}
#if BTM_PM_DEBUG == TRUE
BTM_TRACE_DEBUG( "btm_pm state:0x%x, pm_pend_link: %d", p_cb->state, btm_cb.pm_pend_link);
BTM_TRACE_DEBUG( "btm_pm state:0x%x, pm_pend_link_hdl: %d", p_cb->state, btm_cb.pm_pend_link_hdl);
#endif // BTM_PM_DEBUG
/* if mode == hold or pending, return */
if ( (p_cb->state == BTM_PM_STS_HOLD) ||
(p_cb->state == BTM_PM_STS_PENDING) ||
(btm_cb.pm_pend_link != MAX_L2CAP_LINKS) ) { /* command pending */
if (acl_ind != btm_cb.pm_pend_link) {
(btm_cb.pm_pend_link_hdl != BTM_INVALID_HANDLE) ) { /* command pending */
if (p_acl_cb->hci_handle != btm_cb.pm_pend_link_hdl) {
/* set the stored mask */
p_cb->state |= BTM_PM_STORED_MASK;
BTM_TRACE_DEBUG( "btm_pm state stored:%d", acl_ind);
BTM_TRACE_DEBUG( "btm_pm state stored:%d", p_acl_cb->hci_handle);
}
return BTM_CMD_STORED;
}
return btm_pm_snd_md_req(pm_id, acl_ind, p_mode);
return btm_pm_snd_md_req(pm_id, p_acl_cb->hci_handle, p_mode);
}
/*******************************************************************************
@ -280,13 +275,12 @@ tBTM_STATUS BTM_SetPowerMode (UINT8 pm_id, BD_ADDR remote_bda, tBTM_PM_PWR_MD *p
*******************************************************************************/
tBTM_STATUS BTM_ReadPowerMode (BD_ADDR remote_bda, tBTM_PM_MODE *p_mode)
{
int acl_ind;
if ( (acl_ind = btm_pm_find_acl_ind(remote_bda)) == MAX_L2CAP_LINKS) {
tACL_CONN *p_acl_cb = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR);
if (!p_acl_cb) {
return (BTM_UNKNOWN_ADDR);
}
*p_mode = btm_cb.pm_mode_db[acl_ind].state;
*p_mode = p_acl_cb->p_pm_mode_db->state;
return BTM_SUCCESS;
}
@ -314,21 +308,26 @@ tBTM_STATUS BTM_SetSsrParams (BD_ADDR remote_bda, UINT16 max_lat,
#if (BTM_SSR_INCLUDED == TRUE)
int acl_ind;
tBTM_PM_MCB *p_cb;
tACL_CONN *p_acl_cb = NULL;
if ( (acl_ind = btm_pm_find_acl_ind(remote_bda)) == MAX_L2CAP_LINKS) {
return (BTM_UNKNOWN_ADDR);
}
p_acl_cb = btm_bda_to_acl(remote_bda);
if (!p_acl_cb) {
return (BTM_UNKNOWN_ADDR);
}
p_cb = p_acl_cb->p_pm_mode_db;
if (BTM_PM_STS_ACTIVE == btm_cb.pm_mode_db[acl_ind].state ||
BTM_PM_STS_SNIFF == btm_cb.pm_mode_db[acl_ind].state) {
if (btsnd_hcic_sniff_sub_rate(btm_cb.acl_db[acl_ind].hci_handle, max_lat,
if (BTM_PM_STS_ACTIVE == p_cb->state ||
BTM_PM_STS_SNIFF == p_cb->state) {
if (btsnd_hcic_sniff_sub_rate(p_acl_cb->hci_handle, max_lat,
min_rmt_to, min_loc_to)) {
return BTM_SUCCESS;
} else {
return BTM_NO_RESOURCES;
}
}
p_cb = &btm_cb.pm_mode_db[acl_ind];
p_cb->max_lat = max_lat;
p_cb->min_rmt_to = min_rmt_to;
p_cb->min_loc_to = min_loc_to;
@ -364,12 +363,12 @@ void btm_pm_reset(void)
btm_cb.pm_reg_db[xx].mask = BTM_PM_REC_NOT_USED;
}
if (cb != NULL && btm_cb.pm_pend_link < MAX_L2CAP_LINKS) {
(*cb)(btm_cb.acl_db[btm_cb.pm_pend_link].remote_addr, BTM_PM_STS_ERROR, BTM_DEV_RESET, 0);
if (cb != NULL && btm_cb.pm_pend_link_hdl != BTM_INVALID_HANDLE) {
(*cb)((btm_handle_to_acl(btm_cb.pm_pend_link_hdl))->remote_addr, BTM_PM_STS_ERROR, BTM_DEV_RESET, 0);
}
/* no command pending */
btm_cb.pm_pend_link = MAX_L2CAP_LINKS;
btm_cb.pm_pend_link_hdl = BTM_INVALID_HANDLE;
}
/*******************************************************************************
@ -382,16 +381,23 @@ void btm_pm_reset(void)
** Returns void
**
*******************************************************************************/
void btm_pm_sm_alloc(UINT8 ind)
tBTM_PM_MCB *btm_pm_sm_alloc(void)
{
tBTM_PM_MCB *p_db = &btm_cb.pm_mode_db[ind]; /* per ACL link */
memset (p_db, 0, sizeof(tBTM_PM_MCB));
p_db->state = BTM_PM_ST_ACTIVE;
#if BTM_PM_DEBUG == TRUE
BTM_TRACE_DEBUG( "btm_pm_sm_alloc ind:%d st:%d", ind, p_db->state);
#endif // BTM_PM_DEBUG
tBTM_PM_MCB *p_db = (tBTM_PM_MCB *) osi_malloc(sizeof(tBTM_PM_MCB)); /* per ACL link */
if (p_db) {
memset (p_db, 0, sizeof(tBTM_PM_MCB));
p_db->state = BTM_PM_ST_ACTIVE;
if (list_length(btm_cb.p_pm_mode_db_list) >= MAX_L2CAP_LINKS) {
osi_free(p_db);
p_db = NULL;
}
if (!list_append(btm_cb.p_pm_mode_db_list, p_db)) {
osi_free(p_db);
p_db = NULL;
}
}
return p_db;
}
/*******************************************************************************
**
** Function btm_pm_find_acl_ind
@ -402,25 +408,6 @@ void btm_pm_sm_alloc(UINT8 ind)
** Returns void
**
*******************************************************************************/
static int btm_pm_find_acl_ind(BD_ADDR remote_bda)
{
tACL_CONN *p = &btm_cb.acl_db[0];
UINT8 xx;
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p++) {
if ((p->in_use) && (!memcmp (p->remote_addr, remote_bda, BD_ADDR_LEN))
#if (BLE_INCLUDED == TRUE)
&& p->transport == BT_TRANSPORT_BR_EDR
#endif // BLE_INCLUDED
) {
#if BTM_PM_DEBUG == TRUE
BTM_TRACE_DEBUG( "btm_pm_find_acl_ind ind:%d, st:%d", xx, btm_cb.pm_mode_db[xx].state);
#endif // BTM_PM_DEBUG
break;
}
}
return xx;
}
/*******************************************************************************
**
@ -557,19 +544,20 @@ static tBTM_PM_MODE btm_pm_get_set_mode(UINT8 pm_id, tBTM_PM_MCB *p_cb, tBTM_PM_
** Returns tBTM_STATUS
**, BOOLEAN *p_chg_ind
*******************************************************************************/
static tBTM_STATUS btm_pm_snd_md_req(UINT8 pm_id, int link_ind, tBTM_PM_PWR_MD *p_mode)
static tBTM_STATUS btm_pm_snd_md_req(UINT8 pm_id, UINT16 link_hdl, tBTM_PM_PWR_MD *p_mode)
{
tBTM_PM_PWR_MD md_res;
tBTM_PM_MODE mode;
tBTM_PM_MCB *p_cb = &btm_cb.pm_mode_db[link_ind];
tACL_CONN *p_acl_cb = btm_handle_to_acl(link_hdl);
tBTM_PM_MCB *p_cb = p_acl_cb->p_pm_mode_db;
BOOLEAN chg_ind = FALSE;
mode = btm_pm_get_set_mode(pm_id, p_cb, p_mode, &md_res);
md_res.mode = mode;
#if BTM_PM_DEBUG == TRUE
BTM_TRACE_DEBUG( "btm_pm_snd_md_req link_ind:%d, mode: %d",
link_ind, mode);
BTM_TRACE_DEBUG( "btm_pm_snd_md_req link_hdl:%d, mode: %d",
link_hdl, mode);
#endif // BTM_PM_DEBUG
if ( p_cb->state == mode) {
@ -593,19 +581,19 @@ static tBTM_STATUS btm_pm_snd_md_req(UINT8 pm_id, int link_ind, tBTM_PM_PWR_MD *
}
#if (BTM_SSR_INCLUDED == TRUE)
else if (BTM_PM_MD_SNIFF == md_res.mode && p_cb->max_lat) {
btsnd_hcic_sniff_sub_rate(btm_cb.acl_db[link_ind].hci_handle, p_cb->max_lat,
btsnd_hcic_sniff_sub_rate(link_hdl, p_cb->max_lat,
p_cb->min_rmt_to, p_cb->min_loc_to);
p_cb->max_lat = 0;
}
#endif // BTM_SSR_INCLUDED
/* Default is failure */
btm_cb.pm_pend_link = MAX_L2CAP_LINKS;
btm_cb.pm_pend_link_hdl = BTM_INVALID_HANDLE;
/* send the appropriate HCI command */
btm_cb.pm_pend_id = pm_id;
#if BTM_PM_DEBUG == TRUE
BTM_TRACE_DEBUG("btm_pm_snd_md_req state:0x%x, link_ind: %d", p_cb->state, link_ind);
BTM_TRACE_DEBUG("btm_pm_snd_md_req state:0x%x, link_hdl: %d", p_cb->state, link_hdl);
#endif // BTM_PM_DEBUG
BTM_TRACE_DEBUG("%s switching from %s to %s.", __func__, mode_to_string(p_cb->state), mode_to_string(md_res.mode));
@ -613,13 +601,13 @@ static tBTM_STATUS btm_pm_snd_md_req(UINT8 pm_id, int link_ind, tBTM_PM_PWR_MD *
case BTM_PM_MD_ACTIVE:
switch (p_cb->state) {
case BTM_PM_MD_SNIFF:
if (btsnd_hcic_exit_sniff_mode(btm_cb.acl_db[link_ind].hci_handle)) {
btm_cb.pm_pend_link = link_ind;
if (btsnd_hcic_exit_sniff_mode(link_hdl)) {
btm_cb.pm_pend_link_hdl = link_hdl;
}
break;
case BTM_PM_MD_PARK:
if (btsnd_hcic_exit_park_mode(btm_cb.acl_db[link_ind].hci_handle)) {
btm_cb.pm_pend_link = link_ind;
if (btsnd_hcic_exit_park_mode(link_hdl)) {
btm_cb.pm_pend_link_hdl = link_hdl;
}
break;
default:
@ -629,24 +617,24 @@ static tBTM_STATUS btm_pm_snd_md_req(UINT8 pm_id, int link_ind, tBTM_PM_PWR_MD *
break;
case BTM_PM_MD_HOLD:
if (btsnd_hcic_hold_mode (btm_cb.acl_db[link_ind].hci_handle,
if (btsnd_hcic_hold_mode (link_hdl,
md_res.max, md_res.min)) {
btm_cb.pm_pend_link = link_ind;
btm_cb.pm_pend_link_hdl = link_hdl;
}
break;
case BTM_PM_MD_SNIFF:
if (btsnd_hcic_sniff_mode (btm_cb.acl_db[link_ind].hci_handle,
if (btsnd_hcic_sniff_mode (link_hdl,
md_res.max, md_res.min, md_res.attempt,
md_res.timeout)) {
btm_cb.pm_pend_link = link_ind;
btm_cb.pm_pend_link_hdl = link_hdl;
}
break;
case BTM_PM_MD_PARK:
if (btsnd_hcic_park_mode (btm_cb.acl_db[link_ind].hci_handle,
if (btsnd_hcic_park_mode (link_hdl,
md_res.max, md_res.min)) {
btm_cb.pm_pend_link = link_ind;
btm_cb.pm_pend_link_hdl = link_hdl;
}
break;
default:
@ -654,10 +642,10 @@ static tBTM_STATUS btm_pm_snd_md_req(UINT8 pm_id, int link_ind, tBTM_PM_PWR_MD *
break;
}
if (btm_cb.pm_pend_link == MAX_L2CAP_LINKS) {
if (btm_cb.pm_pend_link_hdl == BTM_INVALID_HANDLE) {
/* the command was not sent */
#if BTM_PM_DEBUG == TRUE
BTM_TRACE_DEBUG( "pm_pend_link: %d", btm_cb.pm_pend_link);
BTM_TRACE_DEBUG( "pm_pend_link_hdl: %d", btm_cb.pm_pend_link_hdl);
#endif // BTM_PM_DEBUG
return (BTM_NO_RESOURCES);
}
@ -678,15 +666,18 @@ static tBTM_STATUS btm_pm_snd_md_req(UINT8 pm_id, int link_ind, tBTM_PM_PWR_MD *
*******************************************************************************/
static void btm_pm_check_stored(void)
{
int xx;
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++) {
if (btm_cb.pm_mode_db[xx].state & BTM_PM_STORED_MASK) {
btm_cb.pm_mode_db[xx].state &= ~BTM_PM_STORED_MASK;
BTM_TRACE_DEBUG( "btm_pm_check_stored :%d", xx);
btm_pm_snd_md_req(BTM_PM_SET_ONLY_ID, xx, NULL);
tACL_CONN *p_acl_cb = NULL;
list_node_t *p_node = NULL;
for (p_node = list_begin(btm_cb.p_acl_db_list); p_node; p_node = list_next(p_node)) {
p_acl_cb = list_node(p_node);
if (p_acl_cb->p_pm_mode_db->state & BTM_PM_STORED_MASK) {
p_acl_cb->p_pm_mode_db->state &= ~BTM_PM_STORED_MASK;
BTM_TRACE_DEBUG( "btm_pm_check_stored :%d", p_acl_cb->hci_handle);
btm_pm_snd_md_req(BTM_PM_SET_ONLY_ID, p_acl_cb->hci_handle, NULL);
break;
}
}
}
@ -706,12 +697,15 @@ void btm_pm_proc_cmd_status(UINT8 status)
{
tBTM_PM_MCB *p_cb;
tBTM_PM_STATUS pm_status;
tACL_CONN *p_acl_cb;
if (btm_cb.pm_pend_link >= MAX_L2CAP_LINKS) {
if (btm_cb.pm_pend_link_hdl == BTM_INVALID_HANDLE) {
return;
}
p_cb = &btm_cb.pm_mode_db[btm_cb.pm_pend_link];
p_acl_cb = btm_handle_to_acl(btm_cb.pm_pend_link_hdl);
p_cb = p_acl_cb->p_pm_mode_db;
if (status == HCI_SUCCESS) {
p_cb->state = BTM_PM_ST_PENDING;
@ -726,15 +720,15 @@ void btm_pm_proc_cmd_status(UINT8 status)
/* notify the caller is appropriate */
if ( (btm_cb.pm_pend_id != BTM_PM_SET_ONLY_ID) &&
(btm_cb.pm_reg_db[btm_cb.pm_pend_id].mask & BTM_PM_REG_NOTIF) ) {
(*btm_cb.pm_reg_db[btm_cb.pm_pend_id].cback)(btm_cb.acl_db[btm_cb.pm_pend_link].remote_addr, pm_status, 0, status);
(*btm_cb.pm_reg_db[btm_cb.pm_pend_id].cback)(p_acl_cb->remote_addr, pm_status, 0, status);
}
/* no pending cmd now */
#if BTM_PM_DEBUG == TRUE
BTM_TRACE_DEBUG( "btm_pm_proc_cmd_status state:0x%x, pm_pend_link: %d(new: %d)",
p_cb->state, btm_cb.pm_pend_link, MAX_L2CAP_LINKS);
p_cb->state, btm_cb.pm_pend_link_hdl, MAX_L2CAP_LINKS);
#endif // BTM_PM_DEBUG
btm_cb.pm_pend_link = MAX_L2CAP_LINKS;
btm_cb.pm_pend_link_hdl = BTM_INVALID_HANDLE;
btm_pm_check_stored();
}
@ -757,19 +751,18 @@ void btm_pm_proc_mode_change (UINT8 hci_status, UINT16 hci_handle, UINT8 mode, U
{
tACL_CONN *p;
tBTM_PM_MCB *p_cb = NULL;
int xx, yy, zz;
int yy;
tBTM_PM_STATE old_state;
tL2C_LCB *p_lcb;
/* get the index to acl_db */
if ((xx = btm_handle_to_acl_index(hci_handle)) >= MAX_L2CAP_LINKS) {
p = btm_handle_to_acl(hci_handle);
if (!p) {
return;
}
p = &btm_cb.acl_db[xx];
/* update control block */
p_cb = &(btm_cb.pm_mode_db[xx]);
p_cb = p->p_pm_mode_db;
old_state = p_cb->state;
p_cb->state = mode;
p_cb->interval = interval;
@ -798,14 +791,17 @@ void btm_pm_proc_mode_change (UINT8 hci_status, UINT16 hci_handle, UINT8 mode, U
#if BTM_PM_DEBUG == TRUE
BTM_TRACE_DEBUG( "btm_pm_proc_mode_change: Sending stored req:%d", xx);
#endif // BTM_PM_DEBUG
btm_pm_snd_md_req(BTM_PM_SET_ONLY_ID, xx, NULL);
btm_pm_snd_md_req(BTM_PM_SET_ONLY_ID, hci_handle, NULL);
} else {
for (zz = 0; zz < MAX_L2CAP_LINKS; zz++) {
if (btm_cb.pm_mode_db[zz].chg_ind == TRUE) {
list_node_t *p_node = NULL;
for (p_node =(list_begin(btm_cb.p_pm_mode_db_list)); p_node; p_node = (list_next(p_node))) {
p_cb = (tBTM_PM_MCB *)list_node(p_node);
if (p_cb->chg_ind == TRUE) {
#if BTM_PM_DEBUG == TRUE
BTM_TRACE_DEBUG( "btm_pm_proc_mode_change: Sending PM req :%d", zz);
#endif // BTM_PM_DEBUG
btm_pm_snd_md_req(BTM_PM_SET_ONLY_ID, zz, NULL);
btm_pm_snd_md_req(BTM_PM_SET_ONLY_ID, hci_handle, NULL);
break;
}
}
@ -848,15 +844,14 @@ void btm_pm_proc_ssr_evt (UINT8 *p, UINT16 evt_len)
STREAM_TO_UINT16 (handle, p);
/* get the index to acl_db */
if ((xx = btm_handle_to_acl_index(handle)) >= MAX_L2CAP_LINKS) {
return;
}
p += 2;
STREAM_TO_UINT16 (max_rx_lat, p);
p_cb = &(btm_cb.pm_mode_db[xx]);
p_acl = &btm_cb.acl_db[xx];
p_acl = btm_handle_to_acl(handle);
if (!p_acl) {
return;
}
p_cb = p_acl->p_pm_mode_db;
if (p_cb->interval == max_rx_lat) {
/* using legacy sniff */
use_ssr = FALSE;

View File

@ -481,7 +481,6 @@ static tBTM_STATUS btm_send_connect_request(UINT16 acl_handle,
tBTM_ESCO_PARAMS *p_setup)
{
UINT16 temp_pkt_types;
UINT8 xx;
tACL_CONN *p_acl;
/* Send connect request depending on version of spec */
@ -499,9 +498,8 @@ static tBTM_STATUS btm_send_connect_request(UINT16 acl_handle,
/* Finally, remove EDR eSCO if the remote device doesn't support it */
/* UPF25: Only SCO was brought up in this case */
btm_handle_to_acl_index(acl_handle);
if ((xx = btm_handle_to_acl_index(acl_handle)) < MAX_L2CAP_LINKS) {
p_acl = &btm_cb.acl_db[xx];
p_acl = btm_handle_to_acl(acl_handle);
if (p_acl) {
if (!HCI_EDR_ESCO_2MPS_SUPPORTED(p_acl->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0])) {
BTM_TRACE_WARNING("BTM Remote does not support 2-EDR eSCO");

View File

@ -2971,7 +2971,7 @@ static tBTM_STATUS btm_sec_dd_create_conn (tBTM_SEC_DEV_REC *p_dev_rec)
#if (SMP_INCLUDED == TRUE)
void btm_sec_rmt_name_request_complete (UINT8 *p_bd_addr, UINT8 *p_bd_name, UINT8 status)
{
tBTM_SEC_DEV_REC *p_dev_rec;
tBTM_SEC_DEV_REC *p_dev_rec = NULL;
int i;
DEV_CLASS dev_class;
UINT8 old_sec_state;
@ -2987,19 +2987,18 @@ void btm_sec_rmt_name_request_complete (UINT8 *p_bd_addr, UINT8 *p_bd_name, UINT
if (p_bd_addr) {
p_dev_rec = btm_find_dev (p_bd_addr);
} else {
p_dev_rec = &btm_cb.sec_dev_rec[0];
for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++) {
list_node_t *p_node = NULL;
for (p_node = list_begin(btm_cb.p_sec_dev_rec_list); p_node; p_node = list_next(p_node)) {
p_dev_rec = list_node(p_node);
if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE)
&& (p_dev_rec->sec_state == BTM_SEC_STATE_GETTING_NAME)) {
p_bd_addr = p_dev_rec->bd_addr;
break;
}
}
if (i == BTM_SEC_MAX_DEVICE_RECORDS) {
p_dev_rec = NULL;
}
}
if (!p_bd_addr) {
p_dev_rec = NULL;
}
}
@ -4051,7 +4050,6 @@ void btm_sec_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable)
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_handle (handle);
#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
tACL_CONN *p_acl = NULL;
UINT8 acl_idx = btm_handle_to_acl_index(handle);
#endif
BTM_TRACE_EVENT ("Security Manager: encrypt_change status:%d State:%d, encr_enable = %d\n",
status, (p_dev_rec) ? p_dev_rec->sec_state : 0, encr_enable);
@ -4096,9 +4094,7 @@ void btm_sec_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable)
BTM_TRACE_DEBUG ("after update p_dev_rec->sec_flags=0x%x\n", p_dev_rec->sec_flags );
#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
if (acl_idx != MAX_L2CAP_LINKS) {
p_acl = &btm_cb.acl_db[acl_idx];
}
p_acl = btm_handle_to_acl(handle);
if (p_acl != NULL) {
btm_sec_check_pending_enc_req(p_dev_rec, p_acl->transport, encr_enable);
@ -5649,10 +5645,11 @@ static void btm_restore_mode(void)
tBTM_SEC_DEV_REC *btm_sec_find_dev_by_sec_state (UINT8 state)
{
#if (SMP_INCLUDED == TRUE)
tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
for (int i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++) {
if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE)
tBTM_SEC_DEV_REC *p_dev_rec = NULL;
list_node_t *p_node = NULL;
for (p_node = list_begin(btm_cb.p_sec_dev_rec_list); p_node; p_node = list_next(p_node)) {
p_dev_rec = list_node(p_node);
if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE)
&& (p_dev_rec->sec_state == state)) {
return (p_dev_rec);
}
@ -5660,7 +5657,6 @@ tBTM_SEC_DEV_REC *btm_sec_find_dev_by_sec_state (UINT8 state)
#endif ///SMP_INCLUDED == TRUE
return (NULL);
}
/*******************************************************************************
**
** Function btm_sec_change_pairing_state
@ -6148,22 +6144,17 @@ BOOLEAN btm_sec_is_le_capable_dev (BD_ADDR bda)
**
*******************************************************************************/
#if (BLE_INCLUDED == TRUE)
BOOLEAN btm_sec_find_bonded_dev (UINT8 start_idx, UINT8 *p_found_idx, tBTM_SEC_DEV_REC **p_rec)
BOOLEAN btm_sec_find_bonded_dev (UINT8 start_idx, UINT16 *p_found_handle, tBTM_SEC_DEV_REC **p_rec)
{
BOOLEAN found = FALSE;
#if (SMP_INCLUDED== TRUE)
tBTM_SEC_DEV_REC *p_dev_rec;
int i;
if (start_idx >= BTM_SEC_MAX_DEVICE_RECORDS) {
BTM_TRACE_DEBUG ("LE bonded device not found\n");
return found;
}
p_dev_rec = &btm_cb.sec_dev_rec[start_idx];
for (i = start_idx; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++) {
list_node_t *p_node = NULL;
for (p_node = list_begin(btm_cb.p_sec_dev_rec_list); p_node; p_node = list_next(p_node)) {
p_dev_rec = list_node(p_node);
if (p_dev_rec->ble.key_type || (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN)) {
*p_found_idx = i;
*p_found_handle = p_dev_rec->hci_handle;
*p_rec = p_dev_rec;
break;
}

View File

@ -192,7 +192,7 @@ typedef struct {
BD_ADDR private_addr;
BD_ADDR random_bda;
BOOLEAN busy;
UINT16 index;
tBTM_SEC_DEV_REC *p_dev_rec;
tBTM_BLE_RESOLVE_CBACK *p_resolve_cback;
tBTM_BLE_ADDR_CBACK *p_generate_cback;
void *p;

View File

@ -25,6 +25,8 @@
#ifndef BTM_INT_H
#define BTM_INT_H
typedef struct tBTM_SEC_DEV_REC tBTM_SEC_DEV_REC;
#include "common/bt_defs.h"
#include "common/bt_target.h"
#include "stack/hcidefs.h"
@ -75,6 +77,36 @@ typedef char tBTM_LOC_BD_NAME[BTM_MAX_LOC_BD_NAME_LEN + 1];
#define BTM_IS_BRCM_CONTROLLER() (controller_get_interface()->get_bt_version()->manufacturer == LMP_COMPID_BROADCOM)
typedef struct t_acl_db_param{
#define ACL_DB_HANDLE 0x00
#define ACL_DB_BDA 0x01
UINT8 type;
void *p_data1;
void *p_data2;
}tACL_DB_PARAM;
enum {
BTM_PM_ST_ACTIVE = BTM_PM_STS_ACTIVE,
BTM_PM_ST_HOLD = BTM_PM_STS_HOLD,
BTM_PM_ST_SNIFF = BTM_PM_STS_SNIFF,
BTM_PM_ST_PARK = BTM_PM_STS_PARK,
BTM_PM_ST_PENDING = BTM_PM_STS_PENDING
};
typedef UINT8 tBTM_PM_STATE;
typedef struct {
tBTM_PM_PWR_MD req_mode[BTM_MAX_PM_RECORDS + 1]; /* the desired mode and parameters of the connection*/
tBTM_PM_PWR_MD set_mode; /* the mode and parameters sent down to the host controller. */
UINT16 interval; /* the interval from last mode change event. */
#if (BTM_SSR_INCLUDED == TRUE)
UINT16 max_lat; /* stored SSR maximum latency */
UINT16 min_rmt_to;/* stored SSR minimum remote timeout */
UINT16 min_loc_to;/* stored SSR minimum local timeout */
#endif
tBTM_PM_STATE state; /* contains the current mode of the connection */
BOOLEAN chg_ind; /* a request change indication */
} tBTM_PM_MCB;
/* Define the ACL Management control structure
*/
typedef struct {
@ -127,6 +159,7 @@ BD_FEATURES peer_le_features; /* Peer LE Used features mask for the de
tBTM_SET_PKT_DATA_LENGTH_CBACK *p_set_pkt_data_cback;
tBTM_LE_SET_PKT_DATA_LENGTH_PARAMS data_length_params;
#endif
tBTM_PM_MCB *p_pm_mode_db; /* Pointer to PM mode control block per ACL link */
} tACL_CONN;
@ -538,7 +571,7 @@ typedef UINT8 tBTM_BOND_TYPE;
** Define structure for Security Device Record.
** A record exists for each device authenticated with this device
*/
typedef struct {
struct tBTM_SEC_DEV_REC{
tBTM_SEC_SERV_REC *p_cur_service;
tBTM_SEC_CALLBACK *p_callback;
void *p_ref_data;
@ -647,7 +680,7 @@ typedef struct {
#define BTM_SEC_NO_LAST_SERVICE_ID 0
UINT8 last_author_service_id; /* ID of last serviced authorized: Reset after each l2cap connection */
BOOLEAN enc_init_by_we;
} tBTM_SEC_DEV_REC;
};
#define BTM_SEC_IS_SM4(sm) ((BOOLEAN)(BTM_SM4_TRUE == ((sm)&BTM_SM4_TRUE)))
#define BTM_SEC_IS_SM4_LEGACY(sm) ((BOOLEAN)(BTM_SM4_KNOWN == ((sm)&BTM_SM4_TRUE)))
@ -669,15 +702,6 @@ typedef struct {
UINT8 def_inq_scan_mode; /* ??? limited/general/none */
} tBTM_CFG;
enum {
BTM_PM_ST_ACTIVE = BTM_PM_STS_ACTIVE,
BTM_PM_ST_HOLD = BTM_PM_STS_HOLD,
BTM_PM_ST_SNIFF = BTM_PM_STS_SNIFF,
BTM_PM_ST_PARK = BTM_PM_STS_PARK,
BTM_PM_ST_PENDING = BTM_PM_STS_PENDING
};
typedef UINT8 tBTM_PM_STATE;
enum {
BTM_PM_SET_MODE_EVT, /* Set power mode API is called. */
BTM_PM_UPDATE_EVT,
@ -707,19 +731,6 @@ typedef struct {
UINT8 link_ind;
} tBTM_PM_SM_DATA;
typedef struct {
tBTM_PM_PWR_MD req_mode[BTM_MAX_PM_RECORDS + 1]; /* the desired mode and parameters of the connection*/
tBTM_PM_PWR_MD set_mode; /* the mode and parameters sent down to the host controller. */
UINT16 interval; /* the interval from last mode change event. */
#if (BTM_SSR_INCLUDED == TRUE)
UINT16 max_lat; /* stored SSR maximum latency */
UINT16 min_rmt_to;/* stored SSR minimum remote timeout */
UINT16 min_loc_to;/* stored SSR minimum local timeout */
#endif
tBTM_PM_STATE state; /* contains the current mode of the connection */
BOOLEAN chg_ind; /* a request change indication */
} tBTM_PM_MCB;
#define BTM_PM_REC_NOT_USED 0
typedef struct {
tBTM_PM_STATUS_CBACK *cback;/* to notify the registered party of mode change event */
@ -798,13 +809,15 @@ typedef BOOLEAN CONNECTION_TYPE;
#define BTM_STATE_BUFFER_SIZE 5 /* size of state buffer */
#define BTM_INVALID_HANDLE 0xFFFF
typedef struct {
tBTM_CFG cfg; /* Device configuration */
/****************************************************
** ACL Management
****************************************************/
tACL_CONN acl_db[MAX_L2CAP_LINKS];
list_t *p_acl_db_list;
#if (CLASSIC_BT_INCLUDED == TRUE)
UINT8 btm_scn[BTM_MAX_SCN]; /* current SCNs: TRUE if SCN is in use */
#endif ///CLASSIC_BT_INCLUDED == TRUE
@ -817,10 +830,10 @@ typedef struct {
/****************************************************
** Power Management
****************************************************/
tBTM_PM_MCB pm_mode_db[MAX_L2CAP_LINKS]; /* per ACL link */
list_t *p_pm_mode_db_list;
tBTM_PM_RCB pm_reg_db[BTM_MAX_PM_RECORDS + 1]; /* per application/module */
UINT8 pm_pend_link; /* the index of acl_db, which has a pending PM cmd */
UINT8 pm_pend_id; /* the id pf the module, which has a pending PM cmd */
UINT16 pm_pend_link_hdl; /* the index of acl_db, which has a pending PM cmd */
UINT8 pm_pend_id; /* the id pf the module, which has a pending PM cmd */
/*****************************************************
** Device control
@ -902,7 +915,7 @@ typedef struct {
#if SMP_INCLUDED == TRUE || CLASSIC_BT_INCLUDED == TRUE
tBTM_SEC_SERV_REC sec_serv_rec[BTM_SEC_MAX_SERVICE_RECORDS];
#endif // SMP_INCLUDED == TRUE || BT_CLASSIC_ENABLED == TRUE
tBTM_SEC_DEV_REC sec_dev_rec[BTM_SEC_MAX_DEVICE_RECORDS];
list_t *p_sec_dev_rec_list;
tBTM_SEC_SERV_REC *p_out_serv;
tBTM_MKEY_CALLBACK *mkey_cback;
@ -952,6 +965,19 @@ extern tBTM_CB *btm_cb_ptr;
#define btm_cb (*btm_cb_ptr)
#endif
typedef struct tSecDevContext {
#define SEC_DEV_BTDM_BDA 0x01
#define SEC_DEV_BDA 0x02
#define SEC_DEV_HDL 0x03
#define SEC_DEV_ID_ADDR 0x04
UINT8 type;
BOOLEAN free_check;
union {
BD_ADDR_PTR p_bd_addr;
UINT16 handle;
}context;
}tSecDevContext;
/* Internal functions provided by btm_main.c
********************************************
*/
@ -987,6 +1013,7 @@ BOOLEAN btm_lookup_eir(BD_ADDR_PTR p_rem_addr);
/* Internal functions provided by btm_acl.c
********************************************
*/
void btm_acl_free(void);
void btm_acl_init (void);
void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, BD_NAME bdn,
UINT16 hci_handle, UINT8 link_role, tBT_TRANSPORT transport);
@ -998,7 +1025,6 @@ void btm_cont_rswitch (tACL_CONN *p,
tBTM_SEC_DEV_REC *p_dev_rec,
UINT8 hci_status);
UINT8 btm_handle_to_acl_index (UINT16 hci_handle);
tACL_CONN *btm_handle_to_acl (UINT16 hci_handle);
void btm_read_link_policy_complete (UINT8 *p);
void btm_read_rssi_complete (UINT8 *p);
@ -1025,7 +1051,7 @@ tACL_CONN *btm_bda_to_acl (BD_ADDR bda, tBT_TRANSPORT transport);
BOOLEAN btm_acl_notif_conn_collision (BD_ADDR bda);
void btm_pm_reset(void);
void btm_pm_sm_alloc(UINT8 ind);
tBTM_PM_MCB *btm_pm_sm_alloc(void);
void btm_pm_proc_cmd_status(UINT8 status);
void btm_pm_proc_mode_change (UINT8 hci_status, UINT16 hci_handle, UINT8 mode,
UINT16 interval);
@ -1103,6 +1129,8 @@ tBTM_SEC_DEV_REC *btm_find_dev_by_handle (UINT16 handle);
tBTM_BOND_TYPE btm_get_bond_type_dev(BD_ADDR bd_addr);
BOOLEAN btm_set_bond_type_dev(BD_ADDR bd_addr,
tBTM_BOND_TYPE bond_type);
void btm_sec_dev_init(void);
void btm_sec_dev_free(void);
/* Internal functions provided by btm_sec.c
**********************************************
@ -1142,7 +1170,7 @@ void btm_sec_set_peer_sec_caps (tACL_CONN *p_acl_cb, tBTM_SEC_DEV_REC *p_dev_rec
#if BLE_INCLUDED == TRUE
void btm_sec_clear_ble_keys (tBTM_SEC_DEV_REC *p_dev_rec);
BOOLEAN btm_sec_find_bonded_dev (UINT8 start_idx, UINT8 *p_found_idx, tBTM_SEC_DEV_REC **p_rec);
BOOLEAN btm_sec_find_bonded_dev (UINT8 start_idx, UINT16 *p_found_handle, tBTM_SEC_DEV_REC **p_rec);
BOOLEAN btm_sec_is_a_bonded_dev (BD_ADDR bda);
void btm_consolidate_dev(tBTM_SEC_DEV_REC *p_target_rec);
BOOLEAN btm_sec_is_le_capable_dev (BD_ADDR bda);
@ -1180,6 +1208,7 @@ void btm_ble_lock_free(void);
void btm_sec_handle_remote_legacy_auth_cmp(UINT16 handle);
void btm_sec_update_legacy_auth_state(tACL_CONN *p_acl_cb, UINT8 legacy_auth_state);
BOOLEAN btm_sec_legacy_authentication_mutual (tBTM_SEC_DEV_REC *p_dev_rec);
BOOLEAN btm_find_sec_dev_in_list (void *p_node_data, void *context);
/*
#ifdef __cplusplus

View File

@ -1242,7 +1242,6 @@ void GATT_Deregister (tGATT_IF gatt_if)
tGATT_REG *p_reg = gatt_get_regcb(gatt_if);
tGATT_TCB *p_tcb;
tGATT_CLCB *p_clcb;
UINT8 i, j;
#if (GATTS_INCLUDED == TRUE)
UINT8 ii;
tGATT_SR_REG *p_sreg;
@ -1269,7 +1268,9 @@ void GATT_Deregister (tGATT_IF gatt_if)
#endif ///GATTS_INCLUDED == TRUE
/* When an application deregisters, check remove the link associated with the app */
for (i = 0, p_tcb = gatt_cb.tcb; i < GATT_MAX_PHY_CHANNEL; i++, p_tcb++) {
list_node_t *p_node = NULL;
for(p_node = list_begin(gatt_cb.p_tcb_list); p_node; p_node = list_next(p_node)) {
p_tcb = list_node(p_node);
if (p_tcb->in_use) {
if (gatt_get_ch_state(p_tcb) != GATT_CH_CLOSE) {
gatt_update_app_use_link_flag(gatt_if, p_tcb, FALSE, FALSE);
@ -1279,7 +1280,9 @@ void GATT_Deregister (tGATT_IF gatt_if)
}
}
for (j = 0, p_clcb = &gatt_cb.clcb[j]; j < GATT_CL_MAX_LCB; j++, p_clcb++) {
list_node_t *p_node = NULL;
for(p_node = list_begin(gatt_cb.p_clcb_list); p_node; p_node = list_next(p_node)) {
p_clcb = list_node(p_node);
if (p_clcb->in_use &&
(p_clcb->p_reg->gatt_if == gatt_if) &&
(p_clcb->p_tcb->tcb_idx == p_tcb->tcb_idx)) {
@ -1508,7 +1511,7 @@ tGATT_STATUS GATT_SendServiceChangeIndication (BD_ADDR bd_addr)
start_idx = 0;
BD_ADDR addr;
while (gatt_find_the_connected_bda(start_idx, addr, &found_idx, &transport)) {
p_tcb = &gatt_cb.tcb[found_idx];
p_tcb = gatt_get_tcb_by_idx(found_idx);
srv_chg_ind_pending = gatt_is_srv_chg_ind_pending(p_tcb);
if (!srv_chg_ind_pending) {

View File

@ -96,12 +96,15 @@ tGATT_DEFAULT gatt_default;
void gatt_init (void)
{
tL2CAP_FIXED_CHNL_REG fixed_reg;
#if GATT_DYNAMIC_MEMORY
gatt_cb_ptr = (tGATT_CB *)osi_malloc(sizeof(tGATT_CB));
#endif /* #if GATT_DYNAMIC_MEMORY */
memset (&gatt_cb, 0, sizeof(tGATT_CB));
memset (&fixed_reg, 0, sizeof(tL2CAP_FIXED_CHNL_REG));
gatt_cb.p_clcb_list = list_new(osi_free_func);
gatt_cb.p_tcb_list = list_new(osi_free_func);
#if defined(GATT_INITIAL_TRACE_LEVEL)
gatt_cb.trace_level = GATT_INITIAL_TRACE_LEVEL;
#else
@ -167,25 +170,31 @@ void gatt_free(void)
fixed_queue_free(gatt_cb.pending_new_srv_start_q, NULL);
gatt_cb.pending_new_srv_start_q = NULL;
for (i = 0; i < GATT_MAX_PHY_CHANNEL; i++)
{
fixed_queue_free(gatt_cb.tcb[i].pending_enc_clcb, NULL);
gatt_cb.tcb[i].pending_enc_clcb = NULL;
list_node_t *p_node = NULL;
tGATT_TCB *p_tcb = NULL;
for(p_node = list_begin(gatt_cb.p_tcb_list); p_node; p_node = list_next(p_node)) {
p_tcb = list_node(p_node);
fixed_queue_free(p_tcb->pending_enc_clcb, NULL);
p_tcb->pending_enc_clcb = NULL;
fixed_queue_free(gatt_cb.tcb[i].pending_ind_q, NULL);
gatt_cb.tcb[i].pending_ind_q = NULL;
fixed_queue_free(p_tcb->pending_ind_q, NULL);
p_tcb->pending_ind_q = NULL;
btu_free_timer(&gatt_cb.tcb[i].conf_timer_ent);
memset(&gatt_cb.tcb[i].conf_timer_ent, 0, sizeof(TIMER_LIST_ENT));
btu_free_timer(&p_tcb->conf_timer_ent);
memset(&p_tcb->conf_timer_ent, 0, sizeof(TIMER_LIST_ENT));
btu_free_timer(&gatt_cb.tcb[i].ind_ack_timer_ent);
memset(&gatt_cb.tcb[i].ind_ack_timer_ent, 0, sizeof(TIMER_LIST_ENT));
btu_free_timer(&p_tcb->ind_ack_timer_ent);
memset(&p_tcb->ind_ack_timer_ent, 0, sizeof(TIMER_LIST_ENT));
#if (GATTS_INCLUDED == TRUE)
fixed_queue_free(gatt_cb.tcb[i].sr_cmd.multi_rsp_q, NULL);
gatt_cb.tcb[i].sr_cmd.multi_rsp_q = NULL;
fixed_queue_free(p_tcb->sr_cmd.multi_rsp_q, NULL);
p_tcb->sr_cmd.multi_rsp_q = NULL;
#endif /* #if (GATTS_INCLUDED == TRUE) */
}
list_free(gatt_cb.p_tcb_list);
#if (GATTC_INCLUDED == TRUE)
list_free(gatt_cb.p_clcb_list);
#endif //(GATTC_INCLUDED == TRUE)
#if (GATTS_INCLUDED == TRUE)
for (i = 0; i < GATT_MAX_SR_PROFILES; i++) {
@ -392,7 +401,7 @@ BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr, tBLE_ADDR_TYPE bd_a
GATT_TRACE_ERROR("gatt_connect failed");
fixed_queue_free(p_tcb->pending_enc_clcb, NULL);
fixed_queue_free(p_tcb->pending_ind_q, NULL);
memset(p_tcb, 0, sizeof(tGATT_TCB));
gatt_tcb_free(p_tcb);
} else {
ret = TRUE;
}
@ -1146,8 +1155,8 @@ void gatt_proc_srv_chg (void)
gatt_set_srv_chg();
start_idx = 0;
while (gatt_find_the_connected_bda(start_idx, bda, &found_idx, &transport)) {
p_tcb = &gatt_cb.tcb[found_idx];
srv_chg_ind_pending = gatt_is_srv_chg_ind_pending(p_tcb);
p_tcb = gatt_get_tcb_by_idx(found_idx);
srv_chg_ind_pending = gatt_is_srv_chg_ind_pending(p_tcb);
if (!srv_chg_ind_pending) {
gatt_send_srv_chg_ind(bda);

View File

@ -78,6 +78,7 @@ static const UINT8 base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x0
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static UINT32 gatt_tcb_id;
/*******************************************************************************
**
@ -779,27 +780,27 @@ BOOLEAN gatt_remove_an_item_from_list(tGATT_HDL_LIST_INFO *p_list, tGATT_HDL_LIS
BOOLEAN gatt_find_the_connected_bda(UINT8 start_idx, BD_ADDR bda, UINT8 *p_found_idx,
tBT_TRANSPORT *p_transport)
{
UINT8 i;
BOOLEAN found = FALSE;
GATT_TRACE_DEBUG("gatt_find_the_connected_bda start_idx=%d", start_idx);
for (i = start_idx ; i < GATT_MAX_PHY_CHANNEL; i ++) {
if (gatt_cb.tcb[i].in_use && gatt_cb.tcb[i].ch_state == GATT_CH_OPEN) {
memcpy( bda, gatt_cb.tcb[i].peer_bda, BD_ADDR_LEN);
*p_found_idx = i;
*p_transport = gatt_cb.tcb[i].transport;
tGATT_TCB *p_tcb = NULL;
list_node_t *p_node = NULL;
for(p_node = list_begin(gatt_cb.p_tcb_list); p_node; p_node = list_next(p_node)) {
p_tcb = list_node(p_node);
if (p_tcb->in_use && p_tcb->ch_state == GATT_CH_OPEN) {
memcpy( bda, p_tcb->peer_bda, BD_ADDR_LEN);
*p_found_idx = p_tcb->tcb_idx;
*p_transport = p_tcb->transport;
found = TRUE;
GATT_TRACE_DEBUG("gatt_find_the_connected_bda bda :%02x-%02x-%02x-%02x-%02x-%02x",
bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
break;
}
}
GATT_TRACE_DEBUG("gatt_find_the_connected_bda found=%d found_idx=%d", found, i);
GATT_TRACE_DEBUG("gatt_find_the_connected_bda found=%d found_idx=%d", found, p_tcb->tcb_idx);
return found;
}
/*******************************************************************************
**
** Function gatt_is_srv_chg_ind_pending
@ -883,19 +884,19 @@ tGATTS_SRV_CHG *gatt_is_bda_in_the_srv_chg_clt_list (BD_ADDR bda)
*******************************************************************************/
BOOLEAN gatt_is_bda_connected(BD_ADDR bda)
{
UINT8 i = 0;
BOOLEAN connected = FALSE;
for ( i = 0; i < GATT_MAX_PHY_CHANNEL; i ++) {
if (gatt_cb.tcb[i].in_use &&
!memcmp(gatt_cb.tcb[i].peer_bda, bda, BD_ADDR_LEN)) {
tGATT_TCB *p_tcb = NULL;
list_node_t *p_node = NULL;
for(p_node = list_begin(gatt_cb.p_tcb_list); p_node; p_node = list_next(p_node)) {
p_tcb = list_node(p_node);
if (p_tcb->in_use &&
!memcmp(p_tcb->peer_bda, bda, BD_ADDR_LEN)) {
connected = TRUE;
break;
}
}
return connected;
}
/*******************************************************************************
**
** Function gatt_find_i_tcb_by_addr
@ -908,17 +909,19 @@ BOOLEAN gatt_is_bda_connected(BD_ADDR bda)
UINT8 gatt_find_i_tcb_by_addr(BD_ADDR bda, tBT_TRANSPORT transport)
{
UINT8 i = 0;
for ( ; i < GATT_MAX_PHY_CHANNEL; i ++) {
if (!memcmp(gatt_cb.tcb[i].peer_bda, bda, BD_ADDR_LEN) &&
gatt_cb.tcb[i].transport == transport) {
list_node_t *p_node = NULL;
tGATT_TCB *p_tcb = NULL;
for(p_node = list_begin(gatt_cb.p_tcb_list); p_node; p_node = list_next(p_node)) {
p_tcb = list_node(p_node);
if (!memcmp(p_tcb->peer_bda, bda, BD_ADDR_LEN) &&
p_tcb->transport == transport) {
i = p_tcb->tcb_idx;
return i;
}
}
return GATT_INDEX_INVALID;
}
/*******************************************************************************
**
** Function gatt_get_tcb_by_idx
@ -930,10 +933,13 @@ UINT8 gatt_find_i_tcb_by_addr(BD_ADDR bda, tBT_TRANSPORT transport)
*******************************************************************************/
tGATT_TCB *gatt_get_tcb_by_idx(UINT8 tcb_idx)
{
tGATT_TCB *p_tcb = NULL;
if ( (tcb_idx < GATT_MAX_PHY_CHANNEL) && gatt_cb.tcb[tcb_idx].in_use) {
p_tcb = &gatt_cb.tcb[tcb_idx];
tGATT_TCB *p_tcb = NULL;
list_node_t *p_node = NULL;
for(p_node = list_begin(gatt_cb.p_tcb_list); p_node; p_node = list_next(p_node)) {
p_tcb = list_node(p_node);
if ( (tcb_idx < GATT_MAX_PHY_CHANNEL) && p_tcb->in_use && p_tcb->tcb_idx == tcb_idx ) {
break;
}
}
return p_tcb;
@ -954,7 +960,7 @@ tGATT_TCB *gatt_find_tcb_by_addr(BD_ADDR bda, tBT_TRANSPORT transport)
UINT8 i = 0;
if ((i = gatt_find_i_tcb_by_addr(bda, transport)) != GATT_INDEX_INVALID) {
p_tcb = &gatt_cb.tcb[i];
p_tcb = gatt_get_tcb_by_idx(i);
}
return p_tcb;
@ -973,7 +979,7 @@ UINT8 gatt_find_i_tcb_free(void)
UINT8 i = 0, j = GATT_INDEX_INVALID;
for (i = 0; i < GATT_MAX_PHY_CHANNEL; i ++) {
if (!gatt_cb.tcb[i].in_use) {
if (!((1 << i) & gatt_tcb_id)) {
j = i;
break;
}
@ -982,6 +988,48 @@ UINT8 gatt_find_i_tcb_free(void)
}
/*******************************************************************************
**
** Function gatt_tcb_alloc
**
** Description The function allocates tcb for given tcb_idx and update tcb_id
**
** Returns Allocated tcb block
**
*******************************************************************************/
tGATT_TCB *gatt_tcb_alloc(UINT8 tcb_idx)
{
/* Allocate tcb block */
tGATT_TCB *p_tcb = (tGATT_TCB *)osi_malloc(sizeof(tGATT_TCB));
if (p_tcb && list_length(gatt_cb.p_tcb_list) < GATT_MAX_PHY_CHANNEL) {
memset(p_tcb, 0, sizeof(tGATT_TCB));
/* Add tcb block to list in gatt_cb */
list_append(gatt_cb.p_tcb_list, p_tcb);
/* Update tcb id */
gatt_tcb_id |= 1 << tcb_idx;
} else if(p_tcb) {
osi_free(p_tcb);
p_tcb = NULL;
}
return p_tcb;
}
/*******************************************************************************
**
** Function gatt_tcb_free
**
** Description The function free the given tcb block and update tcb id
**
** Returns void
**
*******************************************************************************/
void gatt_tcb_free( tGATT_TCB *p_tcb)
{
UINT8 tcb_idx = p_tcb->tcb_idx;
if (list_remove(gatt_cb.p_tcb_list, p_tcb)) {
gatt_tcb_id &= ~(1 << tcb_idx);
}
}
/*******************************************************************************
**
** Function gatt_allocate_tcb_by_bdaddr
**
** Description The function locate or allocate new tcb entry for matching bda.
@ -1003,8 +1051,10 @@ tGATT_TCB *gatt_allocate_tcb_by_bdaddr(BD_ADDR bda, tBT_TRANSPORT transport)
allocated = TRUE;
}
if (i != GATT_INDEX_INVALID) {
p_tcb = &gatt_cb.tcb[i];
p_tcb = gatt_tcb_alloc(i);
if (!p_tcb) {
return NULL;
}
if (allocated) {
memset(p_tcb, 0, sizeof(tGATT_TCB));
p_tcb->pending_enc_clcb = fixed_queue_new(QUEUE_SIZE_MAX);
@ -1216,7 +1266,7 @@ BOOLEAN gatt_parse_uuid_from_cmd(tBT_UUID *p_uuid_rec, UINT16 uuid_size, UINT8 *
*******************************************************************************/
void gatt_start_rsp_timer(UINT16 clcb_idx)
{
tGATT_CLCB *p_clcb = &gatt_cb.clcb[clcb_idx];
tGATT_CLCB *p_clcb = gatt_clcb_find_by_idx(clcb_idx);
UINT32 timeout = GATT_WAIT_FOR_RSP_TOUT;
p_clcb->rsp_timer_ent.param = (TIMER_PARAM_TYPE)p_clcb;
if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
@ -1625,19 +1675,65 @@ tGATT_REG *gatt_get_regcb (tGATT_IF gatt_if)
BOOLEAN gatt_is_clcb_allocated (UINT16 conn_id)
{
UINT8 i = 0;
BOOLEAN is_allocated = FALSE;
for (i = 0; i < GATT_CL_MAX_LCB; i++) {
if (gatt_cb.clcb[i].in_use && (gatt_cb.clcb[i].conn_id == conn_id)) {
is_allocated = TRUE;
break;
}
tGATT_CLCB *p_clcb = gatt_clcb_find_by_conn_id(conn_id);
if (p_clcb) {
is_allocated = TRUE;
}
return is_allocated;
}
/*******************************************************************************
**
** Function gatt_clcb_find_by_conn_id
**
** Description Find clcb block using clcb_idx stored at the time of alloc
**
** Returns pointer to clcb corresponding to conn_id
**
*******************************************************************************/
tGATT_CLCB *gatt_clcb_find_by_conn_id(UINT16 conn_id)
{
list_node_t *p_node = NULL;
tGATT_CLCB *p_clcb = NULL;
tGATT_CLCB *p_clcb_ret = NULL;
for(p_node = list_begin(gatt_cb.p_clcb_list); p_node; p_node = list_next(p_node)) {
p_clcb = list_node(p_node);
if (p_clcb->conn_id == conn_id) {
p_clcb_ret = p_clcb;
break;
}
}
return p_clcb_ret;
}
/*******************************************************************************
**
** Function gatt_clcb_find_by_idx
**
** Description Find clcb block using clcb_idx stored at the time of alloc
**
** Returns pointer to clcb corresponding to clcb_idx
**
*******************************************************************************/
tGATT_CLCB *gatt_clcb_find_by_idx(UINT16 clcb_idx)
{
list_node_t *p_node = NULL;
tGATT_CLCB *p_clcb = NULL;
tGATT_CLCB *p_clcb_ret = NULL;
for(p_node = list_begin(gatt_cb.p_clcb_list); p_node; p_node = list_next(p_node)) {
p_clcb = list_node(p_node);
if (p_clcb->clcb_idx == clcb_idx) {
p_clcb_ret = p_clcb;
break;
}
}
return p_clcb_ret;
}
/*******************************************************************************
**
** Function gatt_clcb_alloc
@ -1649,24 +1745,23 @@ BOOLEAN gatt_is_clcb_allocated (UINT16 conn_id)
*******************************************************************************/
tGATT_CLCB *gatt_clcb_alloc (UINT16 conn_id)
{
UINT8 i = 0;
tGATT_CLCB *p_clcb = NULL;
tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
UINT8 tcb_idx = GATT_GET_TCB_IDX(conn_id);
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(tcb_idx);
tGATT_REG *p_reg = gatt_get_regcb(gatt_if);
for (i = 0; i < GATT_CL_MAX_LCB; i++) {
if (!gatt_cb.clcb[i].in_use) {
p_clcb = &gatt_cb.clcb[i];
p_clcb->in_use = TRUE;
p_clcb->conn_id = conn_id;
p_clcb->clcb_idx = i;
p_clcb->p_reg = p_reg;
p_clcb->p_tcb = p_tcb;
break;
}
if (list_length(gatt_cb.p_clcb_list) < GATT_CL_MAX_LCB) {
p_clcb = (tGATT_CLCB *)osi_malloc(sizeof(tGATT_CLCB));
if (p_clcb) {
memset(p_clcb, 0, sizeof(tGATT_CLCB));
p_clcb->in_use = TRUE;
p_clcb->conn_id = conn_id;
//Add index of the clcb same as conn_id
p_clcb->clcb_idx = conn_id;
p_clcb->p_reg = p_reg;
p_clcb->p_tcb = p_tcb;
}
}
return p_clcb;
}
@ -1685,6 +1780,7 @@ void gatt_clcb_dealloc (tGATT_CLCB *p_clcb)
if (p_clcb && p_clcb->in_use) {
btu_free_timer(&p_clcb->rsp_timer_ent);
memset(p_clcb, 0, sizeof(tGATT_CLCB));
list_remove(gatt_cb.p_clcb_list, p_clcb);
}
}
@ -1702,19 +1798,17 @@ void gatt_clcb_dealloc (tGATT_CLCB *p_clcb)
*******************************************************************************/
tGATT_TCB *gatt_find_tcb_by_cid (UINT16 lcid)
{
UINT16 xx = 0;
tGATT_TCB *p_tcb = NULL;
for (xx = 0; xx < GATT_MAX_PHY_CHANNEL; xx++) {
if (gatt_cb.tcb[xx].in_use && gatt_cb.tcb[xx].att_lcid == lcid) {
p_tcb = &gatt_cb.tcb[xx];
tGATT_TCB *p_tcb = NULL;
list_node_t *p_node = NULL;
for(p_node = list_begin(gatt_cb.p_tcb_list); p_node; p_node = list_next(p_node)) {
p_tcb = list_node(p_node);
if (p_tcb->in_use && p_tcb->att_lcid == lcid) {
break;
}
}
return p_tcb;
}
/*******************************************************************************
**
** Function gatt_num_apps_hold_link
@ -1750,12 +1844,15 @@ UINT8 gatt_num_apps_hold_link(tGATT_TCB *p_tcb)
*******************************************************************************/
UINT8 gatt_num_clcb_by_bd_addr(BD_ADDR bda)
{
UINT8 i, num = 0;
UINT8 num = 0;
for (i = 0; i < GATT_CL_MAX_LCB; i ++) {
if (gatt_cb.clcb[i].in_use && memcmp(gatt_cb.clcb[i].p_tcb->peer_bda, bda, BD_ADDR_LEN) == 0) {
num ++;
}
list_node_t *p_node = NULL;
tGATT_CLCB *p_clcb = NULL;
for(p_node = list_begin(gatt_cb.p_clcb_list); p_node; p_node = list_next(p_node)) {
p_clcb = list_node(p_node);
if (memcmp(p_clcb->p_tcb->peer_bda, bda, BD_ADDR_LEN) == 0) {
num++;
}
}
return num;
}
@ -1989,7 +2086,7 @@ BOOLEAN gatt_find_app_hold_link(tGATT_TCB *p_tcb, UINT8 start_idx, UINT8 *p_foun
for (i = start_idx; i < GATT_MAX_APPS; i ++) {
if (p_tcb->app_hold_link[i]) {
*p_gatt_if = gatt_cb.clcb[i].p_reg->gatt_if;
*p_gatt_if = p_tcb->app_hold_link[i];
*p_found_idx = i;
found = TRUE;
break;
@ -2064,7 +2161,7 @@ tGATT_CLCB *gatt_cmd_dequeue(tGATT_TCB *p_tcb, UINT8 *p_op_code)
tGATT_CLCB *p_clcb = NULL;
if (p_tcb->pending_cl_req != p_tcb->next_slot_inq) {
p_clcb = &gatt_cb.clcb[p_cmd->clcb_idx];
p_clcb = gatt_clcb_find_by_idx(p_cmd->clcb_idx);
*p_op_code = p_cmd->op_code;
@ -2227,8 +2324,9 @@ void gatt_cleanup_upon_disc(BD_ADDR bda, UINT16 reason, tBT_TRANSPORT transport)
if ((p_tcb = gatt_find_tcb_by_addr(bda, transport)) != NULL) {
GATT_TRACE_DEBUG ("found p_tcb ");
gatt_set_ch_state(p_tcb, GATT_CH_CLOSE);
for (i = 0; i < GATT_CL_MAX_LCB; i ++) {
p_clcb = &gatt_cb.clcb[i];
list_node_t *p_node = NULL;
for(p_node = list_begin(gatt_cb.p_clcb_list); p_node; p_node = list_next(p_node)) {
p_clcb = list_node(p_node);
if (p_clcb->in_use && p_clcb->p_tcb == p_tcb) {
btu_stop_timer(&p_clcb->rsp_timer_ent);
GATT_TRACE_DEBUG ("found p_clcb conn_id=%d clcb_idx=%d", p_clcb->conn_id, p_clcb->clcb_idx);
@ -2258,8 +2356,7 @@ void gatt_cleanup_upon_disc(BD_ADDR bda, UINT16 reason, tBT_TRANSPORT transport)
(*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, bda, conn_id, FALSE, reason, transport);
}
}
memset(p_tcb, 0, sizeof(tGATT_TCB));
gatt_tcb_free(p_tcb);
} else {
GATT_TRACE_DEBUG ("exit gatt_cleanup_upon_disc ");
BTM_Recovery_Pre_State();

View File

@ -500,7 +500,7 @@ typedef struct {
} tGATT_PROFILE_CLCB;
typedef struct {
tGATT_TCB tcb[GATT_MAX_PHY_CHANNEL];
list_t *p_tcb_list;
fixed_queue_t *sign_op_queue;
tGATT_SR_REG sr_reg[GATT_MAX_SR_PROFILES];
@ -516,7 +516,7 @@ typedef struct {
fixed_queue_t *srv_chg_clt_q; /* service change clients queue */
fixed_queue_t *pending_new_srv_start_q; /* pending new service start queue */
tGATT_REG cl_rcb[GATT_MAX_APPS];
tGATT_CLCB clcb[GATT_CL_MAX_LCB]; /* connection link control block*/
list_t *p_clcb_list; /* connection link control block*/
tGATT_SCCB sccb[GATT_MAX_SCCB]; /* sign complete callback function GATT_MAX_SCCB <= GATT_CL_MAX_LCB */
UINT8 trace_level;
UINT16 def_mtu_size;
@ -675,6 +675,8 @@ extern tGATT_REG *gatt_get_regcb (tGATT_IF gatt_if);
extern BOOLEAN gatt_is_clcb_allocated (UINT16 conn_id);
extern tGATT_CLCB *gatt_clcb_alloc (UINT16 conn_id);
extern void gatt_clcb_dealloc (tGATT_CLCB *p_clcb);
extern tGATT_CLCB *gatt_clcb_find_by_conn_id(UINT16 conn_id);
extern tGATT_CLCB *gatt_clcb_find_by_idx(UINT16 cclcb_idx);
extern void gatt_sr_copy_prep_cnt_to_cback_cnt(tGATT_TCB *p_tcb );
extern BOOLEAN gatt_sr_is_cback_cnt_zero(tGATT_TCB *p_tcb );
@ -693,6 +695,7 @@ extern tGATT_TCB *gatt_allocate_tcb_by_bdaddr(BD_ADDR bda, tBT_TRANSPORT transpo
extern tGATT_TCB *gatt_get_tcb_by_idx(UINT8 tcb_idx);
extern tGATT_TCB *gatt_find_tcb_by_addr(BD_ADDR bda, tBT_TRANSPORT transport);
extern BOOLEAN gatt_send_ble_burst_data (BD_ADDR remote_bda, BT_HDR *p_buf);
extern void gatt_tcb_free( tGATT_TCB *p_tcb);
/* GATT client functions */
extern void gatt_dequeue_sr_cmd (tGATT_TCB *p_tcb);

View File

@ -25,7 +25,6 @@
#define L2C_INT_H
#include <stdbool.h>
#include "stack/btm_api.h"
#include "stack/l2c_api.h"
#include "stack/l2cdefs.h"
@ -372,6 +371,7 @@ typedef struct {
#endif /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */
/* Define a link control block. There is one link control block between
** this device and any other device (i.e. BD ADDR).
*/
@ -466,6 +466,7 @@ typedef struct t_l2c_linkcb {
} tL2C_LCB;
/* Define the L2CAP control structure
*/
typedef struct {
@ -478,12 +479,10 @@ typedef struct {
BOOLEAN is_cong_cback_context;
tL2C_LCB lcb_pool[MAX_L2CAP_LINKS]; /* Link Control Block pool */
tL2C_CCB ccb_pool[MAX_L2CAP_CHANNELS]; /* Channel Control Block pool */
list_t *p_lcb_pool; /* Link Control Block pool */
list_t *p_ccb_pool; /* Channel Control Block pool */
tL2C_RCB rcb_pool[MAX_L2CAP_CLIENTS]; /* Registration info pool */
tL2C_CCB *p_free_ccb_first; /* Pointer to first free CCB */
tL2C_CCB *p_free_ccb_last; /* Pointer to last free CCB */
UINT8 desire_role; /* desire to be master/slave when accepting a connection */
BOOLEAN disallow_switch; /* FALSE, to allow switch at create conn */

View File

@ -120,12 +120,11 @@ void L2CA_Deregister (UINT16 psm)
tL2C_RCB *p_rcb;
tL2C_CCB *p_ccb;
tL2C_LCB *p_lcb;
int ii;
list_node_t *p_node = NULL;
if ((p_rcb = l2cu_find_rcb_by_psm (psm)) != NULL) {
p_lcb = &l2cb.lcb_pool[0];
for (ii = 0; ii < MAX_L2CAP_LINKS; ii++, p_lcb++) {
for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
p_lcb = list_node(p_node);
if (p_lcb->in_use) {
if (((p_ccb = p_lcb->ccb_queue.p_first_ccb) == NULL)
|| (p_lcb->link_state == LST_DISCONNECTING)) {
@ -403,7 +402,6 @@ BOOLEAN L2CA_ErtmConnectRsp (BD_ADDR p_bd_addr, UINT8 id, UINT16 lcid, UINT16 re
L2CAP_TRACE_WARNING ("L2CAP - no LCB for L2CA_conn_rsp");
return (FALSE);
}
/* Now, find the channel control block */
if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, lcid)) == NULL) {
L2CAP_TRACE_WARNING ("L2CAP - no CCB for L2CA_conn_rsp");
@ -815,6 +813,7 @@ BOOLEAN L2CA_SetIdleTimeout (UINT16 cid, UINT16 timeout, BOOLEAN is_global)
BOOLEAN L2CA_SetIdleTimeoutByBdAddr(BD_ADDR bd_addr, UINT16 timeout, tBT_TRANSPORT transport)
{
tL2C_LCB *p_lcb;
list_node_t *p_node = NULL;
if (memcmp (BT_BD_ANY, bd_addr, BD_ADDR_LEN)) {
p_lcb = l2cu_find_lcb_by_bd_addr( bd_addr, transport);
@ -828,10 +827,8 @@ BOOLEAN L2CA_SetIdleTimeoutByBdAddr(BD_ADDR bd_addr, UINT16 timeout, tBT_TRANSPO
return FALSE;
}
} else {
int xx;
tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
p_lcb = list_node(p_node);
if ((p_lcb->in_use) && (p_lcb->link_state == LST_CONNECTED)) {
p_lcb->idle_timeout = timeout;
@ -1188,10 +1185,9 @@ BOOLEAN L2CA_SetFlushTimeout (BD_ADDR bd_addr, UINT16 flush_tout)
return (FALSE);
}
} else {
int xx;
p_lcb = &l2cb.lcb_pool[0];
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
list_node_t *p_node = NULL;
for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
p_lcb = list_node(p_node);
if ((p_lcb->in_use) && (p_lcb->link_state == LST_CONNECTED)) {
if (p_lcb->link_flush_tout != flush_tout) {
p_lcb->link_flush_tout = flush_tout;
@ -1397,9 +1393,10 @@ void L2CA_DeregisterLECoc(UINT16 psm)
return;
}
tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
for (int i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++)
{
tL2C_LCB *p_lcb = NULL;
list_node_t *p_node = NULL;
for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
p_lcb = list_node(p_node);
if (!p_lcb->in_use || p_lcb->transport != BT_TRANSPORT_LE) {
continue;
}

View File

@ -136,6 +136,7 @@ BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int, UINT16 max_in
p_lcb->waiting_update_conn_max_interval = max_int;
p_lcb->waiting_update_conn_latency = latency;
p_lcb->waiting_update_conn_timeout = timeout;
p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
if(l2cble_start_conn_update(p_lcb) == TRUE) {
@ -586,7 +587,6 @@ void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status, UINT16 conn_in
p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING;
p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PARAM_FULL;
btu_stop_timer(&p_lcb->upda_con_timer);
if (conn_param_update_cb.update_conn_param_cb != NULL) {
@ -922,13 +922,14 @@ void l2c_link_processs_ble_num_bufs (UINT16 num_lm_ble_bufs)
*******************************************************************************/
void l2c_ble_link_adjust_allocation (void)
{
UINT16 qq, yy, qq_remainder;
UINT16 qq, yy = 0, qq_remainder;
tL2C_LCB *p_lcb;
UINT16 hi_quota, low_quota;
UINT16 num_lowpri_links = 0;
UINT16 num_hipri_links = 0;
UINT16 controller_xmit_quota = l2cb.num_lm_ble_bufs;
UINT16 high_pri_link_quota = L2CAP_HIGH_PRI_MIN_XMIT_QUOTA_A;
list_node_t *p_node = NULL;
/* If no links active, reset buffer quotas and controller buffers */
if (l2cb.num_ble_links_active == 0) {
@ -938,7 +939,8 @@ void l2c_ble_link_adjust_allocation (void)
}
/* First, count the links */
for (yy = 0, p_lcb = &l2cb.lcb_pool[0]; yy < MAX_L2CAP_LINKS; yy++, p_lcb++) {
for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
p_lcb = list_node(p_node);
if (p_lcb->in_use && p_lcb->transport == BT_TRANSPORT_LE) {
if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH) {
num_hipri_links++;
@ -984,7 +986,9 @@ void l2c_ble_link_adjust_allocation (void)
l2cb.ble_round_robin_quota, qq);
/* Now, assign the quotas to each link */
for (yy = 0, p_lcb = &l2cb.lcb_pool[0]; yy < MAX_L2CAP_LINKS; yy++, p_lcb++) {
p_node = NULL;
for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
p_lcb = list_node(p_node);
if (p_lcb->in_use && p_lcb->transport == BT_TRANSPORT_LE) {
if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH) {
p_lcb->link_xmit_quota = high_pri_link_quota;

View File

@ -56,7 +56,6 @@ BOOLEAN l2c_link_hci_conn_req (BD_ADDR bd_addr)
{
tL2C_LCB *p_lcb;
tL2C_LCB *p_lcb_cur;
int xx;
BOOLEAN no_links;
/* See if we have a link control block for the remote device */
@ -74,7 +73,9 @@ BOOLEAN l2c_link_hci_conn_req (BD_ADDR bd_addr)
no_links = TRUE;
/* If we already have connection, accept as a master */
for (xx = 0, p_lcb_cur = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS; xx++, p_lcb_cur++) {
list_node_t *p_node = NULL;
for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
p_lcb_cur = list_node(p_node);
if (p_lcb_cur == p_lcb) {
continue;
}
@ -682,13 +683,14 @@ void l2c_info_timeout (tL2C_LCB *p_lcb)
*******************************************************************************/
void l2c_link_adjust_allocation (void)
{
UINT16 qq, yy, qq_remainder;
UINT16 qq, yy = 0, qq_remainder;
tL2C_LCB *p_lcb;
UINT16 hi_quota, low_quota;
UINT16 num_lowpri_links = 0;
UINT16 num_hipri_links = 0;
UINT16 controller_xmit_quota = l2cb.num_lm_acl_bufs;
UINT16 high_pri_link_quota = L2CAP_HIGH_PRI_MIN_XMIT_QUOTA_A;
list_node_t *p_node = NULL;
/* If no links active, reset buffer quotas and controller buffers */
if (l2cb.num_links_active == 0) {
@ -698,7 +700,8 @@ void l2c_link_adjust_allocation (void)
}
/* First, count the links */
for (yy = 0, p_lcb = &l2cb.lcb_pool[0]; yy < MAX_L2CAP_LINKS; yy++, p_lcb++) {
for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
p_lcb = list_node(p_node);
if (p_lcb->in_use) {
if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH) {
num_hipri_links++;
@ -744,7 +747,9 @@ void l2c_link_adjust_allocation (void)
l2cb.round_robin_quota, qq);
/* Now, assign the quotas to each link */
for (yy = 0, p_lcb = &l2cb.lcb_pool[0]; yy < MAX_L2CAP_LINKS; yy++, p_lcb++) {
p_node = NULL;
for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
p_lcb = list_node(p_node);
if (p_lcb->in_use) {
if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH) {
p_lcb->link_xmit_quota = high_pri_link_quota;
@ -796,32 +801,31 @@ void l2c_link_adjust_allocation (void)
** Returns void
**
*******************************************************************************/
void l2c_link_adjust_chnl_allocation (void)
bool l2c_chnl_allocation_in_ccb_list (void *p_ccb_node, void *context)
{
UINT8 xx;
L2CAP_TRACE_DEBUG ("l2c_link_adjust_chnl_allocation");
/* assign buffer quota to each channel based on its data rate requirement */
for (xx = 0; xx < MAX_L2CAP_CHANNELS; xx++)
{
tL2C_CCB *p_ccb = l2cb.ccb_pool + xx;
if (!p_ccb->in_use) {
continue;
}
UNUSED(context);
tL2C_CCB *p_ccb = (tL2C_CCB *)p_ccb_node;
if (p_ccb->in_use) {
tL2CAP_CHNL_DATA_RATE data_rate = p_ccb->tx_data_rate + p_ccb->rx_data_rate;
p_ccb->buff_quota = L2CAP_CBB_DEFAULT_DATA_RATE_BUFF_QUOTA * data_rate;
L2CAP_TRACE_EVENT("CID:0x%04x FCR Mode:%u Priority:%u TxDataRate:%u RxDataRate:%u Quota:%u",
p_ccb->local_cid, p_ccb->peer_cfg.fcr.mode,
p_ccb->ccb_priority, p_ccb->tx_data_rate,
p_ccb->rx_data_rate, p_ccb->buff_quota);
p_ccb->local_cid, p_ccb->peer_cfg.fcr.mode,
p_ccb->ccb_priority, p_ccb->tx_data_rate,
p_ccb->rx_data_rate, p_ccb->buff_quota);
/* quota may be change so check congestion */
l2cu_check_channel_congestion (p_ccb);
}
return false;
}
void l2c_link_adjust_chnl_allocation (void)
{
L2CAP_TRACE_DEBUG ("l2c_link_adjust_chnl_allocation");
/* assign buffer quota to each channel based on its data rate requirement */
list_foreach(l2cb.p_ccb_pool, l2c_chnl_allocation_in_ccb_list, NULL);
}
/*******************************************************************************
@ -876,7 +880,6 @@ UINT8 l2c_link_pkts_rcvd (UINT16 *num_pkts, UINT16 *handles)
void l2c_link_role_changed (BD_ADDR bd_addr, UINT8 new_role, UINT8 hci_status)
{
tL2C_LCB *p_lcb;
int xx;
/* Make sure not called from HCI Command Status (bd_addr and new_role are invalid) */
if (bd_addr) {
@ -893,7 +896,9 @@ void l2c_link_role_changed (BD_ADDR bd_addr, UINT8 new_role, UINT8 hci_status)
}
/* Check if any LCB was waiting for switch to be completed */
for (xx = 0, p_lcb = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
list_node_t *p_node = NULL;
for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
p_lcb = list_node(p_node);
if ((p_lcb->in_use) && (p_lcb->link_state == LST_CONNECTING_WAIT_SWITCH)) {
l2cu_create_conn_after_switch (p_lcb);
}
@ -981,7 +986,6 @@ BOOLEAN l2c_link_check_power_mode (tL2C_LCB *p_lcb)
*******************************************************************************/
void l2c_link_check_send_pkts (tL2C_LCB *p_lcb, tL2C_CCB *p_ccb, BT_HDR *p_buf)
{
int xx;
BOOLEAN single_write = FALSE;
L2CAP_TRACE_DEBUG("%s",__func__);
/* Save the channel ID for faster counting */
@ -1020,14 +1024,25 @@ void l2c_link_check_send_pkts (tL2C_LCB *p_lcb, tL2C_CCB *p_ccb, BT_HDR *p_buf)
** have at least 1, then do a round-robin for all the LCBs
*/
if ( (p_lcb == NULL) || (p_lcb->link_xmit_quota == 0) ) {
list_node_t *p_node = NULL;
tL2C_LCB *p_lcb_cur = NULL;
if (p_lcb == NULL) {
p_lcb = l2cb.lcb_pool;
p_node = list_begin(l2cb.p_lcb_pool);
p_lcb = list_node(p_node);
} else if (!single_write) {
p_lcb++;
for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
p_lcb_cur = list_node(p_node);
if (p_lcb_cur == p_lcb) {
p_node = list_next(p_node);
p_lcb = list_node(p_node);
break;
}
}
}
/* Loop through, starting at the next */
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
for ( ; p_node; p_node = list_next(p_node)) {
p_lcb = list_node(p_node);
#if (BLE_INCLUDED == TRUE)
L2CAP_TRACE_DEBUG("window = %d,robin_unacked = %d,robin_quota=%d",l2cb.controller_le_xmit_window,l2cb.ble_round_robin_unacked,l2cb.ble_round_robin_quota);
#endif ///BLE_INCLUDED == TRUE
@ -1047,9 +1062,10 @@ void l2c_link_check_send_pkts (tL2C_LCB *p_lcb, tL2C_CCB *p_ccb, BT_HDR *p_buf)
/* Check for wraparound */
if (p_lcb == &l2cb.lcb_pool[MAX_L2CAP_LINKS]) {
p_lcb = &l2cb.lcb_pool[0];
}
if (p_node == list_end(l2cb.p_lcb_pool)) {
p_node = list_begin(l2cb.p_lcb_pool);
p_lcb = list_node(p_node);
}
L2CAP_TRACE_DEBUG("in_use=%d,segment_being_sent=%d,link_state=%d,link_xmit_quota=%d",p_lcb->in_use,p_lcb->partial_segment_being_sent,p_lcb->link_state,p_lcb->link_xmit_quota);
if ( (!p_lcb->in_use)
|| (p_lcb->partial_segment_being_sent)

View File

@ -827,7 +827,6 @@ void l2c_process_held_packets(BOOLEAN timed_out)
*******************************************************************************/
void l2c_init (void)
{
INT16 xx;
#if L2C_DYNAMIC_MEMORY
l2c_cb_ptr = (tL2C_CB *)osi_malloc(sizeof(tL2C_CB));
#endif /* #if L2C_DYNAMIC_MEMORY */
@ -835,9 +834,13 @@ void l2c_init (void)
/* the psm is increased by 2 before being used */
l2cb.dyn_psm = 0xFFF;
/* Put all the channel control blocks on the free queue */
for (xx = 0; xx < MAX_L2CAP_CHANNELS - 1; xx++) {
l2cb.ccb_pool[xx].p_next_ccb = &l2cb.ccb_pool[xx + 1];
l2cb.p_ccb_pool = list_new(osi_free_func);
if (l2cb.p_ccb_pool == NULL) {
L2CAP_TRACE_ERROR("%s unable to allocate memory for L2CAP channel control block", __func__);
}
l2cb.p_lcb_pool = list_new(osi_free_func);
if (l2cb.p_lcb_pool == NULL) {
L2CAP_TRACE_ERROR("%s unable to allocate memory for L2CAP Link control block", __func__);
}
#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
@ -846,8 +849,6 @@ void l2c_init (void)
#endif
l2cb.p_free_ccb_first = &l2cb.ccb_pool[0];
l2cb.p_free_ccb_last = &l2cb.ccb_pool[MAX_L2CAP_CHANNELS - 1];
#ifdef L2CAP_DESIRED_LINK_ROLE
l2cb.desire_role = L2CAP_DESIRED_LINK_ROLE;
@ -892,6 +893,8 @@ void l2c_free(void)
{
list_free(l2cb.rcv_pending_q);
l2cb.rcv_pending_q = NULL;
list_free(l2cb.p_lcb_pool);
list_free(l2cb.p_ccb_pool);
#if L2C_DYNAMIC_MEMORY
FREE_AND_RESET(l2c_cb_ptr);
#endif

View File

@ -245,6 +245,16 @@ BOOLEAN L2CA_UcdRegister ( UINT16 psm, tL2CAP_UCD_CB_INFO *p_cb_info )
** Return value: TRUE if successs
**
*******************************************************************************/
BOOLEAN L2CA_UcdDeregister_In_CCB_List (void *p_ccb_node, void * context)
{
p_ccb = (tL2C_CCB *)p_ccb_node;
if (( p_ccb->in_use )
&& ( p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID )) {
l2cu_release_ccb (p_ccb);
}
return false;
}
BOOLEAN L2CA_UcdDeregister ( UINT16 psm )
{
tL2C_CCB *p_ccb;
@ -275,15 +285,7 @@ BOOLEAN L2CA_UcdDeregister ( UINT16 psm )
}
/* delete CCB for UCD */
p_ccb = l2cb.ccb_pool;
for ( xx = 0; xx < MAX_L2CAP_CHANNELS; xx++ ) {
if (( p_ccb->in_use )
&& ( p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID )) {
l2cu_release_ccb (p_ccb);
}
p_ccb++;
}
list_foreach(l2cb.p_ccb_pool, L2CA_UcdDeregister_In_CCB_List, NULL);
return (TRUE);
}

View File

@ -37,6 +37,7 @@
#include "btm_int.h"
#include "stack/hcidefs.h"
#include "osi/allocator.h"
#include "osi/list.h"
/*******************************************************************************
**
@ -49,11 +50,19 @@
*******************************************************************************/
tL2C_LCB *l2cu_allocate_lcb (BD_ADDR p_bd_addr, BOOLEAN is_bonding, tBT_TRANSPORT transport)
{
int xx;
tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
if (!p_lcb->in_use) {
tL2C_LCB *p_lcb = NULL;
bool list_ret = false;
if (list_length(l2cb.p_lcb_pool) < MAX_L2CAP_LINKS) {
p_lcb = (tL2C_LCB *)osi_malloc(sizeof(tL2C_LCB));
if (p_lcb) {
memset (p_lcb, 0, sizeof(tL2C_LCB));
list_ret = list_append(l2cb.p_lcb_pool, p_lcb);
}else {
L2CAP_TRACE_ERROR("Error in allocating L2CAP Link Control Block");
}
}
if (list_ret) {
if (p_lcb) {
btu_free_timer(&p_lcb->timer_entry);
btu_free_timer(&p_lcb->info_timer_entry);
btu_free_timer(&p_lcb->upda_con_timer);
@ -263,7 +272,14 @@ void l2cu_release_lcb (tL2C_LCB *p_lcb)
#if (C2H_FLOW_CONTROL_INCLUDED == TRUE)
p_lcb->completed_packets = 0;
#endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE
{
if (list_remove(l2cb.p_lcb_pool, p_lcb)) {
p_lcb = NULL;
}
else {
L2CAP_TRACE_ERROR("Error in removing L2CAP Link Control Block");
}
}
}
@ -279,10 +295,10 @@ void l2cu_release_lcb (tL2C_LCB *p_lcb)
*******************************************************************************/
tL2C_LCB *l2cu_find_lcb_by_bd_addr (BD_ADDR p_bd_addr, tBT_TRANSPORT transport)
{
int xx;
tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
list_node_t *p_node = NULL;
tL2C_LCB *p_lcb = NULL;
for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
p_lcb = list_node(p_node);
if ((p_lcb->in_use) &&
#if BLE_INCLUDED == TRUE
p_lcb->transport == transport &&
@ -1419,43 +1435,19 @@ void l2cu_change_pri_ccb (tL2C_CCB *p_ccb, tL2CAP_CHNL_PRIORITY priority)
*******************************************************************************/
tL2C_CCB *l2cu_allocate_ccb (tL2C_LCB *p_lcb, UINT16 cid)
{
tL2C_CCB *p_ccb;
tL2C_CCB *p_prev;
tL2C_CCB *p_ccb = NULL;
L2CAP_TRACE_DEBUG ("l2cu_allocate_ccb: cid 0x%04x", cid);
if (!l2cb.p_free_ccb_first) {
return (NULL);
if (list_length(l2cb.p_ccb_pool) < MAX_L2CAP_CHANNELS) {
p_ccb = (tL2C_CCB *)osi_malloc(sizeof(tL2C_CCB));
if (p_ccb) {
memset (p_ccb, 0, sizeof(tL2C_CCB));
list_append(l2cb.p_ccb_pool, p_ccb);
}
}
/* If a CID was passed in, use that, else take the first free one */
if (cid == 0) {
p_ccb = l2cb.p_free_ccb_first;
l2cb.p_free_ccb_first = p_ccb->p_next_ccb;
} else {
p_prev = NULL;
p_ccb = &l2cb.ccb_pool[cid - L2CAP_BASE_APPL_CID];
if (p_ccb == l2cb.p_free_ccb_first) {
l2cb.p_free_ccb_first = p_ccb->p_next_ccb;
} else {
for (p_prev = l2cb.p_free_ccb_first; p_prev != NULL; p_prev = p_prev->p_next_ccb) {
if (p_prev->p_next_ccb == p_ccb) {
p_prev->p_next_ccb = p_ccb->p_next_ccb;
if (p_ccb == l2cb.p_free_ccb_last) {
l2cb.p_free_ccb_last = p_prev;
}
break;
}
}
if (p_prev == NULL) {
L2CAP_TRACE_ERROR ("l2cu_allocate_ccb: could not find CCB for CID 0x%04x in the free list", cid);
return NULL;
}
}
if (p_ccb == NULL) {
return (NULL);
}
p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
@ -1463,8 +1455,7 @@ tL2C_CCB *l2cu_allocate_ccb (tL2C_LCB *p_lcb, UINT16 cid)
p_ccb->in_use = TRUE;
/* Get a CID for the connection */
p_ccb->local_cid = L2CAP_BASE_APPL_CID + (UINT16)(p_ccb - l2cb.ccb_pool);
p_ccb->local_cid = L2CAP_BASE_APPL_CID + (list_length(l2cb.p_ccb_pool) - 1);
p_ccb->p_lcb = p_lcb;
p_ccb->p_rcb = NULL;
p_ccb->should_free_rcb = false;
@ -1628,7 +1619,6 @@ void l2cu_release_ccb (tL2C_CCB *p_ccb)
{
tL2C_LCB *p_lcb = p_ccb->p_lcb;
tL2C_RCB *p_rcb = p_ccb->p_rcb;
L2CAP_TRACE_DEBUG ("l2cu_release_ccb: cid 0x%04x in_use: %u", p_ccb->local_cid, p_ccb->in_use);
/* If already released, could be race condition */
@ -1645,7 +1635,6 @@ void l2cu_release_ccb (tL2C_CCB *p_ccb)
p_ccb->p_rcb = NULL;
p_ccb->should_free_rcb = false;
}
if (p_lcb) {
btm_sec_clr_temp_auth_service (p_lcb->remote_bd_addr);
}
@ -1682,22 +1671,17 @@ void l2cu_release_ccb (tL2C_CCB *p_ccb)
p_ccb->p_lcb = NULL;
}
/* Put the CCB back on the free pool */
if (!l2cb.p_free_ccb_first) {
l2cb.p_free_ccb_first = p_ccb;
l2cb.p_free_ccb_last = p_ccb;
p_ccb->p_next_ccb = NULL;
p_ccb->p_prev_ccb = NULL;
} else {
p_ccb->p_next_ccb = NULL;
p_ccb->p_prev_ccb = l2cb.p_free_ccb_last;
l2cb.p_free_ccb_last->p_next_ccb = p_ccb;
l2cb.p_free_ccb_last = p_ccb;
}
/* Flag as not in use */
p_ccb->in_use = FALSE;
{
if (list_remove(l2cb.p_ccb_pool, p_ccb)) {
p_ccb = NULL;
}
else {
L2CAP_TRACE_ERROR("Error in removing L2CAP Channel Control Block");
}
}
/* If no channels on the connection, start idle timeout */
if ((p_lcb) && p_lcb->in_use && (p_lcb->link_state == LST_CONNECTED)) {
if (!p_lcb->ccb_queue.p_first_ccb) {
@ -2188,10 +2172,10 @@ void l2cu_process_our_cfg_rsp (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
*******************************************************************************/
void l2cu_device_reset (void)
{
int xx;
tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
list_node_t *p_node = NULL;
tL2C_LCB *p_lcb = NULL;
for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
p_lcb = list_node(p_node);
if ((p_lcb->in_use) && (p_lcb->handle != HCI_INVALID_HANDLE)) {
l2c_link_hci_disc_comp (p_lcb->handle, (UINT8) - 1);
}
@ -2212,11 +2196,11 @@ void l2cu_device_reset (void)
*******************************************************************************/
BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb, tBT_TRANSPORT transport)
{
int xx;
tL2C_LCB *p_lcb_cur = &l2cb.lcb_pool[0];
#if BTM_SCO_INCLUDED == TRUE
BOOLEAN is_sco_active;
#endif
list_node_t *p_node = NULL;
tL2C_LCB *p_lcb_cur = NULL;
#if (BLE_INCLUDED == TRUE)
tBT_DEVICE_TYPE dev_type;
@ -2241,7 +2225,8 @@ BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb, tBT_TRANSPORT transport)
/* If there is a connection where we perform as a slave, try to switch roles
for this connection */
for (xx = 0, p_lcb_cur = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS; xx++, p_lcb_cur++) {
for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
p_lcb_cur = list_node(p_node);
if (p_lcb_cur == p_lcb) {
continue;
}
@ -2295,10 +2280,11 @@ BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb, tBT_TRANSPORT transport)
UINT8 l2cu_get_num_hi_priority (void)
{
UINT8 no_hi = 0;
int xx;
tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
list_node_t *p_node = NULL;
tL2C_LCB *p_lcb = NULL;
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
p_lcb = list_node(p_node);
if ((p_lcb->in_use) && (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) {
no_hi++;
}
@ -2395,10 +2381,11 @@ BOOLEAN l2cu_create_conn_after_switch (tL2C_LCB *p_lcb)
*******************************************************************************/
tL2C_LCB *l2cu_find_lcb_by_state (tL2C_LINK_STATE state)
{
UINT16 i;
tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
list_node_t *p_node = NULL;
tL2C_LCB *p_lcb = NULL;
for (i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++) {
for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
p_lcb = list_node(p_node);
if ((p_lcb->in_use) && (p_lcb->link_state == state)) {
return (p_lcb);
}
@ -2425,12 +2412,11 @@ BOOLEAN l2cu_lcb_disconnecting (void)
{
tL2C_LCB *p_lcb;
tL2C_CCB *p_ccb;
UINT16 i;
BOOLEAN status = FALSE;
list_node_t *p_node = NULL;
p_lcb = &l2cb.lcb_pool[0];
for (i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++) {
for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
p_lcb = list_node(p_node);
if (p_lcb->in_use) {
/* no ccbs on lcb, or lcb is in disconnecting state */
if ((!p_lcb->ccb_queue.p_first_ccb) || (p_lcb->link_state == LST_DISCONNECTING)) {
@ -2541,8 +2527,8 @@ void l2cu_resubmit_pending_sec_req (BD_ADDR p_bda)
tL2C_LCB *p_lcb;
tL2C_CCB *p_ccb;
tL2C_CCB *p_next_ccb;
int xx;
L2CAP_TRACE_DEBUG ("l2cu_resubmit_pending_sec_req p_bda: %p", p_bda);
list_node_t *p_node = NULL;
/* If we are called with a BDA, only resubmit for that BDA */
if (p_bda) {
@ -2559,7 +2545,8 @@ void l2cu_resubmit_pending_sec_req (BD_ADDR p_bda)
}
} else {
/* No BDA pasesed in, so check all links */
for (xx = 0, p_lcb = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
p_lcb = list_node(p_node);
if (p_lcb->in_use) {
/* For all channels, send the event through their FSMs */
for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) {
@ -3179,11 +3166,11 @@ void l2cu_send_peer_ble_credit_based_disconn_req(tL2C_CCB *p_ccb)
*******************************************************************************/
UINT8 l2cu_find_completed_packets(UINT16 *handles, UINT16 *num_packets)
{
int xx;
UINT8 num = 0;
tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
list_node_t *p_node = NULL;
tL2C_LCB *p_lcb = NULL;
for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
p_lcb = list_node(p_node);
if ((p_lcb->in_use) && (p_lcb->completed_packets > 0)) {
*(handles++) = p_lcb->handle;
*(num_packets++) = p_lcb->completed_packets;
@ -3212,10 +3199,10 @@ UINT8 l2cu_find_completed_packets(UINT16 *handles, UINT16 *num_packets)
*******************************************************************************/
tL2C_LCB *l2cu_find_lcb_by_handle (UINT16 handle)
{
int xx;
tL2C_LCB *p_lcb = &l2cb.lcb_pool[0];
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
list_node_t *p_node = NULL;
tL2C_LCB *p_lcb = NULL;
for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
p_lcb = list_node(p_node);
if ((p_lcb->in_use) && (p_lcb->handle == handle)) {
return (p_lcb);
}
@ -3236,50 +3223,35 @@ tL2C_LCB *l2cu_find_lcb_by_handle (UINT16 handle)
** Returns pointer to matched CCB, or NULL if no match
**
*******************************************************************************/
bool l2cu_find_ccb_in_list(void *p_ccb_node, void *p_local_cid)
{
tL2C_CCB *p_ccb = (tL2C_CCB *)p_ccb_node;
uint8_t local_cid = *((uint8_t *)p_local_cid);
if (p_ccb->local_cid == local_cid && p_ccb->in_use) {
return FALSE;
}
return TRUE;
}
tL2C_CCB *l2cu_find_ccb_by_cid (tL2C_LCB *p_lcb, UINT16 local_cid)
{
tL2C_CCB *p_ccb = NULL;
#if (L2CAP_UCD_INCLUDED == TRUE)
UINT8 xx;
#endif
if (local_cid >= L2CAP_BASE_APPL_CID) {
/* find the associated CCB by "index" */
local_cid -= L2CAP_BASE_APPL_CID;
if (local_cid >= MAX_L2CAP_CHANNELS) {
return NULL;
}
p_ccb = l2cb.ccb_pool + local_cid;
/* make sure the CCB is in use */
if (!p_ccb->in_use) {
p_ccb = NULL;
}
/* make sure it's for the same LCB */
else if (p_lcb && p_lcb != p_ccb->p_lcb) {
p_ccb = NULL;
}
#if (L2CAP_UCD_INCLUDED == FALSE)
if (local_cid < L2CAP_BASE_APPL_CID) {
return NULL;
}
#if (L2CAP_UCD_INCLUDED == TRUE)
else {
/* searching fixed channel */
p_ccb = l2cb.ccb_pool;
for ( xx = 0; xx < MAX_L2CAP_CHANNELS; xx++ ) {
if ((p_ccb->local_cid == local_cid)
&& (p_ccb->in_use)
&& (p_lcb == p_ccb->p_lcb)) {
break;
} else {
p_ccb++;
}
}
if ( xx >= MAX_L2CAP_CHANNELS ) {
return NULL;
}
#endif //(L2CAP_UCD_INCLUDED == FALSE)
list_node_t *p_node = NULL;
p_node = (list_foreach(l2cb.p_ccb_pool, l2cu_find_ccb_in_list, &local_cid));
if (p_node) {
p_ccb = (tL2C_CCB *)list_node(p_node);
if (p_lcb && p_lcb != p_ccb->p_lcb) {
p_ccb = NULL;
}
}
#endif
return (p_ccb);
}

View File

@ -29,6 +29,7 @@
#include "common/bt_defs.h"
#include "stack/sdp_api.h"
#include "stack/l2c_api.h"
#include "osi/list.h"
#if (SDP_INCLUDED == TRUE)
/* Continuation length - we use a 2-byte offset */
@ -136,7 +137,7 @@ typedef struct {
typedef struct {
UINT32 di_primary_handle; /* Device ID Primary record or NULL if nonexistent */
UINT16 num_records;
tSDP_RECORD record[SDP_MAX_RECORDS];
list_t *p_record_list;
} tSDP_DB;
enum {

View File

@ -37,6 +37,8 @@
#include "stack/sdp_api.h"
#include "sdpint.h"
#include "osi/list.h"
#if (SDP_INCLUDED == TRUE)
#if SDP_SERVER_ENABLED == TRUE
@ -62,18 +64,25 @@ tSDP_RECORD *sdp_db_service_search (tSDP_RECORD *p_rec, tSDP_UUID_SEQ *p_seq)
{
UINT16 xx, yy;
tSDP_ATTRIBUTE *p_attr;
tSDP_RECORD *p_end = &sdp_cb.server_db.record[sdp_cb.server_db.num_records];
list_node_t *p_node = NULL;
/* If NULL, start at the beginning, else start at the first specified record */
if (!p_rec) {
p_rec = &sdp_cb.server_db.record[0];
p_node = list_begin(sdp_cb.server_db.p_record_list);
} else {
p_rec++;
/* get node in the record list with given p_rec */
p_node = list_get_node(sdp_cb.server_db.p_record_list, p_rec);
if (p_node == NULL) {
return NULL;
}
/* get next node */
p_node = list_next(p_node);
}
/* Look through the records. The spec says that a match occurs if */
/* the record contains all the passed UUIDs in it. */
for ( ; p_rec < p_end; p_rec++) {
for( ; p_node; p_node = list_next(p_node)) {
p_rec = list_node(p_node);
for (yy = 0; yy < p_seq->num_uids; yy++) {
p_attr = &p_rec->attribute[0];
for (xx = 0; xx < p_rec->num_attributes; xx++, p_attr++) {
@ -161,11 +170,12 @@ static BOOLEAN find_uuid_in_seq (UINT8 *p , UINT32 seq_len, UINT8 *p_uuid,
tSDP_RECORD *sdp_db_find_record (UINT32 handle)
{
tSDP_RECORD *p_rec;
tSDP_RECORD *p_end = &sdp_cb.server_db.record[sdp_cb.server_db.num_records];
list_node_t *p_node = NULL;
/* Look through the records for the caller's handle */
for (p_rec = &sdp_cb.server_db.record[0]; p_rec < p_end; p_rec++) {
if (p_rec->record_handle == handle) {
for(p_node = list_begin(sdp_cb.server_db.p_record_list); p_node; p_node = list_next(p_node)) {
p_rec = list_node(p_node);
if (p_rec->record_handle == handle) {
return (p_rec);
}
}
@ -278,30 +288,42 @@ UINT32 SDP_CreateRecord (void)
UINT32 handle;
UINT8 buf[4];
tSDP_DB *p_db = &sdp_cb.server_db;
tSDP_RECORD *p_rec = NULL;
tSDP_RECORD *p_rec_prev = NULL;
/* First, check if there is a free record */
if (p_db->num_records < SDP_MAX_RECORDS) {
memset (&p_db->record[p_db->num_records], 0,
sizeof (tSDP_RECORD));
p_rec =(tSDP_RECORD *)osi_malloc(sizeof(tSDP_RECORD));
if (p_rec) {
memset(p_rec, 0, sizeof(tSDP_RECORD));
/* Save previous rec */
if (p_db->num_records) {
p_rec_prev = list_back(p_db->p_record_list);
}
/* Append new record */
list_append(p_db->p_record_list, p_rec);
/* We will use a handle of the first unreserved handle plus last record
** number + 1 */
if (p_db->num_records) {
handle = p_db->record[p_db->num_records - 1].record_handle + 1;
} else {
handle = 0x10000;
}
/* We will use a handle of the first unreserved handle plus last record
** number + 1 */
if (p_db->num_records) {
handle = p_rec_prev->record_handle + 1;
} else {
handle = 0x10000;
}
p_db->record[p_db->num_records].record_handle = handle;
p_rec->record_handle = handle;
p_db->num_records++;
SDP_TRACE_DEBUG("SDP_CreateRecord ok, num_records:%d\n", p_db->num_records);
/* Add the first attribute (the handle) automatically */
UINT32_TO_BE_FIELD (buf, handle);
SDP_AddAttribute (handle, ATTR_ID_SERVICE_RECORD_HDL, UINT_DESC_TYPE,
4, buf);
p_db->num_records++;
SDP_TRACE_DEBUG("SDP_CreateRecord ok, num_records:%d\n", p_db->num_records);
/* Add the first attribute (the handle) automatically */
UINT32_TO_BE_FIELD (buf, handle);
SDP_AddAttribute (handle, ATTR_ID_SERVICE_RECORD_HDL, UINT_DESC_TYPE,
4, buf);
return (p_db->record[p_db->num_records - 1].record_handle);
return (p_rec->record_handle);
} else {
SDP_TRACE_ERROR("SDP_CreateRecord fail, memory allocation failed\n");
}
} else {
SDP_TRACE_ERROR("SDP_CreateRecord fail, exceed maximum records:%d\n", SDP_MAX_RECORDS);
}
@ -326,30 +348,26 @@ UINT32 SDP_CreateRecord (void)
BOOLEAN SDP_DeleteRecord (UINT32 handle)
{
#if SDP_SERVER_ENABLED == TRUE
UINT16 xx, yy, zz;
tSDP_RECORD *p_rec = &sdp_cb.server_db.record[0];
tSDP_RECORD *p_rec = NULL;
list_node_t *p_node = NULL;
if (handle == 0 || sdp_cb.server_db.num_records == 0) {
/* Delete all records in the database */
sdp_cb.server_db.num_records = 0;
for(p_node = list_begin(sdp_cb.server_db.p_record_list); p_node; p_node = list_next(p_node)) {
list_remove(sdp_cb.server_db.p_record_list, p_node);
}
/* require new DI record to be created in SDP_SetLocalDiRecord */
sdp_cb.server_db.di_primary_handle = 0;
return (TRUE);
} else {
/* Find the record in the database */
for (xx = 0; xx < sdp_cb.server_db.num_records; xx++, p_rec++) {
for(p_node = list_begin(sdp_cb.server_db.p_record_list); p_node; p_node = list_next(p_node)) {
p_rec = list_node(p_node);
if (p_rec->record_handle == handle) {
/* Found it. Shift everything up one */
for (yy = xx; yy < sdp_cb.server_db.num_records; yy++, p_rec++) {
*p_rec = *(p_rec + 1);
/* Adjust the attribute value pointer for each attribute */
for (zz = 0; zz < p_rec->num_attributes; zz++) {
p_rec->attribute[zz].value_ptr -= sizeof(tSDP_RECORD);
}
}
list_remove(sdp_cb.server_db.p_record_list, p_rec);
sdp_cb.server_db.num_records--;
@ -387,8 +405,9 @@ BOOLEAN SDP_AddAttribute (UINT32 handle, UINT16 attr_id, UINT8 attr_type,
UINT32 attr_len, UINT8 *p_val)
{
#if SDP_SERVER_ENABLED == TRUE
UINT16 xx, yy, zz;
tSDP_RECORD *p_rec = &sdp_cb.server_db.record[0];
UINT16 xx, yy;
tSDP_RECORD *p_rec = NULL;
list_node_t *p_node= NULL;
#if (BT_TRACE_VERBOSE == TRUE)
if (sdp_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) {
@ -418,7 +437,8 @@ BOOLEAN SDP_AddAttribute (UINT32 handle, UINT16 attr_id, UINT8 attr_type,
#endif
/* Find the record in the database */
for (zz = 0; zz < sdp_cb.server_db.num_records; zz++, p_rec++) {
for(p_node = list_begin(sdp_cb.server_db.p_record_list); p_node; p_node = list_next(p_node)) {
p_rec= list_node(p_node);
if (p_rec->record_handle == handle) {
tSDP_ATTRIBUTE *p_attr = &p_rec->attribute[0];
@ -850,12 +870,14 @@ BOOLEAN SDP_DeleteAttribute (UINT32 handle, UINT16 attr_id)
{
#if SDP_SERVER_ENABLED == TRUE
UINT16 xx, yy;
tSDP_RECORD *p_rec = &sdp_cb.server_db.record[0];
tSDP_RECORD *p_rec = NULL;
list_node_t *p_node= NULL;
UINT8 *pad_ptr;
UINT32 len; /* Number of bytes in the entry */
/* Find the record in the database */
for (xx = 0; xx < sdp_cb.server_db.num_records; xx++, p_rec++) {
for(p_node = list_begin(sdp_cb.server_db.p_record_list); p_node; p_node = list_next(p_node)) {
p_rec= list_node(p_node);
if (p_rec->record_handle == handle) {
tSDP_ATTRIBUTE *p_attr = &p_rec->attribute[0];

View File

@ -41,6 +41,8 @@
#include "stack/sdp_api.h"
#include "sdpint.h"
#include "osi/list.h"
#if (SDP_INCLUDED == TRUE)
/********************************************************************************/
/* G L O B A L S D P D A T A */
@ -87,6 +89,7 @@ void sdp_init (void)
/* Clears all structures and local SDP database (if Server is enabled) */
memset (&sdp_cb, 0, sizeof (tSDP_CB));
sdp_cb.server_db.p_record_list = list_new(osi_free_func);
/* Initialize the L2CAP configuration. We only care about MTU and flush */
sdp_cb.l2cap_my_cfg.mtu_present = TRUE;
sdp_cb.l2cap_my_cfg.mtu = SDP_MTU_SIZE;
@ -140,6 +143,7 @@ void sdp_init (void)
void sdp_deinit (void)
{
list_free(sdp_cb.server_db.p_record_list);
#if SDP_DYNAMIC_MEMORY
osi_free(sdp_cb_ptr);
sdp_cb_ptr = NULL;