kopia lustrzana https://github.com/espressif/esp-idf
1575 wiersze
57 KiB
C
1575 wiersze
57 KiB
C
/******************************************************************************
|
|
*
|
|
* Copyright (C) 2016 The Android Open Source Project
|
|
* Copyright (C) 2009-2012 Broadcom Corporation
|
|
* Copyright (C) 2019 Blake Felt
|
|
*
|
|
* 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.
|
|
*
|
|
******************************************************************************/
|
|
/************************************************************************************
|
|
*
|
|
* Filename: btc_hd.c
|
|
*
|
|
* Description: HID Device Profile Bluetooth Interface
|
|
*
|
|
*
|
|
***********************************************************************************/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "btc/btc_util.h"
|
|
#include "btc/btc_manage.h"
|
|
#include "device/bdaddr.h"
|
|
#include "btc/btc_storage.h"
|
|
#include "osi/allocator.h"
|
|
#include "bta/utl.h"
|
|
#include "bta/bta_hh_api.h"
|
|
#include "stack/l2c_api.h"
|
|
// #include "bta_dm_int.h"
|
|
|
|
#if HID_HOST_INCLUDED == TRUE
|
|
#include "btc_hh.h"
|
|
|
|
|
|
/*******************************************************************************
|
|
* Static variables
|
|
******************************************************************************/
|
|
btc_hh_cb_t btc_hh_cb;
|
|
static bdstr_t bdstr;
|
|
|
|
/******************************************************************************
|
|
* Constants & Macros
|
|
*****************************************************************************/
|
|
#define COD_MASK 0x07FF
|
|
|
|
#define COD_UNCLASSIFIED ((0x1F) << 8)
|
|
#define COD_HID_KEYBOARD 0x0540
|
|
#define COD_HID_POINTING 0x0580
|
|
#define COD_HID_COMBO 0x05C0
|
|
#define COD_HID_MAJOR 0x0500
|
|
#define COD_HID_MASK 0x0700
|
|
|
|
#define is_hidh_init() (btc_hh_cb.status > BTC_HH_DISABLED)
|
|
#define BTC_TIMEOUT_VUP_MS (3 * 1000)
|
|
|
|
static inline void btc_hh_cb_to_app(esp_hidh_cb_event_t event, esp_hidh_cb_param_t *param)
|
|
{
|
|
esp_hh_cb_t btc_hh_cb = (esp_hh_cb_t)btc_profile_cb_get(BTC_PID_HH);
|
|
if (btc_hh_cb) {
|
|
btc_hh_cb(event, param);
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function proto_mode_change_to_lower_layer
|
|
*
|
|
* Description Change the upper layer protocol mode definition to the lower layer protocol mode definition
|
|
*
|
|
* Returns Lower layer protocol mode definition
|
|
******************************************************************************/
|
|
static inline tBTA_HH_PROTO_MODE proto_mode_change_to_lower_layer(esp_hidh_protocol_mode_t protocol_mode)
|
|
{
|
|
tBTA_HH_PROTO_MODE proto_mode = BTA_HH_PROTO_UNKNOWN;
|
|
|
|
switch (protocol_mode) {
|
|
case ESP_HIDH_REPORT_MODE:
|
|
proto_mode = BTA_HH_PROTO_RPT_MODE;
|
|
break;
|
|
case ESP_HIDH_BOOT_MODE:
|
|
proto_mode = BTA_HH_PROTO_BOOT_MODE;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return proto_mode;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function proto_mode_change_to_upper_layer
|
|
*
|
|
* Description Change the lower layer protocol mode definition to the upper layer protocol mode definition
|
|
*
|
|
* Returns Upper layer protocol mode definition
|
|
******************************************************************************/
|
|
static inline esp_hidh_protocol_mode_t proto_mode_change_to_upper_layer(tBTA_HH_PROTO_MODE proto_mode)
|
|
{
|
|
esp_hidh_protocol_mode_t protocol_mode = ESP_HIDH_UNSUPPORTED_MODE;
|
|
|
|
switch (proto_mode) {
|
|
case BTA_HH_PROTO_RPT_MODE:
|
|
protocol_mode = ESP_HIDH_REPORT_MODE;
|
|
break;
|
|
case BTA_HH_PROTO_BOOT_MODE:
|
|
protocol_mode = ESP_HIDH_BOOT_MODE;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return protocol_mode;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function btc_hh_find_connected_dev_by_handle
|
|
*
|
|
* Description Return the connected device pointer of the specified device
|
|
* handle
|
|
*
|
|
* Returns Device entry pointer in the device table
|
|
******************************************************************************/
|
|
btc_hh_device_t *btc_hh_find_connected_dev_by_handle(uint8_t handle)
|
|
{
|
|
uint32_t i;
|
|
for (i = 0; i < BTC_HH_MAX_HID; i++) {
|
|
if (btc_hh_cb.devices[i].dev_status == ESP_HIDH_CONN_STATE_CONNECTED && btc_hh_cb.devices[i].dev_handle == handle) {
|
|
return &btc_hh_cb.devices[i];
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function btc_hh_find_dev_by_bda
|
|
*
|
|
* Description Return the device pointer of the specified bd_addr.
|
|
*
|
|
* Returns Device entry pointer in the device table
|
|
******************************************************************************/
|
|
static btc_hh_device_t *btc_hh_find_dev_by_bda(BD_ADDR bd_addr)
|
|
{
|
|
uint8_t i;
|
|
for (i = 0; i < BTC_HH_MAX_HID; i++) {
|
|
if (btc_hh_cb.devices[i].dev_status != ESP_HIDH_CONN_STATE_UNKNOWN &&
|
|
memcmp(btc_hh_cb.devices[i].bd_addr, bd_addr, BD_ADDR_LEN) == 0) {
|
|
return &btc_hh_cb.devices[i];
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function btc_hh_find_connected_dev_by_bda
|
|
*
|
|
* Description Return the connected device pointer of the specified
|
|
* RawAddress.
|
|
*
|
|
* Returns Device entry pointer in the device table
|
|
******************************************************************************/
|
|
static btc_hh_device_t *btc_hh_find_connected_dev_by_bda(BD_ADDR bd_addr)
|
|
{
|
|
uint32_t i;
|
|
for (i = 0; i < BTC_HH_MAX_HID; i++) {
|
|
if (btc_hh_cb.devices[i].dev_status == ESP_HIDH_CONN_STATE_CONNECTED &&
|
|
memcmp(btc_hh_cb.devices[i].bd_addr, bd_addr, BD_ADDR_LEN) == 0) {
|
|
return &btc_hh_cb.devices[i];
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function btc_hh_stop_vup_timer
|
|
*
|
|
* Description stop virtual unplug timer
|
|
*
|
|
* Returns void
|
|
******************************************************************************/
|
|
void btc_hh_stop_vup_timer(BD_ADDR bd_addr)
|
|
{
|
|
BTIF_TRACE_API("%s", __func__);
|
|
btc_hh_device_t *p_dev = btc_hh_find_connected_dev_by_bda(bd_addr);
|
|
|
|
if (p_dev != NULL) {
|
|
BTC_TRACE_DEBUG("stop VUP timer");
|
|
if (p_dev->vup_timer) {
|
|
osi_alarm_free(p_dev->vup_timer);
|
|
p_dev->vup_timer = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function btc_hh_timer_timeout
|
|
*
|
|
* Description Process timer timeout
|
|
*
|
|
* Returns void
|
|
******************************************************************************/
|
|
void btc_hh_timer_timeout(void *data)
|
|
{
|
|
btc_hh_device_t *p_dev = (btc_hh_device_t *)data;
|
|
bt_status_t status;
|
|
tBTA_HH p_data;
|
|
btc_msg_t msg;
|
|
msg.sig = BTC_SIG_API_CB;
|
|
msg.pid = BTC_PID_HH;
|
|
msg.act = BTA_HH_VC_UNPLUG_EVT;
|
|
|
|
BTC_TRACE_API("%s", __func__);
|
|
if (p_dev->dev_status != ESP_HIDH_CONN_STATE_CONNECTED){
|
|
BTC_TRACE_ERROR("%s Device[%s] is not connected!", __func__,
|
|
bdaddr_to_string((const bt_bdaddr_t *)p_dev->bd_addr, bdstr, sizeof(bdstr)));
|
|
return;
|
|
}
|
|
|
|
memset(&p_data, 0, sizeof(tBTA_HH));
|
|
p_data.dev_status.status = BTA_HH_ERR;
|
|
p_data.dev_status.handle = p_dev->dev_handle;
|
|
|
|
/* switch context to btif task context */
|
|
status = btc_transfer_context(&msg, &p_data, sizeof(tBTA_HH), NULL, NULL);
|
|
if (status != BT_STATUS_SUCCESS) {
|
|
BTC_TRACE_ERROR("%s context transfer failed", __func__);
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function btc_hh_start_vup_timer
|
|
*
|
|
* Description start virtual unplug timer
|
|
*
|
|
* Returns void
|
|
******************************************************************************/
|
|
void btc_hh_start_vup_timer(BD_ADDR bd_addr)
|
|
{
|
|
BTC_TRACE_API("%s", __func__);
|
|
|
|
btc_hh_device_t *p_dev = btc_hh_find_connected_dev_by_bda(bd_addr);
|
|
if (p_dev == NULL) {
|
|
BTC_TRACE_ERROR("%s Error: device not connected!", __func__);
|
|
return;
|
|
}
|
|
|
|
if (p_dev->vup_timer) {
|
|
osi_alarm_free(p_dev->vup_timer);
|
|
p_dev->vup_timer = NULL;
|
|
}
|
|
if ((p_dev->vup_timer = osi_alarm_new("btc_hh.vup_timer", btc_hh_timer_timeout, p_dev, BTC_TIMEOUT_VUP_MS)) ==
|
|
NULL) {
|
|
BTC_TRACE_ERROR("%s unable to malloc vup_timer!", __func__);
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function btc_hh_add_added_dev
|
|
*
|
|
* Description Add a new device to the added device list.
|
|
*
|
|
* Returns true if add successfully, otherwise false.
|
|
******************************************************************************/
|
|
bool btc_hh_add_added_dev(BD_ADDR bd_addr, tBTA_HH_ATTR_MASK attr_mask)
|
|
{
|
|
int i;
|
|
for (i = 0; i < BTC_HH_MAX_ADDED_DEV; i++) {
|
|
if (memcmp(btc_hh_cb.added_devices[i].bd_addr, bd_addr, BD_ADDR_LEN) == 0) {
|
|
return false;
|
|
}
|
|
}
|
|
for (i = 0; i < BTC_HH_MAX_ADDED_DEV; i++) {
|
|
if (memcmp(btc_hh_cb.added_devices[i].bd_addr, bd_addr_null, BD_ADDR_LEN) == 0) {
|
|
memcpy(btc_hh_cb.added_devices[i].bd_addr, bd_addr, BD_ADDR_LEN);
|
|
btc_hh_cb.added_devices[i].dev_handle = BTA_HH_INVALID_HANDLE;
|
|
btc_hh_cb.added_devices[i].attr_mask = attr_mask;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
BTC_TRACE_ERROR("%s: Error, out of space to add device", __func__);
|
|
return false;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
**
|
|
** Function btc_hh_remove_device
|
|
**
|
|
** Description Remove an added device from the stack.
|
|
**
|
|
** Returns void
|
|
******************************************************************************/
|
|
void btc_hh_remove_device(BD_ADDR bd_addr)
|
|
{
|
|
int i;
|
|
btc_hh_device_t *p_dev;
|
|
btc_hh_added_device_t *p_added_dev;
|
|
|
|
for (i = 0; i < BTC_HH_MAX_ADDED_DEV; i++) {
|
|
p_added_dev = &btc_hh_cb.added_devices[i];
|
|
if (memcmp(p_added_dev->bd_addr, bd_addr, BD_ADDR_LEN) == 0) {
|
|
BTA_HhRemoveDev(p_added_dev->dev_handle);
|
|
btc_storage_remove_hid_info((bt_bdaddr_t *)p_added_dev->bd_addr);
|
|
memset(p_added_dev->bd_addr, 0, 6);
|
|
p_added_dev->dev_handle = BTA_HH_INVALID_HANDLE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
p_dev = btc_hh_find_dev_by_bda(bd_addr);
|
|
if (p_dev == NULL) {
|
|
BTC_TRACE_ERROR("%s Oops, can't find device", __func__);
|
|
return;
|
|
}
|
|
|
|
/* need to notify up-layer device is disconnected to avoid state out of sync
|
|
* with up-layer */ //[boblane]
|
|
// HAL_CBACK(bt_hh_callbacks, connection_state_cb, &(p_dev->bd_addr), BTHH_CONN_STATE_DISCONNECTED);
|
|
|
|
p_dev->dev_status = ESP_HIDH_CONN_STATE_UNKNOWN;
|
|
p_dev->dev_handle = BTA_HH_INVALID_HANDLE;
|
|
p_dev->ready_for_data = false;
|
|
|
|
if (btc_hh_cb.device_num > 0) {
|
|
btc_hh_cb.device_num--;
|
|
} else {
|
|
BTC_TRACE_WARNING("%s: device_num = 0", __func__);
|
|
}
|
|
}
|
|
|
|
static void bte_hh_arg_deep_copy(btc_msg_t *msg, void *p_dst, void *p_src)
|
|
{
|
|
tBTA_HH *p_dst_data = (tBTA_HH *)p_dst;
|
|
tBTA_HH *p_src_data = (tBTA_HH *)p_src;
|
|
switch (msg->act)
|
|
{
|
|
case BTA_HH_GET_RPT_EVT: {
|
|
BT_HDR *src_hdr = p_src_data->hs_data.rsp_data.p_rpt_data;
|
|
if (src_hdr) {
|
|
p_dst_data->hs_data.rsp_data.p_rpt_data = osi_malloc(sizeof(BT_HDR) + src_hdr->offset + src_hdr->len);
|
|
if (p_dst_data->hs_data.rsp_data.p_rpt_data == NULL) {
|
|
BTC_TRACE_ERROR("%s malloc p_rpt_data failed!", __func__);
|
|
p_dst_data->hs_data.status = ESP_HIDH_ERR_NO_RES;
|
|
break;
|
|
}
|
|
memcpy(p_dst_data->hs_data.rsp_data.p_rpt_data, src_hdr, sizeof(BT_HDR) + src_hdr->offset + src_hdr->len);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH *p_data)
|
|
{
|
|
bt_status_t status;
|
|
int param_len = 0;
|
|
|
|
BTC_TRACE_API("%s event=%d", __func__, event);
|
|
|
|
switch (event) {
|
|
case BTA_HH_ENABLE_EVT:
|
|
param_len = sizeof(tBTA_HH_STATUS);
|
|
break;
|
|
case BTA_HH_DISABLE_EVT:
|
|
param_len = sizeof(tBTA_HH_STATUS);
|
|
break;
|
|
case BTA_HH_OPEN_EVT:
|
|
param_len = sizeof(tBTA_HH_CONN);
|
|
break;
|
|
case BTA_HH_CLOSE_EVT:
|
|
param_len = sizeof(tBTA_HH_CBDATA);
|
|
break;
|
|
case BTA_HH_GET_RPT_EVT:
|
|
param_len = sizeof(tBTA_HH_HSDATA);
|
|
break;
|
|
case BTA_HH_SET_RPT_EVT:
|
|
param_len = sizeof(tBTA_HH_CBDATA);
|
|
break;
|
|
case BTA_HH_GET_PROTO_EVT:
|
|
param_len = sizeof(tBTA_HH_HSDATA);
|
|
break;
|
|
case BTA_HH_SET_PROTO_EVT:
|
|
param_len = sizeof(tBTA_HH_CBDATA);
|
|
break;
|
|
case BTA_HH_GET_IDLE_EVT:
|
|
param_len = sizeof(tBTA_HH_HSDATA);
|
|
break;
|
|
case BTA_HH_SET_IDLE_EVT:
|
|
param_len = sizeof(tBTA_HH_CBDATA);
|
|
break;
|
|
case BTA_HH_GET_DSCP_EVT:
|
|
param_len = sizeof(tBTA_HH_DEV_DSCP_INFO);
|
|
break;
|
|
case BTA_HH_ADD_DEV_EVT:
|
|
param_len = sizeof(tBTA_HH_DEV_INFO);
|
|
break;
|
|
case BTA_HH_RMV_DEV_EVT:
|
|
param_len = sizeof(tBTA_HH_DEV_INFO);
|
|
break;
|
|
case BTA_HH_VC_UNPLUG_EVT:
|
|
param_len = sizeof(tBTA_HH_CBDATA);
|
|
break;
|
|
case BTA_HH_DATA_EVT:
|
|
param_len = sizeof(tBTA_HH_API_SENDDATA);
|
|
break;
|
|
case BTA_HH_API_ERR_EVT:
|
|
param_len = 0;
|
|
break;
|
|
}
|
|
|
|
btc_msg_t msg;
|
|
msg.sig = BTC_SIG_API_CB;
|
|
msg.pid = BTC_PID_HH;
|
|
msg.act = event;
|
|
|
|
status = btc_transfer_context(&msg, p_data, param_len, bte_hh_arg_deep_copy, btc_hh_cb_arg_deep_free);
|
|
assert(status == BT_STATUS_SUCCESS);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function btc_hh_init
|
|
*
|
|
* Description initializes the hh interface
|
|
*
|
|
* Returns void
|
|
*
|
|
******************************************************************************/
|
|
static void btc_hh_init(void)
|
|
{
|
|
BTC_TRACE_API("%s", __func__);
|
|
esp_hidh_status_t ret = ESP_HIDH_OK;
|
|
do {
|
|
if (is_hidh_init()) {
|
|
BTC_TRACE_ERROR("%s HH has been initiated, shall uninit first!", __func__);
|
|
ret = ESP_HIDH_NEED_DEINIT;
|
|
break;
|
|
}
|
|
|
|
memset(&btc_hh_cb, 0, sizeof(btc_hh_cb));
|
|
for (uint8_t i = 0; i < BTC_HH_MAX_HID; i++) {
|
|
btc_hh_cb.devices[i].dev_status = ESP_HIDH_CONN_STATE_UNKNOWN;
|
|
}
|
|
BTA_HhEnable(BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT, bte_hh_evt);
|
|
} while (0);
|
|
|
|
if (ret != ESP_HIDH_OK) {
|
|
esp_hidh_cb_param_t param;
|
|
param.init.status = ret;
|
|
btc_hh_cb_to_app(ESP_HIDH_INIT_EVT, ¶m);
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function btc_hh_deinit
|
|
*
|
|
* Description de-initializes the hh interface
|
|
*
|
|
* Returns void
|
|
*
|
|
******************************************************************************/
|
|
static void btc_hh_deinit(void)
|
|
{
|
|
BTC_TRACE_API("%s", __func__);
|
|
esp_hidh_status_t ret = ESP_HIDH_OK;
|
|
do {
|
|
if (!is_hidh_init()) {
|
|
BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
|
|
ret = ESP_HIDH_NEED_INIT;
|
|
break;
|
|
}
|
|
|
|
// close all connections
|
|
for (uint8_t i = 0; i < BTC_HH_MAX_HID; i++) {
|
|
if(btc_hh_cb.devices[i].dev_status == ESP_HIDH_CONN_STATE_CONNECTED){
|
|
BTA_HhClose(btc_hh_cb.devices[i].dev_handle);
|
|
}
|
|
}
|
|
btc_hh_cb.service_dereg_active = TRUE;
|
|
btc_hh_cb.status = BTC_HH_DISABLING;
|
|
BTA_HhDisable();
|
|
} while (0);
|
|
|
|
if (ret != ESP_HIDH_OK) {
|
|
esp_hidh_cb_param_t param;
|
|
param.deinit.status = ret;
|
|
btc_hh_cb_to_app(ESP_HIDH_DEINIT_EVT, ¶m);
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function btc_hh_connect
|
|
*
|
|
* Description connection initiated from the BTC thread context
|
|
*
|
|
* Returns void
|
|
*
|
|
******************************************************************************/
|
|
static void btc_hh_connect(btc_hidh_args_t *arg)
|
|
{
|
|
BTC_TRACE_API("%s", __func__);
|
|
esp_hidh_status_t ret = ESP_HIDH_OK;
|
|
btc_hh_added_device_t* added_dev = NULL;
|
|
btc_hh_device_t* dev = NULL;
|
|
esp_hidh_cb_param_t param;
|
|
|
|
do {
|
|
if (!is_hidh_init()) {
|
|
BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
|
|
ret = ESP_HIDH_NEED_INIT;
|
|
break;
|
|
}
|
|
|
|
if (btc_hh_cb.status == BTC_HH_DEV_CONNECTING) {
|
|
BTC_TRACE_ERROR("%s HH is connecting, ignore!", __func__);
|
|
ret = ESP_HIDH_BUSY;
|
|
break;
|
|
}
|
|
|
|
dev = btc_hh_find_dev_by_bda(arg->connect.bd_addr);
|
|
if (!dev && btc_hh_cb.device_num >= BTC_HH_MAX_HID) {
|
|
BTC_TRACE_ERROR("%s exceeded the maximum supported HID device number %d!", __func__, BTC_HH_MAX_HID);
|
|
ret = ESP_HIDH_ERR_NO_RES;
|
|
break;
|
|
} else if (dev && dev->dev_status == ESP_HIDH_CONN_STATE_CONNECTED) {
|
|
BTC_TRACE_WARNING("%s Device[%s] already connected", __func__,
|
|
bdaddr_to_string((const bt_bdaddr_t *)arg->connect.bd_addr, bdstr, sizeof(bdstr)));
|
|
param.open.conn_status = ESP_HIDH_CONN_STATE_CONNECTED;
|
|
break;
|
|
}
|
|
|
|
for (int i = 0; i < BTC_HH_MAX_ADDED_DEV; i++) {
|
|
if (memcmp(btc_hh_cb.added_devices[i].bd_addr, arg->connect.bd_addr, BD_ADDR_LEN) == 0) {
|
|
added_dev = &btc_hh_cb.added_devices[i];
|
|
BTC_TRACE_WARNING("%s Device[%s] already added, attr_mask = 0x%x", __func__,
|
|
bdaddr_to_string((const bt_bdaddr_t *)arg->connect.bd_addr, bdstr, sizeof(bdstr)),
|
|
added_dev->attr_mask);
|
|
}
|
|
}
|
|
|
|
if (added_dev != NULL) {
|
|
if (added_dev->dev_handle == BTA_HH_INVALID_HANDLE) {
|
|
// No space for more HID device now.
|
|
BTC_TRACE_ERROR("device added but addition failed");
|
|
memset(added_dev->bd_addr, 0, sizeof(added_dev->bd_addr));
|
|
ret = ESP_HIDH_ERR;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Not checking the NORMALLY_Connectible flags from sdp record, and anyways
|
|
sending this request from host, for subsequent user initiated connection. If the remote is
|
|
not in pagescan mode, we will do 2 retries to connect before giving up */
|
|
btc_hh_cb.status = BTC_HH_DEV_CONNECTING;
|
|
memcpy(btc_hh_cb.pending_conn_address, arg->connect.bd_addr, BD_ADDR_LEN);
|
|
BTA_HhOpen(arg->connect.bd_addr, BTA_HH_PROTO_RPT_MODE, (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT));
|
|
param.open.conn_status = ESP_HIDH_CONN_STATE_CONNECTING;
|
|
ret = ESP_HIDH_OK;
|
|
} while (0);
|
|
|
|
if (ret != ESP_HIDH_OK) {
|
|
param.open.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED;
|
|
}
|
|
param.open.status = ret;
|
|
param.open.handle = BTA_HH_INVALID_HANDLE;
|
|
memcpy(param.open.bd_addr, arg->connect.bd_addr, BD_ADDR_LEN);
|
|
param.open.is_orig = true;
|
|
btc_hh_cb_to_app(ESP_HIDH_OPEN_EVT, ¶m);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function btc_hh_disconnect
|
|
*
|
|
* Description disconnection initiated from the BTC thread context
|
|
*
|
|
* Returns void
|
|
*
|
|
******************************************************************************/
|
|
static void btc_hh_disconnect(btc_hidh_args_t *arg)
|
|
{
|
|
BTC_TRACE_API("%s", __func__);
|
|
esp_hidh_status_t ret = ESP_HIDH_OK;
|
|
btc_hh_device_t *p_dev;
|
|
esp_hidh_cb_param_t param;
|
|
|
|
do {
|
|
if (!is_hidh_init()) {
|
|
BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
|
|
ret = ESP_HIDH_NEED_INIT;
|
|
break;
|
|
}
|
|
p_dev = btc_hh_find_connected_dev_by_bda(arg->disconnect.bd_addr);
|
|
if (p_dev != NULL) {
|
|
BTA_HhClose(p_dev->dev_handle);
|
|
param.close.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTING;
|
|
param.close.handle = p_dev->dev_handle;
|
|
} else {
|
|
ret = ESP_HIDH_NO_CONNECTION;
|
|
BTC_TRACE_ERROR("%s Error: device not connected!", __func__);
|
|
}
|
|
|
|
} while (0);
|
|
|
|
if (ret != ESP_HIDH_OK) {
|
|
param.close.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED;
|
|
param.close.handle = BTA_HH_INVALID_HANDLE;
|
|
}
|
|
param.close.status = ret;
|
|
btc_hh_cb_to_app(ESP_HIDH_CLOSE_EVT, ¶m);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function btc_hh_virtual_unplug
|
|
*
|
|
* Description Virtual unplug initiated from the BTC thread context
|
|
* Special handling for HID mouse-
|
|
*
|
|
* Returns void
|
|
*
|
|
******************************************************************************/
|
|
static void btc_hh_virtual_unplug(btc_hidh_args_t *arg)
|
|
{
|
|
BTC_TRACE_API("%s", __func__);
|
|
esp_hidh_status_t ret = ESP_HIDH_OK;
|
|
btc_hh_device_t *p_dev;
|
|
esp_hidh_cb_param_t param;
|
|
|
|
do {
|
|
if (!is_hidh_init()) {
|
|
BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
|
|
ret = ESP_HIDH_NEED_INIT;
|
|
break;
|
|
}
|
|
p_dev = btc_hh_find_dev_by_bda(arg->unplug.bd_addr);
|
|
if ((p_dev != NULL) && (p_dev->dev_status == ESP_HIDH_CONN_STATE_CONNECTED) &&
|
|
(p_dev->attr_mask & HID_VIRTUAL_CABLE)) {
|
|
BTC_TRACE_DEBUG("%s: Sending BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG", __func__);
|
|
/* start the timer */
|
|
btc_hh_start_vup_timer(arg->unplug.bd_addr);
|
|
p_dev->local_vup = true;
|
|
BTA_HhSendCtrl(p_dev->dev_handle, BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG);
|
|
|
|
param.unplug.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTING;
|
|
param.unplug.handle = p_dev->dev_handle;
|
|
} else if ((p_dev != NULL) && (p_dev->dev_status == ESP_HIDH_CONN_STATE_CONNECTED)) {
|
|
BTC_TRACE_WARNING("%s: Virtual unplug not supported, disconnecting device", __func__);
|
|
/* start the timer */
|
|
btc_hh_start_vup_timer(arg->unplug.bd_addr);
|
|
p_dev->local_vup = true;
|
|
BTA_HhClose(p_dev->dev_handle);
|
|
|
|
param.unplug.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTING;
|
|
param.unplug.handle = p_dev->dev_handle;
|
|
} else {
|
|
BTC_TRACE_ERROR("%s: Error, device not opened, status = %d", __func__, btc_hh_cb.status);
|
|
ret = ESP_HIDH_NO_CONNECTION;
|
|
if (memcmp(btc_hh_cb.pending_conn_address, arg->unplug.bd_addr, BD_ADDR_LEN) == 0 &&
|
|
(btc_hh_cb.status == BTC_HH_DEV_CONNECTING)) {
|
|
btc_hh_cb.status = (BTC_HH_STATUS)BTC_HH_DEV_DISCONNECTED;
|
|
memset(btc_hh_cb.pending_conn_address, 0, BD_ADDR_LEN);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
if (ret != ESP_HIDH_OK) {
|
|
param.unplug.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED;
|
|
param.unplug.handle = BTA_HH_INVALID_HANDLE;
|
|
}
|
|
param.unplug.status = ret;
|
|
btc_hh_cb_to_app(ESP_HIDH_VC_UNPLUG_EVT, ¶m);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function btc_hh_set_info
|
|
*
|
|
* Description Set the HID device descriptor for the specified HID device.
|
|
*
|
|
* Returns void
|
|
*
|
|
******************************************************************************/
|
|
static void btc_hh_set_info(btc_hidh_args_t *arg)
|
|
{
|
|
BTC_TRACE_API("%s", __func__);
|
|
esp_hidh_status_t ret = ESP_HIDH_OK;
|
|
esp_hidh_cb_param_t param;
|
|
tBTA_HH_DEV_DSCP_INFO dscp_info;
|
|
|
|
BTC_TRACE_DEBUG("%s: sub_class = 0x%02x, app_id = %d, vendor_id = 0x%04x, "
|
|
"product_id = 0x%04x, version= 0x%04x",
|
|
__func__, arg->set_info.hid_info->sub_class, arg->set_info.hid_info->app_id,
|
|
arg->set_info.hid_info->vendor_id, arg->set_info.hid_info->product_id,
|
|
arg->set_info.hid_info->version);
|
|
do {
|
|
if (!is_hidh_init()) {
|
|
BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
|
|
ret = ESP_HIDH_NEED_INIT;
|
|
break;
|
|
}
|
|
|
|
memset(&dscp_info, 0, sizeof(dscp_info));
|
|
dscp_info.vendor_id = arg->set_info.hid_info->vendor_id;
|
|
dscp_info.product_id = arg->set_info.hid_info->product_id;
|
|
dscp_info.version = arg->set_info.hid_info->version;
|
|
dscp_info.ctry_code = arg->set_info.hid_info->ctry_code;
|
|
|
|
dscp_info.descriptor.dl_len = arg->set_info.hid_info->dl_len;
|
|
dscp_info.descriptor.dsc_list = (uint8_t *)osi_malloc(dscp_info.descriptor.dl_len);
|
|
if (dscp_info.descriptor.dsc_list == NULL) {
|
|
BTC_TRACE_ERROR("%s malloc dsc_list failed!", __func__);
|
|
ret = ESP_HIDH_ERR_NO_RES;
|
|
break;
|
|
}
|
|
memcpy(dscp_info.descriptor.dsc_list, arg->set_info.hid_info->dsc_list, dscp_info.descriptor.dl_len);
|
|
|
|
if (btc_hh_add_added_dev(arg->set_info.bd_addr, arg->set_info.hid_info->attr_mask)) {
|
|
btc_hh_cb.add_event = BTC_HH_SET_INFO_EVT;
|
|
BTA_HhAddDev(arg->set_info.bd_addr, arg->set_info.hid_info->attr_mask, arg->set_info.hid_info->sub_class,
|
|
arg->set_info.hid_info->app_id, dscp_info);
|
|
} else {
|
|
BTC_TRACE_ERROR("%s malloc dsc_list failed!", __func__);
|
|
ret = ESP_HIDH_ERR;
|
|
break;
|
|
}
|
|
} while(0);
|
|
utl_freebuf((void **)&dscp_info.descriptor.dsc_list);
|
|
|
|
if (ret != ESP_HIDH_OK) {
|
|
param.set_info.status = ret;
|
|
param.set_info.handle = BTA_HH_INVALID_HANDLE;
|
|
memcpy(param.set_info.bd_addr, arg->set_info.bd_addr, BD_ADDR_LEN);
|
|
btc_hh_cb_to_app(ESP_HIDH_SET_INFO_EVT, ¶m);
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function btc_hh_get_protocol
|
|
*
|
|
* Description Get the HID proto mode.
|
|
*
|
|
* Returns void
|
|
*
|
|
******************************************************************************/
|
|
static void btc_hh_get_protocol(btc_hidh_args_t *arg)
|
|
{
|
|
BTC_TRACE_API("%s", __func__);
|
|
esp_hidh_status_t ret = ESP_HIDH_OK;
|
|
esp_hidh_cb_param_t param;
|
|
btc_hh_device_t *p_dev;
|
|
|
|
do {
|
|
if (!is_hidh_init()) {
|
|
BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
|
|
ret = ESP_HIDH_NEED_INIT;
|
|
break;
|
|
}
|
|
p_dev = btc_hh_find_connected_dev_by_bda(arg->get_protocol.bd_addr);
|
|
if (p_dev == NULL) {
|
|
ret = ESP_HIDH_NO_CONNECTION;
|
|
BTC_TRACE_ERROR("%s Error: device not connected!", __func__);
|
|
break;
|
|
}
|
|
BTA_HhGetProtoMode(p_dev->dev_handle);
|
|
} while(0);
|
|
|
|
if (ret != ESP_HIDH_OK) {
|
|
param.get_proto.proto_mode = ESP_HIDH_UNSUPPORTED_MODE;
|
|
param.get_proto.handle = BTA_HH_INVALID_HANDLE;
|
|
param.get_proto.status = ret;
|
|
btc_hh_cb_to_app(ESP_HIDH_GET_PROTO_EVT, ¶m);
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function btc_hh_set_protocol
|
|
*
|
|
* Description Set the HID proto mode.
|
|
*
|
|
* Returns void
|
|
*
|
|
******************************************************************************/
|
|
static void btc_hh_set_protocol(btc_hidh_args_t *arg)
|
|
{
|
|
BTC_TRACE_API("%s", __func__);
|
|
esp_hidh_status_t ret = ESP_HIDH_OK;
|
|
esp_hidh_cb_param_t param;
|
|
btc_hh_device_t *p_dev;
|
|
|
|
do {
|
|
if (!is_hidh_init()) {
|
|
BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
|
|
ret = ESP_HIDH_NEED_INIT;
|
|
break;
|
|
}
|
|
p_dev = btc_hh_find_connected_dev_by_bda(arg->set_protocol.bd_addr);
|
|
if (p_dev == NULL) {
|
|
ret = ESP_HIDH_NO_CONNECTION;
|
|
BTC_TRACE_ERROR("%s Error: device not connected!", __func__);
|
|
break;
|
|
} else if (arg->set_protocol.protocol_mode != ESP_HIDH_REPORT_MODE && arg->set_protocol.protocol_mode != ESP_HIDH_BOOT_MODE) {
|
|
BTC_TRACE_ERROR("%s: Error, device proto_mode = %d.", __func__, arg->set_protocol.protocol_mode);
|
|
ret = ESP_HIDH_HS_INVALID_PARAM;
|
|
break;
|
|
} else {
|
|
BTA_HhSetProtoMode(p_dev->dev_handle, proto_mode_change_to_lower_layer(arg->set_protocol.protocol_mode));
|
|
}
|
|
} while (0);
|
|
|
|
if (ret != ESP_HIDH_OK) {
|
|
param.set_proto.handle = BTA_HH_INVALID_HANDLE;
|
|
param.set_proto.status = ret;
|
|
btc_hh_cb_to_app(ESP_HIDH_SET_PROTO_EVT, ¶m);
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function btc_hh_get_report
|
|
*
|
|
* Description Send a GET_REPORT to HID device.
|
|
*
|
|
* Returns void
|
|
*
|
|
******************************************************************************/
|
|
static void btc_hh_get_report(btc_hidh_args_t *arg)
|
|
{
|
|
BTC_TRACE_API("%s", __func__);
|
|
esp_hidh_status_t ret = ESP_HIDH_OK;
|
|
esp_hidh_cb_param_t param;
|
|
btc_hh_device_t *p_dev;
|
|
|
|
do {
|
|
if (!is_hidh_init()) {
|
|
BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
|
|
ret = ESP_HIDH_NEED_INIT;
|
|
break;
|
|
}
|
|
|
|
p_dev = btc_hh_find_connected_dev_by_bda(arg->get_report.bd_addr);
|
|
if (p_dev == NULL) {
|
|
ret = ESP_HIDH_NO_CONNECTION;
|
|
BTC_TRACE_ERROR("%s Error: device not connected!", __func__);
|
|
break;
|
|
} else if (((int)arg->get_report.report_type) <= BTA_HH_RPTT_RESRV ||
|
|
((int)arg->get_report.report_type) > BTA_HH_RPTT_FEATURE) {
|
|
BTC_TRACE_ERROR("%s Error: report type=%d not supported!", __func__, arg->get_report.report_type);
|
|
ret = ESP_HIDH_HS_INVALID_PARAM;
|
|
break;
|
|
} else {
|
|
BTA_HhGetReport(p_dev->dev_handle, arg->get_report.report_type, arg->get_report.report_id,
|
|
arg->get_report.buffer_size);
|
|
}
|
|
} while (0);
|
|
|
|
if (ret != ESP_HIDH_OK) {
|
|
param.get_rpt.handle = BTA_HH_INVALID_HANDLE;
|
|
param.get_rpt.status = ret;
|
|
param.get_rpt.len = 0;
|
|
param.get_rpt.data = NULL;
|
|
btc_hh_cb_to_app(ESP_HIDH_GET_RPT_EVT, ¶m);
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function create_pbuf
|
|
*
|
|
* Description Helper function to create p_buf for send_data or set_report
|
|
*
|
|
* Returns BT_HDR *
|
|
*
|
|
******************************************************************************/
|
|
static BT_HDR *create_pbuf(uint16_t len, uint8_t *data)
|
|
{
|
|
uint8_t *pbuf_data;
|
|
BT_HDR *p_buf = (BT_HDR *)osi_malloc(len + BTA_HH_MIN_OFFSET + sizeof(BT_HDR));
|
|
if (p_buf == NULL) {
|
|
BTC_TRACE_ERROR("%s failed!", __func__);
|
|
return NULL;
|
|
}
|
|
p_buf->len = len;
|
|
p_buf->offset = BTA_HH_MIN_OFFSET;
|
|
|
|
pbuf_data = (uint8_t *)(p_buf + 1) + p_buf->offset;
|
|
memcpy(pbuf_data, data, len);
|
|
|
|
return p_buf;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function btc_hh_set_report
|
|
*
|
|
* Description Send a SET_REPORT to HID device.
|
|
*
|
|
* Returns void
|
|
*
|
|
******************************************************************************/
|
|
static void btc_hh_set_report(btc_hidh_args_t *arg)
|
|
{
|
|
BTC_TRACE_API("%s", __func__);
|
|
esp_hidh_status_t ret = ESP_HIDH_OK;
|
|
esp_hidh_cb_param_t param;
|
|
btc_hh_device_t *p_dev;
|
|
|
|
do {
|
|
if (!is_hidh_init()) {
|
|
BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
|
|
ret = ESP_HIDH_NEED_INIT;
|
|
break;
|
|
}
|
|
|
|
p_dev = btc_hh_find_connected_dev_by_bda(arg->set_report.bd_addr);
|
|
if (p_dev == NULL) {
|
|
ret = ESP_HIDH_NO_CONNECTION;
|
|
BTC_TRACE_ERROR("%s Error: device not connected!", __func__);
|
|
break;
|
|
} else if (((int)arg->set_report.report_type) <= BTA_HH_RPTT_RESRV ||
|
|
((int)arg->set_report.report_type) > BTA_HH_RPTT_FEATURE) {
|
|
BTC_TRACE_ERROR("%s Error: report type=%d not supported!", __func__, arg->set_report.report_type);
|
|
ret = ESP_HIDH_HS_INVALID_PARAM;
|
|
break;
|
|
} else if (arg->set_report.report == NULL || arg->set_report.len == 0) {
|
|
BTC_TRACE_ERROR("%s Error: report is empty!", __func__);
|
|
ret = ESP_HIDH_HS_INVALID_PARAM;
|
|
break;
|
|
} else {
|
|
BT_HDR* p_buf = create_pbuf(arg->set_report.len, arg->set_report.report);
|
|
if (p_buf == NULL) {
|
|
ret = ESP_HIDH_ERR_NO_RES;
|
|
break;
|
|
}
|
|
BTA_HhSetReport(p_dev->dev_handle, arg->set_report.report_type, p_buf);
|
|
}
|
|
} while(0);
|
|
|
|
if (ret != ESP_HIDH_OK) {
|
|
param.set_rpt.handle = BTA_HH_INVALID_HANDLE;
|
|
param.set_rpt.status = ret;
|
|
btc_hh_cb_to_app(ESP_HIDH_SET_RPT_EVT, ¶m);
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Function btc_hh_send_data
|
|
*
|
|
* Description Send a SEND_DATA to HID device.
|
|
*
|
|
* Returns void
|
|
*
|
|
******************************************************************************/
|
|
static void btc_hh_send_data(btc_hidh_args_t *arg)
|
|
{
|
|
BTC_TRACE_API("%s", __func__);
|
|
esp_hidh_status_t ret = ESP_HIDH_OK;
|
|
esp_hidh_cb_param_t param;
|
|
btc_hh_device_t *p_dev;
|
|
|
|
do {
|
|
if (!is_hidh_init()) {
|
|
BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
|
|
ret = ESP_HIDH_NEED_INIT;
|
|
break;
|
|
}
|
|
|
|
p_dev = btc_hh_find_connected_dev_by_bda(arg->send_data.bd_addr);
|
|
if (p_dev == NULL) {
|
|
ret = ESP_HIDH_NO_CONNECTION;
|
|
BTC_TRACE_ERROR("%s Error: device not connected!", __func__);
|
|
break;
|
|
} else if (arg->send_data.data == NULL || arg->send_data.len == 0) {
|
|
BTC_TRACE_ERROR("%s Error: send data is empty!", __func__);
|
|
ret = ESP_HIDH_HS_INVALID_PARAM;
|
|
break;
|
|
} else {
|
|
BT_HDR *p_buf = create_pbuf(arg->send_data.len, arg->send_data.data);
|
|
if (p_buf == NULL) {
|
|
ret = ESP_HIDH_ERR_NO_RES;
|
|
break;
|
|
}
|
|
p_buf->layer_specific = BTA_HH_RPTT_OUTPUT;
|
|
BTA_HhSendData(p_dev->dev_handle, arg->send_data.bd_addr, p_buf);
|
|
}
|
|
} while(0);
|
|
|
|
if (ret != ESP_HIDH_OK) {
|
|
param.send_data.handle = BTA_HH_INVALID_HANDLE;
|
|
param.send_data.status = ret;
|
|
param.send_data.reason = 0;
|
|
btc_hh_cb_to_app(ESP_HIDH_DATA_EVT, ¶m);
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
**
|
|
** Function btc_hh_get_idle_time
|
|
**
|
|
** Description Get the HID idle time
|
|
**
|
|
** Returns void
|
|
**
|
|
*******************************************************************************/
|
|
static void btc_hh_get_idle_time(btc_hidh_args_t *arg)
|
|
{
|
|
BTC_TRACE_API("%s", __func__);
|
|
esp_hidh_status_t ret = ESP_HIDH_OK;
|
|
esp_hidh_cb_param_t param;
|
|
btc_hh_device_t *p_dev;
|
|
|
|
do {
|
|
if (!is_hidh_init()) {
|
|
BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
|
|
ret = ESP_HIDH_NEED_INIT;
|
|
break;
|
|
}
|
|
|
|
p_dev = btc_hh_find_connected_dev_by_bda(arg->get_idle.bd_addr);
|
|
if (p_dev == NULL) {
|
|
ret = ESP_HIDH_NO_CONNECTION;
|
|
BTC_TRACE_ERROR("%s Error: device not connected!", __func__);
|
|
break;
|
|
}
|
|
BTA_HhGetIdle(p_dev->dev_handle);
|
|
} while (0);
|
|
|
|
if (ret != ESP_HIDH_OK) {
|
|
param.get_idle.handle = BTA_HH_INVALID_HANDLE;
|
|
param.get_idle.status = ret;
|
|
param.get_idle.idle_rate = 0;
|
|
btc_hh_cb_to_app(ESP_HIDH_GET_IDLE_EVT, ¶m);
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
**
|
|
** Function btc_hh_set_idle_time
|
|
**
|
|
** Description Set the HID idle time
|
|
**
|
|
** Returns void
|
|
**
|
|
*******************************************************************************/
|
|
static void btc_hh_set_idle_time(btc_hidh_args_t *arg)
|
|
{
|
|
BTC_TRACE_API("%s", __func__);
|
|
esp_hidh_status_t ret = ESP_HIDH_OK;
|
|
esp_hidh_cb_param_t param;
|
|
btc_hh_device_t *p_dev;
|
|
|
|
do {
|
|
if (!is_hidh_init()) {
|
|
BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__);
|
|
ret = ESP_HIDH_NEED_INIT;
|
|
break;
|
|
}
|
|
|
|
p_dev = btc_hh_find_connected_dev_by_bda(arg->set_idle.bd_addr);
|
|
if (p_dev == NULL) {
|
|
ret = ESP_HIDH_NO_CONNECTION;
|
|
BTC_TRACE_ERROR("%s Error: device not connected!", __func__);
|
|
break;
|
|
}
|
|
BTA_HhSetIdle(p_dev->dev_handle, arg->set_idle.idle_time);
|
|
} while (0);
|
|
|
|
if (ret != ESP_HIDH_OK) {
|
|
param.set_idle.handle = BTA_HH_INVALID_HANDLE;
|
|
param.set_idle.status = ret;
|
|
btc_hh_cb_to_app(ESP_HIDH_SET_IDLE_EVT, ¶m);
|
|
}
|
|
}
|
|
|
|
static void btc_hh_call_arg_deep_free(btc_msg_t *msg)
|
|
{
|
|
btc_hidh_args_t *arg = (btc_hidh_args_t *)msg->arg;
|
|
|
|
switch (msg->act) {
|
|
case BTC_HH_SET_INFO_EVT:
|
|
utl_freebuf((void **)&arg->set_info.hid_info);
|
|
break;
|
|
case BTC_HH_SET_REPORT_EVT:
|
|
utl_freebuf((void **)&arg->set_report.report);
|
|
break;
|
|
case BTC_HH_SEND_DATA_EVT:
|
|
utl_freebuf((void **)&arg->send_data.data);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void btc_hh_call_handler(btc_msg_t *msg)
|
|
{
|
|
btc_hidh_args_t *arg = (btc_hidh_args_t *)(msg->arg);
|
|
switch (msg->act) {
|
|
case BTC_HH_INIT_EVT:
|
|
btc_hh_init();
|
|
break;
|
|
case BTC_HH_CONNECT_EVT:
|
|
btc_hh_connect(arg);
|
|
break;
|
|
case BTC_HH_DISCONNECT_EVT:
|
|
btc_hh_disconnect(arg);
|
|
break;
|
|
case BTC_HH_UNPLUG_EVT:
|
|
btc_hh_virtual_unplug(arg);
|
|
break;
|
|
case BTC_HH_SET_INFO_EVT:
|
|
btc_hh_set_info(arg);
|
|
break;
|
|
case BTC_HH_GET_PROTO_EVT:
|
|
btc_hh_get_protocol(arg);
|
|
break;
|
|
case BTC_HH_SET_PROTO_EVT:
|
|
btc_hh_set_protocol(arg);
|
|
break;
|
|
case BTC_HH_GET_IDLE_EVT:
|
|
btc_hh_get_idle_time(arg);
|
|
break;
|
|
case BTC_HH_SET_IDLE_EVT:
|
|
btc_hh_set_idle_time(arg);
|
|
break;
|
|
case BTC_HH_GET_REPORT_EVT:
|
|
btc_hh_get_report(arg);
|
|
break;
|
|
case BTC_HH_SET_REPORT_EVT:
|
|
btc_hh_set_report(arg);
|
|
break;
|
|
case BTC_HH_SEND_DATA_EVT:
|
|
btc_hh_send_data(arg);
|
|
break;
|
|
case BTC_HH_DEINIT_EVT:
|
|
btc_hh_deinit();
|
|
break;
|
|
default:
|
|
BTC_TRACE_WARNING("unknown hidh action %d", msg->act);
|
|
break;
|
|
}
|
|
btc_hh_call_arg_deep_free(msg);
|
|
}
|
|
|
|
void btc_hh_cb_arg_deep_free(btc_msg_t *msg)
|
|
{
|
|
tBTA_HH *arg = (tBTA_HH *)msg->arg;
|
|
|
|
switch (msg->act) {
|
|
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;
|
|
}
|
|
}
|
|
|
|
bool btc_hh_copy_hid_info(tBTA_HH_DEV_DSCP_INFO *dest, tBTA_HH_DEV_DSCP_INFO *src)
|
|
{
|
|
dest->descriptor.dl_len = 0;
|
|
if (src->descriptor.dl_len > 0) {
|
|
dest->descriptor.dsc_list = (uint8_t *)osi_malloc(src->descriptor.dl_len);
|
|
}
|
|
if (dest->descriptor.dsc_list) {
|
|
memcpy(dest->descriptor.dsc_list, src->descriptor.dsc_list, src->descriptor.dl_len);
|
|
dest->descriptor.dl_len = src->descriptor.dl_len;
|
|
}
|
|
dest->vendor_id = src->vendor_id;
|
|
dest->product_id = src->product_id;
|
|
dest->version = src->version;
|
|
dest->ctry_code = src->ctry_code;
|
|
dest->ssr_max_latency = src->ssr_max_latency;
|
|
dest->ssr_min_tout = src->ssr_min_tout;
|
|
return true;
|
|
}
|
|
|
|
bool btc_hh_cb_copy_hid_info(esp_hidh_cb_param_t *param, tBTA_HH_DEV_DSCP_INFO *src)
|
|
{
|
|
param->dscp.dl_len = 0;
|
|
if (src->descriptor.dl_len > 0) {
|
|
param->dscp.dsc_list = (uint8_t *)osi_malloc(src->descriptor.dl_len);
|
|
}
|
|
if (param->dscp.dsc_list) {
|
|
memcpy(param->dscp.dsc_list, src->descriptor.dsc_list, src->descriptor.dl_len);
|
|
param->dscp.dl_len = src->descriptor.dl_len;
|
|
}
|
|
param->dscp.vendor_id = src->vendor_id;
|
|
param->dscp.product_id = src->product_id;
|
|
param->dscp.version = src->version;
|
|
param->dscp.ctry_code = src->ctry_code;
|
|
param->dscp.ssr_max_latency = src->ssr_max_latency;
|
|
param->dscp.ssr_min_tout = src->ssr_min_tout;
|
|
return true;
|
|
}
|
|
|
|
void btc_hh_cb_handler(btc_msg_t *msg)
|
|
{
|
|
esp_hidh_cb_param_t param = {0};
|
|
tBTA_HH *p_data = (tBTA_HH *)msg->arg;
|
|
btc_hh_device_t *p_dev = NULL;
|
|
int len, i;
|
|
BTC_TRACE_DEBUG("%s: event=%s dereg = %d", __func__, dump_hh_event(msg->act), btc_hh_cb.service_dereg_active);
|
|
switch (msg->act) {
|
|
case BTA_HH_ENABLE_EVT:
|
|
if (p_data->status == BTA_HH_OK) {
|
|
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();
|
|
} else {
|
|
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;
|
|
btc_hh_cb_to_app(ESP_HIDH_INIT_EVT, ¶m);
|
|
break;
|
|
case BTA_HH_DISABLE_EVT:
|
|
btc_hh_cb.status = BTC_HH_DISABLED;
|
|
if (btc_hh_cb.service_dereg_active) {
|
|
BTIF_TRACE_DEBUG("BTA_HH_DISABLE_EVT: enabling HID Device service");
|
|
// btif_hd_service_registration();
|
|
btc_hh_cb.service_dereg_active = FALSE;
|
|
}
|
|
if (p_data->status == BTA_HH_OK) {
|
|
// Clear the control block
|
|
for (uint8_t i = 0; i < BTC_HH_MAX_HID; i++) {
|
|
if (btc_hh_cb.devices[i].vup_timer) {
|
|
osi_alarm_free(btc_hh_cb.devices[i].vup_timer);
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
} else {
|
|
BTC_TRACE_ERROR("Error, HH disabling failed, status = %d", p_data->status);
|
|
}
|
|
param.deinit.status = p_data->status;
|
|
btc_hh_cb_to_app(ESP_HIDH_DEINIT_EVT, ¶m);
|
|
break;
|
|
case BTA_HH_OPEN_EVT:
|
|
BTC_TRACE_DEBUG("handle=%d, status =%d", p_data->conn.handle, p_data->conn.status);
|
|
memset(btc_hh_cb.pending_conn_address, 0, BD_ADDR_LEN);
|
|
if (p_data->conn.status == BTA_HH_OK) {
|
|
p_dev = btc_hh_find_connected_dev_by_handle(p_data->conn.handle);
|
|
if (p_dev == NULL) {
|
|
BTC_TRACE_ERROR("Error, cannot find device with handle %d", p_data->conn.handle);
|
|
btc_hh_cb.status = (BTC_HH_STATUS)BTC_HH_DEV_DISCONNECTED;
|
|
// The connect request must come from device side and exceeded the
|
|
// connected HID device number.
|
|
BTA_HhClose(p_data->conn.handle);
|
|
|
|
param.open.status = ESP_HIDH_ERR;
|
|
param.open.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED;
|
|
} else {
|
|
BTC_TRACE_DEBUG("Found device...Getting dscp info for handle "
|
|
"... %d",
|
|
p_data->conn.handle);
|
|
memcpy(p_dev->bd_addr, p_data->conn.bda, BD_ADDR_LEN);
|
|
btc_hh_cb.status = (BTC_HH_STATUS)BTC_HH_DEV_CONNECTED;
|
|
// Send set_idle if the peer_device is a keyboard [boblane]
|
|
// 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;
|
|
|
|
param.open.status = ESP_HIDH_OK;
|
|
param.open.conn_status = ESP_HIDH_CONN_STATE_CONNECTED;
|
|
}
|
|
} else {
|
|
p_dev = btc_hh_find_dev_by_bda(p_data->conn.bda);
|
|
if (p_dev != NULL) {
|
|
btc_hh_stop_vup_timer(p_dev->bd_addr);
|
|
p_dev->dev_status = ESP_HIDH_CONN_STATE_DISCONNECTED;
|
|
}
|
|
btc_hh_cb.status = (BTC_HH_STATUS)BTC_HH_DEV_DISCONNECTED;
|
|
|
|
param.open.status = p_data->conn.status;
|
|
param.open.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED;
|
|
}
|
|
param.open.handle = p_data->conn.handle;
|
|
param.open.is_orig = p_data->conn.is_orig;
|
|
memcpy(param.open.bd_addr, p_data->conn.bda, BD_ADDR_LEN);
|
|
btc_hh_cb_to_app(ESP_HIDH_OPEN_EVT, ¶m);
|
|
break;
|
|
case BTA_HH_GET_DSCP_EVT:
|
|
len = p_data->dscp_info.descriptor.dl_len;
|
|
BTC_TRACE_DEBUG("len = %d", len);
|
|
do {
|
|
param.dscp.status = ESP_HIDH_OK;
|
|
param.dscp.handle = BTA_HH_INVALID_HANDLE;
|
|
param.dscp.added = false;
|
|
p_dev = btc_hh_cb.p_curr_dev;
|
|
if (p_dev == NULL) {
|
|
BTC_TRACE_ERROR("No HID device is currently connected");
|
|
param.dscp.status = ESP_HIDH_NO_CONNECTION;
|
|
break;
|
|
}
|
|
|
|
if (btc_hh_add_added_dev(p_dev->bd_addr, p_dev->attr_mask)) {
|
|
tBTA_HH_DEV_DSCP_INFO dscp_info;
|
|
bt_status_t ret;
|
|
btc_hh_copy_hid_info(&dscp_info, &p_data->dscp_info);
|
|
btc_hh_cb.add_event = BTC_HH_CONNECT_EVT;
|
|
BTA_HhAddDev(p_dev->bd_addr, p_dev->attr_mask, p_dev->sub_class, p_dev->app_id, dscp_info);
|
|
// write hid info to nvs
|
|
ret = btc_storage_add_hid_device_info((bt_bdaddr_t *)p_dev->bd_addr, p_dev->attr_mask, p_dev->sub_class, p_dev->app_id,
|
|
p_data->dscp_info.vendor_id, p_data->dscp_info.product_id,
|
|
p_data->dscp_info.version, p_data->dscp_info.ctry_code,
|
|
p_data->dscp_info.ssr_max_latency, p_data->dscp_info.ssr_min_tout,
|
|
len, p_data->dscp_info.descriptor.dsc_list);
|
|
|
|
if (ret != BT_STATUS_SUCCESS) {
|
|
BTC_TRACE_ERROR("write hid info to nvs failed!");
|
|
}
|
|
// Free buffer created for dscp_info;
|
|
if (dscp_info.descriptor.dl_len > 0 && dscp_info.descriptor.dsc_list != NULL) {
|
|
utl_freebuf((void **)&dscp_info.descriptor.dsc_list);
|
|
dscp_info.descriptor.dl_len = 0;
|
|
}
|
|
} else {
|
|
// Device already added.
|
|
BTC_TRACE_WARNING("%s: Device already added ", __func__);
|
|
param.dscp.added = true;
|
|
}
|
|
btc_hh_cb_copy_hid_info(¶m, &p_data->dscp_info);
|
|
param.dscp.handle = p_dev->dev_handle;
|
|
} while(0);
|
|
btc_hh_cb_to_app(ESP_HIDH_GET_DSCP_EVT, ¶m);
|
|
if (param.dscp.dl_len > 0 && param.dscp.dsc_list != NULL) {
|
|
utl_freebuf((void **)¶m.dscp.dsc_list);
|
|
param.dscp.dl_len = 0;
|
|
}
|
|
break;
|
|
case BTA_HH_CLOSE_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);
|
|
if (p_dev != NULL) {
|
|
BTC_TRACE_DEBUG("uhid local_vup=%d", p_dev->local_vup);
|
|
btc_hh_stop_vup_timer(p_dev->bd_addr);
|
|
/* If this is a locally initiated VUP, remove the bond as ACL got
|
|
* disconnected while VUP being processed.
|
|
*/
|
|
if (p_dev->local_vup) {
|
|
p_dev->local_vup = false;
|
|
BTA_DmRemoveDevice(p_dev->bd_addr, BT_TRANSPORT_BR_EDR);
|
|
}
|
|
|
|
btc_hh_cb.status = (BTC_HH_STATUS)BTC_HH_DEV_DISCONNECTED;
|
|
p_dev->dev_status = ESP_HIDH_CONN_STATE_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);
|
|
param.close.status = ESP_HIDH_NO_CONNECTION;
|
|
}
|
|
param.close.handle = p_data->dev_status.handle;
|
|
param.close.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED;
|
|
btc_hh_cb_to_app(ESP_HIDH_CLOSE_EVT, ¶m);
|
|
break;
|
|
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;
|
|
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_TRACE_DEBUG("%s---Sending connection state change", __func__);
|
|
param.close.status = ESP_HIDH_OK;
|
|
param.close.handle = p_data->dev_status.handle;
|
|
param.close.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED;
|
|
btc_hh_cb_to_app(ESP_HIDH_CLOSE_EVT, ¶m);
|
|
BTC_TRACE_DEBUG("%s---Removing HID bond", __func__);
|
|
/* If it is locally initiated VUP or remote device has its major COD as
|
|
Peripheral removed the bond.*/
|
|
// [boblane]
|
|
if (p_dev->local_vup) {
|
|
p_dev->local_vup = false;
|
|
BTA_DmRemoveDevice(p_dev->bd_addr, BT_TRANSPORT_BR_EDR);
|
|
} else {
|
|
btc_hh_remove_device(p_dev->bd_addr);
|
|
}
|
|
param.unplug.status = p_data->dev_status.status;
|
|
} else {
|
|
BTC_TRACE_ERROR("Error: cannot find device with handle %d", p_data->dev_status.handle);
|
|
param.unplug.status = ESP_HIDH_NO_CONNECTION;
|
|
}
|
|
param.unplug.handle = p_data->dev_status.handle;
|
|
param.unplug.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED;
|
|
btc_hh_cb_to_app(ESP_HIDH_VC_UNPLUG_EVT, ¶m);
|
|
break;
|
|
case BTA_HH_DATA_EVT:
|
|
BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->send_data.status,
|
|
p_data->send_data.handle);
|
|
param.send_data.handle = p_data->send_data.handle;
|
|
param.send_data.status = p_data->send_data.status;
|
|
param.send_data.reason = p_data->send_data.reason;
|
|
btc_hh_cb_to_app(ESP_HIDH_DATA_EVT, ¶m);
|
|
break;
|
|
case BTA_HH_GET_PROTO_EVT:
|
|
BTC_TRACE_DEBUG("status = %d, handle = %d, proto = [%d], %s", p_data->hs_data.status,
|
|
p_data->hs_data.handle, p_data->hs_data.rsp_data.proto_mode,
|
|
(p_data->hs_data.rsp_data.proto_mode == BTA_HH_PROTO_RPT_MODE)
|
|
? "Report Mode"
|
|
: (p_data->hs_data.rsp_data.proto_mode == BTA_HH_PROTO_BOOT_MODE) ? "Boot Mode"
|
|
: "Unsupported");
|
|
param.get_proto.proto_mode = proto_mode_change_to_upper_layer(p_data->hs_data.rsp_data.proto_mode);
|
|
param.get_proto.handle = p_data->hs_data.handle;
|
|
param.get_proto.status = p_data->hs_data.status;
|
|
btc_hh_cb_to_app(ESP_HIDH_GET_PROTO_EVT, ¶m);
|
|
break;
|
|
case BTA_HH_SET_PROTO_EVT:
|
|
BTIF_TRACE_DEBUG("status = %d, handle = %d", p_data->dev_status.status,
|
|
p_data->dev_status.handle);
|
|
param.set_proto.handle = p_data->dev_status.handle;
|
|
param.set_proto.status = p_data->dev_status.status;
|
|
btc_hh_cb_to_app(ESP_HIDH_SET_PROTO_EVT, ¶m);
|
|
break;
|
|
case BTA_HH_GET_RPT_EVT: {
|
|
BT_HDR *hdr = p_data->hs_data.rsp_data.p_rpt_data;
|
|
uint8_t *data = NULL;
|
|
uint16_t len = 0;
|
|
BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->hs_data.status, p_data->hs_data.handle);
|
|
/* p_rpt_data is NULL in HANDSHAKE response case */
|
|
if (hdr) {
|
|
data = (uint8_t *)(hdr + 1) + hdr->offset;
|
|
len = hdr->len;
|
|
}
|
|
param.get_rpt.handle = p_data->hs_data.handle;
|
|
param.get_rpt.status = p_data->hs_data.status;
|
|
param.get_rpt.len = len;
|
|
param.get_rpt.data = data;
|
|
btc_hh_cb_to_app(ESP_HIDH_GET_RPT_EVT, ¶m);
|
|
break;
|
|
}
|
|
case BTA_HH_SET_RPT_EVT:
|
|
BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->dev_status.status,
|
|
p_data->dev_status.handle);
|
|
param.set_rpt.handle = p_data->dev_status.handle;
|
|
param.set_rpt.status = p_data->dev_status.status;
|
|
btc_hh_cb_to_app(ESP_HIDH_SET_RPT_EVT, ¶m);
|
|
break;
|
|
case BTA_HH_GET_IDLE_EVT:
|
|
BTC_TRACE_DEBUG("handle = %d, status = %d, rate = %d", p_data->hs_data.handle, p_data->hs_data.status,
|
|
p_data->hs_data.rsp_data.idle_rate);
|
|
param.get_idle.handle = p_data->hs_data.handle;
|
|
param.get_idle.status = p_data->hs_data.status;
|
|
param.get_idle.idle_rate = p_data->hs_data.rsp_data.idle_rate;
|
|
btc_hh_cb_to_app(ESP_HIDH_GET_IDLE_EVT, ¶m);
|
|
break;
|
|
case BTA_HH_SET_IDLE_EVT:
|
|
BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->dev_status.status, p_data->dev_status.handle);
|
|
param.set_idle.handle = p_data->dev_status.handle;
|
|
param.set_idle.status = p_data->dev_status.status;
|
|
btc_hh_cb_to_app(BTA_HH_SET_IDLE_EVT, ¶m);
|
|
break;
|
|
case BTA_HH_ADD_DEV_EVT:
|
|
BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->dev_info.status, p_data->dev_info.handle);
|
|
for (uint8_t i = 0; i < BTC_HH_MAX_ADDED_DEV; i++) {
|
|
if (memcmp(btc_hh_cb.added_devices[i].bd_addr, p_data->dev_info.bda, BD_ADDR_LEN) == 0) {
|
|
if (p_data->dev_info.status == BTA_HH_OK) {
|
|
btc_hh_cb.added_devices[i].dev_handle = p_data->dev_info.handle;
|
|
} else {
|
|
memset(btc_hh_cb.added_devices[i].bd_addr, 0, BD_ADDR_LEN);
|
|
btc_hh_cb.added_devices[i].dev_handle = BTA_HH_INVALID_HANDLE;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (btc_hh_cb.add_event == BTC_HH_SET_INFO_EVT) {
|
|
param.set_info.handle = p_data->dev_info.handle;
|
|
param.set_info.status = p_data->dev_info.status;
|
|
memcpy(param.set_info.bd_addr, p_data->dev_info.bda, BD_ADDR_LEN);
|
|
btc_hh_cb_to_app(ESP_HIDH_SET_INFO_EVT, ¶m);
|
|
} else {
|
|
param.add_dev.handle = p_data->dev_info.handle;
|
|
param.add_dev.status = p_data->dev_info.status;
|
|
memcpy(param.add_dev.bd_addr, p_data->dev_info.bda, BD_ADDR_LEN);
|
|
btc_hh_cb_to_app(ESP_HIDH_ADD_DEV_EVT, ¶m);
|
|
}
|
|
break;
|
|
case BTA_HH_RMV_DEV_EVT:
|
|
BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->dev_info.status, p_data->dev_info.handle);
|
|
param.rmv_dev.handle = p_data->dev_info.status;
|
|
param.rmv_dev.status = p_data->dev_info.handle;
|
|
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:
|
|
BTC_TRACE_WARNING("%s: Unhandled event: %d", __func__, msg->act);
|
|
break;
|
|
}
|
|
btc_hh_cb_arg_deep_free(msg);
|
|
}
|
|
|
|
void btc_hh_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
|
{
|
|
btc_hidh_args_t *dst = (btc_hidh_args_t *)p_dest;
|
|
btc_hidh_args_t *src = (btc_hidh_args_t *)p_src;
|
|
|
|
switch (msg->act) {
|
|
case BTC_HH_SET_INFO_EVT:
|
|
dst->set_info.hid_info = (esp_hidh_hid_info_t *)osi_malloc(sizeof(esp_hidh_hid_info_t));
|
|
if (dst->set_info.hid_info) {
|
|
memcpy(dst->set_info.hid_info, src->set_info.hid_info, sizeof(esp_hidh_hid_info_t));
|
|
} else {
|
|
BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act);
|
|
}
|
|
break;
|
|
case BTC_HH_SET_REPORT_EVT:
|
|
dst->set_report.report = (uint8_t *)osi_malloc(src->set_report.len);
|
|
if (dst->set_report.report) {
|
|
memcpy(dst->set_report.report, src->set_report.report, src->set_report.len);
|
|
} else {
|
|
BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act);
|
|
}
|
|
break;
|
|
case BTC_HH_SEND_DATA_EVT:
|
|
dst->send_data.data = (uint8_t *)osi_malloc(src->send_data.len);
|
|
if (dst->send_data.data) {
|
|
memcpy(dst->send_data.data, src->send_data.data, src->send_data.len);
|
|
} else {
|
|
BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
#endif // HID_HOST_INCLUDED == TRUE
|