fix(bt/bluedroid): fixed issues from AI review in GAP, SPP, HID, L2CAP and HCI

This commit is contained in:
Jin Cheng
2026-07-23 07:50:26 +08:00
parent a5045d6952
commit b7ccc6e9ed
65 changed files with 2211 additions and 1160 deletions
@@ -103,6 +103,12 @@ void HID_DevDeinit(void)
******************************************************************************/
uint8_t HID_DevSetTraceLevel(uint8_t new_level)
{
#if (HID_DYNAMIC_MEMORY)
if (!hidd_cb_ptr) {
return BT_TRACE_LEVEL_NONE;
}
#endif /* #if (HID_DYNAMIC_MEMORY) */
if (new_level != 0xFF) {
hd_cb.trace_level = new_level;
}
@@ -159,15 +165,20 @@ tHID_STATUS HID_DevDeregister(void)
{
HIDD_TRACE_API("%s", __func__);
if (!hd_cb.reg_flag)
if (!hd_cb.reg_flag) {
return (HID_ERR_NOT_REGISTERED);
}
if (hd_cb.pending_data) {
osi_free(hd_cb.pending_data);
hd_cb.pending_data = NULL;
}
hidd_conn_dereg();
hd_cb.reg_flag = FALSE;
return (HID_SUCCESS);
}
tHID_STATUS HID_DevSetSecurityLevel(uint8_t sec_lvl)
tHID_STATUS HID_DevSetSecurityLevel(uint16_t sec_lvl)
{
HIDD_TRACE_API("%s", __func__);
if (!BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_HIDD_SEC_CTRL, sec_lvl, HID_PSM_CONTROL, BTM_SEC_PROTO_HID,
@@ -203,6 +214,53 @@ tHID_STATUS HID_DevSetSecurityLevel(uint8_t sec_lvl)
return (HID_SUCCESS);
}
#define HIDD_MAX_DESCRIPTOR_LEN 2048
static size_t hidd_descriptor_list_buf_size(uint16_t desc_len)
{
size_t text_elem_len = (desc_len <= 255) ? (2 + desc_len) : (3 + desc_len);
size_t inner_len = 2 + text_elem_len;
return inner_len + ((inner_len <= 255) ? 2 : 3);
}
static uint8_t *hidd_build_descriptor_list(uint16_t desc_len, uint8_t *p_desc_data, uint16_t *p_list_len)
{
static uint8_t cdt = 0x22;
size_t text_elem_len = (desc_len <= 255) ? (2 + desc_len) : (3 + desc_len);
size_t inner_len = 2 + text_elem_len;
uint8_t *p_buf = (uint8_t *)osi_malloc(hidd_descriptor_list_buf_size(desc_len));
uint8_t *p;
if (p_buf == NULL) {
return NULL;
}
p = p_buf;
if (inner_len <= 255) {
UINT8_TO_BE_STREAM(p, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
UINT8_TO_BE_STREAM(p, (uint8_t)inner_len);
} else {
UINT8_TO_BE_STREAM(p, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_WORD);
UINT16_TO_BE_STREAM(p, (uint16_t)inner_len);
}
UINT8_TO_BE_STREAM(p, (UINT_DESC_TYPE << 3) | SIZE_ONE_BYTE);
UINT8_TO_BE_STREAM(p, cdt);
if (desc_len <= 255) {
UINT8_TO_BE_STREAM(p, (TEXT_STR_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
UINT8_TO_BE_STREAM(p, (uint8_t)desc_len);
} else {
UINT8_TO_BE_STREAM(p, (TEXT_STR_DESC_TYPE << 3) | SIZE_IN_NEXT_WORD);
UINT16_TO_BE_STREAM(p, desc_len);
}
ARRAY_TO_BE_STREAM(p, p_desc_data, (int)desc_len);
*p_list_len = (uint16_t)(p - p_buf);
return p_buf;
}
/*******************************************************************************
*
* Function HID_DevAddRecord
@@ -219,6 +277,13 @@ tHID_STATUS HID_DevAddRecord(uint32_t handle, char *p_name, char *p_description,
HIDD_TRACE_API("%s", __func__);
if (desc_len > HIDD_MAX_DESCRIPTOR_LEN) {
return HID_ERR_INVALID_PARAM;
}
if (desc_len > 0 && p_desc_data == NULL) {
return HID_ERR_INVALID_PARAM;
}
// Service Class ID List
if (result) {
uint16_t uuid = UUID_SERVCLASS_HUMAN_INTERFACE;
@@ -292,23 +357,16 @@ tHID_STATUS HID_DevAddRecord(uint32_t handle, char *p_name, char *p_description,
result &= SDP_AddAttribute(handle, ATTR_ID_HID_VIRTUAL_CABLE, BOOLEAN_DESC_TYPE, 1, (uint8_t *)&bool_true);
result &= SDP_AddAttribute(handle, ATTR_ID_HID_RECONNECT_INITIATE, BOOLEAN_DESC_TYPE, 1, (uint8_t *)&bool_true);
{
static uint8_t cdt = 0x22;
uint8_t *p_buf;
uint8_t seq_len = 4 + desc_len;
p_buf = (uint8_t *)osi_malloc(2048);
uint16_t list_len;
p_buf = hidd_build_descriptor_list(desc_len, p_desc_data, &list_len);
if (p_buf == NULL) {
HIDD_TRACE_ERROR("%s: Buffer allocation failure for size = 2048 ", __func__);
return HID_ERR_NOT_REGISTERED;
HIDD_TRACE_ERROR("%s: Buffer allocation failure for descriptor list size = %u", __func__,
(unsigned)hidd_descriptor_list_buf_size(desc_len));
return HID_ERR_NO_RESOURCES;
}
p = p_buf;
UINT8_TO_BE_STREAM(p, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
UINT8_TO_BE_STREAM(p, seq_len);
UINT8_TO_BE_STREAM(p, (UINT_DESC_TYPE << 3) | SIZE_ONE_BYTE);
UINT8_TO_BE_STREAM(p, cdt);
UINT8_TO_BE_STREAM(p, (TEXT_STR_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
UINT8_TO_BE_STREAM(p, desc_len);
ARRAY_TO_BE_STREAM(p, p_desc_data, (int)desc_len);
result &= SDP_AddAttribute(handle, ATTR_ID_HID_DESCRIPTOR_LIST, DATA_ELE_SEQ_DESC_TYPE, p - p_buf, p_buf);
result &= SDP_AddAttribute(handle, ATTR_ID_HID_DESCRIPTOR_LIST, DATA_ELE_SEQ_DESC_TYPE, list_len, p_buf);
osi_free(p_buf);
}
{
@@ -416,6 +474,7 @@ tHID_STATUS HID_DevUnplugDevice(BD_ADDR addr)
{
if (!memcmp(hd_cb.device.addr, addr, sizeof(BD_ADDR))) {
hd_cb.device.in_use = FALSE;
hd_cb.device.state = HIDD_DEV_NO_CONN;
hd_cb.device.conn.conn_state = HID_CONN_STATE_UNUSED;
hd_cb.device.conn.ctrl_cid = 0;
hd_cb.device.conn.intr_cid = 0;
@@ -480,6 +539,12 @@ tHID_STATUS HID_DevDisconnect(void)
******************************************************************************/
tHID_STATUS HID_DevSetIncomingPolicy(bool allow)
{
#if (HID_DYNAMIC_MEMORY)
if (!hidd_cb_ptr) {
return HID_ERR_NO_RESOURCES;
}
#endif /* #if (HID_DYNAMIC_MEMORY) */
hd_cb.allow_incoming = allow;
return HID_SUCCESS;
}
@@ -551,7 +616,14 @@ tHID_STATUS HID_DevGetDevice(BD_ADDR *addr)
tHID_STATUS HID_DevSetIncomingQos(uint8_t service_type, uint32_t token_rate, uint32_t token_bucket_size,
uint32_t peak_bandwidth, uint32_t latency, uint32_t delay_variation)
{
#if (HID_DYNAMIC_MEMORY)
if (!hidd_cb_ptr) {
return HID_ERR_NO_RESOURCES;
}
#endif /* #if (HID_DYNAMIC_MEMORY) */
HIDD_TRACE_API("%s", __func__);
hd_cb.use_in_qos = TRUE;
hd_cb.in_qos.service_type = service_type;
hd_cb.in_qos.token_rate = token_rate;
@@ -573,7 +645,14 @@ tHID_STATUS HID_DevSetIncomingQos(uint8_t service_type, uint32_t token_rate, uin
tHID_STATUS HID_DevSetOutgoingQos(uint8_t service_type, uint32_t token_rate, uint32_t token_bucket_size,
uint32_t peak_bandwidth, uint32_t latency, uint32_t delay_variation)
{
#if (HID_DYNAMIC_MEMORY)
if (!hidd_cb_ptr) {
return HID_ERR_NO_RESOURCES;
}
#endif /* #if (HID_DYNAMIC_MEMORY) */
HIDD_TRACE_API("%s", __func__);
hd_cb.l2cap_intr_cfg.qos_present = TRUE;
hd_cb.l2cap_intr_cfg.qos.service_type = service_type;
hd_cb.l2cap_intr_cfg.qos.token_rate = token_rate;
@@ -451,6 +451,10 @@ static void hidd_l2cif_disconnect_cfm(uint16_t cid, uint16_t result)
}
if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0)) {
HIDD_TRACE_EVENT("%s: INTR and CTRL disconnected", __func__);
if (hd_cb.pending_data) {
osi_free(hd_cb.pending_data);
hd_cb.pending_data = NULL;
}
hd_cb.device.state = HIDD_DEV_NO_CONN;
p_hcon->conn_state = HID_CONN_STATE_UNUSED;
if (hd_cb.pending_vc_unplug) {
@@ -667,6 +671,7 @@ tHID_STATUS hidd_conn_initiate(void)
if ((p_dev->conn.ctrl_cid = L2CA_ConnectReq(HID_PSM_CONTROL, p_dev->addr)) == 0) {
HIDD_TRACE_WARNING("%s: could not start L2CAP connection", __func__);
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_ERR_L2CAP_FAILED, NULL);
return HID_ERR_L2CAP_FAILED;
} else {
p_dev->conn.conn_state = HID_CONN_STATE_CONNECTING_CTRL;
}
@@ -68,7 +68,9 @@ tHID_STATUS HID_HostGetSDPRecord ( BD_ADDR addr, tSDP_DISCOVERY_DB *p_db, UINT32
uuid_list.uu.uuid16 = UUID_SERVCLASS_HUMAN_INTERFACE;
hh_cb.p_sdp_db = p_db;
SDP_InitDiscoveryDb (p_db, db_len, 1, &uuid_list, 0, NULL);
if (!SDP_InitDiscoveryDb (p_db, db_len, 1, &uuid_list, 0, NULL)) {
return HID_ERR_NO_RESOURCES;
}
if (SDP_ServiceSearchRequest (addr, p_db, hidh_search_callback)) {
hh_cb.sdp_cback = sdp_cback ;
@@ -558,11 +560,10 @@ tHID_STATUS HID_HostCloseDev( UINT8 dev_handle )
return HID_ERR_NO_CONNECTION;
}
hh_cb.devices[dev_handle].conn_tries = HID_HOST_MAX_CONN_RETRY + 1;
return hidh_conn_disconnect( dev_handle );
}
tHID_STATUS HID_HostSetSecurityLevel( char serv_name[], UINT8 sec_lvl )
tHID_STATUS HID_HostSetSecurityLevel( const char *serv_name, UINT8 sec_lvl )
{
if (!BTM_SetSecurityLevel (FALSE, serv_name, BTM_SEC_SERVICE_HIDH_SEC_CTRL,
sec_lvl, HID_PSM_CONTROL, BTM_SEC_PROTO_HID, HID_SEC_CHN)) {
@@ -656,6 +657,11 @@ BOOLEAN HID_HostConnectOrig(UINT8 dev_handle)
BOOLEAN ret = FALSE;
do {
#if (HID_DYNAMIC_MEMORY)
if (!hidh_cb_ptr) {
break;
}
#endif
if (!hh_cb.reg_flag) {
break;
}
@@ -109,6 +109,7 @@ tHID_STATUS hidh_conn_reg (void)
}
for (xx = 0; xx < HID_HOST_MAX_DEVICES; xx++) {
memset(&hh_cb.devices[xx], 0, sizeof(tHID_HOST_DEV_CTB));
hh_cb.devices[xx].in_use = FALSE ;
hh_cb.devices[xx].delay_remove = FALSE;
hh_cb.devices[xx].conn.conn_state = HID_CONN_STATE_UNUSED;
@@ -515,7 +516,7 @@ static void hidh_l2cif_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
}
if (p_hcon == NULL) {
HIDH_TRACE_WARNING ("HID-Host Rcvd L2CAP cfg ind, unknown CID: 0x%x", l2cap_cid);
HIDH_TRACE_WARNING ("HID-Host Rcvd L2CAP cfg cfm, unknown CID: 0x%x", l2cap_cid);
return;
}
@@ -833,6 +834,7 @@ static void hidh_l2cif_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg)
tHID_STATUS hidh_conn_snd_data (UINT8 dhandle, UINT8 trans_type, UINT8 param,
UINT16 data, UINT8 report_id, BT_HDR *buf)
{
tHID_STATUS rc = HID_SUCCESS;
tHID_CONN *p_hcon = &hh_cb.devices[dhandle].conn;
BT_HDR *p_buf;
UINT8 *p_out;
@@ -845,17 +847,13 @@ tHID_STATUS hidh_conn_snd_data (UINT8 dhandle, UINT8 trans_type, UINT8 param,
BOOLEAN blank_datc = FALSE;
if (!BTM_IsAclConnectionUp(hh_cb.devices[dhandle].addr, BT_TRANSPORT_BR_EDR)) {
if (buf) {
osi_free ((void *)buf);
}
return ( HID_ERR_NO_CONNECTION );
rc = HID_ERR_NO_CONNECTION;
goto error;
}
if (p_hcon->conn_flags & HID_CONN_FLAGS_CONGESTED) {
if (buf) {
osi_free ((void *)buf);
}
return ( HID_ERR_CONGESTED );
rc = HID_ERR_CONGESTED;
goto error;
}
switch ( trans_type ) {
@@ -874,7 +872,8 @@ tHID_STATUS hidh_conn_snd_data (UINT8 dhandle, UINT8 trans_type, UINT8 param,
buf_size = HID_INTERRUPT_BUF_SIZE;
break;
default:
return (HID_ERR_INVALID_PARAM) ;
rc = HID_ERR_INVALID_PARAM;
goto error;
}
if ( trans_type == HID_TRANS_SET_IDLE ) {
@@ -886,7 +885,8 @@ tHID_STATUS hidh_conn_snd_data (UINT8 dhandle, UINT8 trans_type, UINT8 param,
do {
if ( buf == NULL || blank_datc ) {
if ((p_buf = (BT_HDR *)osi_malloc(buf_size)) == NULL) {
return (HID_ERR_NO_RESOURCES);
rc = HID_ERR_NO_RESOURCES;
goto error;
}
p_buf->offset = L2CAP_MIN_OFFSET;
@@ -896,7 +896,8 @@ tHID_STATUS hidh_conn_snd_data (UINT8 dhandle, UINT8 trans_type, UINT8 param,
blank_datc = FALSE;
} else if ( (buf->len > (p_hcon->rem_mtu_size - 1))) {
if ((p_buf = (BT_HDR *)osi_malloc(buf_size)) == NULL) {
return (HID_ERR_NO_RESOURCES);
rc = HID_ERR_NO_RESOURCES;
goto error;
}
p_buf->offset = L2CAP_MIN_OFFSET;
@@ -904,11 +905,13 @@ tHID_STATUS hidh_conn_snd_data (UINT8 dhandle, UINT8 trans_type, UINT8 param,
data_size = buf->len;
bytes_copied = p_hcon->rem_mtu_size - 1;
} else {
p_buf = buf ;
p_buf = buf;
p_buf->offset -= 1;
seg_req = FALSE;
data_size = buf->len;
bytes_copied = buf->len;
// The ownership of buf has been handed over to p_buf
buf = NULL;
}
p_out = (UINT8 *)(p_buf + 1) + p_buf->offset;
@@ -937,7 +940,8 @@ tHID_STATUS hidh_conn_snd_data (UINT8 dhandle, UINT8 trans_type, UINT8 param,
/* Send the buffer through L2CAP */
if (L2CA_DataWrite(cid, p_buf) == L2CAP_DW_FAILED) {
return (HID_ERR_CONGESTED);
rc = HID_ERR_CONGESTED;
goto error;
}
if (data_size) {
@@ -950,6 +954,12 @@ tHID_STATUS hidh_conn_snd_data (UINT8 dhandle, UINT8 trans_type, UINT8 param,
} while ((data_size != 0) || blank_datc ) ;
return (HID_SUCCESS);
error:
if (buf) {
osi_free ((void *)buf);
}
return rc;
}
/*******************************************************************************
**
@@ -1018,7 +1028,7 @@ BOOLEAN hidh_conn_is_orig(UINT8 dhandle)
**
** Description This function finds a connection control block based on CID
**
** Returns address of control block, or NULL if not found
** Returns index of connection, or HID_HOST_MAX_DEVICES if not found
**
*******************************************************************************/
static UINT8 find_conn_by_cid (UINT16 cid)