From e47f74ffc0f6f6a489ba5dd2d4c64c4a4d0f8940 Mon Sep 17 00:00:00 2001 From: liqigan Date: Thu, 11 Jun 2026 19:55:15 +0800 Subject: [PATCH] change(bt/bluedroid): Refactored HID host datapath --- .../bt/host/bluedroid/bta/hh/bta_hh_act.c | 72 ++- .../bt/host/bluedroid/bta/hh/bta_hh_le.c | 17 +- .../bluedroid/bta/hh/include/bta_hh_int.h | 6 +- .../bluedroid/bta/include/bta/bta_hh_co.h | 42 +- .../bluedroid/btc/profile/std/hid/bta_hh_co.c | 225 ++++++++-- .../bluedroid/btc/profile/std/hid/btc_hh.c | 416 ++++++++++++++++-- .../btc/profile/std/include/btc_hh.h | 31 +- 7 files changed, 672 insertions(+), 137 deletions(-) diff --git a/components/bt/host/bluedroid/bta/hh/bta_hh_act.c b/components/bt/host/bluedroid/bta/hh/bta_hh_act.c index 8a7725fa300..efe6a99ebd9 100644 --- a/components/bt/host/bluedroid/bta/hh/bta_hh_act.c +++ b/components/bt/host/bluedroid/bta/hh/bta_hh_act.c @@ -40,7 +40,6 @@ ** Constants *****************************************************************************/ - /***************************************************************************** ** Local Function prototypes *****************************************************************************/ @@ -96,6 +95,7 @@ void bta_hh_api_enable(tBTA_HH_DATA *p_data) for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx ++) { bta_hh_cb.cb_index[xx] = BTA_HH_IDX_INVALID; } + } #if (BTA_HH_LE_INCLUDED == TRUE) @@ -538,8 +538,23 @@ void bta_hh_open_cmpl_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) bta_hh_cb.cnt_num ++; /* initialize device driver */ - bta_hh_co_open(dev_handle, p_cb->sub_class, - p_cb->attr_mask, p_cb->app_id); + if (!bta_hh_co_open(dev_handle, p_cb->sub_class, + p_cb->attr_mask, p_cb->app_id)) { + conn.status = BTA_HH_ERR_NO_RES; + p_cb->opened = FALSE; +#if (BTA_HH_LE_INCLUDED == TRUE) + if (!p_cb->is_le_device) +#endif + { + /* Balance the async close path which unconditionally calls bta_sys_conn_close(). */ + bta_sys_conn_open(BTA_ID_HH, p_cb->app_id, p_cb->addr); + } + HID_HostCloseDev(dev_handle); + (* bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn); + p_cb->incoming_conn = FALSE; + p_cb->incoming_hid_handle = BTA_HH_INVALID_HANDLE; + return; + } #if (BTA_HH_LE_INCLUDED == TRUE) conn.status = p_cb->status; @@ -552,6 +567,7 @@ void bta_hh_open_cmpl_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) /* inform role manager */ bta_sys_conn_open( BTA_ID_HH , p_cb->app_id, p_cb->addr); } + p_cb->opened = TRUE; /* set protocol mode when not default report mode */ if ( p_cb->mode != BTA_HH_PROTO_RPT_MODE #if (BTA_HH_LE_INCLUDED == TRUE) @@ -631,12 +647,15 @@ void bta_hh_open_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) void bta_hh_data_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) { BT_HDR *pdata = p_data->hid_cback.p_data; - UINT8 *p_rpt = (UINT8 *)(pdata + 1) + pdata->offset; - bta_hh_co_data((UINT8)p_data->hid_cback.hdr.layer_specific, p_rpt, pdata->len, - p_cb->mode, p_cb->sub_class, p_cb->dscp_info.ctry_code, p_cb->addr, p_cb->app_id); + if (pdata == NULL) { + return; + } - utl_freebuf((void **)&pdata); + bta_hh_co_data_hdr((UINT8)p_data->hid_cback.hdr.layer_specific, pdata, + p_cb->mode, p_cb->sub_class, p_cb->dscp_info.ctry_code, + p_cb->addr, p_cb->app_id); + p_data->hid_cback.p_data = NULL; } @@ -834,6 +853,7 @@ void bta_hh_open_failure(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) /* Report OPEN fail event */ (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat); + p_cb->opened = FALSE; #if BTA_HH_DEBUG bta_hh_trace_dev_db(); @@ -885,6 +905,7 @@ void bta_hh_close_act (tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) /* Report OPEN fail event */ (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat); + p_cb->opened = FALSE; #if BTA_HH_DEBUG bta_hh_trace_dev_db(); @@ -893,24 +914,27 @@ void bta_hh_close_act (tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) } /* otherwise report CLOSE/VC_UNPLUG event */ else { - /* finaliza device driver */ - bta_hh_co_close(p_cb->hid_handle, p_cb->app_id); /* inform role manager */ bta_sys_conn_close( BTA_ID_HH , p_cb->app_id, p_cb->addr); /* update total conn number */ bta_hh_cb.cnt_num --; - if (disc_dat.status) { - disc_dat.status = BTA_HH_ERR; - } + if (p_cb->opened) { + /* finalize device driver only for successfully opened devices */ + bta_hh_co_close(p_cb->hid_handle, p_cb->app_id); + if (disc_dat.status) { + disc_dat.status = BTA_HH_ERR; + } - (*bta_hh_cb.p_cback)(event, (tBTA_HH *)&disc_dat); + (*bta_hh_cb.p_cback)(event, (tBTA_HH *)&disc_dat); - /* if virtually unplug, remove device */ - if (p_cb->vp ) { - HID_HostRemoveDev( p_cb->hid_handle); - bta_hh_clean_up_kdev(p_cb); + /* if virtually unplug, remove device */ + if (p_cb->vp ) { + HID_HostRemoveDev( p_cb->hid_handle); + bta_hh_clean_up_kdev(p_cb); + } } + p_cb->opened = FALSE; #if BTA_HH_DEBUG bta_hh_trace_dev_db(); @@ -1190,9 +1214,17 @@ static void bta_hh_cback (UINT8 dev_handle, BD_ADDR addr, UINT8 event, case HID_HDEV_EVT_CLOSE: sm_event = BTA_HH_INT_CLOSE_EVT; break; - case HID_HDEV_EVT_INTR_DATA: - sm_event = BTA_HH_INT_DATA_EVT; - break; + case HID_HDEV_EVT_INTR_DATA: { + UINT8 index = bta_hh_dev_handle_to_cb_idx(dev_handle); + tBTA_HH_DEV_CB *p_cb = (index != BTA_HH_IDX_INVALID) ? &bta_hh_cb.kdev[index] : NULL; + if (p_cb != NULL && p_cb->state == BTA_HH_CONN_ST) { + bta_hh_co_data_hdr(dev_handle, pdata, p_cb->mode, p_cb->sub_class, p_cb->dscp_info.ctry_code, p_cb->addr, + p_cb->app_id); + } else { + utl_freebuf((void **)&pdata); + } + return; + } case HID_HDEV_EVT_HANDSHAKE: sm_event = BTA_HH_INT_HANDSK_EVT; break; diff --git a/components/bt/host/bluedroid/bta/hh/bta_hh_le.c b/components/bt/host/bluedroid/bta/hh/bta_hh_le.c index 9bb7801a412..69e57cf3189 100644 --- a/components/bt/host/bluedroid/bta/hh/bta_hh_le.c +++ b/components/bt/host/bluedroid/bta/hh/bta_hh_le.c @@ -2266,17 +2266,12 @@ void bta_hh_le_input_rpt_notify(tBTA_GATTC_NOTIFY *p_data) p_buf = p_data->value; } - bta_hh_co_data((UINT8)p_dev_cb->hid_handle, - p_buf, - p_data->len, - p_dev_cb->mode, - 0 , /* no sub class*/ - p_dev_cb->dscp_info.ctry_code, - p_dev_cb->addr, - app_id); - - if (p_buf != p_data->value) { - osi_free(p_buf); + if (p_buf == p_data->value) { + bta_hh_le_co_data((UINT8)p_dev_cb->hid_handle, p_buf, p_data->len, p_dev_cb->mode, 0, /* no sub class*/ + p_dev_cb->dscp_info.ctry_code, p_dev_cb->addr, app_id); + } else { + bta_hh_le_co_data_owned((UINT8)p_dev_cb->hid_handle, p_buf, p_data->len, p_dev_cb->mode, 0, /* no sub class*/ + p_dev_cb->dscp_info.ctry_code, p_dev_cb->addr, app_id); } } diff --git a/components/bt/host/bluedroid/bta/hh/include/bta_hh_int.h b/components/bt/host/bluedroid/bta/hh/include/bta_hh_int.h index 0efb2fcab49..56f99e8420d 100644 --- a/components/bt/host/bluedroid/bta/hh/include/bta_hh_int.h +++ b/components/bt/host/bluedroid/bta/hh/include/bta_hh_int.h @@ -28,6 +28,8 @@ #include "bta/bta_sys.h" #include "bta/utl.h" #include "bta/bta_hh_api.h" +#include "osi/pkt_queue.h" +#include "osi/thread.h" //#if BTA_HH_LE_INCLUDED == TRUE #include "bta/bta_gatt_api.h" @@ -82,7 +84,7 @@ typedef UINT16 tBTA_HH_INT_EVT; /* HID host internal events */ #define BTA_HH_FST_TRANS_CB_EVT BTA_HH_GET_RPT_EVT #define BTA_HH_FST_BTE_TRANS_EVT HID_TRANS_GET_REPORT -/* sub event code used for device maintainence API call */ +/* sub event code used for device maintenance API call */ #define BTA_HH_ADD_DEV 0 #define BTA_HH_REMOVE_DEV 1 @@ -201,7 +203,7 @@ typedef struct { #define BTA_HH_LE_PROTO_MODE_BIT 0x01 #define BTA_HH_LE_CP_BIT 0x02 - UINT8 option_char; /* control point char exisit or not */ + UINT8 option_char; /* control point char exist or not */ BOOLEAN expl_incl_srvc; UINT8 incl_srvc_inst; /* assuming only one included service : battery service */ diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_hh_co.h b/components/bt/host/bluedroid/bta/include/bta/bta_hh_co.h index f0fef370c83..05343c2a97c 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_hh_co.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_hh_co.h @@ -25,6 +25,10 @@ #define BTA_HH_CO_H #include "bta/bta_hh_api.h" +#include "osi/pkt_queue.h" +#include "stack/bt_types.h" + +#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE) typedef struct { UINT16 rpt_uuid; @@ -34,21 +38,48 @@ typedef struct { UINT8 prop; } tBTA_HH_RPT_CACHE_ENTRY; +typedef enum { + BTA_HH_DATA_BUF_RAW = 0, + BTA_HH_DATA_BUF_BT_HDR, +} tBTA_HH_DATA_BUF_TYPE; + +typedef struct { + UINT8 dev_handle; + UINT8 buf_type; // see tBTA_HH_DATA_BUF_TYPE + tBTA_HH_PROTO_MODE proto_mode; + UINT16 len; + void *p_buf; +} tBTA_HH_DATA_PKT; + +extern void bta_hh_co_data_pkt_free(tBTA_HH_DATA_PKT *pkt); +extern void bta_hh_co_data_linked_pkt_free(pkt_linked_item_t *item); +extern UINT8 *bta_hh_co_data_pkt_get_payload(tBTA_HH_DATA_PKT *pkt); + /******************************************************************************* ** ** Function bta_hh_co_data ** ** Description This callout function is executed by HH when data is received -** in interupt channel. +** in interrupt channel. ** ** ** Returns void. ** *******************************************************************************/ -extern void bta_hh_co_data(UINT8 dev_handle, UINT8 *p_rpt, UINT16 len, + +extern void bta_hh_co_data_hdr(UINT8 dev_handle, BT_HDR *p_hdr, + tBTA_HH_PROTO_MODE mode, UINT8 sub_class, + UINT8 ctry_code, BD_ADDR peer_addr, UINT8 app_id); +#if (BLE_INCLUDED == TRUE && BTA_HH_LE_INCLUDED == TRUE) +extern void bta_hh_le_co_data(UINT8 dev_handle, UINT8 *p_rpt, UINT16 len, tBTA_HH_PROTO_MODE mode, UINT8 sub_class, UINT8 ctry_code, BD_ADDR peer_addr, UINT8 app_id); +extern void bta_hh_le_co_data_owned(UINT8 dev_handle, UINT8 *p_buf, UINT16 len, + tBTA_HH_PROTO_MODE mode, UINT8 sub_class, + UINT8 ctry_code, BD_ADDR peer_addr, UINT8 app_id); +#endif /* (BLE_INCLUDED == TRUE && BTA_HH_LE_INCLUDED == TRUE) */ + /******************************************************************************* ** ** Function bta_hh_co_open @@ -57,11 +88,11 @@ extern void bta_hh_co_data(UINT8 dev_handle, UINT8 *p_rpt, UINT16 len, ** opened, and application may do some device specific ** initialization. ** -** Returns void. +** Returns TRUE if platform specific initialization succeeds. ** *******************************************************************************/ -extern void bta_hh_co_open(UINT8 dev_handle, UINT8 sub_class, - UINT16 attr_mask, UINT8 app_id); +extern BOOLEAN bta_hh_co_open(UINT8 dev_handle, UINT8 sub_class, + UINT16 attr_mask, UINT8 app_id); /******************************************************************************* ** @@ -129,4 +160,5 @@ extern tBTA_HH_RPT_CACHE_ENTRY *bta_hh_le_co_cache_load (BD_ADDR remote_bda, extern void bta_hh_le_co_reset_rpt_cache (BD_ADDR remote_bda, UINT8 app_id); #endif /* #if (BLE_INCLUDED == TRUE && BTA_HH_LE_INCLUDED == TRUE) */ +#endif /* defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE) */ #endif /* BTA_HH_CO_H */ diff --git a/components/bt/host/bluedroid/btc/profile/std/hid/bta_hh_co.c b/components/bt/host/bluedroid/btc/profile/std/hid/bta_hh_co.c index 63daecafa64..0885a26b447 100644 --- a/components/bt/host/bluedroid/btc/profile/std/hid/bta_hh_co.c +++ b/components/bt/host/bluedroid/btc/profile/std/hid/bta_hh_co.c @@ -1,8 +1,49 @@ #include #include "btc_hh.h" +#include "bta/utl.h" #include "osi/allocator.h" #if HID_HOST_INCLUDED == TRUE +void bta_hh_co_data_pkt_free(tBTA_HH_DATA_PKT *pkt) +{ + if (pkt == NULL || pkt->p_buf == NULL) { + return; + } + + if (pkt->buf_type == BTA_HH_DATA_BUF_BT_HDR) { + utl_freebuf((void **)&pkt->p_buf); + } else { + osi_free(pkt->p_buf); + } + pkt->p_buf = NULL; +} + +void bta_hh_co_data_linked_pkt_free(pkt_linked_item_t *item) +{ + if (item == NULL) { + return; + } + + bta_hh_co_data_pkt_free((tBTA_HH_DATA_PKT *)item->data); + osi_free(item); +} + +UINT8 *bta_hh_co_data_pkt_get_payload(tBTA_HH_DATA_PKT *pkt) +{ + BT_HDR *hdr; + + if (pkt == NULL || pkt->p_buf == NULL || pkt->len == 0) { + return NULL; + } + + if (pkt->buf_type == BTA_HH_DATA_BUF_BT_HDR) { + hdr = (BT_HDR *)pkt->p_buf; + return hdr->data + hdr->offset; + } + + return (UINT8 *)pkt->p_buf; +} + /******************************************************************************* * * Function bta_hh_co_open @@ -10,16 +51,18 @@ * Description When connection is opened, this call-out function is executed * by HH to do platform specific initialization. * - * Returns void. + * Returns TRUE if platform specific initialization succeeds. ******************************************************************************/ -void bta_hh_co_open(UINT8 dev_handle, UINT8 sub_class, tBTA_HH_ATTR_MASK attr_mask, UINT8 app_id) +BOOLEAN bta_hh_co_open(UINT8 dev_handle, UINT8 sub_class, tBTA_HH_ATTR_MASK attr_mask, UINT8 app_id) { + BOOLEAN is_new_device = TRUE; + uint8_t old_dev_status = ESP_HIDH_CONN_STATE_UNKNOWN; UINT32 i; btc_hh_device_t *p_dev = NULL; if (dev_handle == BTA_HH_INVALID_HANDLE) { APPL_TRACE_WARNING("%s: Oops, dev_handle (%d) is invalid...", __func__, dev_handle); - return; + return FALSE; } for (i = 0; i < BTC_HH_MAX_HID; i++) { @@ -30,6 +73,8 @@ void bta_hh_co_open(UINT8 dev_handle, UINT8 sub_class, tBTA_HH_ATTR_MASK attr_ma "dev_handle=0x%2x, attr_mask=0x%04x, sub_class=0x%02x, app_id=%d", __func__, p_dev->dev_status, dev_handle, p_dev->attr_mask, p_dev->sub_class, p_dev->app_id); + is_new_device = FALSE; + old_dev_status = p_dev->dev_status; break; } p_dev = NULL; @@ -54,11 +99,26 @@ void bta_hh_co_open(UINT8 dev_handle, UINT8 sub_class, tBTA_HH_ATTR_MASK attr_ma if (p_dev == NULL) { APPL_TRACE_ERROR("%s: Error: too many HID devices are connected", __func__); - return; + return FALSE; } p_dev->dev_status = ESP_HIDH_CONN_STATE_CONNECTED; + if (!btc_hh_data_path_init(dev_handle)) { + APPL_TRACE_ERROR("%s: failed to init HID host datapath, dev_handle=%u", __func__, dev_handle); + if (is_new_device) { + p_dev->dev_status = ESP_HIDH_CONN_STATE_UNKNOWN; + p_dev->dev_handle = BTA_HH_INVALID_HANDLE; + if (btc_hh_cb.device_num) { + btc_hh_cb.device_num--; + } + } else { + p_dev->dev_status = old_dev_status; + } + return FALSE; + } + APPL_TRACE_DEBUG("%s: Return device status %d", __func__, p_dev->dev_status); + return TRUE; } /******************************************************************************* @@ -93,64 +153,133 @@ void bta_hh_co_close(UINT8 dev_handle, UINT8 app_id) break; } } + + // data path will be cleaned up on CLOSE or UNPLUG event in btc context } /******************************************************************************* * - * Function bta_hh_co_data + * Function bta_hh_co_data_hdr * - * Description This function is executed by BTA when HID host receive a - * data report on interrupt channel. - * - * Parameters dev_handle - device handle - * *p_rpt - pointer to the report data - * len - length of report data - * mode - Hid host Protocol Mode - * sub_clas - Device Subclass - * app_id - application id + * Description Transfer BT_HDR ownership to BTC queue (BR/EDR zero-copy). * * Returns void ******************************************************************************/ -void bta_hh_co_data(UINT8 dev_handle, UINT8 *p_rpt, UINT16 len, tBTA_HH_PROTO_MODE mode, UINT8 sub_class, UINT8 ctry_code, - BD_ADDR peer_addr, UINT8 app_id) +void bta_hh_co_data_hdr(UINT8 dev_handle, BT_HDR *p_hdr, tBTA_HH_PROTO_MODE mode, UINT8 sub_class, UINT8 ctry_code, + BD_ADDR peer_addr, UINT8 app_id) { - btc_msg_t msg; - tBTA_HH p_data; - BT_HDR *p_buf = NULL; - bt_status_t status; - tBTA_HH_STATUS ret = BTA_HH_OK; - - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_HH; - msg.act = BTA_HH_DATA_IND_EVT; + pkt_linked_item_t *linked_pkt = NULL; + tBTA_HH_DATA_PKT *pkt; APPL_TRACE_DEBUG("%s: dev_handle = %d, subclass = 0x%02X, mode = %d, " "ctry_code = %d, app_id = %d", __func__, dev_handle, sub_class, mode, ctry_code, app_id); - do { - if ((p_rpt == NULL) || (len == 0)) { - ret = BTA_HH_ERR; - break; - } - if ((p_buf = osi_malloc(sizeof(BT_HDR) + len)) == NULL) { - APPL_TRACE_ERROR("%s malloc failed!", __func__); - ret = BTA_HH_ERR_NO_RES; - break; - } - p_buf->offset = 0; - p_buf->len = len; - p_buf->event = 0; - p_buf->layer_specific = dev_handle; - memcpy(p_buf->data, p_rpt, len); - } while (0); + if (p_hdr == NULL || p_hdr->len == 0) { + utl_freebuf((void **)&p_hdr); + return; + } - p_data.int_data.status = ret; - p_data.int_data.handle = dev_handle; - p_data.int_data.p_data = p_buf; - p_data.int_data.proto_mode = mode; - status = btc_transfer_context(&msg, &p_data, sizeof(tBTA_HH), NULL, NULL); - assert(status == BT_STATUS_SUCCESS); + linked_pkt = btc_hh_data_dequeue_reusable_linked_pkt(dev_handle); + if (linked_pkt != NULL) { + bta_hh_co_data_pkt_free((tBTA_HH_DATA_PKT *)linked_pkt->data); + } else { + linked_pkt = (pkt_linked_item_t *)osi_malloc(BT_PKT_LINKED_HDR_SIZE + + sizeof(tBTA_HH_DATA_PKT)); + if (linked_pkt == NULL) { + btc_hh_on_pkt_dropped(dev_handle); + utl_freebuf((void **)&p_hdr); + return; + } + } + + pkt = (tBTA_HH_DATA_PKT *)linked_pkt->data; + pkt->dev_handle = dev_handle; + pkt->len = p_hdr->len; + pkt->proto_mode = mode; + pkt->buf_type = BTA_HH_DATA_BUF_BT_HDR; + pkt->p_buf = p_hdr; + + if (!btc_hh_data_enqueue_linked_pkt(linked_pkt)) { + btc_hh_on_pkt_dropped(dev_handle); + bta_hh_co_data_linked_pkt_free(linked_pkt); + } +} +#endif /* HID_HOST_INCLUDED == TRUE */ + +#if (BLE_INCLUDED == TRUE && BTA_HH_LE_INCLUDED == TRUE) +/******************************************************************************* + * + * Function bta_hh_le_co_data_owned + * + * Description Transfer raw buffer ownership to BTC queue (BLE zero-copy). + * + * Returns void + ******************************************************************************/ +void bta_hh_le_co_data_owned(UINT8 dev_handle, UINT8 *p_buf, UINT16 len, tBTA_HH_PROTO_MODE mode, UINT8 sub_class, + UINT8 ctry_code, BD_ADDR peer_addr, UINT8 app_id) +{ + tBTA_HH_DATA_PKT pkt = { + .dev_handle = dev_handle, + .len = len, + .proto_mode = mode, + .buf_type = BTA_HH_DATA_BUF_RAW, + .p_buf = p_buf, + }; + + APPL_TRACE_DEBUG("%s: dev_handle = %d, subclass = 0x%02X, mode = %d, " + "ctry_code = %d, app_id = %d", + __func__, dev_handle, sub_class, mode, ctry_code, app_id); + + if ((p_buf == NULL) || (len == 0)) { + osi_free(p_buf); + return; + } + + if (!btc_hh_data_enqueue_pkt(&pkt)) { + btc_hh_on_pkt_dropped(dev_handle); + osi_free(p_buf); + } } -#endif /* HID_HOST_INCLUDED == TRUE */ +/******************************************************************************* + * + * Function bta_hh_le_co_data + * + * Description Copy ephemeral report data into BTC queue (BLE GATT notify). + * + * Returns void + ******************************************************************************/ +void bta_hh_le_co_data(UINT8 dev_handle, UINT8 *p_rpt, UINT16 len, tBTA_HH_PROTO_MODE mode, UINT8 sub_class, + UINT8 ctry_code, BD_ADDR peer_addr, UINT8 app_id) +{ + UINT8 *p_buf; + tBTA_HH_DATA_PKT pkt; + + APPL_TRACE_DEBUG("%s: dev_handle = %d, subclass = 0x%02X, mode = %d, " + "ctry_code = %d, app_id = %d", + __func__, dev_handle, sub_class, mode, ctry_code, app_id); + + if ((p_rpt == NULL) || (len == 0)) { + return; + } + + p_buf = (UINT8 *)osi_malloc(len); + if (p_buf == NULL) { + btc_hh_on_pkt_dropped(dev_handle); + return; + } + memcpy(p_buf, p_rpt, len); + + pkt.dev_handle = dev_handle; + pkt.len = len; + pkt.proto_mode = mode; + pkt.buf_type = BTA_HH_DATA_BUF_RAW; + pkt.p_buf = p_buf; + + if (!btc_hh_data_enqueue_pkt(&pkt)) { + btc_hh_on_pkt_dropped(dev_handle); + osi_free(p_buf); + } +} +#endif /* (BLE_INCLUDED == TRUE && BTA_HH_LE_INCLUDED == TRUE) */ diff --git a/components/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c b/components/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c index cda6db3dff2..e73594210ae 100644 --- a/components/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c +++ b/components/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c @@ -34,9 +34,13 @@ #include "device/bdaddr.h" #include "btc/btc_storage.h" #include "osi/allocator.h" +#include "osi/pkt_queue.h" +#include "stack/bt_types.h" +#include "stack/gatt_api.h" #include "bta/utl.h" #include "bta/bta_hh_api.h" #include "stack/l2c_api.h" +#include "esp_log.h" // #include "bta_dm_int.h" #if HID_HOST_INCLUDED == TRUE @@ -64,7 +68,25 @@ static bdstr_t bdstr; #define is_hidh_init() (btc_hh_cb.status > BTC_HH_DISABLED) #define BTC_TIMEOUT_VUP_MS (3 * 1000) +#define BTC_HH_DATA_QUEUE_IDX (1) +/** + * Low-latency profile for gamepad-like traffic: + * keep queue short to avoid stale input backlog and keep batch moderate. + */ +#define BTC_HH_DATA_QUEUE_LEN_MAX (20) // for high report rate, the queue will cause 1.25ms * BTC_HH_DATA_QUEUE_LEN_MAX latency +#define BTC_HH_DATA_BATCH_SIZE_BASE (8) +#define BTC_HH_DATA_BATCH_SIZE_HIGH (10) +#define BTC_HH_DATA_BATCH_SIZE_MAX (12) + static void btc_hh_cb_arg_deep_free(btc_msg_t *msg); +static void btc_hh_data_pkt_handler(void *arg); +static size_t btc_hh_get_batch_size(size_t queue_len); +static bool btc_hh_data_path_init_inner(btc_hh_device_t *p_dev); +static void btc_hh_data_path_deinit_inner(btc_hh_device_t *p_dev); +static bool btc_hh_device_drop_cnt_init(btc_hh_device_t *p_dev); +static void btc_hh_device_drop_cnt_deinit(btc_hh_device_t *p_dev); +static void btc_hh_device_drop_cnt_set(btc_hh_device_t *p_dev, uint32_t cnt); +static void btc_hh_device_drop_cnt_inc(btc_hh_device_t *p_dev); static inline void btc_hh_cb_to_app(esp_hidh_cb_event_t event, esp_hidh_cb_param_t *param) { @@ -146,6 +168,68 @@ btc_hh_device_t *btc_hh_find_connected_dev_by_handle(uint8_t handle) return NULL; } +static bool btc_hh_device_drop_cnt_init(btc_hh_device_t *p_dev) +{ + if (p_dev == NULL) { + return false; + } + + return (osi_mutex_new(&p_dev->lock) == 0); +} + +static void btc_hh_device_drop_cnt_deinit(btc_hh_device_t *p_dev) +{ + if (p_dev == NULL) { + return; + } + + osi_mutex_free(&p_dev->lock); +} + +static void btc_hh_device_drop_cnt_set(btc_hh_device_t *p_dev, uint32_t cnt) +{ + if (p_dev == NULL) { + return; + } + + osi_mutex_lock(&p_dev->lock, OSI_MUTEX_MAX_TIMEOUT); + p_dev->drop_pkt_cnt = cnt; + osi_mutex_unlock(&p_dev->lock); +} + +static void btc_hh_device_drop_cnt_inc(btc_hh_device_t *p_dev) +{ + if (p_dev == NULL) { + return; + } + + osi_mutex_lock(&p_dev->lock, OSI_MUTEX_MAX_TIMEOUT); + p_dev->drop_pkt_cnt++; + osi_mutex_unlock(&p_dev->lock); +} + +void btc_hh_on_pkt_dropped(uint8_t dev_handle) +{ + btc_hh_device_t *p_dev = btc_hh_find_connected_dev_by_handle(dev_handle); + + if (p_dev == NULL) { + return; + } + + btc_hh_device_drop_cnt_inc(p_dev); +} + +void btc_hh_reset_drop_pkt_cnt(uint8_t dev_handle) +{ + btc_hh_device_t *p_dev = btc_hh_find_connected_dev_by_handle(dev_handle); + + if (p_dev == NULL) { + return; + } + + btc_hh_device_drop_cnt_set(p_dev, 0); +} + /******************************************************************************* * * Function btc_hh_find_dev_by_bda @@ -337,9 +421,10 @@ void btc_hh_remove_device(BD_ADDR bd_addr) * with up-layer */ //[boblane] // HAL_CBACK(bt_hh_callbacks, connection_state_cb, &(p_dev->bd_addr), BTHH_CONN_STATE_DISCONNECTED); + btc_hh_device_drop_cnt_set(p_dev, 0); p_dev->dev_status = ESP_HIDH_CONN_STATE_UNKNOWN; p_dev->dev_handle = BTA_HH_INVALID_HANDLE; - p_dev->ready_for_data = false; + btc_hh_data_path_deinit_inner(p_dev); if (btc_hh_cb.device_num > 0) { btc_hh_cb.device_num--; @@ -367,23 +452,6 @@ static void bte_hh_arg_deep_copy(btc_msg_t *msg, void *p_dst, void *p_src) } break; } - case BTA_HH_DATA_IND_EVT: { - BT_HDR *src_hdr = p_src_data->int_data.p_data; - p_dst_data->int_data.p_data = NULL; - if (src_hdr) { - p_dst_data->int_data.p_data = osi_malloc(sizeof(BT_HDR) + src_hdr->len); - if (p_dst_data->int_data.p_data == NULL) { - BTC_TRACE_ERROR("%s malloc int_data.p_data failed!", __func__); - p_dst_data->int_data.status = ESP_HIDH_ERR_NO_RES; - break; - } - BT_HDR *dst_hdr = p_dst_data->int_data.p_data; - memcpy(dst_hdr, src_hdr, sizeof(BT_HDR)); - memcpy(dst_hdr->data, src_hdr->data + src_hdr->offset, src_hdr->len); - dst_hdr->offset = 0; - } - break; - } default: break; } @@ -442,9 +510,6 @@ static void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH *p_data) case BTA_HH_DATA_EVT: param_len = sizeof(tBTA_HH_API_SENDDATA); break; - case BTA_HH_DATA_IND_EVT: - param_len = sizeof(tBTA_HH_INTDATA); - break; case BTA_HH_API_ERR_EVT: param_len = 0; break; @@ -472,6 +537,7 @@ static void btc_hh_init(void) { BTC_TRACE_API("%s", __func__); esp_hidh_status_t ret = ESP_HIDH_OK; + uint8_t i; do { if (is_hidh_init()) { BTC_TRACE_ERROR("%s HH has been initiated, shall uninit first!", __func__); @@ -480,8 +546,19 @@ static void btc_hh_init(void) } memset(&btc_hh_cb, 0, sizeof(btc_hh_cb)); - for (uint8_t i = 0; i < BTC_HH_MAX_HID; i++) { + for (i = 0; i < BTC_HH_MAX_HID; i++) { btc_hh_cb.devices[i].dev_status = ESP_HIDH_CONN_STATE_UNKNOWN; + if (!btc_hh_device_drop_cnt_init(&btc_hh_cb.devices[i])) { + BTC_TRACE_ERROR("%s: device lock init failed", __func__); + ret = ESP_HIDH_ERR_NO_RES; + break; + } + } + if (ret != ESP_HIDH_OK) { + while (i-- > 0) { + btc_hh_device_drop_cnt_deinit(&btc_hh_cb.devices[i]); + } + break; } BTA_HhEnable(BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT, bte_hh_evt); } while (0); @@ -1220,14 +1297,263 @@ static void btc_hh_cb_arg_deep_free(btc_msg_t *msg) case BTA_HH_GET_RPT_EVT: utl_freebuf((void **)&arg->hs_data.rsp_data.p_rpt_data); break; - case BTA_HH_DATA_IND_EVT: - utl_freebuf((void **)&arg->int_data.p_data); - break; default: break; } } +static void btc_hh_data_path_deinit_inner(btc_hh_device_t *p_dev) +{ + struct pkt_queue *queue; + struct osi_event *event; + + if (p_dev == NULL) { + return; + } + + osi_mutex_lock(&p_dev->lock, OSI_MUTEX_MAX_TIMEOUT); + queue = p_dev->data_queue; + event = p_dev->data_ready; + p_dev->data_queue = NULL; + p_dev->data_ready = NULL; + osi_mutex_unlock(&p_dev->lock); + + if (event != NULL) { + osi_event_delete(event); + } + + if (queue != NULL) { + pkt_queue_destroy(queue, bta_hh_co_data_linked_pkt_free); + } +} + +bool btc_hh_data_enqueue_linked_pkt(pkt_linked_item_t *linked_pkt) +{ + tBTA_HH_DATA_PKT *pkt = linked_pkt != NULL ? (tBTA_HH_DATA_PKT *)linked_pkt->data : NULL; + btc_hh_device_t *p_dev = pkt != NULL ? btc_hh_find_connected_dev_by_handle(pkt->dev_handle) : NULL; + struct pkt_queue *data_queue; + struct osi_event *data_ready; + pkt_linked_item_t *old = NULL; + bool enqueue_ok; + + if (p_dev == NULL || pkt == NULL || pkt->p_buf == NULL || pkt->len == 0) { + return false; + } + + osi_mutex_lock(&p_dev->lock, OSI_MUTEX_MAX_TIMEOUT); + data_queue = p_dev->data_queue; + data_ready = p_dev->data_ready; + if (data_queue == NULL) { + osi_mutex_unlock(&p_dev->lock); + return false; + } + + if (pkt_queue_length(data_queue) >= BTC_HH_DATA_QUEUE_LEN_MAX) { + old = pkt_queue_dequeue(data_queue); + if (old != NULL) { + p_dev->drop_pkt_cnt++; + } + } + + enqueue_ok = pkt_queue_enqueue(data_queue, linked_pkt); + if (enqueue_ok && data_ready != NULL) { + osi_thread_post_event(data_ready, 0); + } + osi_mutex_unlock(&p_dev->lock); + + if (old != NULL) { + bta_hh_co_data_linked_pkt_free(old); + } + + return enqueue_ok; +} + +pkt_linked_item_t *btc_hh_data_dequeue_reusable_linked_pkt(uint8_t dev_handle) +{ + btc_hh_device_t *p_dev = btc_hh_find_connected_dev_by_handle(dev_handle); + struct pkt_queue *data_queue; + pkt_linked_item_t *old; + + if (p_dev == NULL) { + return NULL; + } + + osi_mutex_lock(&p_dev->lock, OSI_MUTEX_MAX_TIMEOUT); + data_queue = p_dev->data_queue; + if (data_queue == NULL || pkt_queue_length(data_queue) < BTC_HH_DATA_QUEUE_LEN_MAX) { + osi_mutex_unlock(&p_dev->lock); + return NULL; + } + + old = pkt_queue_dequeue(data_queue); + if (old != NULL) { + p_dev->drop_pkt_cnt++; + } + osi_mutex_unlock(&p_dev->lock); + + return old; +} + +bool btc_hh_data_enqueue_pkt(const tBTA_HH_DATA_PKT *pkt_meta) +{ + pkt_linked_item_t *linked_pkt; + tBTA_HH_DATA_PKT *pkt; + + if (pkt_meta == NULL || pkt_meta->p_buf == NULL || pkt_meta->len == 0) { + return false; + } + + linked_pkt = (pkt_linked_item_t *)osi_malloc(BT_PKT_LINKED_HDR_SIZE + sizeof(tBTA_HH_DATA_PKT)); + if (linked_pkt == NULL) { + return false; + } + + pkt = (tBTA_HH_DATA_PKT *)linked_pkt->data; + *pkt = *pkt_meta; + + if (!btc_hh_data_enqueue_linked_pkt(linked_pkt)) { + osi_free(linked_pkt); + return false; + } + + return true; +} + +static bool btc_hh_data_path_init_inner(btc_hh_device_t *p_dev) +{ + bool result = false; + struct pkt_queue *data_queue = NULL; + struct osi_event *data_ready = NULL; + + do { + if (p_dev == NULL) { + break; + } + + osi_mutex_lock(&p_dev->lock, OSI_MUTEX_MAX_TIMEOUT); + if (p_dev->data_queue != NULL && p_dev->data_ready != NULL) { + osi_mutex_unlock(&p_dev->lock); + result = true; + break; + } + osi_mutex_unlock(&p_dev->lock); + + btc_hh_data_path_deinit_inner(p_dev); + + data_queue = pkt_queue_create(); + if (data_queue == NULL) { + BTC_TRACE_ERROR("%s: pkt_queue_create failed", __func__); + break; + } + + data_ready = osi_event_create(btc_hh_data_pkt_handler, p_dev); + if (data_ready == NULL) { + BTC_TRACE_ERROR("%s: osi_event_create failed", __func__); + break; + } + + if (!osi_event_bind(data_ready, btc_get_current_thread(), BTC_HH_DATA_QUEUE_IDX)) { + BTC_TRACE_ERROR("%s: osi_event_bind failed", __func__); + break; + } + + osi_mutex_lock(&p_dev->lock, OSI_MUTEX_MAX_TIMEOUT); + p_dev->data_queue = data_queue; + p_dev->data_ready = data_ready; + p_dev->drop_pkt_cnt = 0; + osi_mutex_unlock(&p_dev->lock); + data_queue = NULL; + data_ready = NULL; + result = true; + } while (0); + + if (!result) { + btc_hh_data_path_deinit_inner(p_dev); + if (data_ready != NULL) { + osi_event_delete(data_ready); + } + if (data_queue != NULL) { + pkt_queue_destroy(data_queue, bta_hh_co_data_linked_pkt_free); + } + } + + return result; +} + +bool btc_hh_data_path_init(uint8_t dev_handle) +{ + btc_hh_device_t *p_dev = btc_hh_find_connected_dev_by_handle(dev_handle); + return btc_hh_data_path_init_inner(p_dev); +} + +static size_t btc_hh_get_batch_size(size_t queue_len) +{ + size_t batch_size = BTC_HH_DATA_BATCH_SIZE_BASE; + + if (queue_len >= BTC_HH_DATA_BATCH_SIZE_MAX) { + batch_size = BTC_HH_DATA_BATCH_SIZE_MAX; + } else if (queue_len >= BTC_HH_DATA_BATCH_SIZE_HIGH) { + batch_size = BTC_HH_DATA_BATCH_SIZE_HIGH; + } + + return batch_size; +} + +static void btc_hh_data_pkt_handler(void *arg) +{ + tBTA_HH_DATA_PKT *pkt; + pkt_linked_item_t *linked_pkt; + btc_hh_device_t *p_dev = (btc_hh_device_t *)arg; + size_t pkts_to_process; + size_t batch_limit; + uint32_t drop_pkt_cnt; + + if (p_dev == NULL || p_dev->data_queue == NULL) { + return; + } + + drop_pkt_cnt = p_dev->drop_pkt_cnt; + if (drop_pkt_cnt) { + osi_mutex_lock(&p_dev->lock, OSI_MUTEX_MAX_TIMEOUT); + drop_pkt_cnt = p_dev->drop_pkt_cnt; + p_dev->drop_pkt_cnt = 0; + osi_mutex_unlock(&p_dev->lock); + + BTC_TRACE_WARNING("hh hdl:%d drop %u pkts", p_dev->dev_handle, (unsigned int)drop_pkt_cnt); + } + + pkts_to_process = pkt_queue_length(p_dev->data_queue); + batch_limit = btc_hh_get_batch_size(pkts_to_process); + if (pkts_to_process > batch_limit) { + pkts_to_process = batch_limit; + } + + for (size_t i = 0; i < pkts_to_process; i++) { + esp_hidh_cb_param_t param = {0}; + + linked_pkt = pkt_queue_dequeue(p_dev->data_queue); + if (linked_pkt == NULL) { + break; + } + + pkt = (tBTA_HH_DATA_PKT *)linked_pkt->data; + BTC_TRACE_DEBUG("handle = %d", pkt->dev_handle); + if (pkt->len > 0) { + param.data_ind.len = pkt->len; + param.data_ind.data = bta_hh_co_data_pkt_get_payload(pkt); + } + param.data_ind.handle = pkt->dev_handle; + param.data_ind.status = ESP_HIDH_OK; + param.data_ind.proto_mode = proto_mode_change_to_upper_layer(pkt->proto_mode); + btc_hh_cb_to_app(ESP_HIDH_DATA_IND_EVT, ¶m); + bta_hh_co_data_linked_pkt_free(linked_pkt); + } + + if (p_dev->data_ready != NULL && !pkt_queue_is_empty(p_dev->data_queue)) { + osi_thread_post_event(p_dev->data_ready, 0); + } +} + bool btc_hh_copy_hid_info(tBTA_HH_DEV_DSCP_INFO *dest, tBTA_HH_DEV_DSCP_INFO *src) { dest->descriptor.dl_len = 0; @@ -1287,12 +1613,20 @@ void btc_hh_cb_handler(btc_msg_t *msg) btc_hh_cb.status = BTC_HH_ENABLED; BTC_TRACE_DEBUG("Loading added devices"); /* Add hid descriptors for already bonded hid devices*/ - // btc_storage_load_bonded_hid_info(); + btc_storage_load_bonded_hid_info(); + param.init.status = ESP_HIDH_OK; } else { + for (i = 0; i < BTC_HH_MAX_HID; i++) { + btc_hh_device_drop_cnt_deinit(&btc_hh_cb.devices[i]); + } + memset(&btc_hh_cb, 0, sizeof(btc_hh_cb)); + for (i = 0; i < BTC_HH_MAX_HID; i++) { + btc_hh_cb.devices[i].dev_status = ESP_HIDH_CONN_STATE_UNKNOWN; + } btc_hh_cb.status = BTC_HH_DISABLED; BTC_TRACE_ERROR("Error, HH enabling failed, status = %d", p_data->status); + param.init.status = p_data->status; } - param.init.status = p_data->status; btc_hh_cb_to_app(ESP_HIDH_INIT_EVT, ¶m); break; case BTA_HH_DISABLE_EVT: @@ -1302,9 +1636,12 @@ void btc_hh_cb_handler(btc_msg_t *msg) // btif_hd_service_registration(); btc_hh_cb.service_dereg_active = FALSE; } + if (p_data->status == BTA_HH_OK) { // Clear the control block for (i = 0; i < BTC_HH_MAX_HID; i++) { + btc_hh_data_path_deinit_inner(&btc_hh_cb.devices[i]); + btc_hh_device_drop_cnt_deinit(&btc_hh_cb.devices[i]); if (btc_hh_cb.devices[i].vup_timer) { osi_alarm_free(btc_hh_cb.devices[i].vup_timer); } @@ -1343,9 +1680,8 @@ void btc_hh_cb_handler(btc_msg_t *msg) // if (check_cod(&p_data->conn.bda, COD_HID_KEYBOARD) || check_cod(&p_data->conn.bda, COD_HID_COMBO)) // BTA_HhSetIdle(p_data->conn.handle, 0); btc_hh_cb.p_curr_dev = btc_hh_find_connected_dev_by_handle(p_data->conn.handle); - BTA_HhGetDscpInfo(p_data->conn.handle); p_dev->dev_status = ESP_HIDH_CONN_STATE_CONNECTED; - + BTA_HhGetDscpInfo(p_data->conn.handle); param.open.status = ESP_HIDH_OK; param.open.conn_status = ESP_HIDH_CONN_STATE_CONNECTED; } @@ -1354,6 +1690,7 @@ void btc_hh_cb_handler(btc_msg_t *msg) if (p_dev != NULL) { btc_hh_stop_vup_timer(p_dev->bd_addr); p_dev->dev_status = ESP_HIDH_CONN_STATE_DISCONNECTED; + btc_hh_data_path_deinit_inner(p_dev); } btc_hh_cb.status = (BTC_HH_STATUS)BTC_HH_DEV_DISCONNECTED; @@ -1419,10 +1756,13 @@ void btc_hh_cb_handler(btc_msg_t *msg) case BTA_HH_CLOSE_EVT: BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->dev_status.status, p_data->dev_status.handle); + btc_hh_cb.status = (BTC_HH_STATUS)BTC_HH_DEV_DISCONNECTED; p_dev = btc_hh_find_connected_dev_by_handle(p_data->dev_status.handle); if (p_dev != NULL) { BTC_TRACE_DEBUG("uhid local_vup=%d", p_dev->local_vup); btc_hh_stop_vup_timer(p_dev->bd_addr); + p_dev->dev_status = ESP_HIDH_CONN_STATE_DISCONNECTED; + btc_hh_data_path_deinit_inner(p_dev); /* If this is a locally initiated VUP, remove the bond as ACL got * disconnected while VUP being processed. */ @@ -1432,11 +1772,7 @@ void btc_hh_cb_handler(btc_msg_t *msg) BTA_DmRemoveDevice(p_dev->bd_addr, BT_TRANSPORT_BR_EDR); #endif btc_hh_remove_device(p_dev->bd_addr); - } else { - p_dev->dev_status = ESP_HIDH_CONN_STATE_DISCONNECTED; } - - btc_hh_cb.status = (BTC_HH_STATUS)BTC_HH_DEV_DISCONNECTED; param.close.status = p_data->dev_status.status; } else { BTC_TRACE_ERROR("Error: cannot find device with handle %d", p_data->dev_status.handle); @@ -1449,12 +1785,13 @@ void btc_hh_cb_handler(btc_msg_t *msg) case BTA_HH_VC_UNPLUG_EVT: BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->dev_status.status, p_data->dev_status.handle); - p_dev = btc_hh_find_connected_dev_by_handle(p_data->dev_status.handle); btc_hh_cb.status = (BTC_HH_STATUS)BTC_HH_DEV_DISCONNECTED; + p_dev = btc_hh_find_connected_dev_by_handle(p_data->dev_status.handle); if (p_dev != NULL) { /* Stop the VUP timer */ btc_hh_stop_vup_timer(p_dev->bd_addr); p_dev->dev_status = ESP_HIDH_CONN_STATE_DISCONNECTED; + btc_hh_data_path_deinit_inner(p_dev); BTC_TRACE_DEBUG("%s---Sending connection state change", __func__); param.close.status = ESP_HIDH_OK; param.close.handle = p_data->dev_status.handle; @@ -1577,17 +1914,6 @@ void btc_hh_cb_handler(btc_msg_t *msg) memcpy(param.rmv_dev.bd_addr, p_data->dev_info.bda, BD_ADDR_LEN); btc_hh_cb_to_app(ESP_HIDH_RMV_DEV_EVT, ¶m); break; - case BTA_HH_DATA_IND_EVT: - BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->int_data.status, p_data->int_data.handle); - if (p_data->int_data.status == BTA_HH_OK && p_data->int_data.p_data) { - param.data_ind.len = p_data->int_data.p_data->len; - param.data_ind.data = p_data->int_data.p_data->data + p_data->int_data.p_data->offset; - } - param.data_ind.handle = p_data->int_data.handle; - param.data_ind.status = p_data->int_data.status; - param.data_ind.proto_mode = proto_mode_change_to_upper_layer(p_data->int_data.proto_mode); - btc_hh_cb_to_app(ESP_HIDH_DATA_IND_EVT, ¶m); - break; case BTA_HH_API_ERR_EVT: break; default: diff --git a/components/bt/host/bluedroid/btc/profile/std/include/btc_hh.h b/components/bt/host/bluedroid/btc/profile/std/include/btc_hh.h index 827cd095c75..3117cc7a30f 100644 --- a/components/bt/host/bluedroid/btc/profile/std/include/btc_hh.h +++ b/components/bt/host/bluedroid/btc/profile/std/include/btc_hh.h @@ -22,11 +22,18 @@ #include #include "bta/bta_hh_api.h" +#include "bta/bta_hh_co.h" +#include "stack/bt_types.h" #include "btc/btc_task.h" #include "osi/alarm.h" +#include "osi/pkt_queue.h" +#include "osi/thread.h" +#include "osi/mutex.h" #include "esp_hidh_api.h" -#define BTC_HH_MAX_HID 8 +#if (defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE) + +#define BTC_HH_MAX_HID BTA_HH_MAX_DEVICE #define BTC_HH_MAX_ADDED_DEV 32 #define BTC_HH_MAX_KEYSTATES 3 @@ -67,15 +74,18 @@ typedef enum { } BTC_HH_STATUS; typedef struct { - esp_hidh_connection_state_t dev_status; + uint8_t dev_status; // see esp_hidh_connection_state_t uint8_t dev_handle; - BD_ADDR bd_addr; - uint16_t attr_mask; uint8_t sub_class; uint8_t app_id; - bool ready_for_data; - osi_alarm_t *vup_timer; bool local_vup; // Indicated locally initiated VUP + BD_ADDR bd_addr; + uint16_t attr_mask; + uint32_t drop_pkt_cnt; + osi_mutex_t lock; + struct pkt_queue *data_queue; + struct osi_event *data_ready; + osi_alarm_t *vup_timer; } btc_hh_device_t; /* Control block to maintain properties of devices */ @@ -187,4 +197,13 @@ bool btc_hh_add_added_dev(BD_ADDR bd_addr, uint16_t attr_mask); void btc_hh_get_profile_status(esp_hidh_profile_status_t *param); +btc_hh_device_t *btc_hh_find_connected_dev_by_handle(uint8_t handle); +bool btc_hh_data_enqueue_pkt(const tBTA_HH_DATA_PKT *pkt_meta); +bool btc_hh_data_enqueue_linked_pkt(pkt_linked_item_t *linked_pkt); +pkt_linked_item_t *btc_hh_data_dequeue_reusable_linked_pkt(uint8_t dev_handle); +void btc_hh_on_pkt_dropped(uint8_t dev_handle); +void btc_hh_reset_drop_pkt_cnt(uint8_t dev_handle); +bool btc_hh_data_path_init(uint8_t dev_handle); +#endif /* (defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE) */ + #endif /* BTC_HH_H */