fix(bt_hid): size HID TX buffers to report length

This commit is contained in:
hejiaxin
2026-09-03 10:40:52 +08:00
parent 1e2241eb4f
commit 693a830f3e
2 changed files with 23 additions and 6 deletions
@@ -729,7 +729,8 @@ tHID_STATUS hidd_conn_send_data(uint8_t channel, uint8_t msg_type, uint8_t param
BT_HDR *p_buf; BT_HDR *p_buf;
uint8_t *p_out; uint8_t *p_out;
uint16_t cid; uint16_t cid;
uint16_t buf_size; uint16_t max_buf_size;
uint32_t payload_size, buf_size;
HIDD_TRACE_VERBOSE("%s: channel(%d), msg_type(%d), len(%d)", __func__, channel, msg_type, len); HIDD_TRACE_VERBOSE("%s: channel(%d), msg_type(%d), len(%d)", __func__, channel, msg_type, len);
@@ -742,20 +743,34 @@ tHID_STATUS hidd_conn_send_data(uint8_t channel, uint8_t msg_type, uint8_t param
case HID_TRANS_HANDSHAKE: case HID_TRANS_HANDSHAKE:
case HID_TRANS_CONTROL: case HID_TRANS_CONTROL:
cid = p_hcon->ctrl_cid; cid = p_hcon->ctrl_cid;
buf_size = HID_CONTROL_BUF_SIZE; max_buf_size = HID_CONTROL_BUF_SIZE;
break; break;
case HID_TRANS_DATA: case HID_TRANS_DATA:
if (channel == HID_CHANNEL_CTRL) { if (channel == HID_CHANNEL_CTRL) {
cid = p_hcon->ctrl_cid; cid = p_hcon->ctrl_cid;
buf_size = HID_CONTROL_BUF_SIZE; max_buf_size = HID_CONTROL_BUF_SIZE;
} else { } else {
cid = p_hcon->intr_cid; cid = p_hcon->intr_cid;
buf_size = HID_INTERRUPT_BUF_SIZE; max_buf_size = HID_INTERRUPT_BUF_SIZE;
} }
break; break;
default: default:
return (HID_ERR_INVALID_PARAM); return (HID_ERR_INVALID_PARAM);
} }
/* HID header byte, plus an optional report id byte */
payload_size = (uint32_t)len + 2;
buf_size = BT_HDR_SIZE + L2CAP_MIN_OFFSET + payload_size;
if (buf_size > max_buf_size) {
HIDD_TRACE_ERROR("hidd tx: len(%d) too large",len);
return (HID_ERR_INVALID_PARAM);
}
/* rem_mtu_size is only known once the channel has been configured */
if (p_hcon->rem_mtu_size && payload_size > p_hcon->rem_mtu_size) {
HIDD_TRACE_ERROR("hidd tx: len(%d) exceeds peer mtu(%d)",len, p_hcon->rem_mtu_size);
return (HID_ERR_INVALID_PARAM);
}
p_buf = (BT_HDR *)osi_malloc(buf_size); p_buf = (BT_HDR *)osi_malloc(buf_size);
if (p_buf == NULL) if (p_buf == NULL)
return (HID_ERR_NO_RESOURCES); return (HID_ERR_NO_RESOURCES);
@@ -865,11 +865,9 @@ tHID_STATUS hidh_conn_snd_data (UINT8 dhandle, UINT8 trans_type, UINT8 param,
case HID_TRANS_GET_IDLE: case HID_TRANS_GET_IDLE:
case HID_TRANS_SET_IDLE: case HID_TRANS_SET_IDLE:
cid = p_hcon->ctrl_cid; cid = p_hcon->ctrl_cid;
buf_size = HID_CONTROL_BUF_SIZE;
break; break;
case HID_TRANS_DATA: case HID_TRANS_DATA:
cid = p_hcon->intr_cid; cid = p_hcon->intr_cid;
buf_size = HID_INTERRUPT_BUF_SIZE;
break; break;
default: default:
rc = HID_ERR_INVALID_PARAM; rc = HID_ERR_INVALID_PARAM;
@@ -884,6 +882,8 @@ tHID_STATUS hidh_conn_snd_data (UINT8 dhandle, UINT8 trans_type, UINT8 param,
do { do {
if ( buf == NULL || blank_datc ) { if ( buf == NULL || blank_datc ) {
/* HID header byte, an optional report id byte and the inlined data bytes */
buf_size = BT_HDR_SIZE + L2CAP_MIN_OFFSET + 2 + use_data;
if ((p_buf = (BT_HDR *)osi_malloc(buf_size)) == NULL) { if ((p_buf = (BT_HDR *)osi_malloc(buf_size)) == NULL) {
rc = HID_ERR_NO_RESOURCES; rc = HID_ERR_NO_RESOURCES;
goto error; goto error;
@@ -895,6 +895,8 @@ tHID_STATUS hidh_conn_snd_data (UINT8 dhandle, UINT8 trans_type, UINT8 param,
bytes_copied = 0; bytes_copied = 0;
blank_datc = FALSE; blank_datc = FALSE;
} else if ( (buf->len > (p_hcon->rem_mtu_size - 1))) { } else if ( (buf->len > (p_hcon->rem_mtu_size - 1))) {
/* HID header byte plus a full (rem_mtu_size - 1) payload segment */
buf_size = BT_HDR_SIZE + L2CAP_MIN_OFFSET + p_hcon->rem_mtu_size + use_data;
if ((p_buf = (BT_HDR *)osi_malloc(buf_size)) == NULL) { if ((p_buf = (BT_HDR *)osi_malloc(buf_size)) == NULL) {
rc = HID_ERR_NO_RESOURCES; rc = HID_ERR_NO_RESOURCES;
goto error; goto error;