Merge branch 'feature/support_ble_53_feature_for_pts' into 'master'

Bluedroid: support ble host features for PTS

See merge request espressif/esp-idf!21253
This commit is contained in:
Wang Meng Yang
2022-12-12 14:33:37 +08:00
54 changed files with 2140 additions and 109 deletions

View File

@@ -321,6 +321,7 @@ if(CONFIG_BT_ENABLED)
"host/bluedroid/stack/gatt/gatt_db.c"
"host/bluedroid/stack/gatt/gatt_main.c"
"host/bluedroid/stack/gatt/gatt_sr.c"
"host/bluedroid/stack/gatt/gatt_sr_hash.c"
"host/bluedroid/stack/gatt/gatt_utils.c"
"host/bluedroid/stack/hcic/hciblecmds.c"
"host/bluedroid/stack/hcic/hcicmds.c"

View File

@@ -208,6 +208,27 @@ config BT_GATTS_SEND_SERVICE_CHANGE_MODE
default 1 if BT_GATTS_SEND_SERVICE_CHANGE_MANUAL
default 0
config BT_GATTS_ROBUST_CACHING_ENABLED
bool "Enable Robust Caching on Server Side"
depends on BT_GATTS_ENABLE
default n
help
This option enable gatt robust caching feature on server
config BT_GATTS_DEVICE_NAME_WRITABLE
bool "Allow to write device name by GATT clients"
depends on BT_GATTS_ENABLE
default n
help
Enabling this option allows remote GATT clients to write device name
config BT_GATTS_APPEARANCE_WRITABLE
bool "Allow to write appearance by GATT clients"
depends on BT_GATTS_ENABLE
default n
help
Enabling this option allows remote GATT clients to write appearance
config BT_GATTC_ENABLE
bool "Include GATT client module(GATTC)"
depends on BT_BLE_ENABLED
@@ -1094,6 +1115,15 @@ config BT_BLE_RPA_SUPPORTED
For ESP32C3, ESP32S3, ESP32H4 and ESP32C2, devices support network privacy mode and device privacy mode,
users can switch the two modes according to their own needs. So this option is enabled by default.
config BT_BLE_RPA_TIMEOUT
int "Timeout of resolvable private address"
depends on BT_BLUEDROID_ENABLED
range 1 3600
default 900
help
This set RPA timeout of Controller and Host.
Default is 900 s (15 minutes). Range is 1 s to 1 hour (3600 s).
config BT_BLE_50_FEATURES_SUPPORTED
bool "Enable BLE 5.0 features"
depends on (BT_BLUEDROID_ENABLED && (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 || SOC_ESP_NIMBLE_CONTROLLER))

View File

@@ -713,6 +713,38 @@ esp_err_t esp_ble_oob_req_reply(esp_bd_addr_t bd_addr, uint8_t *TK, uint8_t len)
btc_gap_ble_arg_deep_free) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_sc_oob_req_reply(esp_bd_addr_t bd_addr, uint8_t p_c[16], uint8_t p_r[16])
{
if (!p_c || !p_r) {
return ESP_ERR_INVALID_ARG;
}
btc_msg_t msg = {0};
btc_ble_gap_args_t arg;
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_GAP_BLE;
msg.act = BTC_GAP_BLE_SC_OOB_REQ_REPLY_EVT;
memcpy(arg.sc_oob_req_reply.bd_addr, bd_addr, ESP_BD_ADDR_LEN);
arg.sc_oob_req_reply.p_c = p_c;
arg.sc_oob_req_reply.p_r = p_r;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), btc_gap_ble_arg_deep_copy,
btc_gap_ble_arg_deep_free) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_create_sc_oob_data(void)
{
btc_msg_t msg = {0};
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_GAP_BLE;
msg.act = BTC_GAP_BLE_SC_CR_OOB_DATA_EVT;
return (btc_transfer_context(&msg, NULL, 0, NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* #if (SMP_INCLUDED == TRUE) */
esp_err_t esp_ble_gap_disconnect(esp_bd_addr_t remote_device)

View File

@@ -163,6 +163,8 @@ typedef enum {
ESP_GAP_BLE_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_COMPLETE_EVT, /*!< When update duplicate exceptional list complete, the event comes */
#endif //#if (BLE_42_FEATURE_SUPPORT == TRUE)
ESP_GAP_BLE_SET_CHANNELS_EVT = 29, /*!< When setting BLE channels complete, the event comes */
ESP_GAP_BLE_SC_OOB_REQ_EVT, /*!< Secure Connection OOB request event */
ESP_GAP_BLE_SC_CR_LOC_OOB_EVT, /*!< Secure Connection create OOB data complete event */
#if (BLE_50_FEATURE_SUPPORT == TRUE)
ESP_GAP_BLE_READ_PHY_COMPLETE_EVT, /*!< when reading phy complete, this event comes */
ESP_GAP_BLE_SET_PREFERRED_DEFAULT_PHY_COMPLETE_EVT, /*!< when preferred default phy complete, this event comes */
@@ -583,6 +585,13 @@ typedef struct {
esp_bt_octet16_t dhk; /*!< the 16 bits of the dh key value */
} esp_ble_local_id_keys_t; /*!< the structure of the ble local id keys value type*/
/**
* @brief structure type of the ble local oob data value
*/
typedef struct {
esp_bt_octet16_t oob_c; /*!< the 128 bits of confirmation value */
esp_bt_octet16_t oob_r; /*!< the 128 bits of randomizer value */
} esp_ble_local_oob_data_t;
/**
* @brief Structure associated with ESP_AUTH_CMPL_EVT
@@ -609,6 +618,7 @@ typedef union
esp_ble_sec_req_t ble_req; /*!< BLE SMP related request */
esp_ble_key_t ble_key; /*!< BLE SMP keys used when pairing */
esp_ble_local_id_keys_t ble_id_keys; /*!< BLE IR event */
esp_ble_local_oob_data_t oob_data; /*!< BLE SMP secure connection OOB data */
esp_ble_auth_cmpl_t auth_cmpl; /*!< Authentication complete indication. */
} esp_ble_sec_t; /*!< BLE security type */
#if (BLE_42_FEATURE_SUPPORT == TRUE)
@@ -1769,6 +1779,29 @@ esp_err_t esp_ble_get_bond_device_list(int *dev_num, esp_ble_bond_dev_t *dev_lis
*/
esp_err_t esp_ble_oob_req_reply(esp_bd_addr_t bd_addr, uint8_t *TK, uint8_t len);
/**
* @brief This function is called to provide the OOB data for
* SMP in response to ESP_GAP_BLE_SC_OOB_REQ_EVT
*
* @param[in] bd_addr: BD address of the peer device.
* @param[in] p_c: Confirmation value, it shall be a 128-bit random number
* @param[in] p_r: Randomizer value, it should be a 128-bit random number
*
* @return - ESP_OK : success
* - other : failed
*
*/
esp_err_t esp_ble_sc_oob_req_reply(esp_bd_addr_t bd_addr, uint8_t p_c[16], uint8_t p_r[16]);
/**
* @brief This function is called to create the OOB data for
* SMP when secure connection
*
* @return - ESP_OK : success
* - other : failed
*
*/
esp_err_t esp_ble_create_sc_oob_data(void);
#endif /* #if (SMP_INCLUDED == TRUE) */
/**

View File

@@ -1427,6 +1427,40 @@ void bta_dm_oob_reply(tBTA_DM_MSG *p_data)
#endif
}
/*******************************************************************************
**
** Function bta_dm_sc_oob_reply
**
** Description This function is called to provide the OOB data for
** SMP in response to BLE secure connection OOB request.
**
** Returns void
**
*******************************************************************************/
void bta_dm_sc_oob_reply(tBTA_DM_MSG *p_data)
{
#if (BLE_INCLUDED)
BTM_BleSecureConnectionOobDataReply(p_data->sc_oob_reply.bd_addr, p_data->sc_oob_reply.c, p_data->sc_oob_reply.r);
#endif
}
/*******************************************************************************
**
** Function bta_dm_sc_create_oob_data
**
** Description This function is called to create the OOB data for
** SMP when secure connection.
**
** Returns void
**
*******************************************************************************/
void bta_dm_sc_create_oob_data(tBTA_DM_MSG *p_data)
{
#if (BLE_INCLUDED)
BTM_BleSecureConnectionCreateOobData();
#endif
}
/*******************************************************************************
**
** Function bta_dm_ci_io_req_act
@@ -4711,6 +4745,17 @@ static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_D
bta_dm_cb.p_sec_cback(BTA_DM_BLE_OOB_REQ_EVT, &sec_event);
break;
case BTM_LE_SC_OOB_REQ_EVT:
bdcpy(sec_event.ble_req.bd_addr, bda);
bta_dm_cb.p_sec_cback(BTA_DM_BLE_SC_OOB_REQ_EVT, &sec_event);
break;
case BTM_LE_SC_LOC_OOB_EVT:
memcpy(sec_event.local_oob_data.local_oob_c, p_data->local_oob_data.commitment, BT_OCTET16_LEN);
memcpy(sec_event.local_oob_data.local_oob_r, p_data->local_oob_data.randomizer, BT_OCTET16_LEN);
bta_dm_cb.p_sec_cback(BTA_DM_BLE_SC_CR_LOC_OOB_EVT, &sec_event);
break;
case BTM_LE_NC_REQ_EVT:
bdcpy(sec_event.key_notif.bd_addr, bda);
BCM_STRNCPY_S((char *)sec_event.key_notif.bd_name,bta_dm_get_remname(), BD_NAME_LEN);

View File

@@ -650,7 +650,7 @@ void BTA_DmLocalOob(void)
** Function BTA_DmOobReply
**
** This function is called to provide the OOB data for
** SMP in response to BTM_LE_OOB_REQ_EVT
** SMP in response to BTA_LE_OOB_REQ_EVT
**
** Parameters: bd_addr - Address of the peer device
** len - length of simple pairing Randomizer C
@@ -675,6 +675,55 @@ void BTA_DmOobReply(BD_ADDR bd_addr, UINT8 len, UINT8 *p_value)
bta_sys_sendmsg(p_msg);
}
}
/*******************************************************************************
**
** Function BTA_DmSecureConnectionOobReply
**
** This function is called to provide the OOB data for
** SMP in response to BTA_LE_OOB_REQ_EVT
**
** Parameters: bd_addr - Address of the peer device
** p_c - Pointer to Confirmation
** p_r - Pointer to Randomizer
**
** Returns void
**
*******************************************************************************/
void BTA_DmSecureConnectionOobReply(BD_ADDR bd_addr, UINT8 *p_c, UINT8 *p_r)
{
tBTA_DM_API_SC_OOB_REPLY *p_msg;
if ((p_msg = (tBTA_DM_API_SC_OOB_REPLY *) osi_malloc(sizeof(tBTA_DM_API_OOB_REPLY))) != NULL) {
p_msg->hdr.event = BTA_DM_API_SC_OOB_REPLY_EVT;
if((p_c == NULL) || (p_r == NULL)) {
return;
}
memcpy(p_msg->bd_addr, bd_addr, BD_ADDR_LEN);
memcpy(p_msg->c, p_c, BT_OCTET16_LEN);
memcpy(p_msg->r, p_r, BT_OCTET16_LEN);
bta_sys_sendmsg(p_msg);
}
}
/*******************************************************************************
**
** Function BTA_DmSecureConnectionCreateOobData
**
** This function is called to create the OOB data for
** SMP when secure connection
**
** Returns void
**
*******************************************************************************/
void BTA_DmSecureConnectionCreateOobData(void)
{
tBTA_DM_API_SC_CR_OOB_DATA *p_msg;
if ((p_msg = (tBTA_DM_API_SC_CR_OOB_DATA *) osi_malloc(sizeof(tBTA_DM_API_SC_CR_OOB_DATA))) != NULL) {
p_msg->hdr.event = BTA_DM_API_SC_CR_OOB_DATA_EVT;
bta_sys_sendmsg(p_msg);
}
}
#endif /* BTM_OOB_INCLUDED */
/*******************************************************************************
**
@@ -3089,4 +3138,18 @@ void BTA_DmBleGapExtConnect(tBLE_ADDR_TYPE own_addr_type, const BD_ADDR peer_add
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
#if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
uint8_t BTA_DmBlePeriodicAdvSetInfoTrans(uint8_t addr[6], uint16_t service_data, uint8_t adv_handle)
{
BTM_BlePeriodicAdvSetInfoTrans(addr, service_data, adv_handle);
return 0;
}
uint8_t BTA_DmBleSetPeriodicAdvSyncTransParams(uint8_t addr[6], uint8_t mode, uint16_t skip, uint16_t sync_timeout)
{
BTM_BleSetPeriodicAdvSyncTransParams(addr, mode, skip, sync_timeout, 0);
return 0;
}
#endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
#endif

View File

@@ -350,10 +350,6 @@ void bta_dm_co_ble_io_req(BD_ADDR bd_addr, tBTA_IO_CAP *p_io_cap,
*p_auth_req = bte_appl_cfg.ble_auth_req | (bte_appl_cfg.ble_auth_req & BTA_LE_AUTH_REQ_MITM) | ((*p_auth_req) & BTA_LE_AUTH_REQ_MITM);
if (*p_oob_data == BTM_BLE_OOB_ENABLE) {
*p_auth_req = (*p_auth_req)&(~BTA_LE_AUTH_REQ_SC_ONLY);
}
if (bte_appl_cfg.ble_io_cap <= 4) {
*p_io_cap = bte_appl_cfg.ble_io_cap;
}

View File

@@ -96,6 +96,8 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = {
#if (BTM_OOB_INCLUDED == TRUE && SMP_INCLUDED == TRUE)
bta_dm_loc_oob, /* BTA_DM_API_LOC_OOB_EVT */
bta_dm_oob_reply, /* BTA_DM_API_OOB_REPLY_EVT */
bta_dm_sc_oob_reply, /* BTA_DM_API_SC_OOB_REPLY_EVT */
bta_dm_sc_create_oob_data, /* BTA_DM_API_SC_CR_OOB_DATA_EVT */
bta_dm_ci_io_req_act, /* BTA_DM_CI_IO_REQ_EVT */
bta_dm_ci_rmt_oob_act, /* BTA_DM_CI_RMT_OOB_EVT */
#endif /* BTM_OOB_INCLUDED */

View File

@@ -92,6 +92,8 @@ enum {
#if (BTM_OOB_INCLUDED == TRUE && SMP_INCLUDED == TRUE)
BTA_DM_API_LOC_OOB_EVT,
BTA_DM_API_OOB_REPLY_EVT,
BTA_DM_API_SC_OOB_REPLY_EVT,
BTA_DM_API_SC_CR_OOB_DATA_EVT,
BTA_DM_CI_IO_REQ_EVT,
BTA_DM_CI_RMT_OOB_EVT,
#endif /* BTM_OOB_INCLUDED */
@@ -394,8 +396,23 @@ typedef struct {
BD_ADDR bd_addr;
UINT8 len;
UINT8 value[BT_OCTET16_LEN];
UINT8 c[BT_OCTET16_LEN];
UINT8 r[BT_OCTET16_LEN];
} tBTA_DM_API_OOB_REPLY;
/* data type for BTA_DM_API_SC_OOB_REPLY_EVT */
typedef struct {
BT_HDR hdr;
BD_ADDR bd_addr;
UINT8 c[BT_OCTET16_LEN];
UINT8 r[BT_OCTET16_LEN];
} tBTA_DM_API_SC_OOB_REPLY;
/* data type for BTA_DM_API_SC_CR_OOB_DATA_EVT */
typedef struct {
BT_HDR hdr;
} tBTA_DM_API_SC_CR_OOB_DATA;
/* data type for BTA_DM_API_CONFIRM_EVT */
typedef struct {
BT_HDR hdr;
@@ -1047,6 +1064,7 @@ typedef union {
tBTA_DM_API_LOC_OOB loc_oob;
tBTA_DM_API_OOB_REPLY oob_reply;
tBTA_DM_API_SC_OOB_REPLY sc_oob_reply;
tBTA_DM_API_CONFIRM confirm;
tBTA_DM_API_KEY_REQ key_req;
tBTA_DM_CI_IO_REQ ci_io_req;
@@ -1605,6 +1623,8 @@ extern BOOLEAN bta_dm_check_if_only_hd_connected(BD_ADDR peer_addr);
#if (BTM_OOB_INCLUDED == TRUE)
extern void bta_dm_loc_oob(tBTA_DM_MSG *p_data);
extern void bta_dm_oob_reply(tBTA_DM_MSG *p_data);
extern void bta_dm_sc_oob_reply(tBTA_DM_MSG *p_data);
extern void bta_dm_sc_create_oob_data(tBTA_DM_MSG *p_data);
extern void bta_dm_ci_io_req_act(tBTA_DM_MSG *p_data);
extern void bta_dm_ci_rmt_oob_act(tBTA_DM_MSG *p_data);
#endif /* BTM_OOB_INCLUDED */

View File

@@ -126,6 +126,7 @@ static void bta_gattc_enable(tBTA_GATTC_CB *p_cb)
if (p_cb->state == BTA_GATTC_STATE_DISABLED) {
/* initialize control block */
memset(&bta_gattc_cb, 0, sizeof(tBTA_GATTC_CB));
bta_gattc_cb.auto_disc = true;
p_cb->state = BTA_GATTC_STATE_ENABLED;
} else {
APPL_TRACE_DEBUG("GATTC is already enabled");
@@ -692,10 +693,12 @@ void bta_gattc_conn(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
} else
#endif
{ /* cache is building */
if (bta_gattc_cb.auto_disc) {
p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC;
/* cache load failure, start discovery */
bta_gattc_start_discover(p_clcb, NULL);
}
}
} else { /* cache is building */
p_clcb->state = BTA_GATTC_DISCOVER_ST;
}

View File

@@ -1103,4 +1103,108 @@ void BTA_GATTC_Broadcast(tBTA_GATTC_IF client_if, BOOLEAN start)
return;
}
/* Add For BLE PTS */
uint8_t BTA_GATTC_AutoDiscoverEnable(uint8_t enable)
{
APPL_TRACE_DEBUG("%s enable %d", __func__, enable);
bta_gattc_cb.auto_disc = ((enable > 0) ? true : false);
GATTC_AutoDiscoverEnable(enable);
return 0;
}
typedef struct {
UINT16 len;
union {
UINT16 uuid16;
UINT32 uuid32;
UINT8 uuid128[LEN_UUID_128];
} uuid;
} __attribute__((packed)) tAPP_UUID;
uint8_t BTA_GATTC_Discover(uint8_t gatt_if, uint16_t conn_id, void *uuid, uint8_t disc_type, uint16_t s_handle, uint16_t e_handle)
{
tGATT_STATUS status;
tGATT_DISC_PARAM param;
tAPP_UUID *app_uuid = (tAPP_UUID *)uuid;
conn_id = (UINT16)((((UINT8)conn_id) << 8) | gatt_if);
memset(&param, 0, sizeof(tGATT_DISC_PARAM));
if (disc_type == GATT_DISC_SRVC_ALL || disc_type == GATT_DISC_SRVC_BY_UUID) {
param.s_handle = 1;
param.e_handle = 0xFFFF;
} else {
param.s_handle = s_handle;
param.e_handle = e_handle;
}
if (app_uuid) {
param.service.len = app_uuid->len;
if (app_uuid->len == LEN_UUID_16) {
param.service.uu.uuid16 = app_uuid->uuid.uuid16;
} else if (app_uuid->len == LEN_UUID_32) {
param.service.uu.uuid32 = app_uuid->uuid.uuid32;
} else if (app_uuid->len == LEN_UUID_128) {
memcpy(param.service.uu.uuid128, app_uuid->uuid.uuid128, LEN_UUID_128);
} else {
APPL_TRACE_ERROR("%s invalid uuid len %u", __func__, app_uuid->len);
}
}
status = GATTC_Discover (conn_id, disc_type, &param);
if (status != GATT_SUCCESS) {
APPL_TRACE_ERROR("%s status %x", __func__, status);
return -1;
}
return 0;
}
uint8_t BTA_GATTC_ReadLongChar(uint8_t gatt_if, uint16_t conn_id, uint16_t handle, uint16_t offset, uint8_t auth_req)
{
tGATT_STATUS status;
tGATT_READ_PARAM read_param;
conn_id = (UINT16)((((UINT8)conn_id) << 8) | gatt_if);
memset (&read_param, 0, sizeof(tGATT_READ_PARAM));
read_param.partial.handle = handle;
read_param.partial.offset = offset;
read_param.partial.auth_req = auth_req;
status = GATTC_Read(conn_id, GATT_READ_PARTIAL, &read_param);
if (status != GATT_SUCCESS) {
APPL_TRACE_ERROR("%s status %x", __func__, status);
return -1;
}
return 0;
}
uint8_t BTA_GATTC_ReadMultiVariableChar(uint8_t gatt_if, uint16_t conn_id, uint16_t num_handles, uint16_t *handles, uint8_t auth_req)
{
tGATT_STATUS status;
tGATT_READ_PARAM read_param;
if (num_handles > GATT_MAX_READ_MULTI_HANDLES) {
APPL_TRACE_ERROR("%s max read multi handlse %x", __func__, num_handles);
return -1;
}
conn_id = (UINT16)((((UINT8)conn_id) << 8) | gatt_if);
memset (&read_param, 0, sizeof(tGATT_READ_PARAM));
read_param.read_multiple.num_handles = num_handles;
memcpy(read_param.read_multiple.handles, handles, num_handles);
read_param.read_multiple.auth_req = auth_req;
status = GATTC_Read(conn_id, GATT_READ_MULTIPLE_VAR, &read_param);
if (status != GATT_SUCCESS) {
APPL_TRACE_ERROR("%s status %x", __func__, status);
return -1;
}
return 0;
}
/* End BLE PTS */
#endif /* defined(GATTC_INCLUDED) && (GATTC_INCLUDED == TRUE) */

View File

@@ -969,6 +969,10 @@ void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_
BOOLEAN pri_srvc;
tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
if (bta_gattc_cb.auto_disc == FALSE) {
return;
}
p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
if (p_srvc_cb != NULL && p_clcb != NULL && p_clcb->state == BTA_GATTC_DISCOVER_ST) {
@@ -1042,6 +1046,10 @@ void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT
tBTA_GATTC_SERV *p_srvc_cb;
tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
if (bta_gattc_cb.auto_disc == FALSE) {
return;
}
if ( p_clcb && (status != GATT_SUCCESS || p_clcb->status != GATT_SUCCESS) ) {
if (status == GATT_SUCCESS) {
p_clcb->status = status;

View File

@@ -640,4 +640,31 @@ void BTA_GATTS_Listen(tBTA_GATTS_IF server_if, BOOLEAN start, BD_ADDR_PTR target
return;
}
uint8_t BTA_GATTS_SetServiceChangeMode(uint8_t mode)
{
tGATT_STATUS status;
APPL_TRACE_DEBUG("%s mode %u", __func__, mode);
status = GATTS_SetServiceChangeMode(mode);
if (status != GATT_SUCCESS) {
APPL_TRACE_ERROR("%s status %x", __func__, status);
return -1;
}
return 0;
}
uint8_t BTA_GATTS_SendMultiNotification(uint8_t gatt_if, uint16_t conn_id, void *tuples, uint16_t num_tuples)
{
tGATT_STATUS status;
conn_id = (UINT16)((((UINT8)conn_id) << 8) | gatt_if);
status = GATTS_HandleMultiValueNotification(conn_id, (tGATT_HLV *)tuples, num_tuples);
if (status != GATT_SUCCESS) {
APPL_TRACE_ERROR("%s status %x", __func__, status);
return -1;
}
return 0;
}
#endif /* BTA_GATT_INCLUDED */

View File

@@ -24,6 +24,8 @@
#include <stdlib.h>
#include <string.h>
#include "bta/bta_gatts_co.h"
#include "btc/btc_storage.h"
#include "btc/btc_ble_storage.h"
// #include "btif_util.h"
#if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE)
@@ -159,5 +161,89 @@ BOOLEAN bta_gatts_co_load_handle_range(UINT8 index,
return FALSE;
}
/*******************************************************************************
**
** Function bta_gatts_co_cl_feat_save
**
** Description This callout function is executed by GATTS when GATT server
** client support feature is requested to write to NV.
**
** Parameter remote_addr - remote device address
** feature - pointer of client support feature
**
** Returns void.
**
*******************************************************************************/
void bta_gatts_co_cl_feat_save(BD_ADDR remote_addr, UINT8 *feature)
{
bt_bdaddr_t bd_addr;
memcpy(bd_addr.address, remote_addr, BD_ADDR_LEN);
btc_storage_set_gatt_cl_supp_feat(&bd_addr, feature, 1);
}
/*******************************************************************************
**
** Function bta_gatts_co_db_hash_save
**
** Description This callout function is executed by GATTS when GATT server
** client status is requested to write to NV.
**
** Parameter remote_addr - remote device address
** db_hash - pointer of GATT service datebase hash
**
** Returns void.
**
*******************************************************************************/
void bta_gatts_co_db_hash_save(BD_ADDR remote_addr, BT_OCTET16 db_hash)
{
bt_bdaddr_t bd_addr;
memcpy(bd_addr.address, remote_addr, BD_ADDR_LEN);
btc_storage_set_gatt_db_hash(&bd_addr, db_hash, BT_OCTET16_LEN);
}
/*******************************************************************************
**
** Function bta_gatts_co_cl_feat_load
**
** Description This callout function is executed by GATTS when GATT server
** client status is requested to load from NV.
**
** Parameter remote_addr - remote device address
** feature - pointer of GATT service datebase hash
**
** Returns void.
**
*******************************************************************************/
void bta_gatts_co_cl_feat_load(BD_ADDR remote_addr, UINT8 *feature)
{
bt_bdaddr_t bd_addr;
memcpy(bd_addr.address, remote_addr, BD_ADDR_LEN);
btc_storage_get_gatt_cl_supp_feat(&bd_addr, feature, 1);
}
/*******************************************************************************
**
** Function bta_gatts_co_db_hash_load
**
** Description This callout function is executed by GATTS when GATT server
** client status is requested to load from NV.
**
** Parameter remote_addr - remote device address
** db_hash - pointer of GATT service datebase hash
**
** Returns void.
**
*******************************************************************************/
void bta_gatts_co_db_hash_load(BD_ADDR remote_addr, BT_OCTET16 db_hash)
{
bt_bdaddr_t bd_addr;
memcpy(bd_addr.address, remote_addr, BD_ADDR_LEN);
btc_storage_get_gatt_db_hash(&bd_addr, db_hash, BT_OCTET16_LEN);
}
#endif
#endif

View File

@@ -392,6 +392,7 @@ enum {
typedef struct {
UINT8 state;
BOOLEAN auto_disc; /* internal use: true for auto discovering after connected */
tBTA_GATTC_CONN conn_track[BTA_GATTC_CONN_MAX];
tBTA_GATTC_BG_TCK bg_track[BTA_GATTC_KNOWN_SR_MAX];
tBTA_GATTC_RCB cl_rcb[BTA_GATTC_CL_MAX];

View File

@@ -657,6 +657,8 @@ typedef UINT8 tBTA_SIG_STRENGTH_MASK;
#define BTA_DM_SP_KEY_REQ_EVT 30 /* Simple Pairing Passkey request */
#define BTA_DM_PM_MODE_CHG_EVT 31 /* Mode changed event */
#define BTA_DM_ACL_LINK_STAT_EVT 32 /* ACL connection status report event */
#define BTA_DM_BLE_SC_OOB_REQ_EVT 33 /* BLE SMP SC OOB request event */
#define BTA_DM_BLE_SC_CR_LOC_OOB_EVT 34 /* BLE SMP SC Create Local OOB request event */
typedef UINT8 tBTA_DM_SEC_EVT;
@@ -976,6 +978,10 @@ typedef struct {
tBTA_PM_MODE mode; /* the new connection role */
} tBTA_DM_MODE_CHG;
typedef struct {
BT_OCTET16 local_oob_c; /* Local OOB Data Confirmation/Commitment */
BT_OCTET16 local_oob_r; /* Local OOB Data Randomizer */
} tBTA_DM_LOC_OOB_DATA;
/* Union of all security callback structures */
typedef union {
@@ -1001,6 +1007,7 @@ typedef union {
#if BTA_DM_PM_INCLUDED
tBTA_DM_MODE_CHG mode_chg; /* mode change event */
#endif ///BTA_DM_PM_INCLUDED
tBTA_DM_LOC_OOB_DATA local_oob_data; /* Local OOB data generated by us */
} tBTA_DM_SEC;
/* Security callback */
@@ -1919,7 +1926,7 @@ extern void BTA_DmLocalOob(void);
** Function BTA_DmOobReply
**
** This function is called to provide the OOB data for
** SMP in response to BTM_LE_OOB_REQ_EVT
** SMP in response to BTA_LE_OOB_REQ_EVT
**
** Parameters: bd_addr - Address of the peer device
** len - length of simple pairing Randomizer C
@@ -1929,6 +1936,33 @@ extern void BTA_DmLocalOob(void);
**
*******************************************************************************/
extern void BTA_DmOobReply(BD_ADDR bd_addr, UINT8 len, UINT8 *p_value);
/*******************************************************************************
**
** Function BTA_DmSecureConnectionOobReply
**
** This function is called to provide the OOB data for
** SMP in response to BTA_LE_OOB_REQ_EVT when secure connection
**
** Parameters: bd_addr - Address of the peer device
** p_c - Pointer to Confirmation
** p_r - Pointer to Randomizer
**
** Returns void
**
*******************************************************************************/
extern void BTA_DmSecureConnectionOobReply(BD_ADDR bd_addr, UINT8 *p_c, UINT8 *p_r);
/*******************************************************************************
**
** Function BTA_DmSecureConnectionCreateOobData
**
** This function is called to create the OOB data for
** SMP when secure connection
**
** Returns void
**
*******************************************************************************/
extern void BTA_DmSecureConnectionCreateOobData(void);
#endif /* BTM_OOB_INCLUDED */
/*******************************************************************************

View File

@@ -77,5 +77,12 @@ extern BOOLEAN bta_gatts_co_srv_chg(tBTA_GATTS_SRV_CHG_CMD cmd,
extern BOOLEAN bta_gatts_co_load_handle_range(UINT8 index,
tBTA_GATTS_HNDL_RANGE *p_handle);
extern void bta_gatts_co_cl_feat_save(BD_ADDR remote_addr, UINT8 *feature);
extern void bta_gatts_co_db_hash_save(BD_ADDR remote_addr, BT_OCTET16 db_hash);
extern void bta_gatts_co_cl_feat_load(BD_ADDR remote_addr, UINT8 *feature);
extern void bta_gatts_co_db_hash_load(BD_ADDR remote_addr, BT_OCTET16 db_hash);
#endif /* BTA_GATTS_CO_H */

View File

@@ -39,7 +39,9 @@ static void _btc_storage_save(void)
!btc_config_exist(section, BTC_BLE_STORAGE_LE_KEY_PID_STR) &&
!btc_config_exist(section, BTC_BLE_STORAGE_LE_KEY_PCSRK_STR) &&
!btc_config_exist(section, BTC_BLE_STORAGE_LE_KEY_LENC_STR) &&
!btc_config_exist(section, BTC_BLE_STORAGE_LE_KEY_LCSRK_STR)) {
!btc_config_exist(section, BTC_BLE_STORAGE_LE_KEY_LCSRK_STR) &&
!btc_config_exist(section, BTC_BLE_STORAGE_GATT_CL_SUPP_FEAT_STR) &&
!btc_config_exist(section, BTC_BLE_STORAGE_GATT_DB_HASH_STR)) {
iter = btc_config_section_next(iter);
btc_config_remove_section(section);
continue;
@@ -924,3 +926,79 @@ int btc_storage_get_num_ble_bond_devices(void)
}
#endif ///BLE_INCLUDED == TRUE
#endif ///SMP_INCLUDED == TRUE
#if (BLE_INCLUDED == TRUE && GATTS_INCLUDED == TRUE)
bt_status_t btc_storage_get_gatt_cl_supp_feat(bt_bdaddr_t *remote_bd_addr, uint8_t *value, int len)
{
bdstr_t bdstr;
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
int ret = btc_config_get_bin(bdstr, BTC_BLE_STORAGE_GATT_CL_SUPP_FEAT_STR, value, (size_t *)&len);
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
}
bt_status_t btc_storage_set_gatt_cl_supp_feat(bt_bdaddr_t *remote_bd_addr, uint8_t *value, int len)
{
int ret;
bdstr_t bdstr;
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr_t));
ret = btc_config_set_bin(bdstr, BTC_BLE_STORAGE_GATT_CL_SUPP_FEAT_STR, value, (size_t)len);
if (ret == false) {
return BT_STATUS_FAIL;
}
return BT_STATUS_SUCCESS;
}
bt_status_t btc_storage_get_gatt_db_hash(bt_bdaddr_t *remote_bd_addr, uint8_t *value, int len)
{
bdstr_t bdstr;
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
int ret = btc_config_get_bin(bdstr, BTC_BLE_STORAGE_GATT_DB_HASH_STR, value, (size_t *)&len);
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
}
bt_status_t btc_storage_set_gatt_db_hash(bt_bdaddr_t *remote_bd_addr, uint8_t *value, int len)
{
int ret;
bdstr_t bdstr;
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr_t));
ret = btc_config_set_bin(bdstr, BTC_BLE_STORAGE_GATT_DB_HASH_STR, value, (size_t)len);
if (ret == false) {
return BT_STATUS_FAIL;
}
return BT_STATUS_SUCCESS;
}
bt_status_t btc_storage_remove_gatt_cl_supp_feat(bt_bdaddr_t *remote_bd_addr)
{
bool ret = true;
bdstr_t bdstr;
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
ret = btc_config_remove(bdstr, BTC_BLE_STORAGE_GATT_CL_SUPP_FEAT_STR);
if (ret == false) {
return BT_STATUS_FAIL;
}
return BT_STATUS_SUCCESS;
}
bt_status_t btc_storage_remove_gatt_db_hash(bt_bdaddr_t *remote_bd_addr)
{
bool ret = true;
bdstr_t bdstr;
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
ret = btc_config_remove(bdstr, BTC_BLE_STORAGE_GATT_DB_HASH_STR);
if (ret == false) {
return BT_STATUS_FAIL;
}
return BT_STATUS_SUCCESS;
}
#endif /* BLE_INCLUDED == TRUE && GATTS_INCLUDED == TRUE */

View File

@@ -173,6 +173,8 @@ static void btc_dm_remove_ble_bonding_keys(void)
bdcpy(bd_addr.address, btc_dm_cb.pairing_cb.bd_addr);
btc_storage_remove_gatt_cl_supp_feat(&bd_addr);
btc_storage_remove_gatt_db_hash(&bd_addr);
btc_storage_remove_remote_addr_type(&bd_addr, false);
btc_storage_remove_ble_dev_auth_mode(&bd_addr, false);
btc_storage_remove_ble_dev_type(&bd_addr, false);
@@ -809,6 +811,8 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg)
if (p_data->link_down.status == HCI_SUCCESS) {
//remove the bonded key in the config and nvs flash.
btc_storage_remove_gatt_cl_supp_feat(&bd_addr);
btc_storage_remove_gatt_db_hash(&bd_addr);
btc_storage_remove_ble_dev_type(&bd_addr, false);
btc_storage_remove_remote_addr_type(&bd_addr, false);
btc_storage_remove_ble_dev_auth_mode(&bd_addr, false);
@@ -944,6 +948,19 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg)
memcpy(param.ble_security.ble_req.bd_addr, p_data->ble_req.bd_addr, BD_ADDR_LEN);
break;
}
case BTA_DM_BLE_SC_OOB_REQ_EVT: {
rsp_app = true;
ble_msg->act = ESP_GAP_BLE_SC_OOB_REQ_EVT;
memcpy(param.ble_security.ble_req.bd_addr, p_data->ble_req.bd_addr, BD_ADDR_LEN);
break;
}
case BTA_DM_BLE_SC_CR_LOC_OOB_EVT: {
rsp_app = true;
ble_msg->act = ESP_GAP_BLE_SC_CR_LOC_OOB_EVT;
memcpy(param.ble_security.oob_data.oob_c, p_data->local_oob_data.local_oob_c, BT_OCTET16_LEN);
memcpy(param.ble_security.oob_data.oob_r, p_data->local_oob_data.local_oob_r, BT_OCTET16_LEN);
break;
}
case BTA_DM_BLE_LOCAL_IR_EVT: {
rsp_app = true;
ble_msg->act = ESP_GAP_BLE_LOCAL_IR_EVT;

View File

@@ -88,6 +88,20 @@ bt_status_t btc_storage_load_bonded_ble_devices(void);
bt_status_t btc_storage_get_bonded_ble_devices_list(esp_ble_bond_dev_t *bond_dev, int dev_num);
int btc_storage_get_num_ble_bond_devices(void);
#endif ///SMP_INCLUDED == TRUE
#define BTC_BLE_STORAGE_GATT_CL_SUPP_FEAT_STR "GATT_CL_SUPP_FEAT"
#define BTC_BLE_STORAGE_GATT_DB_HASH_STR "GATT_DB_HASH"
bt_status_t btc_storage_get_gatt_cl_supp_feat(bt_bdaddr_t *remote_bd_addr, uint8_t *value, int len);
bt_status_t btc_storage_set_gatt_cl_supp_feat(bt_bdaddr_t *remote_bd_addr, uint8_t *value, int len);
bt_status_t btc_storage_remove_gatt_cl_supp_feat(bt_bdaddr_t *remote_bd_addr);
bt_status_t btc_storage_get_gatt_db_hash(bt_bdaddr_t *remote_bd_addr, uint8_t *value, int len);
bt_status_t btc_storage_set_gatt_db_hash(bt_bdaddr_t *remote_bd_addr, uint8_t *value, int len);
bt_status_t btc_storage_remove_gatt_db_hash(bt_bdaddr_t *remote_bd_addr);
#endif ///__BTC_BLE_STORAGE_H__

View File

@@ -1307,6 +1307,27 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
}
break;
}
case BTC_GAP_BLE_SC_OOB_REQ_REPLY_EVT: {
btc_ble_gap_args_t *src = (btc_ble_gap_args_t *)p_src;
btc_ble_gap_args_t *dst = (btc_ble_gap_args_t *)p_dest;
if (src->sc_oob_req_reply.p_c) {
dst->sc_oob_req_reply.p_c = osi_malloc(BT_OCTET16_LEN);
if (dst->sc_oob_req_reply.p_c) {
memcpy(dst->sc_oob_req_reply.p_c, src->sc_oob_req_reply.p_c, BT_OCTET16_LEN);
} else {
BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act);
}
}
if (src->sc_oob_req_reply.p_r) {
dst->sc_oob_req_reply.p_r = osi_malloc(BT_OCTET16_LEN);
if (dst->sc_oob_req_reply.p_r) {
memcpy(dst->sc_oob_req_reply.p_r, src->sc_oob_req_reply.p_r, BT_OCTET16_LEN);
} else {
BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act);
}
}
break;
}
#if (BLE_50_FEATURE_SUPPORT == TRUE)
case BTC_GAP_BLE_CFG_EXT_ADV_DATA_RAW:
case BTC_GAP_BLE_CFG_EXT_SCAN_RSP_DATA_RAW: {
@@ -1432,6 +1453,17 @@ void btc_gap_ble_arg_deep_free(btc_msg_t *msg)
}
break;
}
case BTC_GAP_BLE_SC_OOB_REQ_REPLY_EVT: {
uint8_t *value = ((btc_ble_gap_args_t *)msg->arg)->sc_oob_req_reply.p_c;
if (value) {
osi_free(value);
}
value = ((btc_ble_gap_args_t *)msg->arg)->sc_oob_req_reply.p_r;
if (value) {
osi_free(value);
}
break;
}
#if (BLE_50_FEATURE_SUPPORT == TRUE)
case BTC_GAP_BLE_CFG_EXT_ADV_DATA_RAW:
case BTC_GAP_BLE_CFG_EXT_SCAN_RSP_DATA_RAW: {
@@ -1690,6 +1722,12 @@ void btc_gap_ble_call_handler(btc_msg_t *msg)
case BTC_GAP_BLE_OOB_REQ_REPLY_EVT:
BTA_DmOobReply(arg->oob_req_reply.bd_addr, arg->oob_req_reply.len, arg->oob_req_reply.p_value);
break;
case BTC_GAP_BLE_SC_OOB_REQ_REPLY_EVT:
BTA_DmSecureConnectionOobReply(arg->sc_oob_req_reply.bd_addr, arg->sc_oob_req_reply.p_c, arg->sc_oob_req_reply.p_r);
break;
case BTC_GAP_BLE_SC_CR_OOB_DATA_EVT:
BTA_DmSecureConnectionCreateOobData();
break;
#endif ///SMP_INCLUDED == TRUE
case BTC_GAP_BLE_DISCONNECT_EVT:
btc_ble_disconnect(arg->disconnect.remote_device);

View File

@@ -54,6 +54,8 @@ typedef enum {
BTC_GAP_BLE_DISCONNECT_EVT,
BTC_GAP_BLE_REMOVE_BOND_DEV_EVT,
BTC_GAP_BLE_OOB_REQ_REPLY_EVT,
BTC_GAP_BLE_SC_OOB_REQ_REPLY_EVT,
BTC_GAP_BLE_SC_CR_OOB_DATA_EVT,
BTC_GAP_BLE_UPDATE_DUPLICATE_SCAN_EXCEPTIONAL_LIST,
BTC_GAP_BLE_SET_AFH_CHANNELS,
#if (BLE_50_FEATURE_SUPPORT == TRUE)
@@ -200,6 +202,11 @@ typedef union {
uint8_t len;
uint8_t *p_value;
} oob_req_reply;
struct sc_oob_req_reply_args {
esp_bd_addr_t bd_addr;
uint8_t *p_c;
uint8_t *p_r;
} sc_oob_req_reply;
//BTC_GAP_BLE_DISCONNECT_EVT
struct disconnect_args {
esp_bd_addr_t remote_device;

View File

@@ -276,12 +276,36 @@
#define UC_BT_GATTS_SEND_SERVICE_CHANGE_MODE 0
#endif
#ifdef CONFIG_BT_GATTS_ROBUST_CACHING_ENABLED
#define UC_BT_GATTS_ROBUST_CACHING_ENABLED CONFIG_BT_GATTS_ROBUST_CACHING_ENABLED
#else
#define UC_BT_GATTS_ROBUST_CACHING_ENABLED FALSE
#endif
#ifdef CONFIG_BT_GATTS_DEVICE_NAME_WRITABLE
#define UC_BT_GATTS_DEVICE_NAME_WRITABLE CONFIG_BT_GATTS_DEVICE_NAME_WRITABLE
#else
#define UC_BT_GATTS_DEVICE_NAME_WRITABLE FALSE
#endif
#ifdef CONFIG_BT_GATTS_APPEARANCE_WRITABLE
#define UC_BT_GATTS_APPEARANCE_WRITABLE CONFIG_BT_GATTS_APPEARANCE_WRITABLE
#else
#define UC_BT_GATTS_APPEARANCE_WRITABLE FALSE
#endif
#ifdef CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN
#define UC_BT_BLE_ACT_SCAN_REP_ADV_SCAN CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN
#else
#define UC_BT_BLE_ACT_SCAN_REP_ADV_SCAN FALSE
#endif
#ifdef CONFIG_BT_BLE_RPA_TIMEOUT
#define UC_BT_BLE_RPA_TIMEOUT CONFIG_BT_BLE_RPA_TIMEOUT
#else
#define UC_BT_BLE_RPA_TIMEOUT 900
#endif
//SCO VOICE OVER HCI
#ifdef CONFIG_BT_HFP_AUDIO_DATA_PATH_HCI
#define UC_BT_HFP_AUDIO_DATA_PATH_HCI CONFIG_BT_HFP_AUDIO_DATA_PATH_HCI

View File

@@ -493,10 +493,32 @@
#define GATTS_SEND_SERVICE_CHANGE_MODE UC_BT_GATTS_SEND_SERVICE_CHANGE_MODE
#endif
#if (UC_BT_GATTS_ROBUST_CACHING_ENABLED == TRUE)
#define GATTS_ROBUST_CACHING_ENABLED TRUE
#else
#define GATTS_ROBUST_CACHING_ENABLED FALSE
#endif
#if (UC_BT_GATTS_DEVICE_NAME_WRITABLE == TRUE)
#define GATTS_DEVICE_NAME_WRITABLE TRUE
#else
#define GATTS_DEVICE_NAME_WRITABLE FALSE
#endif
#if (UC_BT_GATTS_APPEARANCE_WRITABLE == TRUE)
#define GATTS_APPEARANCE_WRITABLE TRUE
#else
#define GATTS_APPEARANCE_WRITABLE FALSE
#endif
#ifdef UC_BT_BLE_ACT_SCAN_REP_ADV_SCAN
#define BTM_BLE_ACTIVE_SCAN_REPORT_ADV_SCAN_RSP_INDIVIDUALLY UC_BT_BLE_ACT_SCAN_REP_ADV_SCAN
#endif
#ifdef UC_BT_BLE_RPA_TIMEOUT
#define BTM_BLE_PRIVATE_ADDR_INT UC_BT_BLE_RPA_TIMEOUT
#endif
/* This feature is used to eanble interleaved scan*/
#ifndef BTA_HOST_INTERLEAVE_SEARCH
#define BTA_HOST_INTERLEAVE_SEARCH FALSE
@@ -2268,6 +2290,9 @@ The maximum number of payload octets that the local device can receive in a sing
#define HEAP_ALLOCATION_FROM_SPIRAM_FIRST FALSE
#endif
// TODO: add menuconfig and api for periodic adv sync transfer
#define BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER FALSE
#include "common/bt_trace.h"
#endif /* BT_TARGET_H */

View File

@@ -496,6 +496,62 @@ void BTM_BleOobDataReply(BD_ADDR bd_addr, UINT8 res, UINT8 len, UINT8 *p_data)
#endif
}
/*******************************************************************************
**
** Function BTM_BleSecureConnectionOobDataReply
**
** Description This function is called to provide the OOB data for
** SMP in response to BTM_LE_SC_OOB_REQ_EVT when secure connection
**
** Parameters: bd_addr - Address of the peer device
** p_c - pointer to Confirmation
** p_r - pointer to Randomizer
**
*******************************************************************************/
void BTM_BleSecureConnectionOobDataReply(BD_ADDR bd_addr, UINT8 *p_c, UINT8 *p_r)
{
#if SMP_INCLUDED == TRUE
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
BTM_TRACE_DEBUG ("%s", __func__);
if (p_dev_rec == NULL) {
BTM_TRACE_ERROR("%s Unknown device", __func__);
return;
}
p_dev_rec->sec_flags |= BTM_SEC_LE_AUTHENTICATED;
tSMP_SC_OOB_DATA oob;
memset(&oob, 0, sizeof(tSMP_SC_OOB_DATA));
oob.peer_oob_data.present = true;
memcpy(&oob.peer_oob_data.commitment, p_c, BT_OCTET16_LEN);
memcpy(&oob.peer_oob_data.randomizer, p_r, BT_OCTET16_LEN);
oob.peer_oob_data.addr_rcvd_from.type = p_dev_rec->ble.ble_addr_type;
memcpy(oob.peer_oob_data.addr_rcvd_from.bda, bd_addr, BD_ADDR_LEN);
SMP_SecureConnectionOobDataReply((UINT8 *)&oob);
#endif
}
/*******************************************************************************
**
** Function BTM_BleSecureConnectionCreateOobData
**
** Description This function is called to create the OOB data for
** SMP when secure connection
**
*******************************************************************************/
void BTM_BleSecureConnectionCreateOobData(void)
{
#if SMP_INCLUDED == TRUE
BTM_TRACE_DEBUG ("%s", __func__);
SMP_CreateLocalSecureConnectionsOobData();
#endif
}
/******************************************************************************
**
** Function BTM_BleSetConnScanParams
@@ -2210,10 +2266,18 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data)
break;
}
} else {
if (event == SMP_SC_LOC_OOB_DATA_UP_EVT) {
tBTM_LE_EVT_DATA evt_data;
memcpy(&evt_data.local_oob_data, &p_data->loc_oob_data, sizeof(tSMP_LOC_OOB_DATA));
if (btm_cb.api.p_le_callback) {
(*btm_cb.api.p_le_callback)(event, bd_addr, &evt_data);
}
} else {
BTM_TRACE_ERROR("btm_proc_smp_cback received for unknown device");
}
}
return 0;
}
#endif ///SMP_INCLUDED == TRUE

View File

@@ -1016,7 +1016,6 @@ void BTM_BleSetPreferExtenedConnParams (BD_ADDR bd_addr, tBTM_EXT_CONN_PARAMS *p
return;
}
void btm_ble_extended_init(void)
{
@@ -1267,3 +1266,33 @@ void btm_ble_periodic_adv_sync_establish_evt(tBTM_BLE_PERIOD_ADV_SYNC_ESTAB *par
}
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
#if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
void BTM_BlePeriodicAdvSetInfoTrans(BD_ADDR bd_addr, UINT16 service_data, UINT8 adv_handle)
{
tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_LE);
if (!p_lcb) {
BTM_TRACE_ERROR("%s, invalid parameters", __func__);
return;
}
if (!btsnd_hcic_ble_periodic_adv_set_info_trans(p_lcb->handle, service_data, adv_handle)) {
BTM_TRACE_ERROR("%s, hci cmd error", __func__);
}
}
void BTM_BleSetPeriodicAdvSyncTransParams(BD_ADDR bd_addr, UINT8 mode, UINT16 skip, UINT16 sync_timeout, UINT8 cte_type)
{
tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_LE);
if (!p_lcb) {
BTM_TRACE_ERROR("%s, invalid parameters", __func__);
return;
}
if (!btsnd_hcic_ble_set_periodic_adv_sync_trans_params(p_lcb->handle, mode, skip, sync_timeout, cte_type)) {
BTM_TRACE_ERROR("%s, hci cmd error", __func__);
}
}
#endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)

View File

@@ -147,8 +147,6 @@ typedef struct {
#define BTM_BLE_ISVALID_PARAM(x, min, max) (((x) >= (min) && (x) <= (max)) || ((x) == BTM_BLE_CONN_PARAM_UNDEF))
#define BTM_BLE_PRIVATE_ADDR_INT 900 /* 15 minutes minimum for random address refreshing */
typedef struct {
UINT16 discoverable_mode;
UINT16 connectable_mode;

View File

@@ -149,8 +149,10 @@ static void btu_ble_periodic_adv_sync_lost_evt(UINT8 *p);
static void btu_ble_scan_timeout_evt(UINT8 *p);
static void btu_ble_adv_set_terminate_evt(UINT8 *p);
static void btu_ble_scan_req_received_evt(UINT8 *p);
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
#if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
static void btu_ble_periodic_adv_sync_trans_recv(UINT8 *p);
#endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
extern osi_sem_t adv_enable_sem;
extern osi_sem_t adv_data_sem;
@@ -421,6 +423,11 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg)
case HCI_BLE_CHANNEL_SELECT_ALG:
break;
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
#if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
case HCI_BLE_PERIOD_ADV_SYNC_TRANS_RECV_EVT:
btu_ble_periodic_adv_sync_trans_recv(p);
break;
#endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
}
break;
#endif /* BLE_INCLUDED */
@@ -2314,6 +2321,27 @@ static void btu_ble_scan_req_received_evt(UINT8 *p)
btm_ble_scan_req_received_evt(&req_received);
}
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
#if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
static void btu_ble_periodic_adv_sync_trans_recv(UINT8 *p)
{
tBTM_BLE_PERIOD_ADV_SYNC_TRANS_RECV recv = {0};
STREAM_TO_UINT8(recv.status, p);
STREAM_TO_UINT16(recv.conn_handle, p);
STREAM_TO_UINT16(recv.service_data, p);
STREAM_TO_UINT16(recv.sync_handle, p);
STREAM_TO_UINT8(recv.adv_sid, p);
STREAM_TO_UINT8(recv.adv_addr_type, p);
STREAM_TO_BDADDR(recv.adv_addr, p);
STREAM_TO_UINT8(recv.adv_phy, p);
STREAM_TO_UINT16(recv.period_adv_interval, p);
STREAM_TO_UINT8(recv.adv_clk_accuracy, p);
HCI_TRACE_DEBUG("%s status %x, conn handle %x, sync handle %x", recv.status, recv.conn_handle, recv.sync_handle);
}
#endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
/**********************************************
** End of BLE Events Handler
***********************************************/

View File

@@ -298,12 +298,34 @@ UINT8 gap_proc_write_req( tGATTS_REQ_TYPE type, tGATT_WRITE_REQ *p_data)
UNUSED(type);
for (i = 0; i < GAP_MAX_CHAR_NUM; i ++, p_db_attr ++) {
if (p_data-> handle == p_db_attr->handle) {
if (p_data->handle == p_db_attr->handle) {
switch (p_db_attr->uuid) {
#if (GATTS_DEVICE_NAME_WRITABLE == TRUE)
case GATT_UUID_GAP_DEVICE_NAME: {
UINT8 *p_val = p_data->value;
p_val[p_data->len] = '\0';
BTM_SetLocalDeviceName((char *)p_val);
return GATT_SUCCESS;
}
#endif
#if (GATTS_APPEARANCE_WRITABLE == TRUE)
case GATT_UUID_GAP_ICON: {
UINT8 *p_val = p_data->value;
if (p_data->len != sizeof(UINT16)) {
return GATT_INVALID_ATTR_LEN;
}
STREAM_TO_UINT16(p_db_attr->attr_value.icon, p_val);
return GATT_SUCCESS;
}
#endif
default:
break;
}
return GATT_WRITE_NOT_PERMIT;
}
}
return GATT_NOT_FOUND;
return GATT_NOT_FOUND;
}
/******************************************************************************
@@ -393,17 +415,26 @@ void gap_attr_db_init(void)
*/
uuid.len = LEN_UUID_16;
uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_DEVICE_NAME;
p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid, GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ,
p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid,
#if (GATTS_DEVICE_NAME_WRITABLE == TRUE)
GATT_PERM_READ | GATT_PERM_WRITE,
GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_WRITE_NR,
#else
GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ,
#endif
NULL, NULL);
p_db_attr ++;
/* add Icon characteristic
*/
uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_ICON;
p_db_attr->handle = GATTS_AddCharacteristic(service_handle,
&uuid,
GATT_PERM_READ,
GATT_CHAR_PROP_BIT_READ,
p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid,
#if (GATTS_APPEARANCE_WRITABLE == TRUE)
GATT_PERM_READ | GATT_PERM_WRITE,
GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_WRITE_NR,
#else
GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ,
#endif
NULL, NULL);
p_db_attr ++;

View File

@@ -197,7 +197,7 @@ BT_HDR *attp_build_read_by_type_value_cmd (UINT16 payload_size, tGATT_FIND_TYPE_
** Returns None.
**
*******************************************************************************/
BT_HDR *attp_build_read_multi_cmd(UINT16 payload_size, UINT16 num_handle, UINT16 *p_handle)
BT_HDR *attp_build_read_multi_cmd(UINT8 op_code, UINT16 payload_size, UINT16 num_handle, UINT16 *p_handle)
{
BT_HDR *p_buf = NULL;
UINT8 *p, i = 0;
@@ -208,7 +208,7 @@ BT_HDR *attp_build_read_multi_cmd(UINT16 payload_size, UINT16 num_handle, UINT16
p_buf->offset = L2CAP_MIN_OFFSET;
p_buf->len = 1;
UINT8_TO_STREAM (p, GATT_REQ_READ_MULTI);
UINT8_TO_STREAM (p, op_code);
for (i = 0; i < num_handle && p_buf->len + 2 <= payload_size; i ++) {
UINT16_TO_STREAM (p, *(p_handle + i));
@@ -304,7 +304,7 @@ BT_HDR *attp_build_value_cmd (UINT16 payload_size, UINT8 op_code, UINT16 handle,
UINT8_TO_STREAM (p, pair_len);
p_buf->len += 1;
}
if (op_code != GATT_RSP_READ_BLOB && op_code != GATT_RSP_READ) {
if (op_code != GATT_RSP_READ_BLOB && op_code != GATT_RSP_READ && op_code != GATT_HANDLE_MULTI_VALUE_NOTIF) {
UINT16_TO_STREAM (p, handle);
p_buf->len += 2;
}
@@ -391,6 +391,7 @@ BT_HDR *attp_build_sr_msg(tGATT_TCB *p_tcb, UINT8 op_code, tGATT_SR_MSG *p_msg)
case GATT_RSP_READ:
case GATT_HANDLE_VALUE_NOTIF:
case GATT_HANDLE_VALUE_IND:
case GATT_HANDLE_MULTI_VALUE_NOTIF:
case GATT_RSP_ERROR:
case GATT_RSP_MTU:
/* Need to check the validation of parameter p_msg*/
@@ -417,6 +418,7 @@ BT_HDR *attp_build_sr_msg(tGATT_TCB *p_tcb, UINT8 op_code, tGATT_SR_MSG *p_msg)
case GATT_RSP_READ:
case GATT_HANDLE_VALUE_NOTIF:
case GATT_HANDLE_VALUE_IND:
case GATT_HANDLE_MULTI_VALUE_NOTIF:
p_cmd = attp_build_value_cmd(p_tcb->payload_size,
op_code,
p_msg->attr_value.handle,
@@ -613,7 +615,8 @@ tGATT_STATUS attp_send_cl_msg (tGATT_TCB *p_tcb, UINT16 clcb_idx, UINT8 op_code,
break;
case GATT_REQ_READ_MULTI:
p_cmd = attp_build_read_multi_cmd(p_tcb->payload_size,
case GATT_REQ_READ_MULTI_VAR:
p_cmd = attp_build_read_multi_cmd(op_code, p_tcb->payload_size,
p_msg->read_multi.num_handles,
p_msg->read_multi.handles);
break;

View File

@@ -122,6 +122,20 @@ BOOLEAN GATTS_NVRegister (const tGATT_APPL_INFO *p_cb_info)
return status;
}
static void gatt_update_for_database_change(void)
{
UINT8 i;
gatts_calculate_datebase_hash(gatt_cb.database_hash);
for (i = 0; i < GATT_MAX_PHY_CHANNEL; i++) {
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(i);
if (p_tcb && p_tcb->in_use) {
gatt_sr_update_cl_status(p_tcb, false);
}
}
}
/*******************************************************************************
**
** Function GATTS_CreateService
@@ -398,7 +412,8 @@ BOOLEAN GATTS_DeleteService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid, UINT16 svc_
GATT_TRACE_DEBUG ("Delete a new service changed item - the service has not yet started");
osi_free(fixed_queue_try_remove_from_queue(gatt_cb.pending_new_srv_start_q, p_buf));
} else {
if (GATTS_SEND_SERVICE_CHANGE_MODE == GATTS_SEND_SERVICE_CHANGE_AUTO) {
gatt_update_for_database_change();
if (gatt_cb.srv_chg_mode == GATTS_SEND_SERVICE_CHANGE_AUTO) {
gatt_proc_srv_chg();
}
}
@@ -510,7 +525,8 @@ tGATT_STATUS GATTS_StartService (tGATT_IF gatt_if, UINT16 service_handle,
if ( (p_buf = gatt_sr_is_new_srv_chg(&p_list->asgn_range.app_uuid128,
&p_list->asgn_range.svc_uuid,
p_list->asgn_range.svc_inst)) != NULL) {
if (GATTS_SEND_SERVICE_CHANGE_MODE == GATTS_SEND_SERVICE_CHANGE_AUTO) {
gatt_update_for_database_change();
if (gatt_cb.srv_chg_mode == GATTS_SEND_SERVICE_CHANGE_AUTO) {
gatt_proc_srv_chg();
}
/* remove the new service element after the srv changed processing is completed*/
@@ -980,6 +996,7 @@ tGATT_STATUS GATTC_Read (UINT16 conn_id, tGATT_READ_TYPE type, tGATT_READ_PARAM
memcpy(&p_clcb->uuid, &p_read->service.uuid, sizeof(tBT_UUID));
break;
case GATT_READ_MULTIPLE:
case GATT_READ_MULTIPLE_VAR:
p_clcb->s_handle = 0;
/* copy multiple handles in CB */
p_read_multi = (tGATT_READ_MULTI *)osi_malloc(sizeof(tGATT_READ_MULTI));
@@ -1171,6 +1188,12 @@ tGATT_STATUS GATTC_SendHandleValueConfirm (UINT16 conn_id, UINT16 handle)
return ret;
}
tGATT_STATUS GATTC_AutoDiscoverEnable(UINT8 enable)
{
gatt_cb.auto_disc = (enable > 0) ? TRUE : FALSE;
return GATT_SUCCESS;
}
#endif ///GATTC_INCLUDED == TRUE
/*******************************************************************************/
@@ -1543,7 +1566,8 @@ tGATT_STATUS GATT_SendServiceChangeIndication (BD_ADDR bd_addr)
tGATT_TCB *p_tcb;
tBT_TRANSPORT transport;
tGATT_STATUS status = GATT_NOT_FOUND;
if (GATTS_SEND_SERVICE_CHANGE_MODE == GATTS_SEND_SERVICE_CHANGE_AUTO) {
if (gatt_cb.srv_chg_mode == GATTS_SEND_SERVICE_CHANGE_AUTO) {
status = GATT_WRONG_STATE;
GATT_TRACE_ERROR ("%s can't send service change indication manually, please configure the option through menuconfig", __func__);
return status;
@@ -1675,4 +1699,72 @@ BOOLEAN GATT_Listen (tGATT_IF gatt_if, BOOLEAN start, BD_ADDR_PTR bd_addr)
return gatt_update_listen_mode();
}
tGATT_STATUS GATTS_SetServiceChangeMode(UINT8 mode)
{
if (mode > GATTS_SEND_SERVICE_CHANGE_MANUAL) {
GATT_TRACE_ERROR("%s invalid service change mode %u", __func__, mode);
return GATT_VALUE_NOT_ALLOWED;
}
gatt_cb.srv_chg_mode = mode;
return GATT_SUCCESS;
}
tGATT_STATUS GATTS_HandleMultiValueNotification (UINT16 conn_id, tGATT_HLV *tuples, UINT16 num_tuples)
{
tGATT_STATUS cmd_sent = GATT_ILLEGAL_PARAMETER;
BT_HDR *p_buf;
tGATT_VALUE notif;
tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
UINT8 tcb_idx = GATT_GET_TCB_IDX(conn_id);
tGATT_REG *p_reg = gatt_get_regcb(gatt_if);
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(tcb_idx);
UINT8 *p = notif.value;
tGATT_HLV *p_hlv = tuples;
GATT_TRACE_API ("GATTS_HandleMultiValueNotification");
if ( (p_reg == NULL) || (p_tcb == NULL)) {
GATT_TRACE_ERROR ("GATTS_HandleMultiValueNotification Unknown conn_id: %u \n", conn_id);
return (tGATT_STATUS) GATT_INVALID_CONN_ID;
}
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
GATT_TRACE_ERROR("connection not established\n");
return GATT_WRONG_STATE;
}
if (tuples == NULL) {
return GATT_ILLEGAL_PARAMETER;
}
notif.len = 0;
while (num_tuples) {
if (!GATT_HANDLE_IS_VALID (p_hlv->handle)) {
return GATT_ILLEGAL_PARAMETER;
}
UINT16_TO_STREAM(p, p_hlv->handle); //handle
UINT16_TO_STREAM(p, p_hlv->length); //length
memcpy (p, p_hlv->value, p_hlv->length); //value
GATT_TRACE_DEBUG("%s handle %x, length %u", __func__, p_hlv->handle, p_hlv->length);
p += p_hlv->length;
notif.len += 4 + p_hlv->length;
num_tuples--;
p_hlv++;
}
notif.auth_req = GATT_AUTH_REQ_NONE;
p_buf = attp_build_sr_msg (p_tcb, GATT_HANDLE_MULTI_VALUE_NOTIF, (tGATT_SR_MSG *)&notif);
if (p_buf != NULL) {
cmd_sent = attp_send_sr_msg (p_tcb, p_buf);
} else {
cmd_sent = GATT_NO_RESOURCES;
}
return cmd_sent;
}
#endif

View File

@@ -29,11 +29,18 @@
#include "stack/gatt_api.h"
#include "gatt_int.h"
#include "stack/sdpdefs.h"
#include "bta/bta_gatts_co.h"
#if (BLE_INCLUDED == TRUE && GATTS_INCLUDED == TRUE)
#define BLE_GATT_SR_SUPP_FEAT_EATT_BITMASK 0x01
#define BLE_GATT_CL_SUPP_FEAT_ROBUST_CACHING_BITMASK 0x01
#define BLE_GATT_CL_SUPP_FEAT_EATT_BITMASK 0x02
#define BLE_GATT_CL_SUPP_FEAT_MULTI_NOTIF_BITMASK 0x04
#define BLE_GATT_CL_SUPP_FEAT_BITMASK 0x07
#define GATTP_MAX_NUM_INC_SVR 0
#define GATTP_MAX_CHAR_NUM 2
#define GATTP_MAX_CHAR_NUM 4
#define GATTP_MAX_ATTR_NUM (GATTP_MAX_CHAR_NUM * 2 + GATTP_MAX_NUM_INC_SVR + 1)
#define GATTP_MAX_CHAR_VALUE_SIZE 50
@@ -180,18 +187,26 @@ void gatt_profile_clcb_dealloc (tGATT_PROFILE_CLCB *p_clcb)
** Returns GATT_SUCCESS if successfully sent; otherwise error code.
**
*******************************************************************************/
tGATT_STATUS gatt_proc_read (tGATTS_REQ_TYPE type, tGATT_READ_REQ *p_data, tGATTS_RSP *p_rsp)
tGATT_STATUS gatt_proc_read (UINT16 conn_id, tGATTS_REQ_TYPE type, tGATT_READ_REQ *p_data, tGATTS_RSP *p_rsp)
{
tGATT_STATUS status = GATT_NO_RESOURCES;
UINT16 len = 0;
UINT8 *value;
UNUSED(type);
GATT_TRACE_DEBUG("%s handle %x", __func__, p_data->handle);
UINT8 tcb_idx = GATT_GET_TCB_IDX(conn_id);
tGATT_TCB *tcb = gatt_get_tcb_by_idx(tcb_idx);
if (p_data->is_long) {
p_rsp->attr_value.offset = p_data->offset;
}
p_rsp->attr_value.handle = p_data->handle;
UINT16 len = 0;
uint8_t *value;
/* handle request for reading service changed */
if (p_data->handle == gatt_cb.handle_of_h_r) {
status = GATTS_GetAttributeValue(p_data->handle, &len, &value);
if(status == GATT_SUCCESS && len > 0 && value) {
if(len > GATT_MAX_ATTR_LEN) {
@@ -200,10 +215,76 @@ tGATT_STATUS gatt_proc_read (tGATTS_REQ_TYPE type, tGATT_READ_REQ *p_data, tGATT
p_rsp->attr_value.len = len;
memcpy(p_rsp->attr_value.value, value, len);
}
}
/* handle request for reading client supported features */
if (p_data->handle == gatt_cb.handle_of_cl_supported_feat) {
p_rsp->attr_value.len = 1;
memcpy(p_rsp->attr_value.value, &tcb->cl_supp_feat, 1);
status = GATT_SUCCESS;
}
/* handle request for reading database hash */
if (p_data->handle == gatt_cb.handle_of_database_hash) {
p_rsp->attr_value.len = BT_OCTET16_LEN;
memcpy(p_rsp->attr_value.value, gatt_cb.database_hash, BT_OCTET16_LEN);
gatt_sr_update_cl_status(tcb, true);
status = GATT_SUCCESS;
}
/* handle request for reading server supported features */
if (p_data->handle == gatt_cb.handle_of_sr_supported_feat) {
p_rsp->attr_value.len = 1;
memcpy(p_rsp->attr_value.value, &gatt_cb.gatt_sr_supported_feat_mask, 1);
status = GATT_SUCCESS;
}
return status;
}
static tGATT_STATUS gatt_sr_write_cl_supp_feat(UINT16 conn_id, tGATT_WRITE_REQ *p_data)
{
UINT8 val_new;
UINT8 val_old;
UINT8 val_xor;
UINT8 val_and;
UINT8 *p = p_data->value;
UINT8 tcb_idx = GATT_GET_TCB_IDX(conn_id);
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(tcb_idx);
GATT_TRACE_DEBUG("%s len %u, feat %x", __func__, p_data->len, *p);
if (p_tcb == NULL) {
GATT_TRACE_ERROR("%s no conn", __func__);
return GATT_NOT_FOUND;
}
if (p_data->len != 1) {
GATT_TRACE_ERROR("%s len %u", __func__, p_data->len);
return GATT_INVALID_PDU;
}
STREAM_TO_UINT8(val_new, p);
val_new = (val_new & BLE_GATT_CL_SUPP_FEAT_BITMASK);
if (val_new == 0) {
GATT_TRACE_ERROR("%s bit cannot be all zero", __func__);
return GATT_VALUE_NOT_ALLOWED;
}
val_old = p_tcb->cl_supp_feat;
val_xor = val_old ^ val_new;
val_and = val_xor & val_new;
if (val_and != val_xor) {
GATT_TRACE_ERROR("%s bit cannot be reset", __func__);
return GATT_VALUE_NOT_ALLOWED;
}
p_tcb->cl_supp_feat = val_new;
bta_gatts_co_cl_feat_save(p_tcb->peer_bda, &p_tcb->cl_supp_feat);
return GATT_SUCCESS;
}
/******************************************************************************
**
** Function gatt_proc_write_req
@@ -213,11 +294,28 @@ tGATT_STATUS gatt_proc_read (tGATTS_REQ_TYPE type, tGATT_READ_REQ *p_data, tGATT
** Returns GATT_SUCCESS if successfully sent; otherwise error code.
**
*******************************************************************************/
tGATT_STATUS gatt_proc_write_req( tGATTS_REQ_TYPE type, tGATT_WRITE_REQ *p_data)
tGATT_STATUS gatt_proc_write_req(UINT16 conn_id, tGATTS_REQ_TYPE type, tGATT_WRITE_REQ *p_data)
{
if(p_data->len > GATT_MAX_ATTR_LEN) {
p_data->len = GATT_MAX_ATTR_LEN;
}
if (p_data->handle == gatt_cb.handle_of_h_r) {
return GATT_WRITE_NOT_PERMIT;
}
if (p_data->handle == gatt_cb.handle_of_cl_supported_feat) {
return gatt_sr_write_cl_supp_feat(conn_id, p_data);
}
if (p_data->handle == gatt_cb.handle_of_database_hash) {
return GATT_WRITE_NOT_PERMIT;
}
if (p_data->handle == gatt_cb.handle_of_sr_supported_feat) {
return GATT_WRITE_NOT_PERMIT;
}
return GATTS_SetAttributeValue(p_data->handle,
p_data->len,
p_data->value);
@@ -244,14 +342,14 @@ static void gatt_request_cback (UINT16 conn_id, UINT32 trans_id, tGATTS_REQ_TYPE
switch (type) {
case GATTS_REQ_TYPE_READ:
status = gatt_proc_read(type, &p_data->read_req, &rsp_msg);
status = gatt_proc_read(conn_id, type, &p_data->read_req, &rsp_msg);
break;
case GATTS_REQ_TYPE_WRITE:
if (!p_data->write_req.need_rsp) {
ignore = TRUE;
}
status = gatt_proc_write_req(type, &p_data->write_req);
status = gatt_proc_write_req(conn_id, type, &p_data->write_req);
break;
case GATTS_REQ_TYPE_WRITE_EXEC:
@@ -370,8 +468,21 @@ void gatt_profile_db_init (void)
};
GATTS_AddCharDescriptor (service_handle, GATT_PERM_READ | GATT_PERM_WRITE , &descr_uuid, &attr_val, NULL);
/* start service
*/
/* add Client Supported Features characteristic */
uuid.uu.uuid16 = GATT_UUID_CLIENT_SUP_FEAT;
gatt_cb.handle_of_cl_supported_feat = GATTS_AddCharacteristic(service_handle, &uuid, GATT_PERM_READ | GATT_PERM_WRITE,
GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_WRITE, NULL, NULL);
/* add Database Hash characteristic */
uuid.uu.uuid16 = GATT_UUID_GATT_DATABASE_HASH;
gatt_cb.handle_of_database_hash = GATTS_AddCharacteristic(service_handle, &uuid, GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ, NULL, NULL);
/* add Server Supported Features characteristic */
uuid.uu.uuid16 = GATT_UUID_SERVER_SUP_FEAT;
gatt_cb.handle_of_sr_supported_feat = GATTS_AddCharacteristic(service_handle, &uuid, GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ, NULL, NULL);
/* start service */
status = GATTS_StartService (gatt_cb.gatt_if, service_handle, GATTP_TRANSPORT_SUPPORTED );
#if (CONFIG_BT_STACK_NO_LOG)
@@ -576,4 +687,100 @@ void GATT_ConfigServiceChangeCCC (BD_ADDR remote_bda, BOOLEAN enable, tBT_TRANSP
gatt_cl_start_config_ccc(p_clcb);
}
/*******************************************************************************
**
** Function gatt_sr_is_cl_robust_caching_supported
**
** Description Check if Robust Caching is supported for the connection
**
** Returns true if enabled by client side, otherwise false
**
*******************************************************************************/
static BOOLEAN gatt_sr_is_cl_robust_caching_supported(tGATT_TCB *p_tcb)
{
// Server robust caching not enabled
if (!GATTS_ROBUST_CACHING_ENABLED) {
return FALSE;
}
return (p_tcb->cl_supp_feat & BLE_GATT_CL_SUPP_FEAT_ROBUST_CACHING_BITMASK);
}
/*******************************************************************************
**
** Function gatt_sr_is_cl_change_aware
**
** Description Check if the connection is change-aware
**
** Returns true if change aware, otherwise false
**
*******************************************************************************/
BOOLEAN gatt_sr_is_cl_change_aware(tGATT_TCB *p_tcb)
{
// If robust caching is not supported, should always return true by default
if (!gatt_sr_is_cl_robust_caching_supported(p_tcb)) {
return true;
}
return p_tcb->is_robust_cache_change_aware;
}
/*******************************************************************************
**
** Function gatt_sr_init_cl_status
**
** Description Restore status for trusted device
**
** Returns none
**
*******************************************************************************/
void gatt_sr_init_cl_status(tGATT_TCB *p_tcb)
{
bta_gatts_co_cl_feat_load(p_tcb->peer_bda, &p_tcb->cl_supp_feat);
// This is used to reset bit when robust caching is disabled
if (!GATTS_ROBUST_CACHING_ENABLED) {
p_tcb->cl_supp_feat &= ~BLE_GATT_CL_SUPP_FEAT_ROBUST_CACHING_BITMASK;
}
if (gatt_sr_is_cl_robust_caching_supported(p_tcb)) {
BT_OCTET16 stored_hash = {0};
bta_gatts_co_db_hash_load(p_tcb->peer_bda, stored_hash);
p_tcb->is_robust_cache_change_aware = (memcmp(stored_hash, gatt_cb.database_hash, BT_OCTET16_LEN) == 0);
} else {
p_tcb->is_robust_cache_change_aware = true;
}
GATT_TRACE_DEBUG("%s feat %x aware %d", __func__, p_tcb->cl_supp_feat, p_tcb->is_robust_cache_change_aware);
}
/*******************************************************************************
**
** Function gatt_sr_update_cl_status
**
** Description Update change-aware status for the remote device
**
** Returns none
**
*******************************************************************************/
void gatt_sr_update_cl_status(tGATT_TCB *p_tcb, BOOLEAN chg_aware)
{
if (p_tcb == NULL) {
return;
}
// if robust caching is not supported, do nothing
if (!gatt_sr_is_cl_robust_caching_supported(p_tcb)) {
return;
}
// only when client status is changed from unaware to aware, we should store database hash
if (!p_tcb->is_robust_cache_change_aware && chg_aware) {
bta_gatts_co_db_hash_save(p_tcb->peer_bda, gatt_cb.database_hash);
}
p_tcb->is_robust_cache_change_aware = chg_aware;
GATT_TRACE_DEBUG("%s status %d", __func__, chg_aware);
}
#endif /* BLE_INCLUDED == TRUE && GATTS_INCLUDED == TRUE */

View File

@@ -53,6 +53,7 @@ static const UINT8 disc_type_to_att_opcode[GATT_DISC_MAX] = {
GATT_REQ_FIND_TYPE_VALUE, /* GATT_DISC_SRVC_BY_UUID, */
GATT_REQ_READ_BY_TYPE, /* GATT_DISC_INC_SRVC, */
GATT_REQ_READ_BY_TYPE, /* GATT_DISC_CHAR, */
GATT_REQ_READ_BY_TYPE, /* GATT_DISC_CHAR_BY_UUID, */
GATT_REQ_FIND_INFO /* GATT_DISC_CHAR_DSCPT, */
};
@@ -65,6 +66,41 @@ static const UINT16 disc_type_to_uuid[GATT_DISC_MAX] = {
0 /* no type filtering for DISC_CHAR_DSCPT */
};
// Use for GATTC discover infomation print
#define GATT_DISC_INFO(fmt, args...) {if (gatt_cb.auto_disc == FALSE) BT_PRINT_I("BT_GATT", fmt, ## args);}
char *gatt_uuid_to_str(const tBT_UUID *uuid)
{
static char dst[48] = {0};
const uint8_t *u8p;
memset(dst, 0, sizeof(dst));
switch (uuid->len) {
case LEN_UUID_16:
sprintf(dst, "0x%04x", uuid->uu.uuid16);
break;
case LEN_UUID_32:
sprintf(dst, "0x%08x", uuid->uu.uuid32);
break;
case LEN_UUID_128:
u8p = uuid->uu.uuid128;
sprintf(dst, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-"
"%02x%02x%02x%02x%02x%02x",
u8p[15], u8p[14], u8p[13], u8p[12],
u8p[11], u8p[10], u8p[9], u8p[8],
u8p[7], u8p[6], u8p[5], u8p[4],
u8p[3], u8p[2], u8p[1], u8p[0]);
break;
default:
dst[0] = '\0';
break;
}
return dst;
}
/*******************************************************************************
**
@@ -107,6 +143,10 @@ void gatt_act_discovery(tGATT_CLCB *p_clcb)
}
}
if (p_clcb->op_subtype == GATT_DISC_CHAR_BY_UUID) {
memcpy(&cl_req.browse.uuid, &p_clcb->uuid, sizeof(tBT_UUID));
}
st = attp_send_cl_msg(p_clcb->p_tcb, p_clcb->clcb_idx, op_code, &cl_req);
if (st != GATT_SUCCESS && st != GATT_CMD_STARTED) {
@@ -181,6 +221,11 @@ void gatt_act_read (tGATT_CLCB *p_clcb, UINT16 offset)
memcpy (&msg.read_multi, p_clcb->p_attr_buf, sizeof(tGATT_READ_MULTI));
break;
case GATT_READ_MULTIPLE_VAR:
op_code = GATT_REQ_READ_MULTI_VAR;
memcpy (&msg.read_multi, p_clcb->p_attr_buf, sizeof(tGATT_READ_MULTI));
break;
case GATT_READ_INC_SRV_UUID128:
op_code = GATT_REQ_READ;
msg.handle = p_clcb->s_handle;
@@ -408,6 +453,7 @@ void gatt_process_find_type_value_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UIN
while (len >= 4) {
STREAM_TO_UINT16 (result.handle, p);
STREAM_TO_UINT16 (result.value.group_value.e_handle, p);
GATT_DISC_INFO("%s handle %x, end handle %x", __func__, result.handle, result.value.group_value.e_handle);
memcpy (&result.value.group_value.service_type, &p_clcb->uuid, sizeof(tBT_UUID));
len -= 4;
@@ -474,6 +520,8 @@ void gatt_process_read_info_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_c
len -= (uuid_len + 2);
GATT_DISC_INFO("%s handle %x, uuid %s", __func__, result.handle, gatt_uuid_to_str(&result.type));
if (p_clcb->p_reg->app_cb.p_disc_res_cb) {
(*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
}
@@ -510,7 +558,7 @@ void gatt_proc_disc_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 opcode
case GATT_REQ_FIND_INFO:
if (reason == GATT_NOT_FOUND) {
status = GATT_SUCCESS;
GATT_TRACE_DEBUG("Discovery completed");
GATT_DISC_INFO("Discovery completed");
}
break;
default:
@@ -541,7 +589,7 @@ void gatt_process_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
UNUSED(op_code);
UNUSED(len);
GATT_TRACE_DEBUG("gatt_process_error_rsp ");
GATT_TRACE_DEBUG("%s", __func__);
STREAM_TO_UINT8(opcode, p);
STREAM_TO_UINT16(handle, p);
STREAM_TO_UINT8(reason, p);
@@ -634,7 +682,7 @@ void gatt_process_notification(tGATT_TCB *p_tcb, UINT8 op_code,
UINT16 conn_id;
tGATT_STATUS encrypt_status;
UINT8 *p = p_data, i,
event = (op_code == GATT_HANDLE_VALUE_NOTIF) ? GATTC_OPTYPE_NOTIFICATION : GATTC_OPTYPE_INDICATION;
event = (op_code == GATT_HANDLE_VALUE_IND) ? GATTC_OPTYPE_INDICATION: GATTC_OPTYPE_NOTIFICATION;
GATT_TRACE_DEBUG("gatt_process_notification ");
@@ -644,8 +692,6 @@ void gatt_process_notification(tGATT_TCB *p_tcb, UINT8 op_code,
}
STREAM_TO_UINT16 (value.handle, p);
value.len = len - 2;
memcpy (value.value, p, value.len);
if (!GATT_HANDLE_IS_VALID(value.handle)) {
/* illegal handle, send ack now */
@@ -655,6 +701,28 @@ void gatt_process_notification(tGATT_TCB *p_tcb, UINT8 op_code,
return;
}
if (op_code == GATT_HANDLE_MULTI_VALUE_NOTIF) {
if (len < GATT_NOTIFICATION_MIN_LEN + 2) {
GATT_TRACE_ERROR("illegal notification PDU length, discard");
return;
}
STREAM_TO_UINT16(value.len, p);
if (value.len > len - 4) {
return;
}
} else {
value.len = len - 2;
}
if (value.len > GATT_MAX_ATTR_LEN) {
GATT_TRACE_ERROR("value length larger than GATT_MAX_ATTR_LEN, discard");
return;
}
memcpy(value.value, p, value.len);
p += value.len;
if (event == GATTC_OPTYPE_INDICATION) {
if (p_tcb->ind_count) {
/* this is an error case that receiving an indication but we
@@ -665,19 +733,16 @@ void gatt_process_notification(tGATT_TCB *p_tcb, UINT8 op_code,
GATT_TRACE_ERROR("gatt_process_notification rcv Ind. but ind_count=%d (will reset ind_count)", p_tcb->ind_count);
}
p_tcb->ind_count = 0;
}
/* should notify all registered client with the handle value notificaion/indication
Note: need to do the indication count and start timer first then do callback
*/
for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) {
if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb && (event == GATTC_OPTYPE_INDICATION)) {
p_tcb->ind_count++;
}
}
if (event == GATTC_OPTYPE_INDICATION) {
/* start a timer for app confirmation */
if (p_tcb->ind_count > 0) {
gatt_start_ind_ack_timer(p_tcb);
@@ -694,6 +759,33 @@ void gatt_process_notification(tGATT_TCB *p_tcb, UINT8 op_code,
}
}
if (op_code != GATT_HANDLE_MULTI_VALUE_NOTIF) {
return;
}
if (len < (4 + value.len)) {
GATT_TRACE_ERROR("no remain data for multi notification");
return;
}
len -= (4 + value.len);
while (len > 4) {
STREAM_TO_UINT16(value.handle, p);
STREAM_TO_UINT16(value.len, p);
len -= 4;
value.len = MIN(len, value.len);
memcpy(value.value, p, value.len);
p += value.len;
len -= value.len;
for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) {
if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb) {
conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
(*p_reg->app_cb.p_cmpl_cb) (conn_id, event, encrypt_status, (tGATT_CL_COMPLETE *)&value);
}
}
}
}
/*******************************************************************************
@@ -746,6 +838,7 @@ void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8
while (len >= (handle_len + value_len)) {
STREAM_TO_UINT16(handle, p);
GATT_DISC_INFO("%s op %x, handle %x", __func__, op_code, handle);
if (!GATT_HANDLE_IS_VALID(handle)) {
gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
@@ -775,6 +868,7 @@ void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8
break;
}
}
GATT_DISC_INFO("DISC ALL SVC end handle %x, uuid %s", record_value.group_value.e_handle, gatt_uuid_to_str(&record_value.group_value.service_type));
}
/* discover included service */
else if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->op_subtype == GATT_DISC_INC_SRVC) {
@@ -790,6 +884,8 @@ void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8
if (value_len == 6) {
STREAM_TO_UINT16(record_value.incl_service.service_type.uu.uuid16, p);
record_value.incl_service.service_type.len = LEN_UUID_16;
GATT_DISC_INFO("DISC INC SVC start handle %x, end handle %x, uuid %s",
record_value.incl_service.s_handle, record_value.incl_service.e_handle, gatt_uuid_to_str(&record_value.incl_service.service_type));
} else if (value_len == 4) {
p_clcb->s_handle = record_value.incl_service.s_handle;
p_clcb->read_uuid128.wait_for_read_rsp = TRUE;
@@ -797,7 +893,7 @@ void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8
memcpy(&p_clcb->read_uuid128.result, &result, sizeof(result));
memcpy(&p_clcb->read_uuid128.result.value, &record_value, sizeof (result.value));
p_clcb->op_subtype |= 0x90;
gatt_act_read(p_clcb, 0);
gatt_act_read(p_clcb, 0); // read 128-bit uuid of include service
return;
} else {
GATT_TRACE_ERROR("gatt_process_read_by_type_rsp INCL_SRVC failed with invalid data value_len=%d", value_len);
@@ -937,6 +1033,9 @@ void gatt_process_read_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
memcpy(p_clcb->read_uuid128.result.value.incl_service.service_type.uu.uuid128, p, len);
p_clcb->read_uuid128.result.value.incl_service.service_type.len = LEN_UUID_128;
tGATT_INCL_SRVC *inc_srvc = &p_clcb->read_uuid128.result.value.incl_service;
GATT_DISC_INFO("DISC INC SRVC start handle %x, end handle %x, uuid %s",
inc_srvc->s_handle, inc_srvc->e_handle, gatt_uuid_to_str(&inc_srvc->service_type));
if ( p_clcb->p_reg->app_cb.p_disc_res_cb) {
(*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &p_clcb->read_uuid128.result);
}
@@ -1133,6 +1232,7 @@ void gatt_client_handle_server_rsp (tGATT_TCB *p_tcb, UINT8 op_code,
case GATT_RSP_READ:
case GATT_RSP_READ_BLOB:
case GATT_RSP_READ_MULTI:
case GATT_RSP_READ_MULTI_VAR:
gatt_process_read_rsp(p_tcb, p_clcb, op_code, len, p_data);
break;
@@ -1154,6 +1254,7 @@ void gatt_client_handle_server_rsp (tGATT_TCB *p_tcb, UINT8 op_code,
case GATT_HANDLE_VALUE_NOTIF:
case GATT_HANDLE_VALUE_IND:
case GATT_HANDLE_MULTI_VALUE_NOTIF:
gatt_process_notification(p_tcb, op_code, len, p_data);
break;

View File

@@ -36,6 +36,9 @@
#include "btm_int.h"
#include "common/bte_appl.h"
extern tGATT_STATUS gap_proc_read(tGATTS_REQ_TYPE type, tGATT_READ_REQ *p_data, tGATTS_RSP *p_rsp);
extern tGATT_STATUS gatt_proc_read(UINT16 conn_id, tGATTS_REQ_TYPE type, tGATT_READ_REQ *p_data, tGATTS_RSP *p_rsp);
/********************************************************************************
** L O C A L F U N C T I O N P R O T O T Y P E S *
*********************************************************************************/
@@ -769,6 +772,66 @@ tGATT_STATUS gatts_set_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle,
return GATT_SUCCESS;
}
/*******************************************************************************
**
** Function gatts_get_attr_value_internal
**
** Description This function get the attribute value in gap service and gatt service
**
** Parameter attr_handle: the attribute handle
** length: the attribute value length
** value: the pointer to the data to be get to the attribute value in the database
**
** Returns Status of the operation.
**
*******************************************************************************/
static tGATT_STATUS gatts_get_attr_value_internal(UINT16 attr_handle, UINT16 *length, UINT8 **value)
{
UINT8 i;
tGATT_READ_REQ read_req;
tGATT_STATUS status = GATT_NOT_FOUND;
tGATT_SR_REG *p_rcb = gatt_cb.sr_reg;
UINT8 service_uuid[LEN_UUID_128] = {0};
// find the service by handle
for (i = 0; i < GATT_MAX_SR_PROFILES; i++, p_rcb++) {
if (p_rcb->in_use && p_rcb->s_hdl <= attr_handle && p_rcb->e_hdl >= attr_handle) {
break;
}
}
// service cb not found
if (i == GATT_MAX_SR_PROFILES) {
return status;
}
if (p_rcb->app_uuid.len != LEN_UUID_128) {
return status;
}
memset(&read_req, 0, sizeof(tGATT_READ_REQ));
read_req.handle = attr_handle;
// read gatt service attribute value
memset(service_uuid, 0x81, LEN_UUID_128);
if (!memcmp(p_rcb->app_uuid.uu.uuid128, service_uuid, LEN_UUID_128)) {
status = gatt_proc_read(0, GATTS_REQ_TYPE_READ, &read_req, &gatt_cb.rsp);
}
// read gap service attribute value
memset(service_uuid, 0x82, LEN_UUID_128);
if (!memcmp(p_rcb->app_uuid.uu.uuid128, service_uuid, LEN_UUID_128)) {
status = gap_proc_read(GATTS_REQ_TYPE_READ, &read_req, &gatt_cb.rsp);
}
if (status == GATT_SUCCESS) {
*length = gatt_cb.rsp.attr_value.len;
*value = gatt_cb.rsp.attr_value.value;
}
return status;
}
/*******************************************************************************
**
** Function gatts_get_attribute_value
@@ -810,6 +873,10 @@ tGATT_STATUS gatts_get_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle,
return GATT_INVALID_PDU;
}
if (gatts_get_attr_value_internal(attr_handle, length, value) == GATT_SUCCESS) {
return GATT_SUCCESS;
}
p_cur = (tGATT_ATTR16 *) p_db->p_attr_list;
while (p_cur != NULL) {

View File

@@ -103,6 +103,7 @@ void gatt_init (void)
memset (&gatt_cb, 0, sizeof(tGATT_CB));
memset (&fixed_reg, 0, sizeof(tL2CAP_FIXED_CHNL_REG));
gatt_cb.auto_disc = TRUE;
gatt_cb.p_clcb_list = list_new(osi_free_func);
gatt_cb.p_tcb_list = list_new(osi_free_func);
#if defined(GATT_INITIAL_TRACE_LEVEL)
@@ -114,6 +115,8 @@ void gatt_init (void)
gatt_cb.sign_op_queue = fixed_queue_new(QUEUE_SIZE_MAX);
gatt_cb.srv_chg_clt_q = fixed_queue_new(QUEUE_SIZE_MAX);
gatt_cb.pending_new_srv_start_q = fixed_queue_new(QUEUE_SIZE_MAX);
gatt_cb.srv_chg_mode = GATTS_SEND_SERVICE_CHANGE_MODE;
/* First, register fixed L2CAP channel for ATT over BLE */
fixed_reg.fixed_chnl_opts.mode = L2CAP_FCR_BASIC_MODE;
fixed_reg.fixed_chnl_opts.max_transmit = 0xFF;

View File

@@ -277,6 +277,117 @@ static BOOLEAN process_read_multi_rsp (tGATT_SR_CMD *p_cmd, tGATT_STATUS status,
return (FALSE);
}
static BOOLEAN process_read_multi_var_rsp (tGATT_SR_CMD *p_cmd, tGATT_STATUS status,
tGATTS_RSP *p_msg, UINT16 mtu)
{
UINT16 ii;
UINT16 total_len;
UINT16 len;
UINT8 *p;
GATT_TRACE_DEBUG ("process_read_multi_var rsp status=%d mtu=%d", status, mtu);
if (p_cmd->multi_rsp_q == NULL) {
p_cmd->multi_rsp_q = fixed_queue_new(QUEUE_SIZE_MAX);
}
/* Enqueue the response */
BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(tGATTS_RSP));
if (p_buf == NULL) {
p_cmd->status = GATT_INSUF_RESOURCE;
return FALSE;
}
memcpy((void *)p_buf, (const void *)p_msg, sizeof(tGATTS_RSP));
fixed_queue_enqueue(p_cmd->multi_rsp_q, p_buf, FIXED_QUEUE_MAX_TIMEOUT);
p_cmd->status = status;
if (status == GATT_SUCCESS) {
GATT_TRACE_DEBUG ("Multi var read count=%d num_hdls=%d",
fixed_queue_length(p_cmd->multi_rsp_q),
p_cmd->multi_req.num_handles);
/* Wait till we get all the responses */
if (fixed_queue_length(p_cmd->multi_rsp_q) == p_cmd->multi_req.num_handles) {
len = sizeof(BT_HDR) + L2CAP_MIN_OFFSET + mtu;
if ((p_buf = (BT_HDR *)osi_calloc(len)) == NULL) {
p_cmd->status = GATT_INSUF_RESOURCE;
return (TRUE);
}
p_buf->offset = L2CAP_MIN_OFFSET;
p = (UINT8 *)(p_buf + 1) + p_buf->offset;
/* First byte in the response is the opcode */
*p++ = GATT_RSP_READ_MULTI_VAR;
p_buf->len = 1;
/* Now walk through the buffers puting the data into the response in order */
list_t *list = NULL;
const list_node_t *node = NULL;
if (! fixed_queue_is_empty(p_cmd->multi_rsp_q)) {
list = fixed_queue_get_list(p_cmd->multi_rsp_q);
}
for (ii = 0; ii < p_cmd->multi_req.num_handles; ii++) {
tGATTS_RSP *p_rsp = NULL;
if (list != NULL) {
if (ii == 0) {
node = list_begin(list);
} else {
node = list_next(node);
}
if (node != list_end(list)) {
p_rsp = (tGATTS_RSP *)list_node(node);
}
}
if (p_rsp != NULL) {
total_len = (p_buf->len + 2); // value length
if (total_len > mtu) {
GATT_TRACE_DEBUG ("multi read variable overflow available len=%d val_len=%d", len, p_rsp->attr_value.len );
break;
}
len = MIN(p_rsp->attr_value.len, (mtu - total_len)); // attribute value length
if (p_rsp->attr_value.handle == p_cmd->multi_req.handles[ii]) {
GATT_TRACE_DEBUG("%s handle %x len %u", __func__, p_rsp->attr_value.handle, p_rsp->attr_value.len);
UINT16_TO_STREAM(p, p_rsp->attr_value.len);
memcpy (p, p_rsp->attr_value.value, len);
p += len;
p_buf->len += (2+len);
} else {
p_cmd->status = GATT_NOT_FOUND;
break;
}
} else {
p_cmd->status = GATT_NOT_FOUND;
break;
}
} /* loop through all handles*/
/* Sanity check on the buffer length */
if (p_buf->len == 0) {
GATT_TRACE_ERROR("%s - nothing found!!", __func__);
p_cmd->status = GATT_NOT_FOUND;
osi_free (p_buf);
} else if (p_cmd->p_rsp_msg != NULL) {
osi_free (p_buf);
} else {
p_cmd->p_rsp_msg = p_buf;
}
return (TRUE);
}
} else { /* any handle read exception occurs, return error */
return (TRUE);
}
/* If here, still waiting */
return (FALSE);
}
/*******************************************************************************
**
** Function gatt_sr_process_app_rsp
@@ -303,6 +414,10 @@ tGATT_STATUS gatt_sr_process_app_rsp (tGATT_TCB *p_tcb, tGATT_IF gatt_if,
if (!process_read_multi_rsp (&p_tcb->sr_cmd, status, p_msg, p_tcb->payload_size)) {
return (GATT_SUCCESS);
}
} else if (op_code == GATT_REQ_READ_MULTI_VAR) {
if (!process_read_multi_var_rsp(&p_tcb->sr_cmd, status, p_msg, p_tcb->payload_size)) {
return (GATT_SUCCESS);
}
} else {
if (op_code == GATT_REQ_PREPARE_WRITE && status == GATT_SUCCESS) {
gatt_sr_update_prep_cnt(p_tcb, gatt_if, TRUE, FALSE);
@@ -514,7 +629,7 @@ void gatt_process_read_multi_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U
sec_flag,
key_size))
!= GATT_SUCCESS) {
GATT_TRACE_DEBUG("read permission denied : 0x%02x", err);
GATT_TRACE_ERROR("read permission denied : 0x%02x", err);
break;
}
} else {
@@ -525,6 +640,7 @@ void gatt_process_read_multi_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U
ll -= 2;
}
if (err == GATT_SUCCESS) {
if (ll != 0) {
GATT_TRACE_ERROR("max attribute handle reached in ReadMultiple Request.");
err = GATT_INVALID_HANDLE;
@@ -533,6 +649,7 @@ void gatt_process_read_multi_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U
if (p_tcb->sr_cmd.multi_req.num_handles == 0) {
err = GATT_INVALID_HANDLE;
}
}
if (err == GATT_SUCCESS) {
if ((trans_id = gatt_sr_enqueue_cmd (p_tcb, op_code, p_tcb->sr_cmd.multi_req.handles[0])) != 0) {
@@ -1563,6 +1680,9 @@ static BOOLEAN gatts_proc_ind_ack(tGATT_TCB *p_tcb, UINT16 ack_handle)
gatts_proc_srv_chg_ind_ack(p_tcb);
/* there is no need to inform the application since srv chg is handled internally by GATT */
continue_processing = FALSE;
/* after receiving ack of svc_chg_ind, reset client status */
gatt_sr_update_cl_status(p_tcb, true);
}
gatts_chk_pending_ind(p_tcb);
@@ -1609,6 +1729,85 @@ void gatts_process_value_conf(tGATT_TCB *p_tcb, UINT8 op_code)
}
}
static BOOLEAN gatts_handle_db_out_of_sync(tGATT_TCB *p_tcb, UINT8 op_code,
UINT16 len, UINT8 *p_data)
{
if (gatt_sr_is_cl_change_aware(p_tcb)) {
return false;
}
bool should_ignore = true;
bool should_rsp = true;
switch (op_code) {
case GATT_REQ_READ_BY_TYPE:
{
tBT_UUID uuid;
UINT16 s_hdl = 0;
UINT16 e_hdl = 0;
UINT16 db_hash_handle = gatt_cb.handle_of_database_hash;
tGATT_STATUS reason = gatts_validate_packet_format(op_code, &len, &p_data, &uuid, &s_hdl, &e_hdl);
if (reason == GATT_SUCCESS &&
(s_hdl <= db_hash_handle && db_hash_handle <= e_hdl) &&
(uuid.uu.uuid16 == GATT_UUID_GATT_DATABASE_HASH)) {
should_ignore = false;
}
break;
}
case GATT_REQ_READ:
// for pts don't process read request
#if 0
{
UINT16 handle = 0;
UINT8 *p = p_data;
tGATT_STATUS status = GATT_SUCCESS;
if (len < 2) {
status = GATT_INVALID_PDU;
} else {
STREAM_TO_UINT16(handle, p);
len -= 2;
}
if (status == GATT_SUCCESS && handle == gatt_cb.handle_of_database_hash) {
should_ignore = false;
}
break;
}
#endif
case GATT_REQ_READ_BY_GRP_TYPE:
case GATT_REQ_FIND_TYPE_VALUE:
case GATT_REQ_FIND_INFO:
case GATT_REQ_READ_BLOB:
case GATT_REQ_READ_MULTI:
case GATT_REQ_READ_MULTI_VAR:
case GATT_REQ_WRITE:
case GATT_REQ_PREPARE_WRITE:
break;
case GATT_CMD_WRITE:
case GATT_SIGN_CMD_WRITE:
should_rsp = false;
break;
case GATT_REQ_MTU:
case GATT_REQ_EXEC_WRITE:
case GATT_HANDLE_VALUE_CONF:
default:
should_ignore = false;
break;
}
if (should_ignore) {
if (should_rsp) {
gatt_send_error_rsp(p_tcb, GATT_DATABASE_OUT_OF_SYNC, op_code, 0x0000, false);
}
GATT_TRACE_ERROR("database out of sync op_code %x, should_rsp %d", op_code, should_rsp);
gatt_sr_update_cl_status(p_tcb, should_rsp);
}
return should_ignore;
}
/*******************************************************************************
**
** Function gatt_server_handle_client_req
@@ -1640,6 +1839,11 @@ void gatt_server_handle_client_req (tGATT_TCB *p_tcb, UINT8 op_code,
}
/* otherwise, ignore the pkt */
} else {
// handle database out of sync
if (gatts_handle_db_out_of_sync(p_tcb, op_code, len, p_data)) {
return;
}
switch (op_code) {
case GATT_REQ_READ_BY_GRP_TYPE: /* discover primary services */
case GATT_REQ_FIND_TYPE_VALUE: /* discover service by UUID */
@@ -1678,6 +1882,7 @@ void gatt_server_handle_client_req (tGATT_TCB *p_tcb, UINT8 op_code,
break;
case GATT_REQ_READ_MULTI:
case GATT_REQ_READ_MULTI_VAR:
gatt_process_read_multi_req (p_tcb, op_code, len, p_data);
break;

View File

@@ -0,0 +1,171 @@
#include "common/bt_target.h"
#include "osi/allocator.h"
#include <string.h>
#include "gatt_int.h"
#include "stack/l2c_api.h"
#include "l2c_int.h"
#include "smp_int.h"
#if (BLE_INCLUDED == TRUE && GATTS_INCLUDED == TRUE)
static void attr_uuid_to_bt_uuid(void *p_attr, tBT_UUID *p_uuid)
{
tGATT_ATTR16 *p_attr16 = (tGATT_ATTR16 *)p_attr;
if (p_attr16->uuid_type == GATT_ATTR_UUID_TYPE_16) {
p_uuid->len = LEN_UUID_16;
p_uuid->uu.uuid16 = p_attr16->uuid;
} else if (p_attr16->uuid_type == GATT_ATTR_UUID_TYPE_32) {
tGATT_ATTR32 *p_attr32 = (tGATT_ATTR32 *)p_attr;
p_uuid->len = LEN_UUID_32;
p_uuid->uu.uuid32 = p_attr32->uuid;
} else if (p_attr16->uuid_type == GATT_ATTR_UUID_TYPE_128) {
tGATT_ATTR128 *p_attr128 = (tGATT_ATTR128 *)p_attr;
p_uuid->len = LEN_UUID_128;
memcpy(p_uuid->uu.uuid128, p_attr128->uuid, LEN_UUID_128);
}
}
static size_t calculate_database_info_size(void)
{
UINT8 i;
tGATT_SVC_DB *p_db;
tGATT_ATTR16 *p_attr;
size_t len = 0;
for (i = 0; i < GATT_MAX_SR_PROFILES; i++) {
p_db = gatt_cb.sr_reg[i].p_db;
if (p_db && p_db->p_attr_list) {
p_attr = (tGATT_ATTR16 *)p_db->p_attr_list;
while (p_attr) {
if (p_attr->uuid == GATT_UUID_PRI_SERVICE ||
p_attr->uuid == GATT_UUID_SEC_SERVICE) {
// Service declaration
len += 4 + p_attr->p_value->uuid.len;
} else if (p_attr->uuid == GATT_UUID_INCLUDE_SERVICE) {
// Included service declaration
len += 8 + p_attr->p_value->incl_handle.service_type.len;
} else if (p_attr->uuid == GATT_UUID_CHAR_DECLARE) {
tBT_UUID char_uuid;
// Characteristic declaration
p_attr = (tGATT_ATTR16 *)p_attr->p_next;
attr_uuid_to_bt_uuid((void *)p_attr, &char_uuid);
// Increment 1 to fetch characteristic uuid from value declaration attribute
len += 7 + char_uuid.len;
} else if (p_attr->uuid == GATT_UUID_CHAR_DESCRIPTION ||
p_attr->uuid == GATT_UUID_CHAR_CLIENT_CONFIG ||
p_attr->uuid == GATT_UUID_CHAR_SRVR_CONFIG ||
p_attr->uuid == GATT_UUID_CHAR_PRESENT_FORMAT ||
p_attr->uuid == GATT_UUID_CHAR_AGG_FORMAT) {
// Descriptor
len += 4;
} else if (p_attr->uuid == GATT_UUID_CHAR_EXT_PROP) {
// Descriptor
len += 6;
}
p_attr = (tGATT_ATTR16 *) p_attr->p_next;
}
}
}
return len;
}
static void fill_database_info(UINT8 *p_data)
{
UINT8 i;
tGATT_SVC_DB *p_db;
tGATT_ATTR16 *p_attr;
for (i = 0; i < GATT_MAX_SR_PROFILES; i++) {
p_db = gatt_cb.sr_reg[i].p_db;
if (p_db && p_db->p_attr_list) {
p_attr = (tGATT_ATTR16 *)p_db->p_attr_list;
while (p_attr) {
if (p_attr->uuid == GATT_UUID_PRI_SERVICE ||
p_attr->uuid == GATT_UUID_SEC_SERVICE) {
// Service declaration
UINT16_TO_STREAM(p_data, p_attr->handle);
UINT16_TO_STREAM(p_data, p_attr->uuid);
gatt_build_uuid_to_stream(&p_data, p_attr->p_value->uuid);
} else if (p_attr->uuid == GATT_UUID_INCLUDE_SERVICE) {
// Included service declaration
UINT16_TO_STREAM(p_data, p_attr->handle);
UINT16_TO_STREAM(p_data, GATT_UUID_INCLUDE_SERVICE);
UINT16_TO_STREAM(p_data, p_attr->p_value->incl_handle.s_handle);
UINT16_TO_STREAM(p_data, p_attr->p_value->incl_handle.e_handle);
gatt_build_uuid_to_stream(&p_data, p_attr->p_value->incl_handle.service_type);
} else if (p_attr->uuid == GATT_UUID_CHAR_DECLARE) {
tBT_UUID char_uuid;
// Characteristic declaration
UINT16_TO_STREAM(p_data, p_attr->handle);
UINT16_TO_STREAM(p_data, GATT_UUID_CHAR_DECLARE);
UINT8_TO_STREAM(p_data, p_attr->p_value->char_decl.property);
UINT16_TO_STREAM(p_data, p_attr->p_value->char_decl.char_val_handle);
p_attr = (tGATT_ATTR16 *)p_attr->p_next;
attr_uuid_to_bt_uuid((void *)p_attr, &char_uuid);
// Increment 1 to fetch characteristic uuid from value declaration attribute
gatt_build_uuid_to_stream(&p_data, char_uuid);
} else if (p_attr->uuid == GATT_UUID_CHAR_DESCRIPTION ||
p_attr->uuid == GATT_UUID_CHAR_CLIENT_CONFIG ||
p_attr->uuid == GATT_UUID_CHAR_SRVR_CONFIG ||
p_attr->uuid == GATT_UUID_CHAR_PRESENT_FORMAT ||
p_attr->uuid == GATT_UUID_CHAR_AGG_FORMAT) {
// Descriptor
UINT16_TO_STREAM(p_data, p_attr->handle);
UINT16_TO_STREAM(p_data, p_attr->uuid);
} else if (p_attr->uuid == GATT_UUID_CHAR_EXT_PROP) {
// Descriptor
UINT16_TO_STREAM(p_data, p_attr->handle);
UINT16_TO_STREAM(p_data, p_attr->uuid);
// TODO: process extended properties descriptor
if (p_attr->p_value->attr_val.attr_len == 2) {
memcpy(p_data, p_attr->p_value->attr_val.attr_val, 2);
} else {
UINT16_TO_STREAM(p_data, 0x0000);
}
}
p_attr = (tGATT_ATTR16 *) p_attr->p_next;
}
}
}
}
tGATT_STATUS gatts_calculate_datebase_hash(BT_OCTET16 hash)
{
UINT8 tmp;
UINT16 i;
UINT16 j;
size_t len;
UINT8 *data_buf = NULL;
len = calculate_database_info_size();
data_buf = (UINT8 *)osi_malloc(len);
if (data_buf == NULL) {
GATT_TRACE_ERROR ("%s failed to allocate buffer (%u)\n", __func__, len);
return GATT_NO_RESOURCES;
}
fill_database_info(data_buf);
// reverse database info
for (i = 0, j = len-1; i < j; i++, j--) {
tmp = data_buf[i];
data_buf[i] = data_buf[j];
data_buf[j] = tmp;
}
#if SMP_INCLUDED == TRUE
BT_OCTET16 key = {0};
aes_cipher_msg_auth_code(key, data_buf, len, 16, hash);
//ESP_LOG_BUFFER_HEX("db hash", hash, BT_OCTET16_LEN);
#else
// TODO
GATT_TRACE_ERROR("%s SMP disabled", __func__);
#endif
osi_free(data_buf);
return GATT_SUCCESS;
}
#endif /* BLE_INCLUDED == TRUE && GATTS_INCLUDED == TRUE */

View File

@@ -1090,6 +1090,7 @@ tGATT_TCB *gatt_allocate_tcb_by_bdaddr(BD_ADDR bda, tBT_TRANSPORT transport)
p_tcb->transport = transport;
}
memcpy(p_tcb->peer_bda, bda, BD_ADDR_LEN);
gatt_sr_init_cl_status(p_tcb);
}
return p_tcb;
}

View File

@@ -405,6 +405,13 @@ typedef struct {
UINT8 pending_cl_req;
UINT8 next_slot_inq; /* index of next available slot in queue */
/* client supported feature */
UINT8 cl_supp_feat;
/* server supported feature */
UINT8 sr_supp_feat;
/* if false, should handle database out of sync */
BOOLEAN is_robust_cache_change_aware;
BOOLEAN in_use;
UINT8 tcb_idx;
tGATT_PREPARE_WRITE_RECORD prepare_write_record; /* prepare write packets record */
@@ -532,6 +539,12 @@ typedef struct {
tGATT_PROFILE_CLCB profile_clcb[GATT_MAX_APPS];
#endif ///GATTS_INCLUDED == TRUE
UINT16 handle_of_h_r; /* Handle of the handles reused characteristic value */
UINT16 handle_of_database_hash;
UINT16 handle_of_cl_supported_feat;
UINT16 handle_of_sr_supported_feat;
BT_OCTET16 database_hash;
UINT8 gatt_sr_supported_feat_mask;
UINT8 gatt_cl_supported_feat_mask;
tGATT_APPL_INFO cb_info;
@@ -540,6 +553,9 @@ typedef struct {
tGATT_HDL_CFG hdl_cfg;
tGATT_BG_CONN_DEV bgconn_dev[GATT_MAX_BG_CONN_DEV];
BOOLEAN auto_disc; /* internal use: true for auto discovering after connected */
UINT8 srv_chg_mode; /* internal use: service change mode */
tGATTS_RSP rsp; /* use to read internal service attribute */
} tGATT_CB;
typedef struct{
@@ -759,4 +775,9 @@ extern BOOLEAN gatt_check_connection_state_by_tcb(tGATT_TCB *p_tcb);
extern void gatt_reset_bgdev_list(void);
extern uint16_t gatt_get_local_mtu(void);
extern void gatt_set_local_mtu(uint16_t mtu);
extern tGATT_STATUS gatts_calculate_datebase_hash(BT_OCTET16 hash);
extern BOOLEAN gatt_sr_is_cl_change_aware(tGATT_TCB *p_tcb);
extern void gatt_sr_init_cl_status(tGATT_TCB *p_tcb);
extern void gatt_sr_update_cl_status(tGATT_TCB *tcb, BOOLEAN chg_aware);
#endif

View File

@@ -1782,4 +1782,87 @@ UINT8 btsnd_hcic_ble_write_rf_path_compensation(UINT16 rf_tx_path, UINT16 rf_rx_
return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p);
}
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
#if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
UINT8 btsnd_hcic_ble_set_periodic_adv_recv_enable(UINT16 sync_handle, UINT8 enable)
{
BT_HDR *p;
UINT8 *pp;
HCIC_BLE_CMD_CREATED(p, pp, 3);
pp = (UINT8 *)(p + 1);
UINT16_TO_STREAM(pp, HCI_BLE_SET_PERIOD_ADV_RECV_ENABLE);
UINT8_TO_STREAM(pp, 3);
UINT16_TO_STREAM(pp, sync_handle);
UINT8_TO_STREAM(pp, enable);
return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p);
}
UINT8 btsnd_hcic_ble_periodic_adv_sync_trans(UINT16 conn_handle, UINT16 service_data, UINT16 sync_handle)
{
BT_HDR *p;
UINT8 *pp;
HCIC_BLE_CMD_CREATED(p, pp, 6);
pp = (UINT8 *)(p + 1);
UINT16_TO_STREAM(pp, HCI_BLE_PERIOD_ADV_SYNC_TRANS);
UINT8_TO_STREAM(pp, 6);
UINT16_TO_STREAM(pp, conn_handle);
UINT16_TO_STREAM(pp, service_data);
UINT16_TO_STREAM(pp, sync_handle);
return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p);
}
UINT8 btsnd_hcic_ble_periodic_adv_set_info_trans(UINT16 conn_handle, UINT16 service_data, UINT8 adv_handle)
{
BT_HDR *p;
UINT8 *pp;
HCI_TRACE_DEBUG("%s conn handle %x, adv handle %x", __func__, conn_handle, adv_handle);
HCIC_BLE_CMD_CREATED(p, pp, 5);
pp = (UINT8 *)(p + 1);
UINT16_TO_STREAM(pp, HCI_BLE_PERIOD_ADV_SET_INFO_TRANS);
UINT8_TO_STREAM(pp, 5);
UINT16_TO_STREAM(pp, conn_handle);
UINT16_TO_STREAM(pp, service_data);
UINT8_TO_STREAM(pp, adv_handle);
return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p);
}
UINT8 btsnd_hcic_ble_set_periodic_adv_sync_trans_params(UINT16 conn_handle, UINT8 mode, UINT16 skip, UINT16 sync_timeout, UINT8 cte_type)
{
BT_HDR *p;
UINT8 *pp;
HCI_TRACE_DEBUG("%s conn handle %x, mode %x, sync timeout %x", __func__, conn_handle, mode, sync_timeout);
HCIC_BLE_CMD_CREATED(p, pp, 8);
pp = (UINT8 *)(p + 1);
UINT16_TO_STREAM(pp, HCI_BLE_SET_PERIOD_ADV_SYNC_TRANS_PARAMS);
UINT8_TO_STREAM(pp, 8);
UINT16_TO_STREAM(pp, conn_handle);
UINT8_TO_STREAM(pp, mode);
UINT16_TO_STREAM(pp, skip);
UINT16_TO_STREAM(pp, sync_timeout);
UINT8_TO_STREAM(pp, cte_type);
return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p);
}
#endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
#endif

View File

@@ -1765,6 +1765,7 @@ typedef union {
#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
tBTM_LE_COMPLT complt; /* BTM_LE_COMPLT_EVT */
tSMP_OOB_DATA_TYPE req_oob_type;
tSMP_LOC_OOB_DATA local_oob_data;
#endif
tBTM_LE_KEY key;
} tBTM_LE_EVT_DATA;

View File

@@ -1288,6 +1288,21 @@ typedef void (*tBTM_BLE_5_HCI_CBACK)(tBTM_BLE_5_GAP_EVENT event, tBTM_BLE_5_GAP_
#endif //#if (BLE_50_FEATURE_SUPPORT == TRUE)
#if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
typedef struct {
UINT8 status;
UINT16 conn_handle;
UINT16 service_data;
UINT16 sync_handle;
UINT8 adv_sid;
UINT8 adv_addr_type;
BD_ADDR adv_addr;
UINT8 adv_phy;
UINT16 period_adv_interval;
UINT8 adv_clk_accuracy;
} tBTM_BLE_PERIOD_ADV_SYNC_TRANS_RECV;
#endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
/*****************************************************************************
** EXTERNAL FUNCTION DECLARATIONS
*****************************************************************************/
@@ -1809,6 +1824,29 @@ void BTM_BleConfirmReply (BD_ADDR bd_addr, UINT8 res);
//extern
void BTM_BleOobDataReply(BD_ADDR bd_addr, UINT8 res, UINT8 len, UINT8 *p_data);
/*******************************************************************************
**
** Function BTM_BleSecureConnectionOobDataReply
**
** Description This function is called to provide the OOB data for
** SMP in response to BTM_LE_SC_OOB_REQ_EVT when secure connection
**
** Parameters: bd_addr - Address of the peer device
** p_c - pointer to Confirmation
** p_r - pointer to Randomizer
**
*******************************************************************************/
void BTM_BleSecureConnectionOobDataReply(BD_ADDR bd_addr, UINT8 *p_c, UINT8 *p_r);
/*******************************************************************************
**
** Function BTM_BleSecureConnectionCreateOobData
**
** Description This function is called to create the OOB data for
** SMP when secure connection
**
*******************************************************************************/
void BTM_BleSecureConnectionCreateOobData(void);
/*******************************************************************************
**
@@ -2614,7 +2652,12 @@ tBTM_STATUS BTM_BleSetExtendedScanParams(tBTM_BLE_EXT_SCAN_PARAMS *params);
tBTM_STATUS BTM_BleExtendedScan(BOOLEAN enable, UINT16 duration, UINT16 period);
void BTM_BleSetPreferExtenedConnParams(BD_ADDR bd_addr, tBTM_EXT_CONN_PARAMS *params);
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
#if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
void BTM_BlePeriodicAdvSetInfoTrans(BD_ADDR bd_addr, UINT16 service_data, UINT8 adv_handle);
void BTM_BleSetPeriodicAdvSyncTransParams(BD_ADDR bd_addr, UINT8 mode, UINT16 skip, UINT16 sync_timeout, UINT8 cte_type);
#endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
#endif

View File

@@ -44,6 +44,8 @@
#define GATT_INSUF_ENCRYPTION 0x0f
#define GATT_UNSUPPORT_GRP_TYPE 0x10
#define GATT_INSUF_RESOURCE 0x11
#define GATT_DATABASE_OUT_OF_SYNC 0x12
#define GATT_VALUE_NOT_ALLOWED 0x13
#define GATT_NO_RESOURCES 0x80
@@ -108,8 +110,11 @@ typedef UINT8 tGATT_STATUS;
#define GATT_HANDLE_VALUE_NOTIF 0x1B
#define GATT_HANDLE_VALUE_IND 0x1D
#define GATT_HANDLE_VALUE_CONF 0x1E
#define GATT_REQ_READ_MULTI_VAR 0x20
#define GATT_RSP_READ_MULTI_VAR 0x21
#define GATT_HANDLE_MULTI_VALUE_NOTIF 0x23
#define GATT_SIGN_CMD_WRITE 0xD2 /* changed in V4.0 1101-0010 (signed write) see write cmd above*/
#define GATT_OP_CODE_MAX GATT_HANDLE_VALUE_CONF + 1 /* 0x1E = 30 + 1 = 31*/
#define GATT_OP_CODE_MAX GATT_HANDLE_MULTI_VALUE_NOTIF + 1 /* 0x1E = 30 + 1 = 31*/
#define GATT_COMMAND_FLAG 0x40 /* Command Flag: set to one means command */
@@ -413,6 +418,7 @@ enum {
GATT_DISC_SRVC_BY_UUID, /* discover service of a special type */
GATT_DISC_INC_SRVC, /* discover the included service within a service */
GATT_DISC_CHAR, /* discover characteristics of a service with/without type requirement */
GATT_DISC_CHAR_BY_UUID, /* discover characteristic with type requirement */
GATT_DISC_CHAR_DSCPT, /* discover characteristic descriptors of a character */
GATT_DISC_MAX /* maximnun discover type */
};
@@ -432,6 +438,7 @@ enum {
GATT_READ_BY_TYPE = 1,
GATT_READ_BY_HANDLE,
GATT_READ_MULTIPLE,
GATT_READ_MULTIPLE_VAR,
GATT_READ_CHAR_VALUE,
GATT_READ_PARTIAL,
GATT_READ_MAX
@@ -655,6 +662,12 @@ typedef struct {
tGATTS_NV_SRV_CHG_CBACK *p_srv_chg_callback;
} tGATT_APPL_INFO;
typedef struct {
UINT16 handle;
UINT16 length;
UINT8 *value;
} tGATT_HLV;
/*
*********************** End Handle Management Definitions **********************/
@@ -1032,6 +1045,18 @@ extern tGATT_STATUS GATTC_ExecuteWrite (UINT16 conn_id, BOOLEAN is_execute);
*******************************************************************************/
extern tGATT_STATUS GATTC_SendHandleValueConfirm (UINT16 conn_id, UINT16 handle);
/*******************************************************************************
**
** Function GATTC_AutoDiscoverEnable
**
** Description This function is called to enable/disable auto discover.
**
** Parameters enable: 0 for disable, otherwise enable.
**
** Returns GATT_SUCCESS if command started successfully.
**
*******************************************************************************/
extern tGATT_STATUS GATTC_AutoDiscoverEnable(UINT8 enable);
/*******************************************************************************
**
@@ -1226,6 +1251,34 @@ extern BOOLEAN GATT_Listen (tGATT_IF gatt_if, BOOLEAN start, BD_ADDR_PTR bd_addr
extern void GATT_ConfigServiceChangeCCC (BD_ADDR remote_bda, BOOLEAN enable,
tBT_TRANSPORT transport);
/*******************************************************************************
**
** Function GATTS_SetServiceChangeMode
**
** Description Configure service change indication mode
**
** Parameters mode: service change mode
**
** Returns Status.
**
*******************************************************************************/
extern tGATT_STATUS GATTS_SetServiceChangeMode(UINT8 mode);
/*******************************************************************************
**
** Function GATTS_HandleMultiValueNotification
**
** Description This function sends multiple handle value notification to a client.
**
** Parameter conn_id: connection identifier.
** tuples: Pointer to handle-length-value tuple list.
** num_tuples: Number of tuples.
**
** Returns GATT_SUCCESS if successfully sent; otherwise error code.
**
*******************************************************************************/
extern tGATT_STATUS GATTS_HandleMultiValueNotification (UINT16 conn_id, tGATT_HLV *tuples, UINT16 num_tuples);
#ifdef __cplusplus
}

View File

@@ -121,4 +121,8 @@
#define GATT_UUID_SCAN_INT_WINDOW 0x2A4F
#define GATT_UUID_SCAN_REFRESH 0x2A31
#define GATT_UUID_CLIENT_SUP_FEAT 0x2B29
#define GATT_UUID_GATT_DATABASE_HASH 0x2B2A
#define GATT_UUID_SERVER_SUP_FEAT 0x2B3A
#endif

View File

@@ -385,6 +385,12 @@
#define HCI_BLE_WR_RF_PATH_COMPENSATION (0x004D | HCI_GRP_BLE_CMDS)
#define HCI_BLE_SET_PRIVACY_MODE (0x004E | HCI_GRP_BLE_CMDS)
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
#if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
#define HCI_BLE_SET_PERIOD_ADV_RECV_ENABLE (0x0059 | HCI_GRP_BLE_CMDS)
#define HCI_BLE_PERIOD_ADV_SYNC_TRANS (0x005A | HCI_GRP_BLE_CMDS)
#define HCI_BLE_PERIOD_ADV_SET_INFO_TRANS (0x005B | HCI_GRP_BLE_CMDS)
#define HCI_BLE_SET_PERIOD_ADV_SYNC_TRANS_PARAMS (0x005C | HCI_GRP_BLE_CMDS)
#endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
// Vendor OGF define
#define HCI_VENDOR_OGF 0x3F
@@ -802,6 +808,9 @@
#define HCI_BLE_SCAN_REQ_RECEIVED_EVT 0x13
#define HCI_BLE_CHANNEL_SELECT_ALG 0x14
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
#if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
#define HCI_BLE_PERIOD_ADV_SYNC_TRANS_RECV_EVT 0x18
#endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
/* Definitions for LE Channel Map */
#define HCI_BLE_CHNL_MAP_SIZE 5

View File

@@ -1031,7 +1031,17 @@ UINT8 btsnd_hcic_ble_read_trans_power(void);
UINT8 btsnd_hcic_ble_read_rf_path_compensation(void);
UINT8 btsnd_hcic_ble_write_rf_path_compensation(UINT16 rf_tx_path, UINT16 rf_rx_path);
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
#if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
UINT8 btsnd_hcic_ble_set_periodic_adv_recv_enable(UINT16 sync_handle, UINT8 enable);
UINT8 btsnd_hcic_ble_periodic_adv_sync_trans(UINT16 conn_handle, UINT16 service_data, UINT16 sync_handle);
UINT8 btsnd_hcic_ble_periodic_adv_set_info_trans(UINT16 conn_handle, UINT16 service_data, UINT8 adv_handle);
UINT8 btsnd_hcic_ble_set_periodic_adv_sync_trans_params(UINT16 conn_handle, UINT8 mode, UINT16 skip, UINT16 sync_timeout, UINT8 cte_type);
#endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE)
#define HCIC_PARAM_SIZE_WRITE_AUTHENT_PAYLOAD_TOUT 4
#define HCI__WRITE_AUTHENT_PAYLOAD_TOUT_HANDLE_OFF 0

View File

@@ -321,4 +321,16 @@
#define L2CAP_FCR_INIT_CRC 0 /* Initial state of the CRC register */
#define L2CAP_FCR_SEQ_MODULO 0x3F /* Mask for sequence numbers (range 0 - 63) */
#define L2CAP_LE_RESULT_CONN_OK 0
#define L2CAP_LE_RESULT_NO_PSM 2
#define L2CAP_LE_RESULT_NO_RESOURCES 4
#define L2CAP_LE_RESULT_INSUFFICIENT_AUTHENTICATION 5
#define L2CAP_LE_RESULT_INSUFFICIENT_AUTHORIZATION 6
#define L2CAP_LE_RESULT_INSUFFICIENT_ENCRY_KEY_SIZE 7
#define L2CAP_LE_RESULT_INSUFFICIENT_ENCRY 8
#define L2CAP_LE_RESULT_INVALID_SOURCE_CID 9
#define L2CAP_LE_RESULT_SOURCE_CID_ALREADY_ALLOCATED 0x0A
#define L2CAP_LE_RESULT_UNACCEPTABLE_PARAMETERS 0x0B
#define L2CAP_LE_RESULT_INVALID_PARAMETERS 0x0C
#endif

View File

@@ -498,13 +498,9 @@ extern void SMP_KeypressNotification (BD_ADDR bd_addr, UINT8 value);
** Description This function is called to start creation of local SC OOB
** data set (tSMP_LOC_OOB_DATA).
**
** Parameters: bd_addr - Address of the device to send OOB data block
** to.
**
** Returns Boolean - TRUE: creation of local SC OOB data set started.
*******************************************************************************/
extern BOOLEAN SMP_CreateLocalSecureConnectionsOobData (
tBLE_BD_ADDR *addr_to_send_to);
extern BOOLEAN SMP_CreateLocalSecureConnectionsOobData (void);
#ifdef __cplusplus
}

View File

@@ -757,6 +757,69 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
}
break;
}
case L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ: {
tL2C_CCB *p_ccb = NULL;
tL2C_RCB *p_rcb = NULL;
UINT16 spsm;
UINT16 scid;
UINT16 mtu;
UINT16 mps;
UINT16 credits;
STREAM_TO_UINT16(spsm, p);
STREAM_TO_UINT16(scid, p);
STREAM_TO_UINT16(mtu, p);
STREAM_TO_UINT16(mps, p);
STREAM_TO_UINT16(credits, p);
L2CAP_TRACE_DEBUG("%s spsm %x, scid %x", __func__, spsm, scid);
p_ccb = l2cu_find_ccb_by_remote_cid(p_lcb, scid);
if (p_ccb) {
l2cu_reject_ble_connection(p_lcb, id, L2CAP_LE_RESULT_SOURCE_CID_ALREADY_ALLOCATED);
break;
}
#if 0
p_rcb = l2cu_find_ble_rcb_by_psm(spsm);
if (p_rcb == NULL) {
break;
}
#endif
p_ccb = l2cu_allocate_ccb(p_lcb, 0);
if (p_ccb == NULL) {
l2cu_reject_ble_connection(p_lcb, id, L2CAP_LE_RESULT_NO_RESOURCES);
break;
}
p_ccb->remote_id = id;
p_ccb->p_rcb = p_rcb;
p_ccb->remote_cid = scid;
p_ccb->local_conn_cfg.mtu = mtu;
p_ccb->local_conn_cfg.mps = controller_get_interface()->get_acl_data_size_ble();
p_ccb->local_conn_cfg.credits = credits;
p_ccb->peer_conn_cfg.mtu = mtu;
p_ccb->peer_conn_cfg.mps = mps;
p_ccb->peer_conn_cfg.credits = credits;
l2cu_send_peer_ble_credit_based_conn_res(p_ccb, L2CAP_LE_RESULT_CONN_OK);
break;
}
case L2CAP_CMD_DISC_REQ: {
tL2C_CCB *p_ccb = NULL;
UINT16 lcid;
UINT16 rcid;
STREAM_TO_UINT16(lcid, p);
STREAM_TO_UINT16(rcid, p);
p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
if (p_ccb) {
p_ccb->remote_id = id;
// TODO
}
l2cu_send_peer_disc_rsp(p_lcb, id, lcid, rcid);
break;
}
default:
L2CAP_TRACE_WARNING ("L2CAP - LE - unknown cmd code: %d", cmd_code);
l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);

View File

@@ -527,6 +527,9 @@ extern BOOLEAN smp_calculate_f5_key(UINT8 *w, UINT8 *t);
extern BOOLEAN smp_calculate_f6(UINT8 *w, UINT8 *n1, UINT8 *n2, UINT8 *r, UINT8 *iocap,
UINT8 *a1, UINT8 *a2, UINT8 *f3);
extern BOOLEAN smp_calculate_h6(UINT8 *w, UINT8 *keyid, UINT8 *h2);
extern void smp_save_local_oob_data(tSMP_CB *p_cb);
extern void smp_clear_local_oob_data(void);
extern tSMP_LOC_OOB_DATA *smp_get_local_oob_data(void);
#if SMP_DEBUG == TRUE
extern void smp_debug_print_nbyte_little_endian (UINT8 *p, const UINT8 *key_name,
UINT8 len);

View File

@@ -622,7 +622,7 @@ void smp_proc_pair_cmd(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
}
}
if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB) {
if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB && p_cb->loc_oob_flag == SMP_OOB_PRESENT) {
if (smp_request_oob_data(p_cb)) {
return;
}
@@ -661,7 +661,8 @@ void smp_proc_pair_cmd(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
}
}
if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB) {
/* Only if peer oob data present, then should request peer oob data */
if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB && p_cb->loc_oob_flag == SMP_OOB_PRESENT) {
if (smp_request_oob_data(p_cb)) {
return;
}
@@ -1459,7 +1460,7 @@ void smp_process_io_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
}
}
if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB) {
if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB && p_cb->loc_oob_flag == SMP_OOB_PRESENT) {
if (smp_request_oob_data(p_cb)) {
return;
}
@@ -1947,6 +1948,7 @@ void smp_set_local_oob_random_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
p_cb->sc_oob_data.loc_oob_data.randomizer, 0,
p_cb->sc_oob_data.loc_oob_data.commitment);
p_cb->sc_oob_data.loc_oob_data.present = true;
#if SMP_DEBUG == TRUE
UINT8 *p_print = NULL;
SMP_TRACE_DEBUG("local SC OOB data set:\n");
@@ -1975,6 +1977,9 @@ void smp_set_local_oob_random_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
p_cb->cb_evt = SMP_SC_LOC_OOB_DATA_UP_EVT;
smp_send_app_cback(p_cb, NULL);
// Store the data for later use when we are paired with
smp_save_local_oob_data(p_cb);
smp_cb_cleanup(p_cb);
}

View File

@@ -471,6 +471,9 @@ void SMP_SecureConnectionOobDataReply(UINT8 *p_data)
return;
}
/* Set local oob data when req_oob_type = SMP_OOB_BOTH */
memcpy(&p_oob->loc_oob_data, smp_get_local_oob_data(), sizeof(tSMP_LOC_OOB_DATA));
SMP_TRACE_EVENT ("%s req_oob_type: %d, loc_oob_data.present: %d, "
"peer_oob_data.present: %d",
__FUNCTION__, p_cb->req_oob_type, p_oob->loc_oob_data.present,
@@ -504,6 +507,7 @@ void SMP_SecureConnectionOobDataReply(UINT8 *p_data)
}
if (data_missing) {
SMP_TRACE_ERROR("%s data missing", __func__);
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
return;
}
@@ -589,32 +593,13 @@ void SMP_KeypressNotification (BD_ADDR bd_addr, UINT8 value)
** Description This function is called to start creation of local SC OOB
** data set (tSMP_LOC_OOB_DATA).
**
** Parameters: bd_addr - Address of the device to send OOB data block to
**
** Returns Boolean - TRUE: creation of local SC OOB data set started.
*******************************************************************************/
BOOLEAN SMP_CreateLocalSecureConnectionsOobData (tBLE_BD_ADDR *addr_to_send_to)
BOOLEAN SMP_CreateLocalSecureConnectionsOobData (void)
{
tSMP_CB *p_cb = &smp_cb;
#if (!CONFIG_BT_STACK_NO_LOG)
UINT8 *bd_addr;
#endif
if (addr_to_send_to == NULL) {
SMP_TRACE_ERROR ("%s addr_to_send_to is not provided", __FUNCTION__);
return FALSE;
}
#if (!CONFIG_BT_STACK_NO_LOG)
bd_addr = addr_to_send_to->bda;
#endif
SMP_TRACE_EVENT ("%s addr type: %u, BDA: %08x%04x, state: %u, br_state: %u",
__FUNCTION__, addr_to_send_to->type,
(bd_addr[0] << 24) + (bd_addr[1] << 16) + (bd_addr[2] << 8) + bd_addr[3],
(bd_addr[4] << 8) + bd_addr[5],
p_cb->state,
p_cb->br_state);
SMP_TRACE_EVENT ("%s state: %u, br_state: %u", __FUNCTION__, p_cb->state, p_cb->br_state);
if ((p_cb->state != SMP_STATE_IDLE) || (p_cb->smp_over_br)) {
SMP_TRACE_WARNING ("%s creation of local OOB data set "\
@@ -622,7 +607,6 @@ BOOLEAN SMP_CreateLocalSecureConnectionsOobData (tBLE_BD_ADDR *addr_to_send_to)
return FALSE;
}
p_cb->sc_oob_data.loc_oob_data.addr_sent_to = *addr_to_send_to;
smp_sm_event(p_cb, SMP_CR_LOC_SC_OOB_DATA_EVT, NULL);
return TRUE;

View File

@@ -71,6 +71,32 @@ static const tSMP_ACT smp_encrypt_action[] = {
smp_generate_rand_cont /* SMP_GEN_SRAND_MRAND_CONT */
};
/* If there is data saved here, then use its info instead
* This needs to be cleared on a successful pairing using the oob data
*/
static tSMP_LOC_OOB_DATA saved_local_oob_data = {};
void smp_save_local_oob_data(tSMP_CB *p_cb)
{
memcpy(&saved_local_oob_data, &p_cb->sc_oob_data.loc_oob_data, sizeof(tSMP_LOC_OOB_DATA));
}
void smp_clear_local_oob_data(void)
{
memset(&saved_local_oob_data, 0, sizeof(tSMP_LOC_OOB_DATA));
}
static BOOLEAN oob_data_is_empty(tSMP_LOC_OOB_DATA *data)
{
tSMP_LOC_OOB_DATA empty_data = {0};
return (memcmp(data, &empty_data, sizeof(tSMP_LOC_OOB_DATA)) == 0);
}
tSMP_LOC_OOB_DATA *smp_get_local_oob_data(void)
{
return &saved_local_oob_data;
}
void smp_debug_print_nbyte_little_endian(UINT8 *p, const UINT8 *key_name, UINT8 len)
{
#if SMP_DEBUG == TRUE
@@ -973,7 +999,19 @@ BOOLEAN smp_calculate_legacy_short_term_key(tSMP_CB *p_cb, tSMP_ENC *output)
*******************************************************************************/
void smp_create_private_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
SMP_TRACE_DEBUG ("%s", __FUNCTION__);
SMP_TRACE_DEBUG("%s", __func__);
if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB) {
SMP_TRACE_EVENT("OOB Association Model");
if (!oob_data_is_empty(&saved_local_oob_data)) {
SMP_TRACE_EVENT("Found OOB data, loading keys");
memcpy(&p_cb->sc_oob_data.loc_oob_data, &saved_local_oob_data, sizeof(tSMP_LOC_OOB_DATA));
smp_process_private_key(p_cb);
return;
}
SMP_TRACE_EVENT("OOB Association Model with no saved data");
}
p_cb->rand_enc_proc_state = SMP_GENERATE_PRIVATE_KEY_0_7;
if (!btsnd_hcic_ble_rand((void *)smp_rand_back)) {
smp_rand_back(NULL);
@@ -1005,7 +1043,7 @@ void smp_use_oob_private_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
case SMP_OOB_BOTH:
case SMP_OOB_LOCAL:
SMP_TRACE_DEBUG("%s restore secret key\n", __func__);
memcpy(p_cb->private_key, p_cb->sc_oob_data.loc_oob_data.private_key_used, BT_OCTET32_LEN);
// copy private key in smp_process_private_key
smp_process_private_key(p_cb);
break;
default:
@@ -1082,13 +1120,22 @@ void smp_process_private_key(tSMP_CB *p_cb)
{
Point public_key;
BT_OCTET32 private_key;
tSMP_LOC_OOB_DATA *p_loc_oob = &p_cb->sc_oob_data.loc_oob_data;
SMP_TRACE_DEBUG ("%s", __FUNCTION__);
/* if local oob data present, then restore oob private and public key */
if (p_loc_oob->present) {
memcpy(p_cb->private_key, p_loc_oob->private_key_used, BT_OCTET32_LEN);
memcpy(p_cb->loc_publ_key.x, p_loc_oob->publ_key_used.x, BT_OCTET32_LEN);
memcpy(p_cb->loc_publ_key.y, p_loc_oob->publ_key_used.y, BT_OCTET32_LEN);
memcpy(p_cb->local_random, p_loc_oob->randomizer, BT_OCTET16_LEN);
} else {
memcpy(private_key, p_cb->private_key, BT_OCTET32_LEN);
ECC_PointMult(&public_key, &(curve_p256.G), (DWORD *) private_key, KEY_LENGTH_DWORDS_P256);
memcpy(p_cb->loc_publ_key.x, public_key.x, BT_OCTET32_LEN);
memcpy(p_cb->loc_publ_key.y, public_key.y, BT_OCTET32_LEN);
}
smp_debug_print_nbyte_little_endian (p_cb->private_key, (const UINT8 *)"private",
BT_OCTET32_LEN);

View File

@@ -1031,6 +1031,8 @@ void smp_proc_pairing_cmpl(tSMP_CB *p_cb)
#endif ///BLE_INCLUDED == TRUE
smp_reset_control_value(p_cb);
// TODO: clear local oob data when start advertising
smp_clear_local_oob_data();
if (p_callback) {
(*p_callback) (SMP_COMPLT_EVT, pairing_bda, &evt_data);