Fork ESP-IDF's bluetooth component

i want better sbc encoding, and no cla will stop me
This commit is contained in:
jacqueline
2024-03-28 14:32:49 +11:00
parent 239e6d8950
commit ee29c25b29
1761 changed files with 737738 additions and 0 deletions
File diff suppressed because it is too large Load Diff
+477
View File
@@ -0,0 +1,477 @@
/******************************************************************************
*
* Copyright (C) 2005-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* This file contains the HID HOST API in the subsystem of BTA.
*
******************************************************************************/
#include "common/bt_target.h"
#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "bta/bta_hh_api.h"
#include "bta_hh_int.h"
#include "stack/l2c_api.h"
#include "bta/utl.h"
#include "osi/allocator.h"
/*****************************************************************************
** Constants
*****************************************************************************/
static const tBTA_SYS_REG bta_hh_reg = {
bta_hh_hdl_event,
BTA_HhDisable
};
/*******************************************************************************
**
** Function BTA_HhEnable
**
** Description Enable the HID host. This function must be called before
** any other functions in the HID host API are called. When the
** enable operation is complete the callback function will be
** called with BTA_HH_ENABLE_EVT.
**
**
** Returns void
**
*******************************************************************************/
void BTA_HhEnable(tBTA_SEC sec_mask, tBTA_HH_CBACK *p_cback)
{
tBTA_HH_API_ENABLE *p_buf;
/* register with BTA system manager */
bta_sys_register(BTA_ID_HH, &bta_hh_reg);
APPL_TRACE_API("%s sec_mask:0x%x p_cback:%p", __func__, sec_mask, p_cback);
p_buf = (tBTA_HH_API_ENABLE *)osi_malloc((UINT16)sizeof(tBTA_HH_API_ENABLE));
if (p_buf != NULL) {
memset(p_buf, 0, sizeof(tBTA_HH_API_ENABLE));
p_buf->hdr.event = BTA_HH_API_ENABLE_EVT;
p_buf->p_cback = p_cback;
p_buf->sec_mask = sec_mask;
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
**
** Function BTA_HhDisable
**
** Description Disable the HID host. If the server is currently
** connected, the connection will be closed.
**
** Returns void
**
*******************************************************************************/
void BTA_HhDisable(void)
{
BT_HDR *p_buf;
bta_sys_deregister(BTA_ID_HH);
if ((p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR))) != NULL) {
p_buf->event = BTA_HH_API_DISABLE_EVT;
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
**
** Function BTA_HhClose
**
** Description Disconnect a connection.
**
** Returns void
**
*******************************************************************************/
void BTA_HhClose(UINT8 dev_handle)
{
BT_HDR *p_buf;
if ((p_buf = (BT_HDR *)osi_malloc((UINT16)sizeof(BT_HDR))) != NULL) {
memset(p_buf, 0, sizeof(BT_HDR));
p_buf->event = BTA_HH_API_CLOSE_EVT;
p_buf->layer_specific = (UINT16) dev_handle;
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
**
** Function BTA_HhOpen
**
** Description Connect to a device of specified BD address in specified
** protocol mode and security level.
**
** Returns void
**
*******************************************************************************/
void BTA_HhOpen(BD_ADDR dev_bda, tBTA_HH_PROTO_MODE mode, tBTA_SEC sec_mask)
{
tBTA_HH_API_CONN *p_buf;
p_buf = (tBTA_HH_API_CONN *)osi_malloc((UINT16)sizeof(tBTA_HH_API_CONN));
if (p_buf != NULL) {
memset((void *)p_buf, 0, sizeof(tBTA_HH_API_CONN));
p_buf->hdr.event = BTA_HH_API_OPEN_EVT;
p_buf->hdr.layer_specific = BTA_HH_INVALID_HANDLE;
p_buf->sec_mask = sec_mask;
p_buf->mode = mode;
bdcpy(p_buf->bd_addr, dev_bda);
bta_sys_sendmsg((void *)p_buf);
} else {
APPL_TRACE_ERROR("No resource to send HID host Connect request.");
}
}
/*******************************************************************************
**
** Function bta_hh_snd_write_dev
**
*******************************************************************************/
static void bta_hh_snd_write_dev(UINT8 dev_handle, UINT8 t_type, UINT8 param,
UINT16 data, UINT8 rpt_id, BT_HDR *p_data)
{
tBTA_HH_CMD_DATA *p_buf;
UINT16 len = (UINT16) (sizeof(tBTA_HH_CMD_DATA) );
if ((p_buf = (tBTA_HH_CMD_DATA *)osi_malloc(len)) != NULL) {
memset(p_buf, 0, sizeof(tBTA_HH_CMD_DATA));
p_buf->hdr.event = BTA_HH_API_WRITE_DEV_EVT;
p_buf->hdr.layer_specific = (UINT16) dev_handle;
p_buf->t_type = t_type;
p_buf->data = data;
p_buf->param = param;
p_buf->p_data = p_data;
p_buf->rpt_id = rpt_id;
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
**
** Function BTA_HhSetReport
**
** Description send SET_REPORT to device.
**
** Parameter dev_handle: device handle
** r_type: report type, could be BTA_HH_RPTT_OUTPUT or
** BTA_HH_RPTT_FEATURE.
** Returns void
**
*******************************************************************************/
void BTA_HhSetReport(UINT8 dev_handle, tBTA_HH_RPT_TYPE r_type, BT_HDR *p_data)
{
bta_hh_snd_write_dev(dev_handle, HID_TRANS_SET_REPORT, r_type, 0, 0, p_data);
}
/*******************************************************************************
**
** Function BTA_HhGetReport
**
** Description Send a GET_REPORT to HID device.
**
** Returns void
**
*******************************************************************************/
void BTA_HhGetReport(UINT8 dev_handle, tBTA_HH_RPT_TYPE r_type, UINT8 rpt_id, UINT16 buf_size)
{
UINT8 param = (buf_size) ? (r_type | 0x08) : r_type;
bta_hh_snd_write_dev(dev_handle, HID_TRANS_GET_REPORT, param,
buf_size, rpt_id, NULL);
}
/*******************************************************************************
**
** Function BTA_HhSetProtoMode
**
** Description This function set the protocol mode at specified HID handle
**
** Returns void
**
*******************************************************************************/
void BTA_HhSetProtoMode(UINT8 dev_handle, tBTA_HH_PROTO_MODE p_type)
{
bta_hh_snd_write_dev(dev_handle, HID_TRANS_SET_PROTOCOL, (UINT8)p_type,
0, 0, NULL);
}
/*******************************************************************************
**
** Function BTA_HhGetProtoMode
**
** Description This function get protocol mode information.
**
** Returns void
**
*******************************************************************************/
void BTA_HhGetProtoMode(UINT8 dev_handle)
{
bta_hh_snd_write_dev(dev_handle, HID_TRANS_GET_PROTOCOL, 0, 0, 0, NULL);
}
/*******************************************************************************
**
** Function BTA_HhSetIdle
**
** Description send SET_IDLE to device.
**
** Returns void
**
*******************************************************************************/
void BTA_HhSetIdle(UINT8 dev_handle, UINT16 idle_rate)
{
bta_hh_snd_write_dev(dev_handle, HID_TRANS_SET_IDLE, 0, idle_rate, 0, NULL);
}
/*******************************************************************************
**
** Function BTA_HhGetIdle
**
** Description Send a GET_IDLE from HID device.
**
** Returns void
**
*******************************************************************************/
void BTA_HhGetIdle(UINT8 dev_handle)
{
bta_hh_snd_write_dev(dev_handle, HID_TRANS_GET_IDLE, 0, 0, 0, NULL);
}
/*******************************************************************************
**
** Function BTA_HhSendCtrl
**
** Description Send a control command to HID device.
**
** Returns void
**
*******************************************************************************/
void BTA_HhSendCtrl(UINT8 dev_handle, tBTA_HH_TRANS_CTRL_TYPE c_type)
{
bta_hh_snd_write_dev(dev_handle, HID_TRANS_CONTROL, (UINT8)c_type, 0, 0, NULL);
}
/*******************************************************************************
**
** Function BTA_HhSendData
**
** Description This function send DATA transaction to HID device.
**
** Parameter dev_handle: device handle
** dev_bda: remote device address
** p_data: data to be sent in the DATA transaction; or
** the data to be write into the Output Report of a LE HID
** device. The report is identified the report ID which is
** the value of the byte (UINT8 *)(p_buf + 1) + p_buf->offset.
** p_data->layer_specific needs to be set to the report type,
** it can be OUTPUT report, or FEATURE report.
**
** Returns void
**
*******************************************************************************/
void BTA_HhSendData(UINT8 dev_handle, BD_ADDR dev_bda, BT_HDR *p_data)
{
UNUSED(dev_bda);
#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
if (p_data->layer_specific != BTA_HH_RPTT_OUTPUT) {
APPL_TRACE_ERROR("ERROR! Wrong report type! Write Command only valid for output report!");
return;
}
#endif
bta_hh_snd_write_dev(dev_handle, HID_TRANS_DATA, (UINT8)p_data->layer_specific, 0, 0, p_data);
}
/*******************************************************************************
**
** Function BTA_HhGetDscpInfo
**
** Description Get HID device report descriptor
**
** Returns void
**
*******************************************************************************/
void BTA_HhGetDscpInfo(UINT8 dev_handle)
{
BT_HDR *p_buf;
if ((p_buf = (BT_HDR *)osi_malloc((UINT16)sizeof(BT_HDR))) != NULL) {
memset(p_buf, 0, sizeof(BT_HDR));
p_buf->event = BTA_HH_API_GET_DSCP_EVT;
p_buf->layer_specific = (UINT16) dev_handle;
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
**
** Function BTA_HhAddDev
**
** Description Add a virtually cabled device into HID-Host device list
** to manage and assign a device handle for future API call,
** host applciation call this API at start-up to initialize its
** virtually cabled devices.
**
** Returns void
**
*******************************************************************************/
void BTA_HhAddDev(BD_ADDR bda, tBTA_HH_ATTR_MASK attr_mask, UINT8 sub_class,
UINT8 app_id, tBTA_HH_DEV_DSCP_INFO dscp_info)
{
tBTA_HH_MAINT_DEV *p_buf;
UINT16 len = sizeof(tBTA_HH_MAINT_DEV) + dscp_info.descriptor.dl_len;
p_buf = (tBTA_HH_MAINT_DEV *)osi_malloc(len);
if (p_buf != NULL) {
memset(p_buf, 0, sizeof(tBTA_HH_MAINT_DEV));
p_buf->hdr.event = BTA_HH_API_MAINT_DEV_EVT;
p_buf->sub_event = BTA_HH_ADD_DEV_EVT;
p_buf->hdr.layer_specific = BTA_HH_INVALID_HANDLE;
p_buf->attr_mask = (UINT16) attr_mask;
p_buf->sub_class = sub_class;
p_buf->app_id = app_id;
bdcpy(p_buf->bda, bda);
memcpy(&p_buf->dscp_info, &dscp_info, sizeof(tBTA_HH_DEV_DSCP_INFO));
if ( dscp_info.descriptor.dl_len != 0 && dscp_info.descriptor.dsc_list) {
p_buf->dscp_info.descriptor.dl_len = dscp_info.descriptor.dl_len;
p_buf->dscp_info.descriptor.dsc_list = (UINT8 *)(p_buf + 1);
memcpy(p_buf->dscp_info.descriptor.dsc_list, dscp_info.descriptor.dsc_list, dscp_info.descriptor.dl_len);
} else {
p_buf->dscp_info.descriptor.dsc_list = NULL;
p_buf->dscp_info.descriptor.dl_len = 0;
}
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
**
** Function BTA_HhRemoveDev
**
** Description Remove a device from the HID host devices list.
**
** Returns void
**
*******************************************************************************/
void BTA_HhRemoveDev(UINT8 dev_handle )
{
tBTA_HH_MAINT_DEV *p_buf;
p_buf = (tBTA_HH_MAINT_DEV *)osi_malloc((UINT16)sizeof(tBTA_HH_MAINT_DEV));
if (p_buf != NULL) {
memset(p_buf, 0, sizeof(tBTA_HH_MAINT_DEV));
p_buf->hdr.event = BTA_HH_API_MAINT_DEV_EVT;
p_buf->sub_event = BTA_HH_RMV_DEV_EVT;
p_buf->hdr.layer_specific = (UINT16) dev_handle;
bta_sys_sendmsg(p_buf);
}
}
#if BTA_HH_LE_INCLUDED == TRUE
/*******************************************************************************
**
** Function BTA_HhUpdateLeScanParam
**
** Description Update the scan paramteters if connected to a LE hid device as
** report host.
**
** Returns void
**
*******************************************************************************/
void BTA_HhUpdateLeScanParam(UINT8 dev_handle, UINT16 scan_int, UINT16 scan_win)
{
tBTA_HH_SCPP_UPDATE *p_buf;
p_buf = (tBTA_HH_SCPP_UPDATE *)osi_malloc((UINT16)sizeof(tBTA_HH_SCPP_UPDATE));
if (p_buf != NULL) {
memset(p_buf, 0, sizeof(tBTA_HH_SCPP_UPDATE));
p_buf->hdr.event = BTA_HH_API_SCPP_UPDATE_EVT;
p_buf->hdr.layer_specific = (UINT16) dev_handle;
p_buf->scan_int = scan_int;
p_buf->scan_win = scan_win;
bta_sys_sendmsg(p_buf);
}
}
#endif
/*******************************************************************************/
/* Utility Function */
/*******************************************************************************/
/*******************************************************************************
**
** Function BTA_HhParseBootRpt
**
** Description This utility function parse a boot mode report.
** For keyboard report, report data will carry the keycode max
** up to 6 key press in one report. Application need to convert
** the keycode into keypress character according to keyboard
** language.
**
** Returns void
**
*******************************************************************************/
void BTA_HhParseBootRpt(tBTA_HH_BOOT_RPT *p_data, UINT8 *p_report,
UINT16 report_len)
{
p_data->dev_type = BTA_HH_DEVT_UNKNOWN;
if (p_report) {
/* first byte is report ID */
switch (p_report[0]) {
case BTA_HH_KEYBD_RPT_ID: /* key board report ID */
p_data->dev_type = p_report[0];
bta_hh_parse_keybd_rpt(p_data, p_report + 1, (UINT16)(report_len - 1));
break;
case BTA_HH_MOUSE_RPT_ID: /* mouse report ID */
p_data->dev_type = p_report[0];
bta_hh_parse_mice_rpt(p_data, p_report + 1, (UINT16)(report_len - 1));
break;
default:
APPL_TRACE_DEBUG("Unknown boot report: %d", p_report[0]);;
break;
}
}
return;
}
#endif /* BTA_HH_INCLUDED */
+64
View File
@@ -0,0 +1,64 @@
/******************************************************************************
*
* Copyright (C) 2005-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* This file contains compile-time configurable constants for the BTA Hid
* Host.
*
******************************************************************************/
#include "common/bt_target.h"
#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
#include "bta/bta_hh_api.h"
/* max number of device types supported by BTA */
#define BTA_HH_MAX_DEVT_SPT 9
/* size of database for service discovery */
#ifndef BTA_HH_DISC_BUF_SIZE
#define BTA_HH_DISC_BUF_SIZE BT_DEFAULT_BUFFER_SIZE
#endif
/* The type of devices supported by BTA HH and corresponding application ID */
tBTA_HH_SPT_TOD p_devt_list[BTA_HH_MAX_DEVT_SPT] = {
{BTA_HH_DEVT_MIC, BTA_HH_APP_ID_MI},
{BTA_HH_DEVT_KBD, BTA_HH_APP_ID_KB},
{BTA_HH_DEVT_KBD | BTA_HH_DEVT_MIC, BTA_HH_APP_ID_KB},
{BTA_HH_DEVT_RMC, BTA_HH_APP_ID_RMC},
{BTA_HH_DEVT_RMC | BTA_HH_DEVT_KBD, BTA_HH_APP_ID_RMC},
{BTA_HH_DEVT_MIC | BTA_HH_DEVT_DGT, BTA_HH_APP_ID_MI},
{BTA_HH_DEVT_JOS, BTA_HH_APP_ID_JOY},
{BTA_HH_DEVT_GPD, BTA_HH_APP_ID_GPAD},
{BTA_HH_DEVT_UNKNOWN, BTA_HH_APP_ID_3DSG}
};
const tBTA_HH_CFG bta_hh_cfg = {
BTA_HH_MAX_DEVT_SPT, /* number of supported type of devices */
p_devt_list, /* ToD & AppID list */
BTA_HH_DISC_BUF_SIZE /* HH SDP discovery database size */
};
tBTA_HH_CFG *p_bta_hh_cfg = (tBTA_HH_CFG *) &bta_hh_cfg;
#endif ///defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
File diff suppressed because it is too large Load Diff
+568
View File
@@ -0,0 +1,568 @@
/******************************************************************************
*
* Copyright (C) 2005-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* This file contains the HID host main functions and state machine.
*
******************************************************************************/
#include "common/bt_target.h"
#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
#include <string.h>
#include "bta/bta_hh_api.h"
#include "bta_hh_int.h"
#include "osi/allocator.h"
/*****************************************************************************
** Constants and types
*****************************************************************************/
/* state machine action enumeration list */
enum {
BTA_HH_API_DISC_ACT, /* HID host process API close action */
BTA_HH_OPEN_ACT, /* HID host process BTA_HH_EVT_OPEN */
BTA_HH_CLOSE_ACT, /* HID host process BTA_HH_EVT_CLOSE */
BTA_HH_DATA_ACT, /* HID host receive data report */
BTA_HH_CTRL_DAT_ACT,
BTA_HH_HANDSK_ACT,
BTA_HH_START_SDP, /* HID host inquery */
BTA_HH_SDP_CMPL,
BTA_HH_WRITE_DEV_ACT,
BTA_HH_GET_DSCP_ACT,
BTA_HH_MAINT_DEV_ACT,
BTA_HH_OPEN_CMPL_ACT,
BTA_HH_OPEN_FAILURE,
#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
BTA_HH_GATT_CLOSE,
BTA_HH_LE_OPEN_FAIL,
BTA_HH_GATT_OPEN,
BTA_HH_W4_LE_READ_CHAR,
BTA_HH_LE_READ_CHAR,
BTA_HH_W4_LE_READ_DESCR,
BTA_HH_LE_READ_DESCR,
BTA_HH_W4_LE_WRITE,
BTA_HH_LE_WRITE,
BTA_HH_WRITE_DESCR,
BTA_HH_START_SEC,
BTA_HH_SEC_CMPL,
BTA_HH_LE_UPDATE_SCPP,
BTA_HH_GATT_ENC_CMPL,
#endif
BTA_HH_NUM_ACTIONS
};
#define BTA_HH_IGNORE BTA_HH_NUM_ACTIONS
/* type for action functions */
typedef void (*tBTA_HH_ACTION)(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
/* action functions */
const tBTA_HH_ACTION bta_hh_action[] = {
bta_hh_api_disc_act,
bta_hh_open_act,
bta_hh_close_act,
bta_hh_data_act,
bta_hh_ctrl_dat_act,
bta_hh_handsk_act,
bta_hh_start_sdp,
bta_hh_sdp_cmpl,
bta_hh_write_dev_act,
bta_hh_get_dscp_act,
bta_hh_maint_dev_act,
bta_hh_open_cmpl_act,
bta_hh_open_failure
#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
, bta_hh_gatt_close
, bta_hh_le_open_fail
, bta_hh_gatt_open
, bta_hh_w4_le_read_char_cmpl
, bta_hh_le_read_char_cmpl
, bta_hh_w4_le_read_descr_cmpl
, bta_hh_le_read_descr_cmpl
, bta_hh_w4_le_write_cmpl
, bta_hh_le_write_cmpl
, bta_hh_le_write_char_descr_cmpl
, bta_hh_start_security
, bta_hh_security_cmpl
, bta_hh_le_update_scpp
, bta_hh_le_notify_enc_cmpl
#endif
};
/* state table information */
#define BTA_HH_ACTION 0 /* position of action */
#define BTA_HH_NEXT_STATE 1 /* position of next state */
#define BTA_HH_NUM_COLS 2 /* number of columns */
/* state table for idle state */
const UINT8 bta_hh_st_idle[][BTA_HH_NUM_COLS] = {
/* Event Action Next state */
/* BTA_HH_API_OPEN_EVT */ {BTA_HH_START_SDP, BTA_HH_W4_CONN_ST },
/* BTA_HH_API_CLOSE_EVT */ {BTA_HH_IGNORE, BTA_HH_IDLE_ST },
/* BTA_HH_INT_OPEN_EVT */ {BTA_HH_OPEN_ACT, BTA_HH_W4_CONN_ST },
/* BTA_HH_INT_CLOSE_EVT */ {BTA_HH_CLOSE_ACT, BTA_HH_IDLE_ST },
/* BTA_HH_INT_DATA_EVT */ {BTA_HH_IGNORE, BTA_HH_IDLE_ST },
/* BTA_HH_INT_CTRL_DATA */ {BTA_HH_IGNORE, BTA_HH_IDLE_ST },
/* BTA_HH_INT_HANDSK_EVT */ {BTA_HH_IGNORE, BTA_HH_IDLE_ST },
/* BTA_HH_SDP_CMPL_EVT */ {BTA_HH_IGNORE, BTA_HH_IDLE_ST },
/* BTA_HH_API_WRITE_DEV_EVT */ {BTA_HH_IGNORE, BTA_HH_IDLE_ST },
/* BTA_HH_API_GET_DSCP_EVT */ {BTA_HH_IGNORE, BTA_HH_IDLE_ST },
/* BTA_HH_API_MAINT_DEV_EVT */ {BTA_HH_MAINT_DEV_ACT, BTA_HH_IDLE_ST },
/* BTA_HH_OPEN_CMPL_EVT */ {BTA_HH_OPEN_CMPL_ACT, BTA_HH_CONN_ST }
#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
/* BTA_HH_GATT_CLOSE_EVT */ , {BTA_HH_IGNORE, BTA_HH_IDLE_ST }
/* BTA_HH_GATT_OPEN_EVT */ , {BTA_HH_GATT_OPEN, BTA_HH_W4_CONN_ST }
/* BTA_HH_START_ENC_EVT */ , {BTA_HH_IGNORE, BTA_HH_IDLE_ST }
/* BTA_HH_ENC_CMPL_EVT */ , {BTA_HH_IGNORE, BTA_HH_IDLE_ST }
/* READ_CHAR_CMPL_EVT */ , {BTA_HH_IGNORE, BTA_HH_IDLE_ST }
/* BTA_HH_GATT_WRITE_CMPL_EVT*/ , {BTA_HH_IGNORE, BTA_HH_IDLE_ST }
/* READ_DESCR_CMPL_EVT */ , {BTA_HH_IGNORE, BTA_HH_IDLE_ST }
/* WRITE_DESCR_CMPL_EVT */ , {BTA_HH_IGNORE, BTA_HH_IDLE_ST }
/* SCPP_UPDATE_EVT */ , {BTA_HH_IGNORE, BTA_HH_IDLE_ST }
/* BTA_HH_GATT_ENC_CMPL_EVT */ , {BTA_HH_IGNORE, BTA_HH_IDLE_ST }
#endif
};
const UINT8 bta_hh_st_w4_conn[][BTA_HH_NUM_COLS] = {
/* Event Action Next state */
/* BTA_HH_API_OPEN_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_CONN_ST },
/* BTA_HH_API_CLOSE_EVT */ {BTA_HH_IGNORE, BTA_HH_IDLE_ST },
/* BTA_HH_INT_OPEN_EVT */ {BTA_HH_OPEN_ACT, BTA_HH_W4_CONN_ST },
/* BTA_HH_INT_CLOSE_EVT */ {BTA_HH_OPEN_FAILURE, BTA_HH_IDLE_ST },
/* BTA_HH_INT_DATA_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_CONN_ST },
/* BTA_HH_INT_CTRL_DATA */ {BTA_HH_IGNORE, BTA_HH_W4_CONN_ST },
/* BTA_HH_INT_HANDSK_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_CONN_ST },
/* BTA_HH_SDP_CMPL_EVT */ {BTA_HH_SDP_CMPL, BTA_HH_W4_CONN_ST },
/* BTA_HH_API_WRITE_DEV_EVT */ {BTA_HH_WRITE_DEV_ACT, BTA_HH_W4_CONN_ST },
/* BTA_HH_API_GET_DSCP_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_CONN_ST },
/* BTA_HH_API_MAINT_DEV_EVT */ {BTA_HH_MAINT_DEV_ACT, BTA_HH_IDLE_ST },
/* BTA_HH_OPEN_CMPL_EVT */ {BTA_HH_OPEN_CMPL_ACT, BTA_HH_CONN_ST }
#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
/* BTA_HH_GATT_CLOSE_EVT */ , {BTA_HH_LE_OPEN_FAIL, BTA_HH_IDLE_ST }
/* BTA_HH_GATT_OPEN_EVT */ , {BTA_HH_GATT_OPEN, BTA_HH_W4_CONN_ST }
/* BTA_HH_START_ENC_EVT */ , {BTA_HH_START_SEC, BTA_HH_W4_SEC }
/* BTA_HH_ENC_CMPL_EVT */ , {BTA_HH_IGNORE, BTA_HH_W4_CONN_ST }
/* READ_CHAR_CMPL_EVT */ , {BTA_HH_W4_LE_READ_CHAR, BTA_HH_W4_CONN_ST }
/* BTA_HH_GATT_WRITE_CMPL_EVT*/ , {BTA_HH_W4_LE_WRITE, BTA_HH_W4_CONN_ST }
/* READ_DESCR_CMPL_EVT */ , {BTA_HH_W4_LE_READ_DESCR, BTA_HH_W4_CONN_ST }
/* WRITE_DESCR_CMPL_EVT */ , {BTA_HH_WRITE_DESCR, BTA_HH_W4_CONN_ST }
/* SCPP_UPDATE_EVT */ , {BTA_HH_IGNORE, BTA_HH_W4_CONN_ST }
/* BTA_HH_GATT_ENC_CMPL_EVT */ , {BTA_HH_IGNORE, BTA_HH_W4_CONN_ST }
#endif
};
const UINT8 bta_hh_st_connected[][BTA_HH_NUM_COLS] = {
/* Event Action Next state */
/* BTA_HH_API_OPEN_EVT */ {BTA_HH_IGNORE, BTA_HH_CONN_ST },
/* BTA_HH_API_CLOSE_EVT */ {BTA_HH_API_DISC_ACT, BTA_HH_CONN_ST },
/* BTA_HH_INT_OPEN_EVT */ {BTA_HH_OPEN_ACT, BTA_HH_CONN_ST },
/* BTA_HH_INT_CLOSE_EVT */ {BTA_HH_CLOSE_ACT, BTA_HH_IDLE_ST },
/* BTA_HH_INT_DATA_EVT */ {BTA_HH_DATA_ACT, BTA_HH_CONN_ST },
/* BTA_HH_INT_CTRL_DATA */ {BTA_HH_CTRL_DAT_ACT, BTA_HH_CONN_ST },
/* BTA_HH_INT_HANDSK_EVT */ {BTA_HH_HANDSK_ACT, BTA_HH_CONN_ST },
/* BTA_HH_SDP_CMPL_EVT */ {BTA_HH_IGNORE, BTA_HH_CONN_ST },
/* BTA_HH_API_WRITE_DEV_EVT */ {BTA_HH_WRITE_DEV_ACT, BTA_HH_CONN_ST },
/* BTA_HH_API_GET_DSCP_EVT */ {BTA_HH_GET_DSCP_ACT, BTA_HH_CONN_ST },
/* BTA_HH_API_MAINT_DEV_EVT */ {BTA_HH_MAINT_DEV_ACT, BTA_HH_CONN_ST },
/* BTA_HH_OPEN_CMPL_EVT */ {BTA_HH_IGNORE, BTA_HH_CONN_ST }
#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
/* BTA_HH_GATT_CLOSE_EVT */ , {BTA_HH_GATT_CLOSE, BTA_HH_IDLE_ST }
/* BTA_HH_GATT_OPEN_EVT */ , {BTA_HH_IGNORE, BTA_HH_CONN_ST }
/* BTA_HH_START_ENC_EVT */ , {BTA_HH_IGNORE, BTA_HH_CONN_ST }
/* BTA_HH_ENC_CMPL_EVT */ , {BTA_HH_IGNORE, BTA_HH_CONN_ST }
/* READ_CHAR_CMPL_EVT */ , {BTA_HH_LE_READ_CHAR, BTA_HH_CONN_ST }
/* WRITE_CHAR_CMPL_EVT*/ , {BTA_HH_LE_WRITE, BTA_HH_CONN_ST }
/* READ_DESCR_CMPL_EVT */ , {BTA_HH_LE_READ_DESCR, BTA_HH_CONN_ST } /* do not currently read any descr when connection up */
/* WRITE_DESCR_CMPL_EVT */ , {BTA_HH_WRITE_DESCR, BTA_HH_CONN_ST } /* do not currently write any descr when connection up */
/* SCPP_UPDATE_EVT */ , {BTA_HH_LE_UPDATE_SCPP, BTA_HH_CONN_ST }
/* BTA_HH_GATT_ENC_CMPL_EVT */ , {BTA_HH_IGNORE, BTA_HH_CONN_ST }
#endif
};
#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
const UINT8 bta_hh_st_w4_sec[][BTA_HH_NUM_COLS] = {
/* Event Action Next state */
/* BTA_HH_API_OPEN_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_SEC },
/* BTA_HH_API_CLOSE_EVT */ {BTA_HH_API_DISC_ACT, BTA_HH_W4_SEC },
/* BTA_HH_INT_OPEN_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_SEC },
/* BTA_HH_INT_CLOSE_EVT */ {BTA_HH_OPEN_FAILURE, BTA_HH_IDLE_ST },
/* BTA_HH_INT_DATA_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_SEC },
/* BTA_HH_INT_CTRL_DATA */ {BTA_HH_IGNORE, BTA_HH_W4_SEC },
/* BTA_HH_INT_HANDSK_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_SEC },
/* BTA_HH_SDP_CMPL_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_SEC },
/* BTA_HH_API_WRITE_DEV_EVT */ {BTA_HH_IGNORE , BTA_HH_W4_SEC },
/* BTA_HH_API_GET_DSCP_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_SEC },
/* BTA_HH_API_MAINT_DEV_EVT */ {BTA_HH_MAINT_DEV_ACT, BTA_HH_W4_SEC },
/* BTA_HH_OPEN_CMPL_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_SEC },
/* BTA_HH_GATT_CLOSE_EVT */ {BTA_HH_LE_OPEN_FAIL, BTA_HH_IDLE_ST },
/* BTA_HH_GATT_OPEN_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_SEC },
/* BTA_HH_START_ENC_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_SEC },
/* BTA_HH_ENC_CMPL_EVT */ {BTA_HH_SEC_CMPL, BTA_HH_W4_CONN_ST },
/* READ_CHAR_CMPL_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_SEC },
/* BTA_HH_GATT_WRITE_CMPL_EVT*/ {BTA_HH_IGNORE, BTA_HH_W4_SEC },
/* READ_DESCR_CMPL_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_SEC },
/* WRITE_DESCR_CMPL_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_SEC }
/* SCPP_UPDATE_EVT */ , {BTA_HH_IGNORE, BTA_HH_W4_SEC }
/* BTA_HH_GATT_ENC_CMPL_EVT */ , {BTA_HH_GATT_ENC_CMPL, BTA_HH_W4_SEC }
};
#endif
/* type for state table */
typedef const UINT8 (*tBTA_HH_ST_TBL)[BTA_HH_NUM_COLS];
/* state table */
const tBTA_HH_ST_TBL bta_hh_st_tbl[] = {
bta_hh_st_idle,
bta_hh_st_w4_conn,
bta_hh_st_connected
#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
, bta_hh_st_w4_sec
#endif
};
/*****************************************************************************
** Global data
*****************************************************************************/
#if BTA_DYNAMIC_MEMORY == FALSE
tBTA_HH_CB bta_hh_cb;
#else
tBTA_HH_CB *bta_hh_cb_ptr;
#endif
/*****************************************************************************
** Static functions
*****************************************************************************/
#if BTA_HH_DEBUG == TRUE
static char *bta_hh_evt_code(tBTA_HH_INT_EVT evt_code);
static char *bta_hh_state_code(tBTA_HH_STATE state_code);
#endif
/*******************************************************************************
**
** Function bta_hh_sm_execute
**
** Description State machine event handling function for HID Host
**
**
** Returns void
**
*******************************************************************************/
void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16 event, tBTA_HH_DATA *p_data)
{
tBTA_HH_ST_TBL state_table;
UINT8 action;
tBTA_HH cback_data;
tBTA_HH_EVT cback_event = 0;
#if BTA_HH_DEBUG == TRUE
tBTA_HH_STATE in_state ;
UINT16 debug_event = event;
#endif
memset(&cback_data, 0, sizeof(tBTA_HH));
/* handle exception, no valid control block was found */
if (!p_cb) {
/* BTA HH enabled already? otherwise ignore the event although it's bad*/
if (bta_hh_cb.p_cback != NULL) {
switch (event) {
/* no control block available for new connection */
case BTA_HH_API_OPEN_EVT:
cback_event = BTA_HH_OPEN_EVT;
/* build cback data */
bdcpy(cback_data.conn.bda, ((tBTA_HH_API_CONN *)p_data)->bd_addr);
cback_data.conn.status = BTA_HH_ERR_DB_FULL;
cback_data.conn.handle = BTA_HH_INVALID_HANDLE;
/* check if host initiate the connection*/
cback_data.conn.is_orig = !p_cb->incoming_conn;
break;
/* DB full, BTA_HhAddDev */
case BTA_HH_API_MAINT_DEV_EVT:
cback_event = p_data->api_maintdev.sub_event;
if (p_data->api_maintdev.sub_event == BTA_HH_ADD_DEV_EVT) {
bdcpy(cback_data.dev_info.bda, p_data->api_maintdev.bda);
cback_data.dev_info.status = BTA_HH_ERR_DB_FULL;
cback_data.dev_info.handle = BTA_HH_INVALID_HANDLE;
} else {
cback_data.dev_info.status = BTA_HH_ERR_HDL;
cback_data.dev_info.handle = (UINT8)p_data->api_maintdev.hdr.layer_specific;
}
break;
case BTA_HH_API_WRITE_DEV_EVT:
cback_event = (p_data->api_sndcmd.t_type - BTA_HH_FST_BTE_TRANS_EVT) +
BTA_HH_FST_TRANS_CB_EVT;
if (p_data->api_sndcmd.p_data != NULL) {
osi_free(p_data->api_sndcmd.p_data);
}
if (p_data->api_sndcmd.t_type == HID_TRANS_SET_PROTOCOL ||
p_data->api_sndcmd.t_type == HID_TRANS_SET_REPORT ||
p_data->api_sndcmd.t_type == HID_TRANS_SET_IDLE) {
cback_data.dev_status.status = BTA_HH_ERR_HDL;
cback_data.dev_status.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific;
} else if (p_data->api_sndcmd.t_type != HID_TRANS_DATA &&
p_data->api_sndcmd.t_type != HID_TRANS_CONTROL) {
cback_data.hs_data.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific;
cback_data.hs_data.status = BTA_HH_ERR_HDL;
/* hs_data.rsp_data will be all zero, which is not valid value */
} else if (p_data->api_sndcmd.t_type == HID_TRANS_CONTROL &&
p_data->api_sndcmd.param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG) {
cback_data.status = BTA_HH_ERR_HDL;
cback_event = BTA_HH_VC_UNPLUG_EVT;
} else {
cback_event = 0;
}
break;
case BTA_HH_API_CLOSE_EVT:
cback_event = BTA_HH_CLOSE_EVT;
cback_data.dev_status.status = BTA_HH_ERR_HDL;
cback_data.dev_status.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific;
break;
default:
/* invalid handle, call bad API event */
APPL_TRACE_ERROR("wrong device handle: [%d], event:%d", p_data->hdr.layer_specific, event - BTA_HH_API_OPEN_EVT);
/* Free the callback buffer now */
if (p_data != NULL && p_data->hid_cback.p_data != NULL) {
osi_free(p_data->hid_cback.p_data);
p_data->hid_cback.p_data = NULL;
}
break;
}
if (cback_event) {
(* bta_hh_cb.p_cback)(cback_event, &cback_data);
}
}
}
/* corresponding CB is found, go to state machine */
else {
#if BTA_HH_DEBUG == TRUE
in_state = p_cb->state;
APPL_TRACE_EVENT("bta_hh_sm_execute: State 0x%02x [%s], Event [%s]",
in_state, bta_hh_state_code(in_state),
bta_hh_evt_code(debug_event));
#endif
if ((p_cb->state == BTA_HH_NULL_ST) || (p_cb->state >= BTA_HH_INVALID_ST)) {
APPL_TRACE_ERROR("bta_hh_sm_execute: Invalid state State = 0x%x, Event = %d",
p_cb->state, event);
return;
}
state_table = bta_hh_st_tbl[p_cb->state - 1];
event &= 0xff;
p_cb->state = state_table[event][BTA_HH_NEXT_STATE] ;
if ((action = state_table[event][BTA_HH_ACTION]) != BTA_HH_IGNORE) {
(*bta_hh_action[action])(p_cb, p_data);
}
#if BTA_HH_DEBUG == TRUE
if (in_state != p_cb->state) {
APPL_TRACE_DEBUG("HH State Change: [%s] -> [%s] after Event [%s]",
bta_hh_state_code(in_state),
bta_hh_state_code(p_cb->state),
bta_hh_evt_code(debug_event));
}
#endif
}
return;
}
/*******************************************************************************
**
** Function bta_hh_hdl_event
**
** Description HID host main event handling function.
**
**
** Returns void
**
*******************************************************************************/
BOOLEAN bta_hh_hdl_event(BT_HDR *p_msg)
{
UINT8 index = BTA_HH_IDX_INVALID;
tBTA_HH_DEV_CB *p_cb = NULL;
switch (p_msg->event) {
case BTA_HH_API_ENABLE_EVT:
bta_hh_api_enable((tBTA_HH_DATA *) p_msg);
break;
case BTA_HH_API_DISABLE_EVT:
bta_hh_api_disable();
break;
case BTA_HH_DISC_CMPL_EVT: /* disable complete */
bta_hh_disc_cmpl();
break;
default:
/* all events processed in state machine need to find corresponding
CB before proceed */
if (p_msg->event == BTA_HH_API_OPEN_EVT) {
index = bta_hh_find_cb(((tBTA_HH_API_CONN *)p_msg)->bd_addr);
} else if (p_msg->event == BTA_HH_API_MAINT_DEV_EVT) {
/* if add device */
if (((tBTA_HH_MAINT_DEV *)p_msg)->sub_event == BTA_HH_ADD_DEV_EVT) {
index = bta_hh_find_cb(((tBTA_HH_MAINT_DEV *)p_msg)->bda);
} else { /* else remove device by handle */
index = bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific);
// btla-specific ++
/* If BT disable is done while the HID device is connected and Link_Key uses unauthenticated combination
* then we can get into a situation where remove_bonding is called with the index set to 0 (without getting
* cleaned up). Only when VIRTUAL_UNPLUG is called do we cleanup the index and make it MAX_KNOWN.
* So if REMOVE_DEVICE is called and in_use is FALSE then we should treat this as a NULL p_cb. Hence we
* force the index to be IDX_INVALID
*/
if ((index != BTA_HH_IDX_INVALID) &&
(bta_hh_cb.kdev[index].in_use == FALSE)) {
index = BTA_HH_IDX_INVALID;
}
// btla-specific --
}
} else if (p_msg->event == BTA_HH_INT_OPEN_EVT) {
index = bta_hh_find_cb(((tBTA_HH_CBACK_DATA *)p_msg)->addr);
uint8_t hdl = BTA_HH_IDX_INVALID;
if (HID_HostGetDev(((tBTA_HH_CBACK_DATA *)p_msg)->addr, &hdl) == HID_SUCCESS && hdl != BTA_HH_IDX_INVALID) {
bta_hh_cb.cb_index[hdl] = bta_hh_cb.kdev[index].index;
}
} else {
index = bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific);
}
if (index != BTA_HH_IDX_INVALID) {
p_cb = &bta_hh_cb.kdev[index];
}
#if BTA_HH_DEBUG
APPL_TRACE_DEBUG("bta_hh_hdl_event:: handle = %d dev_cb[%d] ", p_msg->layer_specific, index);
#endif
bta_hh_sm_execute(p_cb, p_msg->event, (tBTA_HH_DATA *) p_msg);
}
return (TRUE);
}
/*****************************************************************************
** Debug Functions
*****************************************************************************/
#if BTA_HH_DEBUG
/*******************************************************************************
**
** Function bta_hh_evt_code
**
** Description
**
** Returns void
**
*******************************************************************************/
static char *bta_hh_evt_code(tBTA_HH_INT_EVT evt_code)
{
switch (evt_code) {
case BTA_HH_API_DISABLE_EVT:
return "BTA_HH_API_DISABLE_EVT";
case BTA_HH_API_ENABLE_EVT:
return "BTA_HH_API_ENABLE_EVT";
case BTA_HH_API_OPEN_EVT:
return "BTA_HH_API_OPEN_EVT";
case BTA_HH_API_CLOSE_EVT:
return "BTA_HH_API_CLOSE_EVT";
case BTA_HH_INT_OPEN_EVT:
return "BTA_HH_INT_OPEN_EVT";
case BTA_HH_INT_CLOSE_EVT:
return "BTA_HH_INT_CLOSE_EVT";
case BTA_HH_INT_HANDSK_EVT:
return "BTA_HH_INT_HANDSK_EVT";
case BTA_HH_INT_DATA_EVT:
return "BTA_HH_INT_DATA_EVT";
case BTA_HH_INT_CTRL_DATA:
return "BTA_HH_INT_CTRL_DATA";
case BTA_HH_API_WRITE_DEV_EVT:
return "BTA_HH_API_WRITE_DEV_EVT";
case BTA_HH_SDP_CMPL_EVT:
return "BTA_HH_SDP_CMPL_EVT";
case BTA_HH_DISC_CMPL_EVT:
return "BTA_HH_DISC_CMPL_EVT";
case BTA_HH_API_MAINT_DEV_EVT:
return "BTA_HH_API_MAINT_DEV_EVT";
case BTA_HH_API_GET_DSCP_EVT:
return "BTA_HH_API_GET_DSCP_EVT";
case BTA_HH_OPEN_CMPL_EVT:
return "BTA_HH_OPEN_CMPL_EVT";
#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
case BTA_HH_GATT_CLOSE_EVT:
return "BTA_HH_GATT_CLOSE_EVT";
case BTA_HH_GATT_OPEN_EVT:
return "BTA_HH_GATT_OPEN_EVT";
case BTA_HH_START_ENC_EVT:
return "BTA_HH_START_ENC_EVT";
case BTA_HH_ENC_CMPL_EVT:
return "BTA_HH_ENC_CMPL_EVT";
case BTA_HH_GATT_READ_CHAR_CMPL_EVT:
return "BTA_HH_GATT_READ_CHAR_CMPL_EVT";
case BTA_HH_GATT_WRITE_CHAR_CMPL_EVT:
return "BTA_HH_GATT_WRITE_CHAR_CMPL_EVT";
case BTA_HH_GATT_READ_DESCR_CMPL_EVT:
return "BTA_HH_GATT_READ_DESCR_CMPL_EVT";
case BTA_HH_GATT_WRITE_DESCR_CMPL_EVT:
return "BTA_HH_GATT_WRITE_DESCR_CMPL_EVT";
#endif
default:
return "unknown HID Host event code";
}
}
/*******************************************************************************
**
** Function bta_hh_state_code
**
** Description get string representation of HID host state code.
**
** Returns void
**
*******************************************************************************/
static char *bta_hh_state_code(tBTA_HH_STATE state_code)
{
switch (state_code) {
case BTA_HH_NULL_ST:
return"BTA_HH_NULL_ST";
case BTA_HH_IDLE_ST:
return "BTA_HH_IDLE_ST";
case BTA_HH_W4_CONN_ST:
return "BTA_HH_W4_CONN_ST";
case BTA_HH_CONN_ST:
return "BTA_HH_CONN_ST";
#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
case BTA_HH_W4_SEC:
return "BTA_HH_W4_SEC";
#endif
default:
return "unknown HID Host state";
}
}
#endif /* Debug Functions */
#endif /* BTA_HH_INCLUDED */
+531
View File
@@ -0,0 +1,531 @@
/******************************************************************************
*
* Copyright (C) 2005-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
#include <string.h>
#include "common/bt_target.h"
#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
#include "osi/allocator.h"
#include "bta_hh_int.h"
/* if SSR max latency is not defined by remote device, set the default value
as half of the link supervision timeout */
#define BTA_HH_GET_DEF_SSR_MAX_LAT(x) ((x)>> 1)
/*****************************************************************************
** Constants
*****************************************************************************/
#define BTA_HH_KB_CTRL_MASK 0x11
#define BTA_HH_KB_SHIFT_MASK 0x22
#define BTA_HH_KB_ALT_MASK 0x44
#define BTA_HH_KB_GUI_MASK 0x88
#define BTA_HH_KB_CAPS_LOCK 0x39 /* caps lock */
#define BTA_HH_KB_NUM_LOCK 0x53 /* num lock */
#define BTA_HH_MAX_RPT_CHARS 8
static const UINT8 bta_hh_mod_key_mask[BTA_HH_MOD_MAX_KEY] = {
BTA_HH_KB_CTRL_MASK,
BTA_HH_KB_SHIFT_MASK,
BTA_HH_KB_ALT_MASK,
BTA_HH_KB_GUI_MASK
};
/*******************************************************************************
**
** Function bta_hh_find_cb
**
** Description Find best available control block according to BD address.
**
**
** Returns void
**
*******************************************************************************/
UINT8 bta_hh_find_cb(BD_ADDR bda)
{
UINT8 xx;
/* See how many active devices there are. */
for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++) {
/* check if any active/known devices is a match */
if ((!bdcmp (bda, bta_hh_cb.kdev[xx].addr) &&
bdcmp(bda, bd_addr_null) != 0) ) {
#if BTA_HH_DEBUG
APPL_TRACE_DEBUG("found kdev_cb[%d] hid_handle = %d ", xx,
bta_hh_cb.kdev[xx].hid_handle)
#endif
return xx;
}
#if BTA_HH_DEBUG
else {
APPL_TRACE_DEBUG("in_use ? [%d] kdev[%d].hid_handle = %d state = [%d]",
bta_hh_cb.kdev[xx].in_use, xx,
bta_hh_cb.kdev[xx].hid_handle,
bta_hh_cb.kdev[xx].state);
}
#endif
}
/* if no active device match, find a spot for it */
for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++) {
if (!bta_hh_cb.kdev[xx].in_use) {
bdcpy(bta_hh_cb.kdev[xx].addr, bda);
bta_hh_cb.kdev[xx].in_use = TRUE;
break;
}
}
/* If device list full, report BTA_HH_IDX_INVALID */
#if BTA_HH_DEBUG
APPL_TRACE_DEBUG("bta_hh_find_cb:: index = %d while max = %d",
xx, BTA_HH_MAX_DEVICE);
#endif
if (xx == BTA_HH_MAX_DEVICE) {
xx = BTA_HH_IDX_INVALID;
}
return xx;
}
/*******************************************************************************
**
** Function bta_hh_clean_up_kdev
**
** Description Clean up device control block when device is removed from
** manitainace list, and update control block index map.
**
** Returns void
**
*******************************************************************************/
void bta_hh_clean_up_kdev(tBTA_HH_DEV_CB *p_cb)
{
UINT8 index;
if (p_cb->hid_handle != BTA_HH_INVALID_HANDLE ) {
#if BTA_HH_LE_INCLUDED == TRUE
if (p_cb->is_le_device) {
bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = BTA_HH_IDX_INVALID;
} else
#endif
{
bta_hh_cb.cb_index[p_cb->hid_handle] = BTA_HH_IDX_INVALID;
}
}
/* reset device control block */
index = p_cb->index; /* Preserve index for this control block */
/* Free buffer for report descriptor info */
utl_freebuf((void **)&p_cb->dscp_info.descriptor.dsc_list);
memset(p_cb, 0, sizeof (tBTA_HH_DEV_CB)); /* Reset control block */
p_cb->index = index; /* Restore index for this control block */
p_cb->state = BTA_HH_IDLE_ST;
p_cb->hid_handle = BTA_HH_INVALID_HANDLE;
}
/*******************************************************************************
**
** Function bta_hh_update_di_info
**
** Description Maintain a known device list for BTA HH.
**
** Returns void
**
*******************************************************************************/
void bta_hh_update_di_info(tBTA_HH_DEV_CB *p_cb, UINT16 vendor_id, UINT16 product_id,
UINT16 version, UINT8 flag)
{
#if BTA_HH_DEBUG
APPL_TRACE_DEBUG("vendor_id = 0x%2x product_id = 0x%2x version = 0x%2x",
vendor_id, product_id, version);
#endif
p_cb->dscp_info.vendor_id = vendor_id;
p_cb->dscp_info.product_id = product_id;
p_cb->dscp_info.version = version;
#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
p_cb->dscp_info.flag = flag;
#else
UNUSED(flag);
#endif
}
/*******************************************************************************
**
** Function bta_hh_add_device_to_list
**
** Description Maintain a known device list for BTA HH.
**
** Returns void
**
*******************************************************************************/
void bta_hh_add_device_to_list(tBTA_HH_DEV_CB *p_cb, UINT8 handle,
UINT16 attr_mask,
tHID_DEV_DSCP_INFO *p_dscp_info,
UINT8 sub_class,
UINT16 ssr_max_latency,
UINT16 ssr_min_tout,
UINT8 app_id)
{
#if BTA_HH_DEBUG
APPL_TRACE_DEBUG("subclass = 0x%2x", sub_class);
#endif
p_cb->hid_handle = handle;
p_cb->in_use = TRUE;
p_cb->attr_mask = attr_mask;
p_cb->sub_class = sub_class;
p_cb->app_id = app_id;
p_cb->dscp_info.ssr_max_latency = ssr_max_latency;
p_cb->dscp_info.ssr_min_tout = ssr_min_tout;
/* store report descriptor info */
if ( p_dscp_info) {
utl_freebuf((void **)&p_cb->dscp_info.descriptor.dsc_list);
if (p_dscp_info->dl_len &&
(p_cb->dscp_info.descriptor.dsc_list =
(UINT8 *)osi_malloc(p_dscp_info->dl_len)) != NULL) {
p_cb->dscp_info.descriptor.dl_len = p_dscp_info->dl_len;
memcpy(p_cb->dscp_info.descriptor.dsc_list, p_dscp_info->dsc_list,
p_dscp_info->dl_len);
}
}
return;
}
/*******************************************************************************
**
** Function bta_hh_tod_spt
**
** Description Check to see if this type of device is supported
**
** Returns
**
*******************************************************************************/
BOOLEAN bta_hh_tod_spt(tBTA_HH_DEV_CB *p_cb, UINT8 sub_class)
{
UINT8 xx;
UINT8 cod = (sub_class >> 2); /* lower two bits are reserved */
for (xx = 0 ; xx < p_bta_hh_cfg->max_devt_spt; xx ++) {
if (cod == (UINT8) p_bta_hh_cfg->p_devt_list[xx].tod) {
p_cb->app_id = p_bta_hh_cfg->p_devt_list[xx].app_id;
#if BTA_HH_DEBUG
APPL_TRACE_EVENT("bta_hh_tod_spt sub_class:0x%x supported", sub_class);
#endif
return TRUE;
}
}
#if BTA_HH_DEBUG
APPL_TRACE_ERROR("bta_hh_tod_spt sub_class:0x%x NOT supported", sub_class);
#endif
return FALSE;
}
/*******************************************************************************
**
** Function bta_hh_parse_keybd_rpt
**
** Description This utility function parse a boot mode keyboard report.
**
** Returns void
**
*******************************************************************************/
void bta_hh_parse_keybd_rpt(tBTA_HH_BOOT_RPT *p_kb_data, UINT8 *p_report,
UINT16 report_len)
{
tBTA_HH_KB_CB *p_kb = &bta_hh_cb.kb_cb;
tBTA_HH_KEYBD_RPT *p_data = &p_kb_data->data_rpt.keybd_rpt;
UINT8 this_char, ctl_shift;
UINT16 xx, yy, key_idx = 0;
UINT8 this_report[BTA_HH_MAX_RPT_CHARS];
#if BTA_HH_DEBUG
APPL_TRACE_DEBUG("bta_hh_parse_keybd_rpt: (report=%p, report_len=%d) called",
p_report, report_len);
#endif
if (report_len < 2) {
return;
}
ctl_shift = *p_report++;
report_len--;
if (report_len > BTA_HH_MAX_RPT_CHARS) {
report_len = BTA_HH_MAX_RPT_CHARS;
}
memset (this_report, 0, BTA_HH_MAX_RPT_CHARS);
memset (p_data, 0, sizeof(tBTA_HH_KEYBD_RPT));
memcpy (this_report, p_report, report_len);
/* Take care of shift, control, GUI and alt, modifier keys */
for (xx = 0; xx < BTA_HH_MOD_MAX_KEY; xx ++ ) {
if (ctl_shift & bta_hh_mod_key_mask[xx]) {
APPL_TRACE_DEBUG("Mod Key[%02x] pressed", bta_hh_mod_key_mask[xx] );
p_kb->mod_key[xx] = TRUE;
} else if (p_kb->mod_key[xx]) {
p_kb->mod_key[xx] = FALSE;
}
/* control key flag is set */
p_data->mod_key[xx] = p_kb->mod_key[xx];
}
/***************************************************************************/
/* First step is to remove all characters we saw in the last report */
/***************************************************************************/
for (xx = 0; xx < report_len; xx++) {
for (yy = 0; yy < BTA_HH_MAX_RPT_CHARS; yy++) {
if (this_report[xx] == p_kb->last_report[yy]) {
this_report[xx] = 0;
}
}
}
/***************************************************************************/
/* Now, process all the characters in the report, up to 6 keycodes */
/***************************************************************************/
for (xx = 0; xx < report_len; xx++) {
#if BTA_HH_DEBUG
APPL_TRACE_DEBUG("this_char = %02x", this_report[xx]);
#endif
if ((this_char = this_report[xx]) == 0) {
continue;
}
/* take the key code as the report data */
if (this_report[xx] == BTA_HH_KB_CAPS_LOCK) {
p_kb->caps_lock = p_kb->caps_lock ? FALSE : TRUE;
} else if (this_report[xx] == BTA_HH_KB_NUM_LOCK) {
p_kb->num_lock = p_kb->num_lock ? FALSE : TRUE;
} else {
p_data->this_char[key_idx ++] = this_char;
}
#if BTA_HH_DEBUG
APPL_TRACE_DEBUG("found keycode %02x ", this_report[xx]);
#endif
p_data->caps_lock = p_kb->caps_lock;
p_data->num_lock = p_kb->num_lock;
}
memset (p_kb->last_report, 0, BTA_HH_MAX_RPT_CHARS);
memcpy (p_kb->last_report, p_report, report_len);
return;
}
/*******************************************************************************
**
** Function bta_hh_parse_mice_rpt
**
** Description This utility function parse a boot mode mouse report.
**
** Returns void
**
*******************************************************************************/
void bta_hh_parse_mice_rpt(tBTA_HH_BOOT_RPT *p_mice_data, UINT8 *p_report,
UINT16 report_len)
{
tBTA_HH_MICE_RPT *p_data = &p_mice_data->data_rpt.mice_rpt;
#if BTA_HH_DEBUG
UINT8 xx;
APPL_TRACE_DEBUG("bta_hh_parse_mice_rpt: bta_keybd_rpt_rcvd(report=%p, \
report_len=%d) called", p_report, report_len);
#endif
if (report_len < 3) {
return;
}
if (report_len > BTA_HH_MAX_RPT_CHARS) {
report_len = BTA_HH_MAX_RPT_CHARS;
}
#if BTA_HH_DEBUG
for (xx = 0; xx < report_len; xx++) {
APPL_TRACE_DEBUG("this_char = %02x", p_report[xx]);
}
#endif
/* only first bytes lower 3 bits valid */
p_data->mouse_button = (p_report[0] & 0x07);
/* x displacement */
p_data->delta_x = p_report[1];
/* y displacement */
p_data->delta_y = p_report[2];
#if BTA_HH_DEBUG
APPL_TRACE_DEBUG("mice button: 0x%2x", p_data->mouse_button);
APPL_TRACE_DEBUG("mice move: x = %d y = %d", p_data->delta_x,
p_data->delta_y );
#endif
return;
}
/*******************************************************************************
**
** Function bta_hh_read_ssr_param
**
** Description Read the SSR Parameter for the remote device
**
** Returns tBTA_HH_STATUS operation status
**
*******************************************************************************/
tBTA_HH_STATUS bta_hh_read_ssr_param(BD_ADDR bd_addr, UINT16 *p_max_ssr_lat, UINT16 *p_min_ssr_tout)
{
tBTA_HH_STATUS status = BTA_HH_ERR;
tBTA_HH_CB *p_cb = &bta_hh_cb;
UINT8 i;
UINT16 ssr_max_latency;
for (i = 0; i < BTA_HH_MAX_KNOWN; i ++) {
if (memcmp(p_cb->kdev[i].addr, bd_addr, BD_ADDR_LEN) == 0) {
/* if remote device does not have HIDSSRHostMaxLatency attribute in SDP,
set SSR max latency default value here. */
if (p_cb->kdev[i].dscp_info.ssr_max_latency == HID_SSR_PARAM_INVALID) {
/* The default is calculated as half of link supervision timeout.*/
BTM_GetLinkSuperTout(p_cb->kdev[i].addr, &ssr_max_latency) ;
ssr_max_latency = BTA_HH_GET_DEF_SSR_MAX_LAT(ssr_max_latency);
/* per 1.1 spec, if the newly calculated max latency is greater than
BTA_HH_SSR_MAX_LATENCY_DEF which is 500ms, use BTA_HH_SSR_MAX_LATENCY_DEF */
if (ssr_max_latency > BTA_HH_SSR_MAX_LATENCY_DEF) {
ssr_max_latency = BTA_HH_SSR_MAX_LATENCY_DEF;
}
* p_max_ssr_lat = ssr_max_latency;
} else {
* p_max_ssr_lat = p_cb->kdev[i].dscp_info.ssr_max_latency;
}
if (p_cb->kdev[i].dscp_info.ssr_min_tout == HID_SSR_PARAM_INVALID) {
* p_min_ssr_tout = BTA_HH_SSR_MIN_TOUT_DEF;
} else {
* p_min_ssr_tout = p_cb->kdev[i].dscp_info.ssr_min_tout;
}
status = BTA_HH_OK;
break;
}
}
return status;
}
/*******************************************************************************
**
** Function bta_hh_cleanup_disable
**
** Description when disable finished, cleanup control block and send callback
**
**
** Returns void
**
*******************************************************************************/
void bta_hh_cleanup_disable(tBTA_HH_STATUS status)
{
UINT8 xx;
/* free buffer in CB holding report descriptors */
for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx ++) {
utl_freebuf((void **)&bta_hh_cb.kdev[xx].dscp_info.descriptor.dsc_list);
}
utl_freebuf((void **)&bta_hh_cb.p_disc_db);
if (bta_hh_cb.p_cback) {
(*bta_hh_cb.p_cback)(BTA_HH_DISABLE_EVT, (tBTA_HH*)&status);
/* all connections are down, no waiting for diconnect */
memset(&bta_hh_cb, 0, sizeof(tBTA_HH_CB));
}
}
/*******************************************************************************
**
** Function bta_hh_dev_handle_to_cb_idx
**
** Description convert a HID device handle to the device control block index.
**
**
** Returns UINT8: index of the device control block.
**
*******************************************************************************/
UINT8 bta_hh_dev_handle_to_cb_idx(UINT8 dev_handle)
{
UINT8 index = BTA_HH_IDX_INVALID;
#if BTA_HH_LE_INCLUDED == TRUE
if (BTA_HH_IS_LE_DEV_HDL(dev_handle)) {
if (BTA_HH_IS_LE_DEV_HDL_VALID(dev_handle)) {
index = bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(dev_handle)];
}
#if BTA_HH_DEBUG == TRUE
APPL_TRACE_DEBUG("bta_hh_dev_handle_to_cb_idx dev_handle = %d index = %d", dev_handle, index);
#endif
} else
#endif
{
/* regular HID device checking */
if (dev_handle < BTA_HH_MAX_KNOWN ) {
index = bta_hh_cb.cb_index[dev_handle];
}
}
return index;
}
#if BTA_HH_DEBUG
/*******************************************************************************
**
** Function bta_hh_trace_dev_db
**
** Description Check to see if this type of device is supported
**
** Returns
**
*******************************************************************************/
void bta_hh_trace_dev_db(void)
{
UINT8 xx;
APPL_TRACE_DEBUG("bta_hh_trace_dev_db:: Device DB list********************");
for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++) {
APPL_TRACE_DEBUG("kdev[%d] in_use[%d] handle[%d] ", xx,
bta_hh_cb.kdev[xx].in_use, bta_hh_cb.kdev[xx].hid_handle);
APPL_TRACE_DEBUG("\t\t\t attr_mask[%04x] state [%d] sub_class[%02x] index = %d",
bta_hh_cb.kdev[xx].attr_mask, bta_hh_cb.kdev[xx].state,
bta_hh_cb.kdev[xx].sub_class, bta_hh_cb.kdev[xx].index);
}
APPL_TRACE_DEBUG("*********************************************************");
}
#endif
#endif /* HL_INCLUDED */
@@ -0,0 +1,403 @@
/******************************************************************************
*
* Copyright (C) 2005-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* This file contains BTA HID Host internal definitions
*
******************************************************************************/
#ifndef BTA_HH_INT_H
#define BTA_HH_INT_H
#include "bta/bta_sys.h"
#include "bta/utl.h"
#include "bta/bta_hh_api.h"
//#if BTA_HH_LE_INCLUDED == TRUE
#include "bta/bta_gatt_api.h"
//#endif
#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
/* can be moved to bta/bta_api.h */
#define BTA_HH_MAX_RPT_CHARS 8
#if (BTA_GATT_INCLUDED == FALSE || BLE_INCLUDED == FALSE)
#undef BTA_HH_LE_INCLUDED
#define BTA_HH_LE_INCLUDED FALSE
#endif
/* state machine events, these events are handled by the state machine */
enum {
BTA_HH_API_OPEN_EVT = BTA_SYS_EVT_START(BTA_ID_HH),
BTA_HH_API_CLOSE_EVT,
BTA_HH_INT_OPEN_EVT,
BTA_HH_INT_CLOSE_EVT,
BTA_HH_INT_DATA_EVT,
BTA_HH_INT_CTRL_DATA,
BTA_HH_INT_HANDSK_EVT,
BTA_HH_SDP_CMPL_EVT,
BTA_HH_API_WRITE_DEV_EVT,
BTA_HH_API_GET_DSCP_EVT,
BTA_HH_API_MAINT_DEV_EVT,
BTA_HH_OPEN_CMPL_EVT,
#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
BTA_HH_GATT_CLOSE_EVT,
BTA_HH_GATT_OPEN_EVT,
BTA_HH_START_ENC_EVT,
BTA_HH_ENC_CMPL_EVT,
BTA_HH_GATT_READ_CHAR_CMPL_EVT,
BTA_HH_GATT_WRITE_CHAR_CMPL_EVT,
BTA_HH_GATT_READ_DESCR_CMPL_EVT,
BTA_HH_GATT_WRITE_DESCR_CMPL_EVT,
BTA_HH_API_SCPP_UPDATE_EVT,
BTA_HH_GATT_ENC_CMPL_EVT,
#endif
/* not handled by execute state machine */
BTA_HH_API_ENABLE_EVT,
BTA_HH_API_DISABLE_EVT,
BTA_HH_DISC_CMPL_EVT
};
typedef UINT16 tBTA_HH_INT_EVT; /* HID host internal events */
#define BTA_HH_INVALID_EVT (BTA_HH_DISC_CMPL_EVT + 1)
/* event used to map between BTE event and BTA event */
#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 */
#define BTA_HH_ADD_DEV 0
#define BTA_HH_REMOVE_DEV 1
/* state machine states */
enum {
BTA_HH_NULL_ST,
BTA_HH_IDLE_ST,
BTA_HH_W4_CONN_ST,
BTA_HH_CONN_ST
#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
, BTA_HH_W4_SEC
#endif
, BTA_HH_INVALID_ST /* Used to check invalid states before executing SM function */
};
typedef UINT8 tBTA_HH_STATE;
/* data structure used to send a command/data to HID device */
typedef struct {
BT_HDR hdr;
UINT8 t_type;
UINT8 param;
UINT8 rpt_id;
#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
UINT8 srvc_id;
#endif
UINT16 data;
BT_HDR *p_data;
} tBTA_HH_CMD_DATA;
/* data type for BTA_HH_API_ENABLE_EVT */
typedef struct {
BT_HDR hdr;
UINT8 sec_mask;
UINT8 service_name[BTA_SERVICE_NAME_LEN + 1];
tBTA_HH_CBACK *p_cback;
} tBTA_HH_API_ENABLE;
typedef struct {
BT_HDR hdr;
BD_ADDR bd_addr;
UINT8 sec_mask;
tBTA_HH_PROTO_MODE mode;
} tBTA_HH_API_CONN;
/* internal event data from BTE HID callback */
typedef struct {
BT_HDR hdr;
BD_ADDR addr;
UINT32 data;
BT_HDR *p_data;
} tBTA_HH_CBACK_DATA;
typedef struct {
BT_HDR hdr;
BD_ADDR bda;
UINT16 attr_mask;
UINT16 sub_event;
UINT8 sub_class;
UINT8 app_id;
tBTA_HH_DEV_DSCP_INFO dscp_info;
} tBTA_HH_MAINT_DEV;
#if BTA_HH_LE_INCLUDED == TRUE
typedef struct {
BT_HDR hdr;
UINT16 conn_id;
tBTA_GATT_REASON reason; /* disconnect reason code, not useful when connect event is reported */
} tBTA_HH_LE_CLOSE;
typedef struct {
BT_HDR hdr;
UINT16 scan_int;
UINT16 scan_win;
} tBTA_HH_SCPP_UPDATE;
#endif
/* union of all event data types */
typedef union {
BT_HDR hdr;
tBTA_HH_API_ENABLE api_enable;
tBTA_HH_API_CONN api_conn;
tBTA_HH_CMD_DATA api_sndcmd;
tBTA_HH_CBACK_DATA hid_cback;
tBTA_HH_STATUS status;
tBTA_HH_MAINT_DEV api_maintdev;
#if BTA_HH_LE_INCLUDED == TRUE
tBTA_HH_LE_CLOSE le_close;
tBTA_GATTC_OPEN le_open;
tBTA_HH_SCPP_UPDATE le_scpp_update;
tBTA_GATTC_ENC_CMPL_CB le_enc_cmpl;
#endif
} tBTA_HH_DATA;
#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
typedef struct {
UINT8 index;
BOOLEAN in_use;
UINT8 inst_id; /* share service instance ID and report instance ID, as
hi 4 for service instance ID, low 4 as charatceristic instance ID */
tBTA_HH_RPT_TYPE rpt_type;
UINT16 uuid;
UINT8 prop;
UINT8 rpt_id;
BOOLEAN client_cfg_exist;
UINT16 client_cfg_value;
} tBTA_HH_LE_RPT;
#ifndef BTA_HH_LE_RPT_MAX
#define BTA_HH_LE_RPT_MAX 20
#endif
typedef struct {
BOOLEAN in_use;
tBTA_HH_LE_RPT report[BTA_HH_LE_RPT_MAX];
#define BTA_HH_LE_PROTO_MODE_BIT 0x01
#define BTA_HH_LE_CP_BIT 0x02
UINT8 option_char; /* control point char exisit or not */
BOOLEAN expl_incl_srvc;
UINT8 incl_srvc_inst; /* assuming only one included service : battery service */
UINT8 cur_expl_char_idx; /* currently discovering service index */
UINT8 *rpt_map;
UINT16 ext_rpt_ref;
tBTA_HH_DEV_DESCR descriptor;
} tBTA_HH_LE_HID_SRVC;
#ifndef BTA_HH_LE_HID_SRVC_MAX
#define BTA_HH_LE_HID_SRVC_MAX 1
#endif
/* convert a HID handle to the LE CB index */
#define BTA_HH_GET_LE_CB_IDX(x) (((x) >> 4) - 1)
/* convert a GATT connection ID to HID device handle, it is the hi 4 bits of a UINT8 */
#define BTA_HH_GET_LE_DEV_HDL(x) (UINT8)(((x) + 1) << 4)
/* check to see if th edevice handle is a LE device handle */
#define BTA_HH_IS_LE_DEV_HDL(x) ((x) & 0xf0)
#define BTA_HH_IS_LE_DEV_HDL_VALID(x) (((x)>>4) <= BTA_HH_LE_MAX_KNOWN)
#endif
/* device control block */
typedef struct {
tBTA_HH_DEV_DSCP_INFO dscp_info; /* report descriptor and DI information */
BD_ADDR addr; /* BD-Addr of the HID device */
UINT16 attr_mask; /* attribute mask */
UINT16 w4_evt; /* W4_handshake event name */
UINT8 index; /* index number referenced to handle index */
UINT8 sub_class; /* Cod sub class */
UINT8 sec_mask; /* security mask */
UINT8 app_id; /* application ID for this connection */
UINT8 hid_handle; /* device handle : low 4 bits for regular HID: HID_HOST_MAX_DEVICES can not exceed 15;
high 4 bits for LE HID: GATT_MAX_PHY_CHANNEL can not exceed 15 */
BOOLEAN vp; /* virtually unplug flag */
BOOLEAN in_use; /* control block currently in use */
BOOLEAN incoming_conn; /* is incoming connection? */
UINT8 incoming_hid_handle; /* temporary handle for incoming connection? */
BOOLEAN opened; /* TRUE if device successfully opened HID connection */
tBTA_HH_PROTO_MODE mode; /* protocol mode */
tBTA_HH_PROTO_MODE new_mode; /* protocol mode */
tBTA_HH_STATE state; /* CB state */
#if (BTA_HH_LE_INCLUDED == TRUE)
#define BTA_HH_LE_DISC_NONE 0x00
#define BTA_HH_LE_DISC_HIDS 0x01
#define BTA_HH_LE_DISC_DIS 0x02
#define BTA_HH_LE_DISC_SCPS 0x04
UINT8 disc_active;
tBTA_HH_STATUS status;
tBTA_GATT_REASON reason;
BOOLEAN is_le_device;
tBTA_HH_LE_HID_SRVC hid_srvc[BTA_HH_LE_HID_SRVC_MAX];
UINT16 conn_id;
BOOLEAN in_bg_conn;
UINT8 total_srvc;
UINT8 clt_cfg_idx;
UINT8 cur_srvc_index; /* currently discovering service index */
BOOLEAN scps_supported;
#define BTA_HH_LE_SCPS_NOTIFY_NONE 0
#define BTA_HH_LE_SCPS_NOTIFY_SPT 0x01
#define BTA_HH_LE_SCPS_NOTIFY_ENB 0x02
UINT8 scps_notify; /* scan refresh supported/notification enabled */
#endif
BOOLEAN security_pending;
} tBTA_HH_DEV_CB;
/* key board parsing control block */
typedef struct {
BOOLEAN mod_key[4]; /* ctrl, shift(upper), Alt, GUI */
BOOLEAN num_lock;
BOOLEAN caps_lock;
UINT8 last_report[BTA_HH_MAX_RPT_CHARS];
} tBTA_HH_KB_CB;
/******************************************************************************
** Main Control Block
*******************************************************************************/
typedef struct {
tBTA_HH_KB_CB kb_cb; /* key board control block,
suppose BTA will connect
to only one keyboard at
the same time */
tBTA_HH_DEV_CB kdev[BTA_HH_MAX_DEVICE]; /* device control block */
tBTA_HH_DEV_CB *p_cur; /* current device control
block idx, used in sdp */
UINT8 cb_index[BTA_HH_MAX_KNOWN]; /* maintain a CB index
map to dev handle */
#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
UINT8 le_cb_index[BTA_HH_MAX_DEVICE]; /* maintain a CB index map to LE dev handle */
tBTA_GATTC_IF gatt_if;
#endif
tBTA_HH_CBACK *p_cback; /* Application callbacks */
tSDP_DISCOVERY_DB *p_disc_db;
UINT8 trace_level; /* tracing level */
UINT8 cnt_num; /* connected device number */
BOOLEAN w4_disable; /* w4 disable flag */
}
tBTA_HH_CB;
#if BTA_DYNAMIC_MEMORY == FALSE
extern tBTA_HH_CB bta_hh_cb;
#else
extern tBTA_HH_CB *bta_hh_cb_ptr;
#define bta_hh_cb (*bta_hh_cb_ptr)
#endif
/* from bta_hh_cfg.c */
extern tBTA_HH_CFG *p_bta_hh_cfg;
/*****************************************************************************
** Function prototypes
*****************************************************************************/
extern BOOLEAN bta_hh_hdl_event(BT_HDR *p_msg);
extern void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16 event,
tBTA_HH_DATA *p_data);
/* action functions */
extern void bta_hh_api_disc_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
extern void bta_hh_open_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
extern void bta_hh_close_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
extern void bta_hh_data_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
extern void bta_hh_ctrl_dat_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
extern void bta_hh_start_sdp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
extern void bta_hh_sdp_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
extern void bta_hh_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
extern void bta_hh_get_dscp_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
extern void bta_hh_handsk_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
extern void bta_hh_maint_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
extern void bta_hh_open_cmpl_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
extern void bta_hh_open_failure(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
/* utility functions */
extern UINT8 bta_hh_find_cb(BD_ADDR bda);
extern void bta_hh_parse_keybd_rpt(tBTA_HH_BOOT_RPT *p_kb_data,
UINT8 *p_report, UINT16 report_len);
extern void bta_hh_parse_mice_rpt(tBTA_HH_BOOT_RPT *p_kb_data,
UINT8 *p_report, UINT16 report_len);
extern BOOLEAN bta_hh_tod_spt(tBTA_HH_DEV_CB *p_cb, UINT8 sub_class);
extern void bta_hh_clean_up_kdev(tBTA_HH_DEV_CB *p_cb);
extern void bta_hh_add_device_to_list(tBTA_HH_DEV_CB *p_cb, UINT8 handle,
UINT16 attr_mask,
tHID_DEV_DSCP_INFO *p_dscp_info,
UINT8 sub_class, UINT16 max_latency, UINT16 min_tout, UINT8 app_id);
extern void bta_hh_update_di_info(tBTA_HH_DEV_CB *p_cb, UINT16 vendor_id, UINT16 product_id,
UINT16 version, UINT8 flag);
extern void bta_hh_cleanup_disable(tBTA_HH_STATUS status);
extern UINT8 bta_hh_dev_handle_to_cb_idx(UINT8 dev_handle);
/* action functions used outside state machine */
extern void bta_hh_api_enable(tBTA_HH_DATA *p_data);
extern void bta_hh_api_disable(void);
extern void bta_hh_disc_cmpl(void);
extern tBTA_HH_STATUS bta_hh_read_ssr_param(BD_ADDR bd_addr, UINT16 *p_max_ssr_lat, UINT16 *p_min_ssr_tout);
/* functions for LE HID */
#if (BTA_HH_LE_INCLUDED == TRUE)
extern void bta_hh_le_enable(void);
extern BOOLEAN bta_hh_le_is_hh_gatt_if(tBTA_GATTC_IF client_if);
extern void bta_hh_le_deregister(void);
extern BOOLEAN bta_hh_is_le_device(tBTA_HH_DEV_CB *p_cb, BD_ADDR remote_bda);
extern void bta_hh_le_open_conn(tBTA_HH_DEV_CB *p_cb, BD_ADDR remote_bda);
extern void bta_hh_le_api_disc_act(tBTA_HH_DEV_CB *p_cb);
extern void bta_hh_le_get_dscp_act(tBTA_HH_DEV_CB *p_cb);
extern void bta_hh_le_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
extern UINT8 bta_hh_le_add_device(tBTA_HH_DEV_CB *p_cb, tBTA_HH_MAINT_DEV *p_dev_info);
extern void bta_hh_le_remove_dev_bg_conn(tBTA_HH_DEV_CB *p_cb);
extern void bta_hh_le_open_fail(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
extern void bta_hh_gatt_open(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
extern void bta_hh_gatt_close(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
extern void bta_hh_start_security(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
extern void bta_hh_start_srvc_discovery(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
extern void bta_hh_w4_le_read_char_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
extern void bta_hh_le_read_char_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
extern void bta_hh_w4_le_read_descr_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
extern void bta_hh_le_read_descr_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
extern void bta_hh_w4_le_write_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
extern void bta_hh_le_write_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
extern void bta_hh_le_write_char_descr_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
extern void bta_hh_start_security(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
extern void bta_hh_security_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
extern void bta_hh_le_update_scpp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
extern void bta_hh_le_notify_enc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
extern void bta_hh_ci_load_rpt (tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
#endif
#if BTA_HH_DEBUG
extern void bta_hh_trace_dev_db(void);
#endif
#endif ///defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
#endif