component/bt: use fixed_pkt_queue instead of fixed_queue for hci commands

some fixes after modifications:
  1. removed the use of waiting_command_t
  2. fix assert for HCI write_eir command
  3. fixed the crash upon handling command status event when trying to free to the HCI command buffer
  4. fixed the issue in transmitting HCI vendor specific commands
  5. fixed the lost command complete callbacks for HCI commands LE_RAND and LE_ENCRYPT
This commit is contained in:
wangmengyang
2022-07-19 22:16:12 +08:00
parent dd02446224
commit 20705588b2
9 changed files with 187 additions and 132 deletions

View File

@@ -662,14 +662,13 @@ tBTM_DEV_STATUS_CB *BTM_RegisterForDeviceStatusNotif (tBTM_DEV_STATUS_CB *p_cb)
tBTM_STATUS BTM_VendorSpecificCommand(UINT16 opcode, UINT8 param_len,
UINT8 *p_param_buf, tBTM_VSC_CMPL_CB *p_cb)
{
void *p_buf;
BT_HDR *p_buf;
BTM_TRACE_EVENT ("BTM: BTM_VendorSpecificCommand: Opcode: 0x%04X, ParamLen: %i.",
opcode, param_len);
/* Allocate a buffer to hold HCI command plus the callback function */
if ((p_buf = osi_malloc((UINT16)(sizeof(BT_HDR) + sizeof (tBTM_CMPL_CB *) +
param_len + HCIC_PREAMBLE_SIZE))) != NULL) {
if ((p_buf = HCI_GET_CMD_BUF(param_len)) != NULL) {
/* Send the HCI command (opcode will be OR'd with HCI_GRP_VENDOR_SPECIFIC) */
btsnd_hcic_vendor_spec_cmd (p_buf, opcode, param_len, p_param_buf, (void *)p_cb);

View File

@@ -2395,6 +2395,7 @@ tBTM_STATUS BTM_WriteEIR( BT_HDR *p_buff, BOOLEAN fec_required)
if (controller_get_interface()->supports_extended_inquiry_response()) {
BTM_TRACE_API("Write Extended Inquiry Response to controller\n");
btsnd_hcic_write_ext_inquiry_response (p_buff, fec_required);
osi_free(p_buff);
return BTM_SUCCESS;
} else {
osi_free(p_buff);

View File

@@ -43,6 +43,7 @@
#include "common/bt_trace.h"
#include "osi/thread.h"
#include "osi/pkt_queue.h"
//#include "osi/mutex.h"
// TODO(zachoverflow): remove this horrible hack
#include "stack/btu.h"
@@ -451,15 +452,21 @@ void btu_hcif_send_cmd (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_buf)
STREAM_TO_UINT16(opcode, stream);
// Eww...horrible hackery here
/* If command was a VSC, then extract command_complete callback */
if ((opcode & HCI_GRP_VENDOR_SPECIFIC) == HCI_GRP_VENDOR_SPECIFIC
assert (p_buf->layer_specific == HCI_CMD_BUF_TYPE_METADATA);
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(p_buf);
metadata->command_complete_cb = btu_hcif_command_complete_evt;
metadata->command_status_cb = btu_hcif_command_status_evt;
metadata->opcode = opcode;
vsc_callback = metadata->context;
/* If command is not a VSC, then the context field should be empty */
if ((opcode & HCI_GRP_VENDOR_SPECIFIC) != HCI_GRP_VENDOR_SPECIFIC
#if BLE_INCLUDED == TRUE
|| (opcode == HCI_BLE_RAND)
|| (opcode == HCI_BLE_ENCRYPT)
&& (opcode != HCI_BLE_RAND)
&& (opcode != HCI_BLE_ENCRYPT)
#endif
) {
vsc_callback = *((void **)(p_buf + 1));
) {
assert (vsc_callback == NULL);
}
hci_layer_get_interface()->transmit_command(
@@ -472,6 +479,7 @@ void btu_hcif_send_cmd (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_buf)
btu_check_bt_sleep ();
#endif
}
#if (BLE_50_FEATURE_SUPPORT == TRUE)
UINT8 btu_hcif_send_cmd_sync (UINT8 controller_id, BT_HDR *p_buf)
{
@@ -492,15 +500,22 @@ UINT8 btu_hcif_send_cmd_sync (UINT8 controller_id, BT_HDR *p_buf)
sync_info->opcode = opcode;
// Eww...horrible hackery here
/* If command was a VSC, then extract command_complete callback */
if ((opcode & HCI_GRP_VENDOR_SPECIFIC) == HCI_GRP_VENDOR_SPECIFIC
assert (p_buf->layer_specific == HCI_CMD_BUF_TYPE_METADATA);
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(p_buf);
metadata->command_complete_cb = btu_hcif_command_complete_evt;
metadata->command_status_cb = btu_hcif_command_status_evt;
metadata->command_free_cb = NULL;
metadata->opcode = opcode;
vsc_callback = metadata->context;
/* If command is not a VSC, then the context field should be empty */
if ((opcode & HCI_GRP_VENDOR_SPECIFIC) != HCI_GRP_VENDOR_SPECIFIC
#if BLE_INCLUDED == TRUE
|| (opcode == HCI_BLE_RAND)
|| (opcode == HCI_BLE_ENCRYPT)
&& (opcode != HCI_BLE_RAND)
&& (opcode != HCI_BLE_ENCRYPT)
#endif
) {
vsc_callback = *((void **)(p_buf + 1));
) {
assert (vsc_callback == NULL);
}
hci_layer_get_interface()->transmit_command(
@@ -1434,7 +1449,11 @@ static void btu_hcif_command_status_evt_on_task(BT_HDR *event)
stream,
hack->context);
osi_free(hack->command);
// check the HCI command integrity: opcode
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(hack->command);
assert(metadata->opcode == opcode);
HCI_FREE_CMD_BUF(hack->command);
osi_free(event);
}

View File

@@ -33,7 +33,6 @@
#include <stddef.h>
#include <string.h>
#define HCI_GET_CMD_BUF(paramlen) ((BT_HDR *)osi_malloc(HCIC_PREAMBLE_SIZE + sizeof(BT_HDR) + paramlen))
#if (BLE_50_FEATURE_SUPPORT == TRUE)
static BlE_SYNC ble_sync_info;
@@ -557,19 +556,17 @@ BOOLEAN btsnd_hcic_ble_encrypt (UINT8 *key, UINT8 key_len,
BT_HDR *p;
UINT8 *pp;
if ((p = HCI_GET_CMD_BUF(sizeof (void *) +
HCIC_PARAM_SIZE_BLE_ENCRYPT)) == NULL) {
if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_BLE_ENCRYPT)) == NULL) {
return (FALSE);
}
pp = (UINT8 *)(p + 1);
p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_ENCRYPT;
p->offset = sizeof(void *);
*((void **)pp) = p_cmd_cplt_cback; /* Store command complete callback in buffer */
pp += sizeof(void *); /* Skip over callback pointer */
p->offset = 0;
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(p);
metadata->context = p_cmd_cplt_cback;
UINT16_TO_STREAM (pp, HCI_BLE_ENCRYPT);
UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_ENCRYPT);
@@ -596,18 +593,17 @@ BOOLEAN btsnd_hcic_ble_rand (void *p_cmd_cplt_cback)
BT_HDR *p;
UINT8 *pp;
if ((p = HCI_GET_CMD_BUF(sizeof (void *) +
HCIC_PARAM_SIZE_BLE_RAND)) == NULL) {
if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_BLE_RAND)) == NULL) {
return (FALSE);
}
pp = (UINT8 *)(p + 1);
p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_RAND;
p->offset = sizeof(void *);
p->offset = 0;
*((void **)pp) = p_cmd_cplt_cback; /* Store command complete callback in buffer */
pp += sizeof(void *); /* Skip over callback pointer */
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(p);
metadata->context = p_cmd_cplt_cback;
UINT16_TO_STREAM (pp, HCI_BLE_RAND);
UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_RAND);
@@ -1046,6 +1042,9 @@ BOOLEAN btsnd_hcic_ble_update_adv_report_flow_control (UINT16 num)
p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL;
p->offset = 0;
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(p);
metadata->flags_src |= HCI_CMD_MSG_F_SRC_NOACK;
UINT16_TO_STREAM (pp, HCI_VENDOR_BLE_ADV_REPORT_FLOW_CONTROL);
UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL);
UINT16_TO_STREAM (pp, num);

View File

@@ -35,8 +35,6 @@
#include "btm_int.h" /* Included for UIPC_* macro definitions */
#define HCI_GET_CMD_BUF(paramlen) ((BT_HDR *)osi_malloc(HCIC_PREAMBLE_SIZE + sizeof(BT_HDR) + paramlen))
BOOLEAN btsnd_hcic_inquiry(const LAP inq_lap, UINT8 duration, UINT8 response_cnt)
{
BT_HDR *p;
@@ -1331,6 +1329,9 @@ BOOLEAN btsnd_hcic_host_num_xmitted_pkts (UINT8 num_handles, UINT16 *handle,
p->len = HCIC_PREAMBLE_SIZE + 1 + (num_handles * 4);
p->offset = 0;
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(p);
metadata->flags_src |= HCI_CMD_MSG_F_SRC_NOACK;
UINT16_TO_STREAM (pp, HCI_HOST_NUM_PACKETS_DONE);
UINT8_TO_STREAM (pp, p->len - HCIC_PREAMBLE_SIZE);
@@ -1431,9 +1432,13 @@ BOOLEAN btsnd_hcic_sniff_sub_rate(UINT16 handle, UINT16 max_lat,
#endif /* BTM_SSR_INCLUDED */
/**** Extended Inquiry Response Commands ****/
void btsnd_hcic_write_ext_inquiry_response (void *buffer, UINT8 fec_req)
void btsnd_hcic_write_ext_inquiry_response (BT_HDR *buffer, UINT8 fec_req)
{
BT_HDR *p = (BT_HDR *)buffer;
BT_HDR *p;
if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_EXT_INQ_RESP)) == NULL) {
return;
}
UINT8 *pp = (UINT8 *)(p + 1);
p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_EXT_INQ_RESP;
@@ -1441,9 +1446,10 @@ void btsnd_hcic_write_ext_inquiry_response (void *buffer, UINT8 fec_req)
UINT16_TO_STREAM (pp, HCI_WRITE_EXT_INQ_RESPONSE);
UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_EXT_INQ_RESP);
UINT8_TO_STREAM (pp, fec_req);
memcpy(pp, buffer->data + 4, p->len - 4);
btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
}
@@ -1862,17 +1868,17 @@ BOOLEAN btsnd_hcic_write_pagescan_type (UINT8 type)
#error "HCI_CMD_POOL_BUF_SIZE must be larger than 268"
#endif
void btsnd_hcic_vendor_spec_cmd (void *buffer, UINT16 opcode, UINT8 len,
void btsnd_hcic_vendor_spec_cmd (BT_HDR *buffer, UINT16 opcode, UINT8 len,
UINT8 *p_data, void *p_cmd_cplt_cback)
{
BT_HDR *p = (BT_HDR *)buffer;
BT_HDR *p = buffer;
UINT8 *pp = (UINT8 *)(p + 1);
p->len = HCIC_PREAMBLE_SIZE + len;
p->offset = sizeof(void *);
p->offset = 0;
*((void **)pp) = p_cmd_cplt_cback; /* Store command complete callback in buffer */
pp += sizeof(void *); /* Skip over callback pointer */
hci_cmd_metadata_t * metadata = HCI_GET_CMD_METAMSG(p);
metadata->context = p_cmd_cplt_cback;
UINT16_TO_STREAM (pp, HCI_GRP_VENDOR_SPECIFIC | opcode);
UINT8_TO_STREAM (pp, len);

View File

@@ -19,9 +19,66 @@
#ifndef HCIMSGS_H
#define HCIMSGS_H
#include <stddef.h>
#include "common/bt_target.h"
#include "stack/hcidefs.h"
#include "stack/bt_types.h"
#include "osi/pkt_queue.h"
#include "osi/allocator.h"
#define HCI_CMD_BUF_TYPE_METADATA (0xa56e)
#define HCI_CMD_MSG_F_SRC_NOACK (0x01)
typedef void (*hci_cmd_cmpl_cb)(BT_HDR *response, void *context);
typedef void (*hci_cmd_stat_cb)(uint8_t status, BT_HDR *command, void *context);
typedef void (*hci_cmd_free_cb)(pkt_linked_item_t *linked_pkt);
typedef struct {
uint8_t flags_src;
uint8_t flags_vnd; // used for downstream layer
uint16_t opcode;
hci_cmd_cmpl_cb command_complete_cb;
hci_cmd_stat_cb command_status_cb;
void *context;
void *complete_future;
hci_cmd_free_cb command_free_cb;
BT_HDR command;
} hci_cmd_metadata_t;
#define HCI_CMD_METADATA_HDR_SIZE (sizeof(hci_cmd_metadata_t))
#define HCI_CMD_LINKED_BUF_SIZE(paramlen) (BT_PKT_LINKED_HDR_SIZE + HCI_CMD_METADATA_HDR_SIZE + HCIC_PREAMBLE_SIZE + (paramlen))
#define HCI_GET_CMD_METAMSG(cmd_ptr) (hci_cmd_metadata_t *)((void *)(cmd_ptr) - offsetof(hci_cmd_metadata_t, command))
#define HCI_GET_CMD_LINKED_STRUCT(metadata_ptr) (pkt_linked_item_t *)((void *)(metadata_ptr) - offsetof(pkt_linked_item_t, data))
static inline BT_HDR *hci_get_cmd_buf(size_t param_len)
{
pkt_linked_item_t *linked_pkt = osi_calloc(HCI_CMD_LINKED_BUF_SIZE(param_len));
if (linked_pkt == NULL) {
return NULL;
}
hci_cmd_metadata_t *metadata = (hci_cmd_metadata_t *)linked_pkt->data;
BT_HDR *command = &metadata->command;
command->layer_specific = HCI_CMD_BUF_TYPE_METADATA;
command->len = HCIC_PREAMBLE_SIZE + param_len;
command->offset = 0;
return command;
}
static inline void hci_free_cmd_buf(BT_HDR *buf)
{
assert(buf->layer_specific == HCI_CMD_BUF_TYPE_METADATA);
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(buf);
pkt_linked_item_t *linked_pkt = HCI_GET_CMD_LINKED_STRUCT(metadata);
osi_free(linked_pkt);
}
#define HCI_GET_CMD_BUF(param_len) hci_get_cmd_buf(param_len)
#define HCI_FREE_CMD_BUF(buf) hci_free_cmd_buf(buf)
void bte_main_hci_send(BT_HDR *p_msg, UINT16 event);
void bte_main_lpm_allow_bt_device_sleep(void);
@@ -378,7 +435,7 @@ BOOLEAN btsnd_hcic_sniff_sub_rate(UINT16 handle, UINT16 max_lat,
#endif /* BTM_SSR_INCLUDED */
/* Extended Inquiry Response */
void btsnd_hcic_write_ext_inquiry_response(void *buffer, UINT8 fec_req);
void btsnd_hcic_write_ext_inquiry_response(BT_HDR *buffer, UINT8 fec_req);
#define HCIC_PARAM_SIZE_EXT_INQ_RESP 241
@@ -641,7 +698,7 @@ BOOLEAN btsnd_hcic_write_inquiry_mode(UINT8 type); /* Write Inquiry
#define HCID_GET_SCO_LEN(p) (*((UINT8 *)((p) + 1) + p->offset + 2))
void btsnd_hcic_vendor_spec_cmd (void *buffer, UINT16 opcode,
void btsnd_hcic_vendor_spec_cmd (BT_HDR *buffer, UINT16 opcode,
UINT8 len, UINT8 *p_data,
void *p_cmd_cplt_cback);