Fork ESP-IDF's bluetooth component
i want better sbc encoding, and no cla will stop me
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,608 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2012 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file contains functions for BLE address management.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "stack/bt_types.h"
|
||||
#include "stack/hcimsgs.h"
|
||||
#include "stack/btu.h"
|
||||
#include "btm_int.h"
|
||||
#include "stack/gap_api.h"
|
||||
#include "device/controller.h"
|
||||
|
||||
#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
|
||||
#include "btm_ble_int.h"
|
||||
#include "stack/smp_api.h"
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_gen_resolve_paddr_cmpl
|
||||
**
|
||||
** Description This is callback functioin when resolvable private address
|
||||
** generation is complete.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void btm_gen_resolve_paddr_cmpl(tSMP_ENC *p)
|
||||
{
|
||||
tBTM_LE_RANDOM_CB *p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
|
||||
BTM_TRACE_EVENT ("btm_gen_resolve_paddr_cmpl");
|
||||
|
||||
if (p) {
|
||||
/* set hash to be LSB of rpAddress */
|
||||
p_cb->private_addr[5] = p->param_buf[0];
|
||||
p_cb->private_addr[4] = p->param_buf[1];
|
||||
p_cb->private_addr[3] = p->param_buf[2];
|
||||
|
||||
/* set it to controller */
|
||||
btm_ble_set_random_addr(p_cb->private_addr);
|
||||
|
||||
p_cb->exist_addr_bit |= BTM_BLE_GAP_ADDR_BIT_RESOLVABLE;
|
||||
memcpy(p_cb->resolvale_addr, p_cb->private_addr, BD_ADDR_LEN);
|
||||
if (p_cb->set_local_privacy_cback){
|
||||
(*p_cb->set_local_privacy_cback)(BTM_SET_PRIVACY_SUCCESS);
|
||||
p_cb->set_local_privacy_cback = NULL;
|
||||
}
|
||||
|
||||
/* start a periodical timer to refresh random addr */
|
||||
btu_stop_timer_oneshot(&p_cb->raddr_timer_ent);
|
||||
#if (BTM_BLE_CONFORMANCE_TESTING == TRUE)
|
||||
btu_start_timer_oneshot(&p_cb->raddr_timer_ent, BTU_TTYPE_BLE_RANDOM_ADDR,
|
||||
btm_cb.ble_ctr_cb.rpa_tout);
|
||||
#else
|
||||
btu_start_timer_oneshot(&p_cb->raddr_timer_ent, BTU_TTYPE_BLE_RANDOM_ADDR,
|
||||
BTM_BLE_PRIVATE_ADDR_INT);
|
||||
#endif
|
||||
} else {
|
||||
/* random address set failure */
|
||||
BTM_TRACE_DEBUG("set random address failed");
|
||||
if (p_cb->set_local_privacy_cback){
|
||||
(*p_cb->set_local_privacy_cback)(BTM_SET_PRIVACY_FAIL);
|
||||
p_cb->set_local_privacy_cback = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_gen_resolve_paddr_low
|
||||
**
|
||||
** Description This function is called when random address has generate the
|
||||
** random number base for low 3 byte bd address.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_gen_resolve_paddr_low(tBTM_RAND_ENC *p)
|
||||
{
|
||||
#if (BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE)
|
||||
tBTM_LE_RANDOM_CB *p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
|
||||
tSMP_ENC output;
|
||||
|
||||
BTM_TRACE_EVENT ("btm_gen_resolve_paddr_low");
|
||||
if (p) {
|
||||
p->param_buf[2] &= (~BLE_RESOLVE_ADDR_MASK);
|
||||
p->param_buf[2] |= BLE_RESOLVE_ADDR_MSB;
|
||||
|
||||
p_cb->private_addr[2] = p->param_buf[0];
|
||||
p_cb->private_addr[1] = p->param_buf[1];
|
||||
p_cb->private_addr[0] = p->param_buf[2];
|
||||
|
||||
/* encrypt with ur IRK */
|
||||
if (!SMP_Encrypt(btm_cb.devcb.id_keys.irk, BT_OCTET16_LEN, p->param_buf, 3, &output)) {
|
||||
btm_gen_resolve_paddr_cmpl(NULL);
|
||||
} else {
|
||||
btm_gen_resolve_paddr_cmpl(&output);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_gen_resolvable_private_addr
|
||||
**
|
||||
** Description This function generate a resolvable private address.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_gen_resolvable_private_addr (void *p_cmd_cplt_cback)
|
||||
{
|
||||
BTM_TRACE_EVENT ("btm_gen_resolvable_private_addr");
|
||||
/* generate 3B rand as BD LSB, SRK with it, get BD MSB */
|
||||
if (!btsnd_hcic_ble_rand((void *)p_cmd_cplt_cback)) {
|
||||
btm_gen_resolve_paddr_cmpl(NULL);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_gen_non_resolve_paddr_cmpl
|
||||
**
|
||||
** Description This is the callback function when non-resolvable private
|
||||
** function is generated and write to controller.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void btm_gen_non_resolve_paddr_cmpl(tBTM_RAND_ENC *p)
|
||||
{
|
||||
tBTM_LE_RANDOM_CB *p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
|
||||
tBTM_BLE_ADDR_CBACK *p_cback = p_cb->p_generate_cback;
|
||||
void *p_data = p_cb->p;
|
||||
UINT8 *pp;
|
||||
BD_ADDR static_random;
|
||||
|
||||
BTM_TRACE_EVENT ("btm_gen_non_resolve_paddr_cmpl");
|
||||
|
||||
p_cb->p_generate_cback = NULL;
|
||||
if (p) {
|
||||
|
||||
pp = p->param_buf;
|
||||
STREAM_TO_BDADDR(static_random, pp);
|
||||
/* mask off the 2 MSB */
|
||||
static_random[0] &= BLE_STATIC_PRIVATE_MSB_MASK;
|
||||
|
||||
/* report complete */
|
||||
if (p_cback) {
|
||||
(* p_cback)(static_random, p_data);
|
||||
}
|
||||
} else {
|
||||
BTM_TRACE_DEBUG("btm_gen_non_resolvable_private_addr failed");
|
||||
if (p_cback) {
|
||||
(* p_cback)(NULL, p_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_gen_non_resolvable_private_addr
|
||||
**
|
||||
** Description This function generate a non-resolvable private address.
|
||||
**
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_gen_non_resolvable_private_addr (tBTM_BLE_ADDR_CBACK *p_cback, void *p)
|
||||
{
|
||||
tBTM_LE_RANDOM_CB *p_mgnt_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
|
||||
|
||||
BTM_TRACE_EVENT ("btm_gen_non_resolvable_private_addr");
|
||||
|
||||
if (p_mgnt_cb->p_generate_cback != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
p_mgnt_cb->p_generate_cback = p_cback;
|
||||
p_mgnt_cb->p = p;
|
||||
if (!btsnd_hcic_ble_rand((void *)btm_gen_non_resolve_paddr_cmpl)) {
|
||||
btm_gen_non_resolve_paddr_cmpl(NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
** Utility functions for Random address resolving
|
||||
*******************************************************************************/
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_resolve_address_cmpl
|
||||
**
|
||||
** Description This function sends the random address resolving complete
|
||||
** callback.
|
||||
**
|
||||
** Returns None.
|
||||
**
|
||||
*******************************************************************************/
|
||||
#if SMP_INCLUDED == TRUE
|
||||
static void btm_ble_resolve_address_cmpl(void)
|
||||
{
|
||||
tBTM_LE_RANDOM_CB *p_mgnt_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
|
||||
|
||||
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_mgnt_cb->p_dev_rec, p_mgnt_cb->p);
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_proc_resolve_x
|
||||
**
|
||||
** Description This function compares the X with random address 3 MSO bytes
|
||||
** to find a match, if not match, continue for next record.
|
||||
**
|
||||
** Returns None.
|
||||
**
|
||||
*******************************************************************************/
|
||||
static BOOLEAN btm_ble_proc_resolve_x(tSMP_ENC *p)
|
||||
{
|
||||
tBTM_LE_RANDOM_CB *p_mgnt_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
|
||||
UINT8 comp[3];
|
||||
BTM_TRACE_EVENT ("btm_ble_proc_resolve_x");
|
||||
/* compare the hash with 3 LSB of bd address */
|
||||
comp[0] = p_mgnt_cb->random_bda[5];
|
||||
comp[1] = p_mgnt_cb->random_bda[4];
|
||||
comp[2] = p_mgnt_cb->random_bda[3];
|
||||
|
||||
if (p) {
|
||||
if (!memcmp(p->param_buf, &comp[0], 3)) {
|
||||
/* match is found */
|
||||
BTM_TRACE_EVENT ("match is found");
|
||||
btm_ble_resolve_address_cmpl();
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
#endif ///SMP_INCLUDED == TRUE
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_init_pseudo_addr
|
||||
**
|
||||
** Description This function is used to initialize pseudo address.
|
||||
** If pseudo address is not available, use dummy address
|
||||
**
|
||||
** Returns TRUE is updated; FALSE otherwise.
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN btm_ble_init_pseudo_addr (tBTM_SEC_DEV_REC *p_dev_rec, BD_ADDR new_pseudo_addr)
|
||||
{
|
||||
#if (SMP_INCLUDED == TRUE)
|
||||
BD_ADDR dummy_bda = {0};
|
||||
|
||||
if (memcmp(p_dev_rec->ble.pseudo_addr, dummy_bda, BD_ADDR_LEN) == 0) {
|
||||
memcpy(p_dev_rec->ble.pseudo_addr, new_pseudo_addr, BD_ADDR_LEN);
|
||||
return TRUE;
|
||||
}
|
||||
#endif ///SMP_INCLUDED == TRUE
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_addr_resolvable
|
||||
**
|
||||
** Description This function checks if a RPA is resolvable by the device key.
|
||||
**
|
||||
** Returns TRUE is resolvable; FALSE otherwise.
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN btm_ble_addr_resolvable (BD_ADDR rpa, tBTM_SEC_DEV_REC *p_dev_rec)
|
||||
{
|
||||
BOOLEAN rt = FALSE;
|
||||
#if (SMP_INCLUDED == TRUE)
|
||||
if (!BTM_BLE_IS_RESOLVE_BDA(rpa)) {
|
||||
return rt;
|
||||
}
|
||||
|
||||
UINT8 rand[3];
|
||||
tSMP_ENC output;
|
||||
if ((p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) &&
|
||||
(p_dev_rec->ble.key_type & BTM_LE_KEY_PID)) {
|
||||
BTM_TRACE_DEBUG("%s try to resolve", __func__);
|
||||
/* use the 3 MSB of bd address as prand */
|
||||
rand[0] = rpa[2];
|
||||
rand[1] = rpa[1];
|
||||
rand[2] = rpa[0];
|
||||
|
||||
/* generate X = E irk(R0, R1, R2) and R is random address 3 LSO */
|
||||
SMP_Encrypt(p_dev_rec->ble.keys.irk, BT_OCTET16_LEN,
|
||||
&rand[0], 3, &output);
|
||||
|
||||
rand[0] = rpa[5];
|
||||
rand[1] = rpa[4];
|
||||
rand[2] = rpa[3];
|
||||
|
||||
if (!memcmp(output.param_buf, &rand[0], 3)) {
|
||||
btm_ble_init_pseudo_addr (p_dev_rec, rpa);
|
||||
rt = TRUE;
|
||||
}
|
||||
}
|
||||
#endif ///SMP_INCLUDED == TRUE
|
||||
return rt;
|
||||
}
|
||||
|
||||
#if (BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE)
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_match_random_bda
|
||||
**
|
||||
** Description This function match the random address to the appointed device
|
||||
** record, starting from calculating IRK. If record index exceed
|
||||
** the maximum record number, matching failed and send callback.
|
||||
**
|
||||
** Returns None.
|
||||
**
|
||||
*******************************************************************************/
|
||||
static BOOLEAN btm_ble_match_random_bda(tBTM_SEC_DEV_REC *p_dev_rec)
|
||||
{
|
||||
/* use the 3 MSB of bd address as prand */
|
||||
|
||||
tBTM_LE_RANDOM_CB *p_mgnt_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
|
||||
UINT8 rand[3];
|
||||
rand[0] = p_mgnt_cb->random_bda[2];
|
||||
rand[1] = p_mgnt_cb->random_bda[1];
|
||||
rand[2] = p_mgnt_cb->random_bda[0];
|
||||
|
||||
BTM_TRACE_EVENT("%s p_dev_rec = 0x%08x", __func__, (uint32_t)p_dev_rec);
|
||||
|
||||
{
|
||||
tSMP_ENC output;
|
||||
|
||||
BTM_TRACE_DEBUG("sec_flags = %02x device_type = %d", p_dev_rec->sec_flags,
|
||||
p_dev_rec->device_type);
|
||||
|
||||
if ((p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) &&
|
||||
(p_dev_rec->ble.key_type & BTM_LE_KEY_PID)) {
|
||||
/* generate X = E irk(R0, R1, R2) and R is random address 3 LSO */
|
||||
SMP_Encrypt(p_dev_rec->ble.keys.irk, BT_OCTET16_LEN,
|
||||
&rand[0], 3, &output);
|
||||
return btm_ble_proc_resolve_x(&output);
|
||||
} else {
|
||||
// not completed
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif ///BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_resolve_random_addr
|
||||
**
|
||||
** Description This function is called to resolve a random address.
|
||||
**
|
||||
** Returns pointer to the security record of the device whom a random
|
||||
** address is matched to.
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_resolve_random_addr(BD_ADDR random_bda, tBTM_BLE_RESOLVE_CBACK *p_cback, void *p)
|
||||
{
|
||||
#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->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 */
|
||||
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;
|
||||
}
|
||||
p_mgnt_cb->p_dev_rec = NULL;
|
||||
}
|
||||
btm_ble_resolve_address_cmpl();
|
||||
} else {
|
||||
(*p_cback)(NULL, p);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** address mapping between pseudo address and real connection address
|
||||
*******************************************************************************/
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_find_dev_by_identity_addr
|
||||
**
|
||||
** Description find the security record whose LE static address is matching
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_SEC_DEV_REC *btm_find_dev_by_identity_addr(BD_ADDR bd_addr, UINT8 addr_type)
|
||||
{
|
||||
#if BLE_PRIVACY_SPT == TRUE
|
||||
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;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_identity_addr_to_random_pseudo
|
||||
**
|
||||
** Description This function map a static BD address to a pseudo random address
|
||||
** in security database.
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN btm_identity_addr_to_random_pseudo(BD_ADDR bd_addr, UINT8 *p_addr_type, BOOLEAN refresh)
|
||||
{
|
||||
#if BLE_PRIVACY_SPT == TRUE
|
||||
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_identity_addr(bd_addr, *p_addr_type);
|
||||
|
||||
BTM_TRACE_EVENT ("%s", __func__);
|
||||
/* evt reported on static address, map static address to random pseudo */
|
||||
if (p_dev_rec != NULL) {
|
||||
/* if RPA offloading is supported, or 4.2 controller, do RPA refresh */
|
||||
if (refresh && controller_get_interface()->get_ble_resolving_list_max_size() != 0) {
|
||||
btm_ble_read_resolving_list_entry(p_dev_rec);
|
||||
}
|
||||
|
||||
/* assign the original address to be the current report address */
|
||||
if (!btm_ble_init_pseudo_addr (p_dev_rec, bd_addr)) {
|
||||
memcpy(bd_addr, p_dev_rec->ble.pseudo_addr, BD_ADDR_LEN);
|
||||
}
|
||||
|
||||
*p_addr_type = p_dev_rec->ble.ble_addr_type;
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_random_pseudo_to_identity_addr
|
||||
**
|
||||
** Description This function map a random pseudo address to a public address
|
||||
** random_pseudo is input and output parameter
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN btm_random_pseudo_to_identity_addr(BD_ADDR random_pseudo, UINT8 *p_static_addr_type)
|
||||
{
|
||||
#if BLE_PRIVACY_SPT == TRUE
|
||||
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (random_pseudo);
|
||||
|
||||
if (p_dev_rec != NULL) {
|
||||
if (p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) {
|
||||
* p_static_addr_type = p_dev_rec->ble.static_addr_type;
|
||||
memcpy(random_pseudo, p_dev_rec->ble.static_addr, BD_ADDR_LEN);
|
||||
if (controller_get_interface()->supports_ble_privacy() && p_dev_rec->ble.ble_addr_type != BLE_ADDR_PUBLIC) {
|
||||
*p_static_addr_type |= BLE_ADDR_TYPE_ID_BIT;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_refresh_peer_resolvable_private_addr
|
||||
**
|
||||
** Description This function refresh the currently used resolvable remote private address into security
|
||||
** database and set active connection address.
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_refresh_peer_resolvable_private_addr(BD_ADDR pseudo_bda, BD_ADDR rpa,
|
||||
UINT8 rra_type)
|
||||
{
|
||||
#if BLE_PRIVACY_SPT == TRUE
|
||||
UINT8 rra_dummy = FALSE;
|
||||
BD_ADDR dummy_bda = {0};
|
||||
|
||||
if (memcmp(dummy_bda, rpa, BD_ADDR_LEN) == 0) {
|
||||
rra_dummy = TRUE;
|
||||
}
|
||||
|
||||
/* update security record here, in adv event or connection complete process */
|
||||
tBTM_SEC_DEV_REC *p_sec_rec = btm_find_dev(pseudo_bda);
|
||||
if (p_sec_rec != NULL) {
|
||||
memcpy(p_sec_rec->ble.cur_rand_addr, rpa, BD_ADDR_LEN);
|
||||
|
||||
/* unknown, if dummy address, set to static */
|
||||
if (rra_type == BTM_BLE_ADDR_PSEUDO) {
|
||||
p_sec_rec->ble.active_addr_type = rra_dummy ? BTM_BLE_ADDR_STATIC : BTM_BLE_ADDR_RRA;
|
||||
} else {
|
||||
p_sec_rec->ble.active_addr_type = rra_type;
|
||||
}
|
||||
} else {
|
||||
BTM_TRACE_ERROR("No matching known device in record");
|
||||
return;
|
||||
}
|
||||
|
||||
BTM_TRACE_DEBUG("%s: active_addr_type: %d ",
|
||||
__func__, p_sec_rec->ble.active_addr_type);
|
||||
|
||||
/* connection refresh remote address */
|
||||
tACL_CONN *p_acl = btm_bda_to_acl(p_sec_rec->bd_addr, BT_TRANSPORT_LE);
|
||||
if (p_acl == NULL) {
|
||||
p_acl = btm_bda_to_acl(p_sec_rec->ble.pseudo_addr, BT_TRANSPORT_LE);
|
||||
}
|
||||
|
||||
if (p_acl != NULL) {
|
||||
if (rra_type == BTM_BLE_ADDR_PSEUDO) {
|
||||
/* use static address, resolvable_private_addr is empty */
|
||||
if (rra_dummy) {
|
||||
p_acl->active_remote_addr_type = p_sec_rec->ble.static_addr_type;
|
||||
memcpy(p_acl->active_remote_addr, p_sec_rec->ble.static_addr, BD_ADDR_LEN);
|
||||
} else {
|
||||
p_acl->active_remote_addr_type = BLE_ADDR_RANDOM;
|
||||
memcpy(p_acl->active_remote_addr, rpa, BD_ADDR_LEN);
|
||||
}
|
||||
} else {
|
||||
p_acl->active_remote_addr_type = rra_type;
|
||||
memcpy(p_acl->active_remote_addr, rpa, BD_ADDR_LEN);
|
||||
}
|
||||
|
||||
BTM_TRACE_DEBUG("p_acl->active_remote_addr_type: %d ", p_acl->active_remote_addr_type);
|
||||
BTM_TRACE_DEBUG("%s conn_addr: %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
__func__, p_acl->active_remote_addr[0], p_acl->active_remote_addr[1],
|
||||
p_acl->active_remote_addr[2], p_acl->active_remote_addr[3],
|
||||
p_acl->active_remote_addr[4], p_acl->active_remote_addr[5]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_refresh_local_resolvable_private_addr
|
||||
**
|
||||
** Description This function refresh the currently used resolvable private address for the
|
||||
** active link to the remote device
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_refresh_local_resolvable_private_addr(BD_ADDR pseudo_addr,
|
||||
BD_ADDR local_rpa)
|
||||
{
|
||||
#if BLE_PRIVACY_SPT == TRUE
|
||||
tACL_CONN *p = btm_bda_to_acl(pseudo_addr, BT_TRANSPORT_LE);
|
||||
BD_ADDR dummy_bda = {0};
|
||||
|
||||
if (p != NULL) {
|
||||
if (btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type >= BLE_ADDR_RANDOM) {
|
||||
p->conn_addr_type = BLE_ADDR_RANDOM;
|
||||
if (memcmp(local_rpa, dummy_bda, BD_ADDR_LEN)) {
|
||||
memcpy(p->conn_addr, local_rpa, BD_ADDR_LEN);
|
||||
} else {
|
||||
memcpy(p->conn_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, BD_ADDR_LEN);
|
||||
}
|
||||
} else {
|
||||
p->conn_addr_type = BLE_ADDR_PUBLIC;
|
||||
memcpy(p->conn_addr, &controller_get_interface()->get_address()->address, BD_ADDR_LEN);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,953 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2014 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
#include <string.h>
|
||||
//#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include "common/bt_target.h"
|
||||
|
||||
#include "stack/btm_ble_api.h"
|
||||
#include "stack/bt_types.h"
|
||||
//#include "bt_utils.h"
|
||||
#include "stack/btu.h"
|
||||
#include "btm_int.h"
|
||||
#include "device/controller.h"
|
||||
#include "stack/hcimsgs.h"
|
||||
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
|
||||
#if BTM_DYNAMIC_MEMORY == FALSE
|
||||
tBTM_BLE_BATCH_SCAN_CB ble_batchscan_cb;
|
||||
tBTM_BLE_ADV_TRACK_CB ble_advtrack_cb;
|
||||
#else
|
||||
tBTM_BLE_BATCH_SCAN_CB *ble_batchscan_cb_ptr;
|
||||
tBTM_BLE_ADV_TRACK_CB *ble_advtrack_cb_ptr;
|
||||
#define ble_batchscan_cb (*ble_batchscan_cb_ptr)
|
||||
#define ble_advtrack_cb (*ble_advtrack_cb_ptr)
|
||||
#endif
|
||||
|
||||
/* length of each batch scan command */
|
||||
#define BTM_BLE_BATCH_SCAN_STORAGE_CFG_LEN 4
|
||||
#define BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN 12
|
||||
#define BTM_BLE_BATCH_SCAN_ENB_DISB_LEN 2
|
||||
#define BTM_BLE_BATCH_SCAN_READ_RESULTS_LEN 2
|
||||
|
||||
#define BTM_BLE_BATCH_SCAN_CB_EVT_MASK 0xF0
|
||||
#define BTM_BLE_BATCH_SCAN_SUBCODE_MASK 0x0F
|
||||
|
||||
/*******************************************************************************
|
||||
** Local functions
|
||||
*******************************************************************************/
|
||||
void btm_ble_batchscan_vsc_cmpl_cback (tBTM_VSC_CMPL *p_params);
|
||||
void btm_ble_batchscan_cleanup(void);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_batchscan_filter_track_adv_vse_cback
|
||||
**
|
||||
** Description VSE callback for batch scan, filter, and tracking events.
|
||||
**
|
||||
** Returns None
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_batchscan_filter_track_adv_vse_cback(UINT8 len, UINT8 *p)
|
||||
{
|
||||
tBTM_BLE_TRACK_ADV_DATA adv_data;
|
||||
|
||||
UINT8 sub_event = 0;
|
||||
tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
|
||||
STREAM_TO_UINT8(sub_event, p);
|
||||
|
||||
BTM_TRACE_EVENT("btm_ble_batchscan_filter_track_adv_vse_cback called with event:%x", sub_event);
|
||||
if (HCI_VSE_SUBCODE_BLE_THRESHOLD_SUB_EVT == sub_event &&
|
||||
NULL != ble_batchscan_cb.p_thres_cback) {
|
||||
ble_batchscan_cb.p_thres_cback(ble_batchscan_cb.ref_value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (HCI_VSE_SUBCODE_BLE_TRACKING_SUB_EVT == sub_event && NULL != ble_advtrack_cb.p_track_cback) {
|
||||
if (len < 10) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&adv_data, 0 , sizeof(tBTM_BLE_TRACK_ADV_DATA));
|
||||
BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
|
||||
adv_data.client_if = (UINT8)ble_advtrack_cb.ref_value;
|
||||
if (cmn_ble_vsc_cb.version_supported > BTM_VSC_CHIP_CAPABILITY_L_VERSION) {
|
||||
STREAM_TO_UINT8(adv_data.filt_index, p);
|
||||
STREAM_TO_UINT8(adv_data.advertiser_state, p);
|
||||
STREAM_TO_UINT8(adv_data.advertiser_info_present, p);
|
||||
STREAM_TO_BDADDR(adv_data.bd_addr.address, p);
|
||||
STREAM_TO_UINT8(adv_data.addr_type, p);
|
||||
|
||||
/* Extract the adv info details */
|
||||
if (ADV_INFO_PRESENT == adv_data.advertiser_info_present) {
|
||||
STREAM_TO_UINT8(adv_data.tx_power, p);
|
||||
STREAM_TO_UINT8(adv_data.rssi_value, p);
|
||||
STREAM_TO_UINT16(adv_data.time_stamp, p);
|
||||
|
||||
STREAM_TO_UINT8(adv_data.adv_pkt_len, p);
|
||||
if (adv_data.adv_pkt_len > 0) {
|
||||
adv_data.p_adv_pkt_data = osi_malloc(adv_data.adv_pkt_len);
|
||||
memcpy(adv_data.p_adv_pkt_data, p, adv_data.adv_pkt_len);
|
||||
}
|
||||
|
||||
STREAM_TO_UINT8(adv_data.scan_rsp_len, p);
|
||||
if (adv_data.scan_rsp_len > 0) {
|
||||
adv_data.p_scan_rsp_data = osi_malloc(adv_data.scan_rsp_len);
|
||||
memcpy(adv_data.p_scan_rsp_data, p, adv_data.scan_rsp_len);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Based on L-release version */
|
||||
STREAM_TO_UINT8(adv_data.filt_index, p);
|
||||
STREAM_TO_UINT8(adv_data.addr_type, p);
|
||||
STREAM_TO_BDADDR(adv_data.bd_addr.address, p);
|
||||
STREAM_TO_UINT8(adv_data.advertiser_state, p);
|
||||
}
|
||||
|
||||
BTM_TRACE_EVENT("track_adv_vse_cback called: %d, %d, %d", adv_data.filt_index,
|
||||
adv_data.addr_type, adv_data.advertiser_state);
|
||||
ble_advtrack_cb.p_track_cback(&adv_data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_batchscan_enq_op_q
|
||||
**
|
||||
** Description enqueue a batchscan operation in q to check command complete
|
||||
** status
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_batchscan_enq_op_q(UINT8 opcode, tBTM_BLE_BATCH_SCAN_STATE cur_state,
|
||||
UINT8 cb_evt, tBTM_BLE_REF_VALUE ref_value)
|
||||
{
|
||||
ble_batchscan_cb.op_q.sub_code[ble_batchscan_cb.op_q.next_idx] = (opcode | (cb_evt << 4));
|
||||
ble_batchscan_cb.op_q.cur_state[ble_batchscan_cb.op_q.next_idx] = cur_state;
|
||||
ble_batchscan_cb.op_q.ref_value[ble_batchscan_cb.op_q.next_idx] = ref_value;
|
||||
BTM_TRACE_DEBUG("btm_ble_batchscan_enq_op_q: subcode:%d, Cur_state:%d, ref_value:%d",
|
||||
ble_batchscan_cb.op_q.sub_code[ble_batchscan_cb.op_q.next_idx],
|
||||
ble_batchscan_cb.op_q.cur_state[ble_batchscan_cb.op_q.next_idx],
|
||||
ble_batchscan_cb.op_q.ref_value[ble_batchscan_cb.op_q.next_idx]);
|
||||
ble_batchscan_cb.op_q.next_idx = (ble_batchscan_cb.op_q.next_idx + 1)
|
||||
% BTM_BLE_BATCH_SCAN_MAX;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_batchscan_enq_rep_q
|
||||
**
|
||||
** Description enqueue a batchscan report operation in q to check command complete
|
||||
** status
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS btm_ble_batchscan_enq_rep_q(UINT8 report_format, tBTM_BLE_REF_VALUE ref_value)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; i++) {
|
||||
if (report_format == ble_batchscan_cb.main_rep_q.rep_mode[i]) {
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
ble_batchscan_cb.main_rep_q.rep_mode[ble_batchscan_cb.main_rep_q.next_idx] = report_format;
|
||||
ble_batchscan_cb.main_rep_q.ref_value[ble_batchscan_cb.main_rep_q.next_idx] = ref_value;
|
||||
ble_batchscan_cb.main_rep_q.num_records[ble_batchscan_cb.main_rep_q.next_idx] = 0;
|
||||
ble_batchscan_cb.main_rep_q.data_len[ble_batchscan_cb.main_rep_q.next_idx] = 0;
|
||||
ble_batchscan_cb.main_rep_q.p_data[ble_batchscan_cb.main_rep_q.next_idx] = NULL;
|
||||
BTM_TRACE_DEBUG("btm_ble_batchscan_enq_rep_q: index:%d, rep %d, ref %d",
|
||||
ble_batchscan_cb.main_rep_q.next_idx, report_format, ref_value);
|
||||
|
||||
ble_batchscan_cb.main_rep_q.next_idx = (ble_batchscan_cb.main_rep_q.next_idx + 1)
|
||||
% BTM_BLE_BATCH_REP_MAIN_Q_SIZE;
|
||||
return BTM_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_batchscan_enq_rep_data
|
||||
**
|
||||
** Description setup the data in the main report queue
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_batchscan_enq_rep_data(UINT8 report_format, UINT8 num_records, UINT8 *p_data,
|
||||
UINT8 data_len)
|
||||
{
|
||||
int index = 0, len = 0;
|
||||
UINT8 *p_orig_data = NULL, *p_app_data = NULL;
|
||||
|
||||
for (index = 0; index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; index++) {
|
||||
if (report_format == ble_batchscan_cb.main_rep_q.rep_mode[index]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BTM_TRACE_DEBUG("btm_ble_batchscan_enq_rep_data: index:%d, rep %d, num %d len : %d",
|
||||
index, report_format, num_records, data_len);
|
||||
|
||||
if (index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE && data_len > 0 && num_records > 0) {
|
||||
len = ble_batchscan_cb.main_rep_q.data_len[index];
|
||||
p_orig_data = ble_batchscan_cb.main_rep_q.p_data[index];
|
||||
if (NULL != p_orig_data) {
|
||||
p_app_data = osi_malloc(len + data_len);
|
||||
memcpy(p_app_data, p_orig_data, len);
|
||||
memcpy(p_app_data + len, p_data, data_len);
|
||||
osi_free(p_orig_data);
|
||||
ble_batchscan_cb.main_rep_q.p_data[index] = p_app_data;
|
||||
ble_batchscan_cb.main_rep_q.num_records[index] += num_records;
|
||||
ble_batchscan_cb.main_rep_q.data_len[index] += data_len;
|
||||
} else {
|
||||
p_app_data = osi_malloc(data_len);
|
||||
memcpy(p_app_data, p_data, data_len);
|
||||
ble_batchscan_cb.main_rep_q.p_data[index] = p_app_data;
|
||||
ble_batchscan_cb.main_rep_q.num_records[index] = num_records;
|
||||
ble_batchscan_cb.main_rep_q.data_len[index] = data_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_batchscan_deq_rep_q
|
||||
**
|
||||
** Description dequeue a batchscan report in q when command complete
|
||||
** is received
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_batchscan_deq_rep_data(UINT8 report_format, tBTM_BLE_REF_VALUE *p_ref_value,
|
||||
UINT8 *p_num_records, UINT8 **p_data, UINT16 *p_data_len)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
for (index = 0; index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; index++) {
|
||||
if (report_format == ble_batchscan_cb.main_rep_q.rep_mode[index]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (BTM_BLE_BATCH_REP_MAIN_Q_SIZE == index) {
|
||||
BTM_TRACE_ERROR("btm_ble_batchscan_deq_rep_data: rep_format:%d not found", report_format);
|
||||
return;
|
||||
}
|
||||
|
||||
*p_num_records = ble_batchscan_cb.main_rep_q.num_records[index];
|
||||
*p_ref_value = ble_batchscan_cb.main_rep_q.ref_value[index];
|
||||
*p_data = ble_batchscan_cb.main_rep_q.p_data[index];
|
||||
*p_data_len = ble_batchscan_cb.main_rep_q.data_len[index];
|
||||
|
||||
ble_batchscan_cb.main_rep_q.p_data[index] = NULL;
|
||||
ble_batchscan_cb.main_rep_q.data_len[index] = 0;
|
||||
ble_batchscan_cb.main_rep_q.rep_mode[index] = 0;
|
||||
ble_batchscan_cb.main_rep_q.ref_value[index] = 0;
|
||||
ble_batchscan_cb.main_rep_q.num_records[index] = 0;
|
||||
|
||||
BTM_TRACE_DEBUG("btm_ble_batchscan_deq_rep_data: index:%d, rep %d, num %d, data_len %d",
|
||||
index, report_format, *p_num_records, *p_data_len);
|
||||
|
||||
ble_batchscan_cb.main_rep_q.pending_idx = (ble_batchscan_cb.main_rep_q.pending_idx + 1)
|
||||
% BTM_BLE_BATCH_SCAN_MAX;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_batchscan_deq_op_q
|
||||
**
|
||||
** Description dequeue a batch scan operation from q when command complete
|
||||
** is received
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_batchscan_deq_op_q(UINT8 *p_opcode, tBTM_BLE_BATCH_SCAN_STATE *cur_state,
|
||||
UINT8 *p_cb_evt, tBTM_BLE_REF_VALUE *p_ref)
|
||||
{
|
||||
*p_cb_evt = (ble_batchscan_cb.op_q.sub_code[ble_batchscan_cb.op_q.pending_idx] >> 4);
|
||||
*p_opcode = (ble_batchscan_cb.op_q.sub_code[ble_batchscan_cb.op_q.pending_idx]
|
||||
& BTM_BLE_BATCH_SCAN_SUBCODE_MASK);
|
||||
*p_ref = ble_batchscan_cb.op_q.ref_value[ble_batchscan_cb.op_q.pending_idx];
|
||||
*cur_state = (ble_batchscan_cb.op_q.cur_state[ble_batchscan_cb.op_q.pending_idx]);
|
||||
ble_batchscan_cb.op_q.pending_idx = (ble_batchscan_cb.op_q.pending_idx + 1)
|
||||
% BTM_BLE_BATCH_SCAN_MAX;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_read_batchscan_reports
|
||||
**
|
||||
** Description This function reads the reports from controller
|
||||
**
|
||||
** Parameters scan_mode - The mode for which the reports are to be read out from the controller
|
||||
** ref_value - Reference value
|
||||
**
|
||||
** Returns status
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS btm_ble_read_batchscan_reports(tBTM_BLE_BATCH_SCAN_MODE scan_mode,
|
||||
tBTM_BLE_REF_VALUE ref_value)
|
||||
{
|
||||
tBTM_STATUS status = BTM_NO_RESOURCES;
|
||||
UINT8 param[BTM_BLE_BATCH_SCAN_READ_RESULTS_LEN], *pp;
|
||||
pp = param;
|
||||
|
||||
memset(param, 0, BTM_BLE_BATCH_SCAN_READ_RESULTS_LEN);
|
||||
|
||||
UINT8_TO_STREAM (pp, BTM_BLE_BATCH_SCAN_READ_RESULTS);
|
||||
UINT8_TO_STREAM (pp, scan_mode);
|
||||
|
||||
if ((status = BTM_VendorSpecificCommand (HCI_BLE_BATCH_SCAN_OCF,
|
||||
BTM_BLE_BATCH_SCAN_READ_RESULTS_LEN, param, btm_ble_batchscan_vsc_cmpl_cback))
|
||||
!= BTM_CMD_STARTED) {
|
||||
BTM_TRACE_ERROR("btm_ble_read_batchscan_reports %d", status);
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
if (BTM_CMD_STARTED == status) {
|
||||
/* The user needs to be provided scan read reports event */
|
||||
btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_READ_RESULTS, ble_batchscan_cb.cur_state,
|
||||
BTM_BLE_BATCH_SCAN_READ_REPTS_EVT, ref_value);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_batchscan_vsc_cmpl_cback
|
||||
**
|
||||
** Description Batch scan VSC complete callback
|
||||
**
|
||||
** Parameters p_params - VSC completed callback parameters
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_batchscan_vsc_cmpl_cback (tBTM_VSC_CMPL *p_params)
|
||||
{
|
||||
UINT8 *p = p_params->p_param_buf;
|
||||
UINT16 len = p_params->param_len;
|
||||
tBTM_BLE_REF_VALUE ref_value = 0;
|
||||
|
||||
UINT8 status = 0, subcode = 0, opcode = 0;
|
||||
UINT8 report_format = 0, num_records = 0, cb_evt = 0;
|
||||
UINT16 data_len = 0;
|
||||
tBTM_BLE_BATCH_SCAN_STATE cur_state = 0;
|
||||
tBTM_STATUS btm_status = 0;
|
||||
UINT8 *p_data = NULL;
|
||||
|
||||
if (len < 2) {
|
||||
BTM_TRACE_ERROR("wrong length for btm_ble_batch_scan_vsc_cmpl_cback");
|
||||
btm_ble_batchscan_deq_op_q(&opcode, &cur_state, &cb_evt, &ref_value);
|
||||
return;
|
||||
}
|
||||
|
||||
STREAM_TO_UINT8(status, p);
|
||||
STREAM_TO_UINT8(subcode, p);
|
||||
|
||||
btm_ble_batchscan_deq_op_q(&opcode, &cur_state, &cb_evt, &ref_value);
|
||||
|
||||
BTM_TRACE_DEBUG("btm_ble_batchscan op_code = %02x state = %02x cb_evt = %02x,ref_value=%d",
|
||||
opcode, cur_state, cb_evt, ref_value);
|
||||
|
||||
if (opcode != subcode) {
|
||||
BTM_TRACE_ERROR("Got unexpected VSC cmpl, expected: %d got: %d", subcode, opcode);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (subcode) {
|
||||
case BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE: {
|
||||
if (BTM_SUCCESS == status && BTM_BLE_SCAN_ENABLE_CALLED == cur_state) {
|
||||
ble_batchscan_cb.cur_state = BTM_BLE_SCAN_ENABLED_STATE;
|
||||
} else if (BTM_BLE_SCAN_ENABLE_CALLED == cur_state) {
|
||||
BTM_TRACE_ERROR("SCAN_ENB_DISAB_CUST_FEATURE - Invalid state after enb");
|
||||
ble_batchscan_cb.cur_state = BTM_BLE_SCAN_INVALID_STATE;
|
||||
}
|
||||
|
||||
BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEAT status = %d, state: %d,evt=%d",
|
||||
status, ble_batchscan_cb.cur_state, cb_evt);
|
||||
|
||||
if (cb_evt != 0 && NULL != ble_batchscan_cb.p_setup_cback) {
|
||||
ble_batchscan_cb.p_setup_cback(cb_evt, ref_value, status);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM: {
|
||||
BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM status = %d, evt=%d",
|
||||
status, cb_evt);
|
||||
if (cb_evt != 0 && NULL != ble_batchscan_cb.p_setup_cback) {
|
||||
ble_batchscan_cb.p_setup_cback(cb_evt, ref_value, status);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case BTM_BLE_BATCH_SCAN_SET_PARAMS: {
|
||||
BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_SET_PARAMS status = %d,evt=%d", status, cb_evt);
|
||||
|
||||
if (BTM_BLE_SCAN_DISABLE_CALLED == cur_state) {
|
||||
if (BTM_SUCCESS == status) {
|
||||
ble_batchscan_cb.cur_state = BTM_BLE_SCAN_DISABLED_STATE;
|
||||
} else {
|
||||
BTM_TRACE_ERROR("BTM_BLE_BATCH_SCAN_SET_PARAMS - Invalid state after disabled");
|
||||
ble_batchscan_cb.cur_state = BTM_BLE_SCAN_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
if (cb_evt != 0 && NULL != ble_batchscan_cb.p_setup_cback) {
|
||||
ble_batchscan_cb.p_setup_cback(cb_evt, ref_value, status);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case BTM_BLE_BATCH_SCAN_READ_RESULTS: {
|
||||
if (cb_evt != 0 && NULL != ble_batchscan_cb.p_scan_rep_cback) {
|
||||
STREAM_TO_UINT8(report_format, p);
|
||||
STREAM_TO_UINT8(num_records, p);
|
||||
p = (uint8_t *)(p_params->p_param_buf + 4);
|
||||
BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_READ_RESULTS status=%d,len=%d,rec=%d",
|
||||
status, len - 4, num_records);
|
||||
|
||||
if (0 == num_records) {
|
||||
btm_ble_batchscan_deq_rep_data(report_format, &ref_value, &num_records,
|
||||
&p_data, &data_len);
|
||||
if (NULL != ble_batchscan_cb.p_scan_rep_cback) {
|
||||
ble_batchscan_cb.p_scan_rep_cback(ref_value, report_format, num_records,
|
||||
data_len, p_data, status);
|
||||
}
|
||||
} else {
|
||||
if ((len - 4) > 0) {
|
||||
btm_ble_batchscan_enq_rep_data(report_format, num_records, p, len - 4);
|
||||
/* More records could be in the buffer and needs to be pulled out */
|
||||
btm_status = btm_ble_read_batchscan_reports(report_format, ref_value);
|
||||
if (BTM_CMD_STARTED != btm_status) {
|
||||
btm_ble_batchscan_deq_rep_data(report_format, &ref_value, &num_records,
|
||||
&p_data, &data_len);
|
||||
/* Send whatever is available, in case of a command failure */
|
||||
if (NULL != ble_batchscan_cb.p_scan_rep_cback && NULL != p_data) {
|
||||
ble_batchscan_cb.p_scan_rep_cback(ref_value, report_format,
|
||||
num_records, data_len, p_data, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_set_storage_config
|
||||
**
|
||||
** Description This function writes the storage configuration in controller
|
||||
**
|
||||
** Parameters batch_scan_full_max -Max storage space (in %) allocated to full scanning
|
||||
** batch_scan_trunc_max -Max storage space (in %) allocated to truncated scanning
|
||||
** batch_scan_notify_threshold - Setup notification level based on total space
|
||||
**
|
||||
** Returns status
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS btm_ble_set_storage_config(UINT8 batch_scan_full_max, UINT8 batch_scan_trunc_max,
|
||||
UINT8 batch_scan_notify_threshold)
|
||||
{
|
||||
tBTM_STATUS status = BTM_NO_RESOURCES;
|
||||
UINT8 param[BTM_BLE_BATCH_SCAN_STORAGE_CFG_LEN], *pp;
|
||||
|
||||
pp = param;
|
||||
memset(param, 0, BTM_BLE_BATCH_SCAN_STORAGE_CFG_LEN);
|
||||
|
||||
UINT8_TO_STREAM (pp, BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM);
|
||||
UINT8_TO_STREAM (pp, batch_scan_full_max);
|
||||
UINT8_TO_STREAM (pp, batch_scan_trunc_max);
|
||||
UINT8_TO_STREAM (pp, batch_scan_notify_threshold);
|
||||
|
||||
if ((status = BTM_VendorSpecificCommand (HCI_BLE_BATCH_SCAN_OCF,
|
||||
BTM_BLE_BATCH_SCAN_STORAGE_CFG_LEN, param,
|
||||
btm_ble_batchscan_vsc_cmpl_cback)) != BTM_CMD_STARTED) {
|
||||
BTM_TRACE_ERROR("btm_ble_set_storage_config %d", status);
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_set_batchscan_param
|
||||
**
|
||||
** Description This function writes the batch scan params in controller
|
||||
**
|
||||
** Parameters scan_mode -Batch scan mode
|
||||
** scan_interval - Scan interval
|
||||
** scan_window - Scan window
|
||||
** discard_rule -Discard rules
|
||||
** addr_type - Address type
|
||||
**
|
||||
** Returns status
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS btm_ble_set_batchscan_param(tBTM_BLE_BATCH_SCAN_MODE scan_mode,
|
||||
UINT32 scan_interval, UINT32 scan_window, tBLE_ADDR_TYPE addr_type,
|
||||
tBTM_BLE_DISCARD_RULE discard_rule)
|
||||
{
|
||||
tBTM_STATUS status = BTM_NO_RESOURCES;
|
||||
UINT8 scan_param[BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN], *pp_scan;
|
||||
|
||||
pp_scan = scan_param;
|
||||
memset(scan_param, 0, BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN);
|
||||
|
||||
// Override param and decide addr_type based on own addr type
|
||||
// TODO: Remove upper layer parameter?
|
||||
addr_type = btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type;
|
||||
|
||||
UINT8_TO_STREAM (pp_scan, BTM_BLE_BATCH_SCAN_SET_PARAMS);
|
||||
UINT8_TO_STREAM (pp_scan, scan_mode);
|
||||
UINT32_TO_STREAM (pp_scan, scan_window);
|
||||
UINT32_TO_STREAM (pp_scan, scan_interval);
|
||||
UINT8_TO_STREAM (pp_scan, addr_type);
|
||||
UINT8_TO_STREAM (pp_scan, discard_rule);
|
||||
|
||||
if ((status = BTM_VendorSpecificCommand (HCI_BLE_BATCH_SCAN_OCF,
|
||||
BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN,
|
||||
scan_param, btm_ble_batchscan_vsc_cmpl_cback)) != BTM_CMD_STARTED) {
|
||||
BTM_TRACE_ERROR("btm_ble_set_batchscan_param %d", status);
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_enable_disable_batchscan
|
||||
**
|
||||
** Description This function enables the customer specific feature in controller
|
||||
**
|
||||
** Parameters enable_disable: true - enable, false - disable
|
||||
**
|
||||
** Returns status
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS btm_ble_enable_disable_batchscan(BOOLEAN should_enable)
|
||||
{
|
||||
tBTM_STATUS status = BTM_NO_RESOURCES;
|
||||
UINT8 shld_enable = 0x01;
|
||||
UINT8 enable_param[BTM_BLE_BATCH_SCAN_ENB_DISB_LEN], *pp_enable;
|
||||
|
||||
if (!should_enable) {
|
||||
shld_enable = 0x00;
|
||||
}
|
||||
|
||||
if (should_enable) {
|
||||
pp_enable = enable_param;
|
||||
memset(enable_param, 0, BTM_BLE_BATCH_SCAN_ENB_DISB_LEN);
|
||||
|
||||
UINT8_TO_STREAM (pp_enable, BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE);
|
||||
UINT8_TO_STREAM (pp_enable, shld_enable);
|
||||
|
||||
if ((status = BTM_VendorSpecificCommand(HCI_BLE_BATCH_SCAN_OCF,
|
||||
BTM_BLE_BATCH_SCAN_ENB_DISB_LEN, enable_param,
|
||||
btm_ble_batchscan_vsc_cmpl_cback)) != BTM_CMD_STARTED) {
|
||||
status = BTM_MODE_UNSUPPORTED;
|
||||
BTM_TRACE_ERROR("btm_ble_enable_disable_batchscan %d", status);
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
} else if ((status = btm_ble_set_batchscan_param(BTM_BLE_BATCH_SCAN_MODE_DISABLE,
|
||||
ble_batchscan_cb.scan_interval, ble_batchscan_cb.scan_window,
|
||||
ble_batchscan_cb.addr_type, ble_batchscan_cb.discard_rule)) != BTM_CMD_STARTED) {
|
||||
status = BTM_MODE_UNSUPPORTED;
|
||||
BTM_TRACE_ERROR("btm_ble_enable_disable_batchscan %d", status);
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
if (should_enable) {
|
||||
ble_batchscan_cb.cur_state = BTM_BLE_SCAN_ENABLE_CALLED;
|
||||
} else {
|
||||
ble_batchscan_cb.cur_state = BTM_BLE_SCAN_DISABLE_CALLED;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_BleSetStorageConfig
|
||||
**
|
||||
** Description This function is called to write storage config params.
|
||||
**
|
||||
** Parameters: batch_scan_full_max - Max storage space (in %) allocated to full style
|
||||
** batch_scan_trunc_max - Max storage space (in %) allocated to trunc style
|
||||
** batch_scan_notify_threshold - Setup notification level based on total space
|
||||
** p_setup_cback - Setup callback pointer
|
||||
** p_thres_cback - Threshold callback pointer
|
||||
** p_rep_cback - Reports callback pointer
|
||||
** ref_value - Reference value
|
||||
**
|
||||
** Returns tBTM_STATUS
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS BTM_BleSetStorageConfig(UINT8 batch_scan_full_max, UINT8 batch_scan_trunc_max,
|
||||
UINT8 batch_scan_notify_threshold,
|
||||
tBTM_BLE_SCAN_SETUP_CBACK *p_setup_cback,
|
||||
tBTM_BLE_SCAN_THRESHOLD_CBACK *p_thres_cback,
|
||||
tBTM_BLE_SCAN_REP_CBACK *p_rep_cback,
|
||||
tBTM_BLE_REF_VALUE ref_value)
|
||||
{
|
||||
tBTM_STATUS status = BTM_NO_RESOURCES;
|
||||
tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
|
||||
|
||||
BTM_TRACE_EVENT (" BTM_BleSetStorageConfig: %d, %d, %d, %d, %d",
|
||||
ble_batchscan_cb.cur_state, ref_value, batch_scan_full_max, batch_scan_trunc_max,
|
||||
batch_scan_notify_threshold);
|
||||
|
||||
if (!controller_get_interface()->supports_ble()) {
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
|
||||
|
||||
if (0 == cmn_ble_vsc_cb.tot_scan_results_strg) {
|
||||
BTM_TRACE_ERROR("Controller does not support batch scan");
|
||||
return BTM_ERR_PROCESSING;
|
||||
}
|
||||
|
||||
ble_batchscan_cb.p_setup_cback = p_setup_cback;
|
||||
ble_batchscan_cb.p_thres_cback = p_thres_cback;
|
||||
ble_batchscan_cb.p_scan_rep_cback = p_rep_cback;
|
||||
ble_batchscan_cb.ref_value = ref_value;
|
||||
|
||||
if (batch_scan_full_max > BTM_BLE_ADV_SCAN_FULL_MAX ||
|
||||
batch_scan_trunc_max > BTM_BLE_ADV_SCAN_TRUNC_MAX ||
|
||||
batch_scan_notify_threshold > BTM_BLE_ADV_SCAN_THR_MAX) {
|
||||
BTM_TRACE_ERROR("Illegal set storage config params");
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
if (BTM_BLE_SCAN_INVALID_STATE == ble_batchscan_cb.cur_state ||
|
||||
BTM_BLE_SCAN_DISABLED_STATE == ble_batchscan_cb.cur_state ||
|
||||
BTM_BLE_SCAN_DISABLE_CALLED == ble_batchscan_cb.cur_state) {
|
||||
status = btm_ble_enable_disable_batchscan(TRUE);
|
||||
if (BTM_CMD_STARTED != status) {
|
||||
return status;
|
||||
}
|
||||
|
||||
ble_batchscan_cb.cur_state = BTM_BLE_SCAN_ENABLE_CALLED;
|
||||
btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE,
|
||||
BTM_BLE_SCAN_ENABLE_CALLED, 0, ref_value);
|
||||
}
|
||||
|
||||
status = btm_ble_set_storage_config(batch_scan_full_max, batch_scan_trunc_max,
|
||||
batch_scan_notify_threshold);
|
||||
if (BTM_CMD_STARTED != status) {
|
||||
return status;
|
||||
}
|
||||
/* The user needs to be provided scan config storage event */
|
||||
btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM, ble_batchscan_cb.cur_state,
|
||||
BTM_BLE_BATCH_SCAN_CFG_STRG_EVT, ref_value);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_BleEnableBatchScan
|
||||
**
|
||||
** Description This function is called to configure and enable batch scanning
|
||||
**
|
||||
** Parameters: scan_mode -Batch scan mode
|
||||
** scan_interval - Scan interval value
|
||||
** scan_window - Scan window value
|
||||
** discard_rule - Data discard rule
|
||||
** ref_value - Reference value
|
||||
**
|
||||
** Returns tBTM_STATUS
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS BTM_BleEnableBatchScan(tBTM_BLE_BATCH_SCAN_MODE scan_mode,
|
||||
UINT32 scan_interval, UINT32 scan_window, tBLE_ADDR_TYPE addr_type,
|
||||
tBTM_BLE_DISCARD_RULE discard_rule, tBTM_BLE_REF_VALUE ref_value)
|
||||
{
|
||||
tBTM_STATUS status = BTM_NO_RESOURCES;
|
||||
tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
|
||||
BTM_TRACE_EVENT (" BTM_BleEnableBatchScan: %d, %d, %d, %d, %d, %d",
|
||||
scan_mode, scan_interval, scan_window, addr_type, discard_rule, ref_value);
|
||||
|
||||
if (!controller_get_interface()->supports_ble()) {
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
|
||||
|
||||
if (0 == cmn_ble_vsc_cb.tot_scan_results_strg) {
|
||||
BTM_TRACE_ERROR("Controller does not support batch scan");
|
||||
return BTM_ERR_PROCESSING;
|
||||
}
|
||||
|
||||
BTM_TRACE_DEBUG("BTM_BleEnableBatchScan: %d, %x, %x, %d, %d", scan_mode, scan_interval,
|
||||
scan_window, discard_rule, ble_batchscan_cb.cur_state);
|
||||
|
||||
/* Only 16 bits will be used for scan interval and scan window as per agreement with Google */
|
||||
/* So the standard LE range would suffice for scan interval and scan window */
|
||||
if ((BTM_BLE_ISVALID_PARAM(scan_interval, BTM_BLE_SCAN_INT_MIN, BTM_BLE_SCAN_INT_MAX) ||
|
||||
BTM_BLE_ISVALID_PARAM(scan_window, BTM_BLE_SCAN_WIN_MIN, BTM_BLE_SCAN_WIN_MAX))
|
||||
&& (BTM_BLE_BATCH_SCAN_MODE_PASS == scan_mode || BTM_BLE_BATCH_SCAN_MODE_ACTI == scan_mode
|
||||
|| BTM_BLE_BATCH_SCAN_MODE_PASS_ACTI == scan_mode)
|
||||
&& (BTM_BLE_DISCARD_OLD_ITEMS == discard_rule ||
|
||||
BTM_BLE_DISCARD_LOWER_RSSI_ITEMS == discard_rule)) {
|
||||
if (BTM_BLE_SCAN_INVALID_STATE == ble_batchscan_cb.cur_state ||
|
||||
BTM_BLE_SCAN_DISABLED_STATE == ble_batchscan_cb.cur_state ||
|
||||
BTM_BLE_SCAN_DISABLE_CALLED == ble_batchscan_cb.cur_state) {
|
||||
status = btm_ble_enable_disable_batchscan(TRUE);
|
||||
if (BTM_CMD_STARTED != status) {
|
||||
return status;
|
||||
}
|
||||
btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE,
|
||||
BTM_BLE_SCAN_ENABLE_CALLED, 0, ref_value);
|
||||
}
|
||||
|
||||
ble_batchscan_cb.scan_mode = scan_mode;
|
||||
ble_batchscan_cb.scan_interval = scan_interval;
|
||||
ble_batchscan_cb.scan_window = scan_window;
|
||||
ble_batchscan_cb.addr_type = addr_type;
|
||||
ble_batchscan_cb.discard_rule = discard_rule;
|
||||
/* This command starts batch scanning, if enabled */
|
||||
status = btm_ble_set_batchscan_param(scan_mode, scan_interval, scan_window, addr_type,
|
||||
discard_rule);
|
||||
if (BTM_CMD_STARTED != status) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/* The user needs to be provided scan enable event */
|
||||
btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_SET_PARAMS, ble_batchscan_cb.cur_state,
|
||||
BTM_BLE_BATCH_SCAN_ENABLE_EVT, ref_value);
|
||||
} else {
|
||||
BTM_TRACE_ERROR("Illegal enable scan params");
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_BleDisableBatchScan
|
||||
**
|
||||
** Description This function is called to disable batch scanning
|
||||
**
|
||||
** Parameters: ref_value - Reference value
|
||||
**
|
||||
** Returns tBTM_STATUS
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS BTM_BleDisableBatchScan(tBTM_BLE_REF_VALUE ref_value)
|
||||
{
|
||||
tBTM_STATUS status = BTM_NO_RESOURCES;
|
||||
tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
|
||||
BTM_TRACE_EVENT (" BTM_BleDisableBatchScan");
|
||||
|
||||
if (!controller_get_interface()->supports_ble()) {
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
|
||||
|
||||
if (0 == cmn_ble_vsc_cb.tot_scan_results_strg) {
|
||||
BTM_TRACE_ERROR("Controller does not support batch scan");
|
||||
return BTM_ERR_PROCESSING;
|
||||
}
|
||||
|
||||
status = btm_ble_enable_disable_batchscan(FALSE);
|
||||
if (BTM_CMD_STARTED == status) {
|
||||
/* The user needs to be provided scan disable event */
|
||||
btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_SET_PARAMS,
|
||||
BTM_BLE_SCAN_DISABLE_CALLED, BTM_BLE_BATCH_SCAN_DISABLE_EVT,
|
||||
ref_value);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_BleReadScanReports
|
||||
**
|
||||
** Description This function is called to start reading batch scan reports
|
||||
**
|
||||
** Parameters: scan_mode - Batch scan mode
|
||||
** ref_value - Reference value
|
||||
**
|
||||
** Returns tBTM_STATUS
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS BTM_BleReadScanReports(tBTM_BLE_BATCH_SCAN_MODE scan_mode,
|
||||
tBTM_BLE_REF_VALUE ref_value)
|
||||
{
|
||||
tBTM_STATUS status = BTM_NO_RESOURCES;
|
||||
tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
|
||||
UINT8 read_scan_mode = 0;
|
||||
UINT8 *p_data = NULL, num_records = 0;
|
||||
UINT16 data_len = 0;
|
||||
|
||||
BTM_TRACE_EVENT (" BTM_BleReadScanReports; %d, %d", scan_mode, ref_value);
|
||||
|
||||
if (!controller_get_interface()->supports_ble()) {
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
|
||||
|
||||
if (0 == cmn_ble_vsc_cb.tot_scan_results_strg) {
|
||||
BTM_TRACE_ERROR("Controller does not support batch scan");
|
||||
return BTM_ERR_PROCESSING;
|
||||
}
|
||||
|
||||
/* Check if the requested scan mode has already been setup by the user */
|
||||
read_scan_mode = ble_batchscan_cb.scan_mode & BTM_BLE_BATCH_SCAN_MODE_ACTI;
|
||||
if (0 == read_scan_mode) {
|
||||
read_scan_mode = ble_batchscan_cb.scan_mode & BTM_BLE_BATCH_SCAN_MODE_PASS;
|
||||
}
|
||||
|
||||
/* Check only for modes, as scan reports can be called after disabling batch scan */
|
||||
if (read_scan_mode > 0 && (BTM_BLE_BATCH_SCAN_MODE_PASS == scan_mode ||
|
||||
BTM_BLE_BATCH_SCAN_MODE_ACTI == scan_mode)) {
|
||||
status = btm_ble_batchscan_enq_rep_q(scan_mode, ref_value);
|
||||
if (BTM_SUCCESS == status) {
|
||||
status = btm_ble_read_batchscan_reports(scan_mode, ref_value);
|
||||
if (BTM_CMD_STARTED != status) {
|
||||
btm_ble_batchscan_deq_rep_data(scan_mode, &ref_value,
|
||||
&num_records, &p_data, &data_len);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
BTM_TRACE_ERROR("Illegal read scan params: %d, %d, %d", read_scan_mode, scan_mode,
|
||||
ble_batchscan_cb.cur_state);
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_BleTrackAdvertiser
|
||||
**
|
||||
** Description This function is called to setup the callback for tracking advertisers
|
||||
**
|
||||
** Parameters: p_track_cback - Tracking callback pointer
|
||||
** ref_value - Reference value
|
||||
**
|
||||
** Returns tBTM_STATUS
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS BTM_BleTrackAdvertiser(tBTM_BLE_TRACK_ADV_CBACK *p_track_cback,
|
||||
tBTM_BLE_REF_VALUE ref_value)
|
||||
{
|
||||
tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
|
||||
BTM_TRACE_EVENT (" BTM_BleTrackAdvertiser");
|
||||
if (!controller_get_interface()->supports_ble()) {
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
|
||||
|
||||
if (0 == cmn_ble_vsc_cb.tot_scan_results_strg) {
|
||||
BTM_TRACE_ERROR("Controller does not support scan storage");
|
||||
return BTM_ERR_PROCESSING;
|
||||
}
|
||||
|
||||
ble_advtrack_cb.p_track_cback = p_track_cback;
|
||||
ble_advtrack_cb.ref_value = ref_value;
|
||||
return BTM_CMD_STARTED;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_batchscan_init
|
||||
**
|
||||
** Description This function initialize the batch scan control block.
|
||||
**
|
||||
** Parameters None
|
||||
**
|
||||
** Returns status
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_batchscan_init(void)
|
||||
{
|
||||
#if BTM_DYNAMIC_MEMORY == TRUE
|
||||
ble_batchscan_cb_ptr = (tBTM_BLE_BATCH_SCAN_CB *)osi_malloc(sizeof(tBTM_BLE_BATCH_SCAN_CB));
|
||||
ble_advtrack_cb_ptr = (tBTM_BLE_ADV_TRACK_CB *)osi_malloc(sizeof(tBTM_BLE_ADV_TRACK_CB));
|
||||
if (ble_batchscan_cb_ptr == NULL || ble_advtrack_cb_ptr == NULL) {
|
||||
BTM_TRACE_ERROR("%s malloc failed", __func__);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
BTM_TRACE_EVENT (" btm_ble_batchscan_init");
|
||||
memset(&ble_batchscan_cb, 0, sizeof(tBTM_BLE_BATCH_SCAN_CB));
|
||||
memset(&ble_advtrack_cb, 0, sizeof(tBTM_BLE_ADV_TRACK_CB));
|
||||
BTM_RegisterForVSEvents(btm_ble_batchscan_filter_track_adv_vse_cback, TRUE);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_batchscan_cleanup
|
||||
**
|
||||
** Description This function cleans the batch scan control block.
|
||||
**
|
||||
** Parameters None
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_batchscan_cleanup(void)
|
||||
{
|
||||
int index = 0;
|
||||
BTM_TRACE_EVENT (" btm_ble_batchscan_cleanup");
|
||||
|
||||
for (index = 0; index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; index++) {
|
||||
if (NULL != ble_batchscan_cb.main_rep_q.p_data[index]) {
|
||||
osi_free(ble_batchscan_cb.main_rep_q.p_data[index]);
|
||||
ble_batchscan_cb.main_rep_q.p_data[index] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&ble_batchscan_cb, 0, sizeof(tBTM_BLE_BATCH_SCAN_CB));
|
||||
memset(&ble_advtrack_cb, 0, sizeof(tBTM_BLE_ADV_TRACK_CB));
|
||||
|
||||
#if BTM_DYNAMIC_MEMORY == TRUE
|
||||
osi_free(ble_batchscan_cb_ptr);
|
||||
osi_free(ble_advtrack_cb_ptr);
|
||||
ble_batchscan_cb_ptr = NULL;
|
||||
ble_advtrack_cb_ptr = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,836 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2012 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file contains functions for BLE whitelist operation.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "common/bt_trace.h"
|
||||
#include "device/controller.h"
|
||||
#include "osi/allocator.h"
|
||||
#include "osi/hash_map.h"
|
||||
#include "stack/bt_types.h"
|
||||
#include "stack/btu.h"
|
||||
#include "btm_int.h"
|
||||
#include "l2c_int.h"
|
||||
#include "stack/hcimsgs.h"
|
||||
//#include "bt_utils.h"
|
||||
|
||||
#ifndef BTM_BLE_SCAN_PARAM_TOUT
|
||||
#define BTM_BLE_SCAN_PARAM_TOUT 50 /* 50 seconds */
|
||||
#endif
|
||||
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
|
||||
static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state);
|
||||
static void btm_wl_update_to_controller(void);
|
||||
|
||||
// Unfortunately (for now?) we have to maintain a copy of the device whitelist
|
||||
// on the host to determine if a device is pending to be connected or not. This
|
||||
// controls whether the host should keep trying to scan for whitelisted
|
||||
// peripherals or not.
|
||||
// TODO: Move all of this to controller/le/background_list or similar?
|
||||
static const size_t background_connection_buckets = 42;
|
||||
static hash_map_t *background_connections = NULL;
|
||||
|
||||
typedef struct background_connection_t {
|
||||
bt_bdaddr_t address;
|
||||
} background_connection_t;
|
||||
|
||||
static bool bdaddr_equality_fn(const void *x, const void *y)
|
||||
{
|
||||
return bdaddr_equals((bt_bdaddr_t *)x, (bt_bdaddr_t *)y);
|
||||
}
|
||||
|
||||
static void background_connections_lazy_init(void)
|
||||
{
|
||||
if (!background_connections) {
|
||||
background_connections = hash_map_new(background_connection_buckets,
|
||||
hash_function_bdaddr, NULL, osi_free_func, bdaddr_equality_fn);
|
||||
assert(background_connections);
|
||||
}
|
||||
}
|
||||
|
||||
static BOOLEAN background_connection_add(bt_bdaddr_t *address)
|
||||
{
|
||||
assert(address);
|
||||
background_connections_lazy_init();
|
||||
background_connection_t *connection = hash_map_get(background_connections, address);
|
||||
if (!connection) {
|
||||
connection = osi_calloc(sizeof(background_connection_t));
|
||||
connection->address = *address;
|
||||
hash_map_set(background_connections, &(connection->address), connection);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOLEAN background_connection_remove(bt_bdaddr_t *address)
|
||||
{
|
||||
if (address && background_connections) {
|
||||
return hash_map_erase(background_connections, address);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void background_connections_clear(void)
|
||||
{
|
||||
if (background_connections) {
|
||||
hash_map_clear(background_connections);
|
||||
}
|
||||
}
|
||||
|
||||
static bool background_connections_pending_cb(hash_map_entry_t *hash_entry, void *context)
|
||||
{
|
||||
bool *pending_connections = context;
|
||||
background_connection_t *connection = hash_entry->data;
|
||||
const bool connected = BTM_IsAclConnectionUp(connection->address.address, BT_TRANSPORT_LE);
|
||||
if (!connected) {
|
||||
*pending_connections = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool background_connections_pending(void)
|
||||
{
|
||||
bool pending_connections = false;
|
||||
if (background_connections) {
|
||||
hash_map_foreach(background_connections, background_connections_pending_cb, &pending_connections);
|
||||
}
|
||||
return pending_connections;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_update_scanner_filter_policy
|
||||
**
|
||||
** Description This function updates the filter policy of scanner
|
||||
*******************************************************************************/
|
||||
void btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy)
|
||||
{
|
||||
tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var;
|
||||
|
||||
UINT32 scan_interval = !p_inq->scan_interval ? BTM_BLE_GAP_DISC_SCAN_INT : p_inq->scan_interval;
|
||||
UINT32 scan_window = !p_inq->scan_window ? BTM_BLE_GAP_DISC_SCAN_WIN : p_inq->scan_window;
|
||||
|
||||
BTM_TRACE_EVENT ("%s\n", __func__);
|
||||
|
||||
p_inq->sfp = scan_policy;
|
||||
p_inq->scan_type = p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE ? BTM_BLE_SCAN_MODE_ACTI : p_inq->scan_type;
|
||||
|
||||
if (btm_cb.cmn_ble_vsc_cb.extended_scan_support == 0) {
|
||||
btsnd_hcic_ble_set_scan_params(p_inq->scan_type, (UINT16)scan_interval,
|
||||
(UINT16)scan_window,
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
|
||||
scan_policy);
|
||||
} else {
|
||||
btm_ble_send_extended_scan_params(p_inq->scan_type, scan_interval, scan_window,
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
|
||||
scan_policy);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_add_dev_to_controller
|
||||
**
|
||||
** Description This function load the device into controller white list
|
||||
*******************************************************************************/
|
||||
BOOLEAN btm_add_dev_to_controller (BOOLEAN to_add, BD_ADDR bd_addr, tBLE_ADDR_TYPE wl_addr_type)
|
||||
{
|
||||
/*
|
||||
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
|
||||
tBLE_ADDR_TYPE addr_type = BLE_ADDR_PUBLIC;
|
||||
BOOLEAN started = FALSE;
|
||||
BD_ADDR dummy_bda = {0};
|
||||
tBT_DEVICE_TYPE dev_type;
|
||||
|
||||
if (p_dev_rec != NULL &&
|
||||
p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) {
|
||||
if (to_add) {
|
||||
if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_PUBLIC || !BTM_BLE_IS_RESOLVE_BDA(bd_addr)) {
|
||||
started = btsnd_hcic_ble_add_white_list (p_dev_rec->ble.ble_addr_type, bd_addr);
|
||||
p_dev_rec->ble.in_controller_list |= BTM_WHITE_LIST_BIT;
|
||||
} else if (memcmp(p_dev_rec->ble.static_addr, bd_addr, BD_ADDR_LEN) != 0 &&
|
||||
memcmp(p_dev_rec->ble.static_addr, dummy_bda, BD_ADDR_LEN) != 0) {
|
||||
started = btsnd_hcic_ble_add_white_list (p_dev_rec->ble.static_addr_type,
|
||||
p_dev_rec->ble.static_addr);
|
||||
p_dev_rec->ble.in_controller_list |= BTM_WHITE_LIST_BIT;
|
||||
}
|
||||
} else {
|
||||
if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_PUBLIC || !BTM_BLE_IS_RESOLVE_BDA(bd_addr)) {
|
||||
started = btsnd_hcic_ble_remove_from_white_list (p_dev_rec->ble.ble_addr_type, bd_addr);
|
||||
}
|
||||
if (memcmp(p_dev_rec->ble.static_addr, dummy_bda, BD_ADDR_LEN) != 0 &&
|
||||
memcmp(p_dev_rec->ble.static_addr, bd_addr, BD_ADDR_LEN) != 0) {
|
||||
started = btsnd_hcic_ble_remove_from_white_list (p_dev_rec->ble.static_addr_type, p_dev_rec->ble.static_addr);
|
||||
}
|
||||
p_dev_rec->ble.in_controller_list &= ~BTM_WHITE_LIST_BIT;
|
||||
}
|
||||
} // if not a known device, shall we add it?
|
||||
else {
|
||||
BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type);
|
||||
|
||||
if (to_add) {
|
||||
started = btsnd_hcic_ble_add_white_list (addr_type, bd_addr);
|
||||
}else{
|
||||
started = btsnd_hcic_ble_remove_from_white_list (addr_type, bd_addr);
|
||||
}
|
||||
}
|
||||
|
||||
return started;
|
||||
*/
|
||||
|
||||
/* Controller do not support resolvable address now, only support public address and static random address */
|
||||
BOOLEAN started = FALSE;
|
||||
if(wl_addr_type > BLE_ADDR_RANDOM) {
|
||||
BTM_TRACE_ERROR("wl_addr_type is error\n");
|
||||
return started;
|
||||
}
|
||||
|
||||
if (to_add) {
|
||||
started = btsnd_hcic_ble_add_white_list (wl_addr_type, bd_addr);
|
||||
}else{
|
||||
started = btsnd_hcic_ble_remove_from_white_list (wl_addr_type, bd_addr);
|
||||
}
|
||||
|
||||
return started;
|
||||
|
||||
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_execute_wl_dev_operation
|
||||
**
|
||||
** Description execute the pending whitelist device operation(loading or removing)
|
||||
*******************************************************************************/
|
||||
BOOLEAN btm_execute_wl_dev_operation(void)
|
||||
{
|
||||
tBTM_BLE_WL_OP *p_dev_op = btm_cb.ble_ctr_cb.wl_op_q;
|
||||
UINT8 i = 0;
|
||||
BOOLEAN rt = TRUE;
|
||||
|
||||
for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM && rt; i ++, p_dev_op ++) {
|
||||
if (p_dev_op->in_use) {
|
||||
rt = btm_add_dev_to_controller(p_dev_op->to_add, p_dev_op->bd_addr, p_dev_op->addr_type);
|
||||
memset(p_dev_op, 0, sizeof(tBTM_BLE_WL_OP));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_enq_wl_dev_operation
|
||||
**
|
||||
** Description enqueue the pending whitelist device operation(loading or removing).
|
||||
*******************************************************************************/
|
||||
void btm_enq_wl_dev_operation(BOOLEAN to_add, BD_ADDR bd_addr, tBLE_ADDR_TYPE addr_type)
|
||||
{
|
||||
tBTM_BLE_WL_OP *p_dev_op = btm_cb.ble_ctr_cb.wl_op_q;
|
||||
UINT8 i = 0;
|
||||
|
||||
for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM; i ++, p_dev_op ++) {
|
||||
if (p_dev_op->in_use && p_dev_op->addr_type == addr_type && !memcmp(p_dev_op->bd_addr, bd_addr, BD_ADDR_LEN)) {
|
||||
p_dev_op->to_add = to_add;
|
||||
return;
|
||||
} else if (!p_dev_op->in_use) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i != BTM_BLE_MAX_BG_CONN_DEV_NUM) {
|
||||
p_dev_op->in_use = TRUE;
|
||||
p_dev_op->to_add = to_add;
|
||||
p_dev_op->addr_type = addr_type;
|
||||
memcpy(p_dev_op->bd_addr, bd_addr, BD_ADDR_LEN);
|
||||
} else {
|
||||
BTM_TRACE_ERROR("max pending WL operation reached, discard");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_update_dev_to_white_list
|
||||
**
|
||||
** Description This function adds or removes a device into/from
|
||||
** the white list.
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr, tBLE_ADDR_TYPE addr_type, tBTM_UPDATE_WHITELIST_CBACK *update_wl_cb)
|
||||
{
|
||||
if(addr_type > BLE_ADDR_RANDOM) {
|
||||
BTM_TRACE_ERROR("%s address type is error, unable to add device", __func__);
|
||||
if (update_wl_cb){
|
||||
update_wl_cb(HCI_ERR_ILLEGAL_PARAMETER_FMT,to_add);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BD_ADDR invalid_rand_addr_a, invalid_rand_addr_b;
|
||||
memset(invalid_rand_addr_a, 0xff, sizeof(BD_ADDR));
|
||||
memset(invalid_rand_addr_b, 0x00, sizeof(BD_ADDR));
|
||||
|
||||
// look for public address information
|
||||
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(bd_addr);
|
||||
// p_dev_rec is created at bluetooth initialization, p_dev_rec->ble.static_addr maybe be all 0 before pairing
|
||||
if(p_dev_rec && memcmp(invalid_rand_addr_b, p_dev_rec->ble.static_addr, BD_ADDR_LEN) != 0) {
|
||||
memcpy(bd_addr, p_dev_rec->ble.static_addr, BD_ADDR_LEN);
|
||||
addr_type = p_dev_rec->ble.static_addr_type;
|
||||
}
|
||||
|
||||
// The device to be added to white list must be public address or random address
|
||||
if(addr_type == BLE_ADDR_RANDOM) {
|
||||
/*
|
||||
A static address is a 48-bit randomly generated address and shall meet the following requirements:
|
||||
• The two most significant bits of the address shall be equal to 1
|
||||
• All bits of the random part of the address shall not be equal to 1
|
||||
• All bits of the random part of the address shall not be equal to 0
|
||||
*/
|
||||
invalid_rand_addr_b[0] = invalid_rand_addr_b[0] | BT_STATIC_RAND_ADDR_MASK;
|
||||
if(memcmp(invalid_rand_addr_a, bd_addr, BD_ADDR_LEN) != 0
|
||||
&& memcmp(invalid_rand_addr_b, bd_addr, BD_ADDR_LEN) != 0){
|
||||
// do nothing
|
||||
} else {
|
||||
BTC_TRACE_ERROR(" controller not support resolvable address");
|
||||
if (update_wl_cb){
|
||||
update_wl_cb(HCI_ERR_ILLEGAL_PARAMETER_FMT,to_add);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
|
||||
|
||||
if (to_add && p_cb->white_list_avail_size == 0) {
|
||||
BTM_TRACE_ERROR("%s Whitelist full, unable to add device", __func__);
|
||||
if (update_wl_cb){
|
||||
update_wl_cb(HCI_ERR_MEMORY_FULL,to_add);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (to_add) {
|
||||
/* added the bd_addr to the connection hash map queue */
|
||||
if(!background_connection_add((bt_bdaddr_t *)bd_addr)) {
|
||||
/* if the bd_addr already exist in whitelist, just callback return TRUE */
|
||||
if (update_wl_cb){
|
||||
update_wl_cb(HCI_SUCCESS,to_add);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
} else {
|
||||
/* remove the bd_addr to the connection hash map queue */
|
||||
if(!background_connection_remove((bt_bdaddr_t *)bd_addr)){
|
||||
/* if the bd_addr don't exist in whitelist, just callback return TRUE */
|
||||
if (update_wl_cb){
|
||||
update_wl_cb(HCI_SUCCESS,to_add);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (update_wl_cb){
|
||||
//save add whitelist complete callback
|
||||
p_cb->update_wl_cb = update_wl_cb;
|
||||
}
|
||||
/* stop the auto connect */
|
||||
btm_suspend_wl_activity(p_cb->wl_state);
|
||||
/* save the bd_addr to the btm_cb env */
|
||||
btm_enq_wl_dev_operation(to_add, bd_addr, addr_type);
|
||||
/* save the ba_addr to the controller white list */
|
||||
btm_wl_update_to_controller();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_clear_white_list
|
||||
**
|
||||
** Description This function clears the white list.
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_clear_white_list (tBTM_UPDATE_WHITELIST_CBACK *update_wl_cb)
|
||||
{
|
||||
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
|
||||
|
||||
BTM_TRACE_EVENT ("btm_ble_clear_white_list");
|
||||
btsnd_hcic_ble_clear_white_list();
|
||||
background_connections_clear();
|
||||
|
||||
if (update_wl_cb) {
|
||||
p_cb->update_wl_cb = update_wl_cb;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_clear_white_list_complete
|
||||
**
|
||||
** Description Indicates white list cleared.
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_clear_white_list_complete(UINT8 *p_data, UINT16 evt_len)
|
||||
{
|
||||
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
|
||||
UINT8 status;
|
||||
UNUSED(evt_len);
|
||||
|
||||
BTM_TRACE_EVENT ("btm_ble_clear_white_list_complete");
|
||||
STREAM_TO_UINT8 (status, p_data);
|
||||
|
||||
if (status == HCI_SUCCESS) {
|
||||
p_cb->white_list_avail_size = controller_get_interface()->get_ble_white_list_size();
|
||||
} else {
|
||||
BTM_TRACE_ERROR ("%s failed, status 0x%x\n", __func__, status);
|
||||
}
|
||||
|
||||
if (p_cb->update_wl_cb) {
|
||||
(*p_cb->update_wl_cb)(status, BTM_WHITELIST_CLEAR);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_white_list_init
|
||||
**
|
||||
** Description Initialize white list size
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_white_list_init(UINT8 white_list_size)
|
||||
{
|
||||
BTM_TRACE_DEBUG("%s white_list_size = %d", __func__, white_list_size);
|
||||
btm_cb.ble_ctr_cb.white_list_avail_size = white_list_size;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_add_2_white_list_complete
|
||||
**
|
||||
** Description White list element added
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_add_2_white_list_complete(UINT8 status)
|
||||
{
|
||||
BTM_TRACE_EVENT("%s status=%d", __func__, status);
|
||||
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
|
||||
if (status == HCI_SUCCESS) {
|
||||
--btm_cb.ble_ctr_cb.white_list_avail_size;
|
||||
}
|
||||
// add whitelist complete callback
|
||||
if (p_cb->update_wl_cb)
|
||||
{
|
||||
(*p_cb->update_wl_cb)(status, BTM_WHITELIST_ADD);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_remove_from_white_list_complete
|
||||
**
|
||||
** Description White list element removal complete
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_remove_from_white_list_complete(UINT8 *p, UINT16 evt_len)
|
||||
{
|
||||
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
|
||||
UNUSED(evt_len);
|
||||
BTM_TRACE_EVENT ("%s status=%d", __func__, *p);
|
||||
if (*p == HCI_SUCCESS) {
|
||||
++btm_cb.ble_ctr_cb.white_list_avail_size;
|
||||
}
|
||||
if (p_cb->update_wl_cb)
|
||||
{
|
||||
(*p_cb->update_wl_cb)(*p, BTM_WHITELIST_REMOVE);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_start_auto_conn
|
||||
**
|
||||
** Description This function is to start/stop auto connection procedure.
|
||||
**
|
||||
** Parameters start: TRUE to start; FALSE to stop.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN btm_ble_start_auto_conn(BOOLEAN start)
|
||||
{
|
||||
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
|
||||
BD_ADDR dummy_bda = {0};
|
||||
BOOLEAN exec = TRUE;
|
||||
UINT16 scan_int;
|
||||
UINT16 scan_win;
|
||||
UINT8 own_addr_type = p_cb->addr_mgnt_cb.own_addr_type;
|
||||
UINT8 peer_addr_type = BLE_ADDR_PUBLIC;
|
||||
|
||||
if (start) {
|
||||
if (p_cb->conn_state == BLE_CONN_IDLE && background_connections_pending()
|
||||
&& btm_ble_topology_check(BTM_BLE_STATE_INIT)) {
|
||||
p_cb->wl_state |= BTM_BLE_WL_INIT;
|
||||
|
||||
btm_execute_wl_dev_operation();
|
||||
|
||||
#if BLE_PRIVACY_SPT == TRUE
|
||||
btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_INIT);
|
||||
#endif
|
||||
scan_int = (p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF) ?
|
||||
BTM_BLE_SCAN_SLOW_INT_1 : p_cb->scan_int;
|
||||
scan_win = (p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF) ?
|
||||
BTM_BLE_SCAN_SLOW_WIN_1 : p_cb->scan_win;
|
||||
|
||||
#if BLE_PRIVACY_SPT == TRUE
|
||||
if (btm_cb.ble_ctr_cb.rl_state != BTM_BLE_RL_IDLE
|
||||
&& controller_get_interface()->supports_ble_privacy()) {
|
||||
own_addr_type |= BLE_ADDR_TYPE_ID_BIT;
|
||||
peer_addr_type |= BLE_ADDR_TYPE_ID_BIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!btsnd_hcic_ble_create_ll_conn (scan_int, /* UINT16 scan_int */
|
||||
scan_win, /* UINT16 scan_win */
|
||||
0x01, /* UINT8 white_list */
|
||||
peer_addr_type, /* UINT8 addr_type_peer */
|
||||
dummy_bda, /* BD_ADDR bda_peer */
|
||||
own_addr_type, /* UINT8 addr_type_own */
|
||||
BTM_BLE_CONN_INT_MIN_DEF, /* UINT16 conn_int_min */
|
||||
BTM_BLE_CONN_INT_MAX_DEF, /* UINT16 conn_int_max */
|
||||
BTM_BLE_CONN_SLAVE_LATENCY_DEF, /* UINT16 conn_latency */
|
||||
BTM_BLE_CONN_TIMEOUT_DEF, /* UINT16 conn_timeout */
|
||||
0, /* UINT16 min_len */
|
||||
0)) { /* UINT16 max_len */
|
||||
/* start auto connection failed */
|
||||
exec = FALSE;
|
||||
p_cb->wl_state &= ~BTM_BLE_WL_INIT;
|
||||
} else {
|
||||
btm_ble_set_conn_st (BLE_BG_CONN);
|
||||
}
|
||||
} else {
|
||||
exec = FALSE;
|
||||
}
|
||||
} else {
|
||||
if (p_cb->conn_state == BLE_BG_CONN) {
|
||||
btsnd_hcic_ble_create_conn_cancel();
|
||||
btm_ble_set_conn_st (BLE_CONN_CANCEL);
|
||||
p_cb->wl_state &= ~BTM_BLE_WL_INIT;
|
||||
} else {
|
||||
BTM_TRACE_DEBUG("conn_st = %d, not in auto conn state, cannot stop", p_cb->conn_state);
|
||||
exec = FALSE;
|
||||
}
|
||||
}
|
||||
return exec;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_start_select_conn
|
||||
**
|
||||
** Description This function is to start/stop selective connection procedure.
|
||||
**
|
||||
** Parameters start: TRUE to start; FALSE to stop.
|
||||
** p_select_cback: callback function to return application
|
||||
** selection.
|
||||
**
|
||||
** Returns BOOLEAN: selective connection procedure is started.
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN btm_ble_start_select_conn(BOOLEAN start, tBTM_BLE_SEL_CBACK *p_select_cback)
|
||||
{
|
||||
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
|
||||
UINT32 scan_int = p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int;
|
||||
UINT32 scan_win = p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win;
|
||||
|
||||
BTM_TRACE_EVENT ("%s", __func__);
|
||||
|
||||
if (start) {
|
||||
if (!BTM_BLE_IS_SCAN_ACTIVE(p_cb->scan_activity)) {
|
||||
if (p_select_cback != NULL) {
|
||||
btm_cb.ble_ctr_cb.p_select_cback = p_select_cback;
|
||||
}
|
||||
|
||||
btm_execute_wl_dev_operation();
|
||||
|
||||
btm_update_scanner_filter_policy(SP_ADV_WL);
|
||||
btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_PASS;
|
||||
|
||||
/* Process advertising packets only from devices in the white list */
|
||||
if (btm_cb.cmn_ble_vsc_cb.extended_scan_support == 0) {
|
||||
/* use passive scan by default */
|
||||
if (!btsnd_hcic_ble_set_scan_params(BTM_BLE_SCAN_MODE_PASS,
|
||||
scan_int,
|
||||
scan_win,
|
||||
p_cb->addr_mgnt_cb.own_addr_type,
|
||||
SP_ADV_WL)) {
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
if (!btm_ble_send_extended_scan_params(BTM_BLE_SCAN_MODE_PASS,
|
||||
scan_int,
|
||||
scan_win,
|
||||
p_cb->addr_mgnt_cb.own_addr_type,
|
||||
SP_ADV_WL)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!btm_ble_topology_check(BTM_BLE_STATE_PASSIVE_SCAN)) {
|
||||
BTM_TRACE_ERROR("peripheral device cannot initiate passive scan for a selective connection");
|
||||
return FALSE;
|
||||
} else if (background_connections_pending()) {
|
||||
#if BLE_PRIVACY_SPT == TRUE
|
||||
btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_SCAN);
|
||||
#endif
|
||||
if (!btsnd_hcic_ble_set_scan_enable(TRUE, TRUE)) { /* duplicate filtering enabled */
|
||||
return FALSE;
|
||||
}
|
||||
/* mark up inquiry status flag */
|
||||
p_cb->scan_activity |= BTM_LE_SELECT_CONN_ACTIVE;
|
||||
p_cb->wl_state |= BTM_BLE_WL_SCAN;
|
||||
}
|
||||
} else {
|
||||
BTM_TRACE_ERROR("scan active, can not start selective connection procedure");
|
||||
return FALSE;
|
||||
}
|
||||
} else { /* disable selective connection mode */
|
||||
p_cb->scan_activity &= ~BTM_LE_SELECT_CONN_ACTIVE;
|
||||
p_cb->p_select_cback = NULL;
|
||||
p_cb->wl_state &= ~BTM_BLE_WL_SCAN;
|
||||
|
||||
/* stop scanning */
|
||||
if (!BTM_BLE_IS_SCAN_ACTIVE(p_cb->scan_activity)) {
|
||||
btm_ble_stop_scan(); /* duplicate filtering enabled */
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_initiate_select_conn
|
||||
**
|
||||
** Description This function is to start/stop selective connection procedure.
|
||||
**
|
||||
** Parameters start: TRUE to start; FALSE to stop.
|
||||
** p_select_cback: callback function to return application
|
||||
** selection.
|
||||
**
|
||||
** Returns BOOLEAN: selective connection procedure is started.
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_initiate_select_conn(BD_ADDR bda)
|
||||
{
|
||||
BTM_TRACE_EVENT ("btm_ble_initiate_select_conn");
|
||||
|
||||
/* use direct connection procedure to initiate connection */
|
||||
if (!L2CA_ConnectFixedChnl(L2CAP_ATT_CID, bda, BLE_ADDR_UNKNOWN_TYPE, FALSE)) {
|
||||
BTM_TRACE_ERROR("btm_ble_initiate_select_conn failed");
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_suspend_bg_conn
|
||||
**
|
||||
** Description This function is to suspend an active background connection
|
||||
** procedure.
|
||||
**
|
||||
** Parameters none.
|
||||
**
|
||||
** Returns none.
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN btm_ble_suspend_bg_conn(void)
|
||||
{
|
||||
BTM_TRACE_EVENT ("%s\n", __func__);
|
||||
|
||||
if (btm_cb.ble_ctr_cb.bg_conn_type == BTM_BLE_CONN_AUTO) {
|
||||
return btm_ble_start_auto_conn(FALSE);
|
||||
} else if (btm_cb.ble_ctr_cb.bg_conn_type == BTM_BLE_CONN_SELECTIVE) {
|
||||
return btm_ble_start_select_conn(FALSE, NULL);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_suspend_wl_activity
|
||||
**
|
||||
** Description This function is to suspend white list related activity
|
||||
**
|
||||
** Returns none.
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state)
|
||||
{
|
||||
if (wl_state & BTM_BLE_WL_INIT) {
|
||||
btm_ble_start_auto_conn(FALSE);
|
||||
}
|
||||
if (wl_state & BTM_BLE_WL_SCAN) {
|
||||
btm_ble_start_select_conn(FALSE, NULL);
|
||||
}
|
||||
if (wl_state & BTM_BLE_WL_ADV) {
|
||||
btm_ble_stop_adv();
|
||||
}
|
||||
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_resume_wl_activity
|
||||
**
|
||||
** Description This function is to resume white list related activity
|
||||
**
|
||||
** Returns none.
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state)
|
||||
{
|
||||
btm_ble_resume_bg_conn();
|
||||
if (wl_state & BTM_BLE_WL_ADV) {
|
||||
btm_ble_start_adv();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_wl_update_to_controller
|
||||
**
|
||||
** Description This function is to update white list to controller
|
||||
**
|
||||
** Returns none.
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void btm_wl_update_to_controller(void)
|
||||
{
|
||||
/* whitelist will be added in the btm_ble_resume_bg_conn(), we do not
|
||||
support background connection now, so we nedd to use btm_execute_wl_dev_operation
|
||||
to add whitelist directly ,if we support background connection in the future,
|
||||
please delete btm_execute_wl_dev_operation(). */
|
||||
btm_execute_wl_dev_operation();
|
||||
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_resume_bg_conn
|
||||
**
|
||||
** Description This function is to resume a background auto connection
|
||||
** procedure.
|
||||
**
|
||||
** Parameters none.
|
||||
**
|
||||
** Returns none.
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN btm_ble_resume_bg_conn(void)
|
||||
{
|
||||
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
|
||||
BOOLEAN ret = FALSE;
|
||||
|
||||
if (p_cb->bg_conn_type != BTM_BLE_CONN_NONE) {
|
||||
if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO) {
|
||||
ret = btm_ble_start_auto_conn(TRUE);
|
||||
}
|
||||
|
||||
if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE) {
|
||||
ret = btm_ble_start_select_conn(TRUE, btm_cb.ble_ctr_cb.p_select_cback);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_get_conn_st
|
||||
**
|
||||
** Description This function get BLE connection state
|
||||
**
|
||||
** Returns connection state
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_BLE_CONN_ST btm_ble_get_conn_st(void)
|
||||
{
|
||||
return btm_cb.ble_ctr_cb.conn_state;
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_set_conn_st
|
||||
**
|
||||
** Description This function set BLE connection state
|
||||
**
|
||||
** Returns None.
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st)
|
||||
{
|
||||
btm_cb.ble_ctr_cb.conn_state = new_st;
|
||||
|
||||
if (new_st == BLE_BG_CONN || new_st == BLE_DIR_CONN) {
|
||||
btm_ble_set_topology_mask(BTM_BLE_STATE_INIT_BIT);
|
||||
} else {
|
||||
btm_ble_clear_topology_mask(BTM_BLE_STATE_INIT_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_enqueue_direct_conn_req
|
||||
**
|
||||
** Description This function enqueue the direct connection request
|
||||
**
|
||||
** Returns None.
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_enqueue_direct_conn_req(void *p_param)
|
||||
{
|
||||
tBTM_BLE_CONN_REQ *p = (tBTM_BLE_CONN_REQ *)osi_malloc(sizeof(tBTM_BLE_CONN_REQ));
|
||||
|
||||
p->p_param = p_param;
|
||||
|
||||
fixed_queue_enqueue(btm_cb.ble_ctr_cb.conn_pending_q, p, FIXED_QUEUE_MAX_TIMEOUT);
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_send_pending_direct_conn
|
||||
**
|
||||
** Description This function send the pending direct connection request in queue
|
||||
**
|
||||
** Returns TRUE if started, FALSE otherwise
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN btm_send_pending_direct_conn(void)
|
||||
{
|
||||
tBTM_BLE_CONN_REQ *p_req;
|
||||
BOOLEAN rt = FALSE;
|
||||
|
||||
p_req = (tBTM_BLE_CONN_REQ*)fixed_queue_dequeue(btm_cb.ble_ctr_cb.conn_pending_q, 0);
|
||||
if (p_req != NULL) {
|
||||
rt = l2cble_init_direct_conn((tL2C_LCB *)(p_req->p_param));
|
||||
|
||||
osi_free((void *)p_req);
|
||||
}
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,108 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2014 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "common/bt_target.h"
|
||||
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
#include "stack/bt_types.h"
|
||||
#include "stack/hcimsgs.h"
|
||||
#include "stack/btu.h"
|
||||
#include "btm_int.h"
|
||||
//#include "bt_utils.h"
|
||||
#include "stack/hcidefs.h"
|
||||
#include "stack/btm_ble_api.h"
|
||||
|
||||
tBTM_BLE_ENERGY_INFO_CB ble_energy_info_cb;
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_cont_energy_cmpl_cback
|
||||
**
|
||||
** Description Controller VSC complete callback
|
||||
**
|
||||
** Parameters
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_cont_energy_cmpl_cback (tBTM_VSC_CMPL *p_params)
|
||||
{
|
||||
UINT8 *p = p_params->p_param_buf;
|
||||
UINT16 len = p_params->param_len;
|
||||
UINT8 status = 0;
|
||||
UINT32 total_tx_time = 0, total_rx_time = 0, total_idle_time = 0, total_energy_used = 0;
|
||||
|
||||
if (len < 17) {
|
||||
BTM_TRACE_ERROR("wrong length for btm_ble_cont_energy_cmpl_cback");
|
||||
return;
|
||||
}
|
||||
|
||||
STREAM_TO_UINT8(status, p);
|
||||
STREAM_TO_UINT32(total_tx_time, p);
|
||||
STREAM_TO_UINT32(total_rx_time, p);
|
||||
STREAM_TO_UINT32(total_idle_time, p);
|
||||
STREAM_TO_UINT32(total_energy_used, p);
|
||||
|
||||
BTM_TRACE_DEBUG("energy_info status=%d,tx_t=%u, rx_t=%u, ener_used=%u, idle_t=%u",
|
||||
status, total_tx_time, total_rx_time, total_energy_used, total_idle_time);
|
||||
|
||||
if (NULL != ble_energy_info_cb.p_ener_cback) {
|
||||
ble_energy_info_cb.p_ener_cback(total_tx_time, total_rx_time, total_idle_time,
|
||||
total_energy_used, status);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_BleGetEnergyInfo
|
||||
**
|
||||
** Description This function obtains the energy info
|
||||
**
|
||||
** Parameters p_ener_cback - Callback pointer
|
||||
**
|
||||
** Returns status
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS BTM_BleGetEnergyInfo(tBTM_BLE_ENERGY_INFO_CBACK *p_ener_cback)
|
||||
{
|
||||
tBTM_STATUS status = BTM_ILLEGAL_VALUE;
|
||||
tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
|
||||
|
||||
BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
|
||||
|
||||
BTM_TRACE_EVENT("BTM_BleGetEnergyInfo\n");
|
||||
|
||||
if (0 == cmn_ble_vsc_cb.energy_support) {
|
||||
BTM_TRACE_ERROR("Controller does not support get energy info\n");
|
||||
return BTM_ERR_PROCESSING;
|
||||
}
|
||||
|
||||
ble_energy_info_cb.p_ener_cback = p_ener_cback;
|
||||
if ((status = BTM_VendorSpecificCommand (HCI_BLE_ENERGY_INFO_OCF, 0, NULL,
|
||||
btm_ble_cont_energy_cmpl_cback)) != BTM_CMD_STARTED) {
|
||||
BTM_TRACE_ERROR("BTM_BleGetEnergyInfo status: %d", status);
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,878 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2014 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "common/bt_target.h"
|
||||
#include "device/controller.h"
|
||||
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
#include "stack/bt_types.h"
|
||||
#include "stack/hcimsgs.h"
|
||||
#include "stack/btu.h"
|
||||
#include "btm_int.h"
|
||||
//#include "bt_utils.h"
|
||||
#include "stack/hcidefs.h"
|
||||
#include "stack/btm_ble_api.h"
|
||||
|
||||
/************************************************************************************
|
||||
** Constants & Macros
|
||||
************************************************************************************/
|
||||
/* length of each multi adv sub command */
|
||||
#define BTM_BLE_MULTI_ADV_ENB_LEN 3
|
||||
#define BTM_BLE_MULTI_ADV_SET_PARAM_LEN 24
|
||||
#define BTM_BLE_MULTI_ADV_WRITE_DATA_LEN (BTM_BLE_AD_DATA_LEN + 3)
|
||||
#define BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN 8
|
||||
|
||||
#define BTM_BLE_MULTI_ADV_CB_EVT_MASK 0xF0
|
||||
#define BTM_BLE_MULTI_ADV_SUBCODE_MASK 0x0F
|
||||
|
||||
/************************************************************************************
|
||||
** Static variables
|
||||
************************************************************************************/
|
||||
#if BTM_DYNAMIC_MEMORY == FALSE
|
||||
tBTM_BLE_MULTI_ADV_CB btm_multi_adv_cb;
|
||||
tBTM_BLE_MULTI_ADV_INST_IDX_Q btm_multi_adv_idx_q;
|
||||
#else
|
||||
tBTM_BLE_MULTI_ADV_CB *btm_multi_adv_cb_ptr;
|
||||
tBTM_BLE_MULTI_ADV_INST_IDX_Q *btm_multi_adv_idx_q_ptr;
|
||||
#define btm_multi_adv_cb (*btm_multi_adv_cb_ptr)
|
||||
#define btm_multi_adv_idx_q (*btm_multi_adv_idx_q_ptr)
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
** Externs
|
||||
************************************************************************************/
|
||||
extern void btm_ble_update_dmt_flag_bits(UINT8 *flag_value,
|
||||
const UINT16 connect_mode, const UINT16 disc_mode);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_multi_adv_enq_op_q
|
||||
**
|
||||
** Description enqueue a multi adv operation in q to check command complete
|
||||
** status.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_multi_adv_enq_op_q(UINT8 opcode, UINT8 inst_id, UINT8 cb_evt)
|
||||
{
|
||||
tBTM_BLE_MULTI_ADV_OPQ *p_op_q = &btm_multi_adv_cb.op_q;
|
||||
|
||||
p_op_q->p_inst_id[p_op_q->next_idx] = inst_id;
|
||||
|
||||
p_op_q->p_sub_code[p_op_q->next_idx] = (opcode | (cb_evt << 4));
|
||||
|
||||
p_op_q->next_idx = (p_op_q->next_idx + 1) % BTM_BleMaxMultiAdvInstanceCount();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_multi_adv_deq_op_q
|
||||
**
|
||||
** Description dequeue a multi adv operation from q when command complete
|
||||
** is received.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_multi_adv_deq_op_q(UINT8 *p_opcode, UINT8 *p_inst_id, UINT8 *p_cb_evt)
|
||||
{
|
||||
tBTM_BLE_MULTI_ADV_OPQ *p_op_q = &btm_multi_adv_cb.op_q;
|
||||
|
||||
*p_inst_id = p_op_q->p_inst_id[p_op_q->pending_idx] & 0x7F;
|
||||
*p_cb_evt = (p_op_q->p_sub_code[p_op_q->pending_idx] >> 4);
|
||||
*p_opcode = (p_op_q->p_sub_code[p_op_q->pending_idx] & BTM_BLE_MULTI_ADV_SUBCODE_MASK);
|
||||
|
||||
p_op_q->pending_idx = (p_op_q->pending_idx + 1) % BTM_BleMaxMultiAdvInstanceCount();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_multi_adv_vsc_cmpl_cback
|
||||
**
|
||||
** Description Multi adv VSC complete callback
|
||||
**
|
||||
** Parameters
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_multi_adv_vsc_cmpl_cback (tBTM_VSC_CMPL *p_params)
|
||||
{
|
||||
UINT8 status, subcode;
|
||||
UINT8 *p = p_params->p_param_buf, inst_id;
|
||||
UINT16 len = p_params->param_len;
|
||||
tBTM_BLE_MULTI_ADV_INST *p_inst ;
|
||||
UINT8 cb_evt = 0, opcode;
|
||||
|
||||
if (len < 2) {
|
||||
BTM_TRACE_ERROR("wrong length for btm_ble_multi_adv_vsc_cmpl_cback");
|
||||
return;
|
||||
}
|
||||
|
||||
STREAM_TO_UINT8(status, p);
|
||||
STREAM_TO_UINT8(subcode, p);
|
||||
|
||||
btm_ble_multi_adv_deq_op_q(&opcode, &inst_id, &cb_evt);
|
||||
|
||||
BTM_TRACE_DEBUG("op_code = %02x inst_id = %d cb_evt = %02x", opcode, inst_id, cb_evt);
|
||||
|
||||
if (opcode != subcode || inst_id == 0) {
|
||||
BTM_TRACE_ERROR("get unexpected VSC cmpl, expect: %d get: %d", subcode, opcode);
|
||||
return;
|
||||
}
|
||||
|
||||
p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1];
|
||||
|
||||
switch (subcode) {
|
||||
case BTM_BLE_MULTI_ADV_ENB: {
|
||||
BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_ENB status = %d", status);
|
||||
|
||||
/* Mark as not in use here, if instance cannot be enabled */
|
||||
if (HCI_SUCCESS != status && BTM_BLE_MULTI_ADV_ENB_EVT == cb_evt) {
|
||||
btm_multi_adv_cb.p_adv_inst[inst_id - 1].in_use = FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case BTM_BLE_MULTI_ADV_SET_PARAM: {
|
||||
BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_SET_PARAM status = %d", status);
|
||||
break;
|
||||
}
|
||||
|
||||
case BTM_BLE_MULTI_ADV_WRITE_ADV_DATA: {
|
||||
BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_WRITE_ADV_DATA status = %d", status);
|
||||
break;
|
||||
}
|
||||
|
||||
case BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA: {
|
||||
BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA status = %d", status);
|
||||
break;
|
||||
}
|
||||
|
||||
case BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR: {
|
||||
BTM_TRACE_DEBUG("BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR status = %d", status);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (cb_evt != 0 && p_inst->p_cback != NULL) {
|
||||
(p_inst->p_cback)(cb_evt, inst_id, p_inst->p_ref, status);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_enable_multi_adv
|
||||
**
|
||||
** Description This function enable the customer specific feature in controller
|
||||
**
|
||||
** Parameters enable: enable or disable
|
||||
** inst_id: adv instance ID, can not be 0
|
||||
**
|
||||
** Returns status
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS btm_ble_enable_multi_adv (BOOLEAN enable, UINT8 inst_id, UINT8 cb_evt)
|
||||
{
|
||||
UINT8 param[BTM_BLE_MULTI_ADV_ENB_LEN], *pp;
|
||||
UINT8 enb = enable ? 1 : 0;
|
||||
tBTM_STATUS rt;
|
||||
|
||||
pp = param;
|
||||
memset(param, 0, BTM_BLE_MULTI_ADV_ENB_LEN);
|
||||
|
||||
UINT8_TO_STREAM (pp, BTM_BLE_MULTI_ADV_ENB);
|
||||
UINT8_TO_STREAM (pp, enb);
|
||||
UINT8_TO_STREAM (pp, inst_id);
|
||||
|
||||
BTM_TRACE_EVENT (" btm_ble_enable_multi_adv: enb %d, Inst ID %d", enb, inst_id);
|
||||
|
||||
if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
|
||||
BTM_BLE_MULTI_ADV_ENB_LEN,
|
||||
param,
|
||||
btm_ble_multi_adv_vsc_cmpl_cback))
|
||||
== BTM_CMD_STARTED) {
|
||||
btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_ENB, inst_id, cb_evt);
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_map_adv_tx_power
|
||||
**
|
||||
** Description return the actual power in dBm based on the mapping in config file
|
||||
**
|
||||
** Parameters advertise parameters used for this instance.
|
||||
**
|
||||
** Returns tx power in dBm
|
||||
**
|
||||
*******************************************************************************/
|
||||
static const int btm_ble_tx_power[BTM_BLE_ADV_TX_POWER_MAX + 1] = BTM_BLE_ADV_TX_POWER;
|
||||
char btm_ble_map_adv_tx_power(int tx_power_index)
|
||||
{
|
||||
if (0 <= tx_power_index && tx_power_index <= BTM_BLE_ADV_TX_POWER_MAX) {
|
||||
return (char)btm_ble_tx_power[tx_power_index];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_multi_adv_set_params
|
||||
**
|
||||
** Description This function enable the customer specific feature in controller
|
||||
**
|
||||
** Parameters advertise parameters used for this instance.
|
||||
**
|
||||
** Returns status
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS btm_ble_multi_adv_set_params (tBTM_BLE_MULTI_ADV_INST *p_inst,
|
||||
tBTM_BLE_ADV_PARAMS *p_params,
|
||||
UINT8 cb_evt)
|
||||
{
|
||||
UINT8 param[BTM_BLE_MULTI_ADV_SET_PARAM_LEN], *pp;
|
||||
tBTM_STATUS rt;
|
||||
BD_ADDR dummy = {0, 0, 0, 0, 0, 0};
|
||||
|
||||
pp = param;
|
||||
memset(param, 0, BTM_BLE_MULTI_ADV_SET_PARAM_LEN);
|
||||
|
||||
UINT8_TO_STREAM(pp, BTM_BLE_MULTI_ADV_SET_PARAM);
|
||||
|
||||
UINT16_TO_STREAM (pp, p_params->adv_int_min);
|
||||
UINT16_TO_STREAM (pp, p_params->adv_int_max);
|
||||
UINT8_TO_STREAM (pp, p_params->adv_type);
|
||||
|
||||
#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
|
||||
if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE) {
|
||||
UINT8_TO_STREAM (pp, BLE_ADDR_RANDOM);
|
||||
BDADDR_TO_STREAM (pp, p_inst->rpa);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
UINT8_TO_STREAM (pp, BLE_ADDR_PUBLIC);
|
||||
BDADDR_TO_STREAM (pp, controller_get_interface()->get_address()->address);
|
||||
}
|
||||
|
||||
BTM_TRACE_EVENT (" btm_ble_multi_adv_set_params,Min %d, Max %d,adv_type %d",
|
||||
p_params->adv_int_min, p_params->adv_int_max, p_params->adv_type);
|
||||
|
||||
UINT8_TO_STREAM (pp, 0);
|
||||
BDADDR_TO_STREAM (pp, dummy);
|
||||
|
||||
if (p_params->channel_map == 0 || p_params->channel_map > BTM_BLE_DEFAULT_ADV_CHNL_MAP) {
|
||||
p_params->channel_map = BTM_BLE_DEFAULT_ADV_CHNL_MAP;
|
||||
}
|
||||
UINT8_TO_STREAM (pp, p_params->channel_map);
|
||||
|
||||
if (p_params->adv_filter_policy >= AP_SCAN_CONN_POLICY_MAX) {
|
||||
p_params->adv_filter_policy = AP_SCAN_CONN_ALL;
|
||||
}
|
||||
UINT8_TO_STREAM (pp, p_params->adv_filter_policy);
|
||||
|
||||
UINT8_TO_STREAM (pp, p_inst->inst_id);
|
||||
|
||||
if (p_params->tx_power > BTM_BLE_ADV_TX_POWER_MAX) {
|
||||
p_params->tx_power = BTM_BLE_ADV_TX_POWER_MAX;
|
||||
}
|
||||
UINT8_TO_STREAM (pp, btm_ble_map_adv_tx_power(p_params->tx_power));
|
||||
|
||||
BTM_TRACE_EVENT("set_params:Chnl Map %d,adv_fltr policy %d,ID:%d, TX Power%d",
|
||||
p_params->channel_map, p_params->adv_filter_policy, p_inst->inst_id, p_params->tx_power);
|
||||
|
||||
if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
|
||||
BTM_BLE_MULTI_ADV_SET_PARAM_LEN,
|
||||
param,
|
||||
btm_ble_multi_adv_vsc_cmpl_cback))
|
||||
== BTM_CMD_STARTED) {
|
||||
p_inst->adv_evt = p_params->adv_type;
|
||||
|
||||
#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
|
||||
if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE) {
|
||||
/* start timer */
|
||||
p_inst->raddr_timer_ent.param = (TIMER_PARAM_TYPE) p_inst;
|
||||
btu_start_timer_oneshot(&p_inst->raddr_timer_ent, BTU_TTYPE_BLE_RANDOM_ADDR,
|
||||
BTM_BLE_PRIVATE_ADDR_INT);
|
||||
}
|
||||
#endif
|
||||
btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_SET_PARAM, p_inst->inst_id, cb_evt);
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_multi_adv_write_rpa
|
||||
**
|
||||
** Description This function write the random address for the adv instance into
|
||||
** controller
|
||||
**
|
||||
** Parameters
|
||||
**
|
||||
** Returns status
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS btm_ble_multi_adv_write_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst, BD_ADDR random_addr)
|
||||
{
|
||||
UINT8 param[BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN], *pp = param;
|
||||
tBTM_STATUS rt;
|
||||
|
||||
BTM_TRACE_EVENT ("%s-BD_ADDR:%02x-%02x-%02x-%02x-%02x-%02x,inst_id:%d",
|
||||
__FUNCTION__, random_addr[5], random_addr[4], random_addr[3], random_addr[2],
|
||||
random_addr[1], random_addr[0], p_inst->inst_id);
|
||||
|
||||
memset(param, 0, BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN);
|
||||
|
||||
UINT8_TO_STREAM (pp, BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR);
|
||||
BDADDR_TO_STREAM(pp, random_addr);
|
||||
UINT8_TO_STREAM(pp, p_inst->inst_id);
|
||||
|
||||
if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
|
||||
BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN,
|
||||
param,
|
||||
btm_ble_multi_adv_vsc_cmpl_cback)) == BTM_CMD_STARTED) {
|
||||
/* start a periodical timer to refresh random addr */
|
||||
btu_stop_timer_oneshot(&p_inst->raddr_timer_ent);
|
||||
p_inst->raddr_timer_ent.param = (TIMER_PARAM_TYPE) p_inst;
|
||||
btu_start_timer_oneshot(&p_inst->raddr_timer_ent, BTU_TTYPE_BLE_RANDOM_ADDR,
|
||||
BTM_BLE_PRIVATE_ADDR_INT);
|
||||
|
||||
btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR, p_inst->inst_id, 0);
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_multi_adv_gen_rpa_cmpl
|
||||
**
|
||||
** Description RPA generation completion callback for each adv instance. Will
|
||||
** continue write the new RPA into controller.
|
||||
**
|
||||
** Returns none.
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_multi_adv_gen_rpa_cmpl(tBTM_RAND_ENC *p)
|
||||
{
|
||||
#if (SMP_INCLUDED == TRUE)
|
||||
tSMP_ENC output;
|
||||
UINT8 index = 0;
|
||||
tBTM_BLE_MULTI_ADV_INST *p_inst = NULL;
|
||||
|
||||
/* Retrieve the index of adv instance from stored Q */
|
||||
if (btm_multi_adv_idx_q.front == -1) {
|
||||
BTM_TRACE_ERROR(" %s can't locate advertise instance", __FUNCTION__);
|
||||
return;
|
||||
} else {
|
||||
index = btm_multi_adv_idx_q.inst_index_queue[btm_multi_adv_idx_q.front];
|
||||
if (btm_multi_adv_idx_q.front == btm_multi_adv_idx_q.rear) {
|
||||
btm_multi_adv_idx_q.front = -1;
|
||||
btm_multi_adv_idx_q.rear = -1;
|
||||
} else {
|
||||
btm_multi_adv_idx_q.front = (btm_multi_adv_idx_q.front + 1) % BTM_BLE_MULTI_ADV_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
p_inst = &(btm_multi_adv_cb.p_adv_inst[index]);
|
||||
|
||||
BTM_TRACE_EVENT ("btm_ble_multi_adv_gen_rpa_cmpl inst_id = %d", p_inst->inst_id);
|
||||
if (p) {
|
||||
p->param_buf[2] &= (~BLE_RESOLVE_ADDR_MASK);
|
||||
p->param_buf[2] |= BLE_RESOLVE_ADDR_MSB;
|
||||
|
||||
p_inst->rpa[2] = p->param_buf[0];
|
||||
p_inst->rpa[1] = p->param_buf[1];
|
||||
p_inst->rpa[0] = p->param_buf[2];
|
||||
|
||||
if (!SMP_Encrypt(btm_cb.devcb.id_keys.irk, BT_OCTET16_LEN, p->param_buf, 3, &output)) {
|
||||
BTM_TRACE_DEBUG("generate random address failed");
|
||||
} else {
|
||||
/* set hash to be LSB of rpAddress */
|
||||
p_inst->rpa[5] = output.param_buf[0];
|
||||
p_inst->rpa[4] = output.param_buf[1];
|
||||
p_inst->rpa[3] = output.param_buf[2];
|
||||
}
|
||||
|
||||
if (p_inst->inst_id != BTM_BLE_MULTI_ADV_DEFAULT_STD &&
|
||||
p_inst->inst_id < BTM_BleMaxMultiAdvInstanceCount()) {
|
||||
/* set it to controller */
|
||||
btm_ble_multi_adv_write_rpa(p_inst, p_inst->rpa);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_multi_adv_configure_rpa
|
||||
**
|
||||
** Description This function set the random address for the adv instance
|
||||
**
|
||||
** Parameters advertise parameters used for this instance.
|
||||
**
|
||||
** Returns none
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_multi_adv_configure_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst)
|
||||
{
|
||||
if (btm_multi_adv_idx_q.front == (btm_multi_adv_idx_q.rear + 1) % BTM_BLE_MULTI_ADV_MAX) {
|
||||
BTM_TRACE_ERROR("outstanding rand generation exceeded max allowed ");
|
||||
return;
|
||||
} else {
|
||||
if (btm_multi_adv_idx_q.front == -1) {
|
||||
btm_multi_adv_idx_q.front = 0;
|
||||
btm_multi_adv_idx_q.rear = 0;
|
||||
} else {
|
||||
btm_multi_adv_idx_q.rear = (btm_multi_adv_idx_q.rear + 1) % BTM_BLE_MULTI_ADV_MAX;
|
||||
}
|
||||
btm_multi_adv_idx_q.inst_index_queue[btm_multi_adv_idx_q.rear] = p_inst->index;
|
||||
}
|
||||
btm_gen_resolvable_private_addr((void *)btm_ble_multi_adv_gen_rpa_cmpl);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_multi_adv_reenable
|
||||
**
|
||||
** Description This function re-enable adv instance upon a connection establishment.
|
||||
**
|
||||
** Parameters advertise parameters used for this instance.
|
||||
**
|
||||
** Returns none.
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_multi_adv_reenable(UINT8 inst_id)
|
||||
{
|
||||
tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1];
|
||||
|
||||
if (TRUE == p_inst->in_use) {
|
||||
if (p_inst->adv_evt != BTM_BLE_CONNECT_DIR_EVT) {
|
||||
btm_ble_enable_multi_adv (TRUE, p_inst->inst_id, 0);
|
||||
} else
|
||||
/* mark directed adv as disabled if adv has been stopped */
|
||||
{
|
||||
(p_inst->p_cback)(BTM_BLE_MULTI_ADV_DISABLE_EVT, p_inst->inst_id, p_inst->p_ref, 0);
|
||||
p_inst->in_use = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_multi_adv_enb_privacy
|
||||
**
|
||||
** Description This function enable/disable privacy setting in multi adv
|
||||
**
|
||||
** Parameters enable: enable or disable the adv instance.
|
||||
**
|
||||
** Returns none.
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_multi_adv_enb_privacy(BOOLEAN enable)
|
||||
{
|
||||
UINT8 i;
|
||||
tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[0];
|
||||
|
||||
for (i = 0; i < BTM_BleMaxMultiAdvInstanceCount() - 1; i ++, p_inst++) {
|
||||
p_inst->in_use = FALSE;
|
||||
if (enable) {
|
||||
btm_ble_multi_adv_configure_rpa (p_inst);
|
||||
} else {
|
||||
btu_stop_timer_oneshot(&p_inst->raddr_timer_ent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_BleEnableAdvInstance
|
||||
**
|
||||
** Description This function enable a Multi-ADV instance with the specified
|
||||
** adv parameters
|
||||
**
|
||||
** Parameters p_params: pointer to the adv parameter structure, set as default
|
||||
** adv parameter when the instance is enabled.
|
||||
** p_cback: callback function for the adv instance.
|
||||
** p_ref: reference data attach to the adv instance to be enabled.
|
||||
**
|
||||
** Returns status
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS BTM_BleEnableAdvInstance (tBTM_BLE_ADV_PARAMS *p_params,
|
||||
tBTM_BLE_MULTI_ADV_CBACK *p_cback, void *p_ref)
|
||||
{
|
||||
UINT8 i;
|
||||
tBTM_STATUS rt = BTM_NO_RESOURCES;
|
||||
tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[0];
|
||||
|
||||
BTM_TRACE_EVENT("BTM_BleEnableAdvInstance called");
|
||||
|
||||
if (0 == btm_cb.cmn_ble_vsc_cb.adv_inst_max) {
|
||||
BTM_TRACE_ERROR("Controller does not support Multi ADV");
|
||||
return BTM_ERR_PROCESSING;
|
||||
}
|
||||
|
||||
if (NULL == p_inst) {
|
||||
BTM_TRACE_ERROR("Invalid instance in BTM_BleEnableAdvInstance");
|
||||
return BTM_ERR_PROCESSING;
|
||||
}
|
||||
|
||||
for (i = 0; i < BTM_BleMaxMultiAdvInstanceCount() - 1; i ++, p_inst++) {
|
||||
if (FALSE == p_inst->in_use) {
|
||||
p_inst->in_use = TRUE;
|
||||
/* configure adv parameter */
|
||||
if (p_params) {
|
||||
rt = btm_ble_multi_adv_set_params(p_inst, p_params, 0);
|
||||
} else {
|
||||
rt = BTM_CMD_STARTED;
|
||||
}
|
||||
|
||||
/* enable adv */
|
||||
BTM_TRACE_EVENT("btm_ble_enable_multi_adv being called with inst_id:%d",
|
||||
p_inst->inst_id);
|
||||
|
||||
if (BTM_CMD_STARTED == rt) {
|
||||
if ((rt = btm_ble_enable_multi_adv (TRUE, p_inst->inst_id,
|
||||
BTM_BLE_MULTI_ADV_ENB_EVT)) == BTM_CMD_STARTED) {
|
||||
p_inst->p_cback = p_cback;
|
||||
p_inst->p_ref = p_ref;
|
||||
}
|
||||
}
|
||||
|
||||
if (BTM_CMD_STARTED != rt) {
|
||||
p_inst->in_use = FALSE;
|
||||
BTM_TRACE_ERROR("BTM_BleEnableAdvInstance failed");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_BleUpdateAdvInstParam
|
||||
**
|
||||
** Description This function update a Multi-ADV instance with the specified
|
||||
** adv parameters.
|
||||
**
|
||||
** Parameters inst_id: adv instance ID
|
||||
** p_params: pointer to the adv parameter structure.
|
||||
**
|
||||
** Returns status
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS BTM_BleUpdateAdvInstParam (UINT8 inst_id, tBTM_BLE_ADV_PARAMS *p_params)
|
||||
{
|
||||
tBTM_STATUS rt = BTM_ILLEGAL_VALUE;
|
||||
tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1];
|
||||
|
||||
BTM_TRACE_EVENT("BTM_BleUpdateAdvInstParam called with inst_id:%d", inst_id);
|
||||
|
||||
if (0 == btm_cb.cmn_ble_vsc_cb.adv_inst_max) {
|
||||
BTM_TRACE_ERROR("Controller does not support Multi ADV");
|
||||
return BTM_ERR_PROCESSING;
|
||||
}
|
||||
|
||||
if (inst_id < BTM_BleMaxMultiAdvInstanceCount() &&
|
||||
inst_id != BTM_BLE_MULTI_ADV_DEFAULT_STD &&
|
||||
p_params != NULL) {
|
||||
if (FALSE == p_inst->in_use) {
|
||||
BTM_TRACE_DEBUG("adv instance %d is not active", inst_id);
|
||||
return BTM_WRONG_MODE;
|
||||
} else {
|
||||
btm_ble_enable_multi_adv(FALSE, inst_id, 0);
|
||||
}
|
||||
|
||||
if (BTM_CMD_STARTED == btm_ble_multi_adv_set_params(p_inst, p_params, 0)) {
|
||||
rt = btm_ble_enable_multi_adv(TRUE, inst_id, BTM_BLE_MULTI_ADV_PARAM_EVT);
|
||||
}
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_BleCfgAdvInstData
|
||||
**
|
||||
** Description This function configure a Multi-ADV instance with the specified
|
||||
** adv data or scan response data.
|
||||
**
|
||||
** Parameters inst_id: adv instance ID
|
||||
** is_scan_rsp: is this scan response. if no, set as adv data.
|
||||
** data_mask: adv data mask.
|
||||
** p_data: pointer to the adv data structure.
|
||||
**
|
||||
** Returns status
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS BTM_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp,
|
||||
tBTM_BLE_AD_MASK data_mask,
|
||||
tBTM_BLE_ADV_DATA *p_data)
|
||||
{
|
||||
UINT8 param[BTM_BLE_MULTI_ADV_WRITE_DATA_LEN], *pp = param;
|
||||
UINT8 sub_code = (is_scan_rsp) ?
|
||||
BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA : BTM_BLE_MULTI_ADV_WRITE_ADV_DATA;
|
||||
UINT8 *p_len;
|
||||
tBTM_STATUS rt;
|
||||
UINT8 *pp_temp = (UINT8 *)(param + BTM_BLE_MULTI_ADV_WRITE_DATA_LEN - 1);
|
||||
tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
|
||||
|
||||
BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
|
||||
if (0 == cmn_ble_vsc_cb.adv_inst_max) {
|
||||
BTM_TRACE_ERROR("Controller does not support Multi ADV");
|
||||
return BTM_ERR_PROCESSING;
|
||||
}
|
||||
|
||||
btm_ble_update_dmt_flag_bits(&p_data->flag, btm_cb.btm_inq_vars.connectable_mode,
|
||||
btm_cb.btm_inq_vars.discoverable_mode);
|
||||
|
||||
BTM_TRACE_EVENT("BTM_BleCfgAdvInstData called with inst_id:%d", inst_id);
|
||||
if (inst_id > BTM_BLE_MULTI_ADV_MAX || inst_id == BTM_BLE_MULTI_ADV_DEFAULT_STD) {
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
memset(param, 0, BTM_BLE_MULTI_ADV_WRITE_DATA_LEN);
|
||||
|
||||
UINT8_TO_STREAM(pp, sub_code);
|
||||
p_len = pp ++;
|
||||
btm_ble_build_adv_data(&data_mask, &pp, p_data);
|
||||
*p_len = (UINT8)(pp - param - 2);
|
||||
UINT8_TO_STREAM(pp_temp, inst_id);
|
||||
|
||||
if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
|
||||
(UINT8)BTM_BLE_MULTI_ADV_WRITE_DATA_LEN,
|
||||
param,
|
||||
btm_ble_multi_adv_vsc_cmpl_cback))
|
||||
== BTM_CMD_STARTED) {
|
||||
btm_ble_multi_adv_enq_op_q(sub_code, inst_id, BTM_BLE_MULTI_ADV_DATA_EVT);
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_BleDisableAdvInstance
|
||||
**
|
||||
** Description This function disables a Multi-ADV instance.
|
||||
**
|
||||
** Parameters inst_id: adv instance ID
|
||||
**
|
||||
** Returns status
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS BTM_BleDisableAdvInstance (UINT8 inst_id)
|
||||
{
|
||||
tBTM_STATUS rt = BTM_ILLEGAL_VALUE;
|
||||
tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
|
||||
|
||||
BTM_TRACE_EVENT("BTM_BleDisableAdvInstance with inst_id:%d", inst_id);
|
||||
|
||||
BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
|
||||
|
||||
if (0 == cmn_ble_vsc_cb.adv_inst_max) {
|
||||
BTM_TRACE_ERROR("Controller does not support Multi ADV");
|
||||
return BTM_ERR_PROCESSING;
|
||||
}
|
||||
|
||||
if (inst_id < BTM_BleMaxMultiAdvInstanceCount() &&
|
||||
inst_id != BTM_BLE_MULTI_ADV_DEFAULT_STD) {
|
||||
if ((rt = btm_ble_enable_multi_adv(FALSE, inst_id, BTM_BLE_MULTI_ADV_DISABLE_EVT))
|
||||
== BTM_CMD_STARTED) {
|
||||
btm_ble_multi_adv_configure_rpa(&btm_multi_adv_cb.p_adv_inst[inst_id - 1]);
|
||||
btu_stop_timer_oneshot(&btm_multi_adv_cb.p_adv_inst[inst_id - 1].raddr_timer_ent);
|
||||
btm_multi_adv_cb.p_adv_inst[inst_id - 1].in_use = FALSE;
|
||||
}
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_multi_adv_vse_cback
|
||||
**
|
||||
** Description VSE callback for multi adv events.
|
||||
**
|
||||
** Returns
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_multi_adv_vse_cback(UINT8 len, UINT8 *p)
|
||||
{
|
||||
UINT8 sub_event;
|
||||
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--;
|
||||
|
||||
BTM_TRACE_EVENT("btm_ble_multi_adv_vse_cback called with event:%d", sub_event);
|
||||
if ((sub_event == HCI_VSE_SUBCODE_BLE_MULTI_ADV_ST_CHG) && (len >= 4)) {
|
||||
STREAM_TO_UINT8(adv_inst, p);
|
||||
++p;
|
||||
STREAM_TO_UINT16(conn_handle, p);
|
||||
|
||||
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(p_acl_cb->conn_addr, btm_multi_adv_cb.p_adv_inst[adv_inst - 1].rpa,
|
||||
BD_ADDR_LEN);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (adv_inst < BTM_BleMaxMultiAdvInstanceCount() &&
|
||||
adv_inst != BTM_BLE_MULTI_ADV_DEFAULT_STD) {
|
||||
BTM_TRACE_EVENT("btm_ble_multi_adv_reenable called");
|
||||
btm_ble_multi_adv_reenable(adv_inst);
|
||||
}
|
||||
/* re-enable connectibility */
|
||||
else if (adv_inst == BTM_BLE_MULTI_ADV_DEFAULT_STD) {
|
||||
if (btm_cb.ble_ctr_cb.inq_var.connectable_mode == BTM_BLE_CONNECTABLE) {
|
||||
btm_ble_set_connectability ( btm_cb.ble_ctr_cb.inq_var.connectable_mode );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_multi_adv_init
|
||||
**
|
||||
** Description This function initialize the multi adv control block.
|
||||
**
|
||||
** Parameters None
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_multi_adv_init(void)
|
||||
{
|
||||
#if BTM_DYNAMIC_MEMORY == TRUE
|
||||
btm_multi_adv_cb_ptr = (tBTM_BLE_MULTI_ADV_CB *)osi_malloc(sizeof(tBTM_BLE_MULTI_ADV_CB));
|
||||
btm_multi_adv_idx_q_ptr = (tBTM_BLE_MULTI_ADV_INST_IDX_Q *)osi_malloc(sizeof(tBTM_BLE_MULTI_ADV_INST_IDX_Q));
|
||||
if (btm_multi_adv_cb_ptr == NULL || btm_multi_adv_idx_q_ptr == NULL) {
|
||||
BTM_TRACE_ERROR("%s malloc failed", __func__);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
UINT8 i = 0;
|
||||
memset(&btm_multi_adv_cb, 0, sizeof(tBTM_BLE_MULTI_ADV_CB));
|
||||
memset (&btm_multi_adv_idx_q, 0, sizeof (tBTM_BLE_MULTI_ADV_INST_IDX_Q));
|
||||
btm_multi_adv_idx_q.front = -1;
|
||||
btm_multi_adv_idx_q.rear = -1;
|
||||
|
||||
if (btm_cb.cmn_ble_vsc_cb.adv_inst_max > 0) {
|
||||
btm_multi_adv_cb.p_adv_inst = osi_malloc( sizeof(tBTM_BLE_MULTI_ADV_INST) *
|
||||
(btm_cb.cmn_ble_vsc_cb.adv_inst_max));
|
||||
memset(btm_multi_adv_cb.p_adv_inst, 0, sizeof(tBTM_BLE_MULTI_ADV_INST) *
|
||||
(btm_cb.cmn_ble_vsc_cb.adv_inst_max));
|
||||
|
||||
btm_multi_adv_cb.op_q.p_sub_code = osi_malloc( sizeof(UINT8) *
|
||||
(btm_cb.cmn_ble_vsc_cb.adv_inst_max));
|
||||
memset(btm_multi_adv_cb.op_q.p_sub_code, 0,
|
||||
sizeof(UINT8) * (btm_cb.cmn_ble_vsc_cb.adv_inst_max));
|
||||
|
||||
btm_multi_adv_cb.op_q.p_inst_id = osi_malloc( sizeof(UINT8) *
|
||||
(btm_cb.cmn_ble_vsc_cb.adv_inst_max));
|
||||
memset(btm_multi_adv_cb.op_q.p_inst_id, 0,
|
||||
sizeof(UINT8) * (btm_cb.cmn_ble_vsc_cb.adv_inst_max));
|
||||
}
|
||||
|
||||
/* Initialize adv instance indices and IDs. */
|
||||
for (i = 0; i < btm_cb.cmn_ble_vsc_cb.adv_inst_max; i++) {
|
||||
btm_multi_adv_cb.p_adv_inst[i].index = i;
|
||||
btm_multi_adv_cb.p_adv_inst[i].inst_id = i + 1;
|
||||
}
|
||||
|
||||
BTM_RegisterForVSEvents(btm_ble_multi_adv_vse_cback, TRUE);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_multi_adv_cleanup
|
||||
**
|
||||
** Description This function cleans up multi adv control block.
|
||||
**
|
||||
** Parameters
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_multi_adv_cleanup(void)
|
||||
{
|
||||
if (btm_multi_adv_cb.p_adv_inst) {
|
||||
osi_free(btm_multi_adv_cb.p_adv_inst);
|
||||
btm_multi_adv_cb.p_adv_inst = NULL;
|
||||
}
|
||||
|
||||
if (btm_multi_adv_cb.op_q.p_sub_code) {
|
||||
osi_free(btm_multi_adv_cb.op_q.p_sub_code);
|
||||
btm_multi_adv_cb.op_q.p_sub_code = NULL;
|
||||
}
|
||||
|
||||
if (btm_multi_adv_cb.op_q.p_inst_id) {
|
||||
osi_free(btm_multi_adv_cb.op_q.p_inst_id);
|
||||
btm_multi_adv_cb.op_q.p_inst_id = NULL;
|
||||
}
|
||||
|
||||
#if BTM_DYNAMIC_MEMORY == TRUE
|
||||
if(btm_multi_adv_cb_ptr) {
|
||||
osi_free(btm_multi_adv_cb_ptr);
|
||||
btm_multi_adv_cb_ptr = NULL;
|
||||
}
|
||||
if(btm_multi_adv_idx_q_ptr) {
|
||||
osi_free(btm_multi_adv_idx_q_ptr);
|
||||
btm_multi_adv_idx_q_ptr = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_multi_adv_get_ref
|
||||
**
|
||||
** Description This function obtains the reference pointer for the instance ID provided
|
||||
**
|
||||
** Parameters inst_id - Instance ID
|
||||
**
|
||||
** Returns void*
|
||||
**
|
||||
*******************************************************************************/
|
||||
void *btm_ble_multi_adv_get_ref(UINT8 inst_id)
|
||||
{
|
||||
tBTM_BLE_MULTI_ADV_INST *p_inst = NULL;
|
||||
|
||||
if (inst_id < BTM_BleMaxMultiAdvInstanceCount()) {
|
||||
p_inst = &btm_multi_adv_cb.p_adv_inst[inst_id - 1];
|
||||
if (NULL != p_inst) {
|
||||
return p_inst->p_ref;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,741 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2012 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file contains functions for the Bluetooth Device Manager
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
//#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "stack/bt_types.h"
|
||||
#include "device/controller.h"
|
||||
#include "stack/hcimsgs.h"
|
||||
#include "stack/btu.h"
|
||||
#include "stack/btm_api.h"
|
||||
#include "btm_int.h"
|
||||
#include "stack/hcidefs.h"
|
||||
#include "stack/l2c_api.h"
|
||||
|
||||
static tBTM_SEC_DEV_REC *btm_find_oldest_dev (void);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_SecAddDevice
|
||||
**
|
||||
** Description Add/modify device. This function will be normally called
|
||||
** during host startup to restore all required information
|
||||
** stored in the NVRAM.
|
||||
**
|
||||
** Parameters: bd_addr - BD address of the peer
|
||||
** dev_class - Device Class
|
||||
** bd_name - Name of the peer device. NULL if unknown.
|
||||
** features - Remote device's features (up to 3 pages). NULL if not known
|
||||
** trusted_mask - Bitwise OR of services that do not
|
||||
** require authorization. (array of UINT32)
|
||||
** link_key - Connection link key. NULL if unknown.
|
||||
**
|
||||
** Returns TRUE if added OK, else FALSE
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
|
||||
UINT8 *features, UINT32 trusted_mask[],
|
||||
LINK_KEY link_key, UINT8 key_type, tBTM_IO_CAP io_cap,
|
||||
UINT8 pin_length, UINT8 sc_support)
|
||||
{
|
||||
#if (SMP_INCLUDED == TRUE)
|
||||
tBTM_SEC_DEV_REC *p_dev_rec;
|
||||
int i, j;
|
||||
BOOLEAN found = FALSE;
|
||||
|
||||
BTM_TRACE_API("%s, link key type:%x\n", __FUNCTION__, key_type);
|
||||
p_dev_rec = btm_find_dev (bd_addr);
|
||||
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. */
|
||||
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;
|
||||
memcpy (p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN);
|
||||
p_dev_rec->hci_handle = BTM_GetHCIConnHandle (bd_addr, BT_TRANSPORT_BR_EDR);
|
||||
p_dev_rec->ble_hci_handle = BTM_GetHCIConnHandle (bd_addr, BT_TRANSPORT_LE);
|
||||
p_dev_rec->enc_mode = BTM_ENC_MODE_UNKNOWN;
|
||||
|
||||
#if BLE_INCLUDED == TRUE
|
||||
/* use default value for background connection params */
|
||||
/* update conn params, use default value for background connection params */
|
||||
memset(&p_dev_rec->conn_params, 0xff, sizeof(tBTM_LE_CONN_PRAMS));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (!p_dev_rec) {
|
||||
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;
|
||||
|
||||
if (dev_class) {
|
||||
memcpy (p_dev_rec->dev_class, dev_class, DEV_CLASS_LEN);
|
||||
}
|
||||
|
||||
memset(p_dev_rec->sec_bd_name, 0, sizeof(tBTM_BD_NAME));
|
||||
|
||||
if (bd_name && bd_name[0]) {
|
||||
p_dev_rec->sec_flags |= BTM_SEC_NAME_KNOWN;
|
||||
BCM_STRNCPY_S ((char *)p_dev_rec->sec_bd_name, (char *)bd_name, BTM_MAX_REM_BD_NAME_LEN);
|
||||
}
|
||||
|
||||
p_dev_rec->num_read_pages = 0;
|
||||
if (features) {
|
||||
memcpy (p_dev_rec->features, features, sizeof (p_dev_rec->features));
|
||||
for (i = HCI_EXT_FEATURES_PAGE_MAX; i >= 0; i--) {
|
||||
for (j = 0; j < HCI_FEATURE_BYTES_PER_PAGE; j++) {
|
||||
if (p_dev_rec->features[i][j] != 0) {
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
p_dev_rec->num_read_pages = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
memset (p_dev_rec->features, 0, sizeof (p_dev_rec->features));
|
||||
}
|
||||
|
||||
BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask);
|
||||
|
||||
if (link_key) {
|
||||
BTM_TRACE_EVENT ("BTM_SecAddDevice() BDA: %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
bd_addr[0], bd_addr[1], bd_addr[2],
|
||||
bd_addr[3], bd_addr[4], bd_addr[5]);
|
||||
p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_KNOWN;
|
||||
memcpy (p_dev_rec->link_key, link_key, LINK_KEY_LEN);
|
||||
p_dev_rec->link_key_type = key_type;
|
||||
p_dev_rec->pin_code_length = pin_length;
|
||||
|
||||
if (pin_length >= 16 ||
|
||||
key_type == BTM_LKEY_TYPE_AUTH_COMB ||
|
||||
key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256) {
|
||||
// Set the fiag if the link key was made by using either a 16 digit
|
||||
// pin or MITM.
|
||||
p_dev_rec->sec_flags |= BTM_SEC_16_DIGIT_PIN_AUTHED;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(BTIF_MIXED_MODE_INCLUDED) && (BTIF_MIXED_MODE_INCLUDED == TRUE)
|
||||
if (key_type < BTM_MAX_PRE_SM4_LKEY_TYPE) {
|
||||
p_dev_rec->sm4 = BTM_SM4_KNOWN;
|
||||
} else {
|
||||
p_dev_rec->sm4 = BTM_SM4_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
p_dev_rec->rmt_io_caps = io_cap;
|
||||
p_dev_rec->device_type |= BT_DEVICE_TYPE_BREDR;
|
||||
#endif ///SMP_INCLUDED == TRUE
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_SecDeleteDevice
|
||||
**
|
||||
** Description Free resources associated with the device.
|
||||
**
|
||||
** Parameters: bd_addr - BD address of the peer
|
||||
** transport - BT_TRANSPORT_BR_EDR or BT_TRANSPORT_LE
|
||||
**
|
||||
** Returns TRUE if removed OK, FALSE if not found or ACL link is active
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN BTM_SecDeleteDevice (BD_ADDR bd_addr, tBT_TRANSPORT transport)
|
||||
{
|
||||
|
||||
tBTM_SEC_DEV_REC *p_dev_rec;
|
||||
|
||||
if (BTM_IsAclConnectionUp(bd_addr, transport)) {
|
||||
BTM_TRACE_WARNING("%s FAILED: Cannot Delete when connection is active\n", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
if ((p_dev_rec = btm_find_dev(bd_addr)) != NULL) {
|
||||
/* Tell controller to get rid of the link key, if it has one stored */
|
||||
BTM_DeleteStoredLinkKey (p_dev_rec->bd_addr, NULL);
|
||||
|
||||
btm_sec_free_dev(p_dev_rec, transport);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_SecClearSecurityFlags
|
||||
**
|
||||
** Description Reset the security flags (mark as not-paired) for a given
|
||||
** remove device.
|
||||
**
|
||||
*******************************************************************************/
|
||||
extern void BTM_SecClearSecurityFlags (BD_ADDR bd_addr)
|
||||
{
|
||||
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(bd_addr);
|
||||
if (p_dev_rec == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
p_dev_rec->sec_flags = 0;
|
||||
p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
|
||||
p_dev_rec->sm4 = BTM_SM4_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_SecReadDevName
|
||||
**
|
||||
** Description Looks for the device name in the security database for the
|
||||
** specified BD address.
|
||||
**
|
||||
** Returns Pointer to the name or NULL
|
||||
**
|
||||
*******************************************************************************/
|
||||
char *BTM_SecReadDevName (BD_ADDR bd_addr)
|
||||
{
|
||||
char *p_name = NULL;
|
||||
tBTM_SEC_DEV_REC *p_srec;
|
||||
|
||||
if ((p_srec = btm_find_dev(bd_addr)) != NULL) {
|
||||
p_name = (char *)p_srec->sec_bd_name;
|
||||
}
|
||||
|
||||
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
|
||||
**
|
||||
** Description Look for the record in the device database for the record
|
||||
** with specified address
|
||||
**
|
||||
** Returns Pointer to the record or NULL
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_SEC_DEV_REC *btm_sec_alloc_dev (BD_ADDR bd_addr)
|
||||
{
|
||||
tBTM_SEC_DEV_REC *p_dev_rec = NULL;
|
||||
tBTM_SEC_DEV_REC *p_dev_new_rec = NULL;
|
||||
tBTM_SEC_DEV_REC *p_dev_old_rec = NULL;
|
||||
tBTM_INQ_INFO *p_inq_info;
|
||||
list_node_t *p_node = NULL;
|
||||
BOOLEAN new_entry_found = FALSE;
|
||||
BOOLEAN old_entry_found = FALSE;
|
||||
BOOLEAN malloc_new_entry = FALSE;
|
||||
BTM_TRACE_EVENT ("btm_sec_alloc_dev\n");
|
||||
for (p_node = list_begin(btm_cb.p_sec_dev_rec_list); p_node; p_node = list_next(p_node)) {
|
||||
p_dev_old_rec = list_node(p_node);
|
||||
/* look for old entry which match the bd_addr and the BTM_SEC_IN_USE is cleared */
|
||||
if (!(p_dev_old_rec->sec_flags & BTM_SEC_IN_USE) &&
|
||||
(!memcmp (p_dev_old_rec->bd_addr, bd_addr, BD_ADDR_LEN))) {
|
||||
old_entry_found = TRUE;
|
||||
BTM_TRACE_EVENT ("btm_sec_alloc_dev old device found\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (p_node = list_begin(btm_cb.p_sec_dev_rec_list); p_node; p_node = list_next(p_node)) {
|
||||
p_dev_new_rec = list_node(p_node);
|
||||
/* find the first entry whose BTM_SEC_IN_USE is cleared */
|
||||
if (!(p_dev_new_rec->sec_flags & BTM_SEC_IN_USE)) {
|
||||
new_entry_found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!new_entry_found) {
|
||||
/* We can not find new device. We need malloc a new one if p_sec_dev_rec_list is not full */
|
||||
if (list_length(btm_cb.p_sec_dev_rec_list) < BTM_SEC_MAX_DEVICE_RECORDS){
|
||||
p_dev_new_rec = (tBTM_SEC_DEV_REC *)osi_malloc(sizeof(tBTM_SEC_DEV_REC));
|
||||
if (p_dev_new_rec) {
|
||||
new_entry_found = TRUE;
|
||||
malloc_new_entry = TRUE;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!new_entry_found) {
|
||||
p_dev_rec = btm_find_oldest_dev();
|
||||
} else {
|
||||
/* if the old device entry not present go with new entry */
|
||||
if (old_entry_found) {
|
||||
p_dev_rec = p_dev_old_rec;
|
||||
if (malloc_new_entry) {
|
||||
osi_free(p_dev_new_rec);
|
||||
}
|
||||
} else {
|
||||
if (malloc_new_entry) {
|
||||
list_append(btm_cb.p_sec_dev_rec_list, p_dev_new_rec);
|
||||
}
|
||||
p_dev_rec = p_dev_new_rec;
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
/* Check with the BT manager if details about remote device are known */
|
||||
/* outgoing connection */
|
||||
if ((p_inq_info = BTM_InqDbRead(bd_addr)) != NULL) {
|
||||
memcpy (p_dev_rec->dev_class, p_inq_info->results.dev_class, DEV_CLASS_LEN);
|
||||
|
||||
#if BLE_INCLUDED == TRUE
|
||||
p_dev_rec->device_type = p_inq_info->results.device_type;
|
||||
p_dev_rec->ble.ble_addr_type = p_inq_info->results.ble_addr_type;
|
||||
|
||||
/* update conn params, use default value for background connection params */
|
||||
memset(&p_dev_rec->conn_params, 0xff, sizeof(tBTM_LE_CONN_PRAMS));
|
||||
#endif
|
||||
} else {
|
||||
#if BLE_INCLUDED == TRUE
|
||||
/* update conn params, use default value for background connection params */
|
||||
memset(&p_dev_rec->conn_params, 0xff, sizeof(tBTM_LE_CONN_PRAMS));
|
||||
#endif
|
||||
|
||||
if (!memcmp (bd_addr, btm_cb.connecting_bda, BD_ADDR_LEN)) {
|
||||
memcpy (p_dev_rec->dev_class, btm_cb.connecting_dc, DEV_CLASS_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy (p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN);
|
||||
|
||||
#if BLE_INCLUDED == TRUE
|
||||
p_dev_rec->ble_hci_handle = BTM_GetHCIConnHandle (bd_addr, BT_TRANSPORT_LE);
|
||||
#endif
|
||||
p_dev_rec->hci_handle = BTM_GetHCIConnHandle (bd_addr, BT_TRANSPORT_BR_EDR);
|
||||
p_dev_rec->timestamp = btm_cb.dev_rec_count++;
|
||||
|
||||
return (p_dev_rec);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_sec_free_dev
|
||||
**
|
||||
** Description Mark device record as not used
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_sec_free_dev (tBTM_SEC_DEV_REC *p_dev_rec, tBT_TRANSPORT transport)
|
||||
{
|
||||
if (transport == BT_TRANSPORT_BR_EDR) {
|
||||
memset(p_dev_rec->link_key, 0, LINK_KEY_LEN);
|
||||
p_dev_rec->sec_flags &= ~(BTM_SEC_AUTHORIZED | BTM_SEC_AUTHENTICATED
|
||||
| BTM_SEC_ENCRYPTED | BTM_SEC_NAME_KNOWN
|
||||
| BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LINK_KEY_AUTHED
|
||||
| BTM_SEC_ROLE_SWITCHED | BTM_SEC_16_DIGIT_PIN_AUTHED);
|
||||
} else if (transport == BT_TRANSPORT_LE) {
|
||||
p_dev_rec->bond_type = BOND_TYPE_UNKNOWN;
|
||||
p_dev_rec->sec_flags &= ~(BTM_SEC_LE_AUTHENTICATED | BTM_SEC_LE_ENCRYPTED
|
||||
| BTM_SEC_LE_NAME_KNOWN | BTM_SEC_LE_LINK_KEY_KNOWN
|
||||
| BTM_SEC_LE_LINK_KEY_AUTHED | BTM_SEC_ROLE_SWITCHED);
|
||||
#if BLE_INCLUDED == TRUE
|
||||
/* Clear out any saved BLE keys */
|
||||
btm_sec_clear_ble_keys (p_dev_rec);
|
||||
#endif
|
||||
} else {
|
||||
p_dev_rec->bond_type = BOND_TYPE_UNKNOWN;
|
||||
memset(p_dev_rec->link_key, 0, LINK_KEY_LEN);
|
||||
p_dev_rec->sec_flags = 0;
|
||||
|
||||
#if BLE_INCLUDED == TRUE
|
||||
/* Clear out any saved BLE keys */
|
||||
btm_sec_clear_ble_keys (p_dev_rec);
|
||||
#endif
|
||||
}
|
||||
/* No BLE keys and BT keys, clear the sec_flags */
|
||||
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);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_dev_support_switch
|
||||
**
|
||||
** Description This function is called by the L2CAP to check if remote
|
||||
** device supports role switch
|
||||
**
|
||||
** Parameters: bd_addr - Address of the peer device
|
||||
**
|
||||
** Returns TRUE if device is known and role switch is supported
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN btm_dev_support_switch (BD_ADDR bd_addr)
|
||||
{
|
||||
tBTM_SEC_DEV_REC *p_dev_rec;
|
||||
UINT8 xx;
|
||||
BOOLEAN feature_empty = TRUE;
|
||||
|
||||
#if BTM_SCO_INCLUDED == TRUE
|
||||
/* Role switch is not allowed if a SCO is up */
|
||||
if (btm_is_sco_active_by_bdaddr(bd_addr)) {
|
||||
return (FALSE);
|
||||
}
|
||||
#endif
|
||||
p_dev_rec = btm_find_dev (bd_addr);
|
||||
if (p_dev_rec && controller_get_interface()->supports_master_slave_role_switch()) {
|
||||
if (HCI_SWITCH_SUPPORTED(p_dev_rec->features[HCI_EXT_FEATURES_PAGE_0])) {
|
||||
BTM_TRACE_DEBUG("btm_dev_support_switch return TRUE (feature found)\n");
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/* If the feature field is all zero, we never received them */
|
||||
for (xx = 0 ; xx < BD_FEATURES_LEN ; xx++) {
|
||||
if (p_dev_rec->features[HCI_EXT_FEATURES_PAGE_0][xx] != 0x00) {
|
||||
feature_empty = FALSE; /* at least one is != 0 */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we don't know peer's capabilities, assume it supports Role-switch */
|
||||
if (feature_empty) {
|
||||
BTM_TRACE_DEBUG("btm_dev_support_switch return TRUE (feature empty)\n");
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
BTM_TRACE_DEBUG("btm_dev_support_switch return FALSE\n");
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_find_dev_by_handle
|
||||
**
|
||||
** Description Look for the record in the device database for the record
|
||||
** with specified handle
|
||||
**
|
||||
** Returns Pointer to the record or NULL
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_SEC_DEV_REC *btm_find_dev_by_handle (UINT16 handle)
|
||||
{
|
||||
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;
|
||||
|
||||
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 (p_dev_rec);
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_find_dev
|
||||
**
|
||||
** Description Look for the record in the device database for the record
|
||||
** with specified BD address
|
||||
**
|
||||
** Returns Pointer to the record or NULL
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_SEC_DEV_REC *btm_find_dev(BD_ADDR bd_addr)
|
||||
{
|
||||
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
|
||||
**
|
||||
** Description combine security records if identified as same peer
|
||||
**
|
||||
** Returns none
|
||||
**
|
||||
*******************************************************************************/
|
||||
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 = NULL;
|
||||
tBTM_SEC_DEV_REC temp_rec = *p_target_rec;
|
||||
list_node_t *p_node = NULL;
|
||||
BTM_TRACE_DEBUG("%s\n", __func__);
|
||||
|
||||
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));
|
||||
p_target_rec->ble = temp_rec.ble;
|
||||
p_target_rec->ble_hci_handle = temp_rec.ble_hci_handle;
|
||||
p_target_rec->enc_key_size = temp_rec.enc_key_size;
|
||||
p_target_rec->conn_params = temp_rec.conn_params;
|
||||
p_target_rec->device_type |= temp_rec.device_type;
|
||||
p_target_rec->sec_flags |= temp_rec.sec_flags;
|
||||
|
||||
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;
|
||||
/* Remove the unused device from the list */
|
||||
list_remove(btm_cb.p_sec_dev_rec_list, p_dev_rec);
|
||||
break;
|
||||
}
|
||||
|
||||
/* an RPA device entry is a duplicate of the target record */
|
||||
if (btm_ble_addr_resolvable(p_dev_rec->bd_addr, 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;
|
||||
/* Remove the unused device from the list */
|
||||
list_remove(btm_cb.p_sec_dev_rec_list, p_dev_rec);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_find_or_alloc_dev
|
||||
**
|
||||
** Description Look for the record in the device database for the record
|
||||
** with specified BD address
|
||||
**
|
||||
** Returns Pointer to the record or NULL
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_SEC_DEV_REC *btm_find_or_alloc_dev (BD_ADDR bd_addr)
|
||||
{
|
||||
tBTM_SEC_DEV_REC *p_dev_rec;
|
||||
BTM_TRACE_EVENT ("btm_find_or_alloc_dev\n");
|
||||
if ((p_dev_rec = btm_find_dev (bd_addr)) == NULL) {
|
||||
|
||||
/* Allocate a new device record or reuse the oldest one */
|
||||
p_dev_rec = btm_sec_alloc_dev (bd_addr);
|
||||
}
|
||||
return (p_dev_rec);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_find_oldest_dev
|
||||
**
|
||||
** Description Locates the oldest device in use. It first looks for
|
||||
** the oldest non-paired device. If all devices are paired it
|
||||
** deletes the oldest paired device.
|
||||
**
|
||||
** Returns Pointer to the record or NULL
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_SEC_DEV_REC *btm_find_oldest_dev (void)
|
||||
{
|
||||
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 (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 */
|
||||
}
|
||||
|
||||
if (p_dev_rec->timestamp < ot) {
|
||||
p_oldest = p_dev_rec;
|
||||
ot = p_dev_rec->timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
if (ot != 0xFFFFFFFF) {
|
||||
return (p_oldest);
|
||||
}
|
||||
|
||||
/* All devices are paired; find the oldest */
|
||||
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;
|
||||
}
|
||||
|
||||
if (p_dev_rec->timestamp < ot) {
|
||||
p_oldest = p_dev_rec;
|
||||
ot = p_dev_rec->timestamp;
|
||||
}
|
||||
}
|
||||
return (p_oldest);
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_get_bond_type_dev
|
||||
**
|
||||
** Description Get the bond type for a device in the device database
|
||||
** with specified BD address
|
||||
**
|
||||
** Returns The device bond type if known, otherwise BOND_TYPE_UNKNOWN
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_BOND_TYPE btm_get_bond_type_dev(BD_ADDR bd_addr)
|
||||
{
|
||||
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(bd_addr);
|
||||
|
||||
if (p_dev_rec == NULL) {
|
||||
return BOND_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
return p_dev_rec->bond_type;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_set_bond_type_dev
|
||||
**
|
||||
** Description Set the bond type for a device in the device database
|
||||
** with specified BD address
|
||||
**
|
||||
** Returns TRUE on success, otherwise FALSE
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN btm_set_bond_type_dev(BD_ADDR bd_addr, tBTM_BOND_TYPE bond_type)
|
||||
{
|
||||
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(bd_addr);
|
||||
|
||||
if (p_dev_rec == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,152 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2002-2012 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file contains the definition of the btm control block when
|
||||
* BTM_DYNAMIC_MEMORY is used.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "stack/bt_types.h"
|
||||
#include "common/bt_target.h"
|
||||
#include <string.h>
|
||||
#include "btm_int.h"
|
||||
#include "osi/allocator.h"
|
||||
|
||||
/* Global BTM control block structure
|
||||
*/
|
||||
#if BTM_DYNAMIC_MEMORY == FALSE
|
||||
tBTM_CB btm_cb;
|
||||
#else
|
||||
tBTM_CB *btm_cb_ptr;
|
||||
#endif
|
||||
|
||||
#if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
extern void btm_ble_extendadvcb_init(void);
|
||||
extern void btm_ble_advrecod_init(void);
|
||||
#endif
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_init
|
||||
**
|
||||
** Description This function is called at BTM startup to allocate the
|
||||
** control block (if using dynamic memory), and initializes the
|
||||
** tracing level. It then initializes the various components of
|
||||
** btm.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_init (void)
|
||||
{
|
||||
#if BTM_DYNAMIC_MEMORY
|
||||
btm_cb_ptr = (tBTM_CB *)osi_malloc(sizeof(tBTM_CB));
|
||||
#endif /* #if BTM_DYNAMIC_MEMORY */
|
||||
/* All fields are cleared; nonzero fields are reinitialized in appropriate function */
|
||||
memset(&btm_cb, 0, sizeof(tBTM_CB));
|
||||
btm_cb.page_queue = fixed_queue_new(QUEUE_SIZE_MAX);
|
||||
btm_cb.sec_pending_q = fixed_queue_new(QUEUE_SIZE_MAX);
|
||||
|
||||
#if defined(BTM_INITIAL_TRACE_LEVEL)
|
||||
btm_cb.trace_level = BTM_INITIAL_TRACE_LEVEL;
|
||||
#else
|
||||
btm_cb.trace_level = BT_TRACE_LEVEL_NONE;
|
||||
#endif
|
||||
/* Initialize BTM component structures */
|
||||
btm_inq_db_init(); /* Inquiry Database and Structures */
|
||||
btm_acl_init(); /* ACL Database and Structures */
|
||||
#if (SMP_INCLUDED == TRUE)
|
||||
btm_sec_init(BTM_SEC_MODE_SP); /* Security Manager Database and Structures */
|
||||
#endif ///SMP_INCLUDED == TRUE
|
||||
#if BTM_SCO_INCLUDED == TRUE
|
||||
btm_sco_init(); /* SCO Database and Structures (If included) */
|
||||
#endif
|
||||
|
||||
btm_dev_init(); /* Device Manager Structures & HCI_Reset */
|
||||
#if BLE_INCLUDED == TRUE
|
||||
btm_ble_lock_init();
|
||||
btm_ble_sem_init();
|
||||
#endif
|
||||
btm_sec_dev_init();
|
||||
#if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
btm_ble_extendadvcb_init();
|
||||
btm_ble_advrecod_init();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_free
|
||||
**
|
||||
** Description This function is called at btu core free the fixed queue
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
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
|
||||
#if BLE_INCLUDED == TRUE
|
||||
btm_ble_lock_free();
|
||||
btm_ble_sem_free();
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t btm_acl_active_count(void)
|
||||
{
|
||||
list_node_t *p_node = NULL;
|
||||
tACL_CONN *p_acl_conn = NULL;
|
||||
uint8_t count = 0;
|
||||
|
||||
for (p_node = list_begin(btm_cb.p_acl_db_list); p_node; p_node = list_next(p_node)) {
|
||||
p_acl_conn = list_node(p_node);
|
||||
if (p_acl_conn && p_acl_conn->in_use) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
uint8_t btdm_sec_dev_active_count(void)
|
||||
{
|
||||
tBTM_SEC_DEV_REC *p_dev_rec = NULL;
|
||||
list_node_t *p_node = NULL;
|
||||
uint8_t count = 0;
|
||||
|
||||
/* First look for the non-paired devices for the oldest entry */
|
||||
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 && (p_dev_rec->sec_flags & BTM_SEC_IN_USE)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
@@ -0,0 +1,965 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2000-2012 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* This file contains functions that manages ACL link modes.
|
||||
* This includes operations such as active, hold,
|
||||
* park and sniff modes.
|
||||
*
|
||||
* This module contains both internal and external (API)
|
||||
* functions. External (API) functions are distinguishable
|
||||
* by their names beginning with uppercase BTM.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
//#define LOG_TAG "bt_btm_pm"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
//#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "stack/bt_types.h"
|
||||
#include "stack/hcimsgs.h"
|
||||
#include "stack/btu.h"
|
||||
#include "stack/btm_api.h"
|
||||
#include "btm_int.h"
|
||||
#include "l2c_int.h"
|
||||
#include "stack/hcidefs.h"
|
||||
//#include "bt_utils.h"
|
||||
//#include "osi/include/log.h"
|
||||
#include "osi/allocator.h"
|
||||
/*****************************************************************************/
|
||||
/* to handle different modes */
|
||||
/*****************************************************************************/
|
||||
#define BTM_PM_STORED_MASK 0x80 /* set this mask if the command is stored */
|
||||
#define BTM_PM_NUM_SET_MODES 3 /* only hold, sniff & park */
|
||||
|
||||
/* Usage: (ptr_features[ offset ] & mask )?TRUE:FALSE */
|
||||
/* offset to supported feature */
|
||||
const UINT8 btm_pm_mode_off[BTM_PM_NUM_SET_MODES] = {0, 0, 1};
|
||||
/* mask to supported feature */
|
||||
const UINT8 btm_pm_mode_msk[BTM_PM_NUM_SET_MODES] = {0x40, 0x80, 0x01};
|
||||
|
||||
#define BTM_PM_GET_MD1 1
|
||||
#define BTM_PM_GET_MD2 2
|
||||
#define BTM_PM_GET_COMP 3
|
||||
|
||||
const UINT8 btm_pm_md_comp_matrix[BTM_PM_NUM_SET_MODES * BTM_PM_NUM_SET_MODES] = {
|
||||
BTM_PM_GET_COMP,
|
||||
BTM_PM_GET_MD2,
|
||||
BTM_PM_GET_MD2,
|
||||
|
||||
BTM_PM_GET_MD1,
|
||||
BTM_PM_GET_COMP,
|
||||
BTM_PM_GET_MD1,
|
||||
|
||||
BTM_PM_GET_MD1,
|
||||
BTM_PM_GET_MD2,
|
||||
BTM_PM_GET_COMP
|
||||
};
|
||||
|
||||
/* function prototype */
|
||||
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
|
||||
|
||||
/*
|
||||
#ifdef BTM_PM_DEBUG
|
||||
#undef BTM_PM_DEBUG
|
||||
#define BTM_PM_DEBUG TRUE
|
||||
#endif
|
||||
*/
|
||||
|
||||
#if BTM_PM_DEBUG == TRUE
|
||||
const char *btm_pm_state_str[] = {
|
||||
"pm_active_state",
|
||||
"pm_hold_state",
|
||||
"pm_sniff_state",
|
||||
"pm_park_state",
|
||||
"pm_pend_state"
|
||||
};
|
||||
|
||||
const char *btm_pm_event_str[] = {
|
||||
"pm_set_mode_event",
|
||||
"pm_hci_sts_event",
|
||||
"pm_mod_chg_event",
|
||||
"pm_update_event"
|
||||
};
|
||||
|
||||
const char *btm_pm_action_str[] = {
|
||||
"pm_set_mode_action",
|
||||
"pm_update_db_action",
|
||||
"pm_mod_chg_action",
|
||||
"pm_hci_sts_action",
|
||||
"pm_update_action"
|
||||
};
|
||||
#endif // BTM_PM_DEBUG
|
||||
|
||||
/*****************************************************************************/
|
||||
/* P U B L I C F U N C T I O N S */
|
||||
/*****************************************************************************/
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_PmRegister
|
||||
**
|
||||
** Description register or deregister with power manager
|
||||
**
|
||||
** Returns BTM_SUCCESS if successful,
|
||||
** BTM_NO_RESOURCES if no room to hold registration
|
||||
** BTM_ILLEGAL_VALUE
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS BTM_PmRegister (UINT8 mask, UINT8 *p_pm_id, tBTM_PM_STATUS_CBACK *p_cb)
|
||||
{
|
||||
int xx;
|
||||
|
||||
/* de-register */
|
||||
if (mask & BTM_PM_DEREG) {
|
||||
if (*p_pm_id >= BTM_MAX_PM_RECORDS) {
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
btm_cb.pm_reg_db[*p_pm_id].mask = BTM_PM_REC_NOT_USED;
|
||||
return BTM_SUCCESS;
|
||||
}
|
||||
|
||||
for (xx = 0; xx < BTM_MAX_PM_RECORDS; xx++) {
|
||||
/* find an unused entry */
|
||||
if (btm_cb.pm_reg_db[xx].mask == BTM_PM_REC_NOT_USED) {
|
||||
/* if register for notification, should provide callback routine */
|
||||
if (mask & BTM_PM_REG_NOTIF) {
|
||||
if (p_cb == NULL) {
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
btm_cb.pm_reg_db[xx].cback = p_cb;
|
||||
}
|
||||
btm_cb.pm_reg_db[xx].mask = mask;
|
||||
*p_pm_id = xx;
|
||||
return BTM_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return BTM_NO_RESOURCES;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_SetPowerMode
|
||||
**
|
||||
** Description store the mode in control block or
|
||||
** alter ACL connection behavior.
|
||||
**
|
||||
** Returns BTM_SUCCESS if successful,
|
||||
** BTM_UNKNOWN_ADDR if bd addr is not active or bad
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS BTM_SetPowerMode (UINT8 pm_id, BD_ADDR remote_bda, tBTM_PM_PWR_MD *p_mode)
|
||||
{
|
||||
UINT8 *p_features;
|
||||
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;
|
||||
}
|
||||
|
||||
if (p_mode == NULL) {
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
BTM_TRACE_API( "BTM_SetPowerMode: pm_id %d BDA: %08x mode:0x%x", pm_id,
|
||||
(remote_bda[2] << 24) + (remote_bda[3] << 16) + (remote_bda[4] << 8) + remote_bda[5], p_mode->mode);
|
||||
|
||||
/* take out the force bit */
|
||||
mode = p_mode->mode & ~BTM_PM_MD_FORCE;
|
||||
|
||||
p_acl_cb = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR);
|
||||
if (p_acl_cb == NULL){
|
||||
return BTM_UNKNOWN_ADDR;
|
||||
}
|
||||
|
||||
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 */
|
||||
p_features = BTM_ReadLocalFeatures();
|
||||
if ( !(p_features[ btm_pm_mode_off[ind] ] & btm_pm_mode_msk[ind] ) ) {
|
||||
return BTM_MODE_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == p_cb->state) { /* the requested mode is current mode */
|
||||
/* already in the requested mode and the current interval has less latency than the max */
|
||||
if ( (mode == BTM_PM_MD_ACTIVE) ||
|
||||
((p_mode->mode & BTM_PM_MD_FORCE) && (p_mode->max >= p_cb->interval) && (p_mode->min <= p_cb->interval)) ||
|
||||
((p_mode->mode & BTM_PM_MD_FORCE) == 0 && (p_mode->max >= p_cb->interval)) ) {
|
||||
BTM_TRACE_DEBUG( "BTM_SetPowerMode: mode:0x%x interval %d max:%d, min:%d", p_mode->mode, p_cb->interval, p_mode->max, p_mode->min);
|
||||
return BTM_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
temp_pm_id = pm_id;
|
||||
if (pm_id == BTM_PM_SET_ONLY_ID) {
|
||||
temp_pm_id = BTM_MAX_PM_RECORDS;
|
||||
}
|
||||
|
||||
/* 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_hdl != BTM_INVALID_HANDLE)) ) {
|
||||
#if BTM_PM_DEBUG == TRUE
|
||||
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;
|
||||
*(&p_cb->req_mode[temp_pm_id]) = *((tBTM_PM_PWR_MD *)p_mode);
|
||||
p_cb->chg_ind = TRUE;
|
||||
}
|
||||
|
||||
#if BTM_PM_DEBUG == TRUE
|
||||
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_hdl != BTM_INVALID_HANDLE) ||
|
||||
(p_cb->state & BTM_PM_STORED_MASK) ) { /* 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", p_acl_cb->hci_handle);
|
||||
}
|
||||
return BTM_CMD_STORED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return btm_pm_snd_md_req(pm_id, p_acl_cb->hci_handle, p_mode);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_ReadPowerMode
|
||||
**
|
||||
** Description This returns the current mode for a specific
|
||||
** ACL connection.
|
||||
**
|
||||
** Input Param remote_bda - device address of desired ACL connection
|
||||
**
|
||||
** Output Param p_mode - address where the current mode is copied into.
|
||||
** BTM_ACL_MODE_NORMAL
|
||||
** BTM_ACL_MODE_HOLD
|
||||
** BTM_ACL_MODE_SNIFF
|
||||
** BTM_ACL_MODE_PARK
|
||||
** (valid only if return code is BTM_SUCCESS)
|
||||
**
|
||||
** Returns BTM_SUCCESS if successful,
|
||||
** BTM_UNKNOWN_ADDR if bd addr is not active or bad
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS BTM_ReadPowerMode (BD_ADDR remote_bda, tBTM_PM_MODE *p_mode)
|
||||
{
|
||||
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 = p_acl_cb->p_pm_mode_db->state;
|
||||
return BTM_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_SetSsrParams
|
||||
**
|
||||
** Description This sends the given SSR parameters for the given ACL
|
||||
** connection if it is in ACTIVE mode.
|
||||
**
|
||||
** Input Param remote_bda - device address of desired ACL connection
|
||||
** max_lat - maximum latency (in 0.625ms)(0-0xFFFE)
|
||||
** min_rmt_to - minimum remote timeout
|
||||
** min_loc_to - minimum local timeout
|
||||
**
|
||||
**
|
||||
** Returns BTM_SUCCESS if the HCI command is issued successful,
|
||||
** BTM_UNKNOWN_ADDR if bd addr is not active or bad
|
||||
** BTM_CMD_STORED if the command is stored
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS BTM_SetSsrParams (BD_ADDR remote_bda, UINT16 max_lat,
|
||||
UINT16 min_rmt_to, UINT16 min_loc_to)
|
||||
{
|
||||
#if (BTM_SSR_INCLUDED == TRUE)
|
||||
tBTM_PM_MCB *p_cb;
|
||||
tACL_CONN *p_acl_cb = NULL;
|
||||
|
||||
p_acl_cb = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR);
|
||||
if (!p_acl_cb) {
|
||||
return (BTM_UNKNOWN_ADDR);
|
||||
}
|
||||
p_cb = p_acl_cb->p_pm_mode_db;
|
||||
|
||||
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->max_lat = max_lat;
|
||||
p_cb->min_rmt_to = min_rmt_to;
|
||||
p_cb->min_loc_to = min_loc_to;
|
||||
return BTM_CMD_STORED;
|
||||
#else
|
||||
return BTM_ILLEGAL_ACTION;
|
||||
#endif // BTM_SSR_INCLUDED
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_pm_reset
|
||||
**
|
||||
** Description as a part of the BTM reset process.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_pm_reset(void)
|
||||
{
|
||||
int xx;
|
||||
tBTM_PM_STATUS_CBACK *cb = NULL;
|
||||
|
||||
/* clear the pending request for application */
|
||||
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) ) {
|
||||
cb = btm_cb.pm_reg_db[btm_cb.pm_pend_id].cback;
|
||||
}
|
||||
|
||||
|
||||
/* clear the register record */
|
||||
for (xx = 0; xx < BTM_MAX_PM_RECORDS; xx++) {
|
||||
btm_cb.pm_reg_db[xx].mask = BTM_PM_REC_NOT_USED;
|
||||
}
|
||||
|
||||
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_hdl = BTM_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_pm_sm_alloc
|
||||
**
|
||||
** Description This function initializes the control block of an ACL link.
|
||||
** It is called when an ACL connection is created.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_PM_MCB *btm_pm_sm_alloc(void)
|
||||
{
|
||||
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
|
||||
**
|
||||
** Description This function initializes the control block of an ACL link.
|
||||
** It is called when an ACL connection is created.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_pm_compare_modes
|
||||
** Description get the "more active" mode of the 2
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static tBTM_PM_PWR_MD *btm_pm_compare_modes(tBTM_PM_PWR_MD *p_md1, tBTM_PM_PWR_MD *p_md2, tBTM_PM_PWR_MD *p_res)
|
||||
{
|
||||
UINT8 res;
|
||||
|
||||
if (p_md1 == NULL) {
|
||||
*p_res = *p_md2;
|
||||
p_res->mode &= ~BTM_PM_MD_FORCE;
|
||||
|
||||
return p_md2;
|
||||
}
|
||||
|
||||
if (p_md2->mode == BTM_PM_MD_ACTIVE || p_md1->mode == BTM_PM_MD_ACTIVE) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* check if force bit is involved */
|
||||
if (p_md1->mode & BTM_PM_MD_FORCE) {
|
||||
*p_res = *p_md1;
|
||||
p_res->mode &= ~BTM_PM_MD_FORCE;
|
||||
return p_res;
|
||||
}
|
||||
|
||||
if (p_md2->mode & BTM_PM_MD_FORCE) {
|
||||
*p_res = *p_md2;
|
||||
p_res->mode &= ~BTM_PM_MD_FORCE;
|
||||
return p_res;
|
||||
}
|
||||
|
||||
res = (p_md1->mode - 1) * BTM_PM_NUM_SET_MODES + (p_md2->mode - 1);
|
||||
res = btm_pm_md_comp_matrix[res];
|
||||
switch (res) {
|
||||
case BTM_PM_GET_MD1:
|
||||
*p_res = *p_md1;
|
||||
return p_md1;
|
||||
|
||||
case BTM_PM_GET_MD2:
|
||||
*p_res = *p_md2;
|
||||
return p_md2;
|
||||
|
||||
case BTM_PM_GET_COMP:
|
||||
p_res->mode = p_md1->mode;
|
||||
/* min of the two */
|
||||
p_res->max = (p_md1->max < p_md2->max) ? (p_md1->max) : (p_md2->max);
|
||||
/* max of the two */
|
||||
p_res->min = (p_md1->min > p_md2->min) ? (p_md1->min) : (p_md2->min);
|
||||
|
||||
/* the intersection is NULL */
|
||||
if ( p_res->max < p_res->min) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (p_res->mode == BTM_PM_MD_SNIFF) {
|
||||
/* max of the two */
|
||||
p_res->attempt = (p_md1->attempt > p_md2->attempt) ? (p_md1->attempt) : (p_md2->attempt);
|
||||
p_res->timeout = (p_md1->timeout > p_md2->timeout) ? (p_md1->timeout) : (p_md2->timeout);
|
||||
}
|
||||
return p_res;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_pm_get_set_mode
|
||||
** Description get the resulting mode from the registered parties, then compare it
|
||||
** with the requested mode, if the command is from an unregistered party.
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static tBTM_PM_MODE btm_pm_get_set_mode(UINT8 pm_id, tBTM_PM_MCB *p_cb, tBTM_PM_PWR_MD *p_mode, tBTM_PM_PWR_MD *p_res)
|
||||
{
|
||||
int xx, loop_max;
|
||||
tBTM_PM_PWR_MD *p_md = NULL;
|
||||
|
||||
if (p_mode != NULL && p_mode->mode & BTM_PM_MD_FORCE) {
|
||||
*p_res = *p_mode;
|
||||
p_res->mode &= ~BTM_PM_MD_FORCE;
|
||||
return p_res->mode;
|
||||
}
|
||||
|
||||
if (!p_mode) {
|
||||
loop_max = BTM_MAX_PM_RECORDS + 1;
|
||||
} else {
|
||||
loop_max = BTM_MAX_PM_RECORDS;
|
||||
}
|
||||
|
||||
for ( xx = 0; xx < loop_max; xx++) {
|
||||
/* g through all the registered "set" parties */
|
||||
if (btm_cb.pm_reg_db[xx].mask & BTM_PM_REG_SET) {
|
||||
if (p_cb->req_mode[xx].mode == BTM_PM_MD_ACTIVE) {
|
||||
/* if at least one registered (SET) party says ACTIVE, stay active */
|
||||
return BTM_PM_MD_ACTIVE;
|
||||
} else {
|
||||
/* if registered parties give conflicting information, stay active */
|
||||
if ( (btm_pm_compare_modes(p_md, &p_cb->req_mode[xx], p_res)) == NULL) {
|
||||
return BTM_PM_MD_ACTIVE;
|
||||
}
|
||||
p_md = p_res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if the resulting mode is NULL(nobody registers SET), use the requested mode */
|
||||
if (p_md == NULL) {
|
||||
if (p_mode) {
|
||||
*p_res = *((tBTM_PM_PWR_MD *)p_mode);
|
||||
} else { /* p_mode is NULL when btm_pm_snd_md_req is called from btm_pm_proc_mode_change */
|
||||
return BTM_PM_MD_ACTIVE;
|
||||
}
|
||||
} else {
|
||||
/* if the command is from unregistered party,
|
||||
compare the resulting mode from registered party*/
|
||||
if ( (pm_id == BTM_PM_SET_ONLY_ID) &&
|
||||
((btm_pm_compare_modes(p_mode, p_md, p_res)) == NULL) ) {
|
||||
return BTM_PM_MD_ACTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
return p_res->mode;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_pm_snd_md_req
|
||||
** Description get the resulting mode and send the resuest to host controller
|
||||
** Returns tBTM_STATUS
|
||||
**, BOOLEAN *p_chg_ind
|
||||
*******************************************************************************/
|
||||
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;
|
||||
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_hdl:%d, mode: %d",
|
||||
link_hdl, mode);
|
||||
#endif // BTM_PM_DEBUG
|
||||
|
||||
if ( p_cb->state == mode) {
|
||||
/* already in the resulting mode */
|
||||
if ( (mode == BTM_PM_MD_ACTIVE) ||
|
||||
((md_res.max >= p_cb->interval) && (md_res.min <= p_cb->interval)) ) {
|
||||
return BTM_CMD_STORED;
|
||||
}
|
||||
/* Otherwise, needs to wake, then sleep */
|
||||
chg_ind = TRUE;
|
||||
}
|
||||
p_cb->chg_ind = chg_ind;
|
||||
|
||||
/* cannot go directly from current mode to resulting mode. */
|
||||
if ( mode != BTM_PM_MD_ACTIVE && p_cb->state != BTM_PM_MD_ACTIVE) {
|
||||
p_cb->chg_ind = TRUE; /* needs to wake, then sleep */
|
||||
}
|
||||
|
||||
if (p_cb->chg_ind == TRUE) { /* needs to wake first */
|
||||
md_res.mode = BTM_PM_MD_ACTIVE;
|
||||
}
|
||||
#if (BTM_SSR_INCLUDED == TRUE)
|
||||
else if (BTM_PM_MD_SNIFF == md_res.mode && 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_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_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));
|
||||
switch (md_res.mode) {
|
||||
case BTM_PM_MD_ACTIVE:
|
||||
switch (p_cb->state) {
|
||||
case BTM_PM_MD_SNIFF:
|
||||
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(link_hdl)) {
|
||||
btm_cb.pm_pend_link_hdl = link_hdl;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Failure btm_cb.pm_pend_link = MAX_L2CAP_LINKS */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case BTM_PM_MD_HOLD:
|
||||
if (btsnd_hcic_hold_mode (link_hdl,
|
||||
md_res.max, md_res.min)) {
|
||||
btm_cb.pm_pend_link_hdl = link_hdl;
|
||||
}
|
||||
break;
|
||||
|
||||
case BTM_PM_MD_SNIFF:
|
||||
if (btsnd_hcic_sniff_mode (link_hdl,
|
||||
md_res.max, md_res.min, md_res.attempt,
|
||||
md_res.timeout)) {
|
||||
btm_cb.pm_pend_link_hdl = link_hdl;
|
||||
}
|
||||
break;
|
||||
|
||||
case BTM_PM_MD_PARK:
|
||||
if (btsnd_hcic_park_mode (link_hdl,
|
||||
md_res.max, md_res.min)) {
|
||||
btm_cb.pm_pend_link_hdl = link_hdl;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Failure btm_cb.pm_pend_link = MAX_L2CAP_LINKS */
|
||||
break;
|
||||
}
|
||||
|
||||
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_hdl: %d", btm_cb.pm_pend_link_hdl);
|
||||
#endif // BTM_PM_DEBUG
|
||||
return (BTM_NO_RESOURCES);
|
||||
}
|
||||
|
||||
return BTM_CMD_STARTED;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_pm_check_stored
|
||||
**
|
||||
** Description This function is called when an HCI command status event occurs
|
||||
** to check if there's any PM command issued while waiting for
|
||||
** HCI command status.
|
||||
**
|
||||
** Returns none.
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void btm_pm_check_stored(void)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_pm_proc_cmd_status
|
||||
**
|
||||
** Description This function is called when an HCI command status event occurs
|
||||
** for power manager related commands.
|
||||
**
|
||||
** Input Parms status - status of the event (HCI_SUCCESS if no errors)
|
||||
**
|
||||
** Returns none.
|
||||
**
|
||||
*******************************************************************************/
|
||||
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_hdl == BTM_INVALID_HANDLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
p_acl_cb = btm_handle_to_acl(btm_cb.pm_pend_link_hdl);
|
||||
if (p_acl_cb == NULL) {
|
||||
return;
|
||||
}
|
||||
p_cb = p_acl_cb->p_pm_mode_db;
|
||||
|
||||
if (status == HCI_SUCCESS) {
|
||||
p_cb->state = BTM_PM_ST_PENDING;
|
||||
pm_status = BTM_PM_STS_PENDING;
|
||||
#if BTM_PM_DEBUG == TRUE
|
||||
BTM_TRACE_DEBUG( "btm_pm_proc_cmd_status new state:0x%x", p_cb->state);
|
||||
#endif // BTM_PM_DEBUG
|
||||
} else { /* the command was not successfull. Stay in the same state */
|
||||
pm_status = BTM_PM_STS_ERROR;
|
||||
}
|
||||
|
||||
/* 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)(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_hdl, MAX_L2CAP_LINKS);
|
||||
#endif // BTM_PM_DEBUG
|
||||
btm_cb.pm_pend_link_hdl = BTM_INVALID_HANDLE;
|
||||
|
||||
btm_pm_check_stored();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_process_mode_change
|
||||
**
|
||||
** Description This function is called when an HCI mode change event occurs.
|
||||
**
|
||||
** Input Parms hci_status - status of the event (HCI_SUCCESS if no errors)
|
||||
** hci_handle - connection handle associated with the change
|
||||
** mode - HCI_MODE_ACTIVE, HCI_MODE_HOLD, HCI_MODE_SNIFF, or HCI_MODE_PARK
|
||||
** interval - number of baseband slots (meaning depends on mode)
|
||||
**
|
||||
** Returns none.
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_pm_proc_mode_change (UINT8 hci_status, UINT16 hci_handle, UINT8 mode, UINT16 interval)
|
||||
{
|
||||
tACL_CONN *p;
|
||||
tBTM_PM_MCB *p_cb = NULL;
|
||||
int yy;
|
||||
tBTM_PM_STATE old_state;
|
||||
tL2C_LCB *p_lcb;
|
||||
|
||||
/* get the index to acl_db */
|
||||
p = btm_handle_to_acl(hci_handle);
|
||||
if (!p) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* update control block */
|
||||
p_cb = p->p_pm_mode_db;
|
||||
old_state = p_cb->state;
|
||||
p_cb->state = mode;
|
||||
p_cb->interval = interval;
|
||||
|
||||
BTM_TRACE_DEBUG("%s switched from %s to %s.", __func__, mode_to_string(old_state), mode_to_string(p_cb->state));
|
||||
|
||||
if ((p_lcb = l2cu_find_lcb_by_bd_addr(p->remote_addr, BT_TRANSPORT_BR_EDR)) != NULL) {
|
||||
if ((p_cb->state == BTM_PM_ST_ACTIVE) || (p_cb->state == BTM_PM_ST_SNIFF)) {
|
||||
/* There might be any pending packets due to SNIFF or PENDING state */
|
||||
/* Trigger L2C to start transmission of the pending packets. */
|
||||
BTM_TRACE_DEBUG("btm mode change to active; check l2c_link for outgoing packets");
|
||||
l2c_link_check_send_pkts(p_lcb, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* notify registered parties */
|
||||
for (yy = 0; yy <= BTM_MAX_PM_RECORDS; yy++) {
|
||||
/* set req_mode HOLD mode->ACTIVE */
|
||||
if ( (mode == BTM_PM_MD_ACTIVE) && (p_cb->req_mode[yy].mode == BTM_PM_MD_HOLD) ) {
|
||||
p_cb->req_mode[yy].mode = BTM_PM_MD_ACTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
/* new request has been made. - post a message to BTU task */
|
||||
if (old_state & BTM_PM_STORED_MASK) {
|
||||
#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, hci_handle, NULL);
|
||||
} else {
|
||||
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, hci_handle, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* notify registered parties */
|
||||
for (yy = 0; yy < BTM_MAX_PM_RECORDS; yy++) {
|
||||
if (btm_cb.pm_reg_db[yy].mask & BTM_PM_REG_NOTIF) {
|
||||
(*btm_cb.pm_reg_db[yy].cback)( p->remote_addr, mode, interval, hci_status);
|
||||
}
|
||||
}
|
||||
|
||||
/* If mode change was because of an active role switch or change link key */
|
||||
btm_cont_rswitch(p, btm_find_dev(p->remote_addr), hci_status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_pm_proc_ssr_evt
|
||||
**
|
||||
** Description This function is called when an HCI sniff subrating event occurs.
|
||||
**
|
||||
** Returns none.
|
||||
**
|
||||
*******************************************************************************/
|
||||
#if (BTM_SSR_INCLUDED == TRUE)
|
||||
void btm_pm_proc_ssr_evt (UINT8 *p, UINT16 evt_len)
|
||||
{
|
||||
UINT8 status;
|
||||
UINT16 handle;
|
||||
UINT16 max_rx_lat;
|
||||
int xx;
|
||||
tBTM_PM_MCB *p_cb;
|
||||
tACL_CONN *p_acl = NULL;
|
||||
UINT16 use_ssr = TRUE;
|
||||
UNUSED(evt_len);
|
||||
|
||||
STREAM_TO_UINT8 (status, p);
|
||||
|
||||
STREAM_TO_UINT16 (handle, p);
|
||||
/* get the index to acl_db */
|
||||
|
||||
p += 2;
|
||||
STREAM_TO_UINT16 (max_rx_lat, p);
|
||||
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;
|
||||
}
|
||||
|
||||
/* notify registered parties */
|
||||
for (xx = 0; xx < BTM_MAX_PM_RECORDS; xx++) {
|
||||
if (btm_cb.pm_reg_db[xx].mask & BTM_PM_REG_NOTIF) {
|
||||
if ( p_acl) {
|
||||
(*btm_cb.pm_reg_db[xx].cback)( p_acl->remote_addr, BTM_PM_STS_SSR, use_ssr, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // BTM_SSR_INCLUDED
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_pm_device_in_active_or_sniff_mode
|
||||
**
|
||||
** Description This function is called to check if in active or sniff mode
|
||||
**
|
||||
** Returns TRUE, if in active or sniff mode
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN btm_pm_device_in_active_or_sniff_mode(void)
|
||||
{
|
||||
/* The active state is the highest state-includes connected device and sniff mode*/
|
||||
|
||||
/* Covers active and sniff modes */
|
||||
if (BTM_GetNumAclLinks() > 0) {
|
||||
BTM_TRACE_DEBUG("%s - ACL links: %d", __func__, BTM_GetNumAclLinks());
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
|
||||
/* Check BLE states */
|
||||
if (btm_ble_get_conn_st() != BLE_CONN_IDLE) {
|
||||
BTM_TRACE_DEBUG("%s - BLE state: %x", __func__, btm_ble_get_conn_st());
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_pm_device_in_scan_state
|
||||
**
|
||||
** Description This function is called to check if in paging, inquiry or connecting mode
|
||||
**
|
||||
** Returns TRUE, if in paging, inquiry or connecting mode
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN btm_pm_device_in_scan_state(void)
|
||||
{
|
||||
/* Scan state-paging, inquiry, and trying to connect */
|
||||
|
||||
/* Check for paging */
|
||||
if (btm_cb.is_paging || (!fixed_queue_is_empty(btm_cb.page_queue)) ||
|
||||
BTM_BL_PAGING_STARTED == btm_cb.busy_level) {
|
||||
BTM_TRACE_DEBUG("btm_pm_device_in_scan_state- paging");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Check for inquiry */
|
||||
if ((btm_cb.btm_inq_vars.inq_active & (BTM_BR_INQ_ACTIVE_MASK | BTM_BLE_INQ_ACTIVE_MASK)) != 0) {
|
||||
BTM_TRACE_DEBUG("btm_pm_device_in_scan_state- Inq active");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_PM_ReadControllerState
|
||||
**
|
||||
** Description This function is called to obtain the controller state
|
||||
**
|
||||
** Returns Controller State-BTM_CONTRL_ACTIVE, BTM_CONTRL_SCAN, and BTM_CONTRL_IDLE
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_CONTRL_STATE BTM_PM_ReadControllerState(void)
|
||||
{
|
||||
if (TRUE == btm_pm_device_in_active_or_sniff_mode()) {
|
||||
return BTM_CONTRL_ACTIVE;
|
||||
} else if (TRUE == btm_pm_device_in_scan_state()) {
|
||||
return BTM_CONTRL_SCAN;
|
||||
} else {
|
||||
return BTM_CONTRL_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
#if (!CONFIG_BT_STACK_NO_LOG)
|
||||
static const char *mode_to_string(tBTM_PM_MODE mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case BTM_PM_MD_ACTIVE: return "ACTIVE";
|
||||
case BTM_PM_MD_SNIFF: return "SNIFF";
|
||||
case BTM_PM_MD_PARK: return "PARK";
|
||||
case BTM_PM_MD_HOLD: return "HOLD";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,548 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2012 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* this file contains the main Bluetooth Manager (BTM) internal
|
||||
* definitions.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef BTM_BLE_INT_H
|
||||
#define BTM_BLE_INT_H
|
||||
|
||||
#include "common/bt_target.h"
|
||||
#include "osi/fixed_queue.h"
|
||||
#include "osi/pkt_queue.h"
|
||||
#include "osi/thread.h"
|
||||
#include "stack/hcidefs.h"
|
||||
#include "stack/btm_ble_api.h"
|
||||
#include "btm_int.h"
|
||||
|
||||
#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
|
||||
#include "stack/smp_api.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* scanning enable status */
|
||||
#define BTM_BLE_SCAN_ENABLE 0x01
|
||||
#define BTM_BLE_SCAN_DISABLE 0x00
|
||||
|
||||
/* advertising enable status */
|
||||
#define BTM_BLE_ADV_ENABLE 0x01
|
||||
#define BTM_BLE_ADV_DISABLE 0x00
|
||||
|
||||
/* use the high 4 bits unused by inquiry mode */
|
||||
#define BTM_BLE_SELECT_SCAN 0x20
|
||||
#define BTM_BLE_NAME_REQUEST 0x40
|
||||
#define BTM_BLE_OBSERVE 0x80
|
||||
|
||||
#define BTM_BLE_MAX_WL_ENTRY 1
|
||||
#define BTM_BLE_AD_DATA_LEN 31
|
||||
|
||||
#define BTM_BLE_ENC_MASK 0x03
|
||||
|
||||
#define BTM_BLE_DUPLICATE_DISABLE 0
|
||||
#define BTM_BLE_DUPLICATE_ENABLE 1
|
||||
#define BTM_BLE_DUPLICATE_MAX BTM_BLE_DUPLICATE_ENABLE
|
||||
|
||||
#define BTM_BLE_GAP_DISC_SCAN_INT 18 /* Interval(scan_int) = 11.25 ms= 0x0010 * 0.625 ms */
|
||||
#define BTM_BLE_GAP_DISC_SCAN_WIN 18 /* scan_window = 11.25 ms= 0x0010 * 0.625 ms */
|
||||
#define BTM_BLE_GAP_ADV_INT 512 /* Tgap(gen_disc) = 1.28 s= 512 * 0.625 ms */
|
||||
#define BTM_BLE_GAP_LIM_TOUT 180 /* Tgap(lim_timeout) = 180s max */
|
||||
#define BTM_BLE_LOW_LATENCY_SCAN_INT 8000 /* Interval(scan_int) = 5s= 8000 * 0.625 ms */
|
||||
#define BTM_BLE_LOW_LATENCY_SCAN_WIN 8000 /* scan_window = 5s= 8000 * 0.625 ms */
|
||||
|
||||
|
||||
#define BTM_BLE_GAP_ADV_FAST_INT_1 48 /* TGAP(adv_fast_interval1) = 30(used) ~ 60 ms = 48 *0.625 */
|
||||
#define BTM_BLE_GAP_ADV_FAST_INT_2 160 /* TGAP(adv_fast_interval2) = 100(used) ~ 150 ms = 160 * 0.625 ms */
|
||||
#define BTM_BLE_GAP_ADV_SLOW_INT 2048 /* Tgap(adv_slow_interval) = 1.28 s= 512 * 0.625 ms */
|
||||
#define BTM_BLE_GAP_ADV_DIR_MAX_INT 800 /* Tgap(dir_conn_adv_int_max) = 500 ms = 800 * 0.625 ms */
|
||||
#define BTM_BLE_GAP_ADV_DIR_MIN_INT 400 /* Tgap(dir_conn_adv_int_min) = 250 ms = 400 * 0.625 ms */
|
||||
|
||||
#define BTM_BLE_GAP_FAST_ADV_TOUT 30
|
||||
|
||||
#define BTM_BLE_SEC_REQ_ACT_NONE 0
|
||||
#define BTM_BLE_SEC_REQ_ACT_ENCRYPT 1 /* encrypt the link using current key or key refresh */
|
||||
#define BTM_BLE_SEC_REQ_ACT_PAIR 2
|
||||
#define BTM_BLE_SEC_REQ_ACT_DISCARD 3 /* discard the sec request while encryption is started but not completed */
|
||||
typedef UINT8 tBTM_BLE_SEC_REQ_ACT;
|
||||
|
||||
#define BLE_STATIC_PRIVATE_MSB_MASK 0x3f
|
||||
#define BLE_NON_RESOLVE_ADDR_MSB 0x00 /* most significant bit, bit7, bit6 is 00 to be non-resolvable random */
|
||||
#define BLE_RESOLVE_ADDR_MSB 0x40 /* most significant bit, bit7, bit6 is 01 to be resolvable random */
|
||||
#define BLE_RESOLVE_ADDR_MASK 0xc0 /* bit 6, and bit7 */
|
||||
#define BTM_BLE_IS_NON_RESLVE_BDA(x) ((x[0] & BLE_RESOLVE_ADDR_MASK) == BLE_NON_RESOLVE_ADDR_MSB)
|
||||
#define BTM_BLE_IS_RESOLVE_BDA(x) ((x[0] & BLE_RESOLVE_ADDR_MASK) == BLE_RESOLVE_ADDR_MSB)
|
||||
|
||||
/* LE scan activity bit mask, continue with LE inquiry bits */
|
||||
#define BTM_LE_SELECT_CONN_ACTIVE 0x0040 /* selection connection is in progress */
|
||||
#define BTM_LE_OBSERVE_ACTIVE 0x0080 /* observe is in progress */
|
||||
#define BTM_LE_DISCOVER_ACTIVE 0x0100 /* scan is in progress */
|
||||
|
||||
/* BLE scan activity mask checking */
|
||||
#define BTM_BLE_IS_SCAN_ACTIVE(x) ((x) & BTM_BLE_SCAN_ACTIVE_MASK)
|
||||
#define BTM_BLE_IS_INQ_ACTIVE(x) ((x) & BTM_BLE_INQUIRY_MASK)
|
||||
#define BTM_BLE_IS_OBS_ACTIVE(x) ((x) & BTM_LE_OBSERVE_ACTIVE)
|
||||
#define BTM_BLE_IS_DISCO_ACTIVE(x) ((x) & BTM_LE_DISCOVER_ACTIVE)
|
||||
#define BTM_BLE_IS_SEL_CONN_ACTIVE(x) ((x) & BTM_LE_SELECT_CONN_ACTIVE)
|
||||
|
||||
/* BLE ADDR type ID bit */
|
||||
#define BLE_ADDR_TYPE_ID_BIT 0x02
|
||||
|
||||
#define BTM_VSC_CHIP_CAPABILITY_L_VERSION 55
|
||||
#define BTM_VSC_CHIP_CAPABILITY_M_VERSION 95
|
||||
|
||||
typedef enum {
|
||||
BTM_BLE_IDLE = 0,
|
||||
BTM_BLE_SCANNING = 1,
|
||||
BTM_BLE_ADVERTISING = 2,
|
||||
}tBTM_BLE_GAP_STATE;
|
||||
|
||||
typedef struct {
|
||||
UINT16 data_mask;
|
||||
UINT8 *p_flags;
|
||||
UINT8 ad_data[BTM_BLE_AD_DATA_LEN];
|
||||
UINT8 *p_pad;
|
||||
} tBTM_BLE_LOCAL_ADV_DATA;
|
||||
|
||||
typedef struct {
|
||||
UINT32 inq_count; /* Used for determining if a response has already been */
|
||||
/* received for the current inquiry operation. (We do not */
|
||||
/* want to flood the caller with multiple responses from */
|
||||
/* the same device. */
|
||||
BOOLEAN scan_rsp;
|
||||
tBLE_BD_ADDR le_bda;
|
||||
} tINQ_LE_BDADDR;
|
||||
|
||||
#define BTM_BLE_ADV_DATA_LEN_MAX 31
|
||||
#define BTM_BLE_CACHE_ADV_DATA_MAX 62
|
||||
#if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
#define BTM_BLE_EXT_ADV_DATA_LEN_MAX 251
|
||||
#define BTM_BLE_PERIODIC_ADV_DATA_LEN_MAX 252
|
||||
|
||||
#define BTM_BLE_ADV_DATA_OP_INTERMEDIATE_FRAG 0
|
||||
#define BTM_BLE_ADV_DATA_OP_FIRST_FRAG 1
|
||||
#define BTM_BLE_ADV_DATA_OP_LAST_FRAG 2
|
||||
#define BTM_BLE_ADV_DATA_OP_COMPLETE 3
|
||||
#define BTM_BLE_ADV_DATA_OP_UNCHANGED_DATA 4
|
||||
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
|
||||
#define BTM_BLE_ISVALID_PARAM(x, min, max) (((x) >= (min) && (x) <= (max)) || ((x) == BTM_BLE_CONN_PARAM_UNDEF))
|
||||
|
||||
typedef struct {
|
||||
UINT16 discoverable_mode;
|
||||
UINT16 connectable_mode;
|
||||
BOOLEAN scan_params_set;
|
||||
UINT32 scan_window;
|
||||
UINT32 scan_interval;
|
||||
UINT8 scan_type; /* current scan type: active or passive */
|
||||
UINT8 scan_duplicate_filter; /* duplicate filter enabled for scan */
|
||||
UINT16 adv_interval_min;
|
||||
UINT16 adv_interval_max;
|
||||
tBTM_BLE_AFP afp; /* advertising filter policy */
|
||||
tBTM_BLE_SFP sfp; /* scanning filter policy */
|
||||
tBTM_START_ADV_CMPL_CBACK *p_adv_cb;
|
||||
tBTM_START_STOP_ADV_CMPL_CBACK *p_stop_adv_cb;
|
||||
tBTM_CLEAR_ADV_CMPL_CBACK *p_clear_adv_cb;
|
||||
tBLE_ADDR_TYPE adv_addr_type;
|
||||
UINT8 evt_type;
|
||||
UINT8 adv_mode;
|
||||
tBLE_BD_ADDR direct_bda;
|
||||
tBTM_BLE_EVT directed_conn;
|
||||
BOOLEAN fast_adv_on;
|
||||
TIMER_LIST_ENT fast_adv_timer;
|
||||
|
||||
UINT8 adv_len;
|
||||
UINT8 adv_data_cache[BTM_BLE_CACHE_ADV_DATA_MAX];
|
||||
BD_ADDR adv_addr;
|
||||
/* inquiry BD addr database */
|
||||
UINT8 num_bd_entries;
|
||||
UINT8 max_bd_entries;
|
||||
tBTM_BLE_LOCAL_ADV_DATA adv_data;
|
||||
tBTM_BLE_ADV_CHNL_MAP adv_chnl_map;
|
||||
|
||||
TIMER_LIST_ENT inq_timer_ent;
|
||||
BOOLEAN scan_rsp;
|
||||
tBTM_BLE_GAP_STATE state; /* Current state that the adv or scan process is in */
|
||||
INT8 tx_power;
|
||||
} tBTM_BLE_INQ_CB;
|
||||
|
||||
|
||||
/* random address resolving complete callback */
|
||||
typedef void (tBTM_BLE_RESOLVE_CBACK) (void *match_rec, void *p);
|
||||
|
||||
typedef void (tBTM_BLE_ADDR_CBACK) (BD_ADDR_PTR static_random, void *p);
|
||||
|
||||
#define BTM_BLE_GAP_ADDR_BIT_RANDOM (1<<0)
|
||||
#define BTM_BLE_GAP_ADDR_BIT_RESOLVABLE (1<<1)
|
||||
|
||||
/* random address management control block */
|
||||
typedef struct {
|
||||
tBLE_ADDR_TYPE own_addr_type; /* local device LE address type */
|
||||
UINT8 exist_addr_bit;
|
||||
BD_ADDR static_rand_addr;
|
||||
BD_ADDR resolvale_addr;
|
||||
BD_ADDR private_addr;
|
||||
BD_ADDR random_bda;
|
||||
BOOLEAN busy;
|
||||
tBTM_SEC_DEV_REC *p_dev_rec;
|
||||
tBTM_BLE_RESOLVE_CBACK *p_resolve_cback;
|
||||
tBTM_BLE_ADDR_CBACK *p_generate_cback;
|
||||
void *p;
|
||||
TIMER_LIST_ENT raddr_timer_ent;
|
||||
tBTM_SET_LOCAL_PRIVACY_CBACK *set_local_privacy_cback;
|
||||
} tBTM_LE_RANDOM_CB;
|
||||
|
||||
#define BTM_BLE_MAX_BG_CONN_DEV_NUM 10
|
||||
|
||||
typedef struct {
|
||||
UINT16 min_conn_int;
|
||||
UINT16 max_conn_int;
|
||||
UINT16 slave_latency;
|
||||
UINT16 supervision_tout;
|
||||
|
||||
} tBTM_LE_CONN_PRAMS;
|
||||
|
||||
|
||||
typedef struct {
|
||||
BD_ADDR bd_addr;
|
||||
UINT8 attr;
|
||||
BOOLEAN is_connected;
|
||||
BOOLEAN in_use;
|
||||
} tBTM_LE_BG_CONN_DEV;
|
||||
|
||||
/* white list using state as a bit mask */
|
||||
#define BTM_BLE_WL_IDLE 0
|
||||
#define BTM_BLE_WL_INIT 1
|
||||
#define BTM_BLE_WL_SCAN 2
|
||||
#define BTM_BLE_WL_ADV 4
|
||||
typedef UINT8 tBTM_BLE_WL_STATE;
|
||||
|
||||
/* resolving list using state as a bit mask */
|
||||
#define BTM_BLE_RL_IDLE 0
|
||||
#define BTM_BLE_RL_INIT 1
|
||||
#define BTM_BLE_RL_SCAN 2
|
||||
#define BTM_BLE_RL_ADV 4
|
||||
typedef UINT8 tBTM_BLE_RL_STATE;
|
||||
|
||||
/* BLE connection state */
|
||||
#define BLE_CONN_IDLE 0
|
||||
#define BLE_DIR_CONN 1
|
||||
#define BLE_BG_CONN 2
|
||||
#define BLE_CONN_CANCEL 3
|
||||
typedef UINT8 tBTM_BLE_CONN_ST;
|
||||
|
||||
typedef struct {
|
||||
void *p_param;
|
||||
} tBTM_BLE_CONN_REQ;
|
||||
|
||||
/* LE state request */
|
||||
#define BTM_BLE_STATE_INVALID 0
|
||||
#define BTM_BLE_STATE_CONN_ADV 1
|
||||
#define BTM_BLE_STATE_INIT 2
|
||||
#define BTM_BLE_STATE_MASTER 3
|
||||
#define BTM_BLE_STATE_SLAVE 4
|
||||
#define BTM_BLE_STATE_LO_DUTY_DIR_ADV 5
|
||||
#define BTM_BLE_STATE_HI_DUTY_DIR_ADV 6
|
||||
#define BTM_BLE_STATE_NON_CONN_ADV 7
|
||||
#define BTM_BLE_STATE_PASSIVE_SCAN 8
|
||||
#define BTM_BLE_STATE_ACTIVE_SCAN 9
|
||||
#define BTM_BLE_STATE_SCAN_ADV 10
|
||||
#define BTM_BLE_STATE_MAX 11
|
||||
typedef UINT8 tBTM_BLE_STATE;
|
||||
|
||||
#define BTM_BLE_STATE_CONN_ADV_BIT 0x0001
|
||||
#define BTM_BLE_STATE_INIT_BIT 0x0002
|
||||
#define BTM_BLE_STATE_MASTER_BIT 0x0004
|
||||
#define BTM_BLE_STATE_SLAVE_BIT 0x0008
|
||||
#define BTM_BLE_STATE_LO_DUTY_DIR_ADV_BIT 0x0010
|
||||
#define BTM_BLE_STATE_HI_DUTY_DIR_ADV_BIT 0x0020
|
||||
#define BTM_BLE_STATE_NON_CONN_ADV_BIT 0x0040
|
||||
#define BTM_BLE_STATE_PASSIVE_SCAN_BIT 0x0080
|
||||
#define BTM_BLE_STATE_ACTIVE_SCAN_BIT 0x0100
|
||||
#define BTM_BLE_STATE_SCAN_ADV_BIT 0x0200
|
||||
typedef UINT16 tBTM_BLE_STATE_MASK;
|
||||
|
||||
#define BTM_BLE_STATE_ALL_MASK 0x03ff
|
||||
#define BTM_BLE_STATE_ALL_ADV_MASK (BTM_BLE_STATE_CONN_ADV_BIT|BTM_BLE_STATE_LO_DUTY_DIR_ADV_BIT|BTM_BLE_STATE_HI_DUTY_DIR_ADV_BIT|BTM_BLE_STATE_SCAN_ADV_BIT)
|
||||
#define BTM_BLE_STATE_ALL_SCAN_MASK (BTM_BLE_STATE_PASSIVE_SCAN_BIT|BTM_BLE_STATE_ACTIVE_SCAN_BIT)
|
||||
#define BTM_BLE_STATE_ALL_CONN_MASK (BTM_BLE_STATE_MASTER_BIT|BTM_BLE_STATE_SLAVE_BIT)
|
||||
|
||||
#ifndef BTM_LE_RESOLVING_LIST_MAX
|
||||
#define BTM_LE_RESOLVING_LIST_MAX 0x20
|
||||
#endif
|
||||
|
||||
#define BTM_DUPLICATE_SCAN_EXCEPTIONAL_INFO_ADV_ADDR 0
|
||||
#define BTM_DUPLICATE_SCAN_EXCEPTIONAL_INFO_MESH_LINK_ID 1
|
||||
#define BTM_DUPLICATE_SCAN_EXCEPTIONAL_INFO_MESH_BEACON_TYPE 2
|
||||
#define BTM_DUPLICATE_SCAN_EXCEPTIONAL_INFO_MESH_PROV_SRV_ADV 3
|
||||
#define BTM_DUPLICATE_SCAN_EXCEPTIONAL_INFO_MESH_PROXY_SRV_ADV 4
|
||||
|
||||
typedef struct {
|
||||
BD_ADDR *resolve_q_random_pseudo;
|
||||
UINT8 *resolve_q_action;
|
||||
UINT8 q_next;
|
||||
UINT8 q_pending;
|
||||
} tBTM_BLE_RESOLVE_Q;
|
||||
|
||||
typedef struct {
|
||||
BOOLEAN in_use;
|
||||
BOOLEAN to_add;
|
||||
BD_ADDR bd_addr;
|
||||
tBLE_ADDR_TYPE addr_type;
|
||||
UINT8 attr;
|
||||
} tBTM_BLE_WL_OP;
|
||||
|
||||
/* BLE privacy mode */
|
||||
#define BTM_PRIVACY_NONE 0 /* BLE no privacy */
|
||||
#define BTM_PRIVACY_1_1 1 /* BLE privacy 1.1, do not support privacy 1.0 */
|
||||
#define BTM_PRIVACY_1_2 2 /* BLE privacy 1.2 */
|
||||
#define BTM_PRIVACY_MIXED 3 /* BLE privacy mixed mode, broadcom propietary mode */
|
||||
typedef UINT8 tBTM_PRIVACY_MODE;
|
||||
|
||||
/* data length change event callback */
|
||||
typedef void (tBTM_DATA_LENGTH_CHANGE_CBACK) (UINT16 max_tx_length, UINT16 max_rx_length);
|
||||
|
||||
/* Define BLE Device Management control structure
|
||||
*/
|
||||
typedef struct {
|
||||
UINT16 scan_activity; /* LE scan activity mask */
|
||||
|
||||
/*****************************************************
|
||||
** BLE Inquiry
|
||||
*****************************************************/
|
||||
tBTM_BLE_INQ_CB inq_var;
|
||||
|
||||
/* observer callback and timer */
|
||||
tBTM_INQ_RESULTS_CB *p_obs_results_cb;
|
||||
tBTM_CMPL_CB *p_obs_cmpl_cb;
|
||||
tBTM_INQ_DIS_CB *p_obs_discard_cb;
|
||||
TIMER_LIST_ENT obs_timer_ent;
|
||||
|
||||
/* scan callback and timer */
|
||||
tBTM_INQ_RESULTS_CB *p_scan_results_cb;
|
||||
tBTM_CMPL_CB *p_scan_cmpl_cb;
|
||||
TIMER_LIST_ENT scan_timer_ent;
|
||||
|
||||
struct pkt_queue *adv_rpt_queue;
|
||||
struct osi_event *adv_rpt_ready;
|
||||
|
||||
/* background connection procedure cb value */
|
||||
tBTM_BLE_CONN_TYPE bg_conn_type;
|
||||
UINT32 scan_int;
|
||||
UINT32 scan_win;
|
||||
tBTM_BLE_SEL_CBACK *p_select_cback;
|
||||
/* white list information */
|
||||
UINT8 white_list_avail_size;
|
||||
tBTM_UPDATE_WHITELIST_CBACK *update_wl_cb;
|
||||
tBTM_BLE_WL_STATE wl_state;
|
||||
|
||||
fixed_queue_t *conn_pending_q;
|
||||
tBTM_BLE_CONN_ST conn_state;
|
||||
|
||||
/* random address management control block */
|
||||
tBTM_LE_RANDOM_CB addr_mgnt_cb;
|
||||
|
||||
BOOLEAN enabled;
|
||||
|
||||
#if BLE_PRIVACY_SPT == TRUE
|
||||
BOOLEAN mixed_mode; /* privacy 1.2 mixed mode is on or not */
|
||||
tBTM_PRIVACY_MODE privacy_mode; /* privacy mode */
|
||||
UINT8 resolving_list_avail_size; /* resolving list available size */
|
||||
tBTM_BLE_RESOLVE_Q resolving_list_pend_q; /* Resolving list queue */
|
||||
tBTM_BLE_RL_STATE suspended_rl_state; /* Suspended resolving list state */
|
||||
UINT8 *irk_list_mask; /* IRK list availability mask, up to max entry bits */
|
||||
tBTM_BLE_RL_STATE rl_state; /* Resolving list state */
|
||||
#endif
|
||||
|
||||
tBTM_BLE_WL_OP wl_op_q[BTM_BLE_MAX_BG_CONN_DEV_NUM];
|
||||
|
||||
/* current BLE link state */
|
||||
tBTM_BLE_STATE_MASK cur_states; /* bit mask of tBTM_BLE_STATE */
|
||||
UINT8 link_count[2]; /* total link count master and slave*/
|
||||
tBTM_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_CMPL_CBACK *update_exceptional_list_cmp_cb;
|
||||
} tBTM_BLE_CB;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void btm_ble_timeout(TIMER_LIST_ENT *p_tle);
|
||||
void btm_ble_process_adv_pkt (UINT8 *p);
|
||||
void btm_ble_process_adv_discard_evt(UINT8 *p);
|
||||
void btm_ble_process_direct_adv_pkt (UINT8 *p);
|
||||
bool btm_ble_adv_pkt_ready(void);
|
||||
bool btm_ble_adv_pkt_post(pkt_linked_item_t *pkt);
|
||||
void btm_ble_proc_scan_rsp_rpt (UINT8 *p);
|
||||
tBTM_STATUS btm_ble_read_remote_name(BD_ADDR remote_bda, tBTM_INQ_INFO *p_cur, tBTM_CMPL_CB *p_cb);
|
||||
BOOLEAN btm_ble_cancel_remote_name(BD_ADDR remote_bda);
|
||||
|
||||
tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode);
|
||||
tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode);
|
||||
tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration);
|
||||
void btm_ble_stop_scan(void);
|
||||
void btm_clear_all_pending_le_entry(void);
|
||||
|
||||
BOOLEAN btm_ble_send_extended_scan_params(UINT8 scan_type, UINT32 scan_int, UINT32 scan_win, UINT8 addr_type_own, UINT8 scan_filter_policy);
|
||||
void btm_ble_stop_inquiry(void);
|
||||
void btm_ble_init (void);
|
||||
void btm_ble_free (void);
|
||||
void btm_ble_connected (UINT8 *bda, UINT16 handle, UINT8 enc_mode, UINT8 role, tBLE_ADDR_TYPE addr_type, BOOLEAN addr_matched);
|
||||
void btm_ble_read_remote_features_complete(UINT8 *p);
|
||||
void btm_ble_write_adv_enable_complete(UINT8 *p);
|
||||
void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len, BOOLEAN enhanced);
|
||||
void btm_read_ble_local_supported_states_complete(UINT8 *p, UINT16 evt_len);
|
||||
tBTM_BLE_CONN_ST btm_ble_get_conn_st(void);
|
||||
void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st);
|
||||
UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst, tBTM_BLE_ADV_DATA *p_data);
|
||||
tBTM_STATUS btm_ble_start_adv(void);
|
||||
tBTM_STATUS btm_ble_stop_adv(void);
|
||||
tBTM_STATUS btm_ble_start_scan(void);
|
||||
void btm_ble_create_ll_conn_complete (UINT8 status);
|
||||
void btm_ble_create_conn_cancel_complete (UINT8 *p);
|
||||
tBTM_STATUS btm_ble_set_random_addr(BD_ADDR random_bda);
|
||||
|
||||
/* LE security function from btm_sec.c */
|
||||
#if SMP_INCLUDED == TRUE
|
||||
void btm_ble_link_sec_check(BD_ADDR bd_addr, tBTM_LE_AUTH_REQ auth_req, tBTM_BLE_SEC_REQ_ACT *p_sec_req_act);
|
||||
void btm_ble_ltk_request_reply(BD_ADDR bda, BOOLEAN use_stk, BT_OCTET16 stk);
|
||||
UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data);
|
||||
tBTM_STATUS btm_ble_set_encryption (BD_ADDR bd_addr, void *p_ref_data, UINT8 link_role);
|
||||
void btm_ble_ltk_request(UINT16 handle, UINT8 rand[8], UINT16 ediv);
|
||||
tBTM_STATUS btm_ble_start_encrypt(BD_ADDR bda, BOOLEAN use_stk, BT_OCTET16 stk);
|
||||
void btm_ble_link_encrypted(BD_ADDR bd_addr, UINT8 encr_enable);
|
||||
#endif
|
||||
|
||||
/* LE device management functions */
|
||||
void btm_ble_reset_id( void );
|
||||
|
||||
/* security related functions */
|
||||
void btm_ble_increment_sign_ctr(BD_ADDR bd_addr, BOOLEAN is_local );
|
||||
BOOLEAN btm_get_local_div (BD_ADDR bd_addr, UINT16 *p_div);
|
||||
BOOLEAN btm_ble_get_enc_key_type(BD_ADDR bd_addr, UINT8 *p_key_types);
|
||||
|
||||
void btm_ble_test_command_complete(UINT8 *p);
|
||||
void btm_ble_rand_enc_complete (UINT8 *p, UINT16 op_code, tBTM_RAND_ENC_CB *p_enc_cplt_cback);
|
||||
|
||||
void btm_sec_save_le_key(BD_ADDR bd_addr, tBTM_LE_KEY_TYPE key_type, tBTM_LE_KEY_VALUE *p_keys, BOOLEAN pass_to_application);
|
||||
void btm_ble_update_sec_key_size(BD_ADDR bd_addr, UINT8 enc_key_size);
|
||||
UINT8 btm_ble_read_sec_key_size(BD_ADDR bd_addr);
|
||||
|
||||
/* white list function */
|
||||
BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr, tBLE_ADDR_TYPE addr_type, tBTM_UPDATE_WHITELIST_CBACK *update_wl_cb);
|
||||
void btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy);
|
||||
void btm_update_adv_filter_policy(tBTM_BLE_AFP adv_policy);
|
||||
void btm_ble_clear_white_list (tBTM_UPDATE_WHITELIST_CBACK *update_wl_cb);
|
||||
void btm_read_white_list_size_complete(UINT8 *p, UINT16 evt_len);
|
||||
void btm_ble_add_2_white_list_complete(UINT8 status);
|
||||
void btm_ble_remove_from_white_list_complete(UINT8 *p, UINT16 evt_len);
|
||||
void btm_ble_clear_white_list_complete(UINT8 *p, UINT16 evt_len);
|
||||
void btm_ble_white_list_init(UINT8 white_list_size);
|
||||
|
||||
/* background connection function */
|
||||
BOOLEAN btm_ble_suspend_bg_conn(void);
|
||||
BOOLEAN btm_ble_resume_bg_conn(void);
|
||||
void btm_ble_initiate_select_conn(BD_ADDR bda);
|
||||
BOOLEAN btm_ble_start_auto_conn(BOOLEAN start);
|
||||
BOOLEAN btm_ble_start_select_conn(BOOLEAN start, tBTM_BLE_SEL_CBACK *p_select_cback);
|
||||
BOOLEAN btm_ble_renew_bg_conn_params(BOOLEAN add, BD_ADDR bd_addr);
|
||||
void btm_write_dir_conn_wl(BD_ADDR target_addr);
|
||||
BOOLEAN btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bda, UINT8 status);
|
||||
BOOLEAN btm_execute_wl_dev_operation(void);
|
||||
void btm_ble_update_link_topology_mask(UINT8 role, BOOLEAN increase);
|
||||
|
||||
/* direct connection utility */
|
||||
BOOLEAN btm_send_pending_direct_conn(void);
|
||||
void btm_ble_enqueue_direct_conn_req(void *p_param);
|
||||
|
||||
/* BLE address management */
|
||||
void btm_gen_resolvable_private_addr (void *p_cmd_cplt_cback);
|
||||
void btm_gen_non_resolvable_private_addr (tBTM_BLE_ADDR_CBACK *p_cback, void *p);
|
||||
void btm_ble_resolve_random_addr(BD_ADDR random_bda, tBTM_BLE_RESOLVE_CBACK *p_cback, void *p);
|
||||
void btm_gen_resolve_paddr_low(tBTM_RAND_ENC *p);
|
||||
|
||||
/* privacy function */
|
||||
#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
|
||||
/* BLE address mapping with CS feature */
|
||||
BOOLEAN btm_identity_addr_to_random_pseudo(BD_ADDR bd_addr, UINT8 *p_addr_type, BOOLEAN refresh);
|
||||
BOOLEAN btm_random_pseudo_to_identity_addr(BD_ADDR random_pseudo, UINT8 *p_static_addr_type);
|
||||
void btm_ble_refresh_peer_resolvable_private_addr(BD_ADDR pseudo_bda, BD_ADDR rra, UINT8 rra_type);
|
||||
void btm_ble_refresh_local_resolvable_private_addr(BD_ADDR pseudo_addr, BD_ADDR local_rpa);
|
||||
void btm_ble_read_resolving_list_entry_complete(UINT8 *p, UINT16 evt_len) ;
|
||||
void btm_ble_set_addr_resolution_enable_complete(UINT8 *p, UINT16 evt_len) ;
|
||||
void btm_ble_remove_resolving_list_entry_complete(UINT8 *p, UINT16 evt_len);
|
||||
void btm_ble_add_resolving_list_entry_complete(UINT8 *p, UINT16 evt_len);
|
||||
void btm_ble_clear_resolving_list_complete(UINT8 *p, UINT16 evt_len);
|
||||
void btm_read_ble_resolving_list_size_complete (UINT8 *p, UINT16 evt_len);
|
||||
void btm_ble_enable_resolving_list(UINT8);
|
||||
BOOLEAN btm_ble_disable_resolving_list(UINT8 rl_mask, BOOLEAN to_resume);
|
||||
void btm_ble_enable_resolving_list_for_platform (UINT8 rl_mask);
|
||||
void btm_ble_resolving_list_init(UINT8 max_irk_list_sz);
|
||||
void btm_ble_resolving_list_cleanup(void);
|
||||
void btm_ble_add_default_entry_to_resolving_list(void);
|
||||
#endif
|
||||
|
||||
void btm_ble_multi_adv_configure_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst);
|
||||
void btm_ble_multi_adv_init(void);
|
||||
void *btm_ble_multi_adv_get_ref(UINT8 inst_id);
|
||||
void btm_ble_multi_adv_cleanup(void);
|
||||
void btm_ble_multi_adv_reenable(UINT8 inst_id);
|
||||
void btm_ble_multi_adv_enb_privacy(BOOLEAN enable);
|
||||
char btm_ble_map_adv_tx_power(int tx_power_index);
|
||||
void btm_ble_batchscan_init(void);
|
||||
void btm_ble_batchscan_cleanup(void);
|
||||
void btm_ble_adv_filter_init(void);
|
||||
void btm_ble_adv_filter_cleanup(void);
|
||||
BOOLEAN btm_ble_topology_check(tBTM_BLE_STATE_MASK request);
|
||||
BOOLEAN btm_ble_clear_topology_mask(tBTM_BLE_STATE_MASK request_state);
|
||||
BOOLEAN btm_ble_set_topology_mask(tBTM_BLE_STATE_MASK request_state);
|
||||
tBTM_BLE_STATE_MASK btm_ble_get_topology_mask(void);
|
||||
|
||||
#if BTM_BLE_CONFORMANCE_TESTING == TRUE
|
||||
void btm_ble_set_no_disc_if_pair_fail (BOOLEAN disble_disc);
|
||||
void btm_ble_set_test_mac_value (BOOLEAN enable, UINT8 *p_test_mac_val);
|
||||
void btm_ble_set_test_local_sign_cntr_value(BOOLEAN enable, UINT32 test_local_sign_cntr);
|
||||
void btm_set_random_address(BD_ADDR random_bda);
|
||||
void btm_ble_set_keep_rfu_in_auth_req(BOOLEAN keep_rfu);
|
||||
#endif
|
||||
|
||||
BOOLEAN btm_get_current_conn_params(BD_ADDR bda, UINT16 *interval, UINT16 *latency, UINT16 *timeout);
|
||||
|
||||
#if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
void btm_ble_update_phy_evt(tBTM_BLE_UPDATE_PHY *params);
|
||||
void btm_ble_scan_timeout_evt(void);
|
||||
void btm_ble_adv_set_terminated_evt(tBTM_BLE_ADV_TERMINAT *params);
|
||||
void btm_ble_ext_adv_report_evt(tBTM_BLE_EXT_ADV_REPORT *params);
|
||||
void btm_ble_scan_req_received_evt(tBTM_BLE_SCAN_REQ_RECEIVED *params);
|
||||
void btm_ble_channel_select_algorithm_evt(tBTM_BLE_CHANNEL_SEL_ALG *params);
|
||||
void btm_ble_periodic_adv_report_evt(tBTM_PERIOD_ADV_REPORT *params);
|
||||
void btm_ble_periodic_adv_sync_lost_evt(tBTM_BLE_PERIOD_ADV_SYNC_LOST *params);
|
||||
void btm_ble_periodic_adv_sync_establish_evt(tBTM_BLE_PERIOD_ADV_SYNC_ESTAB *params);
|
||||
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
|
||||
#if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
|
||||
void btm_ble_periodic_adv_sync_trans_recv_evt(tBTM_BLE_PERIOD_ADV_SYNC_TRANS_RECV *params);
|
||||
#endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
|
||||
|
||||
/*
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user