mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
change(bt/bluedroid): Refactored HID host datapath
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -811,6 +830,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();
|
||||
@@ -862,6 +882,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();
|
||||
@@ -870,24 +891,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();
|
||||
@@ -1167,9 +1191,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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -1,8 +1,49 @@
|
||||
#include <string.h>
|
||||
#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) */
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -22,11 +22,18 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#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 */
|
||||
|
||||
Reference in New Issue
Block a user