Merge branch 'bugfix/fix_ble_security_issue_2025_v3_v5.4' into 'release/v5.4'

fix(ble/bluedroid): Fix type mismatch and length validation in HCI packet parser (v5.4)

See merge request espressif/esp-idf!44666
This commit is contained in:
Island
2026-01-12 12:10:41 +08:00
76 changed files with 3015 additions and 212 deletions

View File

@@ -65,10 +65,15 @@ void osi_mutex_unlock(osi_mutex_t *mutex)
xSemaphoreGive(*mutex);
}
/** Delete a semaphore
* @param mutex the mutex to delete */
/** Delete a mutex
* @param mutex the mutex to delete
* Note: Safe to call with NULL or uninitialized mutex (IDFGH-16853)
*/
void osi_mutex_free(osi_mutex_t *mutex)
{
if (mutex == NULL || *mutex == NULL) {
return;
}
vSemaphoreDelete(*mutex);
*mutex = NULL;
}

View File

@@ -69,9 +69,15 @@ osi_sem_take(osi_sem_t *sem, uint32_t timeout)
return ret;
}
// Deallocates a semaphore
/** Deallocates a semaphore
* @param sem the semaphore to delete
* Note: Safe to call with NULL or uninitialized semaphore (IDFGH-16853)
*/
void osi_sem_free(osi_sem_t *sem)
{
if (sem == NULL || *sem == NULL) {
return;
}
vSemaphoreDelete(*sem);
*sem = NULL;
}

View File

@@ -354,7 +354,7 @@ config BT_GATTC_MAX_CACHE_CHAR
config BT_GATTC_NOTIF_REG_MAX
int "Max gattc notify(indication) register number"
depends on BT_GATTC_ENABLE
range 1 64
range 1 255
default 5
help
Maximum GATTC notify(indication) register number
@@ -1359,6 +1359,16 @@ config BT_BLE_FEAT_CREATE_SYNC_ENH
help
Enable the create sync enhancements
config BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX
int "Maximum retry count for periodic advertising create sync"
depends on BT_BLE_50_EXTEND_SYNC_EN
default 3
range 0 16
help
Set the maximum retry count when periodic advertising create sync fails
with error code 0x3E (Connection Failed to be Established).
Set to 0 to disable retry. Default is 3.
menuconfig BT_BLE_FEAT_ISO_EN
bool "Enable BLE 5.2 iso feature"
depends on (BT_BLE_50_FEATURES_SUPPORTED && ((BT_CONTROLLER_ENABLED && SOC_BLE_AUDIO_SUPPORTED) || BT_CONTROLLER_DISABLED)) # NOERROR

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -283,6 +283,27 @@ typedef uint8_t esp_gap_ble_channels[ESP_GAP_BLE_CHANNELS_LEN];
#define VENDOR_HCI_CMD_MASK (0x3F << 10) /**!< 0xFC00 */
/**
* @brief BLE time interval conversion macros
*
* These macros convert time values in milliseconds to BLE interval units.
*
* - Advertising interval: unit is 0.625ms (range: 20ms to 10240ms)
* - Connection interval: unit is 1.25ms (range: 7.5ms to 4000ms)
* - Scan interval/window: unit is 0.625ms
* - Periodic advertising interval: unit is 1.25ms
* - Supervision timeout: unit is 10ms (range: 100ms to 32000ms)
*
* @note If the input value is not an exact multiple of the unit, the result will be rounded to the nearest value.
* For example, ESP_BLE_GAP_ADV_ITVL_MS(25) = 40 (25ms / 0.625ms = 40), but ESP_BLE_GAP_ADV_ITVL_MS(25.5) = 40 (rounded).
*/
#define ESP_BLE_GAP_ADV_ITVL_MS(t) ((uint16_t)((t) * 1000 / 625)) /*!< Convert advertising interval from ms to 0.625ms units. If input is not a multiple of 0.625ms, it will be rounded to the nearest value. */
#define ESP_BLE_GAP_SCAN_ITVL_MS(t) ((uint16_t)((t) * 1000 / 625)) /*!< Convert scan interval from ms to 0.625ms units. If input is not a multiple of 0.625ms, it will be rounded to the nearest value. */
#define ESP_BLE_GAP_SCAN_WIN_MS(t) ((uint16_t)((t) * 1000 / 625)) /*!< Convert scan window from ms to 0.625ms units. If input is not a multiple of 0.625ms, it will be rounded to the nearest value. */
#define ESP_BLE_GAP_CONN_ITVL_MS(t) ((uint16_t)((t) * 1000 / 1250)) /*!< Convert connection interval from ms to 1.25ms units. If input is not a multiple of 1.25ms, it will be rounded to the nearest value. */
#define ESP_BLE_GAP_PERIODIC_ADV_ITVL_MS(t) ((uint16_t)((t) * 1000 / 1250)) /*!< Convert periodic advertising interval from ms to 1.25ms units. If input is not a multiple of 1.25ms, it will be rounded to the nearest value. */
#define ESP_BLE_GAP_SUPERVISION_TIMEOUT_MS(t) ((uint16_t)((t) / 10)) /*!< Convert supervision timeout from ms to 10ms units. If input is not a multiple of 10ms, it will be rounded to the nearest value. */
/* relate to BTM_BLE_AD_TYPE_xxx in stack/btm_ble_api.h */
/// The type of advertising data(not adv_type)
typedef enum {

View File

@@ -528,6 +528,79 @@ BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
APPL_TRACE_ERROR("%s(), line = %d, alloc fail, no memory.", __func__, __LINE__);
return FALSE;
}
} else if (p_data->hdr.event == BTA_GATTC_API_SEARCH_EVT) {
/*
* Fix for Use-After-Free (UAF) bug in service search with filter_uuid.
*
* Problem Description:
* ====================
* In BTA_GATTC_ServiceSearchRequest(), memory is allocated as:
* [tBTA_GATTC_API_SEARCH structure][tBT_UUID data]
*
* The p_srvc_uuid pointer points to the tBT_UUID data located right after
* the structure:
* p_buf->p_srvc_uuid = (tBT_UUID *)(p_buf + 1);
*
* When this command is enqueued (e.g., during DISCOVER_ST state), the original
* code only performed a shallow copy:
* - Only sizeof(tBTA_GATTC_DATA) was allocated for cmd_data
* - memcpy copied the pointer VALUE (not the pointed data)
* - After the original message is freed by bta_sys_event(), the p_srvc_uuid
* pointer becomes a dangling pointer pointing to freed memory
*
* Memory layout before fix:
*
* Original (p_data): Copy (cmd_data):
* +------------------+----------+ +------------------+
* | API_SEARCH | tBT_UUID | | API_SEARCH |
* | p_srvc_uuid: --------► | | p_srvc_uuid: --------► (dangling!)
* +------------------+----------+ +------------------+
* ↑
* After free(), this memory may be
* overwritten by other allocations
*
* Solution:
* =========
* For BTA_GATTC_API_SEARCH_EVT with non-NULL p_srvc_uuid, we need to:
* 1. Allocate extra space for tBT_UUID
* 2. Copy the structure
* 3. Update p_srvc_uuid to point to the new location
* 4. Copy the tBT_UUID data
*
* Memory layout after fix:
*
* Copy (cmd_data):
* +------------------+----------+
* | API_SEARCH | tBT_UUID |
* | p_srvc_uuid: --------► | (points to its own copy)
* +------------------+----------+
*/
if (p_data->api_search.p_srvc_uuid != NULL) {
/* Allocate space for structure + UUID data (deep copy) */
len = sizeof(tBTA_GATTC_DATA) + sizeof(tBT_UUID);
if ((cmd_data = (tBTA_GATTC_DATA *)osi_malloc(len)) != NULL) {
memset(cmd_data, 0, len);
/* Copy the structure */
memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA));
/* Update pointer to point to the space after the structure */
cmd_data->api_search.p_srvc_uuid = (tBT_UUID *)(cmd_data + 1);
/* Copy the UUID data */
memcpy(cmd_data->api_search.p_srvc_uuid,
p_data->api_search.p_srvc_uuid, sizeof(tBT_UUID));
} else {
APPL_TRACE_ERROR("%s(), line = %d, alloc fail, no memory.", __func__, __LINE__);
return FALSE;
}
} else {
/* p_srvc_uuid is NULL, no extra space needed (search all services) */
if ((cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA))) != NULL) {
memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA));
memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA));
} else {
APPL_TRACE_ERROR("%s(), line = %d, alloc fail, no memory.", __func__, __LINE__);
return FALSE;
}
}
} else {
if ((cmd_data = (tBTA_GATTC_DATA *)osi_malloc(sizeof(tBTA_GATTC_DATA))) != NULL) {
memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA));

View File

@@ -247,6 +247,12 @@
#define UC_BT_BLE_FEAT_CREATE_SYNC_ENH FALSE
#endif
#ifdef CONFIG_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX
#define UC_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX CONFIG_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX
#else
#define UC_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX 3
#endif
#ifdef CONFIG_BT_BLE_FEAT_ISO_EN
#define UC_BT_BLE_FEAT_ISO_EN CONFIG_BT_BLE_FEAT_ISO_EN
#else

View File

@@ -296,6 +296,12 @@
#define BLE_FEAT_CREATE_SYNC_ENH FALSE
#endif
#ifdef UC_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX
#define BLE_FEAT_CREATE_SYNC_RETRY_MAX UC_BT_BLE_FEAT_CREATE_SYNC_RETRY_MAX
#else
#define BLE_FEAT_CREATE_SYNC_RETRY_MAX 3
#endif
#if (UC_BT_BLE_FEAT_ISO_EN == TRUE)
#define BLE_FEAT_ISO_EN TRUE
#else

View File

@@ -87,7 +87,7 @@ typedef struct {
uint16_t ble_ext_adv_data_max_len;
#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE)
#if (BLE_50_EXTEND_SYNC_EN == TRUE)
uint16_t get_ble_periodic_advertiser_list_size;
uint8_t get_ble_periodic_advertiser_list_size;
#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE)
#endif //#if (BLE_50_FEATURE_SUPPORT == TRUE)
} controller_local_param_t;

View File

@@ -219,7 +219,7 @@ static void parse_ble_read_suggested_default_data_length_response(
uint16_t *ble_default_packet_txtime_ptr)
{
uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_DEFAULT_DATA_LENGTH, 2 /* bytes after */);
uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_DEFAULT_DATA_LENGTH, 4 /* bytes after: 2+2 */);
if (stream) {
STREAM_TO_UINT16(*ble_default_packet_length_ptr, stream);
STREAM_TO_UINT16(*ble_default_packet_txtime_ptr, stream);
@@ -235,7 +235,7 @@ static void parse_ble_read_adv_max_len_response(
uint16_t *adv_max_len_ptr)
{
uint8_t *stream = read_command_complete_header(response, HCI_BLE_RD_MAX_ADV_DATA_LEN, 1 /* bytes after */);
uint8_t *stream = read_command_complete_header(response, HCI_BLE_RD_MAX_ADV_DATA_LEN, 2 /* bytes after */);
if (stream) {
// Size: 2 Octets ; Value: 0x001F 0x0672 ; Maximum supported advertising data length
STREAM_TO_UINT16(*adv_max_len_ptr, stream);
@@ -246,7 +246,7 @@ static void parse_ble_read_adv_max_len_response(
#if (BLE_50_EXTEND_SYNC_EN == TRUE)
static void parse_ble_read_periodic_adv_list_size_response(
BT_HDR *response,
uint16_t *periodic_adv_list_size_ptr)
uint8_t *periodic_adv_list_size_ptr)
{
uint8_t *stream = read_command_complete_header(response, HCI_BLE_RD_PERIOD_ADV_LIST_SIZE, 1 /* bytes after */);

View File

@@ -114,7 +114,7 @@ typedef struct {
#if (BLE_50_EXTEND_SYNC_EN == TRUE)
void (*parse_ble_read_periodic_adv_list_size_response) (
BT_HDR *response,
uint16_t *periodic_advertiser_list_size
uint8_t *periodic_advertiser_list_size
);
#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE)
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)

View File

@@ -39,6 +39,19 @@ typedef struct {
tBTM_EXT_ADV_RECORD adv_record[MAX_BLE_ADV_INSTANCE] = {0};
#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE)
#if (BLE_50_EXTEND_SYNC_EN == TRUE)
#if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0)
/* Create sync retry control block */
typedef struct {
bool in_use; /* Whether sync creation is in progress */
uint8_t retry_count; /* Current retry count */
tBTM_BLE_Periodic_Sync_Params params; /* Saved sync parameters for retry */
} tBTM_BLE_SYNC_RETRY_CB;
static tBTM_BLE_SYNC_RETRY_CB sync_retry_cb = {0};
#endif // #if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0)
#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE)
extern void btm_ble_inter_set(bool extble_inter);
#if !UC_BT_STACK_NO_LOG
@@ -880,11 +893,19 @@ tBTM_STATUS BTM_BlePeriodicAdvCreateSync(tBTM_BLE_Periodic_Sync_Params *params)
SET_BIT(option, 2);
}
#endif // (BLE_FEAT_CREATE_SYNC_ENH == TRUE)
#if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0)
/* Save parameters for potential retry */
memcpy(&sync_retry_cb.params, params, sizeof(tBTM_BLE_Periodic_Sync_Params));
sync_retry_cb.retry_count = 0;
sync_retry_cb.in_use = true;
#endif // #if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0)
if (!btsnd_hcic_ble_periodic_adv_create_sync(option, params->sid, params->addr_type,
params->addr, params->sync_timeout, params->sync_cte_type)) {
BTM_TRACE_ERROR("LE PA CreateSync cmd failed");
status = BTM_ILLEGAL_VALUE;
#if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0)
sync_retry_cb.in_use = false;
#endif // #if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0)
}
end:
@@ -942,6 +963,11 @@ tBTM_STATUS BTM_BlePeriodicAdvSyncCancel(void)
tBTM_STATUS status = BTM_SUCCESS;
tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0};
#if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0)
/* Clear retry state when sync is cancelled */
sync_retry_cb.in_use = false;
sync_retry_cb.retry_count = 0;
#endif // #if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0)
if ((err = btsnd_hcic_ble_periodic_adv_create_sync_cancel()) != HCI_SUCCESS) {
BTM_TRACE_ERROR("LE PA SyncCancel, cmd err=0x%x", err);
status = BTM_HCI_ERROR | err;
@@ -1399,6 +1425,48 @@ void btm_ble_periodic_adv_sync_establish_evt(tBTM_BLE_PERIOD_ADV_SYNC_ESTAB *par
return;
}
#if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0)
/* Check if retry is needed for error 0x3E (Connection Failed to be Established) */
if (params->status == HCI_ERR_CONN_FAILED_ESTABLISHMENT &&
sync_retry_cb.in_use &&
sync_retry_cb.retry_count < BLE_FEAT_CREATE_SYNC_RETRY_MAX) {
sync_retry_cb.retry_count++;
BTM_TRACE_WARNING("%s, Create sync failed with 0x3E, retry %d/%d",
__func__, sync_retry_cb.retry_count, BLE_FEAT_CREATE_SYNC_RETRY_MAX);
/* Build option from saved parameters */
uint8_t option = 0x00;
if (sync_retry_cb.params.filter_policy) {
SET_BIT(option, 0);
}
#if (BLE_FEAT_CREATE_SYNC_ENH == TRUE)
if (sync_retry_cb.params.reports_disabled) {
SET_BIT(option, 1);
}
if (sync_retry_cb.params.filter_duplicates) {
SET_BIT(option, 2);
}
#endif // (BLE_FEAT_CREATE_SYNC_ENH == TRUE)
/* Retry create sync with saved parameters */
if (btsnd_hcic_ble_periodic_adv_create_sync(option,
sync_retry_cb.params.sid,
sync_retry_cb.params.addr_type,
sync_retry_cb.params.addr,
sync_retry_cb.params.sync_timeout,
sync_retry_cb.params.sync_cte_type)) {
/* Retry command sent successfully, wait for next event */
return;
}
/* If retry command failed, fall through to report failure */
BTM_TRACE_ERROR("%s, Retry create sync command failed", __func__);
}
/* Clear retry state */
sync_retry_cb.in_use = false;
sync_retry_cb.retry_count = 0;
#endif // #if (BLE_FEAT_CREATE_SYNC_RETRY_MAX > 0)
memcpy(&cb_params.sync_estab, params, sizeof(tBTM_BLE_PERIOD_ADV_SYNC_ESTAB));
// If the user has register the callback function, should callback it to the application.

View File

@@ -554,7 +554,13 @@ void gatt_process_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
UNUSED(op_code);
UNUSED(len);
/* Fix: Validate minimum length (opcode:1 + handle:2 + reason:1 = 4 bytes) */
if (len < 4) {
GATT_TRACE_ERROR("invalid error rsp len: %d", len);
gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
return;
}
GATT_TRACE_DEBUG("%s", __func__);
STREAM_TO_UINT8(opcode, p);
@@ -800,6 +806,14 @@ void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8
handle_len = 4;
}
/* Check value_len is sufficient before subtraction to prevent underflow */
if (value_len < handle_len) {
GATT_TRACE_ERROR("gatt_process_read_by_type_rsp: value_len(%d) < handle_len(%d), invalid response",
value_len, handle_len);
gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
return;
}
value_len -= handle_len; /* subtract the handle pairs bytes */
len -= 1;

View File

@@ -479,7 +479,13 @@ void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U
BOOLEAN is_need_dequeue_sr_cmd = FALSE;
tGATT_PREPARE_WRITE_RECORD *prepare_record = NULL;
tGATT_PREPARE_WRITE_QUEUE_DATA * queue_data = NULL;
UNUSED(len);
/* Fix: Validate minimum length (flags: 1 byte) */
if (len < 1) {
GATT_TRACE_ERROR("invalid exec write req len: %d", len);
gatt_send_error_rsp(p_tcb, GATT_INVALID_PDU, op_code, 0, FALSE);
return;
}
#if GATT_CONFORMANCE_TESTING == TRUE
if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code) {
@@ -1234,10 +1240,13 @@ void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle,
switch (op_code) {
case GATT_SIGN_CMD_WRITE:
if (op_code == GATT_SIGN_CMD_WRITE) {
GATT_TRACE_DEBUG("Write CMD with data signing" );
len -= GATT_AUTH_SIGN_LEN;
/* Fix: Validate length before subtraction to prevent underflow */
if (len < GATT_AUTH_SIGN_LEN) {
GATT_TRACE_ERROR("signed write len too short: %d", len);
return; /* GATT_SIGN_CMD_WRITE has no response */
}
GATT_TRACE_DEBUG("Write CMD with data signing" );
len -= GATT_AUTH_SIGN_LEN;
/* fall through */
case GATT_CMD_WRITE:
case GATT_REQ_WRITE:
@@ -1473,7 +1482,13 @@ static void gatts_process_read_req(tGATT_TCB *p_tcb, tGATT_SR_REG *p_rcb, UINT8
UINT8 sec_flag, key_size, *p;
UINT16 offset = 0, value_len = 0;
UNUSED (len);
/* Fix: Validate length for GATT_REQ_READ_BLOB (needs offset: 2 bytes) */
if (op_code == GATT_REQ_READ_BLOB && len < 2) {
GATT_TRACE_ERROR("invalid read blob req len: %d", len);
gatt_send_error_rsp(p_tcb, GATT_INVALID_PDU, op_code, handle, FALSE);
return;
}
if ((p_msg = (BT_HDR *)osi_calloc(buf_len)) == NULL) {
GATT_TRACE_ERROR("gatts_process_find_info failed. no resources.\n");

View File

@@ -715,6 +715,11 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
UINT16 cmd_len;
UINT16 min_interval, max_interval, latency, timeout;
if (pkt_len < L2CAP_CMD_OVERHEAD) {
L2CAP_TRACE_WARNING ("L2CAP - LE - pkt too short: %d", pkt_len);
return;
}
p_pkt_end = p + pkt_len;
STREAM_TO_UINT8 (cmd_code, p);
@@ -731,6 +736,10 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
case L2CAP_CMD_REJECT:
case L2CAP_CMD_ECHO_RSP:
case L2CAP_CMD_INFO_RSP:
if (cmd_len < 2) {
L2CAP_TRACE_WARNING ("L2CAP - LE - short cmd: %d", cmd_len);
return;
}
p += 2;
break;
case L2CAP_CMD_ECHO_REQ:
@@ -739,6 +748,10 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
break;
case L2CAP_CMD_BLE_UPDATE_REQ:
if (cmd_len < 8) {
L2CAP_TRACE_WARNING ("L2CAP - LE - short cmd: %d", cmd_len);
return;
}
STREAM_TO_UINT16 (min_interval, p); /* 0x0006 - 0x0C80 */
STREAM_TO_UINT16 (max_interval, p); /* 0x0006 - 0x0C80 */
STREAM_TO_UINT16 (latency, p); /* 0x0000 - 0x03E8 */
@@ -781,6 +794,10 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
break;
case L2CAP_CMD_BLE_UPDATE_RSP: {
if (cmd_len < 2) {
L2CAP_TRACE_WARNING ("L2CAP - LE - short cmd: %d", cmd_len);
return;
}
UINT16 result = 0;
STREAM_TO_UINT16(result, p); //result = 0 connection param accepted, result = 1 connection param rejected.
UINT8 status = (result == 0) ? HCI_SUCCESS : HCI_ERR_PARAM_OUT_OF_RANGE;
@@ -793,6 +810,10 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
break;
}
case L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ: {
if (cmd_len < 10) {
L2CAP_TRACE_WARNING ("L2CAP - LE - short cmd: %d", cmd_len);
return;
}
tL2C_CCB *p_ccb = NULL;
tL2C_RCB *p_rcb = NULL;
UINT16 spsm;
@@ -841,6 +862,10 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
break;
}
case L2CAP_CMD_DISC_REQ: {
if (cmd_len < 4) {
L2CAP_TRACE_WARNING ("L2CAP - LE - short cmd: %d", cmd_len);
return;
}
tL2C_CCB *p_ccb = NULL;
UINT16 lcid;
UINT16 rcid;