mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-05 05:34:32 +02:00
Merge branch 'feature/add_bt_hid_host_support_dev' into 'master'
Feature/add bt hid host btc layer Closes IDFGH-3329, IDFGH-1104, IDFGH-3724, IDFGH-4383, and IDFGH-5428 See merge request espressif/esp-idf!12016
This commit is contained in:
@@ -55,6 +55,7 @@ if(CONFIG_BT_ENABLED)
|
||||
host/bluedroid/bta/gatt/include
|
||||
host/bluedroid/bta/hf_ag/include
|
||||
host/bluedroid/bta/hf_client/include
|
||||
host/bluedroid/bta/hd/include
|
||||
host/bluedroid/bta/hh/include
|
||||
host/bluedroid/bta/jv/include
|
||||
host/bluedroid/bta/sdp/include
|
||||
@@ -66,12 +67,12 @@ if(CONFIG_BT_ENABLED)
|
||||
host/bluedroid/external/sbc/plc/include
|
||||
host/bluedroid/btc/profile/esp/include
|
||||
host/bluedroid/btc/profile/std/a2dp/include
|
||||
host/bluedroid/btc/profile/std/hid/include
|
||||
host/bluedroid/btc/profile/std/include
|
||||
host/bluedroid/btc/include
|
||||
host/bluedroid/stack/btm/include
|
||||
host/bluedroid/stack/gap/include
|
||||
host/bluedroid/stack/gatt/include
|
||||
host/bluedroid/stack/hid/include
|
||||
host/bluedroid/stack/l2cap/include
|
||||
host/bluedroid/stack/sdp/include
|
||||
host/bluedroid/stack/smp/include
|
||||
@@ -94,6 +95,8 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/bluedroid/api/esp_gatt_common_api.c"
|
||||
"host/bluedroid/api/esp_gattc_api.c"
|
||||
"host/bluedroid/api/esp_gatts_api.c"
|
||||
"host/bluedroid/api/esp_hidd_api.c"
|
||||
"host/bluedroid/api/esp_hidh_api.c"
|
||||
"host/bluedroid/api/esp_hf_ag_api.c"
|
||||
"host/bluedroid/api/esp_hf_client_api.c"
|
||||
"host/bluedroid/api/esp_spp_api.c"
|
||||
@@ -128,6 +131,9 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/bluedroid/bta/gatt/bta_gatts_co.c"
|
||||
"host/bluedroid/bta/gatt/bta_gatts_main.c"
|
||||
"host/bluedroid/bta/gatt/bta_gatts_utils.c"
|
||||
"host/bluedroid/bta/hd/bta_hd_api.c"
|
||||
"host/bluedroid/bta/hd/bta_hd_act.c"
|
||||
"host/bluedroid/bta/hd/bta_hd_main.c"
|
||||
"host/bluedroid/bta/hh/bta_hh_act.c"
|
||||
"host/bluedroid/bta/hh/bta_hh_api.c"
|
||||
"host/bluedroid/bta/hh/bta_hh_cfg.c"
|
||||
@@ -184,8 +190,9 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c"
|
||||
"host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c"
|
||||
"host/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c"
|
||||
"host/bluedroid/btc/profile/std/hid/hidh_api.c"
|
||||
"host/bluedroid/btc/profile/std/hid/hidh_conn.c"
|
||||
"host/bluedroid/btc/profile/std/hid/btc_hd.c"
|
||||
"host/bluedroid/btc/profile/std/hid/btc_hh.c"
|
||||
"host/bluedroid/btc/profile/std/hid/bta_hh_co.c"
|
||||
"host/bluedroid/btc/profile/std/gap/btc_gap_ble.c"
|
||||
"host/bluedroid/btc/profile/std/gap/btc_gap_bt.c"
|
||||
"host/bluedroid/btc/profile/std/gap/bta_gap_bt_co.c"
|
||||
@@ -251,6 +258,10 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/bluedroid/stack/avrc/avrc_pars_tg.c"
|
||||
"host/bluedroid/stack/avrc/avrc_sdp.c"
|
||||
"host/bluedroid/stack/avrc/avrc_utils.c"
|
||||
"host/bluedroid/stack/hid/hidd_api.c"
|
||||
"host/bluedroid/stack/hid/hidd_conn.c"
|
||||
"host/bluedroid/stack/hid/hidh_api.c"
|
||||
"host/bluedroid/stack/hid/hidh_conn.c"
|
||||
"host/bluedroid/stack/btm/btm_acl.c"
|
||||
"host/bluedroid/stack/btm/btm_ble.c"
|
||||
"host/bluedroid/stack/btm/btm_ble_addr.c"
|
||||
|
@@ -53,6 +53,12 @@
|
||||
#if BTC_HF_CLIENT_INCLUDED
|
||||
#include "btc_hf_client.h"
|
||||
#endif /* #if BTC_HF_CLIENT_INCLUDED */
|
||||
#if BTC_HD_INCLUDED == TRUE
|
||||
#include "btc_hd.h"
|
||||
#endif /* BTC_HD_INCLUDED */
|
||||
#if BTC_HH_INCLUDED == TRUE
|
||||
#include "btc_hh.h"
|
||||
#endif /* BTC_HH_INCLUDED */
|
||||
#endif /* #if CLASSIC_BT_INCLUDED */
|
||||
#endif
|
||||
|
||||
@@ -120,6 +126,12 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = {
|
||||
#if BTC_HF_CLIENT_INCLUDED
|
||||
[BTC_PID_HF_CLIENT] = {btc_hf_client_call_handler, btc_hf_client_cb_handler},
|
||||
#endif /* #if BTC_HF_CLIENT_INCLUDED */
|
||||
#if BTC_HD_INCLUDED
|
||||
[BTC_PID_HD] = {btc_hd_call_handler, btc_hd_cb_handler },
|
||||
#endif
|
||||
#if BTC_HH_INCLUDED
|
||||
[BTC_PID_HH] = {btc_hh_call_handler, btc_hh_cb_handler },
|
||||
#endif
|
||||
#endif /* #if CLASSIC_BT_INCLUDED */
|
||||
#endif
|
||||
#if CONFIG_BLE_MESH
|
||||
|
@@ -65,6 +65,8 @@ typedef enum {
|
||||
BTC_PID_AVRC_CT,
|
||||
BTC_PID_AVRC_TG,
|
||||
BTC_PID_SPP,
|
||||
BTC_PID_HD,
|
||||
BTC_PID_HH,
|
||||
#if (BTC_HF_INCLUDED == TRUE)
|
||||
BTC_PID_HF,
|
||||
#endif /* BTC_HF_INCLUDED */
|
||||
@@ -99,6 +101,10 @@ typedef struct {
|
||||
|
||||
typedef void (* btc_arg_deep_copy_t)(btc_msg_t *msg, void *dst, void *src);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* transfer an message to another module in the different task.
|
||||
* @param msg message
|
||||
@@ -124,4 +130,8 @@ void btc_deinit(void);
|
||||
bool btc_check_queue_is_congest(void);
|
||||
int get_btc_work_queue_size(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __BTC_TASK_H__ */
|
||||
|
@@ -46,6 +46,7 @@ COMPONENT_PRIV_INCLUDEDIRS += host/bluedroid/bta/include \
|
||||
host/bluedroid/bta/hf_client/include \
|
||||
host/bluedroid/bta/dm/include \
|
||||
host/bluedroid/bta/gatt/include \
|
||||
host/bluedroid/bta/hd/include \
|
||||
host/bluedroid/bta/hh/include \
|
||||
host/bluedroid/bta/jv/include \
|
||||
host/bluedroid/bta/sdp/include \
|
||||
@@ -70,6 +71,7 @@ COMPONENT_PRIV_INCLUDEDIRS += host/bluedroid/bta/include \
|
||||
host/bluedroid/stack/gap/include \
|
||||
host/bluedroid/stack/gatt/include \
|
||||
host/bluedroid/stack/hcic/include \
|
||||
host/bluedroid/stack/hid/include \
|
||||
host/bluedroid/stack/l2cap/include \
|
||||
host/bluedroid/stack/sdp/include \
|
||||
host/bluedroid/stack/smp/include \
|
||||
@@ -86,6 +88,7 @@ COMPONENT_ADD_INCLUDEDIRS += host/bluedroid/api/include/api \
|
||||
|
||||
COMPONENT_SRCDIRS += host/bluedroid/bta/dm \
|
||||
host/bluedroid/bta/gatt \
|
||||
host/bluedroid/bta/hd \
|
||||
host/bluedroid/bta/hh \
|
||||
host/bluedroid/bta/sdp \
|
||||
host/bluedroid/bta/av \
|
||||
@@ -118,6 +121,7 @@ COMPONENT_SRCDIRS += host/bluedroid/bta/dm \
|
||||
host/bluedroid/stack/gap \
|
||||
host/bluedroid/stack/gatt \
|
||||
host/bluedroid/stack/hcic \
|
||||
host/bluedroid/stack/hid \
|
||||
host/bluedroid/stack/include \
|
||||
host/bluedroid/stack/l2cap \
|
||||
host/bluedroid/stack/sdp \
|
||||
|
@@ -99,13 +99,27 @@ config BT_HFP_WBS_ENABLE
|
||||
This enables Wide Band Speech. Should disable it when SCO data path is PCM.
|
||||
Otherwise there will be no data transmited via GPIOs.
|
||||
|
||||
config BT_HID_HOST_ENABLED
|
||||
bool "Classic BT HID Host"
|
||||
config BT_HID_ENABLED
|
||||
bool "Classic BT HID"
|
||||
depends on BT_CLASSIC_ENABLED
|
||||
default n
|
||||
help
|
||||
This enables the BT HID Host
|
||||
|
||||
choice BT_HID_ROLE
|
||||
prompt "Profile Role configuration"
|
||||
depends on BT_HID_ENABLED
|
||||
config BT_HID_HOST_ENABLED
|
||||
bool "Classic BT HID Host"
|
||||
help
|
||||
This enables the BT HID Host
|
||||
|
||||
config BT_HID_DEVICE_ENABLED
|
||||
bool "Classic BT HID Device"
|
||||
help
|
||||
This enables the BT HID Device
|
||||
endchoice
|
||||
|
||||
config BT_SSP_ENABLED
|
||||
bool "Secure Simple Pairing"
|
||||
depends on BT_CLASSIC_ENABLED
|
||||
|
176
components/bt/host/bluedroid/api/esp_hidd_api.c
Normal file
176
components/bt/host/bluedroid/api/esp_hidd_api.c
Normal file
@@ -0,0 +1,176 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 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.
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_bt_main.h"
|
||||
#include "btc/btc_manage.h"
|
||||
#include "btc_hd.h"
|
||||
#include "esp_hidd_api.h"
|
||||
|
||||
#if (defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE)
|
||||
|
||||
esp_err_t esp_bt_hid_device_register_callback(esp_hd_cb_t *callback)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
if (callback == NULL) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
btc_profile_cb_set(BTC_PID_HD, callback);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_device_init(void)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HD;
|
||||
msg.act = BTC_HD_INIT_EVT;
|
||||
|
||||
/* Switch to BTC context */
|
||||
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_device_deinit(void)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HD;
|
||||
msg.act = BTC_HD_DEINIT_EVT;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_device_register_app(esp_hidd_app_param_t* app_param, esp_hidd_qos_param_t* in_qos, esp_hidd_qos_param_t* out_qos)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
btc_msg_t msg;
|
||||
btc_hidd_args_t args;
|
||||
memset(&args, 0, sizeof(btc_hidd_args_t));
|
||||
args.register_app.app_param = app_param;
|
||||
args.register_app.in_qos = in_qos;
|
||||
args.register_app.out_qos = out_qos;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HD;
|
||||
msg.act = BTC_HD_REGISTER_APP_EVT;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &args, sizeof(btc_hidd_args_t), NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_device_unregister_app(void)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HD;
|
||||
msg.act = BTC_HD_UNREGISTER_APP_EVT;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_device_connect(esp_bd_addr_t bd_addr)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
btc_msg_t msg;
|
||||
btc_hidd_args_t args;
|
||||
memset(&args, 0, sizeof(btc_hidd_args_t));
|
||||
memcpy(args.connect.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HD;
|
||||
msg.act = BTC_HD_CONNECT_EVT;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &args, sizeof(btc_hidd_args_t), NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_device_disconnect(void)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HD;
|
||||
msg.act = BTC_HD_DISCONNECT_EVT;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_device_send_report(esp_hidd_report_type_t type, uint8_t id, uint16_t len, uint8_t* data)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HD;
|
||||
msg.act = BTC_HD_SEND_REPORT_EVT;
|
||||
|
||||
btc_hidd_args_t args;
|
||||
memset(&args, 0, sizeof(btc_hidd_args_t));
|
||||
args.send_report.type = type;
|
||||
args.send_report.id = id;
|
||||
args.send_report.len = len;
|
||||
args.send_report.data = data;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &args, sizeof(btc_hidd_args_t), btc_hd_arg_deep_copy);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_device_report_error(esp_hidd_handshake_error_t error)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HD;
|
||||
msg.act = BTC_HD_REPORT_ERROR_EVT;
|
||||
|
||||
btc_hidd_args_t args;
|
||||
memset(&args, 0, sizeof(btc_hidd_args_t));
|
||||
args.error = error;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &args, sizeof(btc_hidd_args_t), NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_device_virtual_cable_unplug(void)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HD;
|
||||
msg.act = BTC_HD_UNPLUG_EVT;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
#endif /* defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE */
|
254
components/bt/host/bluedroid/api/esp_hidh_api.c
Normal file
254
components/bt/host/bluedroid/api/esp_hidh_api.c
Normal file
@@ -0,0 +1,254 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 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.
|
||||
|
||||
#include "btc/btc_manage.h"
|
||||
#include "btc_hh.h"
|
||||
#include "esp_bt_main.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_hidh_api.h"
|
||||
#include <string.h>
|
||||
|
||||
#if (defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE)
|
||||
|
||||
esp_err_t esp_bt_hid_host_register_callback(esp_hh_cb_t *callback)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
if (callback == NULL) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
btc_profile_cb_set(BTC_PID_HH, callback);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_init(void)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
btc_msg_t msg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_INIT_EVT;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_deinit(void)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
btc_msg_t msg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_DEINIT_EVT;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_connect(esp_bd_addr_t bd_addr)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_msg_t msg;
|
||||
btc_hidh_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_CONNECT_EVT;
|
||||
|
||||
memcpy(arg.connect.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_disconnect(esp_bd_addr_t bd_addr)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_msg_t msg;
|
||||
btc_hidh_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_DISCONNECT_EVT;
|
||||
|
||||
memcpy(arg.disconnect.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_virtual_cable_unplug(esp_bd_addr_t bd_addr)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_msg_t msg;
|
||||
btc_hidh_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_UNPLUG_EVT;
|
||||
|
||||
memcpy(arg.unplug.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_set_info(esp_bd_addr_t bd_addr, esp_hidh_hid_info_t *hid_info)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_msg_t msg;
|
||||
btc_hidh_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_SET_INFO_EVT;
|
||||
|
||||
memcpy(arg.set_info.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
arg.set_info.hid_info = hid_info;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), btc_hh_arg_deep_copy);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_get_protocol(esp_bd_addr_t bd_addr)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_msg_t msg;
|
||||
btc_hidh_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_GET_PROTO_EVT;
|
||||
|
||||
memcpy(arg.get_protocol.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_set_protocol(esp_bd_addr_t bd_addr, esp_hidh_protocol_mode_t protocol_mode)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_msg_t msg;
|
||||
btc_hidh_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_SET_PROTO_EVT;
|
||||
|
||||
memcpy(arg.set_protocol.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
arg.set_protocol.protocol_mode = protocol_mode;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_get_idle(esp_bd_addr_t bd_addr)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_msg_t msg;
|
||||
btc_hidh_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_GET_IDLE_EVT;
|
||||
|
||||
memcpy(arg.get_idle.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_set_idle(esp_bd_addr_t bd_addr, uint16_t idle_time)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_msg_t msg;
|
||||
btc_hidh_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_SET_IDLE_EVT;
|
||||
|
||||
memcpy(arg.set_idle.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
arg.set_idle.idle_time = idle_time;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_get_report(esp_bd_addr_t bd_addr, esp_hidh_report_type_t report_type, uint8_t report_id,
|
||||
int buffer_size)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_msg_t msg;
|
||||
btc_hidh_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_GET_REPORT_EVT;
|
||||
|
||||
memcpy(arg.get_report.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
arg.get_report.report_type = report_type;
|
||||
arg.get_report.report_id = report_id;
|
||||
arg.get_report.buffer_size = buffer_size;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_set_report(esp_bd_addr_t bd_addr, esp_hidh_report_type_t report_type, uint8_t *report,
|
||||
size_t len)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_msg_t msg;
|
||||
btc_hidh_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_SET_REPORT_EVT;
|
||||
|
||||
memcpy(arg.set_report.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
arg.set_report.report_type = report_type;
|
||||
arg.set_report.len = len;
|
||||
arg.set_report.report = report;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), btc_hh_arg_deep_copy);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_send_data(esp_bd_addr_t bd_addr, uint8_t *data, size_t len)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_msg_t msg;
|
||||
btc_hidh_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_SEND_DATA_EVT;
|
||||
|
||||
memcpy(arg.send_data.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
arg.send_data.len = len;
|
||||
arg.send_data.data = data;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), btc_hh_arg_deep_copy);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
#endif /* defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE */
|
379
components/bt/host/bluedroid/api/include/api/esp_hidd_api.h
Normal file
379
components/bt/host/bluedroid/api/include/api/esp_hidd_api.h
Normal file
@@ -0,0 +1,379 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 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.
|
||||
|
||||
#ifndef __ESP_HIDD_API_H__
|
||||
#define __ESP_HIDD_API_H__
|
||||
|
||||
#include "esp_bt_defs.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* sub_class of hid device */
|
||||
#define ESP_HID_CLASS_UNKNOWN (0x00<<2)
|
||||
#define ESP_HID_CLASS_JOS (0x01<<2) /* joy stick */
|
||||
#define ESP_HID_CLASS_GPD (0x02<<2) /* game pad */
|
||||
#define ESP_HID_CLASS_RMC (0x03<<2) /* remote control */
|
||||
#define ESP_HID_CLASS_SED (0x04<<2) /* sensing device */
|
||||
#define ESP_HID_CLASS_DGT (0x05<<2) /* Digitizer tablet */
|
||||
#define ESP_HID_CLASS_CDR (0x06<<2) /* card reader */
|
||||
#define ESP_HID_CLASS_KBD (0x10<<2) /* keyboard */
|
||||
#define ESP_HID_CLASS_MIC (0x20<<2) /* pointing device */
|
||||
#define ESP_HID_CLASS_COM (0x30<<2) /* Combo keyboard/pointing */
|
||||
|
||||
/**
|
||||
* @brief HIDD handshake error
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_HID_PAR_HANDSHAKE_RSP_SUCCESS = 0,
|
||||
ESP_HID_PAR_HANDSHAKE_RSP_NOT_READY = 1,
|
||||
ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID = 2,
|
||||
ESP_HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ = 3,
|
||||
ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM = 4,
|
||||
ESP_HID_PAR_HANDSHAKE_RSP_ERR_UNKNOWN = 14,
|
||||
ESP_HID_PAR_HANDSHAKE_RSP_ERR_FATAL = 15
|
||||
} esp_hidd_handshake_error_t;
|
||||
|
||||
/**
|
||||
* @brief HIDD report types
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_HIDD_REPORT_TYPE_OTHER = 0,
|
||||
ESP_HIDD_REPORT_TYPE_INPUT,
|
||||
ESP_HIDD_REPORT_TYPE_OUTPUT,
|
||||
ESP_HIDD_REPORT_TYPE_FEATURE,
|
||||
// special value for reports to be sent on INTR(INPUT is assumed)
|
||||
ESP_HIDD_REPORT_TYPE_INTRDATA
|
||||
} esp_hidd_report_type_t;
|
||||
|
||||
/**
|
||||
* @brief HIDD connection state
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_HIDD_CONN_STATE_CONNECTED,
|
||||
ESP_HIDD_CONN_STATE_CONNECTING,
|
||||
ESP_HIDD_CONN_STATE_DISCONNECTED,
|
||||
ESP_HIDD_CONN_STATE_DISCONNECTING,
|
||||
ESP_HIDD_CONN_STATE_UNKNOWN
|
||||
} esp_hidd_connection_state_t;
|
||||
|
||||
/**
|
||||
* @brief HID device protocol modes
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_HIDD_REPORT_MODE = 0x00,
|
||||
ESP_HIDD_BOOT_MODE = 0x01,
|
||||
ESP_HIDD_UNSUPPORTED_MODE = 0xff
|
||||
} esp_hidd_protocol_mode_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief HIDD characteristics for SDP report
|
||||
*/
|
||||
typedef struct {
|
||||
const char *name;
|
||||
const char *description;
|
||||
const char *provider;
|
||||
uint8_t subclass;
|
||||
uint8_t *desc_list;
|
||||
int desc_list_len;
|
||||
} esp_hidd_app_param_t;
|
||||
|
||||
/**
|
||||
* @brief HIDD Quality of Service parameters
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t service_type;
|
||||
uint32_t token_rate;
|
||||
uint32_t token_bucket_size;
|
||||
uint32_t peak_bandwidth;
|
||||
uint32_t access_latency;
|
||||
uint32_t delay_variation;
|
||||
} esp_hidd_qos_param_t;
|
||||
|
||||
/**
|
||||
* @brief HID device callback function events
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_HIDD_INIT_EVT = 0, /*!< When HID device is inited, the event comes */
|
||||
ESP_HIDD_DEINIT_EVT, /*!< When HID device is deinited, the event comes */
|
||||
ESP_HIDD_REGISTER_APP_EVT, /*!< When HID device application registered, the event comes */
|
||||
ESP_HIDD_UNREGISTER_APP_EVT, /*!< When HID device application unregistered, the event comes */
|
||||
ESP_HIDD_OPEN_EVT, /*!< When HID device connection to host opened, the event comes */
|
||||
ESP_HIDD_CLOSE_EVT, /*!< When HID device connection to host closed, the event comes */
|
||||
ESP_HIDD_SEND_REPORT_EVT, /*!< When HID device send report to lower layer, the event comes */
|
||||
ESP_HIDD_REPORT_ERR_EVT, /*!< When HID device report handshanke error to lower layer, the event comes */
|
||||
ESP_HIDD_GET_REPORT_EVT, /*!< When HID device receives GET_REPORT request from host, the event comes */
|
||||
ESP_HIDD_SET_REPORT_EVT, /*!< When HID device receives SET_REPORT request from host, the event comes */
|
||||
ESP_HIDD_SET_PROTOCOL_EVT, /*!< When HID device receives SET_PROTOCOL request from host, the event comes */
|
||||
ESP_HIDD_INTR_DATA_EVT, /*!< When HID device receives DATA from host on intr, the event comes */
|
||||
ESP_HIDD_VC_UNPLUG_EVT, /*!< When HID device initiates Virtual Cable Unplug, the event comes */
|
||||
ESP_HIDD_API_ERR_EVT /*!< When HID device has API error, the event comes */
|
||||
} esp_hidd_cb_event_t;
|
||||
|
||||
typedef enum {
|
||||
ESP_HIDD_SUCCESS,
|
||||
ESP_HIDD_ERROR, /*!< general ESP HD error */
|
||||
ESP_HIDD_NO_RES, /*!< out of system resources */
|
||||
ESP_HIDD_BUSY, /*!< Temporarily can not handle this request. */
|
||||
ESP_HIDD_NO_DATA, /*!< No data. */
|
||||
ESP_HIDD_NEED_INIT, /*!< HIDD module shall init first */
|
||||
ESP_HIDD_NEED_DEINIT, /*!< HIDD module shall deinit first */
|
||||
ESP_HIDD_NEED_REG, /*!< HIDD module shall register first */
|
||||
ESP_HIDD_NEED_DEREG, /*!< HIDD module shall deregister first */
|
||||
ESP_HIDD_NO_CONNECTION, /*!< connection may have been closed */
|
||||
} esp_hidd_status_t;
|
||||
|
||||
/**
|
||||
* @brief HID device callback parameters union
|
||||
*/
|
||||
typedef union {
|
||||
/**
|
||||
* @brief ESP_HIDD_INIT_EVT
|
||||
*/
|
||||
struct hidd_init_evt_param {
|
||||
esp_hidd_status_t status; /*!< operation status */
|
||||
} init; /*!< HIDD callback param of ESP_HIDD_INIT_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_DEINIT_EVT
|
||||
*/
|
||||
struct hidd_deinit_evt_param {
|
||||
esp_hidd_status_t status; /*!< operation status */
|
||||
} deinit; /*!< HIDD callback param of ESP_HIDD_DEINIT_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_REGISTER_APP_EVT
|
||||
*/
|
||||
struct hidd_register_app_evt_param {
|
||||
esp_hidd_status_t status; /*!< operation status */
|
||||
bool in_use; /*!< indicate whether use virtual cable plug host address */
|
||||
esp_bd_addr_t bd_addr; /*!< host address */
|
||||
} register_app; /*!< HIDD callback param of ESP_HIDD_REGISTER_APP_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_UNREGISTER_APP_EVT
|
||||
*/
|
||||
struct hidd_unregister_app_evt_param {
|
||||
esp_hidd_status_t status; /*!< operation status */
|
||||
} unregister_app; /*!< HIDD callback param of ESP_HIDD_UNREGISTER_APP_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_OPEN_EVT
|
||||
*/
|
||||
struct hidd_open_evt_param {
|
||||
esp_hidd_status_t status; /*!< operation status */
|
||||
esp_hidd_connection_state_t conn_status; /*!< connection status */
|
||||
esp_bd_addr_t bd_addr; /*!< host address */
|
||||
} open; /*!< HIDD callback param of ESP_HIDD_OPEN_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_CLOSE_EVT
|
||||
*/
|
||||
struct hidd_close_evt_param {
|
||||
esp_hidd_status_t status; /*!< operation status */
|
||||
esp_hidd_connection_state_t conn_status; /*!< connection status */
|
||||
} close; /*!< HIDD callback param of ESP_HIDD_CLOSE_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_SEND_REPORT_EVT
|
||||
*/
|
||||
struct hidd_send_report_evt_param {
|
||||
esp_hidd_status_t status; /*!< operation status */
|
||||
uint8_t reason; /*!< lower layer failed reason(ref hiddefs.h) */
|
||||
esp_hidd_report_type_t report_type; /*!< report type */
|
||||
uint8_t report_id; /*!< report id */
|
||||
} send_report; /*!< HIDD callback param of ESP_HIDD_SEND_REPORT_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_REPORT_ERR_EVT
|
||||
*/
|
||||
struct hidd_report_err_evt_param {
|
||||
esp_hidd_status_t status; /*!< operation status */
|
||||
uint8_t reason; /*!< lower layer failed reason(ref hiddefs.h) */
|
||||
} report_err; /*!< HIDD callback param of ESP_HIDD_REPORT_ERR_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_GET_REPORT_EVT
|
||||
*/
|
||||
struct hidd_get_report_evt_param {
|
||||
esp_hidd_report_type_t report_type; /*!< report type */
|
||||
uint8_t report_id; /*!< report id */
|
||||
uint16_t buffer_size; /*!< buffer size */
|
||||
} get_report; /*!< HIDD callback param of ESP_HIDD_GET_REPORT_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_SET_REPORT_EVT
|
||||
*/
|
||||
struct hidd_set_report_evt_param {
|
||||
esp_hidd_report_type_t report_type; /*!< report type */
|
||||
uint8_t report_id; /*!< report id */
|
||||
uint16_t len; /*!< set_report data length */
|
||||
uint8_t *data; /*!< set_report data pointer */
|
||||
} set_report; /*!< HIDD callback param of ESP_HIDD_SET_REPORT_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_SET_PROTOCOL_EVT
|
||||
*/
|
||||
struct hidd_set_protocol_evt_param {
|
||||
esp_hidd_protocol_mode_t protocol_mode; /*!< protocol mode */
|
||||
} set_protocol; /*!< HIDD callback param of ESP_HIDD_SET_PROTOCOL_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_INTR_DATA_EVT
|
||||
*/
|
||||
struct hidd_intr_data_evt_param {
|
||||
uint8_t report_id; /*!< interrupt channel report id */
|
||||
uint16_t len; /*!< interrupt channel report data length */
|
||||
uint8_t *data; /*!< interrupt channel report data pointer */
|
||||
} intr_data; /*!< HIDD callback param of ESP_HIDD_INTR_DATA_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_VC_UNPLUG_EVT
|
||||
*/
|
||||
struct hidd_vc_unplug_param {
|
||||
esp_hidd_status_t status; /*!< operation status */
|
||||
esp_hidd_connection_state_t conn_status; /*!< connection status */
|
||||
} vc_unplug; /*!< HIDD callback param of ESP_HIDD_VC_UNPLUG_EVT */
|
||||
} esp_hidd_cb_param_t;
|
||||
|
||||
/**
|
||||
* @brief HID device callback function type.
|
||||
* @param event: Event type
|
||||
* @param param: Point to callback parameter, currently is union type
|
||||
*/
|
||||
typedef void (esp_hd_cb_t)(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief This function is called to init callbacks with HID device module.
|
||||
*
|
||||
* @param[in] callback: pointer to the init callback function.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_device_register_callback(esp_hd_cb_t callback);
|
||||
|
||||
/**
|
||||
* @brief This function initializes HIDD. This function should be called after esp_bluedroid_enable and
|
||||
* esp_blueroid_init success, and should be called after esp_bt_hid_device_register_callback.
|
||||
* When the operation is complete the callback function will be called with ESP_HIDD_INIT_EVT.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_device_init(void);
|
||||
|
||||
/**
|
||||
* @brief This function de-initializes HIDD interface. This function should be called after esp_bluedroid_enable() and
|
||||
* esp_blueroid_init() success, and should be called after esp_bt_hid_device_init(). When the operation is complete the callback
|
||||
* function will be called with ESP_HIDD_DEINIT_EVT.
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_device_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Registers HIDD parameters with SDP and sets l2cap Quality of Service. This function should be called after
|
||||
* esp_bluedroid_enable and esp_blueroid_init success, and must be done after esp_bt_hid_device_init. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDD_REGISTER_APP_EVT.
|
||||
*
|
||||
* @param[in] app_param: HIDD parameters
|
||||
* @param[in] in_qos: incoming QoS parameters
|
||||
* @param[in] out_qos: outgoing QoS parameters
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_device_register_app(esp_hidd_app_param_t *app_param, esp_hidd_qos_param_t *in_qos,
|
||||
esp_hidd_qos_param_t *out_qos);
|
||||
|
||||
/**
|
||||
* @brief Removes HIDD parameters from SDP and resets l2cap Quality of Service. This function should be called after esp_bluedroid_enable and
|
||||
* esp_blueroid_init success, and should be called after esp_bt_hid_device_init. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDD_UNREGISTER_APP_EVT.
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_device_unregister_app(void);
|
||||
|
||||
/**
|
||||
* @brief This function connects HIDD interface to connected bluetooth device, if not done already. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDD_OPEN_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote host bluetooth device address.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_device_connect(esp_bd_addr_t bd_addr);
|
||||
|
||||
/**
|
||||
* @brief This function disconnects HIDD interface. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDD_CLOSE_EVT.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_device_disconnect(void);
|
||||
|
||||
/**
|
||||
* @brief Send HIDD report. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDD_SEND_REPORT_EVT.
|
||||
*
|
||||
* @param[in] type: type of report
|
||||
* @param[in] id: report id as defined by descriptor
|
||||
* @param[in] len: length of report
|
||||
* @param[in] data: report data
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_device_send_report(esp_hidd_report_type_t type, uint8_t id, uint16_t len, uint8_t *data);
|
||||
|
||||
/**
|
||||
* @brief Sends HIDD handshake with error info for invalid set_report. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDD_REPORT_ERR_EVT.
|
||||
*
|
||||
* @param[in] error: type of error
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_device_report_error(esp_hidd_handshake_error_t error);
|
||||
|
||||
/**
|
||||
* @brief Unplug virtual cable of HIDD. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDD_VC_UNPLUG_EVT.
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_device_virtual_cable_unplug(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
465
components/bt/host/bluedroid/api/include/api/esp_hidh_api.h
Normal file
465
components/bt/host/bluedroid/api/include/api/esp_hidh_api.h
Normal file
@@ -0,0 +1,465 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 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.
|
||||
|
||||
#ifndef __ESP_HIDH_API_H__
|
||||
#define __ESP_HIDH_API_H__
|
||||
|
||||
#include "esp_bt_defs.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BTHH_MAX_DSC_LEN 884
|
||||
|
||||
/**
|
||||
* @brief HID host connection state
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_HIDH_CONN_STATE_CONNECTED = 0, /*!< connected state */
|
||||
ESP_HIDH_CONN_STATE_CONNECTING, /*!< connecting state */
|
||||
ESP_HIDH_CONN_STATE_DISCONNECTED, /*!< disconnected state */
|
||||
ESP_HIDH_CONN_STATE_DISCONNECTING, /*!< disconnecting state */
|
||||
ESP_HIDH_CONN_STATE_UNKNOWN /*!< unknown state(initial state) */
|
||||
} esp_hidh_connection_state_t;
|
||||
|
||||
typedef enum {
|
||||
ESP_HIDH_OK,
|
||||
ESP_HIDH_HS_HID_NOT_READY, /*!< handshake error : device not ready */
|
||||
ESP_HIDH_HS_INVALID_RPT_ID, /*!< handshake error : invalid report ID */
|
||||
ESP_HIDH_HS_TRANS_NOT_SPT, /*!< handshake error : transaction not spt */
|
||||
ESP_HIDH_HS_INVALID_PARAM, /*!< handshake error : invalid paremter */
|
||||
ESP_HIDH_HS_ERROR, /*!< handshake error : unspecified HS error */
|
||||
ESP_HIDH_ERR, /*!< general ESP HH error */
|
||||
ESP_HIDH_ERR_SDP, /*!< SDP error */
|
||||
ESP_HIDH_ERR_PROTO, /*!< SET_Protocol error,
|
||||
only used in ESP_HIDH_OPEN_EVT callback */
|
||||
|
||||
ESP_HIDH_ERR_DB_FULL, /*!< device database full error, used in
|
||||
ESP_HIDH_OPEN_EVT/ESP_HIDH_ADD_DEV_EVT */
|
||||
ESP_HIDH_ERR_TOD_UNSPT, /*!< type of device not supported */
|
||||
ESP_HIDH_ERR_NO_RES, /*!< out of system resources */
|
||||
ESP_HIDH_ERR_AUTH_FAILED, /*!< authentication fail */
|
||||
ESP_HIDH_ERR_HDL, /*!< connection handle error */
|
||||
ESP_HIDH_ERR_SEC, /*!< encryption error */
|
||||
// self_defined
|
||||
ESP_HIDH_BUSY, /*!< Temporarily can not handle this request. */
|
||||
ESP_HIDH_NO_DATA, /*!< No data. */
|
||||
ESP_HIDH_NEED_INIT, /*!< HIDH module shall init first */
|
||||
ESP_HIDH_NEED_DEINIT, /*!< HIDH module shall deinit first */
|
||||
ESP_HIDH_NO_CONNECTION, /*!< connection may have been closed */
|
||||
} esp_hidh_status_t;
|
||||
|
||||
/**
|
||||
* @brief HID host protocol modes
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_HIDH_BOOT_MODE = 0x00, /*!< boot protocol mode */
|
||||
ESP_HIDH_REPORT_MODE = 0x01, /*!< report protocol mode */
|
||||
ESP_HIDH_UNSUPPORTED_MODE = 0xff /*!< unsupported protocol mode */
|
||||
} esp_hidh_protocol_mode_t;
|
||||
|
||||
/**
|
||||
* @brief HID host report types
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_HIDH_REPORT_TYPE_OTHER = 0, /*!< unsupported report type */
|
||||
ESP_HIDH_REPORT_TYPE_INPUT, /*!< input report type */
|
||||
ESP_HIDH_REPORT_TYPE_OUTPUT, /*!< output report type */
|
||||
ESP_HIDH_REPORT_TYPE_FEATURE, /*!< feature report type */
|
||||
} esp_hidh_report_type_t;
|
||||
|
||||
/**
|
||||
* @brief HID host callback function events
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_HIDH_INIT_EVT = 0, /*!< When HID host is inited, the event comes */
|
||||
ESP_HIDH_DEINIT_EVT, /*!< When HID host is deinited, the event comes */
|
||||
ESP_HIDH_OPEN_EVT, /*!< When HID host connection opened, the event comes */
|
||||
ESP_HIDH_CLOSE_EVT, /*!< When HID host connection closed, the event comes */
|
||||
ESP_HIDH_GET_RPT_EVT, /*!< When Get_Report command is called, the event comes */
|
||||
ESP_HIDH_SET_RPT_EVT, /*!< When Set_Report command is called, the event comes */
|
||||
ESP_HIDH_GET_PROTO_EVT, /*!< When Get_Protocol command is called, the event comes */
|
||||
ESP_HIDH_SET_PROTO_EVT, /*!< When Set_Protocol command is called, the event comes */
|
||||
ESP_HIDH_GET_IDLE_EVT, /*!< When Get_Idle command is called, the event comes */
|
||||
ESP_HIDH_SET_IDLE_EVT, /*!< When Set_Idle command is called, the event comes */
|
||||
ESP_HIDH_GET_DSCP_EVT, /*!< When HIDH is inited, the event comes */
|
||||
ESP_HIDH_ADD_DEV_EVT, /*!< When a device is added, the event comes */
|
||||
ESP_HIDH_RMV_DEV_EVT, /*!< When a device is removed, the event comes */
|
||||
ESP_HIDH_VC_UNPLUG_EVT, /*!< When virtually unplugged, the event comes */
|
||||
ESP_HIDH_DATA_EVT, /*!< When send data on interrupt channel, the event comes */
|
||||
ESP_HIDH_DATA_IND_EVT, /*!< When receive data on interrupt channel, the event comes */
|
||||
ESP_HIDH_SET_INFO_EVT /*!< When set the HID device descriptor, the event comes */
|
||||
} esp_hidh_cb_event_t;
|
||||
|
||||
typedef struct {
|
||||
int attr_mask;
|
||||
uint8_t sub_class;
|
||||
uint8_t app_id;
|
||||
int vendor_id;
|
||||
int product_id;
|
||||
int version;
|
||||
uint8_t ctry_code;
|
||||
int dl_len;
|
||||
uint8_t dsc_list[BTHH_MAX_DSC_LEN];
|
||||
} esp_hidh_hid_info_t;
|
||||
|
||||
/**
|
||||
* @brief HID host callback parameters union
|
||||
*/
|
||||
typedef union {
|
||||
/**
|
||||
* @brief ESP_HIDH_INIT_EVT
|
||||
*/
|
||||
struct hidh_init_evt_param {
|
||||
esp_hidh_status_t status; /*!< status */
|
||||
} init; /*!< HIDH callback param of ESP_HIDH_INIT_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_DEINIT_EVT
|
||||
*/
|
||||
struct hidh_uninit_evt_param {
|
||||
esp_hidh_status_t status; /*!< status */
|
||||
} deinit; /*!< HIDH callback param of ESP_HIDH_DEINIT_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_OPEN_EVT
|
||||
*/
|
||||
struct hidh_open_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
esp_hidh_connection_state_t conn_status; /*!< connection status */
|
||||
bool is_orig; /*!< indicate if host intiate the connection */
|
||||
uint8_t handle; /*!< device handle */
|
||||
esp_bd_addr_t bd_addr; /*!< device address */
|
||||
} open; /*!< HIDH callback param of ESP_HIDH_OPEN_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_CLOSE_EVT
|
||||
*/
|
||||
struct hidh_close_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t reason; /*!< lower layer failed reason(ref hiddefs.h) */
|
||||
esp_hidh_connection_state_t conn_status; /*!< connection status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
} close; /*!< HIDH callback param of ESP_HIDH_CLOSE_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_VC_UNPLUG_EVT
|
||||
*/
|
||||
struct hidh_unplug_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
esp_hidh_connection_state_t conn_status; /*!< connection status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
} unplug; /*!< HIDH callback param of ESP_HIDH_VC_UNPLUG_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_GET_PROTO_EVT
|
||||
*/
|
||||
struct hidh_get_proto_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
esp_hidh_protocol_mode_t proto_mode; /*!< protocol mode */
|
||||
} get_proto; /*!< HIDH callback param of ESP_HIDH_GET_PROTO_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_SET_PROTO_EVT
|
||||
*/
|
||||
struct hidh_set_proto_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
} set_proto; /*!< HIDH callback param of ESP_HIDH_SET_PROTO_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_GET_RPT_EVT
|
||||
*/
|
||||
struct hidh_get_rpt_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
uint16_t len; /*!< data length */
|
||||
uint8_t *data; /*!< data pointer */
|
||||
} get_rpt; /*!< HIDH callback param of ESP_HIDH_GET_RPT_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_SET_RPT_EVT
|
||||
*/
|
||||
struct hidh_set_rpt_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
} set_rpt; /*!< HIDH callback param of ESP_HIDH_SET_RPT_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_DATA_EVT
|
||||
*/
|
||||
struct hidh_send_data_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
uint8_t reason; /*!< lower layer failed reason(ref hiddefs.h) */
|
||||
} send_data; /*!< HIDH callback param of ESP_HIDH_DATA_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_GET_IDLE_EVT
|
||||
*/
|
||||
struct hidh_get_idle_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
uint8_t idle_rate; /*!< idle rate */
|
||||
} get_idle; /*!< HIDH callback param of ESP_HIDH_GET_IDLE_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_SET_IDLE_EVT
|
||||
*/
|
||||
struct hidh_set_idle_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
} set_idle; /*!< HIDH callback param of ESP_HIDH_SET_IDLE_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_DATA_IND_EVT
|
||||
*/
|
||||
struct hidh_data_ind_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
esp_hidh_protocol_mode_t proto_mode; /*!< protocol mode */
|
||||
uint16_t len; /*!< data length */
|
||||
uint8_t *data; /*!< data pointer */
|
||||
} data_ind; /*!< HIDH callback param of ESP_HIDH_DATA_IND_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_ADD_DEV_EVT
|
||||
*/
|
||||
struct hidh_add_dev_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
esp_bd_addr_t bd_addr; /*!< device address */
|
||||
} add_dev; /*!< HIDH callback param of ESP_HIDH_ADD_DEV_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_RMV_DEV_EVT
|
||||
*/
|
||||
struct hidh_rmv_dev_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
esp_bd_addr_t bd_addr; /*!< device address */
|
||||
} rmv_dev; /*!< HIDH callback param of ESP_HIDH_RMV_DEV_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_GET_DSCP_EVT
|
||||
*/
|
||||
struct hidh_get_dscp_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
bool added; /*!< Indicate if added */
|
||||
uint16_t vendor_id; /*!< Vendor ID */
|
||||
uint16_t product_id; /*!< Product ID */
|
||||
uint16_t version; /*!< Version */
|
||||
uint16_t ssr_max_latency; /*!< SSR max latency */
|
||||
uint16_t ssr_min_tout; /*!< SSR min timeout */
|
||||
uint8_t ctry_code; /*!< Country Code */
|
||||
uint16_t dl_len; /*!< Device descriptor length */
|
||||
uint8_t *dsc_list; /*!< Device descriptor pointer */
|
||||
} dscp; /*!< HIDH callback param of ESP_HIDH_GET_DSCP_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_SET_INFO_EVT
|
||||
*/
|
||||
struct hidh_set_info_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
esp_bd_addr_t bd_addr; /*!< device address */
|
||||
} set_info; /*!< HIDH callback param of ESP_HIDH_SET_INFO_EVT */
|
||||
} esp_hidh_cb_param_t;
|
||||
|
||||
/**
|
||||
* @brief HID host callback function type
|
||||
* @param event: Event type
|
||||
* @param param: Point to callback parameter, currently is union type
|
||||
*/
|
||||
typedef void (esp_hh_cb_t)(esp_hidh_cb_event_t event, esp_hidh_cb_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief This function is called to init callbacks with HID host module.
|
||||
*
|
||||
* @param[in] callback: pointer to the init callback function.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_register_callback(esp_hh_cb_t callback);
|
||||
|
||||
/**
|
||||
* @brief This function initializes HID host. This function should be called after esp_bluedroid_enable() and
|
||||
* esp_blueroid_init() success, and should be called after esp_bt_hid_host_register_callback().
|
||||
* When the operation is complete the callback function will be called with ESP_HIDH_INIT_EVT.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_init(void);
|
||||
|
||||
/**
|
||||
* @brief Closes the interface. This function should be called after esp_bluedroid_enable() and
|
||||
* esp_blueroid_init() success, and should be called after esp_bt_hid_host_init().
|
||||
* When the operation is complete the callback function will be called with ESP_HIDH_DEINIT_EVT.
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Connect to hid device. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDH_OPEN_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote device bluetooth device address.
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_connect(esp_bd_addr_t bd_addr);
|
||||
|
||||
/**
|
||||
* @brief Disconnect from hid device. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDH_CLOSE_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote device bluetooth device address.
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_disconnect(esp_bd_addr_t bd_addr);
|
||||
|
||||
/**
|
||||
* @brief Virtual UnPlug (VUP) the specified HID device. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDH_VC_UNPLUG_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote device bluetooth device address.
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_virtual_cable_unplug(esp_bd_addr_t bd_addr);
|
||||
|
||||
/**
|
||||
* @brief Set the HID device descriptor for the specified HID device. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDH_SET_INFO_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote device bluetooth device address.
|
||||
* @param[in] hid_info: HID device descriptor structure.
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_set_info(esp_bd_addr_t bd_addr, esp_hidh_hid_info_t *hid_info);
|
||||
|
||||
/**
|
||||
* @brief Get the HID proto mode. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDH_GET_PROTO_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote device bluetooth device address.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_get_protocol(esp_bd_addr_t bd_addr);
|
||||
|
||||
/**
|
||||
* @brief Set the HID proto mode. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDH_SET_PROTO_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote device bluetooth device address.
|
||||
* @param[in] protocol_mode: Protocol mode type.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_set_protocol(esp_bd_addr_t bd_addr, esp_hidh_protocol_mode_t protocol_mode);
|
||||
|
||||
/**
|
||||
* @brief Get the HID Idle Time. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDH_GET_IDLE_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote device bluetooth device address.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_get_idle(esp_bd_addr_t bd_addr);
|
||||
|
||||
/**
|
||||
* @brief Set the HID Idle Time. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDH_SET_IDLE_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote device bluetooth device address.
|
||||
* @param[in] idle_time: Idle time rate
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_set_idle(esp_bd_addr_t bd_addr, uint16_t idle_time);
|
||||
|
||||
/**
|
||||
* @brief Send a GET_REPORT to HID device. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDH_GET_RPT_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote device bluetooth device address.
|
||||
* @param[in] report_type: Report type
|
||||
* @param[in] report_id: Report id
|
||||
* @param[in] buffer_size: Buffer size
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_get_report(esp_bd_addr_t bd_addr, esp_hidh_report_type_t report_type, uint8_t report_id,
|
||||
int buffer_size);
|
||||
|
||||
/**
|
||||
* @brief Send a SET_REPORT to HID device. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDH_SET_RPT_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote device bluetooth device address.
|
||||
* @param[in] report_type: Report type
|
||||
* @param[in] report: Report data pointer
|
||||
* @param[in] len: Report data length
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_set_report(esp_bd_addr_t bd_addr, esp_hidh_report_type_t report_type, uint8_t *report,
|
||||
size_t len);
|
||||
|
||||
/**
|
||||
* @brief Send data to HID device. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDH_DATA_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote device bluetooth device address.
|
||||
* @param[in] data: Data pointer
|
||||
* @param[in] len: Data length
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_send_data(esp_bd_addr_t bd_addr, uint8_t *data, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@@ -4498,6 +4498,22 @@ void bta_dm_set_encryption (tBTA_DM_MSG *p_data)
|
||||
}
|
||||
#endif ///SMP_INCLUDED == TRUE
|
||||
|
||||
#if (BTA_HD_INCLUDED == TRUE)
|
||||
BOOLEAN bta_dm_check_if_only_hd_connected(BD_ADDR peer_addr)
|
||||
{
|
||||
APPL_TRACE_DEBUG("%s: count(%d)", __func__, bta_dm_conn_srvcs.count);
|
||||
for (uint8_t j = 0; j < bta_dm_conn_srvcs.count; j++) {
|
||||
// Check if profiles other than hid are connected
|
||||
if ((bta_dm_conn_srvcs.conn_srvc[j].id != BTA_ID_HD) &&
|
||||
!bdcmp(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr, peer_addr)) {
|
||||
APPL_TRACE_DEBUG("%s: Another profile (id=%d) is connected", __func__, bta_dm_conn_srvcs.conn_srvc[j].id);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* BTA_HD_INCLUDED == TRUE */
|
||||
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
/*******************************************************************************
|
||||
**
|
||||
|
@@ -117,11 +117,11 @@ tBTA_DM_CFG *const p_bta_dm_cfg = (tBTA_DM_CFG *) &bta_dm_cfg;
|
||||
tBTA_DM_RM *const p_bta_dm_rm_cfg = (tBTA_DM_RM *) &bta_dm_rm_cfg;
|
||||
|
||||
#if BLE_INCLUDED == TRUE
|
||||
# define BTA_DM_NUM_PM_ENTRY 10 /* number of entries in bta_dm_pm_cfg except the first */
|
||||
# define BTA_DM_NUM_PM_SPEC 10 /* number of entries in bta_dm_pm_spec */
|
||||
#else
|
||||
# define BTA_DM_NUM_PM_ENTRY 8 /* number of entries in bta_dm_pm_cfg except the first */
|
||||
# define BTA_DM_NUM_PM_SPEC 8 /* number of entries in bta_dm_pm_spec */
|
||||
#else
|
||||
# define BTA_DM_NUM_PM_ENTRY 6 /* number of entries in bta_dm_pm_cfg except the first */
|
||||
# define BTA_DM_NUM_PM_SPEC 6 /* number of entries in bta_dm_pm_spec */
|
||||
#endif
|
||||
|
||||
#if (BTA_DM_PM_INCLUDED == TRUE)
|
||||
@@ -133,10 +133,12 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_CFG bta_dm_pm_cfg[BTA_DM_NUM_PM_ENTRY + 1]
|
||||
{BTA_ID_JV, BTA_APP_ID_1, 2}, /* app BTA_JV_PM_ID_1, reuse ftc spec table */
|
||||
{BTA_ID_JV, BTA_ALL_APP_ID, 3}, /* reuse fts spec table */
|
||||
{BTA_ID_HS, BTA_ALL_APP_ID, 4}, /* HS spec table */
|
||||
{BTA_ID_AVK, BTA_ALL_APP_ID, 5} /* avk spec table */
|
||||
{BTA_ID_AVK, BTA_ALL_APP_ID, 5}, /* avk spec table */
|
||||
{BTA_ID_HD, BTA_ALL_APP_ID, 6}, /* hd spec table */
|
||||
{BTA_ID_HH, BTA_ALL_APP_ID, 7} /* hh spec table */
|
||||
#if BLE_INCLUDED == TRUE
|
||||
, {BTA_ID_GATTC, BTA_ALL_APP_ID, 6} /* gattc spec table */
|
||||
, {BTA_ID_GATTS, BTA_ALL_APP_ID, 7} /* gatts spec table */
|
||||
, {BTA_ID_GATTC, BTA_ALL_APP_ID, 8} /* gattc spec table */
|
||||
, {BTA_ID_GATTS, BTA_ALL_APP_ID, 9} /* gatts spec table */
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -254,10 +256,48 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] = {
|
||||
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
|
||||
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
|
||||
}
|
||||
},
|
||||
|
||||
/* HD : 6 */
|
||||
{
|
||||
(BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
|
||||
#if (BTM_SSR_INCLUDED == TRUE)
|
||||
(BTA_DM_PM_SSR3), /* the SSR entry */
|
||||
#endif
|
||||
{
|
||||
{{BTA_DM_PM_SNIFF_HD_ACTIVE_IDX, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */
|
||||
{{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
|
||||
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
|
||||
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
|
||||
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */
|
||||
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */
|
||||
{{BTA_DM_PM_SNIFF_HD_IDLE_IDX, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
|
||||
{{BTA_DM_PM_SNIFF_HD_ACTIVE_IDX, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
|
||||
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
|
||||
}
|
||||
},
|
||||
|
||||
/* HH : 7 */
|
||||
{
|
||||
(BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
|
||||
#if (BTM_SSR_INCLUDED == TRUE)
|
||||
(BTA_DM_PM_SSR1), /* the SSR entry */
|
||||
#endif
|
||||
{
|
||||
{{BTA_DM_PM_SNIFF_HH_OPEN_IDX, BTA_DM_PM_HH_OPEN_DELAY + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */
|
||||
{{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
|
||||
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
|
||||
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
|
||||
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */
|
||||
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close, used for HH suspend */
|
||||
{{BTA_DM_PM_SNIFF_HH_IDLE_IDX, BTA_DM_PM_HH_IDLE_DELAY + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
|
||||
{{BTA_DM_PM_SNIFF_HH_ACTIVE_IDX, BTA_DM_PM_HH_ACTIVE_DELAY + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
|
||||
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
|
||||
}
|
||||
}
|
||||
|
||||
#if BLE_INCLUDED == TRUE
|
||||
/* GATTC : 6 */
|
||||
/* GATTC : 8 */
|
||||
, {
|
||||
(BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
|
||||
#if (BTM_SSR_INCLUDED == TRUE)
|
||||
@@ -278,7 +318,7 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] = {
|
||||
{{BTA_DM_PM_RETRY, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
|
||||
}
|
||||
}
|
||||
/* GATTS : 7 */
|
||||
/* GATTS : 9 */
|
||||
, {
|
||||
(BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
|
||||
#if (BTM_SSR_INCLUDED == TRUE)
|
||||
@@ -372,7 +412,7 @@ tBTA_DM_SSR_SPEC bta_dm_ssr_spec[] = {
|
||||
seting default max latency and min remote timeout as 0,
|
||||
and always read individual device preference from HH module */
|
||||
{1200, 2, 2}, /* BTA_DM_PM_SSR2 - others (as long as sniff is allowed)*/
|
||||
{360, 160, 2} /* BTA_DM_PM_SSR3 - HD */
|
||||
{360, 160, 1600} /* BTA_DM_PM_SSR3 - HD */
|
||||
};
|
||||
|
||||
tBTA_DM_SSR_SPEC *const p_bta_dm_ssr_spec = (tBTA_DM_SSR_SPEC *) &bta_dm_ssr_spec;
|
||||
|
@@ -26,6 +26,7 @@
|
||||
|
||||
#include "common/bt_target.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "bta/bta_sys.h"
|
||||
#if (BLE_INCLUDED == TRUE && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
|
||||
#include "bta/bta_gatt_api.h"
|
||||
#endif
|
||||
@@ -1596,6 +1597,11 @@ extern void bta_dm_ble_get_energy_info(tBTA_DM_MSG *p_data);
|
||||
extern void bta_dm_set_encryption(tBTA_DM_MSG *p_data);
|
||||
extern void bta_dm_confirm(tBTA_DM_MSG *p_data);
|
||||
extern void bta_dm_key_req(tBTA_DM_MSG *p_data);
|
||||
|
||||
#if (BTA_HD_INCLUDED == TRUE)
|
||||
extern BOOLEAN bta_dm_check_if_only_hd_connected(BD_ADDR peer_addr);
|
||||
#endif /* BTA_HD_INCLUDED */
|
||||
|
||||
#if (BTM_OOB_INCLUDED == TRUE)
|
||||
extern void bta_dm_loc_oob(tBTA_DM_MSG *p_data);
|
||||
extern void bta_dm_oob_reply(tBTA_DM_MSG *p_data);
|
||||
|
@@ -35,6 +35,7 @@
|
||||
#include "gatt_int.h"
|
||||
#include "osi/allocator.h"
|
||||
#include "osi/mutex.h"
|
||||
#include "bta_hh_int.h"
|
||||
|
||||
#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
|
||||
#include "bta_hh_int.h"
|
||||
@@ -304,7 +305,10 @@ void bta_gattc_deregister(tBTA_GATTC_CB *p_cb, tBTA_GATTC_RCB *p_clreg)
|
||||
bta_gattc_deregister_cmpl(p_clreg);
|
||||
}
|
||||
} else {
|
||||
APPL_TRACE_ERROR("bta_gattc_deregister Deregister Failedm unknown client cif");
|
||||
APPL_TRACE_ERROR("Deregister Failed unknown client cif");
|
||||
#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
|
||||
bta_hh_cleanup_disable(BTA_HH_OK);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
|
774
components/bt/host/bluedroid/bta/hd/bta_hd_act.c
Normal file
774
components/bt/host/bluedroid/bta/hd/bta_hd_act.c
Normal file
@@ -0,0 +1,774 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
* 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 device action functions.
|
||||
*
|
||||
******************************************************************************/
|
||||
#include "common/bt_target.h"
|
||||
|
||||
#if defined(BTA_HD_INCLUDED) && (BTA_HD_INCLUDED == TRUE)
|
||||
|
||||
#include "bta/bta_sys.h"
|
||||
#include "bta_hd_int.h"
|
||||
#include "osi/allocator.h"
|
||||
#include "osi/osi.h"
|
||||
#include "stack/btm_api.h"
|
||||
#include <string.h>
|
||||
|
||||
static void bta_hd_cback(BD_ADDR bd_addr, uint8_t event, uint32_t data, BT_HDR *pdata);
|
||||
|
||||
static bool check_descriptor(uint8_t *data, uint16_t length, bool *has_report_id)
|
||||
{
|
||||
uint8_t *ptr = data;
|
||||
*has_report_id = FALSE;
|
||||
while (ptr < data + length) {
|
||||
uint8_t item = *ptr++;
|
||||
switch (item) {
|
||||
case 0xfe: // long item indicator
|
||||
if (ptr < data + length) {
|
||||
ptr += ((*ptr) + 2);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 0x85: // Report ID
|
||||
*has_report_id = TRUE;
|
||||
default:
|
||||
ptr += (item & 0x03);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (ptr == data + length);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_api_enable
|
||||
*
|
||||
* Description Enables HID device
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void bta_hd_api_enable(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_STATUS status = BTA_HD_ERROR;
|
||||
tHID_STATUS ret;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
HID_DevInit();
|
||||
|
||||
memset(&bta_hd_cb, 0, sizeof(tBTA_HD_CB));
|
||||
|
||||
HID_DevSetSecurityLevel(BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
|
||||
/* store parameters */
|
||||
bta_hd_cb.p_cback = p_data->api_enable.p_cback;
|
||||
|
||||
ret = HID_DevRegister(bta_hd_cback);
|
||||
if (ret == HID_SUCCESS) {
|
||||
status = BTA_HD_OK;
|
||||
} else {
|
||||
APPL_TRACE_ERROR("%s: Failed to register HID device (%d)", __func__, ret);
|
||||
}
|
||||
|
||||
/* signal BTA call back event */
|
||||
(*bta_hd_cb.p_cback)(BTA_HD_ENABLE_EVT, (tBTA_HD *)&status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_api_disable
|
||||
*
|
||||
* Description Disables HID device
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void bta_hd_api_disable(void)
|
||||
{
|
||||
tBTA_HD_STATUS status = BTA_HD_ERROR;
|
||||
tHID_STATUS ret;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
/* service is not enabled */
|
||||
if (bta_hd_cb.p_cback == NULL)
|
||||
return;
|
||||
|
||||
/* Remove service record */
|
||||
if (bta_hd_cb.sdp_handle != 0) {
|
||||
SDP_DeleteRecord(bta_hd_cb.sdp_handle);
|
||||
bta_sys_remove_uuid(UUID_SERVCLASS_HUMAN_INTERFACE);
|
||||
}
|
||||
|
||||
/* Deregister with lower layer */
|
||||
ret = HID_DevDeregister();
|
||||
if (ret == HID_SUCCESS) {
|
||||
status = BTA_HD_OK;
|
||||
} else {
|
||||
APPL_TRACE_ERROR("%s: Failed to deregister HID device (%d)", __func__, ret);
|
||||
}
|
||||
|
||||
(*bta_hd_cb.p_cback)(BTA_HD_DISABLE_EVT, (tBTA_HD *)&status);
|
||||
|
||||
memset(&bta_hd_cb, 0, sizeof(tBTA_HD_CB));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_register_act
|
||||
*
|
||||
* Description Registers SDP record
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void bta_hd_register_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD ret;
|
||||
tBTA_HD_REGISTER_APP *p_app_data = (tBTA_HD_REGISTER_APP *)p_data;
|
||||
bool use_report_id = FALSE;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
ret.reg_status.in_use = FALSE;
|
||||
|
||||
/* Check if len doesn't exceed BTA_HD_APP_DESCRIPTOR_LEN and descriptor
|
||||
* itself is well-formed. Also check if descriptor has Report Id item so we
|
||||
* know if report will have prefix or not. */
|
||||
if (p_app_data->d_len > BTA_HD_APP_DESCRIPTOR_LEN ||
|
||||
!check_descriptor(p_app_data->d_data, p_app_data->d_len, &use_report_id)) {
|
||||
APPL_TRACE_ERROR("%s: Descriptor is too long or malformed", __func__);
|
||||
ret.reg_status.status = BTA_HD_ERROR;
|
||||
(*bta_hd_cb.p_cback)(BTA_HD_REGISTER_APP_EVT, &ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret.reg_status.status = BTA_HD_OK;
|
||||
|
||||
/* Remove old record if for some reason it's already registered */
|
||||
if (bta_hd_cb.sdp_handle != 0) {
|
||||
SDP_DeleteRecord(bta_hd_cb.sdp_handle);
|
||||
}
|
||||
|
||||
bta_hd_cb.use_report_id = use_report_id;
|
||||
bta_hd_cb.sdp_handle = SDP_CreateRecord();
|
||||
HID_DevAddRecord(bta_hd_cb.sdp_handle, p_app_data->name, p_app_data->description, p_app_data->provider,
|
||||
p_app_data->subclass, p_app_data->d_len, p_app_data->d_data);
|
||||
bta_sys_add_uuid(UUID_SERVCLASS_HUMAN_INTERFACE);
|
||||
|
||||
HID_DevSetIncomingQos(p_app_data->in_qos.service_type, p_app_data->in_qos.token_rate,
|
||||
p_app_data->in_qos.token_bucket_size, p_app_data->in_qos.peak_bandwidth,
|
||||
p_app_data->in_qos.access_latency, p_app_data->in_qos.delay_variation);
|
||||
|
||||
HID_DevSetOutgoingQos(p_app_data->out_qos.service_type, p_app_data->out_qos.token_rate,
|
||||
p_app_data->out_qos.token_bucket_size, p_app_data->out_qos.peak_bandwidth,
|
||||
p_app_data->out_qos.access_latency, p_app_data->out_qos.delay_variation);
|
||||
|
||||
// application is registered so we can accept incoming connections
|
||||
HID_DevSetIncomingPolicy(TRUE);
|
||||
|
||||
if (HID_DevGetDevice(&ret.reg_status.bda) == HID_SUCCESS) {
|
||||
ret.reg_status.in_use = TRUE;
|
||||
}
|
||||
|
||||
(*bta_hd_cb.p_cback)(BTA_HD_REGISTER_APP_EVT, &ret);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_unregister_act
|
||||
*
|
||||
* Description Unregisters SDP record
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void bta_hd_unregister_act(UNUSED_ATTR tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_STATUS status = BTA_HD_OK;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
// application is no longer registered so we do not want incoming connections
|
||||
HID_DevSetIncomingPolicy(FALSE);
|
||||
|
||||
if (bta_hd_cb.sdp_handle != 0) {
|
||||
SDP_DeleteRecord(bta_hd_cb.sdp_handle);
|
||||
}
|
||||
|
||||
bta_hd_cb.sdp_handle = 0;
|
||||
bta_sys_remove_uuid(UUID_SERVCLASS_HUMAN_INTERFACE);
|
||||
|
||||
(*bta_hd_cb.p_cback)(BTA_HD_UNREGISTER_APP_EVT, (tBTA_HD *)&status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_unregister2_act
|
||||
*
|
||||
* Description
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void bta_hd_unregister2_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
// close first
|
||||
bta_hd_close_act(p_data);
|
||||
|
||||
// then unregister
|
||||
bta_hd_unregister_act(p_data);
|
||||
|
||||
if (bta_hd_cb.disable_w4_close) {
|
||||
bta_hd_api_disable();
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_connect_act
|
||||
*
|
||||
* Description Connect to device (must be virtually plugged)
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_connect_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tHID_STATUS ret;
|
||||
tBTA_HD_DEVICE_CTRL *p_ctrl = (tBTA_HD_DEVICE_CTRL *)p_data;
|
||||
tBTA_HD cback_data;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
do {
|
||||
ret = HID_DevPlugDevice(p_ctrl->addr);
|
||||
if (ret != HID_SUCCESS) {
|
||||
APPL_TRACE_WARNING("%s: HID_DevPlugDevice returned %d", __func__, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = HID_DevConnect();
|
||||
if (ret != HID_SUCCESS) {
|
||||
APPL_TRACE_WARNING("%s: HID_DevConnect returned %d", __func__, ret);
|
||||
return;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
bdcpy(cback_data.conn.bda, p_ctrl->addr);
|
||||
cback_data.conn.status = (ret == HID_SUCCESS ? BTA_HD_OK : BTA_HD_ERROR);
|
||||
cback_data.conn.conn_status = BTA_HD_CONN_STATE_CONNECTING;
|
||||
bta_hd_cb.p_cback(BTA_HD_OPEN_EVT, &cback_data);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_disconnect_act
|
||||
*
|
||||
* Description Disconnect from device
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_disconnect_act(UNUSED_ATTR tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tHID_STATUS ret;
|
||||
tBTA_HD cback_data;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
ret = HID_DevDisconnect();
|
||||
|
||||
if (ret != HID_SUCCESS) {
|
||||
APPL_TRACE_WARNING("%s: HID_DevDisconnect returned %d", __func__, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if (HID_DevGetDevice(&cback_data.conn.bda) == HID_SUCCESS) {
|
||||
cback_data.conn.status = BTA_HD_OK;
|
||||
cback_data.conn.conn_status = BTA_HD_CONN_STATE_DISCONNECTING;
|
||||
bta_hd_cb.p_cback(BTA_HD_CLOSE_EVT, &cback_data);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_add_device_act
|
||||
*
|
||||
* Description
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_add_device_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_DEVICE_CTRL *p_ctrl = (tBTA_HD_DEVICE_CTRL *)p_data;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
HID_DevPlugDevice(p_ctrl->addr);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_remove_device_act
|
||||
*
|
||||
* Description
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_remove_device_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_DEVICE_CTRL *p_ctrl = (tBTA_HD_DEVICE_CTRL *)p_data;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
HID_DevUnplugDevice(p_ctrl->addr);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_send_report_act
|
||||
*
|
||||
* Description Sends report
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_send_report_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_SEND_REPORT *p_report = (tBTA_HD_SEND_REPORT *)p_data;
|
||||
uint8_t channel;
|
||||
uint8_t report_id;
|
||||
tBTA_HD cback_data;
|
||||
tHID_STATUS ret;
|
||||
|
||||
APPL_TRACE_VERBOSE("%s", __func__);
|
||||
|
||||
channel = p_report->use_intr ? HID_CHANNEL_INTR : HID_CHANNEL_CTRL;
|
||||
report_id = (bta_hd_cb.use_report_id || bta_hd_cb.boot_mode) ? p_report->id : 0x00;
|
||||
|
||||
ret = HID_DevSendReport(channel, p_report->type, report_id, p_report->len, p_report->data);
|
||||
|
||||
/* trigger PM */
|
||||
bta_sys_busy(BTA_ID_HD, 1, bta_hd_cb.bd_addr);
|
||||
bta_sys_idle(BTA_ID_HD, 1, bta_hd_cb.bd_addr);
|
||||
|
||||
cback_data.send_report.status = (ret == HID_SUCCESS ? BTA_HD_OK : BTA_HD_ERROR);
|
||||
cback_data.send_report.reason = ret;
|
||||
cback_data.send_report.report_id = report_id;
|
||||
cback_data.send_report.report_type = p_report->type;
|
||||
bta_hd_cb.p_cback(BTA_HD_SEND_REPORT_EVT, &cback_data);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_report_error_act
|
||||
*
|
||||
* Description
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_report_error_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_REPORT_ERR *p_report = (tBTA_HD_REPORT_ERR *)p_data;
|
||||
tHID_STATUS ret;
|
||||
tBTA_HD cback_data;
|
||||
|
||||
APPL_TRACE_API("%s: error = %d", __func__, p_report->error);
|
||||
|
||||
ret = HID_DevReportError(p_report->error);
|
||||
|
||||
if (ret != HID_SUCCESS) {
|
||||
APPL_TRACE_WARNING("%s: HID_DevReportError returned %d", __func__, ret);
|
||||
}
|
||||
|
||||
cback_data.report_err.status = (ret == HID_SUCCESS ? BTA_HD_OK : BTA_HD_ERROR);
|
||||
cback_data.report_err.reason = ret;
|
||||
bta_hd_cb.p_cback(BTA_HD_REPORT_ERR_EVT, &cback_data);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_vc_unplug_act
|
||||
*
|
||||
* Description Sends Virtual Cable Unplug
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_vc_unplug_act(UNUSED_ATTR tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tHID_STATUS ret;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
bta_hd_cb.vc_unplug = TRUE;
|
||||
ret = HID_DevVirtualCableUnplug();
|
||||
|
||||
if (ret != HID_SUCCESS) {
|
||||
APPL_TRACE_WARNING("%s: HID_DevVirtualCableUnplug returned %d", __func__, ret);
|
||||
}
|
||||
|
||||
/* trigger PM */
|
||||
bta_sys_busy(BTA_ID_HD, 1, bta_hd_cb.bd_addr);
|
||||
bta_sys_idle(BTA_ID_HD, 1, bta_hd_cb.bd_addr);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_open_act
|
||||
*
|
||||
* Description
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_open_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
|
||||
tBTA_HD cback_data;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
HID_DevPlugDevice(p_cback->addr);
|
||||
bta_sys_conn_open(BTA_ID_HD, 1, p_cback->addr);
|
||||
|
||||
bdcpy(cback_data.conn.bda, p_cback->addr);
|
||||
bdcpy(bta_hd_cb.bd_addr, p_cback->addr);
|
||||
cback_data.conn.status = BTA_HD_OK;
|
||||
cback_data.conn.conn_status = BTA_HD_CONN_STATE_CONNECTED;
|
||||
bta_hd_cb.p_cback(BTA_HD_OPEN_EVT, &cback_data);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_close_act
|
||||
*
|
||||
* Description
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_close_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
|
||||
tBTA_HD cback_data;
|
||||
tBTA_HD_EVT cback_event = BTA_HD_CLOSE_EVT;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
bta_sys_conn_close(BTA_ID_HD, 1, p_cback->addr);
|
||||
|
||||
if (bta_hd_cb.vc_unplug) {
|
||||
bta_hd_cb.vc_unplug = FALSE;
|
||||
HID_DevUnplugDevice(p_cback->addr);
|
||||
cback_event = BTA_HD_VC_UNPLUG_EVT;
|
||||
}
|
||||
|
||||
bdcpy(cback_data.conn.bda, p_cback->addr);
|
||||
memset(bta_hd_cb.bd_addr, 0, sizeof(BD_ADDR));
|
||||
cback_data.conn.status = BTA_HD_OK;
|
||||
cback_data.conn.conn_status = BTA_HD_CONN_STATE_DISCONNECTED;
|
||||
bta_hd_cb.p_cback(cback_event, &cback_data);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_intr_data_act
|
||||
*
|
||||
* Description Handles incoming DATA request on intr
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_intr_data_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
|
||||
BT_HDR *p_msg = p_cback->p_data;
|
||||
uint16_t len = p_msg->len;
|
||||
uint8_t *p_buf = (uint8_t *)(p_msg + 1) + p_msg->offset;
|
||||
tBTA_HD_INTR_DATA ret;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
if (bta_hd_cb.use_report_id || bta_hd_cb.boot_mode) {
|
||||
ret.report_id = *p_buf;
|
||||
len--;
|
||||
p_buf++;
|
||||
} else {
|
||||
ret.report_id = 0;
|
||||
}
|
||||
|
||||
ret.len = len;
|
||||
ret.p_data = p_buf;
|
||||
(*bta_hd_cb.p_cback)(BTA_HD_INTR_DATA_EVT, (tBTA_HD *)&ret);
|
||||
if (p_msg) {
|
||||
osi_free(p_msg);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_get_report_act
|
||||
*
|
||||
* Description Handles incoming GET_REPORT request
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_get_report_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
|
||||
bool rep_size_follows = p_cback->data;
|
||||
BT_HDR *p_msg = p_cback->p_data;
|
||||
uint8_t *p_buf = (uint8_t *)(p_msg + 1) + p_msg->offset;
|
||||
tBTA_HD_GET_REPORT ret = {0, 0, 0};
|
||||
uint16_t remaining_len = p_msg->len;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
if (remaining_len < 1) {
|
||||
APPL_TRACE_ERROR("%s invalid data, remaining_len:%d", __func__, remaining_len);
|
||||
return;
|
||||
}
|
||||
|
||||
ret.report_type = *p_buf & HID_PAR_REP_TYPE_MASK;
|
||||
p_buf++;
|
||||
remaining_len--;
|
||||
|
||||
if (bta_hd_cb.use_report_id) {
|
||||
if (remaining_len < 1) {
|
||||
APPL_TRACE_ERROR("%s invalid data, remaining_len:%d", __func__, remaining_len);
|
||||
return;
|
||||
}
|
||||
ret.report_id = *p_buf;
|
||||
p_buf++;
|
||||
remaining_len--;
|
||||
}
|
||||
|
||||
if (rep_size_follows) {
|
||||
if (remaining_len < 2) {
|
||||
APPL_TRACE_ERROR("%s invalid data, remaining_len:%d", __func__, remaining_len);
|
||||
return;
|
||||
}
|
||||
ret.buffer_size = *p_buf | (*(p_buf + 1) << 8);
|
||||
}
|
||||
|
||||
(*bta_hd_cb.p_cback)(BTA_HD_GET_REPORT_EVT, (tBTA_HD *)&ret);
|
||||
if (p_msg) {
|
||||
osi_free(p_msg);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_set_report_act
|
||||
*
|
||||
* Description Handles incoming SET_REPORT request
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_set_report_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
|
||||
BT_HDR *p_msg = p_cback->p_data;
|
||||
uint16_t len = p_msg->len;
|
||||
uint8_t *p_buf = (uint8_t *)(p_msg + 1) + p_msg->offset;
|
||||
tBTA_HD_SET_REPORT ret = {0, 0, 0, NULL};
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
ret.report_type = *p_buf & HID_PAR_REP_TYPE_MASK;
|
||||
p_buf++;
|
||||
len--;
|
||||
|
||||
if (bta_hd_cb.use_report_id || bta_hd_cb.boot_mode) {
|
||||
ret.report_id = *p_buf;
|
||||
len--;
|
||||
p_buf++;
|
||||
} else {
|
||||
ret.report_id = 0;
|
||||
}
|
||||
|
||||
ret.len = len;
|
||||
ret.p_data = p_buf;
|
||||
(*bta_hd_cb.p_cback)(BTA_HD_SET_REPORT_EVT, (tBTA_HD *)&ret);
|
||||
if (p_msg) {
|
||||
osi_free(p_msg);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_set_protocol_act
|
||||
*
|
||||
* Description
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_set_protocol_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
|
||||
tBTA_HD cback_data;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
bta_hd_cb.boot_mode = (p_cback->data == HID_PAR_PROTOCOL_BOOT_MODE);
|
||||
cback_data.set_protocol = p_cback->data;
|
||||
|
||||
(*bta_hd_cb.p_cback)(BTA_HD_SET_PROTOCOL_EVT, &cback_data);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_vc_unplug_done_act
|
||||
*
|
||||
* Description
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_vc_unplug_done_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
|
||||
tBTA_HD cback_data;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
bta_sys_conn_close(BTA_ID_HD, 1, p_cback->addr);
|
||||
|
||||
HID_DevUnplugDevice(p_cback->addr);
|
||||
|
||||
bdcpy(cback_data.conn.bda, p_cback->addr);
|
||||
bdcpy(bta_hd_cb.bd_addr, p_cback->addr);
|
||||
cback_data.conn.status = BTA_HD_OK;
|
||||
cback_data.conn.conn_status = BTA_HD_CONN_STATE_DISCONNECTED;
|
||||
(*bta_hd_cb.p_cback)(BTA_HD_VC_UNPLUG_EVT, &cback_data);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_suspend_act
|
||||
*
|
||||
* Description
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_suspend_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
bta_sys_idle(BTA_ID_HD, 1, p_cback->addr);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_exit_suspend_act
|
||||
*
|
||||
* Description
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_exit_suspend_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
bta_sys_busy(BTA_ID_HD, 1, p_cback->addr);
|
||||
bta_sys_idle(BTA_ID_HD, 1, p_cback->addr);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_cback
|
||||
*
|
||||
* Description BTA HD callback function
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void bta_hd_cback(BD_ADDR bd_addr, uint8_t event, uint32_t data, BT_HDR *pdata)
|
||||
{
|
||||
tBTA_HD_CBACK_DATA *p_buf = NULL;
|
||||
uint16_t sm_event = BTA_HD_INVALID_EVT;
|
||||
|
||||
APPL_TRACE_API("%s: event=%d", __func__, event);
|
||||
|
||||
switch (event) {
|
||||
case HID_DHOST_EVT_OPEN:
|
||||
sm_event = BTA_HD_INT_OPEN_EVT;
|
||||
break;
|
||||
|
||||
case HID_DHOST_EVT_CLOSE:
|
||||
sm_event = BTA_HD_INT_CLOSE_EVT;
|
||||
break;
|
||||
|
||||
case HID_DHOST_EVT_GET_REPORT:
|
||||
sm_event = BTA_HD_INT_GET_REPORT_EVT;
|
||||
break;
|
||||
|
||||
case HID_DHOST_EVT_SET_REPORT:
|
||||
sm_event = BTA_HD_INT_SET_REPORT_EVT;
|
||||
break;
|
||||
|
||||
case HID_DHOST_EVT_SET_PROTOCOL:
|
||||
sm_event = BTA_HD_INT_SET_PROTOCOL_EVT;
|
||||
break;
|
||||
|
||||
case HID_DHOST_EVT_INTR_DATA:
|
||||
sm_event = BTA_HD_INT_INTR_DATA_EVT;
|
||||
break;
|
||||
|
||||
case HID_DHOST_EVT_VC_UNPLUG:
|
||||
sm_event = BTA_HD_INT_VC_UNPLUG_EVT;
|
||||
break;
|
||||
|
||||
case HID_DHOST_EVT_SUSPEND:
|
||||
sm_event = BTA_HD_INT_SUSPEND_EVT;
|
||||
break;
|
||||
|
||||
case HID_DHOST_EVT_EXIT_SUSPEND:
|
||||
sm_event = BTA_HD_INT_EXIT_SUSPEND_EVT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sm_event != BTA_HD_INVALID_EVT &&
|
||||
(p_buf = (tBTA_HD_CBACK_DATA *)osi_malloc(sizeof(tBTA_HD_CBACK_DATA) + sizeof(BT_HDR))) != NULL) {
|
||||
p_buf->hdr.event = sm_event;
|
||||
bdcpy(p_buf->addr, bd_addr);
|
||||
p_buf->data = data;
|
||||
p_buf->p_data = pdata;
|
||||
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
#endif /* BTA_HD_INCLUDED */
|
287
components/bt/host/bluedroid/bta/hd/bta_hd_api.c
Normal file
287
components/bt/host/bluedroid/bta/hd/bta_hd_api.c
Normal file
@@ -0,0 +1,287 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
* 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 DEVICE API in the subsystem of BTA.
|
||||
*
|
||||
******************************************************************************/
|
||||
#include "common/bt_target.h"
|
||||
|
||||
#if defined(BTA_HD_INCLUDED) && (BTA_HD_INCLUDED == TRUE)
|
||||
|
||||
#include "bta/bta_hd_api.h"
|
||||
#include "bta_hd_int.h"
|
||||
#include "osi/allocator.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*****************************************************************************
|
||||
* Constants
|
||||
****************************************************************************/
|
||||
static const tBTA_SYS_REG bta_hd_reg = {bta_hd_hdl_event, BTA_HdDisable};
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdEnable
|
||||
*
|
||||
* Description Enables HID device
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void BTA_HdEnable(tBTA_HD_CBACK *p_cback)
|
||||
{
|
||||
tBTA_HD_API_ENABLE *p_buf;
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
bta_sys_register(BTA_ID_HD, &bta_hd_reg);
|
||||
p_buf = (tBTA_HD_API_ENABLE *)osi_malloc((uint16_t)sizeof(tBTA_HD_API_ENABLE));
|
||||
if (p_buf != NULL) {
|
||||
memset(p_buf, 0, sizeof(tBTA_HD_API_ENABLE));
|
||||
p_buf->hdr.event = BTA_HD_API_ENABLE_EVT;
|
||||
p_buf->p_cback = p_cback;
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdDisable
|
||||
*
|
||||
* Description Disables HID device.
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void BTA_HdDisable(void)
|
||||
{
|
||||
BT_HDR *p_buf;
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
bta_sys_deregister(BTA_ID_HD);
|
||||
if ((p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR))) != NULL) {
|
||||
p_buf->event = BTA_HD_API_DISABLE_EVT;
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdRegisterApp
|
||||
*
|
||||
* Description This function is called when application should be
|
||||
*registered
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdRegisterApp(tBTA_HD_APP_INFO *p_app_info, tBTA_HD_QOS_INFO *p_in_qos, tBTA_HD_QOS_INFO *p_out_qos)
|
||||
{
|
||||
tBTA_HD_REGISTER_APP *p_buf;
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
if ((p_buf = (tBTA_HD_REGISTER_APP *)osi_malloc(sizeof(tBTA_HD_REGISTER_APP))) != NULL) {
|
||||
p_buf->hdr.event = BTA_HD_API_REGISTER_APP_EVT;
|
||||
if (p_app_info->p_name) {
|
||||
strncpy(p_buf->name, p_app_info->p_name, BTA_HD_APP_NAME_LEN);
|
||||
p_buf->name[BTA_HD_APP_NAME_LEN] = '\0';
|
||||
} else {
|
||||
p_buf->name[0] = '\0';
|
||||
}
|
||||
if (p_app_info->p_description) {
|
||||
strncpy(p_buf->description, p_app_info->p_description, BTA_HD_APP_DESCRIPTION_LEN);
|
||||
p_buf->description[BTA_HD_APP_DESCRIPTION_LEN] = '\0';
|
||||
} else {
|
||||
p_buf->description[0] = '\0';
|
||||
}
|
||||
if (p_app_info->p_provider) {
|
||||
strncpy(p_buf->provider, p_app_info->p_provider, BTA_HD_APP_PROVIDER_LEN);
|
||||
p_buf->provider[BTA_HD_APP_PROVIDER_LEN] = '\0';
|
||||
} else {
|
||||
p_buf->provider[0] = '\0';
|
||||
}
|
||||
p_buf->subclass = p_app_info->subclass;
|
||||
p_buf->d_len = p_app_info->descriptor.dl_len;
|
||||
memcpy(p_buf->d_data, p_app_info->descriptor.dsc_list, p_app_info->descriptor.dl_len);
|
||||
// copy qos data as-is
|
||||
memcpy(&p_buf->in_qos, p_in_qos, sizeof(tBTA_HD_QOS_INFO));
|
||||
memcpy(&p_buf->out_qos, p_out_qos, sizeof(tBTA_HD_QOS_INFO));
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdUnregisterApp
|
||||
*
|
||||
* Description This function is called when application should be
|
||||
*unregistered
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdUnregisterApp(void)
|
||||
{
|
||||
BT_HDR *p_buf;
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
if ((p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR))) != NULL) {
|
||||
p_buf->event = BTA_HD_API_UNREGISTER_APP_EVT;
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdSendReport
|
||||
*
|
||||
* Description This function is called when report is to be sent
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdSendReport(tBTA_HD_REPORT *p_report)
|
||||
{
|
||||
tBTA_HD_SEND_REPORT *p_buf;
|
||||
APPL_TRACE_VERBOSE("%s", __func__);
|
||||
if (p_report->len > BTA_HD_REPORT_LEN) {
|
||||
APPL_TRACE_WARNING("%s, report len (%d) > MTU len (%d), can't send report."
|
||||
" Increase value of HID_DEV_MTU_SIZE to send larger reports",
|
||||
__func__, p_report->len, BTA_HD_REPORT_LEN);
|
||||
return;
|
||||
}
|
||||
if ((p_buf = (tBTA_HD_SEND_REPORT *)osi_malloc(sizeof(tBTA_HD_SEND_REPORT))) != NULL) {
|
||||
p_buf->hdr.event = BTA_HD_API_SEND_REPORT_EVT;
|
||||
p_buf->use_intr = p_report->use_intr;
|
||||
p_buf->type = p_report->type;
|
||||
p_buf->id = p_report->id;
|
||||
p_buf->len = p_report->len;
|
||||
memcpy(p_buf->data, p_report->p_data, p_report->len);
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdVirtualCableUnplug
|
||||
*
|
||||
* Description This function is called when VCU shall be sent
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdVirtualCableUnplug(void)
|
||||
{
|
||||
BT_HDR *p_buf;
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
if ((p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR))) != NULL) {
|
||||
p_buf->event = BTA_HD_API_VC_UNPLUG_EVT;
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdConnect
|
||||
*
|
||||
* Description This function is called when connection to host shall be
|
||||
* made
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdConnect(BD_ADDR addr)
|
||||
{
|
||||
tBTA_HD_DEVICE_CTRL *p_buf;
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
if ((p_buf = (tBTA_HD_DEVICE_CTRL *)osi_malloc(sizeof(tBTA_HD_DEVICE_CTRL))) != NULL) {
|
||||
p_buf->hdr.event = BTA_HD_API_CONNECT_EVT;
|
||||
memcpy(p_buf->addr, addr, sizeof(BD_ADDR));
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdDisconnect
|
||||
*
|
||||
* Description This function is called when host shall be disconnected
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdDisconnect(void)
|
||||
{
|
||||
BT_HDR *p_buf;
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
if ((p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR))) != NULL) {
|
||||
p_buf->event = BTA_HD_API_DISCONNECT_EVT;
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdAddDevice
|
||||
*
|
||||
* Description This function is called when a device is virtually cabled
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdAddDevice(BD_ADDR addr)
|
||||
{
|
||||
tBTA_HD_DEVICE_CTRL *p_buf;
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
if ((p_buf = (tBTA_HD_DEVICE_CTRL *)osi_malloc(sizeof(tBTA_HD_DEVICE_CTRL))) != NULL) {
|
||||
p_buf->hdr.event = BTA_HD_API_ADD_DEVICE_EVT;
|
||||
memcpy(p_buf->addr, addr, sizeof(BD_ADDR));
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdRemoveDevice
|
||||
*
|
||||
* Description This function is called when a device is virtually uncabled
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdRemoveDevice(BD_ADDR addr)
|
||||
{
|
||||
tBTA_HD_DEVICE_CTRL *p_buf;
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
if ((p_buf = (tBTA_HD_DEVICE_CTRL *)osi_malloc(sizeof(tBTA_HD_DEVICE_CTRL))) != NULL) {
|
||||
p_buf->hdr.event = BTA_HD_API_REMOVE_DEVICE_EVT;
|
||||
memcpy(p_buf->addr, addr, sizeof(BD_ADDR));
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdReportError
|
||||
*
|
||||
* Description This function is called when reporting error for set report
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdReportError(uint8_t error)
|
||||
{
|
||||
tBTA_HD_REPORT_ERR *p_buf;
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
if ((p_buf = (tBTA_HD_REPORT_ERR *)osi_malloc(sizeof(tBTA_HD_REPORT_ERR))) != NULL) {
|
||||
p_buf->hdr.event = BTA_HD_API_REPORT_ERROR_EVT;
|
||||
p_buf->error = error;
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
#endif /* BTA_HD_INCLUDED */
|
320
components/bt/host/bluedroid/bta/hd/bta_hd_main.c
Normal file
320
components/bt/host/bluedroid/bta/hd/bta_hd_main.c
Normal file
@@ -0,0 +1,320 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
* 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_HD_INCLUDED) && (BTA_HD_INCLUDED == TRUE)
|
||||
|
||||
#include "bta/bta_hd_api.h"
|
||||
#include "bta_hd_int.h"
|
||||
#include <string.h>
|
||||
|
||||
/*****************************************************************************
|
||||
* Constants and types
|
||||
****************************************************************************/
|
||||
/* state machine states */
|
||||
enum {
|
||||
BTA_HD_INIT_ST,
|
||||
BTA_HD_IDLE_ST, /* not connected, waiting for connection */
|
||||
BTA_HD_CONN_ST, /* host connected */
|
||||
BTA_HD_TRANSIENT_TO_INIT_ST, /* transient state: going back from CONN to INIT */
|
||||
};
|
||||
typedef uint8_t tBTA_HD_STATE;
|
||||
|
||||
/* state machine actions */
|
||||
enum {
|
||||
BTA_HD_REGISTER_ACT,
|
||||
BTA_HD_UNREGISTER_ACT,
|
||||
BTA_HD_UNREGISTER2_ACT,
|
||||
BTA_HD_CONNECT_ACT,
|
||||
BTA_HD_DISCONNECT_ACT,
|
||||
BTA_HD_ADD_DEVICE_ACT,
|
||||
BTA_HD_REMOVE_DEVICE_ACT,
|
||||
BTA_HD_SEND_REPORT_ACT,
|
||||
BTA_HD_REPORT_ERROR_ACT,
|
||||
BTA_HD_VC_UNPLUG_ACT,
|
||||
BTA_HD_OPEN_ACT,
|
||||
BTA_HD_CLOSE_ACT,
|
||||
BTA_HD_INTR_DATA_ACT,
|
||||
BTA_HD_GET_REPORT_ACT,
|
||||
BTA_HD_SET_REPORT_ACT,
|
||||
BTA_HD_SET_PROTOCOL_ACT,
|
||||
BTA_HD_VC_UNPLUG_DONE_ACT,
|
||||
BTA_HD_SUSPEND_ACT,
|
||||
BTA_HD_EXIT_SUSPEND_ACT,
|
||||
BTA_HD_NUM_ACTIONS
|
||||
};
|
||||
|
||||
#define BTA_HD_IGNORE BTA_HD_NUM_ACTIONS
|
||||
|
||||
typedef void (*tBTA_HD_ACTION)(tBTA_HD_DATA *p_data);
|
||||
/* action functions */
|
||||
const tBTA_HD_ACTION bta_hd_action[] = {
|
||||
bta_hd_register_act, bta_hd_unregister_act, bta_hd_unregister2_act, bta_hd_connect_act,
|
||||
bta_hd_disconnect_act, bta_hd_add_device_act, bta_hd_remove_device_act, bta_hd_send_report_act,
|
||||
bta_hd_report_error_act, bta_hd_vc_unplug_act, bta_hd_open_act, bta_hd_close_act,
|
||||
bta_hd_intr_data_act, bta_hd_get_report_act, bta_hd_set_report_act, bta_hd_set_protocol_act,
|
||||
bta_hd_vc_unplug_done_act, bta_hd_suspend_act, bta_hd_exit_suspend_act,
|
||||
};
|
||||
|
||||
/* state table information */
|
||||
#define BTA_HD_ACTION 0 /* position of action */
|
||||
#define BTA_HD_NEXT_STATE 1 /* position of next state */
|
||||
#define BTA_HD_NUM_COLS 2 /* number of columns */
|
||||
|
||||
const uint8_t bta_hd_st_init[][BTA_HD_NUM_COLS] = {
|
||||
/* Event Action Next state
|
||||
*/
|
||||
/* BTA_HD_API_REGISTER_APP_EVT */ {BTA_HD_REGISTER_ACT, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_API_UNREGISTER_APP_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_API_CONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_API_DISCONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_API_ADD_DEVICE_EVT */ {BTA_HD_ADD_DEVICE_ACT, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_API_REMOVE_DEVICE_EVT */ {BTA_HD_REMOVE_DEVICE_ACT, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_API_SEND_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_API_REPORT_ERROR_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_API_VC_UNPLUG_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_INT_OPEN_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_INT_CLOSE_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_INT_INTR_DATA_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_INT_GET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_INT_SET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_INT_SET_PROTOCOL_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_INT_VC_UNPLUG_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_INT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_INT_EXIT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
};
|
||||
|
||||
const uint8_t bta_hd_st_idle[][BTA_HD_NUM_COLS] = {
|
||||
/* Event Action Next state
|
||||
*/
|
||||
/* BTA_HD_API_REGISTER_APP_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_API_UNREGISTER_APP_EVT */ {BTA_HD_UNREGISTER_ACT, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_API_CONNECT_EVT */ {BTA_HD_CONNECT_ACT, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_API_DISCONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_API_ADD_DEVICE_EVT */ {BTA_HD_ADD_DEVICE_ACT, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_API_REMOVE_DEVICE_EVT */ {BTA_HD_REMOVE_DEVICE_ACT, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_API_SEND_REPORT_EVT */ {BTA_HD_SEND_REPORT_ACT, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_API_REPORT_ERROR_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_API_VC_UNPLUG_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_OPEN_EVT */ {BTA_HD_OPEN_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_INT_CLOSE_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_INTR_DATA_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_GET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_SET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_SET_PROTOCOL_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_VC_UNPLUG_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_EXIT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
};
|
||||
|
||||
const uint8_t bta_hd_st_conn[][BTA_HD_NUM_COLS] = {
|
||||
/* Event Action Next state */
|
||||
/* BTA_HD_API_REGISTER_APP_EVT */ {BTA_HD_IGNORE, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_API_UNREGISTER_APP_EVT */ {BTA_HD_DISCONNECT_ACT, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_API_CONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_API_DISCONNECT_EVT */ {BTA_HD_DISCONNECT_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_API_ADD_DEVICE_EVT */ {BTA_HD_ADD_DEVICE_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_API_REMOVE_DEVICE_EVT */ {BTA_HD_REMOVE_DEVICE_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_API_SEND_REPORT_EVT */ {BTA_HD_SEND_REPORT_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_API_REPORT_ERROR_EVT */ {BTA_HD_REPORT_ERROR_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_API_VC_UNPLUG_EVT */ {BTA_HD_VC_UNPLUG_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_INT_OPEN_EVT */ {BTA_HD_IGNORE, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_INT_CLOSE_EVT */ {BTA_HD_CLOSE_ACT, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_INTR_DATA_EVT */ {BTA_HD_INTR_DATA_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_INT_GET_REPORT_EVT */ {BTA_HD_GET_REPORT_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_INT_SET_REPORT_EVT */ {BTA_HD_SET_REPORT_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_INT_SET_PROTOCOL_EVT */ {BTA_HD_SET_PROTOCOL_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_INT_VC_UNPLUG_EVT */ {BTA_HD_VC_UNPLUG_DONE_ACT, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_SUSPEND_EVT */ {BTA_HD_SUSPEND_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_INT_EXIT_SUSPEND_EVT */ {BTA_HD_EXIT_SUSPEND_ACT, BTA_HD_CONN_ST},
|
||||
};
|
||||
|
||||
const uint8_t bta_hd_st_transient_to_init[][BTA_HD_NUM_COLS] = {
|
||||
/* Event Action Next state */
|
||||
/* BTA_HD_API_REGISTER_APP_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_API_UNREGISTER_APP_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_API_CONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_API_DISCONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_API_ADD_DEVICE_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_API_REMOVE_DEVICE_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_API_SEND_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_API_REPORT_ERROR_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_API_VC_UNPLUG_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_INT_OPEN_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_INT_CLOSE_EVT */ {BTA_HD_UNREGISTER2_ACT, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_INT_INTR_DATA_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_INT_GET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_INT_SET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_INT_SET_PROTOCOL_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_INT_VC_UNPLUG_EVT */ {BTA_HD_UNREGISTER2_ACT, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_INT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_INT_EXIT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
};
|
||||
|
||||
/* type for state table */
|
||||
typedef const uint8_t (*tBTA_HD_ST_TBL)[BTA_HD_NUM_COLS];
|
||||
/* state table */
|
||||
const tBTA_HD_ST_TBL bta_hd_st_tbl[] = {bta_hd_st_init, bta_hd_st_idle, bta_hd_st_conn, bta_hd_st_transient_to_init};
|
||||
|
||||
/*****************************************************************************
|
||||
* Global data
|
||||
****************************************************************************/
|
||||
#if BTA_DYNAMIC_MEMORY == FALSE
|
||||
tBTA_HD_CB bta_hd_cb;
|
||||
#else
|
||||
tBTA_HD_CB *bta_hd_cb_ptr;
|
||||
#endif
|
||||
|
||||
static const char *bta_hd_evt_code(tBTA_HD_INT_EVT evt_code);
|
||||
static const char *bta_hd_state_code(tBTA_HD_STATE state_code);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_sm_execute
|
||||
*
|
||||
* Description State machine event handling function for HID Device
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void bta_hd_sm_execute(uint16_t event, tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_ST_TBL state_table;
|
||||
tBTA_HD_STATE prev_state;
|
||||
uint8_t action;
|
||||
tBTA_HD cback_data;
|
||||
|
||||
APPL_TRACE_EVENT("%s: state=%s (%d) event=%s (%d)", __func__, bta_hd_state_code(bta_hd_cb.state), bta_hd_cb.state,
|
||||
bta_hd_evt_code(event), event);
|
||||
|
||||
prev_state = bta_hd_cb.state;
|
||||
memset(&cback_data, 0, sizeof(tBTA_HD));
|
||||
state_table = bta_hd_st_tbl[bta_hd_cb.state];
|
||||
event &= 0xff;
|
||||
|
||||
if ((action = state_table[event][BTA_HD_ACTION]) < BTA_HD_IGNORE) {
|
||||
(*bta_hd_action[action])(p_data);
|
||||
}
|
||||
|
||||
bta_hd_cb.state = state_table[event][BTA_HD_NEXT_STATE];
|
||||
|
||||
if (bta_hd_cb.state != prev_state) {
|
||||
APPL_TRACE_EVENT("%s: [new] state=%s (%d)", __func__, bta_hd_state_code(bta_hd_cb.state), bta_hd_cb.state);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_hdl_event
|
||||
*
|
||||
* Description HID device main event handling function.
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
bool bta_hd_hdl_event(BT_HDR *p_msg)
|
||||
{
|
||||
APPL_TRACE_API("%s: p_msg->event=%d", __func__, p_msg->event);
|
||||
|
||||
switch (p_msg->event) {
|
||||
case BTA_HD_API_ENABLE_EVT:
|
||||
bta_hd_api_enable((tBTA_HD_DATA *)p_msg);
|
||||
break;
|
||||
case BTA_HD_API_DISABLE_EVT:
|
||||
if (bta_hd_cb.state == BTA_HD_CONN_ST) {
|
||||
APPL_TRACE_WARNING("%s: host connected, disconnect before disabling", __func__);
|
||||
// unregister (and disconnect)
|
||||
bta_hd_cb.disable_w4_close = TRUE;
|
||||
bta_hd_sm_execute(BTA_HD_API_UNREGISTER_APP_EVT, (tBTA_HD_DATA *)p_msg);
|
||||
} else {
|
||||
bta_hd_api_disable();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
bta_hd_sm_execute(p_msg->event, (tBTA_HD_DATA *)p_msg);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static const char *bta_hd_evt_code(tBTA_HD_INT_EVT evt_code)
|
||||
{
|
||||
switch (evt_code) {
|
||||
case BTA_HD_API_REGISTER_APP_EVT:
|
||||
return "BTA_HD_API_REGISTER_APP_EVT";
|
||||
case BTA_HD_API_UNREGISTER_APP_EVT:
|
||||
return "BTA_HD_API_UNREGISTER_APP_EVT";
|
||||
case BTA_HD_API_CONNECT_EVT:
|
||||
return "BTA_HD_API_CONNECT_EVT";
|
||||
case BTA_HD_API_DISCONNECT_EVT:
|
||||
return "BTA_HD_API_DISCONNECT_EVT";
|
||||
case BTA_HD_API_ADD_DEVICE_EVT:
|
||||
return "BTA_HD_API_ADD_DEVICE_EVT";
|
||||
case BTA_HD_API_REMOVE_DEVICE_EVT:
|
||||
return "BTA_HD_API_REMOVE_DEVICE_EVT";
|
||||
case BTA_HD_API_SEND_REPORT_EVT:
|
||||
return "BTA_HD_API_SEND_REPORT_EVT";
|
||||
case BTA_HD_API_REPORT_ERROR_EVT:
|
||||
return "BTA_HD_API_REPORT_ERROR_EVT";
|
||||
case BTA_HD_API_VC_UNPLUG_EVT:
|
||||
return "BTA_HD_API_VC_UNPLUG_EVT";
|
||||
case BTA_HD_INT_OPEN_EVT:
|
||||
return "BTA_HD_INT_OPEN_EVT";
|
||||
case BTA_HD_INT_CLOSE_EVT:
|
||||
return "BTA_HD_INT_CLOSE_EVT";
|
||||
case BTA_HD_INT_INTR_DATA_EVT:
|
||||
return "BTA_HD_INT_INTR_DATA_EVT";
|
||||
case BTA_HD_INT_GET_REPORT_EVT:
|
||||
return "BTA_HD_INT_GET_REPORT_EVT";
|
||||
case BTA_HD_INT_SET_REPORT_EVT:
|
||||
return "BTA_HD_INT_SET_REPORT_EVT";
|
||||
case BTA_HD_INT_SET_PROTOCOL_EVT:
|
||||
return "BTA_HD_INT_SET_PROTOCOL_EVT";
|
||||
case BTA_HD_INT_VC_UNPLUG_EVT:
|
||||
return "BTA_HD_INT_VC_UNPLUG_EVT";
|
||||
case BTA_HD_INT_SUSPEND_EVT:
|
||||
return "BTA_HD_INT_SUSPEND_EVT";
|
||||
case BTA_HD_INT_EXIT_SUSPEND_EVT:
|
||||
return "BTA_HD_INT_EXIT_SUSPEND_EVT";
|
||||
default:
|
||||
return "<unknown>";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *bta_hd_state_code(tBTA_HD_STATE state_code)
|
||||
{
|
||||
switch (state_code) {
|
||||
case BTA_HD_INIT_ST:
|
||||
return "BTA_HD_INIT_ST";
|
||||
case BTA_HD_IDLE_ST:
|
||||
return "BTA_HD_IDLE_ST";
|
||||
case BTA_HD_CONN_ST:
|
||||
return "BTA_HD_CONN_ST";
|
||||
case BTA_HD_TRANSIENT_TO_INIT_ST:
|
||||
return "BTA_HD_TRANSIENT_TO_INIT_ST";
|
||||
default:
|
||||
return "<unknown>";
|
||||
}
|
||||
}
|
||||
#endif /* BTA_HD_INCLUDED */
|
168
components/bt/host/bluedroid/bta/hd/include/bta_hd_int.h
Normal file
168
components/bt/host/bluedroid/bta/hd/include/bta_hd_int.h
Normal file
@@ -0,0 +1,168 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
* 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 Device internal definitions
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef BTA_HD_INT_H
|
||||
#define BTA_HD_INT_H
|
||||
|
||||
#include "bta/bta_hd_api.h"
|
||||
#include "bta/bta_sys.h"
|
||||
#include "stack/hiddefs.h"
|
||||
|
||||
enum {
|
||||
BTA_HD_API_REGISTER_APP_EVT = BTA_SYS_EVT_START(BTA_ID_HD),
|
||||
BTA_HD_API_UNREGISTER_APP_EVT,
|
||||
BTA_HD_API_CONNECT_EVT,
|
||||
BTA_HD_API_DISCONNECT_EVT,
|
||||
BTA_HD_API_ADD_DEVICE_EVT,
|
||||
BTA_HD_API_REMOVE_DEVICE_EVT,
|
||||
BTA_HD_API_SEND_REPORT_EVT,
|
||||
BTA_HD_API_REPORT_ERROR_EVT,
|
||||
BTA_HD_API_VC_UNPLUG_EVT,
|
||||
BTA_HD_INT_OPEN_EVT,
|
||||
BTA_HD_INT_CLOSE_EVT,
|
||||
BTA_HD_INT_INTR_DATA_EVT,
|
||||
BTA_HD_INT_GET_REPORT_EVT,
|
||||
BTA_HD_INT_SET_REPORT_EVT,
|
||||
BTA_HD_INT_SET_PROTOCOL_EVT,
|
||||
BTA_HD_INT_VC_UNPLUG_EVT,
|
||||
BTA_HD_INT_SUSPEND_EVT,
|
||||
BTA_HD_INT_EXIT_SUSPEND_EVT,
|
||||
/* handled outside state machine */
|
||||
BTA_HD_API_ENABLE_EVT,
|
||||
BTA_HD_API_DISABLE_EVT
|
||||
};
|
||||
typedef uint16_t tBTA_HD_INT_EVT;
|
||||
#define BTA_HD_INVALID_EVT (BTA_HD_API_DISABLE_EVT + 1)
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
tBTA_HD_CBACK *p_cback;
|
||||
} tBTA_HD_API_ENABLE;
|
||||
#define BTA_HD_APP_NAME_LEN 50
|
||||
#define BTA_HD_APP_DESCRIPTION_LEN 50
|
||||
#define BTA_HD_APP_PROVIDER_LEN 50
|
||||
#define BTA_HD_APP_DESCRIPTOR_LEN 2048
|
||||
#define BTA_HD_STATE_DISABLED 0x00
|
||||
#define BTA_HD_STATE_ENABLED 0x01
|
||||
#define BTA_HD_STATE_IDLE 0x02
|
||||
#define BTA_HD_STATE_CONNECTED 0x03
|
||||
#define BTA_HD_STATE_DISABLING 0x04
|
||||
#define BTA_HD_STATE_REMOVING 0x05
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
char name[BTA_HD_APP_NAME_LEN + 1];
|
||||
char description[BTA_HD_APP_DESCRIPTION_LEN + 1];
|
||||
char provider[BTA_HD_APP_PROVIDER_LEN + 1];
|
||||
uint8_t subclass;
|
||||
uint16_t d_len;
|
||||
uint8_t d_data[BTA_HD_APP_DESCRIPTOR_LEN];
|
||||
tBTA_HD_QOS_INFO in_qos;
|
||||
tBTA_HD_QOS_INFO out_qos;
|
||||
} tBTA_HD_REGISTER_APP;
|
||||
|
||||
#define BTA_HD_REPORT_LEN HID_DEV_MTU_SIZE
|
||||
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
bool use_intr;
|
||||
uint8_t type;
|
||||
uint8_t id;
|
||||
uint16_t len;
|
||||
uint8_t data[BTA_HD_REPORT_LEN];
|
||||
} tBTA_HD_SEND_REPORT;
|
||||
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
BD_ADDR addr;
|
||||
} tBTA_HD_DEVICE_CTRL;
|
||||
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
uint8_t error;
|
||||
} tBTA_HD_REPORT_ERR;
|
||||
|
||||
/* union of all event data types */
|
||||
typedef union {
|
||||
BT_HDR hdr;
|
||||
tBTA_HD_API_ENABLE api_enable;
|
||||
tBTA_HD_REGISTER_APP register_app;
|
||||
tBTA_HD_SEND_REPORT send_report;
|
||||
tBTA_HD_DEVICE_CTRL device_ctrl;
|
||||
tBTA_HD_REPORT_ERR report_err;
|
||||
} tBTA_HD_DATA;
|
||||
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
BD_ADDR addr;
|
||||
uint32_t data;
|
||||
BT_HDR *p_data;
|
||||
} tBTA_HD_CBACK_DATA;
|
||||
|
||||
/******************************************************************************
|
||||
* Main Control Block
|
||||
******************************************************************************/
|
||||
typedef struct {
|
||||
tBTA_HD_CBACK *p_cback;
|
||||
uint32_t sdp_handle;
|
||||
uint8_t trace_level;
|
||||
uint8_t state;
|
||||
BD_ADDR bd_addr;
|
||||
bool use_report_id;
|
||||
bool boot_mode;
|
||||
bool vc_unplug;
|
||||
bool disable_w4_close;
|
||||
} tBTA_HD_CB;
|
||||
|
||||
#if BTA_DYNAMIC_MEMORY == FALSE
|
||||
extern tBTA_HD_CB bta_hd_cb;
|
||||
#else
|
||||
extern tBTA_HD_CB *bta_hd_cb_ptr;
|
||||
#define bta_hd_cb (*bta_hd_cb_ptr)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* Function prototypes
|
||||
****************************************************************************/
|
||||
extern bool bta_hd_hdl_event(BT_HDR *p_msg);
|
||||
extern void bta_hd_api_enable(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_api_disable(void);
|
||||
extern void bta_hd_register_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_unregister_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_unregister2_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_connect_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_disconnect_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_add_device_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_remove_device_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_send_report_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_report_error_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_vc_unplug_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_open_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_close_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_intr_data_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_get_report_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_set_report_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_set_protocol_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_vc_unplug_done_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_suspend_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_exit_suspend_act(tBTA_HD_DATA *p_data);
|
||||
|
||||
#endif
|
@@ -323,6 +323,7 @@ void bta_hh_start_sdp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
|
||||
p_cb->sec_mask = p_data->api_conn.sec_mask;
|
||||
p_cb->mode = p_data->api_conn.mode;
|
||||
p_cb->new_mode = p_data->api_conn.mode;
|
||||
bta_hh_cb.p_cur = p_cb;
|
||||
|
||||
#if (BTA_HH_LE_INCLUDED == TRUE)
|
||||
@@ -451,6 +452,8 @@ void bta_hh_sdp_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
HID_HostRemoveDev( p_cb->incoming_hid_handle);
|
||||
}
|
||||
conn_dat.status = status;
|
||||
/* check if host initiate the connection*/
|
||||
conn_dat.is_orig = !p_cb->incoming_conn;
|
||||
(* bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
|
||||
|
||||
/* move state machine W4_CONN ->IDLE */
|
||||
@@ -521,6 +524,8 @@ void bta_hh_open_cmpl_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
|
||||
memset((void *)&conn, 0, sizeof (tBTA_HH_CONN));
|
||||
conn.handle = dev_handle;
|
||||
/* check if host initiate the connection*/
|
||||
conn.is_orig = !p_cb->incoming_conn;
|
||||
bdcpy(conn.bda, p_cb->addr);
|
||||
|
||||
/* increase connection number */
|
||||
@@ -587,6 +592,7 @@ void bta_hh_open_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
APPL_TRACE_EVENT ("bta_hh_open_act: Device[%d] connected", dev_handle);
|
||||
#endif
|
||||
|
||||
p_cb->incoming_conn = TRUE;
|
||||
/* SDP has been done */
|
||||
if (p_cb->app_id != 0) {
|
||||
bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, p_data);
|
||||
@@ -594,7 +600,6 @@ void bta_hh_open_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
/* app_id == 0 indicates an incoming conenction request arrives without SDP
|
||||
performed, do it first */
|
||||
{
|
||||
p_cb->incoming_conn = TRUE;
|
||||
/* store the handle here in case sdp fails - need to disconnect */
|
||||
p_cb->incoming_hid_handle = dev_handle;
|
||||
|
||||
@@ -676,6 +681,11 @@ void bta_hh_handsk_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
case BTA_HH_SET_IDLE_EVT :
|
||||
cback_data.handle = p_cb->hid_handle;
|
||||
cback_data.status = bta_hh_get_trans_status(p_data->hid_cback.data);
|
||||
if (cback_data.status == BTA_HH_OK) {
|
||||
p_cb->mode = p_cb->new_mode;
|
||||
} else {
|
||||
p_cb->new_mode = p_cb->mode;
|
||||
}
|
||||
(* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&cback_data);
|
||||
p_cb->w4_evt = 0;
|
||||
break;
|
||||
@@ -684,6 +694,8 @@ void bta_hh_handsk_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
case BTA_HH_OPEN_EVT:
|
||||
conn.status = p_data->hid_cback.data ? BTA_HH_ERR_PROTO : BTA_HH_OK;
|
||||
conn.handle = p_cb->hid_handle;
|
||||
/* check if host initiate the connection*/
|
||||
conn.is_orig = !p_cb->incoming_conn;
|
||||
bdcpy(conn.bda, p_cb->addr);
|
||||
(* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&conn);
|
||||
#if BTA_HH_DEBUG
|
||||
@@ -787,6 +799,8 @@ void bta_hh_open_failure(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
conn_dat.handle = p_cb->hid_handle;
|
||||
conn_dat.status = (reason == HID_ERR_AUTH_FAILED) ?
|
||||
BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR;
|
||||
/* check if host initiate the connection*/
|
||||
conn_dat.is_orig = !p_cb->incoming_conn;
|
||||
bdcpy(conn_dat.bda, p_cb->addr);
|
||||
HID_HostCloseDev(p_cb->hid_handle);
|
||||
|
||||
@@ -836,6 +850,8 @@ void bta_hh_close_act (tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
/* Failure in opening connection */
|
||||
conn_dat.handle = p_cb->hid_handle;
|
||||
conn_dat.status = (reason == HID_ERR_AUTH_FAILED) ? BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR;
|
||||
/* check if host initiate the connection*/
|
||||
conn_dat.is_orig = !p_cb->incoming_conn;
|
||||
bdcpy(conn_dat.bda, p_cb->addr);
|
||||
HID_HostCloseDev(p_cb->hid_handle);
|
||||
|
||||
@@ -1019,7 +1035,9 @@ void bta_hh_maint_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
*******************************************************************************/
|
||||
void bta_hh_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
{
|
||||
tHID_STATUS status;
|
||||
tBTA_HH_CBDATA cbdata = {BTA_HH_OK, 0};
|
||||
tBTA_HH_API_SENDDATA send_data = {BTA_HH_OK, 0, 0};
|
||||
UINT16 event = (p_data->api_sndcmd.t_type - BTA_HH_FST_BTE_TRANS_EVT) +
|
||||
BTA_HH_FST_TRANS_CB_EVT;
|
||||
|
||||
@@ -1031,25 +1049,33 @@ void bta_hh_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
{
|
||||
|
||||
cbdata.handle = p_cb->hid_handle;
|
||||
send_data.handle = p_cb->hid_handle;
|
||||
|
||||
/* match up BTE/BTA report/boot mode def */
|
||||
if (p_data->api_sndcmd.t_type == HID_TRANS_SET_PROTOCOL) {
|
||||
p_cb->new_mode = p_data->api_sndcmd.param;
|
||||
p_data->api_sndcmd.param = ( p_data->api_sndcmd.param == BTA_HH_PROTO_RPT_MODE) ? \
|
||||
HID_PAR_PROTOCOL_REPORT : HID_PAR_PROTOCOL_BOOT_MODE;
|
||||
}
|
||||
|
||||
if (HID_HostWriteDev (p_cb->hid_handle,
|
||||
p_data->api_sndcmd.t_type,
|
||||
p_data->api_sndcmd.param,
|
||||
p_data->api_sndcmd.data,
|
||||
p_data->api_sndcmd.rpt_id,
|
||||
p_data->api_sndcmd.p_data) != HID_SUCCESS) {
|
||||
APPL_TRACE_ERROR("HID_HostWriteDev Error ");
|
||||
status = HID_HostWriteDev(p_cb->hid_handle, p_data->api_sndcmd.t_type, p_data->api_sndcmd.param,
|
||||
p_data->api_sndcmd.data, p_data->api_sndcmd.rpt_id, p_data->api_sndcmd.p_data);
|
||||
if (status != HID_SUCCESS) {
|
||||
APPL_TRACE_ERROR("HID_HostWriteDev status:%d", status);
|
||||
cbdata.status = BTA_HH_ERR;
|
||||
send_data.status = BTA_HH_ERR;
|
||||
|
||||
if (p_data->api_sndcmd.t_type != HID_TRANS_CONTROL &&
|
||||
p_data->api_sndcmd.t_type != HID_TRANS_DATA) {
|
||||
(* bta_hh_cb.p_cback)(event, (tBTA_HH *)&cbdata);
|
||||
if (p_data->api_sndcmd.t_type != HID_TRANS_CONTROL) {
|
||||
switch (p_data->api_sndcmd.t_type) {
|
||||
case HID_TRANS_DATA:
|
||||
event = BTA_HH_DATA_EVT;
|
||||
send_data.reason = status;
|
||||
(*bta_hh_cb.p_cback)(event, (tBTA_HH *)&send_data);
|
||||
break;
|
||||
default:
|
||||
(*bta_hh_cb.p_cback)(event, (tBTA_HH *)&cbdata);
|
||||
break;
|
||||
}
|
||||
} else if (p_data->api_sndcmd.param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG) {
|
||||
(* bta_hh_cb.p_cback)(BTA_HH_VC_UNPLUG_EVT, (tBTA_HH *)&cbdata);
|
||||
}
|
||||
@@ -1070,6 +1096,7 @@ void bta_hh_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
p_cb->w4_evt = event;
|
||||
break;
|
||||
case HID_TRANS_DATA: /* output report */
|
||||
(*bta_hh_cb.p_cback)(BTA_HH_DATA_EVT, (tBTA_HH *)&send_data);
|
||||
/* fall through */
|
||||
case HID_TRANS_CONTROL:
|
||||
/* no handshake event will be generated */
|
||||
@@ -1098,7 +1125,6 @@ void bta_hh_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
bta_sys_busy(BTA_ID_HH, p_cb->app_id, p_cb->addr);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@@ -24,9 +24,9 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "common/bt_target.h"
|
||||
#include "bta/bta_hh_api.h"
|
||||
|
||||
#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
|
||||
#include "bta/bta_hh_api.h"
|
||||
|
||||
|
||||
/* max number of device types supported by BTA */
|
||||
|
@@ -32,7 +32,7 @@
|
||||
#include "bta/utl.h"
|
||||
|
||||
#define LOG_TAG "bt_bta_hh"
|
||||
#include "osi/include/log.h"
|
||||
// #include "osi/include/log.h"
|
||||
|
||||
#ifndef BTA_HH_LE_RECONN
|
||||
#define BTA_HH_LE_RECONN TRUE
|
||||
|
@@ -292,6 +292,8 @@ void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16 event, tBTA_HH_DATA *p_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:
|
||||
@@ -340,7 +342,7 @@ void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16 event, tBTA_HH_DATA *p_data)
|
||||
|
||||
default:
|
||||
/* invalid handle, call bad API event */
|
||||
APPL_TRACE_ERROR("wrong device handle: [%d]", p_data->hdr.layer_specific);
|
||||
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);
|
||||
@@ -443,6 +445,10 @@ BOOLEAN bta_hh_hdl_event(BT_HDR *p_msg)
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
|
@@ -237,7 +237,7 @@ BOOLEAN bta_hh_tod_spt(tBTA_HH_DEV_CB *p_cb, UINT8 sub_class)
|
||||
}
|
||||
}
|
||||
#if BTA_HH_DEBUG
|
||||
APPL_TRACE_EVENT("bta_hh_tod_spt sub_class:0x%x NOT supported", sub_class);
|
||||
APPL_TRACE_ERROR("bta_hh_tod_spt sub_class:0x%x NOT supported", sub_class);
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
@@ -460,9 +460,11 @@ void bta_hh_cleanup_disable(tBTA_HH_STATUS status)
|
||||
}
|
||||
utl_freebuf((void **)&bta_hh_cb.p_disc_db);
|
||||
|
||||
(* 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));
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@@ -243,6 +243,7 @@ typedef struct {
|
||||
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)
|
||||
@@ -364,6 +365,7 @@ 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);
|
||||
@@ -391,6 +393,7 @@ 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);
|
||||
|
@@ -78,7 +78,7 @@ typedef UINT8 tBTA_STATUS;
|
||||
#define BTA_SAP_SERVICE_ID 17 /* SIM Access profile */
|
||||
#define BTA_A2DP_SINK_SERVICE_ID 18 /* A2DP Sink */
|
||||
#define BTA_AVRCP_SERVICE_ID 19 /* A/V remote control */
|
||||
#define BTA_HID_SERVICE_ID 20 /* HID */
|
||||
#define BTA_HID_SERVICE_ID 20 /* HID Host*/
|
||||
#define BTA_VDP_SERVICE_ID 21 /* Video distribution */
|
||||
#define BTA_PBAP_SERVICE_ID 22 /* PhoneBook Access Server*/
|
||||
#define BTA_HSP_HS_SERVICE_ID 23 /* HFP HS role */
|
||||
@@ -1331,8 +1331,8 @@ typedef UINT8 tBTA_DM_PM_ACTION;
|
||||
#endif
|
||||
|
||||
#ifndef BTA_DM_PM_SNIFF2_MAX
|
||||
#define BTA_DM_PM_SNIFF2_MAX 180
|
||||
#define BTA_DM_PM_SNIFF2_MIN 150
|
||||
#define BTA_DM_PM_SNIFF2_MAX 54 //180
|
||||
#define BTA_DM_PM_SNIFF2_MIN 30 //150
|
||||
#define BTA_DM_PM_SNIFF2_ATTEMPT 4
|
||||
#define BTA_DM_PM_SNIFF2_TIMEOUT 1
|
||||
#endif
|
||||
@@ -1345,8 +1345,8 @@ typedef UINT8 tBTA_DM_PM_ACTION;
|
||||
#endif
|
||||
|
||||
#ifndef BTA_DM_PM_SNIFF4_MAX
|
||||
#define BTA_DM_PM_SNIFF4_MAX 54
|
||||
#define BTA_DM_PM_SNIFF4_MIN 30
|
||||
#define BTA_DM_PM_SNIFF4_MAX 18 //54
|
||||
#define BTA_DM_PM_SNIFF4_MIN 10 //30
|
||||
#define BTA_DM_PM_SNIFF4_ATTEMPT 4
|
||||
#define BTA_DM_PM_SNIFF4_TIMEOUT 1
|
||||
#endif
|
||||
|
295
components/bt/host/bluedroid/bta/include/bta/bta_hd_api.h
Normal file
295
components/bt/host/bluedroid/bta/include/bta/bta_hd_api.h
Normal file
@@ -0,0 +1,295 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
* Copyright (C) 2002-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.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef BTA_HD_API_H
|
||||
#define BTA_HD_API_H
|
||||
|
||||
#include "bta_api.h"
|
||||
#include "stack/hidd_api.h"
|
||||
|
||||
#if BTA_HD_INCLUDED == TRUE
|
||||
|
||||
/*****************************************************************************
|
||||
* Constants and Type Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef BTA_HD_DEBUG
|
||||
#define BTA_HD_DEBUG TRUE
|
||||
#endif
|
||||
|
||||
/* BTA HID Device callback events */
|
||||
#define BTA_HD_ENABLE_EVT 0 /* BT-HD enabled */
|
||||
#define BTA_HD_DISABLE_EVT 1 /* BT-HD disabled */
|
||||
#define BTA_HD_REGISTER_APP_EVT 2 /* application registered */
|
||||
#define BTA_HD_UNREGISTER_APP_EVT 3 /* application unregistered */
|
||||
#define BTA_HD_OPEN_EVT 4 /* connection to host opened */
|
||||
#define BTA_HD_CLOSE_EVT 5 /* connection to host closed */
|
||||
#define BTA_HD_GET_REPORT_EVT 6 /* GET_REPORT request from host */
|
||||
#define BTA_HD_SET_REPORT_EVT 7 /* SET_REPORT request from host */
|
||||
#define BTA_HD_SET_PROTOCOL_EVT 8 /* SET_PROTOCOL request from host */
|
||||
#define BTA_HD_INTR_DATA_EVT 9 /* DATA received from host on intr */
|
||||
#define BTA_HD_VC_UNPLUG_EVT 10 /* Virtual Cable Unplug */
|
||||
// #define BTA_HD_CONN_STATE_EVT 11 /* Report connection state change */
|
||||
#define BTA_HD_SEND_REPORT_EVT 12 /* Send report finish */
|
||||
#define BTA_HD_REPORT_ERR_EVT 13 /* Report Handshake finish */
|
||||
#define BTA_HD_API_ERR_EVT 99 /* BT-HD API error */
|
||||
|
||||
typedef uint16_t tBTA_HD_EVT;
|
||||
|
||||
enum { BTA_HD_OK, BTA_HD_ERROR };
|
||||
|
||||
typedef enum {
|
||||
BTA_HD_CONN_STATE_CONNECTED,
|
||||
BTA_HD_CONN_STATE_CONNECTING,
|
||||
BTA_HD_CONN_STATE_DISCONNECTED,
|
||||
BTA_HD_CONN_STATE_DISCONNECTING,
|
||||
BTA_HD_CONN_STATE_UNKNOWN
|
||||
} tBTA_HD_CONN_STAT;
|
||||
|
||||
typedef uint8_t tBTA_HD_STATUS;
|
||||
typedef tHID_DEV_DSCP_INFO tBTA_HD_DEV_DESCR;
|
||||
|
||||
typedef struct {
|
||||
char *p_name;
|
||||
char *p_description;
|
||||
char *p_provider;
|
||||
uint8_t subclass;
|
||||
tBTA_HD_DEV_DESCR descriptor;
|
||||
} tBTA_HD_APP_INFO;
|
||||
|
||||
typedef struct {
|
||||
uint8_t service_type;
|
||||
uint32_t token_rate;
|
||||
uint32_t token_bucket_size;
|
||||
uint32_t peak_bandwidth;
|
||||
uint32_t access_latency;
|
||||
uint32_t delay_variation;
|
||||
} tBTA_HD_QOS_INFO;
|
||||
|
||||
typedef struct {
|
||||
bool use_intr;
|
||||
uint8_t type;
|
||||
uint8_t id;
|
||||
uint16_t len;
|
||||
uint8_t *p_data;
|
||||
} tBTA_HD_REPORT;
|
||||
|
||||
typedef struct {
|
||||
tBTA_HD_STATUS status;
|
||||
bool in_use;
|
||||
BD_ADDR bda;
|
||||
} tBTA_HD_REG_STATUS;
|
||||
|
||||
typedef struct {
|
||||
BD_ADDR bda;
|
||||
tBTA_HD_STATUS status;
|
||||
tBTA_HD_CONN_STAT conn_status;
|
||||
} tBTA_HD_CONN;
|
||||
|
||||
typedef struct {
|
||||
uint8_t report_type;
|
||||
uint8_t report_id;
|
||||
uint16_t buffer_size;
|
||||
} tBTA_HD_GET_REPORT;
|
||||
|
||||
typedef struct {
|
||||
uint8_t report_type;
|
||||
uint8_t report_id;
|
||||
uint16_t len;
|
||||
uint8_t *p_data;
|
||||
} tBTA_HD_SET_REPORT;
|
||||
|
||||
typedef uint8_t tBTA_HD_SET_PROTOCOL;
|
||||
|
||||
typedef struct {
|
||||
uint8_t report_id;
|
||||
uint16_t len;
|
||||
uint8_t *p_data;
|
||||
} tBTA_HD_INTR_DATA;
|
||||
|
||||
typedef struct {
|
||||
tBTA_HD_STATUS status;
|
||||
uint8_t reason;
|
||||
uint8_t report_type;
|
||||
uint8_t report_id;
|
||||
} tBTA_HD_API_SEND_REPORT;
|
||||
|
||||
typedef struct {
|
||||
tBTA_HD_STATUS status;
|
||||
uint8_t reason;
|
||||
} tBTA_HD_API_REPORT_ERR;
|
||||
|
||||
/* union of data associated with HD callback */
|
||||
typedef union {
|
||||
tBTA_HD_STATUS status; /* BTA_HD_ENABLE_EVT
|
||||
BTA_HD_DISABLE_EVT
|
||||
BTA_HD_UNREGISTER_APP_EVT */
|
||||
tBTA_HD_REG_STATUS reg_status; /* BTA_HD_REGISTER_APP_EVT */
|
||||
tBTA_HD_CONN conn; /* BTA_HD_OPEN_EVT
|
||||
BTA_HD_CLOSE_EVT
|
||||
BTA_HD_VC_UNPLUG_EVT
|
||||
BTA_HD_OWN_VC_UNPLUG_EVT */
|
||||
tBTA_HD_GET_REPORT get_report; /* BTA_HD_GET_REPORT */
|
||||
tBTA_HD_SET_REPORT set_report; /* BTA_HD_SET_REPORT */
|
||||
tBTA_HD_SET_PROTOCOL set_protocol; /* BTA_HD_SETPROTOCOL */
|
||||
tBTA_HD_INTR_DATA intr_data; /* BTA_HD_INTR_DATA_EVT */
|
||||
tBTA_HD_API_SEND_REPORT send_report; /* BTA_HD_API_SEND_REPORT_EVT */
|
||||
tBTA_HD_API_REPORT_ERR report_err; /* BTA_HD_API_REPORT_ERR_EVT */
|
||||
} tBTA_HD;
|
||||
|
||||
/* BTA HD callback function */
|
||||
typedef void (tBTA_HD_CBACK)(tBTA_HD_EVT event, tBTA_HD *p_data);
|
||||
|
||||
/*****************************************************************************
|
||||
* External Function Declarations
|
||||
****************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HhRegister
|
||||
*
|
||||
* Description This function enable HID host and registers HID-Host with
|
||||
* lower layers.
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdEnable(tBTA_HD_CBACK *p_cback);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HhDeregister
|
||||
*
|
||||
* Description This function is called when the host is about power down.
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdDisable(void);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdRegisterApp
|
||||
*
|
||||
* Description This function is called when application should be
|
||||
* registered
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdRegisterApp(tBTA_HD_APP_INFO *p_app_info, tBTA_HD_QOS_INFO *p_in_qos, tBTA_HD_QOS_INFO *p_out_qos);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdUnregisterApp
|
||||
*
|
||||
* Description This function is called when application should be
|
||||
* unregistered
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdUnregisterApp(void);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdSendReport
|
||||
*
|
||||
* Description This function is called when report is to be sent
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdSendReport(tBTA_HD_REPORT *p_report);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdVirtualCableUnplug
|
||||
*
|
||||
* Description This function is called when VCU shall be sent
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdVirtualCableUnplug(void);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdConnect
|
||||
*
|
||||
* Description This function is called when connection to host shall be
|
||||
* made.
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdConnect(BD_ADDR addr);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdDisconnect
|
||||
*
|
||||
* Description This function is called when host shall be disconnected
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdDisconnect(void);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdAddDevice
|
||||
*
|
||||
* Description This function is called when a device is virtually cabled
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdAddDevice(BD_ADDR addr);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdRemoveDevice
|
||||
*
|
||||
* Description This function is called when a device is virtually uncabled
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdRemoveDevice(BD_ADDR addr);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdReportError
|
||||
*
|
||||
* Description This function is called when reporting error for set report
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdReportError(uint8_t error);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BTA_HD_INCLUDED */
|
||||
#endif /* BTA_HD_API_H */
|
@@ -58,7 +58,8 @@
|
||||
#define BTA_HH_VC_UNPLUG_EVT 13 /* virtually unplugged */
|
||||
#define BTA_HH_DATA_EVT 15
|
||||
#define BTA_HH_API_ERR_EVT 16 /* API error is caught */
|
||||
#define BTA_HH_UPDATE_SCPP_EVT 17 /* update scan paramter complete */
|
||||
#define BTA_HH_UPDATE_SCPP_EVT 17 /* update scan paramter complete */
|
||||
#define BTA_HH_DATA_IND_EVT 18 /* Data on interrupt channel */
|
||||
|
||||
typedef UINT16 tBTA_HH_EVT;
|
||||
|
||||
@@ -131,8 +132,8 @@ enum {
|
||||
BTA_HH_ERR_TOD_UNSPT, /* type of device not supported */
|
||||
BTA_HH_ERR_NO_RES, /* out of system resources */
|
||||
BTA_HH_ERR_AUTH_FAILED, /* authentication fail */
|
||||
BTA_HH_ERR_HDL,
|
||||
BTA_HH_ERR_SEC
|
||||
BTA_HH_ERR_HDL, /* connection handle error */
|
||||
BTA_HH_ERR_SEC, /* encryption error */
|
||||
};
|
||||
typedef UINT8 tBTA_HH_STATUS;
|
||||
|
||||
@@ -210,6 +211,7 @@ typedef struct {
|
||||
BD_ADDR bda; /* HID device bd address */
|
||||
tBTA_HH_STATUS status; /* operation status */
|
||||
UINT8 handle; /* device handle */
|
||||
BOOLEAN is_orig; /* indicate if host initiate connection */
|
||||
#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
|
||||
BOOLEAN le_hid; /* is LE devices? */
|
||||
BOOLEAN scps_supported; /* scan parameter service supported */
|
||||
@@ -257,9 +259,9 @@ typedef struct {
|
||||
typedef struct {
|
||||
tBTA_HH_BOOT_RPT_ID dev_type; /* type of device report */
|
||||
union {
|
||||
tBTA_HH_KEYBD_RPT keybd_rpt; /* keyboard report */
|
||||
tBTA_HH_MICE_RPT mice_rpt; /* mouse report */
|
||||
} data_rpt;
|
||||
tBTA_HH_KEYBD_RPT keybd_rpt; /* keyboard report */
|
||||
tBTA_HH_MICE_RPT mice_rpt; /* mouse report */
|
||||
} data_rpt;
|
||||
} tBTA_HH_BOOT_RPT;
|
||||
|
||||
/* handshake data */
|
||||
@@ -267,13 +269,29 @@ typedef struct {
|
||||
tBTA_HH_STATUS status; /* handshake status */
|
||||
UINT8 handle; /* device handle */
|
||||
union {
|
||||
tBTA_HH_PROTO_MODE proto_mode; /* GET_PROTO_EVT :protocol mode */
|
||||
BT_HDR *p_rpt_data; /* GET_RPT_EVT : report data */
|
||||
UINT8 idle_rate; /* GET_IDLE_EVT : idle rate */
|
||||
} rsp_data;
|
||||
tBTA_HH_PROTO_MODE proto_mode; /* GET_PROTO_EVT :protocol mode */
|
||||
BT_HDR *p_rpt_data; /* GET_RPT_EVT : report data */
|
||||
UINT8 idle_rate; /* GET_IDLE_EVT : idle rate */
|
||||
} rsp_data;
|
||||
|
||||
} tBTA_HH_HSDATA;
|
||||
|
||||
|
||||
/* upper layer send data */
|
||||
typedef struct {
|
||||
tBTA_HH_STATUS status; /* handshake status */
|
||||
UINT8 handle; /* device handle */
|
||||
UINT8 reason; /* send data failed reason */
|
||||
} tBTA_HH_API_SENDDATA;
|
||||
|
||||
/* interrupt channel data */
|
||||
typedef struct {
|
||||
tBTA_HH_STATUS status; /* handshake status */
|
||||
UINT8 handle; /* device handle */
|
||||
tBTA_HH_PROTO_MODE proto_mode; /* protocol mode */
|
||||
BT_HDR *p_data; /* DATA_EVT : feature report data */
|
||||
} tBTA_HH_INTDATA;
|
||||
|
||||
/* union of data associated with HD callback */
|
||||
typedef union {
|
||||
tBTA_HH_DEV_INFO dev_info; /* BTA_HH_ADD_DEV_EVT, BTA_HH_RMV_DEV_EVT */
|
||||
@@ -290,10 +308,12 @@ typedef union {
|
||||
BTA_HH_GET_RPT_EVT
|
||||
BTA_HH_GET_PROTO_EVT
|
||||
BTA_HH_GET_IDLE_EVT */
|
||||
tBTA_HH_API_SENDDATA send_data; /* BTA_HH_DATA_EVT */
|
||||
tBTA_HH_INTDATA int_data; /* BTA_HH_DATA_IND_EVT */
|
||||
} tBTA_HH;
|
||||
|
||||
/* BTA HH callback function */
|
||||
typedef void (tBTA_HH_CBACK) (tBTA_HH_EVT event, tBTA_HH *p_data);
|
||||
typedef void (tBTA_HH_CBACK)(tBTA_HH_EVT event, tBTA_HH *p_data);
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
|
@@ -16,11 +16,13 @@
|
||||
#include "btc/btc_storage.h"
|
||||
#include "btc/btc_util.h"
|
||||
#include "osi/osi.h"
|
||||
#include "osi/allocator.h"
|
||||
#include "common/bt_trace.h"
|
||||
#include "esp_system.h"
|
||||
#include "bta/bta_api.h"
|
||||
#include "device/bdaddr.h"
|
||||
#include "btc/btc_config.h"
|
||||
#include "btc_hh.h"
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
@@ -247,3 +249,252 @@ bt_status_t btc_storage_get_bonded_bt_devices_list(bt_bdaddr_t *bond_dev, int *d
|
||||
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#if (defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE)
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_storage_add_hid_device_info
|
||||
*
|
||||
* Description BTC storage API - Adds the hid information of bonded hid
|
||||
* devices-to NVRAM
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS if the store was successful,
|
||||
* BT_STATUS_FAIL otherwise
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
bt_status_t btc_storage_add_hid_device_info(bt_bdaddr_t *remote_bd_addr, uint16_t attr_mask, uint8_t sub_class,
|
||||
uint8_t app_id, uint16_t vendor_id, uint16_t product_id, uint16_t version,
|
||||
uint8_t ctry_code, uint16_t ssr_max_latency, uint16_t ssr_min_tout,
|
||||
uint16_t dl_len, uint8_t *dsc_list)
|
||||
{
|
||||
BTC_TRACE_DEBUG("btc_storage_add_hid_device_info:");
|
||||
bdstr_t bdstr;
|
||||
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
|
||||
btc_config_lock();
|
||||
int ret = btc_config_set_int(bdstr, "HidAttrMask", attr_mask);
|
||||
ret &= btc_config_set_int(bdstr, "HidSubClass", sub_class);
|
||||
ret &= btc_config_set_int(bdstr, "HidAppId", app_id);
|
||||
ret &= btc_config_set_int(bdstr, "HidVendorId", vendor_id);
|
||||
ret &= btc_config_set_int(bdstr, "HidProductId", product_id);
|
||||
ret &= btc_config_set_int(bdstr, "HidVersion", version);
|
||||
ret &= btc_config_set_int(bdstr, "HidCountryCode", ctry_code);
|
||||
ret &= btc_config_set_int(bdstr, "HidSSRMaxLatency", ssr_max_latency);
|
||||
ret &= btc_config_set_int(bdstr, "HidSSRMinTimeout", ssr_min_tout);
|
||||
if (dl_len > 0)
|
||||
btc_config_set_bin(bdstr, "HidDescriptor", dsc_list, dl_len);
|
||||
btc_config_flush();
|
||||
btc_config_unlock();
|
||||
|
||||
BTC_TRACE_DEBUG("Storage add hid device info %d\n", ret);
|
||||
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_storage_load_bonded_hid_info
|
||||
*
|
||||
* Description BTIF storage API - Loads hid info for all the bonded devices
|
||||
* from NVRAM and adds those devices to the BTA_HH.
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
|
||||
*
|
||||
******************************************************************************/
|
||||
bt_status_t btc_storage_load_bonded_hid_info(void)
|
||||
{
|
||||
int value;
|
||||
btc_config_lock();
|
||||
for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
|
||||
iter = btc_config_section_next(iter)) {
|
||||
const char *name = btc_config_section_name(iter);
|
||||
if (string_is_bdaddr(name) && btc_config_exist(name, BTC_STORAGE_LINK_KEY_TYPE_STR) &&
|
||||
btc_config_exist(name, BTC_STORAGE_PIN_LENGTH_STR) && btc_config_exist(name, BTC_STORAGE_SC_SUPPORT) &&
|
||||
btc_config_exist(name, BTC_STORAGE_LINK_KEY_STR) && btc_config_exist(name, "HidAttrMask")) {
|
||||
btc_config_get_int(name, "HidAttrMask", &value);
|
||||
uint16_t attr_mask = (uint16_t)value;
|
||||
|
||||
tBTA_HH_DEV_DSCP_INFO dscp_info;
|
||||
memset(&dscp_info, 0, sizeof(dscp_info));
|
||||
|
||||
btc_config_get_int(name, "HidSubClass", &value);
|
||||
uint8_t sub_class = (uint8_t)value;
|
||||
|
||||
btc_config_get_int(name, "HidAppId", &value);
|
||||
uint8_t app_id = (uint8_t)value;
|
||||
|
||||
btc_config_get_int(name, "HidVendorId", &value);
|
||||
dscp_info.vendor_id = (uint16_t)value;
|
||||
|
||||
btc_config_get_int(name, "HidProductId", &value);
|
||||
dscp_info.product_id = (uint16_t)value;
|
||||
|
||||
btc_config_get_int(name, "HidVersion", &value);
|
||||
dscp_info.version = (uint8_t)value;
|
||||
|
||||
btc_config_get_int(name, "HidCountryCode", &value);
|
||||
dscp_info.ctry_code = (uint8_t)value;
|
||||
|
||||
value = 0;
|
||||
btc_config_get_int(name, "HidSSRMaxLatency", &value);
|
||||
dscp_info.ssr_max_latency = (uint16_t)value;
|
||||
|
||||
value = 0;
|
||||
btc_config_get_int(name, "HidSSRMinTimeout", &value);
|
||||
dscp_info.ssr_min_tout = (uint16_t)value;
|
||||
|
||||
size_t len = btc_config_get_bin_length(name, "HidDescriptor");
|
||||
if (len > 0) {
|
||||
dscp_info.descriptor.dl_len = (uint16_t)len;
|
||||
dscp_info.descriptor.dsc_list = (uint8_t *)osi_malloc(len);
|
||||
btc_config_get_bin(name, "HidDescriptor", (uint8_t *)dscp_info.descriptor.dsc_list, &len);
|
||||
}
|
||||
|
||||
// add extracted information to BTA HH
|
||||
bt_bdaddr_t bd_addr;
|
||||
if (string_to_bdaddr(name, &bd_addr) && btc_hh_add_added_dev(*(BD_ADDR *)&bd_addr, attr_mask)) {
|
||||
BTA_HhAddDev(*(BD_ADDR *)&bd_addr, attr_mask, sub_class, app_id, dscp_info);
|
||||
}
|
||||
|
||||
if (dscp_info.descriptor.dsc_list) {
|
||||
osi_free(dscp_info.descriptor.dsc_list);
|
||||
dscp_info.descriptor.dsc_list = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
btc_config_unlock();
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_storage_remove_hid_info
|
||||
*
|
||||
* Description BTC storage API - Deletes the bonded hid device info from
|
||||
* NVRAM
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS if the deletion was successful,
|
||||
* BT_STATUS_FAIL otherwise
|
||||
*
|
||||
******************************************************************************/
|
||||
bt_status_t btc_storage_remove_hid_info(bt_bdaddr_t *remote_bd_addr)
|
||||
{
|
||||
bdstr_t bdstr;
|
||||
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
|
||||
int ret = 1;
|
||||
btc_config_lock();
|
||||
if (btc_config_exist(bdstr, "HidAttrMask")) {
|
||||
ret &= btc_config_remove(bdstr, "HidAttrMask");
|
||||
}
|
||||
if (btc_config_exist(bdstr, "HidSubClass")) {
|
||||
ret &= btc_config_remove(bdstr, "HidSubClass");
|
||||
}
|
||||
if (btc_config_exist(bdstr, "HidAppId")) {
|
||||
ret &= btc_config_remove(bdstr, "HidAppId");
|
||||
}
|
||||
if (btc_config_exist(bdstr, "HidVendorId")) {
|
||||
ret &= btc_config_remove(bdstr, "HidVendorId");
|
||||
}
|
||||
if (btc_config_exist(bdstr, "HidProductId")) {
|
||||
ret &= btc_config_remove(bdstr, "HidProductId");
|
||||
}
|
||||
if (btc_config_exist(bdstr, "HidVersion")) {
|
||||
ret &= btc_config_remove(bdstr, "HidVersion");
|
||||
}
|
||||
if (btc_config_exist(bdstr, "HidCountryCode")) {
|
||||
ret &= btc_config_remove(bdstr, "HidCountryCode");
|
||||
}
|
||||
if (btc_config_exist(bdstr, "HidSSRMaxLatency")) {
|
||||
ret &= btc_config_remove(bdstr, "HidSSRMaxLatency");
|
||||
}
|
||||
if (btc_config_exist(bdstr, "HidSSRMinTimeout")) {
|
||||
ret &= btc_config_remove(bdstr, "HidSSRMinTimeout");
|
||||
}
|
||||
if (btc_config_exist(bdstr, "HidDescriptor")) {
|
||||
ret &= btc_config_remove(bdstr, "HidDescriptor");
|
||||
}
|
||||
btc_config_flush();
|
||||
btc_config_unlock();
|
||||
BTC_TRACE_DEBUG("%s ret:%d", __func__, ret);
|
||||
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
|
||||
}
|
||||
#endif //(defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE)
|
||||
|
||||
#if (defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE)
|
||||
#include "bta/bta_hd_api.h"
|
||||
/*******************************************************************************
|
||||
* Function btc_storage_load_hidd
|
||||
*
|
||||
* Description Loads hidd bonded device and "plugs" it into hidd
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
|
||||
*
|
||||
******************************************************************************/
|
||||
bt_status_t btc_storage_load_hidd(void)
|
||||
{
|
||||
bt_bdaddr_t bd_addr;
|
||||
int value;
|
||||
btc_config_lock();
|
||||
for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
|
||||
iter = btc_config_section_next(iter)) {
|
||||
const char *name = btc_config_section_name(iter);
|
||||
if (string_is_bdaddr(name) && btc_config_exist(name, BTC_STORAGE_LINK_KEY_TYPE_STR) &&
|
||||
btc_config_exist(name, BTC_STORAGE_PIN_LENGTH_STR) && btc_config_exist(name, BTC_STORAGE_SC_SUPPORT) &&
|
||||
btc_config_exist(name, BTC_STORAGE_LINK_KEY_STR)) {
|
||||
BTC_TRACE_DEBUG("Remote device:%s", name);
|
||||
if (btc_config_get_int(name, "HidDeviceCabled", &value)) {
|
||||
string_to_bdaddr(name, &bd_addr);
|
||||
BTA_HdAddDevice(bd_addr.address);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
btc_config_unlock();
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_storage_set_hidd
|
||||
*
|
||||
* Description Stores hidd bonded device info in nvram.
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
bt_status_t btc_storage_set_hidd(bt_bdaddr_t *remote_bd_addr)
|
||||
{
|
||||
bdstr_t bdstr = {0};
|
||||
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
|
||||
btc_config_lock();
|
||||
int ret = btc_config_set_int(bdstr, "HidDeviceCabled", 1);
|
||||
btc_config_flush();
|
||||
btc_config_unlock();
|
||||
BTC_TRACE_DEBUG("%s ret:%d", __func__, ret);
|
||||
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_storage_remove_hidd
|
||||
*
|
||||
* Description Removes hidd bonded device info from nvram
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
bt_status_t btc_storage_remove_hidd(bt_bdaddr_t *remote_bd_addr)
|
||||
{
|
||||
bdstr_t bdstr;
|
||||
int ret = 0;
|
||||
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
|
||||
btc_config_lock();
|
||||
if (btc_config_exist(bdstr, "HidVersion")) {
|
||||
ret = btc_config_remove(bdstr, "HidDeviceCabled");
|
||||
}
|
||||
btc_config_flush();
|
||||
btc_config_unlock();
|
||||
|
||||
BTC_TRACE_DEBUG("%s ret:%d", __func__, ret);
|
||||
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
|
||||
}
|
||||
#endif //(defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE)
|
||||
|
@@ -35,6 +35,10 @@
|
||||
#include "bta/bta_ag_api.h"
|
||||
#endif ///BTA_AG_INCLUDED == TRUE
|
||||
|
||||
#if (BTA_HH_INCLUDED == TRUE)
|
||||
#include "bta/bta_hh_api.h"
|
||||
#endif ///BTA_HH_INCLUDED == TRUE
|
||||
#include "bta/bta_hd_api.h"
|
||||
#include "common/bt_defs.h"
|
||||
#include "stack/btm_api.h"
|
||||
#include "bta/bta_api.h"
|
||||
@@ -209,6 +213,56 @@ const char* dump_hf_call_setup_state(esp_hf_call_setup_status_t call_setup_state
|
||||
|
||||
#endif // #if (BTA_AG_INCLUDED == TRUE)
|
||||
|
||||
#if (BTA_HH_INCLUDED == TRUE)
|
||||
const char *dump_hh_event(uint16_t event)
|
||||
{
|
||||
switch (event) {
|
||||
CASE_RETURN_STR(BTA_HH_ENABLE_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_DISABLE_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_OPEN_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_CLOSE_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_GET_RPT_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_SET_RPT_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_GET_PROTO_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_SET_PROTO_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_GET_IDLE_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_SET_IDLE_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_GET_DSCP_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_ADD_DEV_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_RMV_DEV_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_VC_UNPLUG_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_DATA_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_API_ERR_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_UPDATE_SCPP_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_DATA_IND_EVT)
|
||||
default:
|
||||
return "UNKNOWN MSG ID";
|
||||
}
|
||||
}
|
||||
#endif ///BTA_HH_INCLUDED
|
||||
|
||||
#if BTA_HD_INCLUDED == TRUE
|
||||
const char* dump_hd_event(uint16_t event) {
|
||||
switch (event) {
|
||||
CASE_RETURN_STR(BTA_HD_ENABLE_EVT)
|
||||
CASE_RETURN_STR(BTA_HD_DISABLE_EVT)
|
||||
CASE_RETURN_STR(BTA_HD_REGISTER_APP_EVT)
|
||||
CASE_RETURN_STR(BTA_HD_UNREGISTER_APP_EVT)
|
||||
CASE_RETURN_STR(BTA_HD_OPEN_EVT)
|
||||
CASE_RETURN_STR(BTA_HD_CLOSE_EVT)
|
||||
CASE_RETURN_STR(BTA_HD_GET_REPORT_EVT)
|
||||
CASE_RETURN_STR(BTA_HD_SET_REPORT_EVT)
|
||||
CASE_RETURN_STR(BTA_HD_SET_PROTOCOL_EVT)
|
||||
CASE_RETURN_STR(BTA_HD_INTR_DATA_EVT)
|
||||
CASE_RETURN_STR(BTA_HD_VC_UNPLUG_EVT)
|
||||
//CASE_RETURN_STR(BTA_HD_CONN_STATE_EVT)
|
||||
CASE_RETURN_STR(BTA_HD_API_ERR_EVT)
|
||||
default:
|
||||
return "UNKNOWN MSG ID";
|
||||
}
|
||||
}
|
||||
#endif ///BTA_HD_INCLUDED
|
||||
|
||||
UINT32 devclass2uint(DEV_CLASS dev_class)
|
||||
{
|
||||
UINT32 cod = 0;
|
||||
|
@@ -27,6 +27,10 @@
|
||||
#define BTC_STORAGE_PIN_LENGTH_STR "PinLength"
|
||||
#define BTC_STORAGE_SC_SUPPORT "SCSupport"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btc_storage_add_bonded_device
|
||||
@@ -91,4 +95,85 @@ int btc_storage_get_num_bt_bond_devices(void);
|
||||
*******************************************************************************/
|
||||
bt_status_t btc_storage_get_bonded_bt_devices_list(bt_bdaddr_t *bond_dev, int *dev_num);
|
||||
|
||||
#if (defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE)
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_storage_add_hid_device_info
|
||||
*
|
||||
* Description BTC storage API - Adds the hid information of bonded hid
|
||||
* devices-to NVRAM
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS if the store was successful,
|
||||
* BT_STATUS_FAIL otherwise
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
bt_status_t btc_storage_add_hid_device_info(bt_bdaddr_t *remote_bd_addr, uint16_t attr_mask, uint8_t sub_class,
|
||||
uint8_t app_id, uint16_t vendor_id, uint16_t product_id, uint16_t version,
|
||||
uint8_t ctry_code, uint16_t ssr_max_latency, uint16_t ssr_min_tout,
|
||||
uint16_t dl_len, uint8_t *dsc_list);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_storage_load_bonded_hid_info
|
||||
*
|
||||
* Description BTIF storage API - Loads hid info for all the bonded devices
|
||||
* from NVRAM and adds those devices to the BTA_HH.
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
|
||||
*
|
||||
******************************************************************************/
|
||||
bt_status_t btc_storage_load_bonded_hid_info(void);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_storage_remove_hid_info
|
||||
*
|
||||
* Description BTC storage API - Deletes the bonded hid device info from
|
||||
* NVRAM
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS if the deletion was successful,
|
||||
* BT_STATUS_FAIL otherwise
|
||||
*
|
||||
******************************************************************************/
|
||||
bt_status_t btc_storage_remove_hid_info(bt_bdaddr_t *remote_bd_addr);
|
||||
#endif // (defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE)
|
||||
|
||||
#if (defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE)
|
||||
/*******************************************************************************
|
||||
* Function btc_storage_load_hidd
|
||||
*
|
||||
* Description Loads hidd bonded device and "plugs" it into hidd
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
|
||||
*
|
||||
******************************************************************************/
|
||||
bt_status_t btc_storage_load_hidd(void);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_storage_set_hidd
|
||||
*
|
||||
* Description Stores hidd bonded device info in nvram.
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
bt_status_t btc_storage_set_hidd(bt_bdaddr_t *remote_bd_addr);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_storage_remove_hidd
|
||||
*
|
||||
* Description Removes hidd bonded device info from nvram
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
bt_status_t btc_storage_remove_hidd(bt_bdaddr_t *remote_bd_addr);
|
||||
#endif //(defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE)
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BTC_STORAGE_H */
|
||||
|
@@ -31,7 +31,9 @@
|
||||
********************************************************************************/
|
||||
typedef char bdstr_t[18];
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*******************************************************************************
|
||||
** Functions
|
||||
********************************************************************************/
|
||||
@@ -48,6 +50,14 @@ const char *dump_hf_call_state(esp_hf_call_status_t call_state);
|
||||
const char* dump_hf_call_setup_state(esp_hf_call_setup_status_t call_setup_state);
|
||||
#endif
|
||||
|
||||
#if(BTA_HD_INCLUDED == TRUE)
|
||||
const char* dump_hd_event(uint16_t event);
|
||||
#endif
|
||||
|
||||
#if(BTA_HH_INCLUDED == TRUE)
|
||||
const char* dump_hh_event(uint16_t event);
|
||||
#endif
|
||||
|
||||
UINT32 devclass2uint(DEV_CLASS dev_class);
|
||||
void uint2devclass(UINT32 dev, DEV_CLASS dev_class);
|
||||
void uuid128_be_to_esp_uuid(esp_bt_uuid_t *u, uint8_t* uuid128);
|
||||
@@ -58,4 +68,8 @@ esp_bt_status_t btc_hci_to_esp_status(uint8_t hci_status);
|
||||
esp_bt_status_t btc_btm_status_to_esp_status (uint8_t btm_status);
|
||||
esp_bt_status_t btc_bta_status_to_esp_status (uint8_t bta_status);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __BTC_UTIL_H__ */
|
||||
|
152
components/bt/host/bluedroid/btc/profile/std/hid/bta_hh_co.c
Normal file
152
components/bt/host/bluedroid/btc/profile/std/hid/bta_hh_co.c
Normal file
@@ -0,0 +1,152 @@
|
||||
#include "btc_hh.h"
|
||||
#include "osi/allocator.h"
|
||||
#include "string.h"
|
||||
#if HID_HOST_INCLUDED == TRUE
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hh_co_open
|
||||
*
|
||||
* Description When connection is opened, this call-out function is executed
|
||||
* by HH to do platform specific initialization.
|
||||
*
|
||||
* Returns void.
|
||||
******************************************************************************/
|
||||
void bta_hh_co_open(uint8_t dev_handle, uint8_t sub_class, tBTA_HH_ATTR_MASK attr_mask, uint8_t app_id)
|
||||
{
|
||||
uint32_t i;
|
||||
btc_hh_device_t *p_dev = NULL;
|
||||
|
||||
if (dev_handle == BTA_HH_INVALID_HANDLE) {
|
||||
APPL_TRACE_WARNING("%s: Oops, dev_handle (%d) is invalid...", __func__, dev_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < BTC_HH_MAX_HID; i++) {
|
||||
p_dev = &btc_hh_cb.devices[i];
|
||||
if (p_dev->dev_status != ESP_HIDH_CONN_STATE_UNKNOWN && p_dev->dev_handle == dev_handle) {
|
||||
// We found a device with the same handle. Must be a device reconnected.
|
||||
APPL_TRACE_WARNING("%s: Found an existing device with the same handle dev_status=%d, "
|
||||
"dev_handle=0x%2x, attr_mask=0x%04x, sub_class=0x%02x, app_id=%d",
|
||||
__func__, p_dev->dev_status, dev_handle, p_dev->attr_mask, p_dev->sub_class,
|
||||
p_dev->app_id);
|
||||
break;
|
||||
}
|
||||
p_dev = NULL;
|
||||
}
|
||||
|
||||
if (p_dev == NULL) {
|
||||
// Did not find a device reconnection case. Find an empty slot now.
|
||||
for (i = 0; i < BTC_HH_MAX_HID; i++) {
|
||||
if (btc_hh_cb.devices[i].dev_status == ESP_HIDH_CONN_STATE_UNKNOWN) {
|
||||
p_dev = &btc_hh_cb.devices[i];
|
||||
p_dev->dev_handle = dev_handle;
|
||||
p_dev->attr_mask = attr_mask;
|
||||
p_dev->sub_class = sub_class;
|
||||
p_dev->app_id = app_id;
|
||||
p_dev->local_vup = false;
|
||||
|
||||
btc_hh_cb.device_num++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p_dev == NULL) {
|
||||
APPL_TRACE_ERROR("%s: Error: too many HID devices are connected", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
p_dev->dev_status = ESP_HIDH_CONN_STATE_CONNECTED;
|
||||
APPL_TRACE_DEBUG("%s: Return device status %d", __func__, p_dev->dev_status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hh_co_close
|
||||
*
|
||||
* Description When connection is closed, this call-out function is executed
|
||||
* by HH to do platform specific finalization.
|
||||
*
|
||||
* Parameters dev_handle - device handle
|
||||
* app_id - application id
|
||||
*
|
||||
* Returns void.
|
||||
******************************************************************************/
|
||||
void bta_hh_co_close(uint8_t dev_handle, uint8_t app_id)
|
||||
{
|
||||
uint32_t i;
|
||||
btc_hh_device_t *p_dev = NULL;
|
||||
|
||||
APPL_TRACE_WARNING("%s: dev_handle = %d, app_id = %d", __func__, dev_handle, app_id);
|
||||
if (dev_handle == BTA_HH_INVALID_HANDLE) {
|
||||
APPL_TRACE_WARNING("%s: Oops, dev_handle (%d) is invalid...", __func__, dev_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < BTC_HH_MAX_HID; i++) {
|
||||
p_dev = &btc_hh_cb.devices[i];
|
||||
if (p_dev->dev_status != ESP_HIDH_CONN_STATE_UNKNOWN && p_dev->dev_handle == dev_handle) {
|
||||
APPL_TRACE_WARNING("%s: Found an existing device with the same handle "
|
||||
"dev_status = %d, dev_handle =%d",
|
||||
__func__, p_dev->dev_status, p_dev->dev_handle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hh_co_data
|
||||
*
|
||||
* Description This function is executed by BTA when HID host receive a
|
||||
* data report on interrupt channel.
|
||||
*
|
||||
* Parameters dev_handle - device handle
|
||||
* *p_rpt - pointer to the report data
|
||||
* len - length of report data
|
||||
* mode - Hid host Protocol Mode
|
||||
* sub_clas - Device Subclass
|
||||
* app_id - application id
|
||||
*
|
||||
* Returns void
|
||||
******************************************************************************/
|
||||
void bta_hh_co_data(UINT8 dev_handle, UINT8 *p_rpt, UINT16 len, tBTA_HH_PROTO_MODE mode, UINT8 sub_class, UINT8 ctry_code,
|
||||
BD_ADDR peer_addr, UINT8 app_id)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
tBTA_HH p_data;
|
||||
BT_HDR *p_buf = NULL;
|
||||
bt_status_t status;
|
||||
tBTA_HH_STATUS ret = BTA_HH_OK;
|
||||
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTA_HH_DATA_IND_EVT;
|
||||
|
||||
APPL_TRACE_DEBUG("%s: dev_handle = %d, subclass = 0x%02X, mode = %d, "
|
||||
"ctry_code = %d, app_id = %d",
|
||||
__func__, dev_handle, sub_class, mode, ctry_code, app_id);
|
||||
|
||||
do {
|
||||
if ((p_buf = osi_malloc(sizeof(BT_HDR) + len)) == NULL) {
|
||||
APPL_TRACE_ERROR("%s malloc failed!", __func__);
|
||||
ret = BTA_HH_ERR_NO_RES;
|
||||
break;
|
||||
}
|
||||
p_buf->offset = 0;
|
||||
p_buf->len = len;
|
||||
p_buf->event = 0;
|
||||
p_buf->layer_specific = dev_handle;
|
||||
memcpy(p_buf->data, p_rpt, len);
|
||||
} while (0);
|
||||
|
||||
p_data.int_data.status = ret;
|
||||
p_data.int_data.handle = dev_handle;
|
||||
p_data.int_data.p_data = p_buf;
|
||||
p_data.int_data.proto_mode = mode;
|
||||
status = btc_transfer_context(&msg, &p_data, sizeof(tBTA_HH), NULL);
|
||||
assert(status == BT_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
#endif /* HID_HOST_INCLUDED == TRUE */
|
831
components/bt/host/bluedroid/btc/profile/std/hid/btc_hd.c
Normal file
831
components/bt/host/bluedroid/btc/profile/std/hid/btc_hd.c
Normal file
@@ -0,0 +1,831 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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 "bta/bta_api.h"
|
||||
#include "bta/bta_hd_api.h"
|
||||
#include "bta/bta_hh_api.h"
|
||||
#include "bta/utl.h"
|
||||
#include "btc/btc_storage.h"
|
||||
#include "btc/btc_util.h"
|
||||
#include "btc/btc_manage.h"
|
||||
#include "btc_hd.h"
|
||||
|
||||
#include "osi/allocator.h"
|
||||
|
||||
#include "esp_hidd_api.h"
|
||||
|
||||
#if HID_DEV_INCLUDED == TRUE
|
||||
#include "bta_dm_int.h"
|
||||
|
||||
/* HD request events */
|
||||
typedef enum { BTC_HD_DUMMY_REQ_EVT = 0 } btc_hd_req_evt_t;
|
||||
|
||||
/*******************************************************************************
|
||||
* Static variables
|
||||
******************************************************************************/
|
||||
btc_hd_cb_t btc_hd_cb;
|
||||
|
||||
// static tBTA_HD_APP_INFO app_info;
|
||||
// static tBTA_HD_QOS_INFO in_qos;
|
||||
// static tBTA_HD_QOS_INFO out_qos;
|
||||
|
||||
/******************************************************************************
|
||||
* Constants & Macros
|
||||
*****************************************************************************/
|
||||
#define BTC_HD_APP_NAME_LEN 50
|
||||
#define BTC_HD_APP_DESCRIPTION_LEN 50
|
||||
#define BTC_HD_APP_PROVIDER_LEN 50
|
||||
#define BTC_HD_APP_DESCRIPTOR_LEN 2048
|
||||
#define COD_HID_KEYBOARD 0x0540
|
||||
#define COD_HID_POINTING 0x0580
|
||||
#define COD_HID_COMBO 0x05C0
|
||||
#define COD_HID_MAJOR 0x0500
|
||||
|
||||
#define is_hidd_init() (btc_hd_cb.status > BTC_HD_DISABLED)
|
||||
#define is_hidd_app_register() (btc_hd_cb.app_registered)
|
||||
|
||||
typedef void (bt_hid_copy_cb_t)(btc_msg_t *msg, void *p_dest, void *p_src);
|
||||
|
||||
static inline void btc_hd_cb_to_app(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param)
|
||||
{
|
||||
esp_hd_cb_t *btc_hd_cb = (esp_hd_cb_t *)btc_profile_cb_get(BTC_PID_HD);
|
||||
if (btc_hd_cb) {
|
||||
btc_hd_cb(event, param);
|
||||
}
|
||||
}
|
||||
|
||||
static void free_app_info_param(void)
|
||||
{
|
||||
utl_freebuf((void **)&btc_hd_cb.app_info.descriptor.dsc_list);
|
||||
utl_freebuf((void **)&btc_hd_cb.app_info.p_provider);
|
||||
utl_freebuf((void **)&btc_hd_cb.app_info.p_description);
|
||||
utl_freebuf((void **)&btc_hd_cb.app_info.p_name);
|
||||
}
|
||||
|
||||
static void bte_hd_arg_deep_copy(btc_msg_t *msg, void *p_dst, void *p_src)
|
||||
{
|
||||
tBTA_HD *p_dst_data = (tBTA_HD *)p_dst;
|
||||
tBTA_HD *p_src_data = (tBTA_HD *)p_src;
|
||||
switch (msg->act)
|
||||
{
|
||||
case BTA_HD_SET_REPORT_EVT: {
|
||||
uint8_t *src_data = p_src_data->set_report.p_data;
|
||||
if (src_data) {
|
||||
p_dst_data->set_report.p_data = osi_malloc(p_src_data->set_report.len);
|
||||
if (p_dst_data->set_report.p_data == NULL) {
|
||||
BTC_TRACE_ERROR("%s malloc set_report data failed!", __func__);
|
||||
break;
|
||||
}
|
||||
memcpy(p_dst_data->set_report.p_data, src_data, p_src_data->set_report.len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BTA_HD_INTR_DATA_EVT: {
|
||||
uint8_t *src_data = p_src_data->intr_data.p_data;
|
||||
if (src_data) {
|
||||
p_dst_data->intr_data.p_data = osi_malloc(p_src_data->intr_data.len);
|
||||
if (p_dst_data->intr_data.p_data == NULL) {
|
||||
BTC_TRACE_ERROR("%s malloc intr_data data failed!", __func__);
|
||||
break;
|
||||
}
|
||||
memcpy(p_dst_data->intr_data.p_data, src_data, p_src_data->intr_data.len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_hd_remove_device
|
||||
*
|
||||
* Description Removes plugged device
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void btc_hd_remove_device(bt_bdaddr_t bd_addr)
|
||||
{
|
||||
BTA_HdRemoveDevice((uint8_t *)&bd_addr);
|
||||
// btc_storage_remove_hidd(&bd_addr);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bte_hd_evt
|
||||
*
|
||||
* Description Switches context from BTE to BTC for all BT-HD events
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void bte_hd_evt(tBTA_HD_EVT event, tBTA_HD *p_data)
|
||||
{
|
||||
bt_status_t status;
|
||||
int param_len = 0;
|
||||
|
||||
BTC_TRACE_API("%s event=%d", __func__, event);
|
||||
|
||||
switch (event) {
|
||||
case BTA_HD_ENABLE_EVT:
|
||||
case BTA_HD_DISABLE_EVT:
|
||||
case BTA_HD_UNREGISTER_APP_EVT:
|
||||
param_len = sizeof(tBTA_HD_STATUS);
|
||||
break;
|
||||
case BTA_HD_REGISTER_APP_EVT:
|
||||
param_len = sizeof(tBTA_HD_REG_STATUS);
|
||||
break;
|
||||
case BTA_HD_OPEN_EVT:
|
||||
case BTA_HD_CLOSE_EVT:
|
||||
case BTA_HD_VC_UNPLUG_EVT:
|
||||
param_len = sizeof(tBTA_HD_CONN);
|
||||
break;
|
||||
case BTA_HD_GET_REPORT_EVT:
|
||||
param_len += sizeof(tBTA_HD_GET_REPORT);
|
||||
break;
|
||||
case BTA_HD_SET_REPORT_EVT:
|
||||
param_len = sizeof(tBTA_HD_SET_REPORT);
|
||||
break;
|
||||
case BTA_HD_SET_PROTOCOL_EVT:
|
||||
param_len += sizeof(p_data->set_protocol);
|
||||
break;
|
||||
case BTA_HD_INTR_DATA_EVT:
|
||||
param_len = sizeof(tBTA_HD_INTR_DATA);
|
||||
break;
|
||||
case BTA_HD_SEND_REPORT_EVT:
|
||||
param_len = sizeof(tBTA_HD_API_SEND_REPORT);
|
||||
break;
|
||||
case BTA_HD_REPORT_ERR_EVT:
|
||||
param_len = sizeof(tBTA_HD_API_REPORT_ERR);
|
||||
break;
|
||||
}
|
||||
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_HD;
|
||||
msg.act = event;
|
||||
|
||||
status = btc_transfer_context(&msg, p_data, param_len, bte_hd_arg_deep_copy);
|
||||
if (status != BT_STATUS_SUCCESS) {
|
||||
BTC_TRACE_ERROR("context transfer failed");
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_hd_init
|
||||
*
|
||||
* Description Initializes BT-HD interface
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void btc_hd_init(void)
|
||||
{
|
||||
BTC_TRACE_API("%s", __func__);
|
||||
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
|
||||
do {
|
||||
if (is_hidd_init()) {
|
||||
BTC_TRACE_ERROR("%s HD has been initiated, shall uninit first!", __func__);
|
||||
ret = ESP_HIDD_NEED_DEINIT;
|
||||
break;
|
||||
}
|
||||
memset(&btc_hd_cb, 0, sizeof(btc_hd_cb));
|
||||
/* enable HD */
|
||||
BTA_HdEnable(bte_hd_evt);
|
||||
} while (0);
|
||||
|
||||
if (ret != ESP_HIDD_SUCCESS) {
|
||||
esp_hidd_cb_param_t param;
|
||||
param.init.status = ret;
|
||||
btc_hd_cb_to_app(ESP_HIDD_INIT_EVT, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_hd_deinit
|
||||
*
|
||||
* Description de-initializes the hd interface
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void btc_hd_unregister_app(void);
|
||||
static void btc_hd_deinit(void)
|
||||
{
|
||||
BTC_TRACE_API("%s", __func__);
|
||||
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
|
||||
do {
|
||||
if (!is_hidd_init()) {
|
||||
BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
|
||||
ret = ESP_HIDD_NEED_INIT;
|
||||
break;
|
||||
}
|
||||
|
||||
btc_hd_cb.service_dereg_active = FALSE;
|
||||
btc_hd_cb.status = BTC_HD_DISABLING;
|
||||
// unresgister app will also relase the connection
|
||||
// and disable after receiving unregister event from lower layer
|
||||
if (is_hidd_app_register()) {
|
||||
btc_hd_unregister_app();
|
||||
} else {
|
||||
BTC_TRACE_WARNING("%s disabling hid device service now", __func__);
|
||||
BTA_HdDisable();
|
||||
}
|
||||
} while (0);
|
||||
|
||||
if (ret != ESP_HIDD_SUCCESS) {
|
||||
esp_hidd_cb_param_t param;
|
||||
param.deinit.status = ret;
|
||||
btc_hd_cb_to_app(ESP_HIDD_DEINIT_EVT, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_hd_register_app
|
||||
*
|
||||
* Description Registers HID Device application
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void btc_hd_register_app(esp_hidd_app_param_t *p_app_param, esp_hidd_qos_param_t *p_in_qos,
|
||||
esp_hidd_qos_param_t *p_out_qos)
|
||||
{
|
||||
BTC_TRACE_API("%s", __func__);
|
||||
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
|
||||
do {
|
||||
if (!is_hidd_init()) {
|
||||
BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
|
||||
ret = ESP_HIDD_NEED_INIT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_hidd_app_register()) {
|
||||
BTC_TRACE_ERROR("%s: application already registered, shall deregister first!", __func__);
|
||||
ret = ESP_HIDD_NEED_DEREG;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((btc_hd_cb.app_info.p_name = (char *)osi_malloc(BTC_HD_APP_NAME_LEN)) == NULL ||
|
||||
(btc_hd_cb.app_info.p_description = (char *)osi_malloc(BTC_HD_APP_DESCRIPTION_LEN)) == NULL ||
|
||||
(btc_hd_cb.app_info.p_provider = (char *)osi_malloc(BTC_HD_APP_PROVIDER_LEN)) == NULL ||
|
||||
(btc_hd_cb.app_info.descriptor.dsc_list = (uint8_t *)osi_malloc(p_app_param->desc_list_len)) == NULL) {
|
||||
BTC_TRACE_ERROR(
|
||||
"%s malloc app_info failed! p_name:%p, p_description:%p, p_provider:%p, descriptor.dsc_list:%p",
|
||||
__func__, btc_hd_cb.app_info.p_name, btc_hd_cb.app_info.p_description, btc_hd_cb.app_info.p_provider,
|
||||
btc_hd_cb.app_info.descriptor.dsc_list);
|
||||
ret = ESP_HIDD_NO_RES;
|
||||
break;
|
||||
}
|
||||
memcpy(btc_hd_cb.app_info.p_name, p_app_param->name, BTC_HD_APP_NAME_LEN);
|
||||
memcpy(btc_hd_cb.app_info.p_description, p_app_param->description, BTC_HD_APP_DESCRIPTION_LEN);
|
||||
memcpy(btc_hd_cb.app_info.p_provider, p_app_param->provider, BTC_HD_APP_PROVIDER_LEN);
|
||||
memcpy(btc_hd_cb.app_info.descriptor.dsc_list, p_app_param->desc_list, p_app_param->desc_list_len);
|
||||
btc_hd_cb.app_info.subclass = p_app_param->subclass;
|
||||
btc_hd_cb.app_info.descriptor.dl_len = p_app_param->desc_list_len;
|
||||
|
||||
btc_hd_cb.in_qos.service_type = p_in_qos->service_type;
|
||||
btc_hd_cb.in_qos.token_rate = p_in_qos->token_rate;
|
||||
btc_hd_cb.in_qos.token_bucket_size = p_in_qos->token_bucket_size;
|
||||
btc_hd_cb.in_qos.peak_bandwidth = p_in_qos->peak_bandwidth;
|
||||
btc_hd_cb.in_qos.access_latency = p_in_qos->access_latency;
|
||||
btc_hd_cb.in_qos.delay_variation = p_in_qos->delay_variation;
|
||||
btc_hd_cb.out_qos.service_type = p_out_qos->service_type;
|
||||
btc_hd_cb.out_qos.token_rate = p_out_qos->token_rate;
|
||||
btc_hd_cb.out_qos.token_bucket_size = p_out_qos->token_bucket_size;
|
||||
btc_hd_cb.out_qos.peak_bandwidth = p_out_qos->peak_bandwidth;
|
||||
btc_hd_cb.out_qos.access_latency = p_out_qos->access_latency;
|
||||
btc_hd_cb.out_qos.delay_variation = p_out_qos->delay_variation;
|
||||
|
||||
BTA_HdRegisterApp(&btc_hd_cb.app_info, &btc_hd_cb.in_qos, &btc_hd_cb.out_qos);
|
||||
} while(0);
|
||||
|
||||
if (ret != ESP_HIDD_SUCCESS) {
|
||||
esp_hidd_cb_param_t param;
|
||||
param.register_app.status = ret;
|
||||
param.register_app.in_use = false;
|
||||
memset(param.register_app.bd_addr, 0, BD_ADDR_LEN);
|
||||
btc_hd_cb_to_app(ESP_HIDD_REGISTER_APP_EVT, ¶m);
|
||||
}
|
||||
free_app_info_param();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_hd_unregister_app
|
||||
*
|
||||
* Description Unregisters HID Device application
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void btc_hd_unregister_app(void)
|
||||
{
|
||||
BTC_TRACE_API("%s", __func__);
|
||||
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
|
||||
do {
|
||||
if (!is_hidd_init()) {
|
||||
BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
|
||||
ret = ESP_HIDD_NEED_INIT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!is_hidd_app_register()) {
|
||||
BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__);
|
||||
ret = ESP_HIDD_NEED_REG;
|
||||
break;
|
||||
}
|
||||
|
||||
if (btc_hd_cb.service_dereg_active) {
|
||||
BTC_TRACE_ERROR("%s: BT-HD deregistering in progress", __func__);
|
||||
ret = ESP_HIDD_BUSY;
|
||||
break;
|
||||
}
|
||||
btc_hd_cb.service_dereg_active = TRUE;
|
||||
BTA_HdUnregisterApp();
|
||||
} while(0);
|
||||
|
||||
if (ret != ESP_HIDD_SUCCESS) {
|
||||
esp_hidd_cb_param_t param;
|
||||
param.unregister_app.status = ret;
|
||||
btc_hd_cb_to_app(ESP_HIDD_UNREGISTER_APP_EVT, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_hd_connect
|
||||
*
|
||||
* Description Connects to host
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void btc_hd_connect(BD_ADDR bd_addr)
|
||||
{
|
||||
BTC_TRACE_API("%s", __func__);
|
||||
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
|
||||
do {
|
||||
if (!is_hidd_init()) {
|
||||
BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
|
||||
ret = ESP_HIDD_NEED_INIT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!is_hidd_app_register()) {
|
||||
BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__);
|
||||
ret = ESP_HIDD_NEED_REG;
|
||||
break;
|
||||
}
|
||||
BTA_HdConnect(bd_addr);
|
||||
} while (0);
|
||||
|
||||
if (ret != ESP_HIDD_SUCCESS) {
|
||||
esp_hidd_cb_param_t param;
|
||||
param.open.status = ret;
|
||||
param.open.conn_status = ESP_HIDD_CONN_STATE_DISCONNECTED;
|
||||
memcpy(param.open.bd_addr, bd_addr, BD_ADDR_LEN);
|
||||
btc_hd_cb_to_app(ESP_HIDD_OPEN_EVT, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_hd_disconnect
|
||||
*
|
||||
* Description Disconnects from host
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void btc_hd_disconnect(void)
|
||||
{
|
||||
BTC_TRACE_API("%s", __func__);
|
||||
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
|
||||
do {
|
||||
if (!is_hidd_init()) {
|
||||
BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
|
||||
ret = ESP_HIDD_NEED_INIT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!is_hidd_app_register()) {
|
||||
BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__);
|
||||
ret = ESP_HIDD_NEED_REG;
|
||||
break;
|
||||
}
|
||||
BTA_HdDisconnect();
|
||||
} while (0);
|
||||
|
||||
if (ret != ESP_HIDD_SUCCESS) {
|
||||
esp_hidd_cb_param_t param;
|
||||
param.close.status = ret;
|
||||
param.close.conn_status = ESP_HIDD_CONN_STATE_DISCONNECTED;
|
||||
btc_hd_cb_to_app(ESP_HIDD_CLOSE_EVT, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_hd_send_report
|
||||
*
|
||||
* Description Sends Reports to hid host
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void btc_hd_send_report(esp_hidd_report_type_t type, uint8_t id, uint16_t len, uint8_t *p_data)
|
||||
{
|
||||
tBTA_HD_REPORT report;
|
||||
|
||||
BTC_TRACE_API("%s: type=%d id=%d len=%d", __func__, type, id, len);
|
||||
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
|
||||
do {
|
||||
if (!is_hidd_init()) {
|
||||
BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
|
||||
ret = ESP_HIDD_NEED_INIT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!is_hidd_app_register()) {
|
||||
BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__);
|
||||
ret = ESP_HIDD_NEED_REG;
|
||||
break;
|
||||
}
|
||||
if (type == ESP_HIDD_REPORT_TYPE_INTRDATA) {
|
||||
report.type = ESP_HIDD_REPORT_TYPE_INPUT;
|
||||
report.use_intr = TRUE;
|
||||
} else {
|
||||
report.type = (type & 0x03);
|
||||
report.use_intr = FALSE;
|
||||
}
|
||||
|
||||
report.id = id;
|
||||
report.len = len;
|
||||
report.p_data = p_data;
|
||||
|
||||
BTA_HdSendReport(&report);
|
||||
} while (0);
|
||||
|
||||
if (ret != ESP_HIDD_SUCCESS) {
|
||||
esp_hidd_cb_param_t param;
|
||||
param.send_report.status = ret;
|
||||
param.send_report.reason = 0;
|
||||
param.send_report.report_type = report.type;
|
||||
param.send_report.report_id = report.id;
|
||||
btc_hd_cb_to_app(ESP_HIDD_SEND_REPORT_EVT, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_hd_report_error
|
||||
*
|
||||
* Description Sends HANDSHAKE with error info for invalid SET_REPORT
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void btc_hd_report_error(uint8_t error)
|
||||
{
|
||||
BTC_TRACE_API("%s", __func__);
|
||||
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
|
||||
do {
|
||||
if (!is_hidd_init()) {
|
||||
BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
|
||||
ret = ESP_HIDD_NEED_INIT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!is_hidd_app_register()) {
|
||||
BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__);
|
||||
ret = ESP_HIDD_NEED_REG;
|
||||
break;
|
||||
}
|
||||
BTA_HdReportError(error);
|
||||
} while (0);
|
||||
|
||||
if (ret != ESP_HIDD_SUCCESS) {
|
||||
esp_hidd_cb_param_t param;
|
||||
param.report_err.status = ret;
|
||||
param.report_err.reason = 0;
|
||||
btc_hd_cb_to_app(ESP_HIDD_REPORT_ERR_EVT, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_hd_virtual_cable_unplug
|
||||
*
|
||||
* Description Sends Virtual Cable Unplug to host
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void btc_hd_virtual_cable_unplug(void)
|
||||
{
|
||||
BTC_TRACE_API("%s", __func__);
|
||||
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
|
||||
do {
|
||||
if (!is_hidd_init()) {
|
||||
BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
|
||||
ret = ESP_HIDD_NEED_INIT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!is_hidd_app_register()) {
|
||||
BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__);
|
||||
ret = ESP_HIDD_NEED_REG;
|
||||
break;
|
||||
}
|
||||
BTA_HdVirtualCableUnplug();
|
||||
} while (0);
|
||||
|
||||
if (ret != ESP_HIDD_SUCCESS) {
|
||||
esp_hidd_cb_param_t param;
|
||||
param.report_err.status = ret;
|
||||
param.report_err.reason = 0;
|
||||
btc_hd_cb_to_app(ESP_HIDD_VC_UNPLUG_EVT, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
static void btc_hd_call_arg_deep_free(btc_msg_t *msg)
|
||||
{
|
||||
btc_hidd_args_t *arg = (btc_hidd_args_t *)msg->arg;
|
||||
|
||||
switch (msg->act) {
|
||||
case BTC_HD_SEND_REPORT_EVT:
|
||||
utl_freebuf((void **)&arg->send_report.data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void btc_hd_call_handler(btc_msg_t *msg)
|
||||
{
|
||||
btc_hidd_args_t *arg = (btc_hidd_args_t *)(msg->arg);
|
||||
switch (msg->act) {
|
||||
case BTC_HD_INIT_EVT:
|
||||
btc_hd_init();
|
||||
break;
|
||||
case BTC_HD_DEINIT_EVT:
|
||||
btc_hd_deinit();
|
||||
break;
|
||||
case BTC_HD_REGISTER_APP_EVT:
|
||||
btc_hd_register_app(arg->register_app.app_param, arg->register_app.in_qos, arg->register_app.out_qos);
|
||||
break;
|
||||
case BTC_HD_UNREGISTER_APP_EVT:
|
||||
btc_hd_unregister_app();
|
||||
break;
|
||||
case BTC_HD_CONNECT_EVT:
|
||||
btc_hd_connect(arg->connect.bd_addr);
|
||||
break;
|
||||
case BTC_HD_DISCONNECT_EVT:
|
||||
btc_hd_disconnect();
|
||||
break;
|
||||
case BTC_HD_SEND_REPORT_EVT:
|
||||
btc_hd_send_report(arg->send_report.type, arg->send_report.id, arg->send_report.len, arg->send_report.data);
|
||||
break;
|
||||
case BTC_HD_REPORT_ERROR_EVT:
|
||||
btc_hd_report_error(arg->error);
|
||||
break;
|
||||
case BTC_HD_UNPLUG_EVT:
|
||||
btc_hd_virtual_cable_unplug();
|
||||
break;
|
||||
default:
|
||||
BTC_TRACE_WARNING("unknown hidd action %i", msg->act);
|
||||
break;
|
||||
}
|
||||
btc_hd_call_arg_deep_free(msg);
|
||||
}
|
||||
|
||||
static void btc_hd_cb_arg_deep_free(btc_msg_t *msg)
|
||||
{
|
||||
tBTA_HD *arg = (tBTA_HD *)msg->arg;
|
||||
|
||||
switch (msg->act) {
|
||||
case BTA_HD_SET_REPORT_EVT:
|
||||
utl_freebuf((void **)&arg->set_report.p_data);
|
||||
break;
|
||||
case BTA_HD_INTR_DATA_EVT:
|
||||
utl_freebuf((void **)&arg->intr_data.p_data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void btc_hd_cb_handler(btc_msg_t *msg)
|
||||
{
|
||||
uint16_t event = msg->act;
|
||||
tBTA_HD *p_data = (tBTA_HD *)msg->arg;
|
||||
esp_hidd_cb_param_t param = {0};
|
||||
BTC_TRACE_API("%s: event=%s", __func__, dump_hd_event(event));
|
||||
|
||||
switch (event) {
|
||||
case BTA_HD_ENABLE_EVT:
|
||||
BTC_TRACE_DEBUG("%s: status=%d", __func__, p_data->status);
|
||||
if (p_data->status == BTA_HD_OK) {
|
||||
btc_storage_load_hidd();
|
||||
btc_hd_cb.status = BTC_HD_ENABLED;
|
||||
} else {
|
||||
btc_hd_cb.status = BTC_HD_DISABLED;
|
||||
BTC_TRACE_WARNING("Failed to enable BT-HD, status=%d", p_data->status);
|
||||
}
|
||||
param.init.status = p_data->status;
|
||||
btc_hd_cb_to_app(ESP_HIDD_INIT_EVT, ¶m);
|
||||
break;
|
||||
case BTA_HD_DISABLE_EVT:
|
||||
BTC_TRACE_DEBUG("%s: status=%d", __func__, p_data->status);
|
||||
if (p_data->status == BTA_HD_OK){
|
||||
btc_hd_cb.status = BTC_HD_DISABLED;
|
||||
if (btc_hd_cb.service_dereg_active) {
|
||||
btc_hd_cb.service_dereg_active = FALSE;
|
||||
}
|
||||
free_app_info_param();
|
||||
memset(&btc_hd_cb, 0, sizeof(btc_hd_cb));
|
||||
} else {
|
||||
BTC_TRACE_WARNING("Failed to disable BT-HD, status=%d", p_data->status);
|
||||
}
|
||||
param.deinit.status = p_data->status;
|
||||
btc_hd_cb_to_app(ESP_HIDD_DEINIT_EVT, ¶m);
|
||||
break;
|
||||
case BTA_HD_REGISTER_APP_EVT:
|
||||
if (p_data->reg_status.status == BTA_HD_OK) {
|
||||
btc_hd_cb.app_registered = TRUE;
|
||||
}
|
||||
param.register_app.status = p_data->reg_status.status;
|
||||
param.register_app.in_use = p_data->reg_status.in_use;
|
||||
if (!p_data->reg_status.in_use) {
|
||||
memset(param.register_app.bd_addr, 0, BD_ADDR_LEN);
|
||||
} else {
|
||||
memcpy(param.register_app.bd_addr, p_data->reg_status.bda, BD_ADDR_LEN);
|
||||
}
|
||||
btc_hd_cb_to_app(ESP_HIDD_REGISTER_APP_EVT, ¶m);
|
||||
break;
|
||||
case BTA_HD_UNREGISTER_APP_EVT:
|
||||
btc_hd_cb.app_registered = FALSE;
|
||||
param.unregister_app.status = p_data->status;
|
||||
btc_hd_cb_to_app(ESP_HIDD_UNREGISTER_APP_EVT, ¶m);
|
||||
if (btc_hd_cb.status == BTC_HD_DISABLING) {
|
||||
BTC_TRACE_WARNING("disabling hid device service now");
|
||||
BTA_HdDisable();
|
||||
}
|
||||
break;
|
||||
case BTA_HD_OPEN_EVT: {
|
||||
bt_bdaddr_t *addr = (bt_bdaddr_t *)&p_data->conn.bda;
|
||||
BTC_TRACE_EVENT("BTA_HD_OPEN_EVT, address (%02x:%02x:%02x:%02x:%02x:%02x)", addr->address[0], addr->address[1],
|
||||
addr->address[2], addr->address[3], addr->address[4], addr->address[5]);
|
||||
if (p_data->conn.status == BTA_HD_OK && p_data->conn.conn_status == BTA_HD_CONN_STATE_CONNECTED) {
|
||||
// /* Check if the connection is from hid host and not hid device */
|
||||
// if (check_cod_hid(addr)) {
|
||||
// /* Incoming connection from hid device, reject it */
|
||||
// BTC_TRACE_WARNING("remote device is not hid host, disconnecting");
|
||||
// btc_hd_cb.forced_disc = TRUE;
|
||||
// BTA_HdDisconnect();
|
||||
// break;
|
||||
// }
|
||||
// btc_storage_set_hidd((bt_bdaddr_t *)&p_data->conn.bda);
|
||||
}
|
||||
param.open.status = p_data->conn.status;
|
||||
param.open.conn_status = p_data->conn.conn_status;
|
||||
memcpy(param.open.bd_addr, p_data->conn.bda, BD_ADDR_LEN);
|
||||
btc_hd_cb_to_app(ESP_HIDD_OPEN_EVT, ¶m);
|
||||
break;
|
||||
}
|
||||
case BTA_HD_CLOSE_EVT:
|
||||
if (btc_hd_cb.forced_disc && p_data->conn.conn_status == BTA_HD_CONN_STATE_DISCONNECTED) {
|
||||
bt_bdaddr_t *addr = (bt_bdaddr_t *)&p_data->conn.bda;
|
||||
BTC_TRACE_WARNING("remote device was forcefully disconnected");
|
||||
btc_hd_remove_device(*addr);
|
||||
btc_hd_cb.forced_disc = FALSE;
|
||||
break;
|
||||
}
|
||||
param.close.status = p_data->conn.status;
|
||||
param.close.conn_status = p_data->conn.conn_status;
|
||||
btc_hd_cb_to_app(ESP_HIDD_CLOSE_EVT, ¶m);
|
||||
break;
|
||||
case BTA_HD_GET_REPORT_EVT:
|
||||
param.get_report.report_type = p_data->get_report.report_type;
|
||||
param.get_report.report_id = p_data->get_report.report_id;
|
||||
param.get_report.buffer_size = p_data->get_report.buffer_size;
|
||||
btc_hd_cb_to_app(ESP_HIDD_GET_REPORT_EVT, ¶m);
|
||||
break;
|
||||
case BTA_HD_SET_REPORT_EVT:
|
||||
param.set_report.report_type = p_data->set_report.report_type;
|
||||
param.set_report.report_id = p_data->set_report.report_id;
|
||||
param.set_report.len = p_data->set_report.len;
|
||||
param.set_report.data = p_data->set_report.p_data;
|
||||
btc_hd_cb_to_app(ESP_HIDD_SET_REPORT_EVT, ¶m);
|
||||
break;
|
||||
case BTA_HD_SET_PROTOCOL_EVT:
|
||||
switch (p_data->set_protocol) {
|
||||
case HID_PAR_PROTOCOL_BOOT_MODE:
|
||||
param.set_protocol.protocol_mode = ESP_HIDD_BOOT_MODE;
|
||||
break;
|
||||
case HID_PAR_PROTOCOL_REPORT:
|
||||
param.set_protocol.protocol_mode = ESP_HIDD_REPORT_MODE;
|
||||
break;
|
||||
default:
|
||||
param.set_protocol.protocol_mode = ESP_HIDD_UNSUPPORTED_MODE;
|
||||
break;
|
||||
}
|
||||
btc_hd_cb_to_app(ESP_HIDD_SET_PROTOCOL_EVT, ¶m);
|
||||
break;
|
||||
case BTA_HD_INTR_DATA_EVT:
|
||||
param.intr_data.report_id = p_data->intr_data.report_id;
|
||||
param.intr_data.len = p_data->intr_data.len;
|
||||
param.intr_data.data = p_data->intr_data.p_data;
|
||||
btc_hd_cb_to_app(ESP_HIDD_INTR_DATA_EVT, ¶m);
|
||||
break;
|
||||
case BTA_HD_VC_UNPLUG_EVT: {
|
||||
bt_bdaddr_t *bd_addr = (bt_bdaddr_t *)&p_data->conn.bda;
|
||||
if (bta_dm_check_if_only_hd_connected(p_data->conn.bda)) {
|
||||
BTC_TRACE_DEBUG("%s: Removing bonding as only HID profile connected", __func__);
|
||||
BTA_DmRemoveDevice((uint8_t *)&p_data->conn.bda, BT_TRANSPORT_BR_EDR);
|
||||
} else {
|
||||
BTC_TRACE_DEBUG("%s: Only removing HID data as some other profiles connected", __func__);
|
||||
btc_hd_remove_device(*bd_addr);
|
||||
}
|
||||
param.close.status = p_data->conn.status;
|
||||
param.close.conn_status = p_data->conn.conn_status;
|
||||
btc_hd_cb_to_app(ESP_HIDD_CLOSE_EVT, ¶m);
|
||||
param.vc_unplug.status = p_data->conn.status;
|
||||
param.vc_unplug.conn_status = p_data->conn.conn_status;
|
||||
btc_hd_cb_to_app(ESP_HIDD_VC_UNPLUG_EVT, ¶m);
|
||||
break;
|
||||
}
|
||||
case BTA_HD_SEND_REPORT_EVT:
|
||||
param.send_report.status = p_data->send_report.status;
|
||||
param.send_report.reason = p_data->send_report.reason;
|
||||
param.send_report.report_type = p_data->send_report.report_type;
|
||||
param.send_report.report_id = p_data->send_report.report_id;
|
||||
btc_hd_cb_to_app(ESP_HIDD_SEND_REPORT_EVT, ¶m);
|
||||
break;
|
||||
case BTA_HD_REPORT_ERR_EVT:
|
||||
param.report_err.status = p_data->report_err.status;
|
||||
param.report_err.reason = p_data->report_err.reason;
|
||||
btc_hd_cb_to_app(ESP_HIDD_REPORT_ERR_EVT, ¶m);
|
||||
break;
|
||||
default:
|
||||
BTC_TRACE_WARNING("%s: unknown event (%d)", __func__, event);
|
||||
break;
|
||||
}
|
||||
btc_hd_cb_arg_deep_free(msg);
|
||||
}
|
||||
|
||||
void btc_hd_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
{
|
||||
btc_hidd_args_t *dst = (btc_hidd_args_t *)p_dest;
|
||||
btc_hidd_args_t *src = (btc_hidd_args_t *)p_src;
|
||||
|
||||
switch (msg->act) {
|
||||
case BTC_HD_SEND_REPORT_EVT:
|
||||
dst->send_report.data = (uint8_t *)osi_malloc(src->send_report.len);
|
||||
if (dst->send_report.data) {
|
||||
memcpy(dst->send_report.data, src->send_report.data, src->send_report.len);
|
||||
} else {
|
||||
BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HID_DEV_INCLUDED==TRUE
|
1569
components/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c
Normal file
1569
components/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c
Normal file
File diff suppressed because it is too large
Load Diff
103
components/bt/host/bluedroid/btc/profile/std/include/btc_hd.h
Normal file
103
components/bt/host/bluedroid/btc/profile/std/include/btc_hd.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef BTC_HD_H
|
||||
#define BTC_HD_H
|
||||
|
||||
#if BTC_HD_INCLUDED == TRUE
|
||||
|
||||
#include <stdint.h>
|
||||
#include "bta/bta_hd_api.h"
|
||||
#include "btc/btc_task.h"
|
||||
#include "esp_hidd_api.h"
|
||||
|
||||
typedef enum {
|
||||
BTC_HD_INIT_EVT = 0,
|
||||
BTC_HD_DEINIT_EVT,
|
||||
BTC_HD_REGISTER_APP_EVT,
|
||||
BTC_HD_UNREGISTER_APP_EVT,
|
||||
BTC_HD_CONNECT_EVT,
|
||||
BTC_HD_DISCONNECT_EVT,
|
||||
BTC_HD_SEND_REPORT_EVT,
|
||||
BTC_HD_REPORT_ERROR_EVT,
|
||||
BTC_HD_UNPLUG_EVT,
|
||||
} BTC_HD_EVT;
|
||||
|
||||
typedef enum { BTC_HD_DISABLED = 0, BTC_HD_ENABLED, BTC_HD_DISABLING } BTC_HD_STATUS;
|
||||
|
||||
/* BTIF-HD control block */
|
||||
typedef struct {
|
||||
BTC_HD_STATUS status;
|
||||
bool app_registered;
|
||||
bool service_dereg_active;
|
||||
bool forced_disc;
|
||||
tBTA_HD_APP_INFO app_info;
|
||||
tBTA_HD_QOS_INFO in_qos;
|
||||
tBTA_HD_QOS_INFO out_qos;
|
||||
} btc_hd_cb_t;
|
||||
|
||||
/* btc_hidd_args_t */
|
||||
typedef union {
|
||||
// BTC_HD_CONNECT_EVT
|
||||
struct connect_arg {
|
||||
BD_ADDR bd_addr;
|
||||
} connect;
|
||||
|
||||
// BTC_HD_REGISTER_APP_EVT
|
||||
struct register_app_arg {
|
||||
esp_hidd_app_param_t *app_param;
|
||||
esp_hidd_qos_param_t *in_qos;
|
||||
esp_hidd_qos_param_t *out_qos;
|
||||
} register_app;
|
||||
|
||||
// BTC_HD_SEND_REPORT_EVT
|
||||
struct send_report_arg {
|
||||
esp_hidd_report_type_t type;
|
||||
uint8_t id;
|
||||
uint16_t len;
|
||||
uint8_t *data;
|
||||
} send_report;
|
||||
|
||||
// BTC_HD_REPORT_ERROR_EVT
|
||||
uint8_t error;
|
||||
} btc_hidd_args_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
* Functions
|
||||
******************************************************************************/
|
||||
void btc_hd_call_handler(btc_msg_t *msg);
|
||||
|
||||
void btc_hd_cb_handler(btc_msg_t *msg);
|
||||
|
||||
// extern btc_hd_cb_t btc_hd_cb;
|
||||
// extern void btc_hd_remove_device(bt_bdaddr_t bd_addr);
|
||||
// extern void btc_hd_service_registration();
|
||||
|
||||
void btc_hd_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BTC_HD_INCLUDED == TRUE */
|
||||
#endif /* BTC_HD_H */
|
187
components/bt/host/bluedroid/btc/profile/std/include/btc_hh.h
Normal file
187
components/bt/host/bluedroid/btc/profile/std/include/btc_hh.h
Normal file
@@ -0,0 +1,187 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef BTC_HH_H
|
||||
#define BTC_HH_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "bta/bta_hh_api.h"
|
||||
#include "btc/btc_task.h"
|
||||
#include "osi/alarm.h"
|
||||
#include "esp_hidh_api.h"
|
||||
|
||||
#define BTC_HH_MAX_HID 8
|
||||
#define BTC_HH_MAX_ADDED_DEV 32
|
||||
|
||||
#define BTC_HH_MAX_KEYSTATES 3
|
||||
#define BTC_HH_KEYSTATE_MASK_NUMLOCK 0x01
|
||||
#define BTC_HH_KEYSTATE_MASK_CAPSLOCK 0x02
|
||||
#define BTC_HH_KEYSTATE_MASK_SCROLLLOCK 0x04
|
||||
|
||||
#define BTC_HH_MAX_POLLING_ATTEMPTS 10
|
||||
#define BTC_HH_POLLING_SLEEP_DURATION_US 5000
|
||||
|
||||
/*******************************************************************************
|
||||
* Type definitions and return values
|
||||
******************************************************************************/
|
||||
typedef enum {
|
||||
BTC_HH_INIT_EVT = 0,
|
||||
BTC_HH_CONNECT_EVT,
|
||||
BTC_HH_DISCONNECT_EVT,
|
||||
BTC_HH_UNPLUG_EVT,
|
||||
BTC_HH_SET_INFO_EVT,
|
||||
BTC_HH_GET_PROTO_EVT,
|
||||
BTC_HH_SET_PROTO_EVT,
|
||||
BTC_HH_GET_IDLE_EVT,
|
||||
BTC_HH_SET_IDLE_EVT,
|
||||
BTC_HH_GET_REPORT_EVT,
|
||||
BTC_HH_SET_REPORT_EVT,
|
||||
BTC_HH_SEND_DATA_EVT,
|
||||
BTC_HH_DEINIT_EVT,
|
||||
} BTC_HH_EVT;
|
||||
|
||||
typedef enum {
|
||||
BTC_HH_DISABLED = 0,
|
||||
BTC_HH_ENABLED,
|
||||
BTC_HH_DISABLING,
|
||||
BTC_HH_DEV_UNKNOWN,
|
||||
BTC_HH_DEV_CONNECTING,
|
||||
BTC_HH_DEV_CONNECTED,
|
||||
BTC_HH_DEV_DISCONNECTED
|
||||
} BTC_HH_STATUS;
|
||||
|
||||
typedef struct {
|
||||
esp_hidh_connection_state_t dev_status;
|
||||
uint8_t dev_handle;
|
||||
BD_ADDR bd_addr;
|
||||
uint16_t attr_mask;
|
||||
uint8_t sub_class;
|
||||
uint8_t app_id;
|
||||
bool ready_for_data;
|
||||
osi_alarm_t *vup_timer;
|
||||
bool local_vup; // Indicated locally initiated VUP
|
||||
} btc_hh_device_t;
|
||||
|
||||
/* Control block to maintain properties of devices */
|
||||
typedef struct {
|
||||
uint8_t dev_handle;
|
||||
BD_ADDR bd_addr;
|
||||
uint16_t attr_mask;
|
||||
} btc_hh_added_device_t;
|
||||
|
||||
/**
|
||||
* BTC-HH control block to maintain added devices and currently
|
||||
* connected hid devices
|
||||
*/
|
||||
typedef struct {
|
||||
BTC_HH_STATUS status;
|
||||
btc_hh_device_t devices[BTC_HH_MAX_HID];
|
||||
uint32_t device_num;
|
||||
BTC_HH_EVT add_event;
|
||||
btc_hh_added_device_t added_devices[BTC_HH_MAX_ADDED_DEV];
|
||||
btc_hh_device_t *p_curr_dev;
|
||||
bool service_dereg_active;
|
||||
BD_ADDR pending_conn_address;
|
||||
} btc_hh_cb_t;
|
||||
|
||||
/* btc_spp_args_t */
|
||||
typedef union {
|
||||
// BTC_HH_CONNECT_EVT
|
||||
struct connect_arg {
|
||||
BD_ADDR bd_addr;
|
||||
} connect;
|
||||
|
||||
// BTC_HH_DISCONNECT_EVT
|
||||
struct disconnect_arg {
|
||||
BD_ADDR bd_addr;
|
||||
} disconnect;
|
||||
|
||||
// BTC_HH_UNPLUG_EVT
|
||||
struct unplug_arg {
|
||||
BD_ADDR bd_addr;
|
||||
} unplug;
|
||||
|
||||
// BTC_HH_SET_INFO_EVT
|
||||
struct set_info_arg {
|
||||
BD_ADDR bd_addr;
|
||||
esp_hidh_hid_info_t *hid_info;
|
||||
} set_info;
|
||||
|
||||
// BTC_HH_GET_PROTO_EVT
|
||||
struct get_protocol_arg {
|
||||
BD_ADDR bd_addr;
|
||||
} get_protocol;
|
||||
|
||||
// BTC_HH_SET_PROTO_EVT
|
||||
struct set_protocol_arg {
|
||||
BD_ADDR bd_addr;
|
||||
esp_hidh_protocol_mode_t protocol_mode;
|
||||
} set_protocol;
|
||||
|
||||
// BTC_HH_GET_IDLE_EVT
|
||||
struct get_idle_arg {
|
||||
BD_ADDR bd_addr;
|
||||
} get_idle;
|
||||
|
||||
// BTC_HH_SET_IDLE_EVT
|
||||
struct set_idle_arg {
|
||||
BD_ADDR bd_addr;
|
||||
uint16_t idle_time;
|
||||
} set_idle;
|
||||
|
||||
// BTC_HH_GET_REPORT_EVT
|
||||
struct get_report_arg {
|
||||
BD_ADDR bd_addr;
|
||||
esp_hidh_report_type_t report_type;
|
||||
uint8_t report_id;
|
||||
int buffer_size;
|
||||
} get_report;
|
||||
|
||||
// BTC_HH_SET_REPORT_EVT
|
||||
struct set_report_arg {
|
||||
BD_ADDR bd_addr;
|
||||
esp_hidh_report_type_t report_type;
|
||||
size_t len;
|
||||
uint8_t *report;
|
||||
} set_report;
|
||||
|
||||
// BTC_HH_SEND_DATA_EVT
|
||||
struct send_data_arg {
|
||||
BD_ADDR bd_addr;
|
||||
size_t len;
|
||||
uint8_t *data;
|
||||
} send_data;
|
||||
} btc_hidh_args_t;
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
extern btc_hh_cb_t btc_hh_cb;
|
||||
/*******************************************************************************
|
||||
* Functions
|
||||
******************************************************************************/
|
||||
|
||||
void btc_hh_call_handler(btc_msg_t *msg);
|
||||
|
||||
void btc_hh_cb_handler(btc_msg_t *msg);
|
||||
|
||||
void btc_hh_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src);
|
||||
|
||||
bool btc_hh_add_added_dev(BD_ADDR bd_addr, uint16_t attr_mask);
|
||||
|
||||
#endif /* BTC_HH_H */
|
@@ -67,6 +67,13 @@
|
||||
#define UC_BT_HFP_CLIENT_ENABLED FALSE
|
||||
#endif
|
||||
|
||||
//HID
|
||||
#ifdef CONFIG_BT_HID_ENABLED
|
||||
#define UC_BT_HID_ENABLED CONFIG_BT_HID_ENABLED
|
||||
#else
|
||||
#define UC_BT_HID_ENABLED FALSE
|
||||
#endif
|
||||
|
||||
//HID HOST(BT)
|
||||
#ifdef CONFIG_BT_HID_HOST_ENABLED
|
||||
#define UC_BT_HID_HOST_ENABLED CONFIG_BT_HID_HOST_ENABLED
|
||||
@@ -74,6 +81,13 @@
|
||||
#define UC_BT_HID_HOST_ENABLED FALSE
|
||||
#endif
|
||||
|
||||
//HID Device(BT)
|
||||
#ifdef CONFIG_BT_HID_DEVICE_ENABLED
|
||||
#define UC_BT_HID_DEVICE_ENABLED CONFIG_BT_HID_DEVICE_ENABLED
|
||||
#else
|
||||
#define UC_BT_HID_DEVICE_ENABLED FALSE
|
||||
#endif
|
||||
|
||||
//SSP
|
||||
#ifdef CONFIG_BT_SSP_ENABLED
|
||||
#define UC_BT_SSP_ENABLED CONFIG_BT_SSP_ENABLED
|
||||
@@ -365,10 +379,18 @@
|
||||
#define UC_BT_LOG_MCA_TRACE_LEVEL UC_TRACE_LEVEL_WARNING
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_LOG_HIDH_TRACE_LEVEL
|
||||
#define UC_BT_LOG_HIDH_TRACE_LEVEL CONFIG_BT_LOG_HIDH_TRACE_LEVEL
|
||||
#ifdef CONFIG_BT_LOG_HID_TRACE_LEVEL
|
||||
#if UC_BT_HID_HOST_ENABLED
|
||||
#define UC_BT_LOG_HIDH_TRACE_LEVEL CONFIG_BT_LOG_HID_TRACE_LEVEL
|
||||
#elif UC_BT_HID_DEVICE_ENABLED
|
||||
#define UC_BT_LOG_HIDD_TRACE_LEVEL CONFIG_BT_LOG_HID_TRACE_LEVEL
|
||||
#endif
|
||||
#else
|
||||
#if UC_BT_HID_HOST_ENABLED
|
||||
#define UC_BT_LOG_HIDH_TRACE_LEVEL UC_TRACE_LEVEL_WARNING
|
||||
#elif UC_BT_HID_DEVICE_ENABLED
|
||||
#define UC_BT_LOG_HIDD_TRACE_LEVEL UC_TRACE_LEVEL_WARNING
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_LOG_APPL_TRACE_LEVEL
|
||||
|
@@ -130,11 +130,22 @@
|
||||
#define BT_SSP_INCLUDED TRUE
|
||||
#endif /* UC_BT_SSP_ENABLED */
|
||||
|
||||
#if UC_BT_HID_ENABLED
|
||||
#define BT_HID_INCLUDED TRUE
|
||||
#endif /* UC_BT_HID_ENABLED */
|
||||
|
||||
#if UC_BT_HID_HOST_ENABLED
|
||||
#define HID_HOST_INCLUDED TRUE
|
||||
#define BTA_HH_INCLUDED TRUE
|
||||
#define BTC_HH_INCLUDED TRUE
|
||||
#endif /* UC_BT_HID_HOST_ENABLED */
|
||||
|
||||
#if UC_BT_HID_DEVICE_ENABLED
|
||||
#define HID_DEV_INCLUDED TRUE
|
||||
#define BTA_HD_INCLUDED TRUE
|
||||
#define BTC_HD_INCLUDED TRUE
|
||||
#endif /* UC_BT_HID_DEVICE_ENABLED */
|
||||
|
||||
#endif /* UC_BT_CLASSIC_ENABLED */
|
||||
|
||||
/* This is set to enable use of GAP L2CAP connections. */
|
||||
@@ -321,6 +332,14 @@
|
||||
#define BTC_SPP_INCLUDED FALSE
|
||||
#endif
|
||||
|
||||
#ifndef BTC_HH_INCLUDED
|
||||
#define BTC_HH_INCLUDED FALSE
|
||||
#endif
|
||||
|
||||
#ifndef BTC_HD_INCLUDED
|
||||
#define BTC_HD_INCLUDED FALSE
|
||||
#endif
|
||||
|
||||
#ifndef SBC_DEC_INCLUDED
|
||||
#define SBC_DEC_INCLUDED FALSE
|
||||
#endif
|
||||
@@ -350,6 +369,10 @@
|
||||
#define BTA_PAN_INCLUDED FALSE
|
||||
#endif
|
||||
|
||||
#ifndef BTA_HD_INCLUDED
|
||||
#define BTA_HD_INCLUDED FALSE
|
||||
#endif
|
||||
|
||||
#ifndef BTA_HH_INCLUDED
|
||||
#define BTA_HH_INCLUDED FALSE
|
||||
#endif
|
||||
@@ -1378,7 +1401,11 @@
|
||||
|
||||
/* The maximum number of attributes in each record. */
|
||||
#ifndef SDP_MAX_REC_ATTR
|
||||
#if defined(HID_DEV_INCLUDED) && (HID_DEV_INCLUDED==TRUE)
|
||||
#define SDP_MAX_REC_ATTR 25
|
||||
#else
|
||||
#define SDP_MAX_REC_ATTR 8
|
||||
#endif /* defined(HID_DEV_INCLUDED) && (HID_DEV_INCLUDED==TRUE) */
|
||||
#endif
|
||||
|
||||
#ifndef SDP_MAX_PAD_LEN
|
||||
@@ -1845,6 +1872,18 @@ Range: 2 octets
|
||||
** HID
|
||||
**
|
||||
******************************************************************************/
|
||||
#ifndef BT_HID_INCLUDED
|
||||
#define BT_HID_INCLUDED FALSE
|
||||
#endif
|
||||
|
||||
/* HID Device Role Included */
|
||||
#ifndef HID_DEV_INCLUDED
|
||||
#define HID_DEV_INCLUDED FALSE
|
||||
#endif
|
||||
|
||||
#ifndef HID_DEV_SUBCLASS
|
||||
#define HID_DEV_SUBCLASS COD_MINOR_POINTING
|
||||
#endif
|
||||
|
||||
#ifndef HID_CONTROL_BUF_SIZE
|
||||
#define HID_CONTROL_BUF_SIZE BT_DEFAULT_BUFFER_SIZE
|
||||
@@ -1854,6 +1893,14 @@ Range: 2 octets
|
||||
#define HID_INTERRUPT_BUF_SIZE BT_DEFAULT_BUFFER_SIZE
|
||||
#endif
|
||||
|
||||
#ifndef HID_DEV_MTU_SIZE
|
||||
#define HID_DEV_MTU_SIZE 64
|
||||
#endif
|
||||
|
||||
#ifndef HID_DEV_FLUSH_TO
|
||||
#define HID_DEV_FLUSH_TO 0xffff
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
** Definitions for Both HID-Host & Device
|
||||
*/
|
||||
|
@@ -106,6 +106,7 @@ static inline void trc_dump_buffer(const char *prefix, uint8_t *data, uint16_t l
|
||||
#define BTTRC_ID_STK_CE 51
|
||||
#define BTTRC_ID_STK_SNEP 52
|
||||
#define BTTRC_ID_STK_NDEF 53
|
||||
#define BTTRC_ID_STK_HIDD 54
|
||||
|
||||
/* LayerIDs for BTA */
|
||||
#define BTTRC_ID_BTA_ACC 55 /* Advanced Camera Client */
|
||||
@@ -199,6 +200,7 @@ static inline void trc_dump_buffer(const char *prefix, uint8_t *data, uint16_t l
|
||||
#define AVRC_INITIAL_TRACE_LEVEL UC_BT_LOG_AVRC_TRACE_LEVEL
|
||||
#define MCA_INITIAL_TRACE_LEVEL UC_BT_LOG_MCA_TRACE_LEVEL
|
||||
#define HIDH_INITIAL_TRACE_LEVEL UC_BT_LOG_HIDH_TRACE_LEVEL
|
||||
#define HIDD_INITIAL_TRACE_LEVEL UC_BT_LOG_HIDD_TRACE_LEVEL
|
||||
#define APPL_INITIAL_TRACE_LEVEL UC_BT_LOG_APPL_TRACE_LEVEL
|
||||
#define GATT_INITIAL_TRACE_LEVEL UC_BT_LOG_GATT_TRACE_LEVEL
|
||||
#define SMP_INITIAL_TRACE_LEVEL UC_BT_LOG_SMP_TRACE_LEVEL
|
||||
@@ -258,6 +260,14 @@ static inline void trc_dump_buffer(const char *prefix, uint8_t *data, uint16_t l
|
||||
#define HIDH_TRACE_EVENT(fmt, args...) {if (hh_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(HIDH,EVENT)) BT_PRINT_D("BT_HIDH", fmt, ## args);}
|
||||
#define HIDH_TRACE_DEBUG(fmt, args...) {if (hh_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(HIDH,DEBUG)) BT_PRINT_D("BT_HIDH", fmt, ## args);}
|
||||
|
||||
/* define traces for HID Device */
|
||||
#define HIDD_TRACE_ERROR(fmt, args...) {if (hd_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(HIDD, ERROR)) BT_PRINT_E("BT_HIDD", fmt, ## args);}
|
||||
#define HIDD_TRACE_WARNING(fmt, args...) {if (hd_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(HIDD, WARNING)) BT_PRINT_W("BT_HIDD", fmt, ## args);}
|
||||
#define HIDD_TRACE_API(fmt, args...) {if (hd_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(HIDD,API)) BT_PRINT_I("BT_HIDD", fmt, ## args);}
|
||||
#define HIDD_TRACE_EVENT(fmt, args...) {if (hd_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(HIDD,EVENT)) BT_PRINT_D("BT_HIDD", fmt, ## args);}
|
||||
#define HIDD_TRACE_DEBUG(fmt, args...) {if (hd_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(HIDD,DEBUG)) BT_PRINT_D("BT_HIDD", fmt, ## args);}
|
||||
#define HIDD_TRACE_VERBOSE(fmt, args...) {if (hd_cb.trace_level >= BT_TRACE_LEVEL_VERBOSE && BT_LOG_LEVEL_CHECK(HIDD,VERBOSE)) BT_PRINT_D("BT_HIDD", fmt, ## args);}
|
||||
|
||||
/* define traces for BNEP */
|
||||
|
||||
#define BNEP_TRACE_ERROR(fmt, args...) {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(BNEP, ERROR)) BT_PRINT_E("BT_BNEP", fmt, ## args);}
|
||||
@@ -418,6 +428,14 @@ extern UINT8 btif_trace_level;
|
||||
#define HIDH_TRACE_EVENT(fmt, args...)
|
||||
#define HIDH_TRACE_DEBUG(fmt, args...)
|
||||
|
||||
/* define traces for HID Device */
|
||||
#define HIDD_TRACE_ERROR(fmt, args...)
|
||||
#define HIDD_TRACE_WARNING(fmt, args...)
|
||||
#define HIDD_TRACE_API(fmt, args...)
|
||||
#define HIDD_TRACE_EVENT(fmt, args...)
|
||||
#define HIDD_TRACE_DEBUG(fmt, args...)
|
||||
#define HIDD_TRACE_VERBOSE(fmt, args...)
|
||||
|
||||
/* define traces for BNEP */
|
||||
|
||||
#define BNEP_TRACE_ERROR(fmt, args...)
|
||||
|
@@ -52,6 +52,14 @@
|
||||
#include "pan_api.h"
|
||||
#endif
|
||||
|
||||
#if (defined(HID_HOST_INCLUDED) && HID_HOST_INCLUDED == TRUE)
|
||||
#include "stack/hidh_api.h"
|
||||
#endif
|
||||
|
||||
#if (defined(HID_DEV_INCLUDED) && HID_DEV_INCLUDED == TRUE)
|
||||
#include "stack/hidd_api.h"
|
||||
#endif
|
||||
|
||||
#if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE)
|
||||
#include "stack/avrc_api.h"
|
||||
#endif
|
||||
@@ -118,6 +126,10 @@
|
||||
#include "bta_hh_int.h"
|
||||
#endif
|
||||
|
||||
#if BTA_HD_INCLUDED==TRUE
|
||||
#include "bta_hd_int.h"
|
||||
#endif
|
||||
|
||||
#if BTA_JV_INCLUDED==TRUE
|
||||
#include "bta_jv_int.h"
|
||||
#endif
|
||||
@@ -175,6 +187,12 @@ void BTE_DeinitStack(void)
|
||||
bta_gattc_cb_ptr = NULL;
|
||||
}
|
||||
#endif
|
||||
#if BTA_HD_INCLUDED==TRUE
|
||||
if (bta_hd_cb_ptr){
|
||||
osi_free(bta_hd_cb_ptr);
|
||||
bta_hd_cb_ptr = NULL;
|
||||
}
|
||||
#endif
|
||||
#if BTA_HH_INCLUDED==TRUE
|
||||
if (bta_hh_cb_ptr){
|
||||
osi_free(bta_hh_cb_ptr);
|
||||
@@ -249,6 +267,14 @@ void BTE_DeinitStack(void)
|
||||
}
|
||||
#endif // BTA_INCLUDED == TRUE
|
||||
|
||||
#if (defined(HID_DEV_INCLUDED) && HID_DEV_INCLUDED == TRUE)
|
||||
HID_DevDeinit();
|
||||
#endif
|
||||
|
||||
#if (defined(HID_HOST_INCLUDED) && HID_HOST_INCLUDED == TRUE)
|
||||
HID_HostDeinit();
|
||||
#endif
|
||||
|
||||
#if (defined(GAP_INCLUDED) && GAP_INCLUDED == TRUE)
|
||||
GAP_Deinit();
|
||||
#endif
|
||||
@@ -347,7 +373,15 @@ bt_status_t BTE_InitStack(void)
|
||||
#endif
|
||||
|
||||
#if (defined(HID_HOST_INCLUDED) && HID_HOST_INCLUDED == TRUE)
|
||||
HID_HostInit();
|
||||
if (HID_HostInit() != HID_SUCCESS) {
|
||||
goto error_exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined(HID_DEV_INCLUDED) && HID_DEV_INCLUDED == TRUE)
|
||||
if (HID_DevInit() != HID_SUCCESS) {
|
||||
goto error_exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined(MCA_INCLUDED) && MCA_INCLUDED == TRUE)
|
||||
@@ -434,6 +468,12 @@ bt_status_t BTE_InitStack(void)
|
||||
}
|
||||
memset((void *)bta_hh_cb_ptr, 0, sizeof(tBTA_HH_CB));
|
||||
#endif
|
||||
#if BTA_HD_INCLUDED==TRUE
|
||||
if ((bta_hd_cb_ptr = (tBTA_HD_CB *)osi_malloc(sizeof(tBTA_HD_CB))) == NULL) {
|
||||
goto error_exit;
|
||||
}
|
||||
memset((void *)bta_hd_cb_ptr, 0, sizeof(tBTA_HD_CB));
|
||||
#endif
|
||||
#if BTA_HL_INCLUDED==TRUE
|
||||
memset((void *)bta_hl_cb_ptr, 0, sizeof(tBTA_HL_CB));
|
||||
#endif
|
||||
|
@@ -394,9 +394,7 @@ tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration);
|
||||
void btm_ble_stop_scan(void);
|
||||
void btm_clear_all_pending_le_entry(void);
|
||||
|
||||
BOOLEAN btm_ble_send_extended_scan_params(UINT8 scan_type, UINT32 scan_int,
|
||||
UINT32 scan_win, UINT8 addr_type_own,
|
||||
UINT8 scan_filter_policy);
|
||||
BOOLEAN btm_ble_send_extended_scan_params(UINT8 scan_type, UINT32 scan_int, UINT32 scan_win, UINT8 addr_type_own, UINT8 scan_filter_policy);
|
||||
void btm_ble_stop_inquiry(void);
|
||||
void btm_ble_init (void);
|
||||
void btm_ble_free (void);
|
||||
@@ -407,8 +405,7 @@ void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len, BOOLEAN enhanced);
|
||||
void btm_read_ble_local_supported_states_complete(UINT8 *p, UINT16 evt_len);
|
||||
tBTM_BLE_CONN_ST btm_ble_get_conn_st(void);
|
||||
void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st);
|
||||
UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst,
|
||||
tBTM_BLE_ADV_DATA *p_data);
|
||||
UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst, tBTM_BLE_ADV_DATA *p_data);
|
||||
tBTM_STATUS btm_ble_start_adv(void);
|
||||
tBTM_STATUS btm_ble_stop_adv(void);
|
||||
tBTM_STATUS btm_ble_start_scan(void);
|
||||
|
@@ -961,12 +961,10 @@ extern tBTM_CallbackFunc conn_param_update_cb;
|
||||
|
||||
typedef UINT8 tBTM_SEC_ACTION;
|
||||
|
||||
/*
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
*/
|
||||
|
||||
#if BTM_DYNAMIC_MEMORY == FALSE
|
||||
extern tBTM_CB btm_cb;
|
||||
|
@@ -54,7 +54,7 @@
|
||||
#endif
|
||||
|
||||
#if (defined(HID_HOST_INCLUDED) && HID_HOST_INCLUDED == TRUE )
|
||||
#include "hidh_int.h"
|
||||
#include "hid_int.h"
|
||||
#endif
|
||||
|
||||
#if (defined(AVDT_INCLUDED) && AVDT_INCLUDED == TRUE)
|
||||
|
586
components/bt/host/bluedroid/stack/hid/hidd_api.c
Normal file
586
components/bt/host/bluedroid/stack/hid/hidd_api.c
Normal file
@@ -0,0 +1,586 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
* Copyright (C) 2002-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 Device API entry points
|
||||
*
|
||||
******************************************************************************/
|
||||
//#include <errno.h>
|
||||
//#include <hardware/bluetooth.h>
|
||||
//#include <hardware/bt_hd.h>
|
||||
#include "stack/hidd_api.h"
|
||||
#include "esp_hidd_api.h"
|
||||
#include "hid_int.h"
|
||||
#include "osi/allocator.h"
|
||||
#include "stack/btm_api.h"
|
||||
#include "stack/btu.h"
|
||||
#include "stack/hiddefs.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if (HID_DEV_INCLUDED == TRUE)
|
||||
|
||||
#if HID_DYNAMIC_MEMORY == FALSE
|
||||
tHID_DEV_CTB hd_cb;
|
||||
#else
|
||||
tHID_DEV_CTB *hidd_cb_ptr = NULL;
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevInit
|
||||
*
|
||||
* Description Initializes control block
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevInit(void)
|
||||
{
|
||||
#if (HID_DYNAMIC_MEMORY)
|
||||
if (!hidd_cb_ptr) {
|
||||
hidd_cb_ptr = (tHID_DEV_CTB *)osi_malloc(sizeof(tHID_DEV_CTB));
|
||||
if (!hidd_cb_ptr) {
|
||||
return HID_ERR_NO_RESOURCES;
|
||||
}
|
||||
}
|
||||
#endif /* #if (HID_DYNAMIC_MEMORY) */
|
||||
memset(&hd_cb, 0, sizeof(tHID_DEV_CTB));
|
||||
#if defined(HIDD_INITIAL_TRACE_LEVEL)
|
||||
hd_cb.trace_level = HIDD_INITIAL_TRACE_LEVEL;
|
||||
#else
|
||||
hd_cb.trace_level = BT_TRACE_LEVEL_NONE;
|
||||
#endif
|
||||
return HID_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevDeinit
|
||||
*
|
||||
* Description Deinitializes control block
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void HID_DevDeinit(void)
|
||||
{
|
||||
#if (HID_DYNAMIC_MEMORY)
|
||||
if (hidd_cb_ptr) {
|
||||
osi_free(hidd_cb_ptr);
|
||||
hidd_cb_ptr = NULL;
|
||||
}
|
||||
#endif /* #if (HID_DYNAMIC_MEMORY) */
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevSetTraceLevel
|
||||
*
|
||||
* Description This function sets the trace level for HID Dev. If called
|
||||
* with
|
||||
* a value of 0xFF, it simply reads the current trace level.
|
||||
*
|
||||
* Returns the new (current) trace level
|
||||
*
|
||||
******************************************************************************/
|
||||
uint8_t HID_DevSetTraceLevel(uint8_t new_level)
|
||||
{
|
||||
if (new_level != 0xFF) {
|
||||
hd_cb.trace_level = new_level;
|
||||
}
|
||||
|
||||
return (hd_cb.trace_level);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevRegister
|
||||
*
|
||||
* Description Registers HID device with lower layers
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevRegister(tHID_DEV_HOST_CALLBACK *host_cback)
|
||||
{
|
||||
tHID_STATUS st;
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
|
||||
if (hd_cb.reg_flag) {
|
||||
return HID_ERR_ALREADY_REGISTERED;
|
||||
}
|
||||
|
||||
if (host_cback == NULL) {
|
||||
return HID_ERR_INVALID_PARAM;
|
||||
}
|
||||
/* Register with L2CAP */
|
||||
if ((st = hidd_conn_reg()) != HID_SUCCESS) {
|
||||
return st;
|
||||
}
|
||||
|
||||
hd_cb.callback = host_cback;
|
||||
hd_cb.reg_flag = TRUE;
|
||||
|
||||
if (hd_cb.pending_data) {
|
||||
osi_free(hd_cb.pending_data);
|
||||
hd_cb.pending_data = NULL;
|
||||
}
|
||||
return (HID_SUCCESS);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevDeregister
|
||||
*
|
||||
* Description Deregisters HID device with lower layers
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevDeregister(void)
|
||||
{
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
|
||||
if (!hd_cb.reg_flag)
|
||||
return (HID_ERR_NOT_REGISTERED);
|
||||
hidd_conn_dereg();
|
||||
hd_cb.reg_flag = FALSE;
|
||||
|
||||
return (HID_SUCCESS);
|
||||
}
|
||||
|
||||
tHID_STATUS HID_DevSetSecurityLevel(uint8_t sec_lvl)
|
||||
{
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
if (!BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_HIDD_SEC_CTRL, sec_lvl, HID_PSM_CONTROL, BTM_SEC_PROTO_HID,
|
||||
HIDD_SEC_CHN)) {
|
||||
HIDD_TRACE_ERROR("Security Registration 1 failed");
|
||||
return (HID_ERR_NO_RESOURCES);
|
||||
}
|
||||
if (!BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_HIDD_SEC_CTRL, sec_lvl, HID_PSM_CONTROL, BTM_SEC_PROTO_HID,
|
||||
HIDD_SEC_CHN)) {
|
||||
HIDD_TRACE_ERROR("Security Registration 2 failed");
|
||||
return (HID_ERR_NO_RESOURCES);
|
||||
}
|
||||
if (!BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_HIDD_NOSEC_CTRL, BTM_SEC_NONE, HID_PSM_CONTROL,
|
||||
BTM_SEC_PROTO_HID, HIDD_NOSEC_CHN)) {
|
||||
HIDD_TRACE_ERROR("Security Registration 3 failed");
|
||||
return (HID_ERR_NO_RESOURCES);
|
||||
}
|
||||
if (!BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_HIDD_NOSEC_CTRL, BTM_SEC_NONE, HID_PSM_CONTROL,
|
||||
BTM_SEC_PROTO_HID, HIDD_NOSEC_CHN)) {
|
||||
HIDD_TRACE_ERROR("Security Registration 4 failed");
|
||||
return (HID_ERR_NO_RESOURCES);
|
||||
}
|
||||
if (!BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_HIDD_INTR, BTM_SEC_NONE, HID_PSM_INTERRUPT, BTM_SEC_PROTO_HID,
|
||||
0)) {
|
||||
HIDD_TRACE_ERROR("Security Registration 5 failed");
|
||||
return (HID_ERR_NO_RESOURCES);
|
||||
}
|
||||
if (!BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_HIDD_INTR, BTM_SEC_NONE, HID_PSM_INTERRUPT, BTM_SEC_PROTO_HID,
|
||||
0)) {
|
||||
HIDD_TRACE_ERROR("Security Registration 6 failed");
|
||||
return (HID_ERR_NO_RESOURCES);
|
||||
}
|
||||
return (HID_SUCCESS);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevAddRecord
|
||||
*
|
||||
* Description Creates SDP record for HID device
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevAddRecord(uint32_t handle, char *p_name, char *p_description, char *p_provider, uint16_t subclass,
|
||||
uint16_t desc_len, uint8_t *p_desc_data)
|
||||
{
|
||||
bool result = TRUE;
|
||||
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
|
||||
// Service Class ID List
|
||||
if (result) {
|
||||
uint16_t uuid = UUID_SERVCLASS_HUMAN_INTERFACE;
|
||||
result &= SDP_AddServiceClassIdList(handle, 1, &uuid);
|
||||
}
|
||||
// Protocol Descriptor List
|
||||
if (result) {
|
||||
tSDP_PROTOCOL_ELEM proto_list[2];
|
||||
proto_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
|
||||
proto_list[0].num_params = 1;
|
||||
proto_list[0].params[0] = BT_PSM_HIDC;
|
||||
proto_list[1].protocol_uuid = UUID_PROTOCOL_HIDP;
|
||||
proto_list[1].num_params = 0;
|
||||
result &= SDP_AddProtocolList(handle, 2, proto_list);
|
||||
}
|
||||
// Language Base Attribute ID List
|
||||
if (result) {
|
||||
result &=
|
||||
SDP_AddLanguageBaseAttrIDList(handle, LANG_ID_CODE_ENGLISH, LANG_ID_CHAR_ENCODE_UTF8, LANGUAGE_BASE_ID);
|
||||
}
|
||||
// Additional Protocol Descriptor List
|
||||
if (result) {
|
||||
tSDP_PROTO_LIST_ELEM add_proto_list;
|
||||
add_proto_list.num_elems = 2;
|
||||
add_proto_list.list_elem[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
|
||||
add_proto_list.list_elem[0].num_params = 1;
|
||||
add_proto_list.list_elem[0].params[0] = BT_PSM_HIDI;
|
||||
add_proto_list.list_elem[1].protocol_uuid = UUID_PROTOCOL_HIDP;
|
||||
add_proto_list.list_elem[1].num_params = 0;
|
||||
result &= SDP_AddAdditionProtoLists(handle, 1, &add_proto_list);
|
||||
}
|
||||
// Service Name (O)
|
||||
// Service Description (O)
|
||||
// Provider Name (O)
|
||||
if (result) {
|
||||
const char *srv_name = p_name;
|
||||
const char *srv_desc = p_description;
|
||||
const char *provider_name = p_provider;
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE, strlen(srv_name) + 1,
|
||||
(uint8_t *)srv_name);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_SERVICE_DESCRIPTION, TEXT_STR_DESC_TYPE, strlen(srv_desc) + 1,
|
||||
(uint8_t *)srv_desc);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_PROVIDER_NAME, TEXT_STR_DESC_TYPE, strlen(provider_name) + 1,
|
||||
(uint8_t *)provider_name);
|
||||
}
|
||||
// Bluetooth Profile Descriptor List
|
||||
if (result) {
|
||||
const uint16_t profile_uuid = UUID_SERVCLASS_HUMAN_INTERFACE;
|
||||
const uint16_t version = 0x0100;
|
||||
result &= SDP_AddProfileDescriptorList(handle, profile_uuid, version);
|
||||
}
|
||||
// HID Parser Version
|
||||
if (result) {
|
||||
uint8_t *p;
|
||||
const uint16_t rel_num = 0x0100;
|
||||
const uint16_t parser_version = 0x0111;
|
||||
const uint16_t prof_ver = 0x0100;
|
||||
const uint8_t dev_subclass = subclass;
|
||||
const uint8_t country_code = 0x21;
|
||||
const uint8_t bool_false = 0x00;
|
||||
const uint8_t bool_true = 0x01;
|
||||
uint16_t temp;
|
||||
p = (uint8_t *)&temp;
|
||||
UINT16_TO_BE_STREAM(p, rel_num);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_HID_DEVICE_RELNUM, UINT_DESC_TYPE, 2, (uint8_t *)&temp);
|
||||
p = (uint8_t *)&temp;
|
||||
UINT16_TO_BE_STREAM(p, parser_version);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_HID_PARSER_VERSION, UINT_DESC_TYPE, 2, (uint8_t *)&temp);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_HID_DEVICE_SUBCLASS, UINT_DESC_TYPE, 1, (uint8_t *)&dev_subclass);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_HID_COUNTRY_CODE, UINT_DESC_TYPE, 1, (uint8_t *)&country_code);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_HID_VIRTUAL_CABLE, BOOLEAN_DESC_TYPE, 1, (uint8_t *)&bool_true);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_HID_RECONNECT_INITIATE, BOOLEAN_DESC_TYPE, 1, (uint8_t *)&bool_true);
|
||||
{
|
||||
static uint8_t cdt = 0x22;
|
||||
uint8_t *p_buf;
|
||||
uint8_t seq_len = 4 + desc_len;
|
||||
p_buf = (uint8_t *)osi_malloc(2048);
|
||||
if (p_buf == NULL) {
|
||||
HIDD_TRACE_ERROR("%s: Buffer allocation failure for size = 2048 ", __func__);
|
||||
return HID_ERR_NOT_REGISTERED;
|
||||
}
|
||||
p = p_buf;
|
||||
UINT8_TO_BE_STREAM(p, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
|
||||
UINT8_TO_BE_STREAM(p, seq_len);
|
||||
UINT8_TO_BE_STREAM(p, (UINT_DESC_TYPE << 3) | SIZE_ONE_BYTE);
|
||||
UINT8_TO_BE_STREAM(p, cdt);
|
||||
UINT8_TO_BE_STREAM(p, (TEXT_STR_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
|
||||
UINT8_TO_BE_STREAM(p, desc_len);
|
||||
ARRAY_TO_BE_STREAM(p, p_desc_data, (int)desc_len);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_HID_DESCRIPTOR_LIST, DATA_ELE_SEQ_DESC_TYPE, p - p_buf, p_buf);
|
||||
osi_free(p_buf);
|
||||
}
|
||||
{
|
||||
uint8_t lang_buf[8];
|
||||
p = lang_buf;
|
||||
uint8_t seq_len = 6;
|
||||
uint16_t lang_english = 0x0409;
|
||||
UINT8_TO_BE_STREAM(p, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
|
||||
UINT8_TO_BE_STREAM(p, seq_len);
|
||||
UINT8_TO_BE_STREAM(p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
|
||||
UINT16_TO_BE_STREAM(p, lang_english);
|
||||
UINT8_TO_BE_STREAM(p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
|
||||
UINT16_TO_BE_STREAM(p, LANGUAGE_BASE_ID);
|
||||
result &=
|
||||
SDP_AddAttribute(handle, ATTR_ID_HID_LANGUAGE_ID_BASE, DATA_ELE_SEQ_DESC_TYPE, p - lang_buf, lang_buf);
|
||||
}
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_HID_BATTERY_POWER, BOOLEAN_DESC_TYPE, 1, (uint8_t *)&bool_true);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_HID_REMOTE_WAKE, BOOLEAN_DESC_TYPE, 1, (uint8_t *)&bool_false);
|
||||
result &=
|
||||
SDP_AddAttribute(handle, ATTR_ID_HID_NORMALLY_CONNECTABLE, BOOLEAN_DESC_TYPE, 1, (uint8_t *)&bool_true);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_HID_BOOT_DEVICE, BOOLEAN_DESC_TYPE, 1, (uint8_t *)&bool_true);
|
||||
p = (uint8_t *)&temp;
|
||||
UINT16_TO_BE_STREAM(p, prof_ver);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_HID_PROFILE_VERSION, UINT_DESC_TYPE, 2, (uint8_t *)&temp);
|
||||
}
|
||||
if (result) {
|
||||
uint16_t browse_group = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
|
||||
result &= SDP_AddUuidSequence(handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse_group);
|
||||
}
|
||||
if (!result) {
|
||||
HIDD_TRACE_ERROR("%s: failed to complete SDP record", __func__);
|
||||
return HID_ERR_NOT_REGISTERED;
|
||||
}
|
||||
return HID_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevSendReport
|
||||
*
|
||||
* Description Sends report
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevSendReport(uint8_t channel, uint8_t type, uint8_t id, uint16_t len, uint8_t *p_data)
|
||||
{
|
||||
HIDD_TRACE_VERBOSE("%s: channel=%d type=%d id=%d len=%d", __func__, channel, type, id, len);
|
||||
|
||||
if (channel == HID_CHANNEL_CTRL) {
|
||||
return hidd_conn_send_data(HID_CHANNEL_CTRL, HID_TRANS_DATA, type, id, len, p_data);
|
||||
}
|
||||
|
||||
if (channel == HID_CHANNEL_INTR && type == HID_PAR_REP_TYPE_INPUT) {
|
||||
// on INTR we can only send INPUT
|
||||
return hidd_conn_send_data(HID_CHANNEL_INTR, HID_TRANS_DATA, HID_PAR_REP_TYPE_INPUT, id, len, p_data);
|
||||
}
|
||||
|
||||
return HID_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevVirtualCableUnplug
|
||||
*
|
||||
* Description Sends Virtual Cable Unplug
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevVirtualCableUnplug(void)
|
||||
{
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
|
||||
return hidd_conn_send_data(HID_CHANNEL_CTRL, HID_TRANS_CONTROL, HID_PAR_CONTROL_VIRTUAL_CABLE_UNPLUG, 0, 0, NULL);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevPlugDevice
|
||||
*
|
||||
* Description Establishes virtual cable to given host
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevPlugDevice(BD_ADDR addr)
|
||||
{
|
||||
hd_cb.device.in_use = TRUE;
|
||||
memcpy(hd_cb.device.addr, addr, sizeof(BD_ADDR));
|
||||
|
||||
return HID_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevUnplugDevice
|
||||
*
|
||||
* Description Unplugs virtual cable from given host
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevUnplugDevice(BD_ADDR addr)
|
||||
{
|
||||
if (!memcmp(hd_cb.device.addr, addr, sizeof(BD_ADDR))) {
|
||||
hd_cb.device.in_use = FALSE;
|
||||
hd_cb.device.conn.conn_state = HID_CONN_STATE_UNUSED;
|
||||
hd_cb.device.conn.ctrl_cid = 0;
|
||||
hd_cb.device.conn.intr_cid = 0;
|
||||
}
|
||||
return HID_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevConnect
|
||||
*
|
||||
* Description Connects to device
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevConnect(void)
|
||||
{
|
||||
if (!hd_cb.reg_flag) {
|
||||
return HID_ERR_NOT_REGISTERED;
|
||||
}
|
||||
if (!hd_cb.device.in_use) {
|
||||
return HID_ERR_INVALID_PARAM;
|
||||
}
|
||||
if (hd_cb.device.state != HIDD_DEV_NO_CONN) {
|
||||
return HID_ERR_ALREADY_CONN;
|
||||
}
|
||||
return hidd_conn_initiate();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevDisconnect
|
||||
*
|
||||
* Description Disconnects from device
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevDisconnect(void)
|
||||
{
|
||||
if (!hd_cb.reg_flag) {
|
||||
return HID_ERR_NOT_REGISTERED;
|
||||
}
|
||||
if (!hd_cb.device.in_use) {
|
||||
return HID_ERR_INVALID_PARAM;
|
||||
}
|
||||
if (hd_cb.device.state == HIDD_DEV_NO_CONN) {
|
||||
return HID_ERR_NO_CONNECTION;
|
||||
}
|
||||
return hidd_conn_disconnect();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevSetIncomingPolicy
|
||||
*
|
||||
* Description Sets policy for incoming connections (allowed/disallowed)
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevSetIncomingPolicy(bool allow)
|
||||
{
|
||||
hd_cb.allow_incoming = allow;
|
||||
return HID_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevReportError
|
||||
*
|
||||
* Description Reports error for Set Report via HANDSHAKE
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevReportError(uint8_t error)
|
||||
{
|
||||
uint8_t handshake_param;
|
||||
|
||||
HIDD_TRACE_API("%s: error = %d", __func__, error);
|
||||
|
||||
switch (error) {
|
||||
case HID_PAR_HANDSHAKE_RSP_SUCCESS:
|
||||
case HID_PAR_HANDSHAKE_RSP_NOT_READY:
|
||||
case HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID:
|
||||
case HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ:
|
||||
case HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM:
|
||||
case HID_PAR_HANDSHAKE_RSP_ERR_UNKNOWN:
|
||||
case HID_PAR_HANDSHAKE_RSP_ERR_FATAL:
|
||||
handshake_param = error;
|
||||
break;
|
||||
default:
|
||||
handshake_param = HID_PAR_HANDSHAKE_RSP_ERR_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
return hidd_conn_send_data(0, HID_TRANS_HANDSHAKE, handshake_param, 0, 0, NULL);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevGetDevice
|
||||
*
|
||||
* Description Returns the BD Address of virtually cabled device
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevGetDevice(BD_ADDR *addr)
|
||||
{
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
|
||||
if (hd_cb.device.in_use) {
|
||||
memcpy(addr, hd_cb.device.addr, sizeof(BD_ADDR));
|
||||
} else {
|
||||
return HID_ERR_NOT_REGISTERED;
|
||||
}
|
||||
|
||||
return HID_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevSetIncomingQos
|
||||
*
|
||||
* Description Sets Incoming QoS values for Interrupt L2CAP Channel
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevSetIncomingQos(uint8_t service_type, uint32_t token_rate, uint32_t token_bucket_size,
|
||||
uint32_t peak_bandwidth, uint32_t latency, uint32_t delay_variation)
|
||||
{
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
hd_cb.use_in_qos = TRUE;
|
||||
hd_cb.in_qos.service_type = service_type;
|
||||
hd_cb.in_qos.token_rate = token_rate;
|
||||
hd_cb.in_qos.token_bucket_size = token_bucket_size;
|
||||
hd_cb.in_qos.peak_bandwidth = peak_bandwidth;
|
||||
hd_cb.in_qos.latency = latency;
|
||||
hd_cb.in_qos.delay_variation = delay_variation;
|
||||
return HID_SUCCESS;
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevSetOutgoingQos
|
||||
*
|
||||
* Description Sets Outgoing QoS values for Interrupt L2CAP Channel
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevSetOutgoingQos(uint8_t service_type, uint32_t token_rate, uint32_t token_bucket_size,
|
||||
uint32_t peak_bandwidth, uint32_t latency, uint32_t delay_variation)
|
||||
{
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
hd_cb.l2cap_intr_cfg.qos_present = TRUE;
|
||||
hd_cb.l2cap_intr_cfg.qos.service_type = service_type;
|
||||
hd_cb.l2cap_intr_cfg.qos.token_rate = token_rate;
|
||||
hd_cb.l2cap_intr_cfg.qos.token_bucket_size = token_bucket_size;
|
||||
hd_cb.l2cap_intr_cfg.qos.peak_bandwidth = peak_bandwidth;
|
||||
hd_cb.l2cap_intr_cfg.qos.latency = latency;
|
||||
hd_cb.l2cap_intr_cfg.qos.delay_variation = delay_variation;
|
||||
return HID_SUCCESS;
|
||||
}
|
||||
#endif
|
780
components/bt/host/bluedroid/stack/hid/hidd_conn.c
Normal file
780
components/bt/host/bluedroid/stack/hid/hidd_conn.c
Normal file
@@ -0,0 +1,780 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
* Copyright (C) 2002-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 connection interface functions
|
||||
*
|
||||
******************************************************************************/
|
||||
#include "btm_int.h"
|
||||
#include "hid_conn.h"
|
||||
#include "hid_int.h"
|
||||
#include "osi/allocator.h"
|
||||
#include "osi/osi.h"
|
||||
#include "stack/btm_api.h"
|
||||
#include "stack/btu.h"
|
||||
#include "stack/hidd_api.h"
|
||||
#include "stack/hiddefs.h"
|
||||
#include "stack/l2c_api.h"
|
||||
#include "stack/l2cdefs.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if (HID_DEV_INCLUDED == TRUE)
|
||||
|
||||
static void hidd_l2cif_connect_ind(BD_ADDR bd_addr, uint16_t cid, uint16_t psm, uint8_t id);
|
||||
static void hidd_l2cif_connect_cfm(uint16_t cid, uint16_t result);
|
||||
static void hidd_l2cif_config_ind(uint16_t cid, tL2CAP_CFG_INFO *p_cfg);
|
||||
static void hidd_l2cif_config_cfm(uint16_t cid, tL2CAP_CFG_INFO *p_cfg);
|
||||
static void hidd_l2cif_disconnect_ind(uint16_t cid, bool ack_needed);
|
||||
static void hidd_l2cif_disconnect_cfm(uint16_t cid, uint16_t result);
|
||||
static void hidd_l2cif_data_ind(uint16_t cid, BT_HDR *p_msg);
|
||||
static void hidd_l2cif_cong_ind(uint16_t cid, bool congested);
|
||||
|
||||
static const tL2CAP_APPL_INFO dev_reg_info = {hidd_l2cif_connect_ind,
|
||||
hidd_l2cif_connect_cfm,
|
||||
NULL,
|
||||
hidd_l2cif_config_ind,
|
||||
hidd_l2cif_config_cfm,
|
||||
hidd_l2cif_disconnect_ind,
|
||||
hidd_l2cif_disconnect_cfm,
|
||||
NULL,
|
||||
hidd_l2cif_data_ind,
|
||||
hidd_l2cif_cong_ind,
|
||||
NULL};
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_check_config_done
|
||||
*
|
||||
* Description Checks if connection is configured and callback can be fired
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void hidd_check_config_done(void)
|
||||
{
|
||||
tHID_CONN *p_hcon;
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if (((p_hcon->conn_flags & HID_CONN_FLAGS_ALL_CONFIGURED) == HID_CONN_FLAGS_ALL_CONFIGURED) &&
|
||||
(p_hcon->conn_state == HID_CONN_STATE_CONFIG)) {
|
||||
p_hcon->conn_state = HID_CONN_STATE_CONNECTED;
|
||||
hd_cb.device.state = HIDD_DEV_CONNECTED;
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_OPEN, 0, NULL);
|
||||
// send outstanding data on intr
|
||||
if (hd_cb.pending_data) {
|
||||
L2CA_DataWrite(p_hcon->intr_cid, hd_cb.pending_data);
|
||||
hd_cb.pending_data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidh_sec_check_complete_term
|
||||
*
|
||||
* Description HID security check complete callback function.
|
||||
*
|
||||
* Returns Send L2CA_ConnectRsp OK if secutiry check succeed; otherwise
|
||||
* send security block L2C connection response.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void hidd_sec_check_complete(UNUSED_ATTR BD_ADDR bd_addr, UNUSED_ATTR tBT_TRANSPORT transport, void *p_ref_data,
|
||||
uint8_t res)
|
||||
{
|
||||
tHID_DEV_DEV_CTB *p_dev = (tHID_DEV_DEV_CTB *)p_ref_data;
|
||||
if (res == BTM_SUCCESS && p_dev->conn.conn_state == HID_CONN_STATE_SECURITY) {
|
||||
p_dev->conn.disc_reason = HID_SUCCESS;
|
||||
p_dev->conn.conn_state = HID_CONN_STATE_CONNECTING_INTR;
|
||||
L2CA_ConnectRsp(p_dev->addr, p_dev->conn.ctrl_id, p_dev->conn.ctrl_cid, L2CAP_CONN_OK, L2CAP_CONN_OK);
|
||||
L2CA_ConfigReq(p_dev->conn.ctrl_cid, &hd_cb.l2cap_cfg);
|
||||
} else if (res != BTM_SUCCESS) {
|
||||
HIDD_TRACE_WARNING("%s: connection rejected by security", __func__);
|
||||
p_dev->conn.disc_reason = HID_ERR_AUTH_FAILED;
|
||||
p_dev->conn.conn_state = HID_CONN_STATE_UNUSED;
|
||||
L2CA_ConnectRsp(p_dev->addr, p_dev->conn.ctrl_id, p_dev->conn.ctrl_cid, L2CAP_CONN_SECURITY_BLOCK,
|
||||
L2CAP_CONN_OK);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_sec_check_complete_orig
|
||||
*
|
||||
* Description HID security check complete callback function (device
|
||||
*originated)
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void hidd_sec_check_complete_orig(UNUSED_ATTR BD_ADDR bd_addr, UNUSED_ATTR tBT_TRANSPORT transport, void *p_ref_data,
|
||||
uint8_t res)
|
||||
{
|
||||
tHID_DEV_DEV_CTB *p_dev = (tHID_DEV_DEV_CTB *)p_ref_data;
|
||||
if (p_dev->conn.conn_state != HID_CONN_STATE_SECURITY) {
|
||||
HIDD_TRACE_WARNING("%s: invalid state (%02x)", __func__, p_dev->conn.conn_state);
|
||||
return;
|
||||
}
|
||||
if (res == BTM_SUCCESS) {
|
||||
HIDD_TRACE_EVENT("%s: security ok", __func__);
|
||||
p_dev->conn.disc_reason = HID_SUCCESS;
|
||||
p_dev->conn.conn_state = HID_CONN_STATE_CONFIG;
|
||||
L2CA_ConfigReq(p_dev->conn.ctrl_cid, &hd_cb.l2cap_cfg);
|
||||
} else {
|
||||
HIDD_TRACE_WARNING("%s: security check failed (%02x)", __func__, res);
|
||||
p_dev->conn.disc_reason = HID_ERR_AUTH_FAILED;
|
||||
hidd_conn_disconnect();
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_l2cif_connect_ind
|
||||
*
|
||||
* Description Handles incoming L2CAP connection (we act as server)
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void hidd_l2cif_connect_ind(BD_ADDR bd_addr, uint16_t cid, uint16_t psm, uint8_t id)
|
||||
{
|
||||
tHID_CONN *p_hcon;
|
||||
tHID_DEV_DEV_CTB *p_dev;
|
||||
bool accept = TRUE; // accept by default
|
||||
HIDD_TRACE_EVENT("%s: psm=%04x cid=%04x id=%02x", __func__, psm, cid, id);
|
||||
p_dev = &hd_cb.device;
|
||||
if (!hd_cb.allow_incoming) {
|
||||
HIDD_TRACE_WARNING("%s: incoming connections not allowed, rejecting", __func__);
|
||||
L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_NO_RESOURCES, 0);
|
||||
return;
|
||||
}
|
||||
if (p_dev->in_use && memcmp(bd_addr, p_dev->addr, sizeof(BD_ADDR))) {
|
||||
HIDD_TRACE_WARNING("%s: incoming connections from different device, rejecting", __func__);
|
||||
L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_NO_RESOURCES, 0);
|
||||
return;
|
||||
} else if (!p_dev->in_use) {
|
||||
p_dev->in_use = TRUE;
|
||||
memcpy(p_dev->addr, bd_addr, sizeof(BD_ADDR));
|
||||
p_dev->state = HIDD_DEV_NO_CONN;
|
||||
}
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
switch (psm) {
|
||||
case HID_PSM_INTERRUPT:
|
||||
if (p_hcon->ctrl_cid == 0) {
|
||||
accept = FALSE;
|
||||
HIDD_TRACE_WARNING("%s: incoming INTR without CTRL, rejecting", __func__);
|
||||
}
|
||||
if (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR) {
|
||||
accept = FALSE;
|
||||
HIDD_TRACE_WARNING("%s: incoming INTR in invalid state (%d), rejecting", __func__, p_hcon->conn_state);
|
||||
}
|
||||
break;
|
||||
case HID_PSM_CONTROL:
|
||||
if (p_hcon->conn_state != HID_CONN_STATE_UNUSED) {
|
||||
accept = FALSE;
|
||||
HIDD_TRACE_WARNING("%s: incoming CTRL in invalid state (%d), rejecting", __func__, p_hcon->conn_state);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
accept = FALSE;
|
||||
HIDD_TRACE_ERROR("%s: received invalid PSM, rejecting", __func__);
|
||||
break;
|
||||
}
|
||||
if (!accept) {
|
||||
L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_NO_RESOURCES, 0);
|
||||
return;
|
||||
}
|
||||
// for CTRL we need to go through security and we reply in callback from there
|
||||
if (psm == HID_PSM_CONTROL) {
|
||||
p_hcon->conn_flags = 0;
|
||||
p_hcon->ctrl_cid = cid;
|
||||
p_hcon->ctrl_id = id;
|
||||
p_hcon->disc_reason = HID_L2CAP_CONN_FAIL;
|
||||
p_hcon->conn_state = HID_CONN_STATE_SECURITY;
|
||||
if (btm_sec_mx_access_request(p_dev->addr, HID_PSM_CONTROL, FALSE, BTM_SEC_PROTO_HID, HIDD_NOSEC_CHN,
|
||||
&hidd_sec_check_complete, p_dev) == BTM_CMD_STARTED) {
|
||||
L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_PENDING, L2CAP_CONN_OK);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// for INTR we go directly to config state
|
||||
p_hcon->conn_state = HID_CONN_STATE_CONFIG;
|
||||
p_hcon->intr_cid = cid;
|
||||
L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_OK, L2CAP_CONN_OK);
|
||||
L2CA_ConfigReq(cid, &hd_cb.l2cap_intr_cfg);
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_l2cif_connect_cfm
|
||||
*
|
||||
* Description Handles L2CAP connection response (we act as client)
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void hidd_l2cif_connect_cfm(uint16_t cid, uint16_t result)
|
||||
{
|
||||
tHID_DEV_DEV_CTB *p_dev = &hd_cb.device;
|
||||
tHID_CONN *p_hcon = &hd_cb.device.conn;
|
||||
HIDD_TRACE_EVENT("%s: cid=%04x result=%d, conn_state=%d", __func__, cid, result, p_hcon->conn_state);
|
||||
if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) {
|
||||
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
|
||||
return;
|
||||
}
|
||||
if (!(p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) ||
|
||||
((cid == p_hcon->ctrl_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_CTRL && (p_hcon->conn_state != HID_CONN_STATE_DISCONNECTING_INTR))) ||
|
||||
((cid == p_hcon->intr_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR) && (p_hcon->conn_state != HID_CONN_STATE_DISCONNECTING_CTRL))) {
|
||||
HIDD_TRACE_WARNING("%s: unexpected, cid:0x%04x, ctrl_cid:0x%04x, intr_cid:0x%04x, conn_state:%d", __func__, cid,
|
||||
p_hcon->ctrl_cid, p_hcon->intr_cid, p_hcon->conn_state);
|
||||
return;
|
||||
}
|
||||
if (result != L2CAP_CONN_OK) {
|
||||
HIDD_TRACE_WARNING("%s: connection failed, now disconnect", __func__);
|
||||
if (cid == p_hcon->ctrl_cid)
|
||||
p_hcon->ctrl_cid = 0;
|
||||
else
|
||||
p_hcon->intr_cid = 0;
|
||||
hidd_conn_disconnect();
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_L2CAP_CONN_FAIL | (uint32_t)result, NULL);
|
||||
return;
|
||||
}
|
||||
/* CTRL connect conf */
|
||||
if (cid == p_hcon->ctrl_cid) {
|
||||
p_hcon->conn_state = HID_CONN_STATE_SECURITY;
|
||||
p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; /* in case disconnected before sec completed */
|
||||
btm_sec_mx_access_request(p_dev->addr, HID_PSM_CONTROL, TRUE, BTM_SEC_PROTO_HID, HIDD_SEC_CHN,
|
||||
&hidd_sec_check_complete_orig, p_dev);
|
||||
} else {
|
||||
p_hcon->conn_state = HID_CONN_STATE_CONFIG;
|
||||
L2CA_ConfigReq(cid, &hd_cb.l2cap_intr_cfg);
|
||||
}
|
||||
return;
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_l2cif_config_ind
|
||||
*
|
||||
* Description Handles incoming L2CAP configuration request
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void hidd_l2cif_config_ind(uint16_t cid, tL2CAP_CFG_INFO *p_cfg)
|
||||
{
|
||||
tHID_CONN *p_hcon;
|
||||
HIDD_TRACE_EVENT("%s: cid=%04x", __func__, cid);
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) {
|
||||
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
|
||||
return;
|
||||
}
|
||||
if ((!p_cfg->mtu_present) || (p_cfg->mtu > HID_DEV_MTU_SIZE))
|
||||
p_hcon->rem_mtu_size = HID_DEV_MTU_SIZE;
|
||||
else
|
||||
p_hcon->rem_mtu_size = p_cfg->mtu;
|
||||
// accept without changes
|
||||
p_cfg->flush_to_present = FALSE;
|
||||
p_cfg->mtu_present = FALSE;
|
||||
p_cfg->result = L2CAP_CFG_OK;
|
||||
if (cid == p_hcon->intr_cid && hd_cb.use_in_qos && !p_cfg->qos_present) {
|
||||
p_cfg->qos_present = TRUE;
|
||||
memcpy(&p_cfg->qos, &hd_cb.in_qos, sizeof(FLOW_SPEC));
|
||||
}
|
||||
L2CA_ConfigRsp(cid, p_cfg);
|
||||
// update flags
|
||||
if (cid == p_hcon->ctrl_cid) {
|
||||
p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_CTRL_CFG_DONE;
|
||||
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_MY_CTRL_CFG_DONE)) {
|
||||
p_hcon->disc_reason = HID_L2CAP_CONN_FAIL;
|
||||
if ((p_hcon->intr_cid = L2CA_ConnectReq(HID_PSM_INTERRUPT, hd_cb.device.addr)) == 0) {
|
||||
p_hcon->conn_state = HID_CONN_STATE_UNUSED;
|
||||
hidd_conn_disconnect();
|
||||
HIDD_TRACE_WARNING("%s: could not start L2CAP connection for INTR", __func__);
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_ERR_L2CAP_FAILED, NULL);
|
||||
return;
|
||||
} else {
|
||||
p_hcon->conn_state = HID_CONN_STATE_CONNECTING_INTR;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_INTR_CFG_DONE;
|
||||
}
|
||||
hidd_check_config_done();
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_l2cif_config_cfm
|
||||
*
|
||||
* Description Handles incoming L2CAP configuration response
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void hidd_l2cif_config_cfm(uint16_t cid, tL2CAP_CFG_INFO *p_cfg)
|
||||
{
|
||||
tHID_CONN *p_hcon;
|
||||
uint32_t reason;
|
||||
HIDD_TRACE_EVENT("%s: cid=%04x pcfg->result=%d", __func__, cid, p_cfg->result);
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) {
|
||||
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
|
||||
return;
|
||||
}
|
||||
if (p_hcon->intr_cid == cid && p_cfg->result == L2CAP_CFG_UNACCEPTABLE_PARAMS && p_cfg->qos_present) {
|
||||
tL2CAP_CFG_INFO new_qos;
|
||||
// QoS parameters not accepted for intr, try again with host proposal
|
||||
memcpy(&new_qos, &hd_cb.l2cap_intr_cfg, sizeof(new_qos));
|
||||
memcpy(&new_qos.qos, &p_cfg->qos, sizeof(FLOW_SPEC));
|
||||
new_qos.qos_present = TRUE;
|
||||
HIDD_TRACE_WARNING("%s: config failed, retry", __func__);
|
||||
L2CA_ConfigReq(cid, &new_qos);
|
||||
return;
|
||||
} else if (p_hcon->intr_cid == cid && p_cfg->result == L2CAP_CFG_UNKNOWN_OPTIONS) {
|
||||
// QoS not understood by remote device, try configuring without QoS
|
||||
HIDD_TRACE_WARNING("%s: config failed, retry without QoS", __func__);
|
||||
L2CA_ConfigReq(cid, &hd_cb.l2cap_cfg);
|
||||
return;
|
||||
} else if (p_cfg->result != L2CAP_CFG_OK) {
|
||||
HIDD_TRACE_WARNING("%s: config failed, disconnecting", __func__);
|
||||
hidd_conn_disconnect();
|
||||
reason = HID_L2CAP_CFG_FAIL | (uint32_t)p_cfg->result;
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, reason, NULL);
|
||||
return;
|
||||
}
|
||||
// update flags
|
||||
if (cid == p_hcon->ctrl_cid) {
|
||||
p_hcon->conn_flags |= HID_CONN_FLAGS_MY_CTRL_CFG_DONE;
|
||||
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_HIS_CTRL_CFG_DONE)) {
|
||||
p_hcon->disc_reason = HID_L2CAP_CONN_FAIL;
|
||||
if ((p_hcon->intr_cid = L2CA_ConnectReq(HID_PSM_INTERRUPT, hd_cb.device.addr)) == 0) {
|
||||
p_hcon->conn_state = HID_CONN_STATE_UNUSED;
|
||||
hidd_conn_disconnect();
|
||||
HIDD_TRACE_WARNING("%s: could not start L2CAP connection for INTR", __func__);
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_ERR_L2CAP_FAILED, NULL);
|
||||
return;
|
||||
} else {
|
||||
p_hcon->conn_state = HID_CONN_STATE_CONNECTING_INTR;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p_hcon->conn_flags |= HID_CONN_FLAGS_MY_INTR_CFG_DONE;
|
||||
}
|
||||
hidd_check_config_done();
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_l2cif_disconnect_ind
|
||||
*
|
||||
* Description Handler incoming L2CAP disconnection request
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void hidd_l2cif_disconnect_ind(uint16_t cid, bool ack_needed)
|
||||
{
|
||||
tHID_CONN *p_hcon;
|
||||
HIDD_TRACE_EVENT("%s: cid=%04x ack_needed=%d", __func__, cid, ack_needed);
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
|
||||
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
|
||||
return;
|
||||
}
|
||||
if (ack_needed)
|
||||
L2CA_DisconnectRsp(cid);
|
||||
if (cid == p_hcon->ctrl_cid) {
|
||||
p_hcon->ctrl_cid = 0;
|
||||
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_CTRL;
|
||||
} else {
|
||||
p_hcon->intr_cid = 0;
|
||||
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_INTR;
|
||||
}
|
||||
if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0)) {
|
||||
HIDD_TRACE_EVENT("%s: INTR and CTRL disconnected", __func__);
|
||||
// clean any outstanding data on intr
|
||||
if (hd_cb.pending_data) {
|
||||
osi_free(hd_cb.pending_data);
|
||||
hd_cb.pending_data = NULL;
|
||||
}
|
||||
hd_cb.device.state = HIDD_DEV_NO_CONN;
|
||||
p_hcon->conn_state = HID_CONN_STATE_UNUSED;
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, p_hcon->disc_reason, NULL);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_l2cif_disconnect_cfm
|
||||
*
|
||||
* Description Handles L2CAP disconection response
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void hidd_l2cif_disconnect_cfm(uint16_t cid, uint16_t result)
|
||||
{
|
||||
tHID_CONN *p_hcon;
|
||||
HIDD_TRACE_EVENT("%s: cid=%04x result=%d", __func__, cid, result);
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
|
||||
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
|
||||
return;
|
||||
}
|
||||
if (cid == p_hcon->ctrl_cid) {
|
||||
p_hcon->ctrl_cid = 0;
|
||||
} else {
|
||||
p_hcon->intr_cid = 0;
|
||||
// now disconnect CTRL
|
||||
L2CA_DisconnectReq(p_hcon->ctrl_cid);
|
||||
}
|
||||
if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0)) {
|
||||
HIDD_TRACE_EVENT("%s: INTR and CTRL disconnected", __func__);
|
||||
hd_cb.device.state = HIDD_DEV_NO_CONN;
|
||||
p_hcon->conn_state = HID_CONN_STATE_UNUSED;
|
||||
if (hd_cb.pending_vc_unplug) {
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_VC_UNPLUG, p_hcon->disc_reason, NULL);
|
||||
hd_cb.pending_vc_unplug = FALSE;
|
||||
} else {
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, p_hcon->disc_reason, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_l2cif_cong_ind
|
||||
*
|
||||
* Description Handles L2CAP congestion status event
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void hidd_l2cif_cong_ind(uint16_t cid, bool congested)
|
||||
{
|
||||
tHID_CONN *p_hcon;
|
||||
HIDD_TRACE_EVENT("%s: cid=%04x congested=%d", __func__, cid, congested);
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
|
||||
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
|
||||
return;
|
||||
}
|
||||
if (congested) {
|
||||
p_hcon->conn_flags |= HID_CONN_FLAGS_CONGESTED;
|
||||
} else {
|
||||
p_hcon->conn_flags &= ~HID_CONN_FLAGS_CONGESTED;
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_l2cif_data_ind
|
||||
*
|
||||
* Description Handler incoming data on L2CAP channel
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void hidd_l2cif_data_ind(uint16_t cid, BT_HDR *p_msg)
|
||||
{
|
||||
tHID_CONN *p_hcon;
|
||||
uint8_t *p_data = (uint8_t *)(p_msg + 1) + p_msg->offset;
|
||||
uint8_t msg_type, param;
|
||||
bool err = FALSE;
|
||||
HIDD_TRACE_EVENT("%s: cid=%04x", __func__, cid);
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
|
||||
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
|
||||
osi_free(p_msg);
|
||||
return;
|
||||
}
|
||||
msg_type = HID_GET_TRANS_FROM_HDR(*p_data);
|
||||
param = HID_GET_PARAM_FROM_HDR(*p_data);
|
||||
if (msg_type == HID_TRANS_DATA && cid == p_hcon->intr_cid) {
|
||||
// skip HID header
|
||||
p_msg->offset++;
|
||||
p_msg->len--;
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_INTR_DATA, 0, p_msg);
|
||||
return;
|
||||
}
|
||||
switch (msg_type) {
|
||||
case HID_TRANS_GET_REPORT:
|
||||
// at this stage we don't know if Report Id shall be included in request
|
||||
// so we pass complete packet in callback and let other code analyze this
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_GET_REPORT, !!(param & HID_PAR_GET_REP_BUFSIZE_FOLLOWS), p_msg);
|
||||
break;
|
||||
case HID_TRANS_SET_REPORT:
|
||||
// as above
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_SET_REPORT, 0, p_msg);
|
||||
break;
|
||||
case HID_TRANS_GET_IDLE:
|
||||
hidd_conn_send_data(HID_CHANNEL_CTRL, HID_TRANS_DATA, HID_PAR_REP_TYPE_OTHER, hd_cb.device.idle_time, 0, NULL);
|
||||
osi_free(p_msg);
|
||||
break;
|
||||
case HID_TRANS_SET_IDLE:
|
||||
if (p_msg->len != 2) {
|
||||
HIDD_TRACE_ERROR("%s: invalid len (%d) set idle request received", __func__, p_msg->len);
|
||||
err = TRUE;
|
||||
} else {
|
||||
hd_cb.device.idle_time = p_data[1];
|
||||
HIDD_TRACE_DEBUG("%s: idle_time = %d", __func__, hd_cb.device.idle_time);
|
||||
if (hd_cb.device.idle_time) {
|
||||
HIDD_TRACE_WARNING("%s: idle_time of %d ms not supported by HID Device", __func__,
|
||||
(hd_cb.device.idle_time * 4));
|
||||
err = TRUE;
|
||||
}
|
||||
}
|
||||
if (!err) {
|
||||
hidd_conn_send_data(0, HID_TRANS_HANDSHAKE, HID_PAR_HANDSHAKE_RSP_SUCCESS, 0, 0, NULL);
|
||||
} else {
|
||||
hidd_conn_send_data(0, HID_TRANS_HANDSHAKE, HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM, 0, 0, NULL);
|
||||
}
|
||||
osi_free(p_msg);
|
||||
break;
|
||||
case HID_TRANS_GET_PROTOCOL:
|
||||
hidd_conn_send_data(HID_CHANNEL_CTRL, HID_TRANS_DATA, HID_PAR_REP_TYPE_OTHER, !hd_cb.device.boot_mode, 0, NULL);
|
||||
osi_free(p_msg);
|
||||
break;
|
||||
case HID_TRANS_SET_PROTOCOL:
|
||||
hd_cb.device.boot_mode = !(param & HID_PAR_PROTOCOL_MASK);
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_SET_PROTOCOL, param & HID_PAR_PROTOCOL_MASK, NULL);
|
||||
hidd_conn_send_data(0, HID_TRANS_HANDSHAKE, HID_PAR_HANDSHAKE_RSP_SUCCESS, 0, 0, NULL);
|
||||
osi_free(p_msg);
|
||||
break;
|
||||
case HID_TRANS_CONTROL:
|
||||
switch (param) {
|
||||
case HID_PAR_CONTROL_SUSPEND:
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_SUSPEND, 0, NULL);
|
||||
break;
|
||||
case HID_PAR_CONTROL_EXIT_SUSPEND:
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_EXIT_SUSPEND, 0, NULL);
|
||||
break;
|
||||
case HID_PAR_CONTROL_VIRTUAL_CABLE_UNPLUG:
|
||||
hidd_conn_disconnect();
|
||||
// set flag so we can notify properly when disconnected
|
||||
hd_cb.pending_vc_unplug = TRUE;
|
||||
break;
|
||||
}
|
||||
osi_free(p_msg);
|
||||
break;
|
||||
case HID_TRANS_DATA:
|
||||
default:
|
||||
HIDD_TRACE_WARNING("%s: got unsupported msg (%d)", __func__, msg_type);
|
||||
hidd_conn_send_data(0, HID_TRANS_HANDSHAKE, HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ, 0, 0, NULL);
|
||||
osi_free(p_msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_conn_reg
|
||||
*
|
||||
* Description Registers L2CAP channels
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS hidd_conn_reg(void)
|
||||
{
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
memset(&hd_cb.l2cap_cfg, 0, sizeof(tL2CAP_CFG_INFO));
|
||||
hd_cb.l2cap_cfg.mtu_present = TRUE;
|
||||
hd_cb.l2cap_cfg.mtu = HID_DEV_MTU_SIZE;
|
||||
hd_cb.l2cap_cfg.flush_to_present = TRUE;
|
||||
hd_cb.l2cap_cfg.flush_to = HID_DEV_FLUSH_TO;
|
||||
memset(&hd_cb.l2cap_intr_cfg, 0, sizeof(tL2CAP_CFG_INFO));
|
||||
hd_cb.l2cap_intr_cfg.mtu_present = TRUE;
|
||||
hd_cb.l2cap_intr_cfg.mtu = HID_DEV_MTU_SIZE;
|
||||
hd_cb.l2cap_intr_cfg.flush_to_present = TRUE;
|
||||
hd_cb.l2cap_intr_cfg.flush_to = HID_DEV_FLUSH_TO;
|
||||
if (!L2CA_Register(HID_PSM_CONTROL, (tL2CAP_APPL_INFO *)&dev_reg_info)) {
|
||||
HIDD_TRACE_ERROR("HID Control (device) registration failed");
|
||||
return (HID_ERR_L2CAP_FAILED);
|
||||
}
|
||||
if (!L2CA_Register(HID_PSM_INTERRUPT, (tL2CAP_APPL_INFO *)&dev_reg_info)) {
|
||||
L2CA_Deregister(HID_PSM_CONTROL);
|
||||
HIDD_TRACE_ERROR("HID Interrupt (device) registration failed");
|
||||
return (HID_ERR_L2CAP_FAILED);
|
||||
}
|
||||
return (HID_SUCCESS);
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_conn_dereg
|
||||
*
|
||||
* Description Deregisters L2CAP channels
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void hidd_conn_dereg(void)
|
||||
{
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
L2CA_Deregister(HID_PSM_CONTROL);
|
||||
L2CA_Deregister(HID_PSM_INTERRUPT);
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_conn_initiate
|
||||
*
|
||||
* Description Initiates HID connection to plugged device
|
||||
*
|
||||
* Returns HID_SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS hidd_conn_initiate(void)
|
||||
{
|
||||
tHID_DEV_DEV_CTB *p_dev = &hd_cb.device;
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
if (!p_dev->in_use) {
|
||||
HIDD_TRACE_WARNING("%s: no virtual cable established", __func__);
|
||||
return (HID_ERR_NOT_REGISTERED);
|
||||
}
|
||||
if (p_dev->conn.conn_state != HID_CONN_STATE_UNUSED) {
|
||||
HIDD_TRACE_WARNING("%s: connection already in progress", __func__);
|
||||
return (HID_ERR_CONN_IN_PROCESS);
|
||||
}
|
||||
p_dev->conn.ctrl_cid = 0;
|
||||
p_dev->conn.intr_cid = 0;
|
||||
p_dev->conn.disc_reason = HID_L2CAP_CONN_FAIL;
|
||||
p_dev->conn.conn_flags = HID_CONN_FLAGS_IS_ORIG;
|
||||
BTM_SetOutService(p_dev->addr, BTM_SEC_SERVICE_HIDD_SEC_CTRL, HIDD_SEC_CHN);
|
||||
/* Check if L2CAP started the connection process */
|
||||
if ((p_dev->conn.ctrl_cid = L2CA_ConnectReq(HID_PSM_CONTROL, p_dev->addr)) == 0) {
|
||||
HIDD_TRACE_WARNING("%s: could not start L2CAP connection", __func__);
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_ERR_L2CAP_FAILED, NULL);
|
||||
} else {
|
||||
p_dev->conn.conn_state = HID_CONN_STATE_CONNECTING_CTRL;
|
||||
}
|
||||
return (HID_SUCCESS);
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_conn_disconnect
|
||||
*
|
||||
* Description Disconnects existing HID connection
|
||||
*
|
||||
* Returns HID_SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS hidd_conn_disconnect(void)
|
||||
{
|
||||
tHID_CONN *p_hcon;
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
// clean any outstanding data on intr
|
||||
if (hd_cb.pending_data) {
|
||||
osi_free(hd_cb.pending_data);
|
||||
hd_cb.pending_data = NULL;
|
||||
}
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if ((p_hcon->ctrl_cid != 0) || (p_hcon->intr_cid != 0)) {
|
||||
/* Set l2cap idle timeout to 0 (so ACL link is disconnected
|
||||
* immediately after last channel is closed) */
|
||||
L2CA_SetIdleTimeoutByBdAddr(hd_cb.device.addr, 0, BT_TRANSPORT_BR_EDR);
|
||||
if (p_hcon->intr_cid) {
|
||||
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_INTR;
|
||||
L2CA_DisconnectReq(p_hcon->intr_cid);
|
||||
} else if (p_hcon->ctrl_cid) {
|
||||
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_CTRL;
|
||||
L2CA_DisconnectReq(p_hcon->ctrl_cid);
|
||||
}
|
||||
} else {
|
||||
HIDD_TRACE_WARNING("%s: already disconnected", __func__);
|
||||
p_hcon->conn_state = HID_CONN_STATE_UNUSED;
|
||||
}
|
||||
return (HID_SUCCESS);
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_conn_send_data
|
||||
*
|
||||
* Description Sends data to host
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS hidd_conn_send_data(uint8_t channel, uint8_t msg_type, uint8_t param, uint8_t data, uint16_t len,
|
||||
uint8_t *p_data)
|
||||
{
|
||||
tHID_CONN *p_hcon;
|
||||
BT_HDR *p_buf;
|
||||
uint8_t *p_out;
|
||||
uint16_t cid;
|
||||
uint16_t buf_size;
|
||||
HIDD_TRACE_VERBOSE("%s: channel(%d), msg_type(%d), len(%d)", __func__, channel, msg_type, len);
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if (p_hcon->conn_flags & HID_CONN_FLAGS_CONGESTED) {
|
||||
return HID_ERR_CONGESTED;
|
||||
}
|
||||
switch (msg_type) {
|
||||
case HID_TRANS_HANDSHAKE:
|
||||
case HID_TRANS_CONTROL:
|
||||
cid = p_hcon->ctrl_cid;
|
||||
buf_size = HID_CONTROL_BUF_SIZE;
|
||||
break;
|
||||
case HID_TRANS_DATA:
|
||||
if (channel == HID_CHANNEL_CTRL) {
|
||||
cid = p_hcon->ctrl_cid;
|
||||
buf_size = HID_CONTROL_BUF_SIZE;
|
||||
} else {
|
||||
cid = p_hcon->intr_cid;
|
||||
buf_size = HID_INTERRUPT_BUF_SIZE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return (HID_ERR_INVALID_PARAM);
|
||||
}
|
||||
p_buf = (BT_HDR *)osi_malloc(buf_size);
|
||||
if (p_buf == NULL)
|
||||
return (HID_ERR_NO_RESOURCES);
|
||||
p_buf->offset = L2CAP_MIN_OFFSET;
|
||||
p_out = (uint8_t *)(p_buf + 1) + p_buf->offset;
|
||||
*p_out = HID_BUILD_HDR(msg_type, param);
|
||||
p_out++;
|
||||
p_buf->len = 1; // start with header only
|
||||
// add report id prefix only if non-zero (which is reserved)
|
||||
if (msg_type == HID_TRANS_DATA && (data || param == HID_PAR_REP_TYPE_OTHER)) {
|
||||
*p_out = data; // report_id
|
||||
p_out++;
|
||||
p_buf->len++;
|
||||
}
|
||||
if (len > 0 && p_data != NULL) {
|
||||
memcpy(p_out, p_data, len);
|
||||
p_buf->len += len;
|
||||
}
|
||||
// check if connected
|
||||
if (hd_cb.device.state != HIDD_DEV_CONNECTED) {
|
||||
// for DATA on intr we hold transfer and try to reconnect
|
||||
if (msg_type == HID_TRANS_DATA && cid == p_hcon->intr_cid) {
|
||||
// drop previous data, we do not queue it for now
|
||||
if (hd_cb.pending_data) {
|
||||
osi_free(hd_cb.pending_data);
|
||||
}
|
||||
hd_cb.pending_data = p_buf;
|
||||
if (hd_cb.device.conn.conn_state == HID_CONN_STATE_UNUSED) {
|
||||
hidd_conn_initiate();
|
||||
}
|
||||
return HID_SUCCESS;
|
||||
}
|
||||
return HID_ERR_NO_CONNECTION;
|
||||
}
|
||||
#ifdef REPORT_TRANSFER_TIMESTAMP
|
||||
if (report_transfer) {
|
||||
HIDD_TRACE_ERROR("%s: report sent", __func__);
|
||||
}
|
||||
#endif
|
||||
HIDD_TRACE_VERBOSE("%s: report sent", __func__);
|
||||
if (!L2CA_DataWrite(cid, p_buf))
|
||||
return (HID_ERR_CONGESTED);
|
||||
return (HID_SUCCESS);
|
||||
}
|
||||
|
||||
#endif
|
@@ -31,7 +31,7 @@
|
||||
#include "stack/bt_types.h"
|
||||
#include "stack/hiddefs.h"
|
||||
#include "stack/hidh_api.h"
|
||||
#include "hidh_int.h"
|
||||
#include "hid_int.h"
|
||||
#include "stack/btm_api.h"
|
||||
#include "stack/btu.h"
|
||||
#include "btm_int.h"
|
||||
@@ -39,7 +39,9 @@
|
||||
#if (HID_HOST_INCLUDED == TRUE)
|
||||
|
||||
#if HID_DYNAMIC_MEMORY == FALSE
|
||||
tHID_HOST_CTB hh_cb;
|
||||
tHID_HOST_CTB hh_cb;
|
||||
#else
|
||||
tHID_HOST_CTB *hidh_cb_ptr = NULL;
|
||||
#endif
|
||||
|
||||
static void hidh_search_callback (UINT16 sdp_result);
|
||||
@@ -218,18 +220,46 @@ static void hidh_search_callback (UINT16 sdp_result)
|
||||
**
|
||||
** Description This function initializes the control block and trace variable
|
||||
**
|
||||
** Returns void
|
||||
** Returns tHID_STATUS
|
||||
**
|
||||
*******************************************************************************/
|
||||
void HID_HostInit (void)
|
||||
tHID_STATUS HID_HostInit (void)
|
||||
{
|
||||
#if (HID_DYNAMIC_MEMORY)
|
||||
if (!hidh_cb_ptr) {
|
||||
hidh_cb_ptr = (tHID_HOST_CTB *)osi_malloc(sizeof(tHID_HOST_CTB));
|
||||
if (!hidh_cb_ptr) {
|
||||
return HID_ERR_NO_RESOURCES;
|
||||
}
|
||||
}
|
||||
#endif /* #if (HID_DYNAMIC_MEMORY) */
|
||||
memset(&hh_cb, 0, sizeof(tHID_HOST_CTB));
|
||||
|
||||
#if defined(HID_INITIAL_TRACE_LEVEL)
|
||||
hh_cb.trace_level = HID_INITIAL_TRACE_LEVEL;
|
||||
#if defined(HIDH_INITIAL_TRACE_LEVEL)
|
||||
hh_cb.trace_level = HIDH_INITIAL_TRACE_LEVEL;
|
||||
#else
|
||||
hh_cb.trace_level = BT_TRACE_LEVEL_NONE;
|
||||
#endif
|
||||
return HID_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function HID_HostInit
|
||||
**
|
||||
** Description This function deinitializes the control block
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void HID_HostDeinit (void)
|
||||
{
|
||||
#if (HID_DYNAMIC_MEMORY)
|
||||
if (hidh_cb_ptr) {
|
||||
osi_free(hidh_cb_ptr);
|
||||
hidh_cb_ptr = NULL;
|
||||
}
|
||||
#endif /* #if (HID_DYNAMIC_MEMORY) */
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -362,6 +392,36 @@ tHID_STATUS HID_HostAddDev ( BD_ADDR addr, UINT16 attr_mask, UINT8 *handle )
|
||||
return (HID_SUCCESS);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function HID_HostGetDev
|
||||
**
|
||||
** Description This is called so HID-host can find this device.
|
||||
**
|
||||
** Returns tHID_STATUS
|
||||
**
|
||||
*******************************************************************************/
|
||||
tHID_STATUS HID_HostGetDev(BD_ADDR addr, UINT8 *handle)
|
||||
{
|
||||
int i;
|
||||
/* Find an entry for this device in hh_cb.devices array */
|
||||
if (!hh_cb.reg_flag) {
|
||||
return (HID_ERR_NOT_REGISTERED);
|
||||
}
|
||||
|
||||
for (i = 0; i < HID_HOST_MAX_DEVICES; i++) {
|
||||
if ((hh_cb.devices[i].in_use) && (!memcmp(addr, hh_cb.devices[i].addr, BD_ADDR_LEN))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == HID_HOST_MAX_DEVICES) {
|
||||
*handle = 0xff;
|
||||
} else {
|
||||
*handle = i;
|
||||
}
|
||||
return (HID_SUCCESS);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
@@ -41,7 +41,7 @@
|
||||
#include "stack/hiddefs.h"
|
||||
|
||||
#include "stack/hidh_api.h"
|
||||
#include "hidh_int.h"
|
||||
#include "hid_int.h"
|
||||
#include "osi/osi.h"
|
||||
|
||||
#if (HID_HOST_INCLUDED == TRUE)
|
||||
@@ -132,15 +132,16 @@ tHID_STATUS hidh_conn_disconnect (UINT8 dhandle)
|
||||
HIDH_TRACE_EVENT ("HID-Host disconnect");
|
||||
|
||||
if ((p_hcon->ctrl_cid != 0) || (p_hcon->intr_cid != 0)) {
|
||||
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING;
|
||||
|
||||
/* Set l2cap idle timeout to 0 (so ACL link is disconnected
|
||||
* immediately after last channel is closed) */
|
||||
L2CA_SetIdleTimeoutByBdAddr(hh_cb.devices[dhandle].addr, 0, BT_TRANSPORT_BR_EDR);
|
||||
/* Disconnect both interrupt and control channels */
|
||||
if (p_hcon->intr_cid) {
|
||||
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_INTR;
|
||||
L2CA_DisconnectReq (p_hcon->intr_cid);
|
||||
} else if (p_hcon->ctrl_cid) {
|
||||
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_CTRL;
|
||||
L2CA_DisconnectReq (p_hcon->ctrl_cid);
|
||||
}
|
||||
} else {
|
||||
@@ -360,12 +361,12 @@ static void hidh_l2cif_connect_cfm (UINT16 l2cap_cid, UINT16 result)
|
||||
p_hcon = &hh_cb.devices[dhandle].conn;
|
||||
}
|
||||
|
||||
if ((p_hcon == NULL)
|
||||
|| (!(p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG))
|
||||
|| ((l2cap_cid == p_hcon->ctrl_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_CTRL))
|
||||
|| ((l2cap_cid == p_hcon->intr_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR)
|
||||
&& (p_hcon->conn_state != HID_CONN_STATE_DISCONNECTING))) {
|
||||
HIDH_TRACE_WARNING ("HID-Host Rcvd unexpected conn cnf, CID 0x%x ", l2cap_cid);
|
||||
if ((p_hcon == NULL) || (!(p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG)) ||
|
||||
((l2cap_cid == p_hcon->ctrl_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_CTRL) &&
|
||||
(p_hcon->conn_state != HID_CONN_STATE_DISCONNECTING_INTR)) ||
|
||||
((l2cap_cid == p_hcon->intr_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR) &&
|
||||
(p_hcon->conn_state != HID_CONN_STATE_DISCONNECTING_CTRL))) {
|
||||
HIDH_TRACE_WARNING("HID-Host Rcvd unexpected conn cnf, CID 0x%x ", l2cap_cid);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -592,12 +593,12 @@ static void hidh_l2cif_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed)
|
||||
|
||||
HIDH_TRACE_EVENT ("HID-Host Rcvd L2CAP disc, CID: 0x%x", l2cap_cid);
|
||||
|
||||
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING;
|
||||
|
||||
if (l2cap_cid == p_hcon->ctrl_cid) {
|
||||
p_hcon->ctrl_cid = 0;
|
||||
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_CTRL;
|
||||
} else {
|
||||
p_hcon->intr_cid = 0;
|
||||
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_INTR;
|
||||
}
|
||||
|
||||
if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0)) {
|
@@ -26,18 +26,21 @@
|
||||
#define HID_CONN_H
|
||||
|
||||
#include "common/bt_defs.h"
|
||||
#if (HID_HOST_INCLUDED == TRUE)
|
||||
|
||||
#if (BT_HID_INCLUDED == TRUE)
|
||||
|
||||
/* Define the HID Connection Block
|
||||
*/
|
||||
typedef struct hid_conn {
|
||||
#define HID_CONN_STATE_UNUSED (0)
|
||||
#define HID_CONN_STATE_CONNECTING_CTRL (1)
|
||||
#define HID_CONN_STATE_CONNECTING_INTR (2)
|
||||
#define HID_CONN_STATE_CONFIG (3)
|
||||
#define HID_CONN_STATE_CONNECTED (4)
|
||||
#define HID_CONN_STATE_DISCONNECTING (5)
|
||||
#define HID_CONN_STATE_SECURITY (6)
|
||||
#define HID_CONN_STATE_UNUSED (0)
|
||||
#define HID_CONN_STATE_CONNECTING_CTRL (1)
|
||||
#define HID_CONN_STATE_CONNECTING_INTR (2)
|
||||
#define HID_CONN_STATE_CONFIG (3)
|
||||
#define HID_CONN_STATE_CONNECTED (4)
|
||||
#define HID_CONN_STATE_DISCONNECTING (5)
|
||||
#define HID_CONN_STATE_SECURITY (6)
|
||||
#define HID_CONN_STATE_DISCONNECTING_CTRL (7)
|
||||
#define HID_CONN_STATE_DISCONNECTING_INTR (8)
|
||||
|
||||
UINT8 conn_state;
|
||||
|
||||
@@ -62,9 +65,8 @@ typedef struct hid_conn {
|
||||
|
||||
#define HID_SEC_CHN 1
|
||||
#define HID_NOSEC_CHN 2
|
||||
#define HIDD_SEC_CHN 3
|
||||
#define HIDD_NOSEC_CHN 4
|
||||
|
||||
#define HIDD_SEC_CHN 3
|
||||
#define HIDD_NOSEC_CHN 4
|
||||
|
||||
#endif ///HID_HOST_INCLUDED == TRUE
|
||||
#endif ///BT_HID_INCLUDED == TRUE
|
||||
#endif
|
@@ -1,5 +1,6 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
* Copyright (C) 2002-2012 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -15,26 +16,21 @@
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file contains HID HOST internal definitions
|
||||
* This file contains HID DEVICE internal definitions
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef HID_INT_H
|
||||
#define HID_INT_H
|
||||
|
||||
#ifndef HIDH_INT_H
|
||||
#define HIDH_INT_H
|
||||
|
||||
#include "stack/hidh_api.h"
|
||||
#include "hid_conn.h"
|
||||
#include "stack/l2c_api.h"
|
||||
#if (BT_HID_INCLUDED == TRUE)
|
||||
|
||||
#if (HID_HOST_INCLUDED == TRUE)
|
||||
|
||||
enum {
|
||||
HID_DEV_NO_CONN,
|
||||
HID_DEV_CONNECTED
|
||||
};
|
||||
#include "stack/hidh_api.h"
|
||||
enum { HID_DEV_NO_CONN, HID_DEV_CONNECTED };
|
||||
|
||||
typedef struct per_device_ctb {
|
||||
BOOLEAN in_use;
|
||||
@@ -70,17 +66,16 @@ extern void hidh_conn_dereg( void );
|
||||
extern tHID_STATUS hidh_conn_disconnect (UINT8 dhandle);
|
||||
extern tHID_STATUS hidh_conn_initiate (UINT8 dhandle);
|
||||
extern void hidh_proc_repage_timeout (TIMER_LIST_ENT *p_tle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
** Main Control Block
|
||||
*******************************************************************************/
|
||||
* Main Control Block
|
||||
******************************************************************************/
|
||||
|
||||
#if HID_DYNAMIC_MEMORY == FALSE
|
||||
extern tHID_HOST_CTB hh_cb;
|
||||
extern tHID_HOST_CTB hh_cb;
|
||||
#else
|
||||
extern tHID_HOST_CTB *hidh_cb_ptr;
|
||||
#define hh_cb (*hidh_cb_ptr)
|
||||
@@ -89,7 +84,60 @@ extern tHID_HOST_CTB *hidh_cb_ptr;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* HID_HOST_INCLUDED == TRUE */
|
||||
|
||||
#endif ///HID_HOST_INCLUDED == TRUE
|
||||
#if (HID_DEV_INCLUDED == TRUE)
|
||||
#include "stack/hidd_api.h"
|
||||
enum { HIDD_DEV_NO_CONN, HIDD_DEV_CONNECTED };
|
||||
|
||||
typedef struct device_ctb {
|
||||
bool in_use;
|
||||
BD_ADDR addr;
|
||||
uint8_t state;
|
||||
tHID_CONN conn;
|
||||
bool boot_mode;
|
||||
uint8_t idle_time;
|
||||
} tHID_DEV_DEV_CTB;
|
||||
|
||||
typedef struct dev_ctb {
|
||||
tHID_DEV_DEV_CTB device;
|
||||
tHID_DEV_HOST_CALLBACK *callback;
|
||||
tL2CAP_CFG_INFO l2cap_cfg;
|
||||
tL2CAP_CFG_INFO l2cap_intr_cfg;
|
||||
bool use_in_qos;
|
||||
FLOW_SPEC in_qos;
|
||||
bool reg_flag;
|
||||
uint8_t trace_level;
|
||||
bool allow_incoming;
|
||||
BT_HDR *pending_data;
|
||||
bool pending_vc_unplug;
|
||||
} tHID_DEV_CTB;
|
||||
|
||||
extern tHID_STATUS hidd_conn_reg(void);
|
||||
extern void hidd_conn_dereg(void);
|
||||
extern tHID_STATUS hidd_conn_initiate(void);
|
||||
extern tHID_STATUS hidd_conn_disconnect(void);
|
||||
extern tHID_STATUS hidd_conn_send_data(uint8_t channel, uint8_t msg_type, uint8_t param, uint8_t data, uint16_t len,
|
||||
uint8_t *p_data);
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
* Main Control Block
|
||||
******************************************************************************/
|
||||
|
||||
#if HID_DYNAMIC_MEMORY == FALSE
|
||||
extern tHID_DEV_CTB hd_cb;
|
||||
#else
|
||||
extern tHID_DEV_CTB *hidd_cb_ptr;
|
||||
#define hd_cb (*hidd_cb_ptr)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* HID_DEV_INCLUDED == TRUE */
|
||||
|
||||
#endif /* BT_HID_INCLUDED == TRUE */
|
||||
#endif /* HID_INT_H */
|
@@ -1252,9 +1252,12 @@ typedef UINT8 tBTM_LINK_KEY_TYPE;
|
||||
#define BTM_SEC_SERVICE_HDP_SNK 48
|
||||
#define BTM_SEC_SERVICE_HDP_SRC 49
|
||||
#define BTM_SEC_SERVICE_ATT 50
|
||||
#define BTM_SEC_SERVICE_HIDD_SEC_CTRL 51
|
||||
#define BTM_SEC_SERVICE_HIDD_NOSEC_CTRL 52
|
||||
#define BTM_SEC_SERVICE_HIDD_INTR 53
|
||||
|
||||
/* Update these as services are added */
|
||||
#define BTM_SEC_SERVICE_FIRST_EMPTY 51
|
||||
#define BTM_SEC_SERVICE_FIRST_EMPTY 54
|
||||
|
||||
#ifndef BTM_SEC_MAX_SERVICES
|
||||
#define BTM_SEC_MAX_SERVICES 65
|
||||
@@ -1915,11 +1918,11 @@ typedef UINT8 tBTM_CONTRL_STATE;
|
||||
/*****************************************************************************
|
||||
** EXTERNAL FUNCTION DECLARATIONS
|
||||
*****************************************************************************/
|
||||
/*
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
** DEVICE CONTROL and COMMON FUNCTIONS
|
||||
*****************************************************************************/
|
||||
@@ -4141,10 +4144,8 @@ tBTM_STATUS BTM_SetAfhChannels (AFH_CHANNELS channels, tBTM_CMPL_CB *p_afh_chann
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS BTM_BleSetChannels (BLE_CHANNELS channels, tBTM_CMPL_CB *p_ble_channels_cmpl_cback);
|
||||
|
||||
/*
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
#endif /* BTM_API_H */
|
||||
|
273
components/bt/host/bluedroid/stack/include/stack/hidd_api.h
Normal file
273
components/bt/host/bluedroid/stack/include/stack/hidd_api.h
Normal file
@@ -0,0 +1,273 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
* Copyright (C) 2002-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.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef HIDD_API_H
|
||||
#define HIDD_API_H
|
||||
#include "hiddefs.h"
|
||||
#include "sdp_api.h"
|
||||
|
||||
#if (HID_DEV_INCLUDED == TRUE)
|
||||
/*****************************************************************************
|
||||
* Type Definitions
|
||||
****************************************************************************/
|
||||
enum {
|
||||
HID_CHANNEL_INTR,
|
||||
HID_CHANNEL_CTRL
|
||||
};
|
||||
/*
|
||||
HID_DHOST_EVT_OPEN - connected to host device (CTRL and INTR), data = n/a
|
||||
HID_DHOST_EVT_CLOSE - disconnected from host device, data=reason
|
||||
HID_DHOST_EVT_GET_REPORT - got GET_REPORT from host
|
||||
HID_DHOST_EVT_SET_REPORT - got SET_REPORT from host
|
||||
HID_DHOST_EVT_SET_PROTOCOL - got SET_PROTOCOL from host
|
||||
*/
|
||||
|
||||
enum {
|
||||
HID_DHOST_EVT_OPEN,
|
||||
HID_DHOST_EVT_CLOSE,
|
||||
HID_DHOST_EVT_GET_REPORT,
|
||||
HID_DHOST_EVT_SET_REPORT,
|
||||
HID_DHOST_EVT_SET_PROTOCOL,
|
||||
HID_DHOST_EVT_INTR_DATA,
|
||||
HID_DHOST_EVT_VC_UNPLUG,
|
||||
HID_DHOST_EVT_SUSPEND,
|
||||
HID_DHOST_EVT_EXIT_SUSPEND,
|
||||
};
|
||||
|
||||
typedef void (tHID_DEV_HOST_CALLBACK)(BD_ADDR bd_addr, uint8_t event, uint32_t data, BT_HDR* p_buf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*****************************************************************************
|
||||
* External Function Declarations
|
||||
****************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevInit
|
||||
*
|
||||
* Description Initializes control block
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
extern tHID_STATUS HID_DevInit(void);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevInit
|
||||
*
|
||||
* Description Deinitializes control block
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void HID_DevDeinit(void);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevRegister
|
||||
*
|
||||
* Description Registers HID device with lower layers
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
extern tHID_STATUS HID_DevRegister(tHID_DEV_HOST_CALLBACK* host_cback);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevDeregister
|
||||
*
|
||||
* Description Deregisters HID device with lower layers
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
extern tHID_STATUS HID_DevDeregister(void);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevSetSecurityLevel
|
||||
*
|
||||
* Description Sets security level for HID device connections
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
extern tHID_STATUS HID_DevSetSecurityLevel(uint8_t sec_lvl);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevAddRecord
|
||||
*
|
||||
* Description Creates SDP record for HID device
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
extern tHID_STATUS HID_DevAddRecord(uint32_t handle, char* p_name,
|
||||
char* p_description, char* p_provider,
|
||||
uint16_t subclass, uint16_t desc_len,
|
||||
uint8_t* p_desc_data);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevSendReport
|
||||
*
|
||||
* Description Sends report
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
extern tHID_STATUS HID_DevSendReport(uint8_t channel, uint8_t type, uint8_t id,
|
||||
uint16_t len, uint8_t* p_data);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevVirtualCableUnplug
|
||||
*
|
||||
* Description Sends Virtual Cable Unplug
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
extern tHID_STATUS HID_DevVirtualCableUnplug(void);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevPlugDevice
|
||||
*
|
||||
* Description Establishes virtual cable to given host
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
extern tHID_STATUS HID_DevPlugDevice(BD_ADDR addr);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevUnplugDevice
|
||||
*
|
||||
* Description Unplugs virtual cable from given host
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
extern tHID_STATUS HID_DevUnplugDevice(BD_ADDR addr);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevConnect
|
||||
*
|
||||
* Description Connects to device
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
extern tHID_STATUS HID_DevConnect(void);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevDisconnect
|
||||
*
|
||||
* Description Disconnects from device
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
extern tHID_STATUS HID_DevDisconnect(void);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevSetIncomingPolicy
|
||||
*
|
||||
* Description Sets policy for incoming connections (allowed/disallowed)
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
extern tHID_STATUS HID_DevSetIncomingPolicy(bool allow);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevReportError
|
||||
*
|
||||
* Description Reports error for Set Report via HANDSHAKE
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
extern tHID_STATUS HID_DevReportError(uint8_t error);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevGetDevice
|
||||
*
|
||||
* Description Returns the BD Address of virtually cabled device
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
extern tHID_STATUS HID_DevGetDevice(BD_ADDR* addr);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevSetIncomingQos
|
||||
*
|
||||
* Description Sets Incoming QoS values for Interrupt L2CAP Channel
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
extern tHID_STATUS HID_DevSetIncomingQos(
|
||||
uint8_t service_type, uint32_t token_rate, uint32_t token_bucket_size,
|
||||
uint32_t peak_bandwidth, uint32_t latency, uint32_t delay_variation);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevSetOutgoingQos
|
||||
*
|
||||
* Description Sets Outgoing QoS values for Interrupt L2CAP Channel
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
extern tHID_STATUS HID_DevSetOutgoingQos(
|
||||
uint8_t service_type, uint32_t token_rate, uint32_t token_bucket_size,
|
||||
uint32_t peak_bandwidth, uint32_t latency, uint32_t delay_variation);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevSetTraceLevel
|
||||
*
|
||||
* Description This function sets the trace level for HID Dev. If called
|
||||
* with a value of 0xFF, it simply reads the current trace level.
|
||||
*
|
||||
* Returns the new (current) trace level
|
||||
*
|
||||
******************************************************************************/
|
||||
extern uint8_t HID_DevSetTraceLevel(uint8_t new_level);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif /* HIDD_API_H */
|
@@ -25,7 +25,8 @@
|
||||
#ifndef HIDDEFS_H
|
||||
#define HIDDEFS_H
|
||||
#include "common/bt_target.h"
|
||||
#if (HID_HOST_INCLUDED == TRUE)
|
||||
|
||||
#if (HID_HOST_INCLUDED == TRUE || HID_DEV_INCLUDED == TRUE)
|
||||
|
||||
#if (SDP_INCLUDED == TRUE)
|
||||
#include "stack/sdp_api.h"
|
||||
|
@@ -139,6 +139,17 @@ extern tHID_STATUS HID_HostDeregister(void);
|
||||
extern tHID_STATUS HID_HostAddDev (BD_ADDR addr, UINT16 attr_mask,
|
||||
UINT8 *handle );
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function HID_HostGetDev
|
||||
**
|
||||
** Description This is called so HID-host can find this device.
|
||||
**
|
||||
** Returns tHID_STATUS
|
||||
**
|
||||
*******************************************************************************/
|
||||
extern tHID_STATUS HID_HostGetDev(BD_ADDR addr, UINT8 *handle);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function HID_HostRemoveDev
|
||||
@@ -191,9 +202,18 @@ extern tHID_STATUS HID_HostCloseDev(UINT8 dev_handle );
|
||||
**
|
||||
** Description This function initializes the control block and trace variable
|
||||
**
|
||||
** Returns tHID_STATUS
|
||||
*******************************************************************************/
|
||||
extern tHID_STATUS HID_HostInit(void);
|
||||
|
||||
/*******************************************************************************
|
||||
** Function HID_HostDeinit
|
||||
**
|
||||
** Description This function deinitializes the control block
|
||||
**
|
||||
** Returns void
|
||||
*******************************************************************************/
|
||||
extern void HID_HostInit(void);
|
||||
extern void HID_HostDeinit(void);
|
||||
|
||||
/*******************************************************************************
|
||||
** Function HID_HostSetSecurityLevel
|
||||
|
@@ -10,7 +10,8 @@ if(CONFIG_BT_ENABLED)
|
||||
list(APPEND srcs
|
||||
"src/ble_hidd.c"
|
||||
"src/ble_hidh.c"
|
||||
"src/bt_hidh.c")
|
||||
"src/bt_hidh.c"
|
||||
"src/bt_hidd.c")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@@ -126,6 +126,21 @@ typedef enum {
|
||||
ESP_HID_COD_MIN_MAX
|
||||
} esp_hid_cod_min_t;
|
||||
|
||||
/* HID transaction Types */
|
||||
typedef enum {
|
||||
ESP_HID_TRANS_HANDSHAKE = 0,
|
||||
ESP_HID_TRANS_CONTROL = 1,
|
||||
ESP_HID_TRANS_GET_REPORT = 4,
|
||||
ESP_HID_TRANS_SET_REPORT = 5,
|
||||
ESP_HID_TRANS_GET_PROTOCOL = 6,
|
||||
ESP_HID_TRANS_SET_PROTOCOL = 7,
|
||||
ESP_HID_TRANS_GET_IDLE = 8,
|
||||
ESP_HID_TRANS_SET_IDLE = 9,
|
||||
ESP_HID_TRANS_DATA = 10,
|
||||
ESP_HID_TRANS_DATAC = 11,
|
||||
ESP_HID_TRANS_MAX
|
||||
} esp_hid_trans_type_t;
|
||||
|
||||
/**
|
||||
* @brief HID report item structure
|
||||
*/
|
||||
|
@@ -53,11 +53,28 @@ typedef struct esp_hidd_dev_s esp_hidd_dev_t;
|
||||
* @brief HIDD callback parameters union
|
||||
*/
|
||||
typedef union {
|
||||
/**
|
||||
* @brief ESP_HIDD_START_EVENT
|
||||
* @note Used only for Classic Bluetooth.
|
||||
*/
|
||||
struct {
|
||||
esp_err_t status; /*!< HID device operation status */
|
||||
} start; /*!< HID callback param of ESP_HIDD_START_EVENT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_STOP_EVENT
|
||||
* @note Used only for Classic Bluetooth.
|
||||
*/
|
||||
struct {
|
||||
esp_err_t status; /*!< HID device operation status */
|
||||
} stop; /*!< HID callback param of ESP_HIDD_STOP_EVENT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_CONNECT_EVENT
|
||||
*/
|
||||
struct {
|
||||
esp_hidd_dev_t *dev; /*!< HID device structure */
|
||||
esp_err_t status; /*!< HID device operation status, used only for Classic Bluetooth */
|
||||
} connect; /*!< HID callback param of ESP_HIDD_CONNECT_EVENT */
|
||||
|
||||
/**
|
||||
@@ -66,6 +83,7 @@ typedef union {
|
||||
struct {
|
||||
esp_hidd_dev_t *dev; /*!< HID device structure */
|
||||
int reason; /*!< Indicate the reason of disconnection */
|
||||
esp_err_t status; /*!< HID device operation status, used only for Classic Bluetooth */
|
||||
} disconnect; /*!< HID callback param of ESP_HIDD_DISCONNECT_EVENT */
|
||||
|
||||
/**
|
||||
@@ -90,6 +108,8 @@ typedef union {
|
||||
uint16_t length; /*!< data length */
|
||||
uint8_t *data; /*!< The pointer to the data */
|
||||
uint8_t map_index; /*!< HID config report map index */
|
||||
uint8_t trans_type; /*!< HID device feature transaction type, used only for Classic Bluetooth */
|
||||
uint8_t report_type; /*!< HID device feature report type, used only for Classic Bluetooth */
|
||||
} feature; /*!< HID callback param of ESP_HIDD_FEATURE_EVENT */
|
||||
|
||||
/**
|
||||
|
@@ -42,6 +42,8 @@ typedef enum {
|
||||
ESP_HIDH_INPUT_EVENT, /*!< Received HID device INPUT report */
|
||||
ESP_HIDH_FEATURE_EVENT, /*!< Received HID device FEATURE report */
|
||||
ESP_HIDH_CLOSE_EVENT, /*!< HID device closed */
|
||||
ESP_HIDH_START_EVENT, /*!< HID host stack started, used only for Classic Bluetooth */
|
||||
ESP_HIDH_STOP_EVENT, /*!< HID host stack stopped, used only for Classic Bluetooth */
|
||||
ESP_HIDH_MAX_EVENT, /*!< HID events end marker */
|
||||
} esp_hidh_event_t;
|
||||
|
||||
@@ -49,11 +51,28 @@ typedef enum {
|
||||
* @brief HIDH callback parameters union
|
||||
*/
|
||||
typedef union {
|
||||
/**
|
||||
* @brief ESP_HIDH_START_EVENT
|
||||
* @note Used only for Classic Bluetooth.
|
||||
*/
|
||||
struct {
|
||||
esp_err_t status; /*!< HID host operation status */
|
||||
} start; /*!< HID callback param of ESP_HIDH_START_EVENT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_STOP_EVENT
|
||||
* @note Used only for Classic Bluetooth.
|
||||
*/
|
||||
struct {
|
||||
esp_err_t status; /*!< HID host operation status */
|
||||
} stop; /*!< HID callback param of ESP_HIDH_STOP_EVENT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_OPEN_EVENT
|
||||
*/
|
||||
struct {
|
||||
esp_hidh_dev_t *dev; /*!< HID Remote bluetooth device */
|
||||
esp_err_t status; /*!< HID host operation status, used only for Classic Bluetooth */
|
||||
} open; /*!< HID callback param of ESP_HIDH_OPEN_EVENT */
|
||||
|
||||
/**
|
||||
@@ -62,6 +81,7 @@ typedef union {
|
||||
struct {
|
||||
esp_hidh_dev_t *dev; /*!< HID Remote bluetooth device. */
|
||||
int reason; /*!< Reason why the connection was closed. BLE Only */
|
||||
esp_err_t status; /*!< HID host operation status, used only for Classic Bluetooth */
|
||||
} close; /*!< HID callback param of ESP_HIDH_CLOSE_EVENT */
|
||||
|
||||
/**
|
||||
@@ -70,6 +90,7 @@ typedef union {
|
||||
struct {
|
||||
esp_hidh_dev_t *dev; /*!< HID Remote bluetooth device */
|
||||
uint8_t level; /*!< Battery Level (0-100%) */
|
||||
esp_err_t status; /*!< HID host operation status */
|
||||
} battery; /*!< HID callback param of ESP_HIDH_BATTERY_EVENT */
|
||||
|
||||
/**
|
||||
@@ -80,7 +101,7 @@ typedef union {
|
||||
esp_hid_usage_t usage; /*!< HID report usage */
|
||||
uint16_t report_id; /*!< HID report index */
|
||||
uint16_t length; /*!< HID data length */
|
||||
uint8_t *data; /*!< The pointer to the HID data */
|
||||
uint8_t *data; /*!< The pointer to the HID data */
|
||||
uint8_t map_index; /*!< HID report map index */
|
||||
} input; /*!< HID callback param of ESP_HIDH_INPUT_EVENT */
|
||||
|
||||
@@ -92,8 +113,10 @@ typedef union {
|
||||
esp_hid_usage_t usage; /*!< HID report usage */
|
||||
uint16_t report_id; /*!< HID report index */
|
||||
uint16_t length; /*!< HID data length */
|
||||
uint8_t *data; /*!< The pointer to the HID data */
|
||||
uint8_t *data; /*!< The pointer to the HID data */
|
||||
uint8_t map_index; /*!< HID report map index */
|
||||
esp_err_t status; /*!< HID host operation status, used only for Classic Bluetooth */
|
||||
esp_hid_trans_type_t trans_type; /*!< HID host feature transaction type, used only for Classic Bluetooth */
|
||||
} feature; /*!< HID callback param of ESP_HIDH_FEATURE_EVENT */
|
||||
|
||||
} esp_hidh_event_data_t;
|
||||
@@ -101,6 +124,7 @@ typedef union {
|
||||
typedef struct {
|
||||
esp_event_handler_t callback;
|
||||
uint16_t event_stack_size;
|
||||
void *callback_arg;
|
||||
} esp_hidh_config_t;
|
||||
|
||||
/**
|
||||
@@ -136,6 +160,14 @@ esp_err_t esp_hidh_dev_close(esp_hidh_dev_t *dev);
|
||||
*/
|
||||
esp_err_t esp_hidh_dev_free(esp_hidh_dev_t *dev);
|
||||
|
||||
/**
|
||||
* @brief Check if the device still exists.
|
||||
* @param dev : pointer to the device
|
||||
*
|
||||
* @return: true if exists
|
||||
*/
|
||||
bool esp_hidh_dev_exists(esp_hidh_dev_t *dev);
|
||||
|
||||
/**
|
||||
* @brief Send an OUTPUT report to the device
|
||||
* @param dev : pointer to the device
|
||||
@@ -173,6 +205,79 @@ esp_err_t esp_hidh_dev_feature_set(esp_hidh_dev_t *dev, size_t map_index, size_t
|
||||
*/
|
||||
esp_err_t esp_hidh_dev_feature_get(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, size_t max_len, uint8_t *data, size_t *length);
|
||||
|
||||
/**
|
||||
* @brief Set_Report command.
|
||||
* @note For now, this function used only for Classic Bluetooth.
|
||||
*
|
||||
* @param dev : pointer to the device
|
||||
* @param map_index : index of the device report map
|
||||
* @param report_id : id of the HID FEATURE report
|
||||
* @param report_type : report type, defines in `esp_hid_common.h`
|
||||
* @param data : pointer to the data to send
|
||||
* @param length : length of the data to send
|
||||
*
|
||||
* @return: ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_hidh_dev_set_report(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type,
|
||||
uint8_t *data, size_t length);
|
||||
|
||||
/**
|
||||
* @brief Get_Report command.
|
||||
* @note For now, this function used only for Classic Bluetooth.
|
||||
*
|
||||
* @param dev : pointer to the device
|
||||
* @param map_index : index of the device report map
|
||||
* @param report_id : id of the HID FEATURE report
|
||||
* @param report_type : report type, defines in `esp_hid_common.h`
|
||||
* @param max_len : size of the buffer that will hold the data
|
||||
*
|
||||
* @return: ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_hidh_dev_get_report(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type,
|
||||
size_t max_len);
|
||||
|
||||
/**
|
||||
* @brief Get_Idle Command.
|
||||
* @note For now, this function used only for Classic Bluetooth.
|
||||
*
|
||||
* @param dev : pointer to the device
|
||||
*
|
||||
* @return: ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_hidh_dev_get_idle(esp_hidh_dev_t *dev);
|
||||
|
||||
/**
|
||||
* @brief Set_Idle Command.
|
||||
* @note For now, this function used only for Classic Bluetooth.
|
||||
*
|
||||
* @param dev : pointer to the device
|
||||
* @param idle_time : idle_time
|
||||
*
|
||||
* @return: ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_hidh_dev_set_idle(esp_hidh_dev_t *dev, uint8_t idle_time);
|
||||
|
||||
/**
|
||||
* @brief Get_Protocol Command.
|
||||
* @note For now, this function used only for Classic Bluetooth.
|
||||
*
|
||||
* @param dev : pointer to the device
|
||||
*
|
||||
* @return: ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_hidh_dev_get_protocol(esp_hidh_dev_t *dev);
|
||||
|
||||
/**
|
||||
* @brief Set_Protocol Command.
|
||||
* @note For now, this function used only for Classic Bluetooth.
|
||||
*
|
||||
* @param dev : pointer to the device
|
||||
* @param protocol_mode : protocol_mode
|
||||
*
|
||||
* @return: ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_hidh_dev_set_protocol(esp_hidh_dev_t *dev, uint8_t protocol_mode);
|
||||
|
||||
/**
|
||||
* @brief Dump the properties of HID Device to UART
|
||||
* @param dev : pointer to the HID Device
|
||||
|
33
components/esp_hid/private/bt_hidd.h
Normal file
33
components/esp_hid/private/bt_hidd.h
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_hidd.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_hid_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if CONFIG_BT_HID_DEVICE_ENABLED
|
||||
|
||||
esp_err_t esp_bt_hidd_dev_init(esp_hidd_dev_t *dev, const esp_hid_device_config_t *config, esp_event_handler_t callback);
|
||||
|
||||
#endif /* CONFIG_BT_HID_DEVICE_ENABLED */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@@ -1,367 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _ESP_BT_HH_API_H_
|
||||
#define _ESP_BT_HH_API_H_
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_bt_defs.h"
|
||||
|
||||
/*****************************************************************************
|
||||
** Constants and Type Definitions
|
||||
*****************************************************************************/
|
||||
#ifndef BTA_HH_DEBUG
|
||||
#define BTA_HH_DEBUG TRUE
|
||||
#endif
|
||||
|
||||
#ifndef BTA_HH_SSR_MAX_LATENCY_DEF
|
||||
#define BTA_HH_SSR_MAX_LATENCY_DEF 800 /* 500 ms*/
|
||||
#endif
|
||||
|
||||
#ifndef BTA_HH_SSR_MIN_TOUT_DEF
|
||||
#define BTA_HH_SSR_MIN_TOUT_DEF 2
|
||||
#endif
|
||||
|
||||
/* defined the minimum offset */
|
||||
#define BTA_HH_MIN_OFFSET L2CAP_MIN_OFFSET+1
|
||||
|
||||
/* HID_HOST_MAX_DEVICES can not exceed 15 for th design of BTA HH */
|
||||
#define BTA_HH_IDX_INVALID 0xff
|
||||
#define BTA_HH_MAX_KNOWN HID_HOST_MAX_DEVICES
|
||||
|
||||
/* Security Service Levels [bit mask] (BTM_SetSecurityLevel)
|
||||
** Encryption should not be used without authentication
|
||||
*/
|
||||
#define BTM_SEC_NONE 0x0000 /* Nothing required */
|
||||
#define BTM_SEC_IN_AUTHORIZE 0x0001 /* Inbound call requires authorization */
|
||||
#define BTM_SEC_IN_AUTHENTICATE 0x0002 /* Inbound call requires authentication */
|
||||
#define BTM_SEC_IN_ENCRYPT 0x0004 /* Inbound call requires encryption */
|
||||
#define BTM_SEC_OUT_AUTHORIZE 0x0008 /* Outbound call requires authorization */
|
||||
#define BTM_SEC_OUT_AUTHENTICATE 0x0010 /* Outbound call requires authentication */
|
||||
#define BTM_SEC_OUT_ENCRYPT 0x0020 /* Outbound call requires encryption */
|
||||
#define BTM_SEC_MODE4_LEVEL4 0x0040 /* Secure Connections Only Mode */
|
||||
#define BTM_SEC_FORCE_MASTER 0x0100 /* Need to switch connection to be master */
|
||||
#define BTM_SEC_ATTEMPT_MASTER 0x0200 /* Try to switch connection to be master */
|
||||
#define BTM_SEC_FORCE_SLAVE 0x0400 /* Need to switch connection to be master */
|
||||
#define BTM_SEC_ATTEMPT_SLAVE 0x0800 /* Try to switch connection to be slave */
|
||||
#define BTM_SEC_IN_MITM 0x1000 /* inbound Do man in the middle protection */
|
||||
#define BTM_SEC_OUT_MITM 0x2000 /* outbound Do man in the middle protection */
|
||||
#define BTM_SEC_IN_MIN_16_DIGIT_PIN 0x4000 /* enforce a minimum of 16 digit for sec mode 2 */
|
||||
|
||||
/* Security Setting Mask */
|
||||
#define BTA_SEC_NONE BTM_SEC_NONE /* No security. */
|
||||
#define BTA_SEC_AUTHORIZE (BTM_SEC_IN_AUTHORIZE ) /* Authorization required (only needed for out going connection )*/
|
||||
#define BTA_SEC_AUTHENTICATE (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_OUT_AUTHENTICATE) /* Authentication required. */
|
||||
#define BTA_SEC_ENCRYPT (BTM_SEC_IN_ENCRYPT | BTM_SEC_OUT_ENCRYPT) /* Encryption required. */
|
||||
#define BTA_SEC_MODE4_LEVEL4 (BTM_SEC_MODE4_LEVEL4) /* Mode 4 level 4 service, i.e. incoming/outgoing MITM and P-256 encryption */
|
||||
#define BTA_SEC_MITM (BTM_SEC_IN_MITM | BTM_SEC_OUT_MITM) /* Man-In-The_Middle protection */
|
||||
#define BTA_SEC_IN_16_DIGITS (BTM_SEC_IN_MIN_16_DIGIT_PIN) /* Min 16 digit for pin code */
|
||||
|
||||
#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
|
||||
/* GATT_MAX_PHY_CHANNEL can not exceed 14 for the design of BTA HH */
|
||||
#define BTA_HH_LE_MAX_KNOWN GATT_MAX_PHY_CHANNEL
|
||||
#define BTA_HH_MAX_DEVICE (HID_HOST_MAX_DEVICES + GATT_MAX_PHY_CHANNEL)
|
||||
#else
|
||||
#define BTA_HH_MAX_DEVICE HID_HOST_MAX_DEVICES
|
||||
#endif
|
||||
/* invalid device handle */
|
||||
#define BTA_HH_INVALID_HANDLE 0xff
|
||||
|
||||
#define BTA_HH_SSR_PARAM_INVALID HID_SSR_PARAM_INVALID
|
||||
|
||||
/* id DI is not existing in remote device, vendor_id in tBTA_HH_DEV_DSCP_INFO will be set to 0xffff */
|
||||
#define BTA_HH_VENDOR_ID_INVALID 0xffff
|
||||
|
||||
/* application ID(none-zero) for each type of device */
|
||||
#define BTA_HH_APP_ID_MI 1
|
||||
#define BTA_HH_APP_ID_KB 2
|
||||
#define BTA_HH_APP_ID_RMC 3
|
||||
#define BTA_HH_APP_ID_3DSG 4
|
||||
#define BTA_HH_APP_ID_JOY 5
|
||||
#define BTA_HH_APP_ID_GPAD 6
|
||||
#define BTA_HH_APP_ID_LE 0xff
|
||||
|
||||
/* type of devices, bit mask */
|
||||
#define BTA_HH_DEVT_UNKNOWN 0x00
|
||||
#define BTA_HH_DEVT_JOS 0x01 /* joy stick */
|
||||
#define BTA_HH_DEVT_GPD 0x02 /* game pad */
|
||||
#define BTA_HH_DEVT_RMC 0x03 /* remote control */
|
||||
#define BTA_HH_DEVT_SED 0x04 /* sensing device */
|
||||
#define BTA_HH_DEVT_DGT 0x05 /* Digitizer tablet */
|
||||
#define BTA_HH_DEVT_CDR 0x06 /* card reader */
|
||||
#define BTA_HH_DEVT_KBD 0x10 /* keyboard */
|
||||
#define BTA_HH_DEVT_MIC 0x20 /* pointing device */
|
||||
#define BTA_HH_DEVT_COM 0x30 /* Combo keyboard/pointing */
|
||||
#define BTA_HH_DEVT_OTHER 0x80
|
||||
typedef uint8_t tBTA_HH_DEVT;
|
||||
|
||||
|
||||
/* BTA HID Host callback events */
|
||||
#define BTA_HH_ENABLE_EVT 0 /* HH enabled */
|
||||
#define BTA_HH_DISABLE_EVT 1 /* HH disabled */
|
||||
#define BTA_HH_OPEN_EVT 2 /* connection opened */
|
||||
#define BTA_HH_CLOSE_EVT 3 /* connection closed */
|
||||
#define BTA_HH_GET_RPT_EVT 4 /* BTA_HhGetReport callback */
|
||||
#define BTA_HH_SET_RPT_EVT 5 /* BTA_HhSetReport callback */
|
||||
#define BTA_HH_GET_PROTO_EVT 6 /* BTA_GetProtoMode callback */
|
||||
#define BTA_HH_SET_PROTO_EVT 7 /* BTA_HhSetProtoMode callback */
|
||||
#define BTA_HH_GET_IDLE_EVT 8 /* BTA_HhGetIdle comes callback */
|
||||
#define BTA_HH_SET_IDLE_EVT 9 /* BTA_HhSetIdle finish callback */
|
||||
#define BTA_HH_GET_DSCP_EVT 10 /* Get report descriptor */
|
||||
#define BTA_HH_ADD_DEV_EVT 11 /* Add Device callback */
|
||||
#define BTA_HH_RMV_DEV_EVT 12 /* remove device finished */
|
||||
#define BTA_HH_VC_UNPLUG_EVT 13 /* virtually unplugged */
|
||||
#define BTA_HH_DATA_EVT 15
|
||||
#define BTA_HH_API_ERR_EVT 16 /* API error is caught */
|
||||
#define BTA_HH_UPDATE_SCPP_EVT 17 /* update scan paramter complete */
|
||||
typedef uint16_t tBTA_HH_EVT;
|
||||
|
||||
/* type of protocol mode */
|
||||
#define BTA_HH_PROTO_RPT_MODE (0x00)
|
||||
#define BTA_HH_PROTO_BOOT_MODE (0x01)
|
||||
#define BTA_HH_PROTO_UNKNOWN (0xff)
|
||||
typedef uint8_t tBTA_HH_PROTO_MODE;
|
||||
|
||||
#define BTA_HH_VIRTUAL_CABLE HID_VIRTUAL_CABLE
|
||||
#define BTA_HH_NORMALLY_CONNECTABLE HID_NORMALLY_CONNECTABLE
|
||||
#define BTA_HH_RECONN_INIT HID_RECONN_INIT
|
||||
#define BTA_HH_SDP_DISABLE HID_SDP_DISABLE
|
||||
#define BTA_HH_BATTERY_POWER HID_BATTERY_POWER
|
||||
#define BTA_HH_REMOTE_WAKE HID_REMOTE_WAKE
|
||||
#define BTA_HH_SUP_TOUT_AVLBL HID_SUP_TOUT_AVLBL
|
||||
#define BTA_HH_SEC_REQUIRED HID_SEC_REQUIRED
|
||||
typedef uint16_t tBTA_HH_ATTR_MASK;
|
||||
|
||||
enum {
|
||||
BTA_HH_OK,
|
||||
BTA_HH_HS_HID_NOT_READY, /* handshake error : device not ready */
|
||||
BTA_HH_HS_INVALID_RPT_ID, /* handshake error : invalid report ID */
|
||||
BTA_HH_HS_TRANS_NOT_SPT, /* handshake error : transaction not spt */
|
||||
BTA_HH_HS_INVALID_PARAM, /* handshake error : invalid paremter */
|
||||
BTA_HH_HS_ERROR, /* handshake error : unspecified HS error */
|
||||
BTA_HH_ERR, /* general BTA HH error */
|
||||
BTA_HH_ERR_SDP, /* SDP error */
|
||||
BTA_HH_ERR_PROTO, /* SET_Protocol error, only used in BTA_HH_OPEN_EVT callback */
|
||||
BTA_HH_ERR_DB_FULL, /* device database full error, used in BTA_HH_OPEN_EVT/BTA_HH_ADD_DEV_EVT */
|
||||
BTA_HH_ERR_TOD_UNSPT, /* type of device not supported */
|
||||
BTA_HH_ERR_NO_RES, /* out of system resources */
|
||||
BTA_HH_ERR_AUTH_FAILED, /* authentication fail */
|
||||
BTA_HH_ERR_HDL,
|
||||
BTA_HH_ERR_SEC
|
||||
};
|
||||
typedef uint8_t tBTA_HH_STATUS;
|
||||
|
||||
enum {
|
||||
BTA_HH_RPTT_RESRV, /* reserved */
|
||||
BTA_HH_RPTT_INPUT, /* input report */
|
||||
BTA_HH_RPTT_OUTPUT, /* output report */
|
||||
BTA_HH_RPTT_FEATURE /* feature report */
|
||||
};
|
||||
typedef uint8_t tBTA_HH_RPT_TYPE;
|
||||
|
||||
/* HID_CONTROL operation code used in BTA_HhSendCtrl()
|
||||
*/
|
||||
enum {
|
||||
BTA_HH_CTRL_NOP = 0, /* mapping from BTE */
|
||||
BTA_HH_CTRL_HARD_RESET, /* hard reset */
|
||||
BTA_HH_CTRL_SOFT_RESET, /* soft reset */
|
||||
BTA_HH_CTRL_SUSPEND, /* enter suspend */
|
||||
BTA_HH_CTRL_EXIT_SUSPEND, /* exit suspend */
|
||||
BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG /* virtual unplug */
|
||||
};
|
||||
typedef uint8_t tBTA_HH_TRANS_CTRL_TYPE;
|
||||
|
||||
|
||||
typedef struct desc_info {
|
||||
uint16_t dl_len;
|
||||
uint8_t *dsc_list;
|
||||
} tBTA_HH_DEV_DESCR;
|
||||
|
||||
/* Define the header of each buffer used in the Bluetooth stack. */
|
||||
typedef struct {
|
||||
uint16_t event;
|
||||
uint16_t len;
|
||||
uint16_t offset;
|
||||
uint16_t layer_specific;
|
||||
uint8_t data[];
|
||||
} BT_HDR;
|
||||
|
||||
#define BT_HDR_SIZE (sizeof (BT_HDR))
|
||||
|
||||
/* callback event data for BTA_HH_OPEN_EVT */
|
||||
typedef struct {
|
||||
esp_bd_addr_t bda; /* HID device bd address */
|
||||
tBTA_HH_STATUS status; /* operation status */
|
||||
uint8_t handle; /* device handle */
|
||||
|
||||
} tBTA_HH_CONN;
|
||||
|
||||
typedef tBTA_HH_CONN tBTA_HH_DEV_INFO;
|
||||
|
||||
/* callback event data */
|
||||
typedef struct {
|
||||
tBTA_HH_STATUS status; /* operation status */
|
||||
uint8_t handle; /* device handle */
|
||||
} tBTA_HH_CBDATA;
|
||||
|
||||
/* report descriptor information */
|
||||
typedef struct {
|
||||
uint16_t vendor_id; /* vendor ID */
|
||||
uint16_t product_id; /* product ID */
|
||||
uint16_t version; /* version */
|
||||
uint16_t ssr_max_latency;/* SSR max latency, BTA_HH_SSR_PARAM_INVALID if unknown */
|
||||
uint16_t ssr_min_tout; /* SSR min timeout, BTA_HH_SSR_PARAM_INVALID if unknown */
|
||||
uint8_t ctry_code; /*Country Code.*/
|
||||
tBTA_HH_DEV_DESCR descriptor;
|
||||
} tBTA_HH_DEV_DSCP_INFO;
|
||||
|
||||
/* handshake data */
|
||||
typedef struct {
|
||||
tBTA_HH_STATUS status; /* handshake status */
|
||||
uint8_t handle; /* device handle */
|
||||
union {
|
||||
tBTA_HH_PROTO_MODE proto_mode; /* GET_PROTO_EVT :protocol mode */
|
||||
BT_HDR *p_rpt_data;/* GET_RPT_EVT : report data */
|
||||
uint8_t idle_rate; /* GET_IDLE_EVT : idle rate */
|
||||
} rsp_data;
|
||||
|
||||
} tBTA_HH_HSDATA;
|
||||
|
||||
/* union of data associated with HD callback */
|
||||
typedef union {
|
||||
tBTA_HH_DEV_INFO dev_info; /* BTA_HH_ADD_DEV_EVT, BTA_HH_RMV_DEV_EVT */
|
||||
tBTA_HH_CONN conn; /* BTA_HH_OPEN_EVT */
|
||||
tBTA_HH_CBDATA dev_status; /* BTA_HH_CLOSE_EVT,
|
||||
BTA_HH_SET_PROTO_EVT
|
||||
BTA_HH_SET_RPT_EVT
|
||||
BTA_HH_SET_IDLE_EVT
|
||||
BTA_HH_UPDATE_SCPP_EVT */
|
||||
|
||||
tBTA_HH_STATUS status; /* BTA_HH_ENABLE_EVT */
|
||||
tBTA_HH_DEV_DSCP_INFO dscp_info; /* BTA_HH_GET_DSCP_EVT */
|
||||
tBTA_HH_HSDATA hs_data; /* GET_ transaction callback
|
||||
BTA_HH_GET_RPT_EVT
|
||||
BTA_HH_GET_PROTO_EVT
|
||||
BTA_HH_GET_IDLE_EVT */
|
||||
} tBTA_HH;
|
||||
|
||||
/* BTA HH callback function */
|
||||
typedef void (tBTA_HH_CBACK) (tBTA_HH_EVT event, tBTA_HH *p_data);
|
||||
|
||||
/*****************************************************************************
|
||||
** External Function Declarations
|
||||
*****************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* This function enable HID host and registers HID-Host with lower layers.*/
|
||||
extern void BTA_HhEnable(uint16_t sec_mask, tBTA_HH_CBACK *p_cback);
|
||||
|
||||
/* This function is called when the host is about power down. */
|
||||
extern void BTA_HhDisable(void);
|
||||
|
||||
/* This function is called to start an inquiry and read SDP record of responding devices; connect to a device if only one active HID device is found. */
|
||||
extern void BTA_HhOpen (esp_bd_addr_t dev_bda, uint8_t bd_type, tBTA_HH_PROTO_MODE mode, uint16_t sec_mask);
|
||||
|
||||
/* This function disconnects the device. */
|
||||
extern void BTA_HhClose(uint8_t dev_handle);
|
||||
|
||||
/* This function set the protocol mode at specified HID handle */
|
||||
extern void BTA_HhSetProtoMode(uint8_t handle, tBTA_HH_PROTO_MODE t_type);
|
||||
|
||||
/* This function get the protocol mode of a specified HID device. */
|
||||
extern void BTA_HhGetProtoMode(uint8_t dev_handle);
|
||||
|
||||
/* send SET_REPORT to device. */
|
||||
extern void BTA_HhSetReport(uint8_t dev_handle, tBTA_HH_RPT_TYPE r_type, BT_HDR *p_data);
|
||||
|
||||
/* Send a GET_REPORT to HID device. */
|
||||
extern void BTA_HhGetReport(uint8_t dev_handle, tBTA_HH_RPT_TYPE r_type, uint8_t rpt_id, uint16_t buf_size);
|
||||
|
||||
/* send SET_IDLE to device. */
|
||||
extern void BTA_HhSetIdle(uint8_t dev_handle, uint16_t idle_rate);
|
||||
|
||||
/* Send a GET_IDLE to HID device. */
|
||||
extern void BTA_HhGetIdle(uint8_t dev_handle);
|
||||
|
||||
/* Send HID_CONTROL request to a HID device. */
|
||||
extern void BTA_HhSendCtrl(uint8_t dev_handle, tBTA_HH_TRANS_CTRL_TYPE c_type);
|
||||
|
||||
/* Send DATA transaction to a HID device. */
|
||||
extern void BTA_HhSendData(uint8_t dev_handle, esp_bd_addr_t dev_bda, BT_HDR *p_buf);
|
||||
|
||||
/* Get report descriptor of the device */
|
||||
extern void BTA_HhGetDscpInfo(uint8_t dev_handle);
|
||||
|
||||
/* 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. */
|
||||
extern void BTA_HhAddDev(esp_bd_addr_t bda, tBTA_HH_ATTR_MASK attr_mask, uint8_t sub_class, uint8_t app_id, tBTA_HH_DEV_DSCP_INFO dscp_info);
|
||||
|
||||
/* Remove a device from the HID host devices list. */
|
||||
extern void BTA_HhRemoveDev(uint8_t dev_handle );
|
||||
|
||||
enum {
|
||||
BTA_HH_MOD_CTRL_KEY,
|
||||
BTA_HH_MOD_SHFT_KEY,
|
||||
BTA_HH_MOD_ALT_KEY,
|
||||
BTA_HH_MOD_GUI_KEY,
|
||||
BTA_HH_MOD_MAX_KEY
|
||||
};
|
||||
|
||||
/* parsed boot mode keyboard report */
|
||||
typedef struct {
|
||||
uint8_t this_char[6]; /* virtual key code */
|
||||
bool mod_key[BTA_HH_MOD_MAX_KEY];/* ctrl, shift, Alt, GUI */
|
||||
bool caps_lock; /* is caps locked */
|
||||
bool num_lock; /* is Num key pressed */
|
||||
} tBTA_HH_KEYBD_RPT;
|
||||
|
||||
/* parsed boot mode mouse report */
|
||||
typedef struct {
|
||||
uint8_t mouse_button; /* mouse button is clicked */
|
||||
int8_t delta_x; /* displacement x */
|
||||
int8_t delta_y; /* displacement y */
|
||||
} tBTA_HH_MICE_RPT;
|
||||
|
||||
enum {
|
||||
BTA_HH_KEYBD_RPT_ID = 1,
|
||||
BTA_HH_MOUSE_RPT_ID
|
||||
};
|
||||
typedef uint8_t tBTA_HH_BOOT_RPT_ID;
|
||||
|
||||
/* parsed Boot report */
|
||||
typedef struct {
|
||||
tBTA_HH_BOOT_RPT_ID dev_type; /* type of device report */
|
||||
union {
|
||||
tBTA_HH_KEYBD_RPT keybd_rpt; /* keyboard report */
|
||||
tBTA_HH_MICE_RPT mice_rpt; /* mouse report */
|
||||
} data_rpt;
|
||||
} tBTA_HH_BOOT_RPT;
|
||||
|
||||
/* This utility function parse a boot mode report. */
|
||||
extern void BTA_HhParseBootRpt(tBTA_HH_BOOT_RPT *p_data, uint8_t *p_report, uint16_t report_len);
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ESP_BT_HH_API_H_ */
|
@@ -22,12 +22,37 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
uint16_t notify_enable : 1;
|
||||
uint16_t indicate_enable : 1;
|
||||
uint16_t reserved : 14;
|
||||
};
|
||||
uint16_t value;
|
||||
} hidd_le_ccc_value_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t map_index; // the index of the report map
|
||||
uint8_t report_id; // the id of the report
|
||||
uint8_t report_type; // input, output or feature
|
||||
uint8_t protocol_mode; // boot or report
|
||||
esp_hid_usage_t usage; // generic, keyboard, mouse, joystick or gamepad
|
||||
uint16_t value_len; // maximum len of value by report map
|
||||
// used by gatts
|
||||
uint8_t index; // index of the value in the gatts attr db
|
||||
uint16_t handle; // obtained once all attributes are registered
|
||||
uint16_t ccc_handle; // obtained once all attributes are registered
|
||||
hidd_le_ccc_value_t ccc; // notifications and/or indications enabled
|
||||
} hidd_report_item_t;
|
||||
|
||||
struct esp_hidd_dev_s {
|
||||
void *dev;
|
||||
esp_hid_transport_t transport;
|
||||
|
||||
bool (*connected) (void *dev);
|
||||
esp_err_t (*deinit) (void *dev);
|
||||
esp_err_t (*disconnect) (void *dev);
|
||||
esp_err_t (*virtual_unplug) (void *dev);
|
||||
esp_err_t (*battery_set) (void *dev, uint8_t level);
|
||||
esp_err_t (*input_set) (void *dev, size_t map_index, size_t report_id, uint8_t *data, size_t length);
|
||||
esp_err_t (*feature_set) (void *dev, size_t map_index, size_t report_id, uint8_t *data, size_t length);
|
||||
@@ -37,6 +62,9 @@ struct esp_hidd_dev_s {
|
||||
|
||||
typedef struct esp_hidd_dev_s esp_hidd_dev_t;
|
||||
|
||||
void esp_hidd_process_event_data_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id,
|
||||
void *event_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_event.h"
|
||||
#include "sys/queue.h"
|
||||
#include "esp_timer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -54,10 +55,18 @@ struct esp_hidh_dev_s {
|
||||
|
||||
esp_hid_device_config_t config;
|
||||
esp_hid_usage_t usage;
|
||||
esp_hid_transport_t transport; //BT, BLE or USB
|
||||
bool connected; //we have all required data to communicate
|
||||
bool opened; //we opened the device manually, else the device connected to us
|
||||
int status; //status of the last command
|
||||
esp_hid_transport_t transport; //BT, BLE or USB
|
||||
esp_hid_trans_type_t trans_type; //indicate what transaction is going on, new transaction only be allowed after the previous done
|
||||
esp_timer_handle_t trans_timer; //transactiion timer
|
||||
uint8_t report_type; //Get_Report tansaction report_type
|
||||
uint8_t report_id; //Get_Report tansaction report_id
|
||||
uint8_t protocol_mode; //device protocol mode
|
||||
bool connected; //we have all required data to communicate
|
||||
bool opened; //we opened the device manually, else the device connected to us
|
||||
bool added; //If lower layer has added the device
|
||||
bool is_orig; //If host initiate the connection
|
||||
bool in_use; //If false, it will be deleted from the devices list.
|
||||
int status; //status of the last command
|
||||
|
||||
size_t reports_len;
|
||||
esp_hidh_dev_report_t *reports;
|
||||
@@ -66,10 +75,16 @@ struct esp_hidh_dev_s {
|
||||
size_t tmp_len;
|
||||
|
||||
xSemaphoreHandle semaphore;
|
||||
xSemaphoreHandle mutex;
|
||||
|
||||
esp_err_t (*close) (esp_hidh_dev_t *dev);
|
||||
esp_err_t (*report_write) (esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type, uint8_t *data, size_t len);
|
||||
esp_err_t (*report_read) (esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type, size_t max_length, uint8_t *value, size_t *value_len);
|
||||
esp_err_t (*set_report) (esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type, uint8_t *data, size_t len);
|
||||
esp_err_t (*get_idle) (esp_hidh_dev_t *dev);
|
||||
esp_err_t (*set_idle) (esp_hidh_dev_t *dev, uint8_t idle_time);
|
||||
esp_err_t (*get_protocol) (esp_hidh_dev_t *dev);
|
||||
esp_err_t (*set_protocol) (esp_hidh_dev_t *dev, uint8_t protocol_mode);
|
||||
void (*dump) (esp_hidh_dev_t *dev, FILE *fp);
|
||||
|
||||
#if CONFIG_BLUEDROID_ENABLED
|
||||
@@ -80,10 +95,10 @@ struct esp_hidh_dev_s {
|
||||
#if CONFIG_BT_HID_HOST_ENABLED
|
||||
struct {
|
||||
esp_bt_cod_t cod;
|
||||
int handle;
|
||||
uint8_t sub_class;
|
||||
uint8_t app_id;
|
||||
uint16_t attr_mask;
|
||||
uint8_t handle;
|
||||
// uint8_t sub_class;
|
||||
// uint8_t app_id;
|
||||
// uint16_t attr_mask;
|
||||
} bt;
|
||||
#endif /* CONFIG_BT_HID_HOST_ENABLED */
|
||||
#if CONFIG_GATTC_ENABLE
|
||||
@@ -105,15 +120,24 @@ esp_hidh_dev_t *esp_hidh_dev_malloc(void);
|
||||
|
||||
#if CONFIG_BLUEDROID_ENABLED
|
||||
esp_hidh_dev_t *esp_hidh_dev_get_by_bda(esp_bd_addr_t bda); //BT/BLE
|
||||
esp_hidh_dev_t *esp_hidh_dev_get_by_handle(int handle); //BT Only
|
||||
esp_hidh_dev_t *esp_hidh_dev_get_by_handle(uint8_t handle); //Classic Bluetooth Only
|
||||
esp_hidh_dev_t *esp_hidh_dev_get_by_conn_id(uint16_t conn_id); //BLE Only
|
||||
#endif /* CONFIG_BLUEDROID_ENABLED */
|
||||
|
||||
esp_hidh_dev_report_t *esp_hidh_dev_get_report_by_id_type_proto(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type, uint8_t protocol_mode);
|
||||
esp_hidh_dev_report_t *esp_hidh_dev_get_report_by_id_and_type(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type);
|
||||
esp_hidh_dev_report_t *esp_hidh_dev_get_input_report_by_len_and_proto(esp_hidh_dev_t *dev, size_t len, int protocol_mode);
|
||||
esp_hidh_dev_report_t *esp_hidh_dev_get_input_report_by_id_and_proto(esp_hidh_dev_t *dev, size_t report_id, int protocol_mode);
|
||||
esp_hidh_dev_report_t *esp_hidh_dev_get_input_report_by_proto_and_data(esp_hidh_dev_t *dev, int protocol_mode,
|
||||
size_t len, const uint8_t *data, bool *has_report_id);
|
||||
esp_hidh_dev_report_t *esp_hidh_dev_get_report_by_handle(esp_hidh_dev_t *dev, uint16_t handle); //BLE Only
|
||||
|
||||
|
||||
void esp_hidh_process_event_data_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id,
|
||||
void *event_data);
|
||||
void esp_hidh_dev_lock(esp_hidh_dev_t *dev);
|
||||
void esp_hidh_dev_unlock(esp_hidh_dev_t *dev);
|
||||
void esp_hidh_dev_wait(esp_hidh_dev_t *dev);
|
||||
void esp_hidh_dev_send(esp_hidh_dev_t *dev);
|
||||
esp_err_t esp_hidh_dev_free_inner(esp_hidh_dev_t *dev);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -38,6 +38,8 @@ static const char *TAG = "BLE_HIDD";
|
||||
/// Length of Boot Report Char. Value Maximal Length
|
||||
#define HIDD_LE_BOOT_REPORT_MAX_LEN (8)
|
||||
|
||||
typedef hidd_report_item_t hidd_le_report_item_t;
|
||||
|
||||
/*
|
||||
* UUIDs
|
||||
* */
|
||||
@@ -126,30 +128,6 @@ enum {
|
||||
HIDD_LE_IDX_NB,
|
||||
};
|
||||
|
||||
/* Client Characteristic Configuration value structure */
|
||||
typedef union {
|
||||
struct {
|
||||
uint16_t notify_enable: 1;
|
||||
uint16_t indicate_enable: 1;
|
||||
uint16_t reserved: 14;
|
||||
};
|
||||
uint16_t value;
|
||||
} hidd_le_ccc_value_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t map_index; //the index of the report map
|
||||
uint8_t report_id; //the id of the report
|
||||
uint8_t report_type; //input, output or feature
|
||||
uint8_t protocol_mode; //boot or report
|
||||
esp_hid_usage_t usage; //generic, keyboard, mouse, joystick or gamepad
|
||||
uint16_t value_len; //maximum len of value by report map
|
||||
//used by gatts
|
||||
uint8_t index; //index of the value in the gatts attr db
|
||||
uint16_t handle; //obtained once all attributes are registered
|
||||
uint16_t ccc_handle; //obtained once all attributes are registered
|
||||
hidd_le_ccc_value_t ccc; //notifications and/or indications enabled
|
||||
} hidd_le_report_item_t;
|
||||
|
||||
typedef struct {
|
||||
esp_gatt_if_t gatt_if;
|
||||
uint16_t handle;
|
||||
@@ -559,23 +537,43 @@ static void hid_event_handler(esp_ble_hidd_dev_t *dev, int device_index, esp_gat
|
||||
} else {
|
||||
ESP_LOGV(TAG, "HID WRITE %8s %7s %6s id: %d, len: %d", esp_hid_usage_str(map->usage), esp_hid_report_type_str(map->report_type), esp_hid_protocol_mode_str(map->protocol_mode), map->report_id, param->write.len);
|
||||
|
||||
esp_hidd_event_data_t cb_param = {0};
|
||||
esp_hidd_event_data_t *p_cb_param = NULL;
|
||||
size_t event_data_size = sizeof(esp_hidd_event_data_t);
|
||||
if (param->write.len > 0 && param->write.value) {
|
||||
event_data_size += param->write.len;
|
||||
}
|
||||
|
||||
if ((p_cb_param = (esp_hidd_event_data_t *)malloc(event_data_size)) == NULL) {
|
||||
ESP_LOGE(TAG, "%s malloc event data failed!", __func__);
|
||||
break;
|
||||
}
|
||||
memset(p_cb_param, 0, event_data_size);
|
||||
if (param->write.len > 0 && param->write.value) {
|
||||
memcpy(((uint8_t *)p_cb_param) + sizeof(esp_hidd_event_data_t), param->write.value,
|
||||
param->write.len);
|
||||
}
|
||||
|
||||
if (map->report_type == ESP_HID_REPORT_TYPE_OUTPUT) {
|
||||
cb_param.output.dev = dev->dev;
|
||||
cb_param.output.report_id = map->report_id;
|
||||
cb_param.output.usage = map->usage;
|
||||
cb_param.output.length = param->write.len;
|
||||
cb_param.output.data = param->write.value;
|
||||
cb_param.output.map_index = device_index;
|
||||
esp_event_post_to(dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_OUTPUT_EVENT, &cb_param, sizeof(esp_hidd_event_data_t), portMAX_DELAY);
|
||||
p_cb_param->output.dev = dev->dev;
|
||||
p_cb_param->output.report_id = map->report_id;
|
||||
p_cb_param->output.usage = map->usage;
|
||||
p_cb_param->output.length = param->write.len;
|
||||
p_cb_param->output.data = param->write.value; /* move the data pointer in the wrapper loop handler */
|
||||
p_cb_param->output.map_index = device_index;
|
||||
esp_event_post_to(dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_OUTPUT_EVENT, p_cb_param, event_data_size, portMAX_DELAY);
|
||||
} else {
|
||||
cb_param.feature.dev = dev->dev;
|
||||
cb_param.feature.report_id = map->report_id;
|
||||
cb_param.feature.usage = map->usage;
|
||||
cb_param.feature.length = param->write.len;
|
||||
cb_param.feature.data = param->write.value;
|
||||
cb_param.feature.map_index = device_index;
|
||||
esp_event_post_to(dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_FEATURE_EVENT, &cb_param, sizeof(esp_hidd_event_data_t), portMAX_DELAY);
|
||||
p_cb_param->feature.dev = dev->dev;
|
||||
p_cb_param->feature.report_id = map->report_id;
|
||||
p_cb_param->feature.usage = map->usage;
|
||||
p_cb_param->feature.length = param->write.len;
|
||||
p_cb_param->feature.data = param->write.value; /* move the data pointer in the wrapper loop handler */
|
||||
p_cb_param->feature.map_index = device_index;
|
||||
esp_event_post_to(dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_FEATURE_EVENT, p_cb_param, event_data_size, portMAX_DELAY);
|
||||
}
|
||||
|
||||
if (p_cb_param) {
|
||||
free(p_cb_param);
|
||||
p_cb_param = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -852,8 +850,14 @@ static esp_err_t esp_ble_hidd_dev_input_set(void *devp, size_t index, size_t id,
|
||||
if (!dev || s_dev != dev) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (!dev->connected) {
|
||||
ESP_LOGE(TAG, "Device Not Connected: %d", index);
|
||||
ESP_LOGE(TAG, "%s Device Not Connected", __func__);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (index >= dev->devices_len) {
|
||||
ESP_LOGE(TAG, "%s index out of range[0-%d]", __func__, dev->devices_len - 1);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
@@ -878,6 +882,17 @@ static esp_err_t esp_ble_hidd_dev_feature_set(void *devp, size_t index, size_t i
|
||||
if (!dev || s_dev != dev) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (!dev->connected) {
|
||||
ESP_LOGE(TAG, "%s Device Not Connected", __func__);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (index >= dev->devices_len) {
|
||||
ESP_LOGE(TAG, "%s index out of range[0-%d]", __func__, dev->devices_len - 1);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
hidd_le_report_item_t *p_rpt;
|
||||
if ((p_rpt = get_report_by_id_and_type(dev, id, ESP_HID_REPORT_TYPE_FEATURE)) != NULL) {
|
||||
ret = esp_ble_gatts_set_attr_value(p_rpt->handle, length, data);
|
||||
@@ -921,9 +936,11 @@ static esp_err_t esp_ble_hidd_dev_event_handler_unregister(void *devp, esp_event
|
||||
|
||||
static void ble_hidd_dev_free(void)
|
||||
{
|
||||
ble_hid_free_config(s_dev);
|
||||
free(s_dev);
|
||||
s_dev = NULL;
|
||||
if (s_dev) {
|
||||
ble_hid_free_config(s_dev);
|
||||
free(s_dev);
|
||||
s_dev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_hidd_dev_init(esp_hidd_dev_t *dev_p, const esp_hid_device_config_t *config, esp_event_handler_t callback)
|
||||
@@ -985,6 +1002,12 @@ esp_err_t esp_ble_hidd_dev_init(esp_hidd_dev_t *dev_p, const esp_hid_device_conf
|
||||
dev_p->event_handler_register = esp_ble_hidd_dev_event_handler_register;
|
||||
dev_p->event_handler_unregister = esp_ble_hidd_dev_event_handler_unregister;
|
||||
|
||||
ret = esp_ble_hidd_dev_event_handler_register(s_dev, esp_hidd_process_event_data_handler, ESP_EVENT_ANY_ID);
|
||||
if (ret != ESP_OK) {
|
||||
ble_hidd_dev_free();
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (callback != NULL) {
|
||||
ret = esp_ble_hidd_dev_event_handler_register(s_dev, callback, ESP_EVENT_ANY_ID);
|
||||
if (ret != ESP_OK) {
|
||||
|
@@ -475,22 +475,44 @@ void esp_hidh_gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gatt
|
||||
} else {
|
||||
report = esp_hidh_dev_get_report_by_handle(dev, p_data->notify.handle);
|
||||
if (report) {
|
||||
esp_hidh_event_data_t *p_param = NULL;
|
||||
size_t event_data_size = sizeof(esp_hidh_event_data_t);
|
||||
|
||||
if (p_data->notify.value_len && p_data->notify.value) {
|
||||
event_data_size += p_data->notify.value_len;
|
||||
}
|
||||
|
||||
if ((p_param = (esp_hidh_event_data_t *)malloc(event_data_size)) == NULL) {
|
||||
ESP_LOGE(TAG, "%s malloc event data failed!", __func__);
|
||||
break;
|
||||
}
|
||||
memset(p_param, 0, event_data_size);
|
||||
if (p_data->notify.value_len && p_data->notify.value) {
|
||||
memcpy(((uint8_t *)p_param) + sizeof(esp_hidh_event_data_t), p_data->notify.value,
|
||||
p_data->notify.value_len);
|
||||
}
|
||||
|
||||
if (report->report_type == ESP_HID_REPORT_TYPE_FEATURE) {
|
||||
p.feature.dev = dev;
|
||||
p.feature.map_index = report->map_index;
|
||||
p.feature.report_id = report->report_id;
|
||||
p.feature.usage = report->usage;
|
||||
p.feature.data = p_data->notify.value;
|
||||
p.feature.length = p_data->notify.value_len;
|
||||
esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_INPUT_EVENT, &p, sizeof(esp_hidh_event_data_t), portMAX_DELAY);
|
||||
p_param->feature.dev = dev;
|
||||
p_param->feature.map_index = report->map_index;
|
||||
p_param->feature.report_id = report->report_id;
|
||||
p_param->feature.usage = report->usage;
|
||||
p_param->feature.length = p_data->notify.value_len;
|
||||
p_param->feature.data = p_data->notify.value;
|
||||
esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_FEATURE_EVENT, p_param, event_data_size, portMAX_DELAY);
|
||||
} else {
|
||||
p.input.dev = dev;
|
||||
p.input.map_index = report->map_index;
|
||||
p.input.report_id = report->report_id;
|
||||
p.input.usage = report->usage;
|
||||
p.input.data = p_data->notify.value;
|
||||
p.input.length = p_data->notify.value_len;
|
||||
esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_INPUT_EVENT, &p, sizeof(esp_hidh_event_data_t), portMAX_DELAY);
|
||||
p_param->input.dev = dev;
|
||||
p_param->input.map_index = report->map_index;
|
||||
p_param->input.report_id = report->report_id;
|
||||
p_param->input.usage = report->usage;
|
||||
p_param->input.length = p_data->notify.value_len;
|
||||
p_param->input.data = p_data->notify.value;
|
||||
esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_INPUT_EVENT, p_param, event_data_size, portMAX_DELAY);
|
||||
}
|
||||
|
||||
if (p_param) {
|
||||
free(p_param);
|
||||
p_param = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -512,13 +534,16 @@ void esp_hidh_gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gatt
|
||||
} else {
|
||||
dev->connected = false;
|
||||
dev->status = p_data->close.status;
|
||||
// free the device in the wrapper event handler
|
||||
dev->in_use = false;
|
||||
if (event_loop_handle) {
|
||||
esp_hidh_event_data_t p = {0};
|
||||
p.close.dev = dev;
|
||||
p.close.reason = p_data->close.reason;
|
||||
p.close.status = ESP_OK;
|
||||
esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_CLOSE_EVENT, &p, sizeof(esp_hidh_event_data_t), portMAX_DELAY);
|
||||
} else {
|
||||
esp_hidh_dev_free(dev);
|
||||
esp_hidh_dev_free_inner(dev);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -620,22 +645,37 @@ esp_err_t esp_ble_hidh_init(const esp_hidh_config_t *config)
|
||||
.task_stack_size = config->event_stack_size > 0 ? config->event_stack_size : 2048,
|
||||
.task_core_id = tskNO_AFFINITY
|
||||
};
|
||||
ret = esp_event_loop_create(&event_task_args, &event_loop_handle);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_event_loop_create failed!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
do {
|
||||
ret = esp_event_loop_create(&event_task_args, &event_loop_handle);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s esp_event_loop_create failed!", __func__);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = esp_ble_gattc_app_register(0);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_ble_gattc_app_register failed!");
|
||||
break;
|
||||
}
|
||||
WAIT_CB();
|
||||
ret = esp_event_handler_register_with(event_loop_handle, ESP_HIDH_EVENTS, ESP_EVENT_ANY_ID,
|
||||
esp_hidh_process_event_data_handler, NULL);
|
||||
ret |= esp_event_handler_register_with(event_loop_handle, ESP_HIDH_EVENTS, ESP_EVENT_ANY_ID, config->callback,
|
||||
config->callback_arg);
|
||||
} while (0);
|
||||
|
||||
ret = esp_ble_gattc_app_register(0);
|
||||
if (ret != ESP_OK) {
|
||||
vSemaphoreDelete(s_ble_hidh_cb_semaphore);
|
||||
s_ble_hidh_cb_semaphore = NULL;
|
||||
return ret;
|
||||
if (event_loop_handle) {
|
||||
esp_event_loop_delete(event_loop_handle);
|
||||
}
|
||||
|
||||
if (s_ble_hidh_cb_semaphore) {
|
||||
vSemaphoreDelete(s_ble_hidh_cb_semaphore);
|
||||
s_ble_hidh_cb_semaphore = NULL;
|
||||
}
|
||||
}
|
||||
WAIT_CB();
|
||||
esp_event_handler_register_with(event_loop_handle, ESP_HIDH_EVENTS, ESP_EVENT_ANY_ID, config->callback, NULL);
|
||||
return ESP_OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_hidh_deinit(void)
|
||||
@@ -669,6 +709,7 @@ esp_hidh_dev_t *esp_ble_hidh_dev_open(esp_bd_addr_t bda, esp_ble_addr_type_t add
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dev->in_use = true;
|
||||
dev->transport = ESP_HID_TRANSPORT_BLE;
|
||||
memcpy(dev->bda, bda, sizeof(esp_bd_addr_t));
|
||||
dev->ble.address_type = address_type;
|
||||
@@ -676,7 +717,7 @@ esp_hidh_dev_t *esp_ble_hidh_dev_open(esp_bd_addr_t bda, esp_ble_addr_type_t add
|
||||
|
||||
ret = esp_ble_gattc_open(hid_gattc_if, dev->bda, dev->ble.address_type, true);
|
||||
if (ret) {
|
||||
esp_hidh_dev_free(dev);
|
||||
esp_hidh_dev_free_inner(dev);
|
||||
ESP_LOGE(TAG, "esp_ble_gattc_open failed: %d", ret);
|
||||
return NULL;
|
||||
}
|
||||
@@ -684,7 +725,7 @@ esp_hidh_dev_t *esp_ble_hidh_dev_open(esp_bd_addr_t bda, esp_ble_addr_type_t add
|
||||
if (dev->ble.conn_id < 0) {
|
||||
ret = dev->status;
|
||||
ESP_LOGE(TAG, "dev open failed! status: 0x%x", dev->status);
|
||||
esp_hidh_dev_free(dev);
|
||||
esp_hidh_dev_free_inner(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -697,6 +738,7 @@ esp_hidh_dev_t *esp_ble_hidh_dev_open(esp_bd_addr_t bda, esp_ble_addr_type_t add
|
||||
|
||||
if (event_loop_handle) {
|
||||
esp_hidh_event_data_t p = {0};
|
||||
p.open.status = ESP_OK;
|
||||
p.open.dev = dev;
|
||||
esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_OPEN_EVENT, &p, sizeof(esp_hidh_event_data_t), portMAX_DELAY);
|
||||
}
|
||||
|
879
components/esp_hid/src/bt_hidd.c
Normal file
879
components/esp_hid/src/bt_hidd.c
Normal file
@@ -0,0 +1,879 @@
|
||||
// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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 "bt_hidd.h"
|
||||
|
||||
#if CONFIG_BT_HID_DEVICE_ENABLED
|
||||
#include "esp_bt.h"
|
||||
#include "esp_bt_defs.h"
|
||||
#include "esp_bt_main.h"
|
||||
#include "esp_hidd.h"
|
||||
#include "esp_hidd_api.h"
|
||||
#include "esp_hidd_private.h"
|
||||
#include "esp_log.h"
|
||||
#include "osi/mutex.h"
|
||||
#include "string.h"
|
||||
|
||||
/* Values for service_type */
|
||||
#define NO_TRAFFIC 0
|
||||
#define BEST_EFFORT 1
|
||||
#define GUARANTEED 2
|
||||
|
||||
static const char *TAG = "BT_HIDD";
|
||||
|
||||
typedef struct {
|
||||
esp_hid_raw_report_map_t reports_map;
|
||||
uint8_t reports_len;
|
||||
hidd_report_item_t *reports;
|
||||
} hidd_dev_map_t;
|
||||
|
||||
typedef struct {
|
||||
esp_hidd_dev_t *dev;
|
||||
esp_event_loop_handle_t event_loop_handle;
|
||||
esp_hid_device_config_t config;
|
||||
uint16_t appearance;
|
||||
bool registered;
|
||||
bool connected;
|
||||
esp_bd_addr_t remote_bda;
|
||||
uint8_t bat_level; // 0 - 100 - battery percentage
|
||||
uint8_t control; // 0x00 suspend, 0x01 suspend off
|
||||
uint8_t protocol_mode; // 0x00 boot, 0x01 report
|
||||
hidd_dev_map_t *devices;
|
||||
uint8_t devices_len;
|
||||
} esp_bt_hidd_dev_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
osi_mutex_t mutex;
|
||||
esp_bt_hidd_dev_t *dev;
|
||||
esp_hidd_app_param_t app_param;
|
||||
esp_hidd_qos_param_t in_qos;
|
||||
esp_hidd_qos_param_t out_qos;
|
||||
} hidd_param_t;
|
||||
|
||||
static hidd_param_t s_hidd_param = {0};
|
||||
#define is_init() (s_hidd_param.dev != NULL)
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
static esp_err_t bt_hidd_get_status(esp_hidd_status_t status)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
switch (status) {
|
||||
case ESP_HIDD_SUCCESS:
|
||||
ret = ESP_OK;
|
||||
break;
|
||||
case ESP_HIDD_NO_RES:
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
break;
|
||||
default:
|
||||
ret = ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t bt_hidd_init_config(esp_bt_hidd_dev_t *dev, const esp_hid_device_config_t *config)
|
||||
{
|
||||
if (config->report_maps == NULL || config->report_maps_len == 0 || config->report_maps_len > 1) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
memset((uint8_t *)(&dev->config), 0, sizeof(esp_hid_device_config_t));
|
||||
dev->config.vendor_id = config->vendor_id;
|
||||
dev->config.product_id = config->product_id;
|
||||
dev->config.version = config->version;
|
||||
if (config->device_name != NULL) {
|
||||
dev->config.device_name = strdup(config->device_name);
|
||||
}
|
||||
if (config->manufacturer_name != NULL) {
|
||||
dev->config.manufacturer_name = strdup(config->manufacturer_name);
|
||||
}
|
||||
if (config->serial_number != NULL) {
|
||||
dev->config.serial_number = strdup(config->serial_number);
|
||||
}
|
||||
dev->appearance = ESP_HID_APPEARANCE_GENERIC;
|
||||
|
||||
if (config->report_maps_len) {
|
||||
dev->devices = (hidd_dev_map_t *)malloc(config->report_maps_len * sizeof(hidd_dev_map_t));
|
||||
if (dev->devices == NULL) {
|
||||
ESP_LOGE(TAG, "devices malloc(%d) failed", config->report_maps_len);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
memset(dev->devices, 0, config->report_maps_len * sizeof(hidd_dev_map_t));
|
||||
dev->devices_len = config->report_maps_len;
|
||||
for (uint8_t d = 0; d < dev->devices_len; d++) {
|
||||
|
||||
//raw report map
|
||||
uint8_t *map = (uint8_t *)malloc(config->report_maps[d].len);
|
||||
if (map == NULL) {
|
||||
ESP_LOGE(TAG, "report map malloc(%d) failed", config->report_maps[d].len);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
memcpy(map, config->report_maps[d].data, config->report_maps[d].len);
|
||||
|
||||
dev->devices[d].reports_map.data = (const uint8_t *)map;
|
||||
dev->devices[d].reports_map.len = config->report_maps[d].len;
|
||||
|
||||
esp_hid_report_map_t *rmap = esp_hid_parse_report_map(config->report_maps[d].data, config->report_maps[d].len);
|
||||
if (rmap == NULL) {
|
||||
ESP_LOGE(TAG, "hid_parse_report_map[%d](%d) failed", d, config->report_maps[d].len);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
dev->appearance = rmap->appearance;
|
||||
dev->devices[d].reports_len = rmap->reports_len;
|
||||
dev->devices[d].reports = (hidd_report_item_t *)malloc(rmap->reports_len * sizeof(hidd_report_item_t));
|
||||
if (dev->devices[d].reports == NULL) {
|
||||
ESP_LOGE(TAG, "reports malloc(%d) failed", rmap->reports_len * sizeof(hidd_report_item_t));
|
||||
free(rmap);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
for (uint8_t r = 0; r < rmap->reports_len; r++) {
|
||||
dev->devices[d].reports[r].map_index = d;
|
||||
dev->devices[d].reports[r].report_id = rmap->reports[r].report_id;
|
||||
dev->devices[d].reports[r].protocol_mode = rmap->reports[r].protocol_mode;
|
||||
dev->devices[d].reports[r].report_type = rmap->reports[r].report_type;
|
||||
dev->devices[d].reports[r].usage = rmap->reports[r].usage;
|
||||
dev->devices[d].reports[r].value_len = rmap->reports[r].value_len;
|
||||
}
|
||||
free(rmap->reports);
|
||||
free(rmap);
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static hidd_report_item_t *get_report_by_idx_id_type(esp_bt_hidd_dev_t *dev, size_t index, uint8_t id, uint8_t type)
|
||||
{
|
||||
hidd_report_item_t *rpt = NULL;
|
||||
if (index >= dev->devices_len) {
|
||||
ESP_LOGE(TAG, "index out of range[0-%d]", dev->devices_len - 1);
|
||||
return NULL;
|
||||
}
|
||||
for (uint8_t i = 0; i < dev->devices[index].reports_len; i++) {
|
||||
rpt = &dev->devices[index].reports[i];
|
||||
if (rpt->report_id == id && rpt->report_type == type && rpt->protocol_mode == dev->protocol_mode) {
|
||||
return rpt;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static hidd_report_item_t *get_report_by_id_and_type(esp_bt_hidd_dev_t *dev, uint8_t id, uint8_t type, uint8_t *index)
|
||||
{
|
||||
hidd_report_item_t *rpt = NULL;
|
||||
for (uint8_t idx = 0; idx < dev->devices_len; idx++) {
|
||||
for (uint8_t i = 0; i < dev->devices[idx].reports_len; i++) {
|
||||
rpt = &dev->devices[idx].reports[i];
|
||||
if (rpt->report_id == id && rpt->report_type == type && rpt->protocol_mode == dev->protocol_mode) {
|
||||
if (index) {
|
||||
*index = idx;
|
||||
}
|
||||
return rpt;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static esp_err_t bt_hid_free_config(esp_bt_hidd_dev_t *dev)
|
||||
{
|
||||
for (uint8_t d = 0; d < dev->devices_len; d++) {
|
||||
free((void *)dev->devices[d].reports);
|
||||
free((void *)dev->devices[d].reports_map.data);
|
||||
}
|
||||
|
||||
free((void *)dev->devices);
|
||||
free((void *)dev->config.device_name);
|
||||
free((void *)dev->config.manufacturer_name);
|
||||
free((void *)dev->config.serial_number);
|
||||
if (dev->event_loop_handle != NULL) {
|
||||
esp_event_loop_delete(dev->event_loop_handle);
|
||||
dev->event_loop_handle = NULL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void bt_hidd_dev_free(void)
|
||||
{
|
||||
if (s_hidd_param.dev) {
|
||||
osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
|
||||
bt_hid_free_config(s_hidd_param.dev);
|
||||
free(s_hidd_param.dev);
|
||||
s_hidd_param.dev = NULL;
|
||||
osi_mutex_unlock(&s_hidd_param.mutex);
|
||||
osi_mutex_free(&s_hidd_param.mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static void build_default_in_qos(esp_hidd_qos_param_t *in_qos, uint32_t value_len)
|
||||
{
|
||||
|
||||
if (value_len > 0) {
|
||||
in_qos->service_type = GUARANTEED;
|
||||
in_qos->token_rate = value_len * 100;
|
||||
in_qos->token_bucket_size = value_len;
|
||||
in_qos->peak_bandwidth = value_len * 100;
|
||||
in_qos->access_latency = 10;
|
||||
in_qos->delay_variation = 10;
|
||||
} else {
|
||||
memset(in_qos, 0, sizeof(esp_hidd_qos_param_t));
|
||||
}
|
||||
}
|
||||
|
||||
static void build_default_out_qos(esp_hidd_qos_param_t *out_qos, uint32_t value_len)
|
||||
{
|
||||
if (value_len > 0) {
|
||||
out_qos->service_type = GUARANTEED;
|
||||
out_qos->token_rate = value_len * 100;
|
||||
out_qos->token_bucket_size = value_len;
|
||||
out_qos->peak_bandwidth = value_len * 100;
|
||||
out_qos->access_latency = 10;
|
||||
out_qos->delay_variation = 10;
|
||||
} else {
|
||||
memset(out_qos, 0, sizeof(esp_hidd_qos_param_t));
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t get_subclass_by_appearance(uint16_t appearance)
|
||||
{
|
||||
uint8_t ret = ESP_HID_CLASS_UNKNOWN;
|
||||
switch (appearance) {
|
||||
case ESP_HID_APPEARANCE_KEYBOARD:
|
||||
ret = ESP_HID_CLASS_KBD;
|
||||
break;
|
||||
case ESP_HID_APPEARANCE_MOUSE:
|
||||
ret = ESP_HID_CLASS_MIC;
|
||||
break;
|
||||
case ESP_HID_APPEARANCE_JOYSTICK:
|
||||
ret = ESP_HID_CLASS_JOS;
|
||||
break;
|
||||
case ESP_HID_APPEARANCE_GAMEPAD:
|
||||
ret = ESP_HID_CLASS_GPD;
|
||||
break;
|
||||
default:
|
||||
ret = ESP_HID_CLASS_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t get_value_len_by_type_protocol(esp_bt_hidd_dev_t *dev, uint8_t report_type, uint8_t protocol_mode)
|
||||
{
|
||||
uint32_t value_len = 0;
|
||||
hidd_report_item_t *rpt = NULL;
|
||||
for (uint8_t d = 0; d < dev->devices_len; d++) {
|
||||
for (uint8_t i = 0; i < dev->devices[d].reports_len; i++) {
|
||||
rpt = &dev->devices[d].reports[i];
|
||||
if (rpt->report_type == report_type && rpt->protocol_mode == dev->protocol_mode) {
|
||||
value_len += rpt->value_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
return value_len;
|
||||
}
|
||||
|
||||
static void bt_hidd_init_app(void)
|
||||
{
|
||||
esp_hid_device_config_t *p_config = &s_hidd_param.dev->config;
|
||||
s_hidd_param.app_param.name = p_config->device_name;
|
||||
s_hidd_param.app_param.description = p_config->device_name;
|
||||
s_hidd_param.app_param.provider = p_config->manufacturer_name;
|
||||
s_hidd_param.app_param.subclass = get_subclass_by_appearance(s_hidd_param.dev->appearance);
|
||||
s_hidd_param.app_param.desc_list = (uint8_t *)s_hidd_param.dev->devices[0].reports_map.data;
|
||||
s_hidd_param.app_param.desc_list_len = s_hidd_param.dev->devices[0].reports_map.len;
|
||||
}
|
||||
|
||||
static void bt_hidd_init_qos(void)
|
||||
{
|
||||
uint32_t value_len = 0;
|
||||
value_len =
|
||||
get_value_len_by_type_protocol(s_hidd_param.dev, ESP_HID_REPORT_TYPE_INPUT, s_hidd_param.dev->protocol_mode);
|
||||
build_default_in_qos(&s_hidd_param.in_qos, value_len);
|
||||
|
||||
value_len =
|
||||
get_value_len_by_type_protocol(s_hidd_param.dev, ESP_HID_REPORT_TYPE_INPUT, s_hidd_param.dev->protocol_mode);
|
||||
build_default_out_qos(&s_hidd_param.out_qos, value_len);
|
||||
}
|
||||
|
||||
static bool esp_bt_hidd_dev_connected(void *devp)
|
||||
{
|
||||
esp_bt_hidd_dev_t *dev = (esp_bt_hidd_dev_t *)devp;
|
||||
bool ret = true;
|
||||
osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
|
||||
do {
|
||||
if (!is_init()) {
|
||||
ESP_LOGE(TAG, "HID device profile is uninit");
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (s_hidd_param.dev != dev) {
|
||||
ESP_LOGE(TAG, "Wrong HID device provided");
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
} while(0);
|
||||
if (ret) {
|
||||
ret = dev->connected;
|
||||
}
|
||||
osi_mutex_unlock(&s_hidd_param.mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t esp_bt_hidd_dev_deinit(void *devp)
|
||||
{
|
||||
esp_bt_hidd_dev_t *dev = (esp_bt_hidd_dev_t *)devp;
|
||||
esp_err_t ret = ESP_OK;
|
||||
osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
|
||||
do {
|
||||
if (!is_init()) {
|
||||
osi_mutex_unlock(&s_hidd_param.mutex);
|
||||
ESP_LOGE(TAG, "HID device profile already uninitialized");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if (s_hidd_param.dev != dev) {
|
||||
ESP_LOGE(TAG, "Wrong HID device provided");
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
} while(0);
|
||||
osi_mutex_unlock(&s_hidd_param.mutex);
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
ret = esp_bt_hid_device_deinit();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t esp_bt_hidd_dev_disconnect(void *devp)
|
||||
{
|
||||
esp_bt_hidd_dev_t *dev = (esp_bt_hidd_dev_t *)devp;
|
||||
esp_err_t ret = ESP_OK;
|
||||
osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
|
||||
do {
|
||||
if (!is_init()) {
|
||||
ESP_LOGE(TAG, "HID device is uninit");
|
||||
ret = ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (s_hidd_param.dev != dev) {
|
||||
ESP_LOGE(TAG, "Wrong HID device provided");
|
||||
ret = ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dev->connected) {
|
||||
osi_mutex_unlock(&s_hidd_param.mutex);
|
||||
ESP_LOGW(TAG, "already disconnected");
|
||||
return ESP_OK;
|
||||
}
|
||||
} while(0);
|
||||
osi_mutex_unlock(&s_hidd_param.mutex);
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
ret = esp_bt_hid_device_disconnect();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t esp_bt_hidd_dev_battery_set(void *devp, uint8_t level)
|
||||
{
|
||||
UNUSED(devp);
|
||||
UNUSED(level);
|
||||
ESP_LOGW(TAG, "Not implement yet!");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_bt_hidd_dev_input_set(void *devp, size_t index, size_t id, uint8_t *data, size_t length)
|
||||
{
|
||||
hidd_report_item_t *p_rpt;
|
||||
esp_bt_hidd_dev_t *dev = (esp_bt_hidd_dev_t *)devp;
|
||||
esp_err_t ret = ESP_OK;
|
||||
osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
|
||||
do {
|
||||
if (!is_init()) {
|
||||
ESP_LOGE(TAG, "HID device is uninit");
|
||||
ret = ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (s_hidd_param.dev != dev) {
|
||||
ESP_LOGE(TAG, "Wrong HID device provided");
|
||||
ret = ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dev->connected) {
|
||||
ESP_LOGE(TAG, "HID device not connected!");
|
||||
ret = ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
p_rpt = get_report_by_idx_id_type(dev, index, id, ESP_HID_REPORT_TYPE_INPUT);
|
||||
if (p_rpt == NULL) {
|
||||
ESP_LOGE(TAG, "HID device not connected!");
|
||||
ret = ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (length > p_rpt->value_len) {
|
||||
ESP_LOGE(TAG, "Data size over %d!", p_rpt->value_len);
|
||||
ret = ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
} while(0);
|
||||
osi_mutex_unlock(&s_hidd_param.mutex);
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
ret = esp_bt_hid_device_send_report(ESP_HIDD_REPORT_TYPE_INTRDATA, id, length, data);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t esp_bt_hidd_dev_feature_set(void *devp, size_t index, size_t id, uint8_t *data, size_t length)
|
||||
{
|
||||
hidd_report_item_t *p_rpt;
|
||||
esp_bt_hidd_dev_t *dev = (esp_bt_hidd_dev_t *)devp;
|
||||
esp_err_t ret = ESP_OK;
|
||||
osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
|
||||
do {
|
||||
if (!is_init()) {
|
||||
ESP_LOGE(TAG, "HID device is uninit");
|
||||
ret = ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (s_hidd_param.dev != dev) {
|
||||
ESP_LOGE(TAG, "Wrong HID device provided");
|
||||
ret = ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dev->connected) {
|
||||
ESP_LOGE(TAG, "HID device not connected!");
|
||||
ret = ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
p_rpt = get_report_by_idx_id_type(dev, index, id, ESP_HID_REPORT_TYPE_FEATURE);
|
||||
if (p_rpt == NULL) {
|
||||
ESP_LOGE(TAG, "HID device not connected!");
|
||||
ret = ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (length > p_rpt->value_len) {
|
||||
ESP_LOGE(TAG, "Data size over %d!", p_rpt->value_len);
|
||||
ret = ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
} while(0);
|
||||
osi_mutex_unlock(&s_hidd_param.mutex);
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
ret = esp_bt_hid_device_send_report(ESP_HID_REPORT_TYPE_FEATURE, id, length, data);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t esp_bt_hidd_dev_event_handler_register(void *devp, esp_event_handler_t callback, esp_hidd_event_t event)
|
||||
{
|
||||
esp_bt_hidd_dev_t *dev = (esp_bt_hidd_dev_t *)devp;
|
||||
esp_err_t ret = ESP_OK;
|
||||
osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
|
||||
do {
|
||||
if (!is_init()) {
|
||||
ESP_LOGE(TAG, "HID device is uninit");
|
||||
ret = ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (s_hidd_param.dev != dev) {
|
||||
ESP_LOGE(TAG, "Wrong HID device provided");
|
||||
ret = ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = esp_event_handler_register_with(dev->event_loop_handle, ESP_HIDD_EVENTS, event, callback, dev->dev);
|
||||
} while (0);
|
||||
osi_mutex_unlock(&s_hidd_param.mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t esp_bt_hidd_dev_event_handler_unregister(void *devp, esp_event_handler_t callback, esp_hidd_event_t event)
|
||||
{
|
||||
esp_bt_hidd_dev_t *dev = (esp_bt_hidd_dev_t *)devp;
|
||||
esp_err_t ret = ESP_OK;
|
||||
osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
|
||||
do {
|
||||
if (!is_init()) {
|
||||
ESP_LOGE(TAG, "HID device is uninit");
|
||||
ret = ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (s_hidd_param.dev != dev) {
|
||||
ESP_LOGE(TAG, "Wrong HID device provided");
|
||||
ret = ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
ret = esp_event_handler_unregister_with(dev->event_loop_handle, ESP_HIDD_EVENTS, event, callback);
|
||||
} while (0);
|
||||
osi_mutex_unlock(&s_hidd_param.mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void bt_hidd_cb(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param)
|
||||
{
|
||||
esp_hidd_event_data_t cb_param = {0};
|
||||
esp_hidd_event_data_t *p_cb_param = NULL;
|
||||
size_t event_data_size = 0;
|
||||
uint8_t map_index = 0;
|
||||
hidd_report_item_t *p_rpt = NULL;
|
||||
|
||||
if (!is_init()) {
|
||||
ESP_LOGE(TAG, "HID device is uninit, event(%d)", event);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event) {
|
||||
case ESP_HIDD_INIT_EVT: {
|
||||
if (param->init.status == ESP_HIDD_SUCCESS) {
|
||||
ESP_LOGD(TAG, "Setting hid parameters in_qos:%d, out_qos:%d", s_hidd_param.in_qos.token_bucket_size,
|
||||
s_hidd_param.out_qos.token_bucket_size);
|
||||
esp_bt_hid_device_register_app(&s_hidd_param.app_param, &s_hidd_param.in_qos, &s_hidd_param.out_qos);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Init hidd failed (%d)!", param->init.status);
|
||||
cb_param.start.status = bt_hidd_get_status(param->init.status);
|
||||
esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_START_EVENT, &cb_param,
|
||||
sizeof(esp_hidd_event_data_t), portMAX_DELAY);
|
||||
|
||||
bt_hidd_dev_free();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_HIDD_DEINIT_EVT: {
|
||||
cb_param.stop.status = bt_hidd_get_status(param->deinit.status);
|
||||
esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_STOP_EVENT, &cb_param,
|
||||
sizeof(esp_hidd_event_data_t), portMAX_DELAY);
|
||||
if (param->deinit.status == ESP_HIDD_SUCCESS) {
|
||||
bt_hidd_dev_free();
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Deinit hidd failed (%d)!", param->deinit.status);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_HIDD_REGISTER_APP_EVT: {
|
||||
if (param->register_app.status == ESP_HIDD_SUCCESS) {
|
||||
ESP_LOGD(TAG, "Setting hid parameters success!");
|
||||
if (param->register_app.in_use && param->register_app.bd_addr != NULL) {
|
||||
ESP_LOGI(TAG, "Start virtual cable plug!");
|
||||
esp_bt_hid_device_connect(param->register_app.bd_addr);
|
||||
}
|
||||
|
||||
osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
|
||||
s_hidd_param.dev->registered = true;
|
||||
osi_mutex_unlock(&s_hidd_param.mutex);
|
||||
|
||||
cb_param.start.status = bt_hidd_get_status(param->init.status);
|
||||
esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_START_EVENT, &cb_param,
|
||||
sizeof(esp_hidd_event_data_t), portMAX_DELAY);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Setting hid parameters failed (%d), now deint!", param->register_app.status);
|
||||
esp_bt_hid_device_deinit();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_HIDD_UNREGISTER_APP_EVT: {
|
||||
break;
|
||||
}
|
||||
case ESP_HIDD_OPEN_EVT: {
|
||||
if (param->open.conn_status == ESP_HIDD_CONN_STATE_CONNECTING) {
|
||||
break;
|
||||
}
|
||||
if (param->open.status == ESP_HIDD_SUCCESS && param->open.conn_status == ESP_HIDD_CONN_STATE_CONNECTED) {
|
||||
ESP_LOGI(TAG, "Connected to %02x:%02x:%02x:%02x:%02x:%02x", param->open.bd_addr[0], param->open.bd_addr[1],
|
||||
param->open.bd_addr[2], param->open.bd_addr[3], param->open.bd_addr[4], param->open.bd_addr[5]);
|
||||
osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
|
||||
s_hidd_param.dev->connected = true;
|
||||
memcpy(s_hidd_param.dev->remote_bda, param->open.bd_addr, ESP_BD_ADDR_LEN);
|
||||
osi_mutex_unlock(&s_hidd_param.mutex);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Connect failed (%d)!", param->open.status);
|
||||
}
|
||||
cb_param.connect.status = bt_hidd_get_status(param->open.status);
|
||||
cb_param.connect.dev = s_hidd_param.dev->dev;
|
||||
esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_CONNECT_EVENT, &cb_param,
|
||||
sizeof(esp_hidd_event_data_t), portMAX_DELAY);
|
||||
break;
|
||||
}
|
||||
case ESP_HIDD_CLOSE_EVT: {
|
||||
if (param->close.conn_status == ESP_HIDD_CONN_STATE_DISCONNECTING) {
|
||||
break;
|
||||
}
|
||||
if (param->close.status == ESP_HIDD_SUCCESS && param->close.conn_status == ESP_HIDD_CONN_STATE_DISCONNECTED) {
|
||||
osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
|
||||
s_hidd_param.dev->connected = false;
|
||||
memset(s_hidd_param.dev->remote_bda, 0, ESP_BD_ADDR_LEN);
|
||||
osi_mutex_unlock(&s_hidd_param.mutex);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Disconnect failed (%d)!", param->close.status);
|
||||
}
|
||||
cb_param.disconnect.status = bt_hidd_get_status(param->close.status);
|
||||
cb_param.disconnect.dev = s_hidd_param.dev->dev;
|
||||
cb_param.disconnect.reason = param->close.status;
|
||||
esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_DISCONNECT_EVENT, &cb_param,
|
||||
sizeof(esp_hidd_event_data_t), portMAX_DELAY);
|
||||
break;
|
||||
}
|
||||
case ESP_HIDD_SEND_REPORT_EVT:
|
||||
break;
|
||||
case ESP_HIDD_REPORT_ERR_EVT:
|
||||
break;
|
||||
case ESP_HIDD_GET_REPORT_EVT: {
|
||||
uint8_t *data_ptr = NULL;
|
||||
p_rpt = get_report_by_id_and_type((esp_bt_hidd_dev_t *)s_hidd_param.dev->dev, param->get_report.report_id,
|
||||
param->get_report.report_type, &map_index);
|
||||
if (p_rpt == NULL) {
|
||||
ESP_LOGE(TAG, "Can not find report!");
|
||||
esp_bt_hid_device_report_error(ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID);
|
||||
break;
|
||||
}
|
||||
if (param->get_report.buffer_size > p_rpt->value_len) {
|
||||
ESP_LOGE(TAG, "Data size over %d!", p_rpt->value_len);
|
||||
esp_bt_hid_device_report_error(ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM);
|
||||
break;
|
||||
}
|
||||
|
||||
event_data_size = sizeof(esp_hidd_event_data_t);
|
||||
if (param->get_report.buffer_size) {
|
||||
event_data_size += 2;
|
||||
}
|
||||
|
||||
if ((p_cb_param = (esp_hidd_event_data_t *)malloc(event_data_size)) == NULL) {
|
||||
ESP_LOGE(TAG, "%s malloc event data failed!", __func__);
|
||||
break;
|
||||
}
|
||||
memset(p_cb_param, 0, event_data_size);
|
||||
p_cb_param->feature.dev = s_hidd_param.dev->dev;
|
||||
p_cb_param->feature.trans_type = ESP_HID_TRANS_GET_REPORT;
|
||||
p_cb_param->feature.report_type = param->get_report.report_type;
|
||||
p_cb_param->feature.report_id = p_rpt->report_id;
|
||||
p_cb_param->feature.usage = p_rpt->usage;
|
||||
p_cb_param->feature.length = param->get_report.buffer_size ? 2 : 0;
|
||||
p_cb_param->feature.data = ((uint8_t *)p_cb_param) + sizeof(esp_hidd_event_data_t);
|
||||
p_cb_param->feature.map_index = map_index;
|
||||
if (param->get_report.buffer_size) {
|
||||
data_ptr = ((uint8_t *)p_cb_param) + sizeof(esp_hidd_event_data_t);
|
||||
*data_ptr++ = (uint8_t)param->get_report.buffer_size;
|
||||
*data_ptr++ = (uint8_t)(param->get_report.buffer_size >> 8);
|
||||
}
|
||||
esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_FEATURE_EVENT, p_cb_param,
|
||||
event_data_size, portMAX_DELAY);
|
||||
break;
|
||||
}
|
||||
case ESP_HIDD_SET_REPORT_EVT: {
|
||||
p_rpt = get_report_by_id_and_type((esp_bt_hidd_dev_t *)s_hidd_param.dev->dev, param->set_report.report_id,
|
||||
param->set_report.report_type, &map_index);
|
||||
if (p_rpt == NULL) {
|
||||
ESP_LOGE(TAG, "Can not find report!");
|
||||
esp_bt_hid_device_report_error(ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID);
|
||||
break;
|
||||
}
|
||||
if (param->set_report.len > p_rpt->value_len) {
|
||||
ESP_LOGE(TAG, "Data size over %d!", p_rpt->value_len);
|
||||
esp_bt_hid_device_report_error(ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM);
|
||||
break;
|
||||
}
|
||||
|
||||
event_data_size = sizeof(esp_hidd_event_data_t);
|
||||
if (param->set_report.len && param->set_report.data) {
|
||||
event_data_size += param->set_report.len;
|
||||
}
|
||||
|
||||
if ((p_cb_param = (esp_hidd_event_data_t *)malloc(event_data_size)) == NULL) {
|
||||
ESP_LOGE(TAG, "%s malloc event data failed!", __func__);
|
||||
break;
|
||||
}
|
||||
memset(p_cb_param, 0, event_data_size);
|
||||
p_cb_param->feature.dev = s_hidd_param.dev->dev;
|
||||
p_cb_param->feature.trans_type = ESP_HID_TRANS_SET_REPORT;
|
||||
p_cb_param->feature.report_type = param->set_report.report_type;
|
||||
p_cb_param->feature.report_id = p_rpt->report_id;
|
||||
p_cb_param->feature.usage = p_rpt->usage;
|
||||
p_cb_param->feature.length = param->set_report.len;
|
||||
p_cb_param->feature.data = param->set_report.data;
|
||||
p_cb_param->feature.map_index = map_index;
|
||||
if (param->set_report.len && param->set_report.data) {
|
||||
memcpy(((uint8_t *)p_cb_param) + sizeof(esp_hidd_event_data_t), param->set_report.data,
|
||||
param->set_report.len);
|
||||
}
|
||||
esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_FEATURE_EVENT, p_cb_param,
|
||||
event_data_size, portMAX_DELAY);
|
||||
break;
|
||||
}
|
||||
case ESP_HIDD_SET_PROTOCOL_EVT: {
|
||||
if (param->set_protocol.protocol_mode != ESP_HIDD_UNSUPPORTED_MODE) {
|
||||
if (s_hidd_param.dev->protocol_mode == param->set_protocol.protocol_mode) {
|
||||
break;
|
||||
}
|
||||
osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT);
|
||||
s_hidd_param.dev->protocol_mode = param->set_protocol.protocol_mode;
|
||||
osi_mutex_unlock(&s_hidd_param.mutex);
|
||||
cb_param.protocol_mode.dev = s_hidd_param.dev->dev;
|
||||
cb_param.protocol_mode.protocol_mode = s_hidd_param.dev->protocol_mode;
|
||||
cb_param.protocol_mode.map_index = 0;
|
||||
esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_PROTOCOL_MODE_EVENT,
|
||||
&cb_param, sizeof(esp_hidd_event_data_t), portMAX_DELAY);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Unsupported protocol mode!");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_HIDD_INTR_DATA_EVT: {
|
||||
p_rpt = get_report_by_id_and_type((esp_bt_hidd_dev_t *)s_hidd_param.dev->dev, param->intr_data.report_id,
|
||||
ESP_HID_REPORT_TYPE_OUTPUT, &map_index);
|
||||
if (p_rpt == NULL) {
|
||||
ESP_LOGE(TAG, "Can not find report!");
|
||||
break;
|
||||
}
|
||||
|
||||
event_data_size = sizeof(esp_hidd_event_data_t);
|
||||
if (param->intr_data.len && param->intr_data.data) {
|
||||
event_data_size += param->intr_data.len;
|
||||
}
|
||||
|
||||
if ((p_cb_param = (esp_hidd_event_data_t *)malloc(event_data_size)) == NULL) {
|
||||
ESP_LOGE(TAG, "%s malloc event data failed!", __func__);
|
||||
break;
|
||||
}
|
||||
memset(p_cb_param, 0, event_data_size);
|
||||
p_cb_param->output.dev = s_hidd_param.dev->dev;
|
||||
p_cb_param->output.report_id = p_rpt->report_id;
|
||||
p_cb_param->output.usage = p_rpt->usage;
|
||||
p_cb_param->output.length = param->intr_data.len;
|
||||
p_cb_param->output.data = param->intr_data.data;
|
||||
p_cb_param->output.map_index = map_index;
|
||||
if (param->intr_data.len && param->intr_data.data) {
|
||||
memcpy(((uint8_t *)p_cb_param) + sizeof(esp_hidd_event_data_t), param->intr_data.data,
|
||||
param->intr_data.len);
|
||||
}
|
||||
esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_OUTPUT_EVENT, p_cb_param,
|
||||
event_data_size, portMAX_DELAY);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (p_cb_param) {
|
||||
free(p_cb_param);
|
||||
p_cb_param = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hidd_dev_init(esp_hidd_dev_t *dev_p, const esp_hid_device_config_t *config, esp_event_handler_t callback)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
if (dev_p == NULL || config == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (is_init()) {
|
||||
ESP_LOGE(TAG, "HID device profile already initialized");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
osi_mutex_new(&s_hidd_param.mutex);
|
||||
if (s_hidd_param.mutex == NULL) {
|
||||
ESP_LOGE(TAG, "HID device mutex could not be allocated");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
s_hidd_param.dev = (esp_bt_hidd_dev_t *)calloc(1, sizeof(esp_bt_hidd_dev_t));
|
||||
if (s_hidd_param.dev == NULL) {
|
||||
ESP_LOGE(TAG, "HID device could not be allocated");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
//[1] Reset the hid device target environment
|
||||
s_hidd_param.dev->connected = false;
|
||||
s_hidd_param.dev->registered = false;
|
||||
s_hidd_param.dev->bat_level = 100;
|
||||
s_hidd_param.dev->control = ESP_HID_CONTROL_EXIT_SUSPEND;
|
||||
s_hidd_param.dev->protocol_mode = ESP_HID_PROTOCOL_MODE_REPORT;
|
||||
s_hidd_param.dev->event_loop_handle = NULL;
|
||||
s_hidd_param.dev->dev = dev_p;
|
||||
|
||||
esp_event_loop_args_t event_task_args = {
|
||||
.queue_size = 5,
|
||||
.task_name = "bt_hidd_events",
|
||||
.task_priority = uxTaskPriorityGet(NULL),
|
||||
.task_stack_size = 2048,
|
||||
.task_core_id = tskNO_AFFINITY
|
||||
};
|
||||
ret = esp_event_loop_create(&event_task_args, &s_hidd_param.dev->event_loop_handle);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "HID device event loop could not be created");
|
||||
bt_hidd_dev_free();
|
||||
return ret;
|
||||
}
|
||||
|
||||
//[2] parse hid descriptor
|
||||
ret = bt_hidd_init_config(s_hidd_param.dev, config);
|
||||
if (ret != ESP_OK) {
|
||||
bt_hidd_dev_free();
|
||||
return ret;
|
||||
}
|
||||
|
||||
//[3] configure hidd app param and qos param
|
||||
bt_hidd_init_app();
|
||||
bt_hidd_init_qos();
|
||||
|
||||
//[4] implement the interface
|
||||
dev_p->dev = s_hidd_param.dev;
|
||||
dev_p->connected = esp_bt_hidd_dev_connected;
|
||||
dev_p->disconnect = esp_bt_hidd_dev_disconnect;
|
||||
dev_p->deinit = esp_bt_hidd_dev_deinit;
|
||||
dev_p->battery_set = esp_bt_hidd_dev_battery_set;
|
||||
dev_p->input_set = esp_bt_hidd_dev_input_set;
|
||||
dev_p->feature_set = esp_bt_hidd_dev_feature_set;
|
||||
dev_p->event_handler_register = esp_bt_hidd_dev_event_handler_register;
|
||||
dev_p->event_handler_unregister = esp_bt_hidd_dev_event_handler_unregister;
|
||||
|
||||
ret = esp_bt_hidd_dev_event_handler_register(s_hidd_param.dev, esp_hidd_process_event_data_handler, ESP_EVENT_ANY_ID);
|
||||
if (ret != ESP_OK) {
|
||||
bt_hidd_dev_free();
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (callback != NULL) {
|
||||
ret = esp_bt_hidd_dev_event_handler_register(s_hidd_param.dev, callback, ESP_EVENT_ANY_ID);
|
||||
if (ret != ESP_OK) {
|
||||
bt_hidd_dev_free();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = esp_bt_hid_device_register_callback(bt_hidd_cb);
|
||||
ret |= esp_bt_hid_device_init();
|
||||
if (ret != ESP_OK) {
|
||||
bt_hidd_dev_free();
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_BT_HID_DEVICE_ENABLED */
|
File diff suppressed because it is too large
Load Diff
@@ -103,7 +103,8 @@ static int handle_report(hid_report_params_t *report, bool first)
|
||||
}
|
||||
|
||||
item.protocol_mode = ESP_HID_PROTOCOL_MODE_BOOT;
|
||||
item.value_len = 8;
|
||||
item.report_id = 0x01;
|
||||
item.value_len = 9;
|
||||
if (add_report(map, &item) != 0) {
|
||||
return -1;
|
||||
}
|
||||
@@ -142,6 +143,7 @@ static int handle_report(hid_report_params_t *report, bool first)
|
||||
}
|
||||
|
||||
item.protocol_mode = ESP_HID_PROTOCOL_MODE_BOOT;
|
||||
item.report_id = 0x02;
|
||||
item.value_len = 4;
|
||||
if (add_report(map, &item) != 0) {
|
||||
return -1;
|
||||
|
@@ -20,11 +20,14 @@
|
||||
#include "ble_hidd.h"
|
||||
#endif /* CONFIG_GATTS_ENABLE */
|
||||
|
||||
#if CONFIG_BT_HID_DEVICE_ENABLED
|
||||
#include "bt_hidd.h"
|
||||
#endif /* CONFIG_BT_HID_DEVICE_ENABLED */
|
||||
|
||||
ESP_EVENT_DEFINE_BASE(ESP_HIDD_EVENTS);
|
||||
|
||||
esp_err_t esp_hidd_dev_init(const esp_hid_device_config_t *config, esp_hid_transport_t transport, esp_event_handler_t callback, esp_hidd_dev_t **dev_out)
|
||||
{
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
esp_hidd_dev_t *dev = (esp_hidd_dev_t *)calloc(1, sizeof(esp_hidd_dev_t));
|
||||
if (dev == NULL) {
|
||||
@@ -37,6 +40,11 @@ esp_err_t esp_hidd_dev_init(const esp_hid_device_config_t *config, esp_hid_trans
|
||||
ret = esp_ble_hidd_dev_init(dev, config, callback);
|
||||
break;
|
||||
#endif /* CONFIG_GATTS_ENABLE */
|
||||
#if CONFIG_BT_HID_DEVICE_ENABLED
|
||||
case ESP_HID_TRANSPORT_BT:
|
||||
ret = esp_bt_hidd_dev_init(dev, config, callback);
|
||||
break;
|
||||
#endif /* CONFIG_BT_HID_DEVICE_ENABLED */
|
||||
default:
|
||||
ret = ESP_FAIL;
|
||||
break;
|
||||
@@ -119,3 +127,29 @@ esp_err_t esp_hidd_dev_event_handler_unregister(esp_hidd_dev_t *dev, esp_event_h
|
||||
}
|
||||
return dev->event_handler_unregister(dev->dev, callback, event);
|
||||
}
|
||||
|
||||
/**
|
||||
* The deep copy data append the end of the esp_hidd_event_data_t, move the data pointer to the correct address. This is
|
||||
* a workaround way, it's better to use flexiable array in the interface.
|
||||
*/
|
||||
void esp_hidd_process_event_data_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id,
|
||||
void *event_data)
|
||||
{
|
||||
esp_hidd_event_t event = (esp_hidd_event_t)event_id;
|
||||
esp_hidd_event_data_t *param = (esp_hidd_event_data_t *)event_data;
|
||||
|
||||
switch (event) {
|
||||
case ESP_HIDD_OUTPUT_EVENT:
|
||||
if (param->output.length && param->output.data) {
|
||||
param->output.data = (uint8_t *)param + sizeof(esp_hidd_event_data_t);
|
||||
}
|
||||
break;
|
||||
case ESP_HIDD_FEATURE_EVENT:
|
||||
if (param->feature.length && param->feature.data) {
|
||||
param->feature.data = (uint8_t *)param + sizeof(esp_hidd_event_data_t);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@@ -21,13 +21,16 @@
|
||||
#include "esp_event_base.h"
|
||||
|
||||
ESP_EVENT_DEFINE_BASE(ESP_HIDH_EVENTS);
|
||||
#define ESP_HIDH_DELAY_FREE_TO 100000 // us
|
||||
|
||||
static const char *TAG = "ESP_HIDH";
|
||||
|
||||
static esp_hidh_dev_head_t s_esp_hidh_devices;
|
||||
|
||||
static esp_timer_handle_t s_esp_hidh_timer;
|
||||
static xSemaphoreHandle s_esp_hidh_devices_semaphore = NULL;
|
||||
|
||||
static void esp_hidh_dev_delay_free(void *arg);
|
||||
|
||||
static inline void lock_devices(void)
|
||||
{
|
||||
if (s_esp_hidh_devices_semaphore != NULL) {
|
||||
@@ -42,7 +45,12 @@ static inline void unlock_devices(void)
|
||||
}
|
||||
}
|
||||
|
||||
static bool esp_hidh_dev_exists(esp_hidh_dev_t *dev)
|
||||
|
||||
/*
|
||||
* Public Functions
|
||||
* */
|
||||
|
||||
bool esp_hidh_dev_exists(esp_hidh_dev_t *dev)
|
||||
{
|
||||
if (dev == NULL) {
|
||||
return false;
|
||||
@@ -59,10 +67,6 @@ static bool esp_hidh_dev_exists(esp_hidh_dev_t *dev)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Public Functions
|
||||
* */
|
||||
|
||||
esp_err_t esp_hidh_init(const esp_hidh_config_t *config)
|
||||
{
|
||||
esp_err_t err = ESP_FAIL;
|
||||
@@ -76,12 +80,25 @@ esp_err_t esp_hidh_init(const esp_hidh_config_t *config)
|
||||
return err;
|
||||
}
|
||||
|
||||
s_esp_hidh_devices_semaphore = xSemaphoreCreateBinary();
|
||||
TAILQ_INIT(&s_esp_hidh_devices);
|
||||
|
||||
esp_timer_create_args_t timer_config = {
|
||||
.callback = &esp_hidh_dev_delay_free,
|
||||
.arg = NULL,
|
||||
.name = "hidh_timer"
|
||||
};
|
||||
|
||||
if ((err = esp_timer_create(&timer_config, &s_esp_hidh_timer)) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s create timer failed!", __func__);
|
||||
return err;
|
||||
}
|
||||
|
||||
s_esp_hidh_devices_semaphore = xSemaphoreCreateMutex();
|
||||
if (s_esp_hidh_devices_semaphore == NULL) {
|
||||
ESP_LOGE(TAG, "xSemaphoreCreateMutex failed!");
|
||||
return err;
|
||||
}
|
||||
|
||||
// unlock_devices();
|
||||
err = ESP_OK;
|
||||
|
||||
#if CONFIG_BT_HID_HOST_ENABLED
|
||||
@@ -96,12 +113,11 @@ esp_err_t esp_hidh_init(const esp_hidh_config_t *config)
|
||||
}
|
||||
#endif /* CONFIG_GATTC_ENABLE */
|
||||
|
||||
if (err == ESP_OK) {
|
||||
TAILQ_INIT(&s_esp_hidh_devices);
|
||||
unlock_devices();
|
||||
} else {
|
||||
if (err != ESP_OK) {
|
||||
vSemaphoreDelete(s_esp_hidh_devices_semaphore);
|
||||
s_esp_hidh_devices_semaphore = NULL;
|
||||
esp_timer_delete(s_esp_hidh_timer);
|
||||
s_esp_hidh_timer = NULL;
|
||||
}
|
||||
|
||||
return err;
|
||||
@@ -115,6 +131,11 @@ esp_err_t esp_hidh_deinit(void)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (esp_timer_is_active(s_esp_hidh_timer)) {
|
||||
ESP_LOGE(TAG, "Busy, try again later!");
|
||||
return ESP_ERR_NOT_FINISHED;
|
||||
}
|
||||
|
||||
if (!TAILQ_EMPTY(&s_esp_hidh_devices)) {
|
||||
ESP_LOGE(TAG, "Please disconnect all devices first!");
|
||||
return err;
|
||||
@@ -138,6 +159,8 @@ esp_err_t esp_hidh_deinit(void)
|
||||
TAILQ_INIT(&s_esp_hidh_devices);
|
||||
vSemaphoreDelete(s_esp_hidh_devices_semaphore);
|
||||
s_esp_hidh_devices_semaphore = NULL;
|
||||
esp_timer_delete(s_esp_hidh_timer);
|
||||
s_esp_hidh_timer = NULL;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
@@ -166,156 +189,317 @@ esp_hidh_dev_t *esp_hidh_dev_open(esp_bd_addr_t bda, esp_hid_transport_t transpo
|
||||
|
||||
esp_err_t esp_hidh_dev_close(esp_hidh_dev_t *dev)
|
||||
{
|
||||
if (!esp_hidh_dev_exists(dev)) {
|
||||
return ESP_FAIL;
|
||||
esp_err_t ret = ESP_OK;
|
||||
if (esp_hidh_dev_exists(dev)) {
|
||||
esp_hidh_dev_lock(dev);
|
||||
ret = dev->close(dev);
|
||||
esp_hidh_dev_unlock(dev);
|
||||
} else {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
return dev->close(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void esp_hidh_dev_dump(esp_hidh_dev_t *dev, FILE *fp)
|
||||
{
|
||||
if (!esp_hidh_dev_exists(dev)) {
|
||||
return;
|
||||
if (esp_hidh_dev_exists(dev)) {
|
||||
esp_hidh_dev_lock(dev);
|
||||
dev->dump(dev, fp);
|
||||
esp_hidh_dev_unlock(dev);
|
||||
}
|
||||
dev->dump(dev, fp);
|
||||
}
|
||||
|
||||
esp_err_t esp_hidh_dev_output_set(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, uint8_t *value, size_t value_len)
|
||||
{
|
||||
if (!esp_hidh_dev_exists(dev)) {
|
||||
return ESP_FAIL;
|
||||
esp_err_t ret = ESP_OK;
|
||||
if (esp_hidh_dev_exists(dev)) {
|
||||
esp_hidh_dev_lock(dev);
|
||||
ret = dev->report_write(dev, map_index, report_id, ESP_HID_REPORT_TYPE_OUTPUT, value, value_len);
|
||||
esp_hidh_dev_unlock(dev);
|
||||
} else {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
return dev->report_write(dev, map_index, report_id, ESP_HID_REPORT_TYPE_OUTPUT, value, value_len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_hidh_dev_feature_set(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, uint8_t *value, size_t value_len)
|
||||
{
|
||||
if (!esp_hidh_dev_exists(dev)) {
|
||||
return ESP_FAIL;
|
||||
esp_err_t ret = ESP_OK;
|
||||
if (esp_hidh_dev_exists(dev)) {
|
||||
esp_hidh_dev_lock(dev);
|
||||
ret = dev->report_write(dev, map_index, report_id, ESP_HID_REPORT_TYPE_FEATURE, value, value_len);
|
||||
esp_hidh_dev_unlock(dev);
|
||||
} else {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
return dev->report_write(dev, map_index, report_id, ESP_HID_REPORT_TYPE_FEATURE, value, value_len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_hidh_dev_feature_get(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, size_t max_length, uint8_t *value, size_t *value_len)
|
||||
{
|
||||
if (!esp_hidh_dev_exists(dev)) {
|
||||
return ESP_FAIL;
|
||||
esp_err_t ret = ESP_OK;
|
||||
if (esp_hidh_dev_exists(dev)) {
|
||||
esp_hidh_dev_lock(dev);
|
||||
ret = dev->report_read(dev, map_index, report_id, ESP_HID_REPORT_TYPE_FEATURE, max_length, value, value_len);
|
||||
esp_hidh_dev_unlock(dev);
|
||||
} else {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
return dev->report_read(dev, map_index, report_id, ESP_HID_REPORT_TYPE_FEATURE, max_length, value, value_len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_hidh_dev_set_report(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type, uint8_t *data, size_t length)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
if (esp_hidh_dev_exists(dev)) {
|
||||
esp_hidh_dev_lock(dev);
|
||||
if (dev->set_report) {
|
||||
ret = dev->set_report(dev, map_index, report_id, report_type, data, length);
|
||||
} else {
|
||||
ret = ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
esp_hidh_dev_unlock(dev);
|
||||
} else {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_hidh_dev_get_report(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type,
|
||||
size_t max_len)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
if (esp_hidh_dev_exists(dev)) {
|
||||
esp_hidh_dev_lock(dev);
|
||||
ret = dev->report_read(dev, map_index, report_id, report_type, max_len, NULL, NULL);
|
||||
esp_hidh_dev_unlock(dev);
|
||||
} else {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_hidh_dev_get_idle(esp_hidh_dev_t *dev)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
if (esp_hidh_dev_exists(dev)) {
|
||||
esp_hidh_dev_lock(dev);
|
||||
if (dev->get_idle) {
|
||||
ret = dev->get_idle(dev);
|
||||
} else {
|
||||
ret = ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
esp_hidh_dev_unlock(dev);
|
||||
} else {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_hidh_dev_set_idle(esp_hidh_dev_t *dev, uint8_t idle_time)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
if (esp_hidh_dev_exists(dev)) {
|
||||
esp_hidh_dev_lock(dev);
|
||||
if (dev->set_idle) {
|
||||
ret = dev->set_idle(dev, idle_time);
|
||||
} else {
|
||||
ret = ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
esp_hidh_dev_unlock(dev);
|
||||
} else {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_hidh_dev_get_protocol(esp_hidh_dev_t *dev)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
if (esp_hidh_dev_exists(dev)) {
|
||||
esp_hidh_dev_lock(dev);
|
||||
if (dev->get_protocol) {
|
||||
ret = dev->get_protocol(dev);
|
||||
} else {
|
||||
ret = ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
esp_hidh_dev_unlock(dev);
|
||||
} else {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_hidh_dev_set_protocol(esp_hidh_dev_t *dev, uint8_t protocol_mode)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
if (esp_hidh_dev_exists(dev)) {
|
||||
esp_hidh_dev_lock(dev);
|
||||
if (dev->set_protocol) {
|
||||
ret = dev->set_protocol(dev, protocol_mode);
|
||||
} else {
|
||||
ret = ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
esp_hidh_dev_unlock(dev);
|
||||
} else {
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const uint8_t *esp_hidh_dev_bda_get(esp_hidh_dev_t *dev)
|
||||
{
|
||||
uint8_t *ret = NULL;
|
||||
#if CONFIG_BLUEDROID_ENABLED
|
||||
if (esp_hidh_dev_exists(dev)) {
|
||||
return dev->bda;
|
||||
esp_hidh_dev_lock(dev);
|
||||
ret = dev->bda;
|
||||
esp_hidh_dev_unlock(dev);
|
||||
}
|
||||
#endif /* CONFIG_BLUEDROID_ENABLED */
|
||||
return NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_hid_transport_t esp_hidh_dev_transport_get(esp_hidh_dev_t *dev)
|
||||
{
|
||||
if (!esp_hidh_dev_exists(dev)) {
|
||||
return ESP_HID_TRANSPORT_MAX;
|
||||
esp_hid_transport_t ret = ESP_HID_TRANSPORT_MAX;
|
||||
if (esp_hidh_dev_exists(dev)) {
|
||||
esp_hidh_dev_lock(dev);
|
||||
ret = dev->transport;
|
||||
esp_hidh_dev_unlock(dev);
|
||||
}
|
||||
return dev->transport;
|
||||
return ret;
|
||||
}
|
||||
|
||||
const esp_hid_device_config_t *esp_hidh_dev_config_get(esp_hidh_dev_t *dev)
|
||||
{
|
||||
if (!esp_hidh_dev_exists(dev)) {
|
||||
return NULL;
|
||||
esp_hid_device_config_t *ret = NULL;
|
||||
if (esp_hidh_dev_exists(dev)) {
|
||||
esp_hidh_dev_lock(dev);
|
||||
ret = &dev->config;
|
||||
esp_hidh_dev_unlock(dev);
|
||||
}
|
||||
return &dev->config;
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *esp_hidh_dev_name_get(esp_hidh_dev_t *dev)
|
||||
{
|
||||
if (!esp_hidh_dev_exists(dev)) {
|
||||
return NULL;
|
||||
const char * ret = NULL;
|
||||
if (esp_hidh_dev_exists(dev)) {
|
||||
esp_hidh_dev_lock(dev);
|
||||
ret = dev->config.device_name ? dev->config.device_name : "";
|
||||
esp_hidh_dev_unlock(dev);
|
||||
}
|
||||
return dev->config.device_name ? dev->config.device_name : "";
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *esp_hidh_dev_manufacturer_get(esp_hidh_dev_t *dev)
|
||||
{
|
||||
if (!esp_hidh_dev_exists(dev)) {
|
||||
return NULL;
|
||||
const char *ret = NULL;
|
||||
if (esp_hidh_dev_exists(dev)) {
|
||||
esp_hidh_dev_lock(dev);
|
||||
ret = dev->config.manufacturer_name ? dev->config.manufacturer_name : "";
|
||||
esp_hidh_dev_unlock(dev);
|
||||
}
|
||||
return dev->config.manufacturer_name ? dev->config.manufacturer_name : "";
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *esp_hidh_dev_serial_get(esp_hidh_dev_t *dev)
|
||||
{
|
||||
if (!esp_hidh_dev_exists(dev)) {
|
||||
return NULL;
|
||||
const char *ret = NULL;
|
||||
if (esp_hidh_dev_exists(dev)) {
|
||||
esp_hidh_dev_lock(dev);
|
||||
ret = dev->config.serial_number ? dev->config.serial_number : "";
|
||||
esp_hidh_dev_unlock(dev);
|
||||
}
|
||||
return dev->config.serial_number ? dev->config.serial_number : "";
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint16_t esp_hidh_dev_vendor_id_get(esp_hidh_dev_t *dev)
|
||||
{
|
||||
if (!esp_hidh_dev_exists(dev)) {
|
||||
return 0;
|
||||
uint16_t ret = 0;
|
||||
if (esp_hidh_dev_exists(dev)) {
|
||||
esp_hidh_dev_lock(dev);
|
||||
ret = dev->config.vendor_id;
|
||||
esp_hidh_dev_unlock(dev);
|
||||
}
|
||||
return dev->config.vendor_id;
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint16_t esp_hidh_dev_product_id_get(esp_hidh_dev_t *dev)
|
||||
{
|
||||
if (!esp_hidh_dev_exists(dev)) {
|
||||
return 0;
|
||||
uint16_t ret = 0;
|
||||
if (esp_hidh_dev_exists(dev)) {
|
||||
esp_hidh_dev_lock(dev);
|
||||
ret = dev->config.product_id;
|
||||
esp_hidh_dev_unlock(dev);
|
||||
}
|
||||
return dev->config.product_id;
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint16_t esp_hidh_dev_version_get(esp_hidh_dev_t *dev)
|
||||
{
|
||||
uint16_t ret = 0;
|
||||
if (!esp_hidh_dev_exists(dev)) {
|
||||
return 0;
|
||||
esp_hidh_dev_lock(dev);
|
||||
ret = dev->config.version;
|
||||
esp_hidh_dev_unlock(dev);
|
||||
}
|
||||
return dev->config.version;
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_hid_usage_t esp_hidh_dev_usage_get(esp_hidh_dev_t *dev)
|
||||
{
|
||||
if (!esp_hidh_dev_exists(dev)) {
|
||||
return ESP_HID_USAGE_GENERIC;
|
||||
esp_hid_usage_t ret = ESP_HID_USAGE_GENERIC;
|
||||
if (esp_hidh_dev_exists(dev)) {
|
||||
esp_hidh_dev_lock(dev);
|
||||
ret = dev->usage;
|
||||
esp_hidh_dev_unlock(dev);
|
||||
}
|
||||
return dev->usage;
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_hidh_dev_reports_get(esp_hidh_dev_t *dev, size_t *num_reports, esp_hid_report_item_t **reports)
|
||||
{
|
||||
esp_err_t ret = 0;
|
||||
esp_hid_report_item_t *r = NULL;
|
||||
|
||||
if (!esp_hidh_dev_exists(dev)) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_hid_report_item_t *r = (esp_hid_report_item_t *)malloc(sizeof(esp_hid_report_item_t) * dev->reports_len);
|
||||
if (r == NULL) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_hidh_dev_report_t *dr = dev->reports;
|
||||
for (uint8_t i = 0; i < dev->reports_len; i++) {
|
||||
if (dr == NULL) {
|
||||
//error
|
||||
free(r);
|
||||
return ESP_FAIL;
|
||||
esp_hidh_dev_lock(dev);
|
||||
do {
|
||||
r = (esp_hid_report_item_t *)malloc(sizeof(esp_hid_report_item_t) * dev->reports_len);
|
||||
if (r == NULL) {
|
||||
ret = ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
r[i].map_index = dr->map_index;
|
||||
r[i].protocol_mode = dr->protocol_mode;
|
||||
r[i].usage = dr->usage;
|
||||
r[i].report_id = dr->report_id;
|
||||
r[i].report_type = dr->report_type;
|
||||
r[i].value_len = dr->value_len;
|
||||
|
||||
dr = dr->next;
|
||||
}
|
||||
*reports = r;
|
||||
*num_reports = dev->reports_len;
|
||||
return ESP_OK;
|
||||
esp_hidh_dev_report_t *dr = dev->reports;
|
||||
for (uint8_t i = 0; i < dev->reports_len; i++) {
|
||||
if (dr == NULL) {
|
||||
// error
|
||||
free(r);
|
||||
ret = ESP_FAIL;
|
||||
goto error_;
|
||||
}
|
||||
r[i].map_index = dr->map_index;
|
||||
r[i].protocol_mode = dr->protocol_mode;
|
||||
r[i].usage = dr->usage;
|
||||
r[i].report_id = dr->report_id;
|
||||
r[i].report_type = dr->report_type;
|
||||
r[i].value_len = dr->value_len;
|
||||
|
||||
dr = dr->next;
|
||||
}
|
||||
*reports = r;
|
||||
*num_reports = dev->reports_len;
|
||||
} while (0);
|
||||
error_:;
|
||||
esp_hidh_dev_unlock(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_hidh_dev_report_maps_get(esp_hidh_dev_t *dev, size_t *num_maps, esp_hid_raw_report_map_t **maps)
|
||||
@@ -323,8 +507,10 @@ esp_err_t esp_hidh_dev_report_maps_get(esp_hidh_dev_t *dev, size_t *num_maps, es
|
||||
if (!esp_hidh_dev_exists(dev)) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
esp_hidh_dev_lock(dev);
|
||||
*num_maps = dev->config.report_maps_len;
|
||||
*maps = dev->config.report_maps;
|
||||
esp_hidh_dev_unlock(dev);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -333,6 +519,37 @@ esp_err_t esp_hidh_dev_report_maps_get(esp_hidh_dev_t *dev, size_t *num_maps, es
|
||||
* Private Functions
|
||||
* */
|
||||
|
||||
/**
|
||||
* `lock_devices()` only protect the devices list, this mutex protect the single deivce instance.
|
||||
*/
|
||||
inline void esp_hidh_dev_lock(esp_hidh_dev_t *dev)
|
||||
{
|
||||
if (dev && dev->mutex != NULL) {
|
||||
xSemaphoreTake(dev->mutex, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
inline void esp_hidh_dev_unlock(esp_hidh_dev_t *dev)
|
||||
{
|
||||
if (dev && dev->mutex != NULL) {
|
||||
xSemaphoreGive(dev->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
inline void esp_hidh_dev_wait(esp_hidh_dev_t *dev)
|
||||
{
|
||||
if (dev && dev->semaphore != NULL) {
|
||||
xSemaphoreTake(dev->semaphore, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
inline void esp_hidh_dev_send(esp_hidh_dev_t *dev)
|
||||
{
|
||||
if (dev && dev->semaphore != NULL) {
|
||||
xSemaphoreGive(dev->semaphore);
|
||||
}
|
||||
}
|
||||
|
||||
esp_hidh_dev_report_t *esp_hidh_dev_get_report_by_handle(esp_hidh_dev_t *dev, uint16_t handle)
|
||||
{
|
||||
esp_hidh_dev_report_t *r = dev->reports;
|
||||
@@ -345,6 +562,19 @@ esp_hidh_dev_report_t *esp_hidh_dev_get_report_by_handle(esp_hidh_dev_t *dev, ui
|
||||
return NULL;
|
||||
}
|
||||
|
||||
esp_hidh_dev_report_t *esp_hidh_dev_get_report_by_id_type_proto(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type, uint8_t protocol_mode)
|
||||
{
|
||||
esp_hidh_dev_report_t *r = dev->reports;
|
||||
while (r) {
|
||||
if (r->map_index == map_index && r->report_type == report_type && r->report_id == report_id &&
|
||||
r->protocol_mode == protocol_mode) {
|
||||
return r;
|
||||
}
|
||||
r = r->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
esp_hidh_dev_report_t *esp_hidh_dev_get_report_by_id_and_type(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type)
|
||||
{
|
||||
esp_hidh_dev_report_t *r = dev->reports;
|
||||
@@ -369,11 +599,68 @@ esp_hidh_dev_report_t *esp_hidh_dev_get_input_report_by_id_and_proto(esp_hidh_de
|
||||
return NULL;
|
||||
}
|
||||
|
||||
esp_hidh_dev_report_t *esp_hidh_dev_get_input_report_by_len_and_proto(esp_hidh_dev_t *dev, size_t len, int protocol_mode)
|
||||
{
|
||||
esp_hidh_dev_report_t *r = dev->reports;
|
||||
while (r) {
|
||||
if (r->value_len == len && (r->report_type & 1) && r->protocol_mode == protocol_mode) {
|
||||
return r;
|
||||
}
|
||||
r = r->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* If no Report ID item tags are present in the Report descriptor, it
|
||||
* can be assumed that only one Input, Output, and Feature report structure exists
|
||||
* and together they represent all of the device’s data.
|
||||
*/
|
||||
esp_hidh_dev_report_t *esp_hidh_dev_get_input_report_by_proto_and_data(esp_hidh_dev_t *dev, int protocol_mode,
|
||||
size_t len, const uint8_t *data, bool *has_report_id)
|
||||
{
|
||||
esp_hidh_dev_report_t *r = dev->reports;
|
||||
*has_report_id = false;
|
||||
// first, assume data not include report id
|
||||
while (r) {
|
||||
if (r->value_len == len && r->report_id == 0 && (r->report_type & 1) &&
|
||||
r->protocol_mode == protocol_mode) {
|
||||
*has_report_id = false;
|
||||
break;
|
||||
}
|
||||
r = r->next;
|
||||
}
|
||||
// indicate data include report id
|
||||
if (r == NULL) {
|
||||
if (*data == 0) {
|
||||
ESP_LOGE(TAG, "data not include report id!");
|
||||
*has_report_id = false;
|
||||
return NULL;
|
||||
}
|
||||
r = dev->reports;
|
||||
while (r) {
|
||||
if (r->value_len == len + 1 && r->report_id == *data && (r->report_type & 1) &&
|
||||
r->protocol_mode == protocol_mode) {
|
||||
*has_report_id = true;
|
||||
break;
|
||||
}
|
||||
r = r->next;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static void esp_hidh_dev_resources_free(esp_hidh_dev_t *dev)
|
||||
{
|
||||
esp_hidh_dev_lock(dev);
|
||||
if (dev->semaphore) {
|
||||
vSemaphoreDelete(dev->semaphore);
|
||||
}
|
||||
if (dev->trans_timer) {
|
||||
esp_timer_stop(dev->trans_timer);
|
||||
esp_timer_delete(dev->trans_timer);
|
||||
dev->trans_timer = NULL;
|
||||
}
|
||||
free((void *)dev->config.device_name);
|
||||
free((void *)dev->config.manufacturer_name);
|
||||
free((void *)dev->config.serial_number);
|
||||
@@ -387,6 +674,10 @@ static void esp_hidh_dev_resources_free(esp_hidh_dev_t *dev)
|
||||
dev->reports = dev->reports->next;
|
||||
free(r);
|
||||
}
|
||||
esp_hidh_dev_unlock(dev);
|
||||
if (dev->mutex) {
|
||||
vSemaphoreDelete(dev->mutex);
|
||||
}
|
||||
free(dev);
|
||||
}
|
||||
|
||||
@@ -405,6 +696,13 @@ esp_hidh_dev_t *esp_hidh_dev_malloc()
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dev->mutex = xSemaphoreCreateMutex();
|
||||
if (dev->mutex == NULL) {
|
||||
ESP_LOGE(TAG, "malloc mutex failed");
|
||||
esp_hidh_dev_resources_free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lock_devices();
|
||||
TAILQ_INSERT_TAIL(&s_esp_hidh_devices, dev, devices);
|
||||
unlock_devices();
|
||||
@@ -412,7 +710,16 @@ esp_hidh_dev_t *esp_hidh_dev_malloc()
|
||||
return dev;
|
||||
}
|
||||
|
||||
/**
|
||||
* The `dev` is allocated by the internal function, and it should also be freed by the internal function. So, when the
|
||||
* user call this function, it will do nothing.
|
||||
*/
|
||||
esp_err_t esp_hidh_dev_free(esp_hidh_dev_t *dev)
|
||||
{
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_hidh_dev_free_inner(esp_hidh_dev_t *dev)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
|
||||
@@ -440,6 +747,20 @@ esp_err_t esp_hidh_dev_free(esp_hidh_dev_t *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void esp_hidh_dev_delay_free(void *arg)
|
||||
{
|
||||
esp_hidh_dev_t *d = NULL;
|
||||
esp_hidh_dev_t *next = NULL;
|
||||
lock_devices();
|
||||
TAILQ_FOREACH_SAFE(d, &s_esp_hidh_devices, devices, next) {
|
||||
if (!d->in_use) {
|
||||
TAILQ_REMOVE(&s_esp_hidh_devices, d, devices);
|
||||
esp_hidh_dev_resources_free(d);
|
||||
}
|
||||
}
|
||||
unlock_devices();
|
||||
}
|
||||
|
||||
#if CONFIG_BLUEDROID_ENABLED
|
||||
esp_hidh_dev_t *esp_hidh_dev_get_by_bda(esp_bd_addr_t bda)
|
||||
{
|
||||
@@ -455,7 +776,7 @@ esp_hidh_dev_t *esp_hidh_dev_get_by_bda(esp_bd_addr_t bda)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
esp_hidh_dev_t *esp_hidh_dev_get_by_handle(int handle)
|
||||
esp_hidh_dev_t *esp_hidh_dev_get_by_handle(uint8_t handle)
|
||||
{
|
||||
#if CONFIG_BT_HID_HOST_ENABLED
|
||||
esp_hidh_dev_t * d = NULL;
|
||||
@@ -486,4 +807,44 @@ esp_hidh_dev_t *esp_hidh_dev_get_by_conn_id(uint16_t conn_id)
|
||||
#endif /* CONFIG_GATTC_ENABLE */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* The deep copy data append the end of the esp_hidh_event_data_t, move the data pointer to the correct address. This is
|
||||
* a workaround way, it's better to use flexiable array in the interface.
|
||||
*/
|
||||
void esp_hidh_process_event_data_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id,
|
||||
void *event_data)
|
||||
{
|
||||
esp_hidh_event_t event = (esp_hidh_event_t)event_id;
|
||||
esp_hidh_event_data_t *param = (esp_hidh_event_data_t *)event_data;
|
||||
|
||||
switch (event) {
|
||||
case ESP_HIDH_INPUT_EVENT:
|
||||
if (param->input.length && param->input.data) {
|
||||
param->input.data = (uint8_t *)param + sizeof(esp_hidh_event_data_t);
|
||||
}
|
||||
break;
|
||||
case ESP_HIDH_FEATURE_EVENT:
|
||||
if (param->feature.length && param->feature.data) {
|
||||
param->feature.data = (uint8_t *)param + sizeof(esp_hidh_event_data_t);
|
||||
}
|
||||
break;
|
||||
case ESP_HIDH_OPEN_EVENT:
|
||||
if (param->open.status != ESP_OK) {
|
||||
if (s_esp_hidh_timer && !esp_timer_is_active(s_esp_hidh_timer) &&
|
||||
esp_timer_start_once(s_esp_hidh_timer, ESP_HIDH_DELAY_FREE_TO) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s set hidh timer failed!", __func__);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ESP_HIDH_CLOSE_EVENT:
|
||||
if (s_esp_hidh_timer && !esp_timer_is_active(s_esp_hidh_timer) &&
|
||||
esp_timer_start_once(s_esp_hidh_timer, ESP_HIDH_DELAY_FREE_TO) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s set hidh timer failed!", __func__);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BLUEDROID_ENABLED */
|
||||
|
@@ -0,0 +1,7 @@
|
||||
|
||||
# The following lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(bt_hid_mouse_device)
|
@@ -0,0 +1,8 @@
|
||||
#
|
||||
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||
# project subdirectory.
|
||||
#
|
||||
|
||||
PROJECT_NAME := bt_hid_mouse_device
|
||||
|
||||
include $(IDF_PATH)/make/project.mk
|
@@ -0,0 +1,11 @@
|
||||
| Supported Targets | ESP32 |
|
||||
| ----------------- | ----- |
|
||||
|
||||
# ESP-IDF HID Device over Bluetooth Classic Demo
|
||||
|
||||
Demo of HID Device over Bluetooth Classic.
|
||||
|
||||
This turns the device into a mouse, but can be altered to be any kind of HID device.
|
||||
|
||||
After loading the code, connect with a computer to a device broadcasting
|
||||
as "HID Mouse Example". The mouse should move left and right while they are connected.
|
@@ -0,0 +1,7 @@
|
||||
#set(COMPONENT_SRCS "main.c")
|
||||
#set(COMPONENT_ADD_INCLUDEDIRS "")
|
||||
|
||||
#register_component()
|
||||
|
||||
idf_component_register(SRCS "main.c"
|
||||
INCLUDE_DIRS ".")
|
@@ -0,0 +1,4 @@
|
||||
#
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
@@ -0,0 +1,436 @@
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp_hidd_api.h"
|
||||
#include "esp_bt_main.h"
|
||||
#include "esp_bt_device.h"
|
||||
#include "esp_bt.h"
|
||||
#include "esp_err.h"
|
||||
#include "nvs.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_gap_bt_api.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
#define BOOT_PROTO_MOUSE_RPT_ID 0x02
|
||||
typedef struct
|
||||
{
|
||||
esp_hidd_app_param_t app_param;
|
||||
esp_hidd_qos_param_t both_qos;
|
||||
uint8_t protocol_mode;
|
||||
SemaphoreHandle_t mouse_mutex;
|
||||
xTaskHandle mouse_task_hdl;
|
||||
uint8_t buffer[4];
|
||||
int8_t x_dir;
|
||||
} local_param_t;
|
||||
|
||||
static local_param_t s_local_param = {0};
|
||||
|
||||
bool check_report_id_type(uint8_t report_id, uint8_t report_type)
|
||||
{
|
||||
bool ret = false;
|
||||
xSemaphoreTake(s_local_param.mouse_mutex, portMAX_DELAY);
|
||||
do {
|
||||
if (report_type != ESP_HIDD_REPORT_TYPE_INPUT) {
|
||||
break;
|
||||
}
|
||||
if (s_local_param.protocol_mode == ESP_HIDD_BOOT_MODE) {
|
||||
if (report_id == BOOT_PROTO_MOUSE_RPT_ID) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (report_id == 0) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
|
||||
if (!ret) {
|
||||
if (s_local_param.protocol_mode == ESP_HIDD_BOOT_MODE) {
|
||||
esp_bt_hid_device_report_error(ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID);
|
||||
} else {
|
||||
esp_bt_hid_device_report_error(ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID);
|
||||
}
|
||||
}
|
||||
xSemaphoreGive(s_local_param.mouse_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// send the buttons, change in x, and change in y
|
||||
void send_mouse(uint8_t buttons, char dx, char dy, char wheel)
|
||||
{
|
||||
xSemaphoreTake(s_local_param.mouse_mutex, portMAX_DELAY);
|
||||
if (s_local_param.protocol_mode == ESP_HIDD_REPORT_MODE) {
|
||||
s_local_param.buffer[0] = buttons;
|
||||
s_local_param.buffer[1] = dx;
|
||||
s_local_param.buffer[2] = dy;
|
||||
s_local_param.buffer[3] = wheel;
|
||||
esp_bt_hid_device_send_report(ESP_HIDD_REPORT_TYPE_INTRDATA, 0x00, 4, s_local_param.buffer);
|
||||
} else if (s_local_param.protocol_mode == ESP_HIDD_BOOT_MODE) {
|
||||
s_local_param.buffer[0] = buttons;
|
||||
s_local_param.buffer[1] = dx;
|
||||
s_local_param.buffer[2] = dy;
|
||||
esp_bt_hid_device_send_report(ESP_HIDD_REPORT_TYPE_INTRDATA, BOOT_PROTO_MOUSE_RPT_ID, 3, s_local_param.buffer);
|
||||
}
|
||||
xSemaphoreGive(s_local_param.mouse_mutex);
|
||||
}
|
||||
|
||||
// move the mouse left and right
|
||||
void mouse_move_task(void* pvParameters) {
|
||||
const char* TAG = "mouse_move_task";
|
||||
|
||||
ESP_LOGI(TAG, "starting");
|
||||
for(;;) {
|
||||
s_local_param.x_dir = 1;
|
||||
int8_t step = 10;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
xSemaphoreTake(s_local_param.mouse_mutex, portMAX_DELAY);
|
||||
s_local_param.x_dir *= -1;
|
||||
xSemaphoreGive(s_local_param.mouse_mutex);
|
||||
for (int j = 0; j < 100; j++) {
|
||||
send_mouse(0, s_local_param.x_dir * step, 0, 0);
|
||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_bt_address(void) {
|
||||
const char* TAG = "bt_address";
|
||||
const uint8_t* bd_addr;
|
||||
|
||||
bd_addr = esp_bt_dev_get_address();
|
||||
ESP_LOGI(TAG, "my bluetooth address is %02X:%02X:%02X:%02X:%02X:%02X",
|
||||
bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
|
||||
}
|
||||
|
||||
// a generic mouse descriptor
|
||||
uint8_t hid_descriptor_mouse_boot_mode[] = {
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
0x09, 0x02, // USAGE (Mouse)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
|
||||
0x09, 0x01, // USAGE (Pointer)
|
||||
0xa1, 0x00, // COLLECTION (Physical)
|
||||
|
||||
0x05, 0x09, // USAGE_PAGE (Button)
|
||||
0x19, 0x01, // USAGE_MINIMUM (Button 1)
|
||||
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||||
0x95, 0x03, // REPORT_COUNT (3)
|
||||
0x75, 0x01, // REPORT_SIZE (1)
|
||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x75, 0x05, // REPORT_SIZE (5)
|
||||
0x81, 0x03, // INPUT (Cnst,Var,Abs)
|
||||
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
0x09, 0x30, // USAGE (X)
|
||||
0x09, 0x31, // USAGE (Y)
|
||||
0x09, 0x38, // USAGE (Wheel)
|
||||
0x15, 0x81, // LOGICAL_MINIMUM (-127)
|
||||
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x95, 0x03, // REPORT_COUNT (3)
|
||||
0x81, 0x06, // INPUT (Data,Var,Rel)
|
||||
|
||||
0xc0, // END_COLLECTION
|
||||
0xc0 // END_COLLECTION
|
||||
};
|
||||
int hid_descriptor_mouse_boot_mode_len = sizeof(hid_descriptor_mouse_boot_mode);
|
||||
|
||||
void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param)
|
||||
{
|
||||
const char* TAG = "esp_bt_gap_cb";
|
||||
switch (event) {
|
||||
case ESP_BT_GAP_AUTH_CMPL_EVT:{
|
||||
if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) {
|
||||
ESP_LOGI(TAG, "authentication success: %s", param->auth_cmpl.device_name);
|
||||
esp_log_buffer_hex(TAG, param->auth_cmpl.bda, ESP_BD_ADDR_LEN);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "authentication failed, status:%d", param->auth_cmpl.stat);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_BT_GAP_PIN_REQ_EVT:{
|
||||
ESP_LOGI(TAG, "ESP_BT_GAP_PIN_REQ_EVT min_16_digit:%d", param->pin_req.min_16_digit);
|
||||
if (param->pin_req.min_16_digit) {
|
||||
ESP_LOGI(TAG, "Input pin code: 0000 0000 0000 0000");
|
||||
esp_bt_pin_code_t pin_code = {0};
|
||||
esp_bt_gap_pin_reply(param->pin_req.bda, true, 16, pin_code);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Input pin code: 1234");
|
||||
esp_bt_pin_code_t pin_code;
|
||||
pin_code[0] = '1';
|
||||
pin_code[1] = '2';
|
||||
pin_code[2] = '3';
|
||||
pin_code[3] = '4';
|
||||
esp_bt_gap_pin_reply(param->pin_req.bda, true, 4, pin_code);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#if (CONFIG_BT_SSP_ENABLED == true)
|
||||
case ESP_BT_GAP_CFM_REQ_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %d", param->cfm_req.num_val);
|
||||
esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true);
|
||||
break;
|
||||
case ESP_BT_GAP_KEY_NOTIF_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BT_GAP_KEY_NOTIF_EVT passkey:%d", param->key_notif.passkey);
|
||||
break;
|
||||
case ESP_BT_GAP_KEY_REQ_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BT_GAP_KEY_REQ_EVT Please enter passkey!");
|
||||
break;
|
||||
#endif
|
||||
case ESP_BT_GAP_MODE_CHG_EVT:
|
||||
ESP_LOGI(TAG, "ESP_BT_GAP_MODE_CHG_EVT mode:%d", param->mode_chg.mode);
|
||||
break;
|
||||
default:
|
||||
ESP_LOGI(TAG, "event: %d", event);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void bt_app_task_start_up(void)
|
||||
{
|
||||
s_local_param.mouse_mutex = xSemaphoreCreateMutex();
|
||||
memset(s_local_param.buffer, 0, 4);
|
||||
xTaskCreate(mouse_move_task, "mouse_move_task", 2 * 1024, NULL, configMAX_PRIORITIES - 3, &s_local_param.mouse_task_hdl);
|
||||
return;
|
||||
}
|
||||
|
||||
void bt_app_task_shut_down(void)
|
||||
{
|
||||
if (s_local_param.mouse_task_hdl) {
|
||||
vTaskDelete(s_local_param.mouse_task_hdl);
|
||||
s_local_param.mouse_task_hdl = NULL;
|
||||
}
|
||||
|
||||
if (s_local_param.mouse_mutex) {
|
||||
vSemaphoreDelete(s_local_param.mouse_mutex);
|
||||
s_local_param.mouse_mutex = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void esp_bt_hidd_cb(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param)
|
||||
{
|
||||
static const char* TAG = "esp_bt_hidd_cb";
|
||||
switch (event) {
|
||||
case ESP_HIDD_INIT_EVT:
|
||||
if (param->init.status == ESP_HIDD_SUCCESS) {
|
||||
ESP_LOGI(TAG, "setting hid parameters");
|
||||
esp_bt_hid_device_register_app(&s_local_param.app_param, &s_local_param.both_qos, &s_local_param.both_qos);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "init hidd failed!");
|
||||
}
|
||||
break;
|
||||
case ESP_HIDD_DEINIT_EVT:
|
||||
break;
|
||||
case ESP_HIDD_REGISTER_APP_EVT:
|
||||
if (param->register_app.status == ESP_HIDD_SUCCESS) {
|
||||
ESP_LOGI(TAG, "setting hid parameters success!");
|
||||
ESP_LOGI(TAG, "setting to connectable, discoverable");
|
||||
esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
|
||||
if (param->register_app.in_use && param->register_app.bd_addr != NULL) {
|
||||
ESP_LOGI(TAG, "start virtual cable plug!");
|
||||
esp_bt_hid_device_connect(param->register_app.bd_addr);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "setting hid parameters failed!");
|
||||
}
|
||||
break;
|
||||
case ESP_HIDD_UNREGISTER_APP_EVT:
|
||||
if (param->unregister_app.status == ESP_HIDD_SUCCESS) {
|
||||
ESP_LOGI(TAG, "unregister app success!");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "unregister app failed!");
|
||||
}
|
||||
break;
|
||||
case ESP_HIDD_OPEN_EVT:
|
||||
if (param->open.status == ESP_HIDD_SUCCESS) {
|
||||
if (param->open.conn_status == ESP_HIDD_CONN_STATE_CONNECTING) {
|
||||
ESP_LOGI(TAG, "connecting...");
|
||||
} else if (param->open.conn_status == ESP_HIDD_CONN_STATE_CONNECTED) {
|
||||
ESP_LOGI(TAG, "connected to %02x:%02x:%02x:%02x:%02x:%02x", param->open.bd_addr[0],
|
||||
param->open.bd_addr[1], param->open.bd_addr[2], param->open.bd_addr[3], param->open.bd_addr[4],
|
||||
param->open.bd_addr[5]);
|
||||
bt_app_task_start_up();
|
||||
ESP_LOGI(TAG, "making self non-discoverable and non-connectable.");
|
||||
esp_bt_gap_set_scan_mode(ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "unknown connection status");
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "open failed!");
|
||||
}
|
||||
break;
|
||||
case ESP_HIDD_CLOSE_EVT:
|
||||
ESP_LOGI(TAG, "ESP_HIDD_CLOSE_EVT");
|
||||
if (param->close.status == ESP_HIDD_SUCCESS) {
|
||||
if (param->close.conn_status == ESP_HIDD_CONN_STATE_DISCONNECTING) {
|
||||
ESP_LOGI(TAG, "disconnecting...");
|
||||
} else if (param->close.conn_status == ESP_HIDD_CONN_STATE_DISCONNECTED) {
|
||||
ESP_LOGI(TAG, "disconnected!");
|
||||
bt_app_task_shut_down();
|
||||
ESP_LOGI(TAG, "making self discoverable and connectable again.");
|
||||
esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "unknown connection status");
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "close failed!");
|
||||
}
|
||||
break;
|
||||
case ESP_HIDD_SEND_REPORT_EVT:
|
||||
ESP_LOGI(TAG, "ESP_HIDD_SEND_REPORT_EVT id:0x%02x, type:%d", param->send_report.report_id,
|
||||
param->send_report.report_type);
|
||||
break;
|
||||
case ESP_HIDD_REPORT_ERR_EVT:
|
||||
ESP_LOGI(TAG, "ESP_HIDD_REPORT_ERR_EVT");
|
||||
break;
|
||||
case ESP_HIDD_GET_REPORT_EVT:
|
||||
ESP_LOGI(TAG, "ESP_HIDD_GET_REPORT_EVT id:0x%02x, type:%d, size:%d", param->get_report.report_id,
|
||||
param->get_report.report_type, param->get_report.buffer_size);
|
||||
if (check_report_id_type(param->get_report.report_id, param->get_report.report_type)) {
|
||||
xSemaphoreTake(s_local_param.mouse_mutex, portMAX_DELAY);
|
||||
if (s_local_param.protocol_mode == ESP_HIDD_REPORT_MODE) {
|
||||
esp_bt_hid_device_send_report(param->get_report.report_type, 0x00, 4, s_local_param.buffer);
|
||||
} else if (s_local_param.protocol_mode == ESP_HIDD_BOOT_MODE) {
|
||||
esp_bt_hid_device_send_report(param->get_report.report_type, 0x02, 3, s_local_param.buffer);
|
||||
}
|
||||
xSemaphoreGive(s_local_param.mouse_mutex);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "check_report_id failed!");
|
||||
}
|
||||
break;
|
||||
case ESP_HIDD_SET_REPORT_EVT:
|
||||
ESP_LOGI(TAG, "ESP_HIDD_SET_REPORT_EVT");
|
||||
break;
|
||||
case ESP_HIDD_SET_PROTOCOL_EVT:
|
||||
ESP_LOGI(TAG, "ESP_HIDD_SET_PROTOCOL_EVT");
|
||||
if (param->set_protocol.protocol_mode == ESP_HIDD_BOOT_MODE) {
|
||||
ESP_LOGI(TAG, " - boot protocol");
|
||||
xSemaphoreTake(s_local_param.mouse_mutex, portMAX_DELAY);
|
||||
s_local_param.x_dir = -1;
|
||||
xSemaphoreGive(s_local_param.mouse_mutex);
|
||||
} else if (param->set_protocol.protocol_mode == ESP_HIDD_REPORT_MODE) {
|
||||
ESP_LOGI(TAG, " - report protocol");
|
||||
}
|
||||
xSemaphoreTake(s_local_param.mouse_mutex, portMAX_DELAY);
|
||||
s_local_param.protocol_mode = param->set_protocol.protocol_mode;
|
||||
xSemaphoreGive(s_local_param.mouse_mutex);
|
||||
break;
|
||||
case ESP_HIDD_INTR_DATA_EVT:
|
||||
ESP_LOGI(TAG, "ESP_HIDD_INTR_DATA_EVT");
|
||||
break;
|
||||
case ESP_HIDD_VC_UNPLUG_EVT:
|
||||
ESP_LOGI(TAG, "ESP_HIDD_VC_UNPLUG_EVT");
|
||||
if (param->vc_unplug.status == ESP_HIDD_SUCCESS) {
|
||||
if (param->close.conn_status == ESP_HIDD_CONN_STATE_DISCONNECTED) {
|
||||
ESP_LOGI(TAG, "disconnected!");
|
||||
bt_app_task_shut_down();
|
||||
ESP_LOGI(TAG, "making self discoverable and connectable again.");
|
||||
esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "unknown connection status");
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "close failed!");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void app_main(void) {
|
||||
const char* TAG = "app_main";
|
||||
esp_err_t ret;
|
||||
|
||||
s_local_param.app_param.name = "Mouse";
|
||||
s_local_param.app_param.description = "Mouse Example";
|
||||
s_local_param.app_param.provider = "ESP32";
|
||||
s_local_param.app_param.subclass = ESP_HID_CLASS_MIC;
|
||||
s_local_param.app_param.desc_list = hid_descriptor_mouse_boot_mode;
|
||||
s_local_param.app_param.desc_list_len = hid_descriptor_mouse_boot_mode_len;
|
||||
memset(&s_local_param.both_qos, 0, sizeof(esp_hidd_qos_param_t)); // don't set the qos parameters
|
||||
s_local_param.protocol_mode = ESP_HIDD_REPORT_MODE;
|
||||
|
||||
ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK( ret );
|
||||
|
||||
ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_BLE));
|
||||
|
||||
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||
if ((ret = esp_bt_controller_init(&bt_cfg)) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "initialize controller failed: %s\n", esp_err_to_name(ret));
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ret = esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT)) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "enable controller failed: %s\n", esp_err_to_name(ret));
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ret = esp_bluedroid_init()) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "initialize bluedroid failed: %s\n", esp_err_to_name(ret));
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ret = esp_bluedroid_enable()) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "enable bluedroid failed: %s\n", esp_err_to_name(ret));
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ret = esp_bt_gap_register_callback(esp_bt_gap_cb)) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "gap register failed: %s\n", esp_err_to_name(ret));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ESP_LOGI(TAG, "setting device name");
|
||||
esp_bt_dev_set_device_name("HID Mouse Example");
|
||||
|
||||
ESP_LOGI(TAG, "setting cod major, peripheral");
|
||||
esp_bt_cod_t cod;
|
||||
cod.major = ESP_BT_COD_MAJOR_DEV_PERIPHERAL;
|
||||
esp_bt_gap_set_cod(cod ,ESP_BT_SET_COD_MAJOR_MINOR);
|
||||
|
||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||
|
||||
ESP_LOGI(TAG, "register hid device callback");
|
||||
esp_bt_hid_device_register_callback(esp_bt_hidd_cb);
|
||||
|
||||
ESP_LOGI(TAG, "starting hid device");
|
||||
esp_bt_hid_device_init();
|
||||
|
||||
#if (CONFIG_BT_SSP_ENABLED == true)
|
||||
/* Set default parameters for Secure Simple Pairing */
|
||||
esp_bt_sp_param_t param_type = ESP_BT_SP_IOCAP_MODE;
|
||||
esp_bt_io_cap_t iocap = ESP_BT_IO_CAP_NONE;
|
||||
esp_bt_gap_set_security_param(param_type, &iocap, sizeof(uint8_t));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set default parameters for Legacy Pairing
|
||||
* Use variable pin, input pin code when pairing
|
||||
*/
|
||||
esp_bt_pin_type_t pin_type = ESP_BT_PIN_TYPE_VARIABLE;
|
||||
esp_bt_pin_code_t pin_code;
|
||||
esp_bt_gap_set_pin(pin_type, 0, pin_code);
|
||||
|
||||
print_bt_address();
|
||||
ESP_LOGI(TAG, "exiting");
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
CONFIG_BT_ENABLED=y
|
||||
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=n
|
||||
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=y
|
||||
CONFIG_BTDM_CTRL_MODE_BTDM=n
|
||||
CONFIG_BT_CLASSIC_ENABLED=y
|
||||
CONFIG_BT_HID_ENABLED=y
|
||||
CONFIG_BT_HID_DEVICE_ENABLED=y
|
@@ -1,5 +1,23 @@
|
||||
| Supported Targets | ESP32 |
|
||||
| ----------------- | ----- |
|
||||
|
||||
# ESP-IDF BLE HID Device Demo
|
||||
# ESP-IDF BT/BLE HID Device Demo
|
||||
|
||||
This demo use APIs which esp_hid component provided to create a BT, BLE or Bluetooth dual mode hid device. Users can choose mode by setting `HID_DEV_MODE`.
|
||||
|
||||
The BT hid device plays as a mouse. When the connection is successfully established, users can follow the usage below to operate the 'mouse'.
|
||||
```
|
||||
########################################################################
|
||||
BT hid mouse demo usage:
|
||||
You can input these value to simulate mouse: 'q', 'w', 'e', 'a', 's', 'd', 'h'
|
||||
q -- click the left key
|
||||
w -- move up
|
||||
e -- click the right key
|
||||
a -- move left
|
||||
s -- move down
|
||||
d -- move right
|
||||
h -- show the help
|
||||
########################################################################
|
||||
```
|
||||
|
||||
The BLE hid device plays as a remote control. When the connection is successfully established, the remote control will set volume up and down periodically.
|
||||
|
@@ -1,6 +1,5 @@
|
||||
set(srcs "esp_hid_device_main.c"
|
||||
"esp_hid_gap.c")
|
||||
|
||||
set(include_dirs ".")
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
|
@@ -18,9 +18,11 @@
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_bt.h"
|
||||
#include "esp_bt_defs.h"
|
||||
#if CONFIG_BT_BLE_ENABLED
|
||||
#include "esp_gap_ble_api.h"
|
||||
#include "esp_gatts_api.h"
|
||||
#include "esp_gatt_defs.h"
|
||||
#endif
|
||||
#include "esp_bt_main.h"
|
||||
#include "esp_bt_device.h"
|
||||
|
||||
@@ -29,6 +31,16 @@
|
||||
|
||||
static const char *TAG = "HID_DEV_DEMO";
|
||||
|
||||
typedef struct
|
||||
{
|
||||
xTaskHandle task_hdl;
|
||||
esp_hidd_dev_t *hid_dev;
|
||||
uint8_t protocol_mode;
|
||||
uint8_t *buffer;
|
||||
} local_param_t;
|
||||
|
||||
#if CONFIG_BT_BLE_ENABLED
|
||||
static local_param_t s_ble_hid_param = {0};
|
||||
const unsigned char hidapiReportMap[] = { //8 bytes input, 8 bytes feature
|
||||
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
|
||||
0x0A, 0x00, 0x01, // Usage (0x0100)
|
||||
@@ -111,7 +123,7 @@ const unsigned char mediaReportMap[] = {
|
||||
0xC0, // End Collection
|
||||
};
|
||||
|
||||
static esp_hid_raw_report_map_t report_maps[] = {
|
||||
static esp_hid_raw_report_map_t ble_report_maps[] = {
|
||||
{
|
||||
.data = hidapiReportMap,
|
||||
.len = sizeof(hidapiReportMap)
|
||||
@@ -122,20 +134,17 @@ static esp_hid_raw_report_map_t report_maps[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static esp_hid_device_config_t hid_config = {
|
||||
static esp_hid_device_config_t ble_hid_config = {
|
||||
.vendor_id = 0x16C0,
|
||||
.product_id = 0x05DF,
|
||||
.version = 0x0100,
|
||||
.device_name = "ESP BLE HID2",
|
||||
.manufacturer_name = "Espressif",
|
||||
.serial_number = "1234567890",
|
||||
.report_maps = report_maps,
|
||||
.report_maps = ble_report_maps,
|
||||
.report_maps_len = 2
|
||||
};
|
||||
|
||||
static esp_hidd_dev_t *hid_dev = NULL;
|
||||
static bool dev_connected = false;
|
||||
|
||||
#define HID_CC_RPT_MUTE 1
|
||||
#define HID_CC_RPT_POWER 2
|
||||
#define HID_CC_RPT_LAST 3
|
||||
@@ -283,14 +292,48 @@ void esp_hidd_send_consumer_value(uint8_t key_cmd, bool key_pressed)
|
||||
break;
|
||||
}
|
||||
}
|
||||
esp_hidd_dev_input_set(hid_dev, 1, HID_RPT_ID_CC_IN, buffer, HID_CC_IN_RPT_LEN);
|
||||
esp_hidd_dev_input_set(s_ble_hid_param.hid_dev, 1, HID_RPT_ID_CC_IN, buffer, HID_CC_IN_RPT_LEN);
|
||||
return;
|
||||
}
|
||||
|
||||
static void hidd_event_callback(void *handler_args, esp_event_base_t base, int32_t id, void *event_data)
|
||||
void ble_hid_demo_task(void *pvParameters)
|
||||
{
|
||||
static bool send_volum_up = false;
|
||||
while (1) {
|
||||
ESP_LOGI(TAG, "Send the volume");
|
||||
if (send_volum_up) {
|
||||
esp_hidd_send_consumer_value(HID_CONSUMER_VOLUME_UP, true);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
esp_hidd_send_consumer_value(HID_CONSUMER_VOLUME_UP, false);
|
||||
} else {
|
||||
esp_hidd_send_consumer_value(HID_CONSUMER_VOLUME_DOWN, true);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
esp_hidd_send_consumer_value(HID_CONSUMER_VOLUME_DOWN, false);
|
||||
}
|
||||
send_volum_up = !send_volum_up;
|
||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
void ble_hid_task_start_up(void)
|
||||
{
|
||||
xTaskCreate(ble_hid_demo_task, "ble_hid_demo_task", 2 * 1024, NULL, configMAX_PRIORITIES - 3,
|
||||
&s_ble_hid_param.task_hdl);
|
||||
}
|
||||
|
||||
void ble_hid_task_shut_down(void)
|
||||
{
|
||||
if (s_ble_hid_param.task_hdl) {
|
||||
vTaskDelete(s_ble_hid_param.task_hdl);
|
||||
s_ble_hid_param.task_hdl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void ble_hidd_event_callback(void *handler_args, esp_event_base_t base, int32_t id, void *event_data)
|
||||
{
|
||||
esp_hidd_event_t event = (esp_hidd_event_t)id;
|
||||
esp_hidd_event_data_t *param = (esp_hidd_event_data_t *)event_data;
|
||||
static const char *TAG = "HID_DEV_BLE";
|
||||
|
||||
switch (event) {
|
||||
case ESP_HIDD_START_EVENT: {
|
||||
@@ -300,7 +343,7 @@ static void hidd_event_callback(void *handler_args, esp_event_base_t base, int32
|
||||
}
|
||||
case ESP_HIDD_CONNECT_EVENT: {
|
||||
ESP_LOGI(TAG, "CONNECT");
|
||||
dev_connected = true;//todo: this should be on auth_complete (in GAP)
|
||||
ble_hid_task_start_up();//todo: this should be on auth_complete (in GAP)
|
||||
break;
|
||||
}
|
||||
case ESP_HIDD_PROTOCOL_MODE_EVENT: {
|
||||
@@ -323,7 +366,7 @@ static void hidd_event_callback(void *handler_args, esp_event_base_t base, int32
|
||||
}
|
||||
case ESP_HIDD_DISCONNECT_EVENT: {
|
||||
ESP_LOGI(TAG, "DISCONNECT: %s", esp_hid_disconnect_reason_str(esp_hidd_dev_transport_get(param->disconnect.dev), param->disconnect.reason));
|
||||
dev_connected = false;
|
||||
ble_hid_task_shut_down();
|
||||
esp_hid_ble_gap_adv_start();
|
||||
break;
|
||||
}
|
||||
@@ -336,31 +379,204 @@ static void hidd_event_callback(void *handler_args, esp_event_base_t base, int32
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
void hid_demo_task(void *pvParameters)
|
||||
#if CONFIG_BT_HID_DEVICE_ENABLED
|
||||
static local_param_t s_bt_hid_param = {0};
|
||||
const unsigned char mouseReportMap[] = {
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
0x09, 0x02, // USAGE (Mouse)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
|
||||
0x09, 0x01, // USAGE (Pointer)
|
||||
0xa1, 0x00, // COLLECTION (Physical)
|
||||
|
||||
0x05, 0x09, // USAGE_PAGE (Button)
|
||||
0x19, 0x01, // USAGE_MINIMUM (Button 1)
|
||||
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||||
0x95, 0x03, // REPORT_COUNT (3)
|
||||
0x75, 0x01, // REPORT_SIZE (1)
|
||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x75, 0x05, // REPORT_SIZE (5)
|
||||
0x81, 0x03, // INPUT (Cnst,Var,Abs)
|
||||
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
0x09, 0x30, // USAGE (X)
|
||||
0x09, 0x31, // USAGE (Y)
|
||||
0x09, 0x38, // USAGE (Wheel)
|
||||
0x15, 0x81, // LOGICAL_MINIMUM (-127)
|
||||
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x95, 0x03, // REPORT_COUNT (3)
|
||||
0x81, 0x06, // INPUT (Data,Var,Rel)
|
||||
|
||||
0xc0, // END_COLLECTION
|
||||
0xc0 // END_COLLECTION
|
||||
};
|
||||
|
||||
static esp_hid_raw_report_map_t bt_report_maps[] = {
|
||||
{
|
||||
.data = mouseReportMap,
|
||||
.len = sizeof(mouseReportMap)
|
||||
},
|
||||
};
|
||||
|
||||
static esp_hid_device_config_t bt_hid_config = {
|
||||
.vendor_id = 0x16C0,
|
||||
.product_id = 0x05DF,
|
||||
.version = 0x0100,
|
||||
.device_name = "ESP BT HID1",
|
||||
.manufacturer_name = "Espressif",
|
||||
.serial_number = "1234567890",
|
||||
.report_maps = bt_report_maps,
|
||||
.report_maps_len = 1
|
||||
};
|
||||
|
||||
// send the buttons, change in x, and change in y
|
||||
void send_mouse(uint8_t buttons, char dx, char dy, char wheel)
|
||||
{
|
||||
static bool send_volum_up = false;
|
||||
static uint8_t buffer[4] = {0};
|
||||
buffer[0] = buttons;
|
||||
buffer[1] = dx;
|
||||
buffer[2] = dy;
|
||||
buffer[3] = wheel;
|
||||
esp_hidd_dev_input_set(s_bt_hid_param.hid_dev, 0, 0, buffer, 4);
|
||||
}
|
||||
|
||||
void bt_hid_demo_task(void *pvParameters)
|
||||
{
|
||||
static const char* help_string = "########################################################################\n"\
|
||||
"BT hid mouse demo usage:\n"\
|
||||
"You can input these value to simulate mouse: 'q', 'w', 'e', 'a', 's', 'd', 'h'\n"\
|
||||
"q -- click the left key\n"\
|
||||
"w -- move up\n"\
|
||||
"e -- click the right key\n"\
|
||||
"a -- move left\n"\
|
||||
"s -- move down\n"\
|
||||
"d -- move right\n"\
|
||||
"h -- show the help\n"\
|
||||
"########################################################################\n";
|
||||
printf("%s\n", help_string);
|
||||
char c;
|
||||
while (1) {
|
||||
if (dev_connected) {
|
||||
ESP_LOGI(TAG, "Send the volume");
|
||||
if (send_volum_up) {
|
||||
esp_hidd_send_consumer_value(HID_CONSUMER_VOLUME_UP, true);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
esp_hidd_send_consumer_value(HID_CONSUMER_VOLUME_UP, false);
|
||||
} else {
|
||||
esp_hidd_send_consumer_value(HID_CONSUMER_VOLUME_DOWN, true);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
esp_hidd_send_consumer_value(HID_CONSUMER_VOLUME_DOWN, false);
|
||||
}
|
||||
send_volum_up = !send_volum_up;
|
||||
c = fgetc(stdin);
|
||||
switch (c) {
|
||||
case 'q':
|
||||
send_mouse(1, 0, 0, 0);
|
||||
break;
|
||||
case 'w':
|
||||
send_mouse(0, 0, -10, 0);
|
||||
break;
|
||||
case 'e':
|
||||
send_mouse(2, 0, 0, 0);
|
||||
break;
|
||||
case 'a':
|
||||
send_mouse(0, -10, 0, 0);
|
||||
break;
|
||||
case 's':
|
||||
send_mouse(0, 0, 10, 0);
|
||||
break;
|
||||
case 'd':
|
||||
send_mouse(0, 10, 0, 0);
|
||||
break;
|
||||
case 'h':
|
||||
printf("%s\n", help_string);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
void bt_hid_task_start_up(void)
|
||||
{
|
||||
xTaskCreate(bt_hid_demo_task, "bt_hid_demo_task", 2 * 1024, NULL, configMAX_PRIORITIES - 3, &s_bt_hid_param.task_hdl);
|
||||
return;
|
||||
}
|
||||
|
||||
void bt_hid_task_shut_down(void)
|
||||
{
|
||||
if (s_bt_hid_param.task_hdl) {
|
||||
vTaskDelete(s_bt_hid_param.task_hdl);
|
||||
s_bt_hid_param.task_hdl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void bt_hidd_event_callback(void *handler_args, esp_event_base_t base, int32_t id, void *event_data)
|
||||
{
|
||||
esp_hidd_event_t event = (esp_hidd_event_t)id;
|
||||
esp_hidd_event_data_t *param = (esp_hidd_event_data_t *)event_data;
|
||||
static const char *TAG = "HID_DEV_BT";
|
||||
|
||||
switch (event) {
|
||||
case ESP_HIDD_START_EVENT: {
|
||||
if (param->start.status == ESP_OK) {
|
||||
ESP_LOGI(TAG, "START OK");
|
||||
ESP_LOGI(TAG, "Setting to connectable, discoverable");
|
||||
esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "START failed!");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_HIDD_CONNECT_EVENT: {
|
||||
if (param->connect.status == ESP_OK) {
|
||||
ESP_LOGI(TAG, "CONNECT OK");
|
||||
ESP_LOGI(TAG, "Setting to non-connectable, non-discoverable");
|
||||
esp_bt_gap_set_scan_mode(ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE);
|
||||
bt_hid_task_start_up();
|
||||
} else {
|
||||
ESP_LOGE(TAG, "CONNECT failed!");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_HIDD_PROTOCOL_MODE_EVENT: {
|
||||
ESP_LOGI(TAG, "PROTOCOL MODE[%u]: %s", param->protocol_mode.map_index, param->protocol_mode.protocol_mode ? "REPORT" : "BOOT");
|
||||
break;
|
||||
}
|
||||
case ESP_HIDD_OUTPUT_EVENT: {
|
||||
ESP_LOGI(TAG, "OUTPUT[%u]: %8s ID: %2u, Len: %d, Data:", param->output.map_index, esp_hid_usage_str(param->output.usage), param->output.report_id, param->output.length);
|
||||
ESP_LOG_BUFFER_HEX(TAG, param->output.data, param->output.length);
|
||||
break;
|
||||
}
|
||||
case ESP_HIDD_FEATURE_EVENT: {
|
||||
ESP_LOGI(TAG, "FEATURE[%u]: %8s ID: %2u, Len: %d, Data:", param->feature.map_index, esp_hid_usage_str(param->feature.usage), param->feature.report_id, param->feature.length);
|
||||
ESP_LOG_BUFFER_HEX(TAG, param->feature.data, param->feature.length);
|
||||
break;
|
||||
}
|
||||
case ESP_HIDD_DISCONNECT_EVENT: {
|
||||
if (param->disconnect.status == ESP_OK) {
|
||||
ESP_LOGI(TAG, "DISCONNECT OK");
|
||||
bt_hid_task_shut_down();
|
||||
ESP_LOGI(TAG, "Setting to connectable, discoverable again");
|
||||
esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "DISCONNECT failed!");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_HIDD_STOP_EVENT: {
|
||||
ESP_LOGI(TAG, "STOP");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
esp_err_t ret;
|
||||
#if HID_DEV_MODE == HIDD_IDLE_MODE
|
||||
ESP_LOGE(TAG, "Please turn on BT HID device or BLE!");
|
||||
return;
|
||||
#endif
|
||||
ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
@@ -368,23 +584,33 @@ void app_main(void)
|
||||
}
|
||||
ESP_ERROR_CHECK( ret );
|
||||
|
||||
#if CONFIG_BT_CLASSIC_ENABLED
|
||||
ret = esp_hid_gap_init(ESP_BT_MODE_BTDM);
|
||||
#else
|
||||
ret = esp_hid_gap_init(ESP_BT_MODE_BLE);
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "setting hid gap, mode:%d", HID_DEV_MODE);
|
||||
ret = esp_hid_gap_init(HID_DEV_MODE);
|
||||
ESP_ERROR_CHECK( ret );
|
||||
|
||||
ret = esp_hid_ble_gap_adv_init(ESP_HID_APPEARANCE_GENERIC, hid_config.device_name);
|
||||
#if CONFIG_BT_BLE_ENABLED
|
||||
ret = esp_hid_ble_gap_adv_init(ESP_HID_APPEARANCE_GENERIC, ble_hid_config.device_name);
|
||||
ESP_ERROR_CHECK( ret );
|
||||
|
||||
if ((ret = esp_ble_gatts_register_callback(esp_hidd_gatts_event_handler)) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "GATTS register callback failed: %d", ret);
|
||||
return;
|
||||
}
|
||||
ESP_LOGI(TAG, "setting ble device");
|
||||
ESP_ERROR_CHECK(
|
||||
esp_hidd_dev_init(&ble_hid_config, ESP_HID_TRANSPORT_BLE, ble_hidd_event_callback, &s_ble_hid_param.hid_dev));
|
||||
#endif
|
||||
|
||||
ESP_ERROR_CHECK( esp_hidd_dev_init(&hid_config, ESP_HID_TRANSPORT_BLE, hidd_event_callback, &hid_dev) );
|
||||
xTaskCreate(&hid_demo_task, "hid_task", 2048, NULL, 2, NULL);
|
||||
|
||||
#if CONFIG_BT_HID_DEVICE_ENABLED
|
||||
ESP_LOGI(TAG, "setting device name");
|
||||
esp_bt_dev_set_device_name(bt_hid_config.device_name);
|
||||
ESP_LOGI(TAG, "setting cod major, peripheral");
|
||||
esp_bt_cod_t cod;
|
||||
cod.major = ESP_BT_COD_MAJOR_DEV_PERIPHERAL;
|
||||
esp_bt_gap_set_cod(cod, ESP_BT_SET_COD_MAJOR_MINOR);
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
ESP_LOGI(TAG, "setting bt device");
|
||||
ESP_ERROR_CHECK(
|
||||
esp_hidd_dev_init(&bt_hid_config, ESP_HID_TRANSPORT_BT, bt_hidd_event_callback, &s_bt_hid_param.hid_dev));
|
||||
#endif
|
||||
}
|
||||
|
@@ -71,6 +71,7 @@ const char *bt_gap_evt_str(uint8_t event)
|
||||
return bt_gap_evt_names[event];
|
||||
}
|
||||
|
||||
#if CONFIG_BT_BLE_ENABLED
|
||||
const char *esp_ble_key_type_str(esp_ble_key_type_t key_type)
|
||||
{
|
||||
const char *key_str = NULL;
|
||||
@@ -109,6 +110,7 @@ const char *esp_ble_key_type_str(esp_ble_key_type_t key_type)
|
||||
}
|
||||
return key_str;
|
||||
}
|
||||
#endif /* CONFIG_BT_BLE_ENABLED */
|
||||
|
||||
void esp_hid_scan_results_free(esp_hid_scan_result_t *results)
|
||||
{
|
||||
@@ -123,6 +125,7 @@ void esp_hid_scan_results_free(esp_hid_scan_result_t *results)
|
||||
}
|
||||
}
|
||||
|
||||
#if (CONFIG_BT_HID_DEVICE_ENABLED || CONFIG_BT_BLE_ENABLED)
|
||||
static esp_hid_scan_result_t *find_scan_result(esp_bd_addr_t bda, esp_hid_scan_result_t *results)
|
||||
{
|
||||
esp_hid_scan_result_t *r = results;
|
||||
@@ -134,8 +137,9 @@ static esp_hid_scan_result_t *find_scan_result(esp_bd_addr_t bda, esp_hid_scan_r
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif /* (CONFIG_BT_HID_DEVICE_ENABLED || CONFIG_BT_BLE_ENABLED) */
|
||||
|
||||
#if CONFIG_BT_CLASSIC_ENABLED
|
||||
#if CONFIG_BT_HID_DEVICE_ENABLED
|
||||
static void add_bt_scan_result(esp_bd_addr_t bda, esp_bt_cod_t *cod, esp_bt_uuid_t *uuid, uint8_t *name, uint8_t name_len, int rssi)
|
||||
{
|
||||
esp_hid_scan_result_t *r = find_scan_result(bda, bt_scan_results);
|
||||
@@ -189,6 +193,7 @@ static void add_bt_scan_result(esp_bd_addr_t bda, esp_bt_cod_t *cod, esp_bt_uuid
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_BT_BLE_ENABLED
|
||||
static void add_ble_scan_result(esp_bd_addr_t bda, esp_ble_addr_type_t addr_type, uint16_t appearance, uint8_t *name, uint8_t name_len, int rssi)
|
||||
{
|
||||
if (find_scan_result(bda, ble_scan_results)) {
|
||||
@@ -222,6 +227,7 @@ static void add_ble_scan_result(esp_bd_addr_t bda, esp_ble_addr_type_t addr_type
|
||||
ble_scan_results = r;
|
||||
num_ble_scan_results++;
|
||||
}
|
||||
#endif /* CONFIG_BT_BLE_ENABLED */
|
||||
|
||||
void print_uuid(esp_bt_uuid_t *uuid)
|
||||
{
|
||||
@@ -239,7 +245,7 @@ void print_uuid(esp_bt_uuid_t *uuid)
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_BT_CLASSIC_ENABLED
|
||||
#if CONFIG_BT_HID_DEVICE_ENABLED
|
||||
static void handle_bt_device_result(struct disc_res_param *disc_res)
|
||||
{
|
||||
GAP_DBG_PRINTF("BT : " ESP_BD_ADDR_STR, ESP_BD_ADDR_HEX(disc_res->bda));
|
||||
@@ -330,6 +336,7 @@ static void handle_bt_device_result(struct disc_res_param *disc_res)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_BT_BLE_ENABLED
|
||||
static void handle_ble_device_result(struct ble_scan_result_evt_param *scan_rst)
|
||||
{
|
||||
|
||||
@@ -375,8 +382,9 @@ static void handle_ble_device_result(struct ble_scan_result_evt_param *scan_rst)
|
||||
add_ble_scan_result(scan_rst->bda, scan_rst->ble_addr_type, appearance, adv_name, adv_name_len, scan_rst->rssi);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_BLE_ENABLED */
|
||||
|
||||
#if CONFIG_BT_CLASSIC_ENABLED
|
||||
#if CONFIG_BT_HID_DEVICE_ENABLED
|
||||
/*
|
||||
* BT GAP
|
||||
* */
|
||||
@@ -398,6 +406,9 @@ static void bt_gap_event_handler(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_para
|
||||
case ESP_BT_GAP_KEY_NOTIF_EVT:
|
||||
ESP_LOGI(TAG, "BT GAP KEY_NOTIF passkey:%d", param->key_notif.passkey);
|
||||
break;
|
||||
case ESP_BT_GAP_MODE_CHG_EVT:
|
||||
ESP_LOGI(TAG, "BT GAP MODE_CHG_EVT mode:%d", param->mode_chg.mode);
|
||||
break;
|
||||
default:
|
||||
ESP_LOGV(TAG, "BT GAP EVENT %s", bt_gap_evt_str(event));
|
||||
break;
|
||||
@@ -408,7 +419,7 @@ static esp_err_t init_bt_gap(void)
|
||||
{
|
||||
esp_err_t ret;
|
||||
esp_bt_sp_param_t param_type = ESP_BT_SP_IOCAP_MODE;
|
||||
esp_bt_io_cap_t iocap = ESP_BT_IO_CAP_IO;
|
||||
esp_bt_io_cap_t iocap = ESP_BT_IO_CAP_NONE;
|
||||
esp_bt_gap_set_security_param(param_type, &iocap, sizeof(uint8_t));
|
||||
/*
|
||||
* Set default parameters for Legacy Pairing
|
||||
@@ -446,6 +457,7 @@ static esp_err_t start_bt_scan(uint32_t seconds)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_BT_BLE_ENABLED
|
||||
/*
|
||||
* BLE GAP
|
||||
* */
|
||||
@@ -667,6 +679,7 @@ esp_err_t esp_hid_ble_gap_adv_start(void)
|
||||
};
|
||||
return esp_ble_gap_start_advertising(&hidd_adv_params);
|
||||
}
|
||||
#endif /* CONFIG_BT_BLE_ENABLED */
|
||||
|
||||
/*
|
||||
* CONTROLLER INIT
|
||||
@@ -676,15 +689,16 @@ static esp_err_t init_low_level(uint8_t mode)
|
||||
{
|
||||
esp_err_t ret;
|
||||
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||
#if CONFIG_BT_CLASSIC_ENABLED
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
bt_cfg.mode = mode;
|
||||
#endif
|
||||
#if CONFIG_BT_HID_DEVICE_ENABLED
|
||||
if (mode & ESP_BT_MODE_CLASSIC_BT) {
|
||||
bt_cfg.mode = mode;
|
||||
bt_cfg.bt_max_acl_conn = 3;
|
||||
bt_cfg.bt_max_sync_conn = 3;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
|
||||
ret = esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
|
||||
if (ret) {
|
||||
ESP_LOGE(TAG, "esp_bt_controller_mem_release failed: %d", ret);
|
||||
@@ -714,7 +728,7 @@ static esp_err_t init_low_level(uint8_t mode)
|
||||
ESP_LOGE(TAG, "esp_bluedroid_enable failed: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
#if CONFIG_BT_CLASSIC_ENABLED
|
||||
#if CONFIG_BT_HID_DEVICE_ENABLED
|
||||
if (mode & ESP_BT_MODE_CLASSIC_BT) {
|
||||
ret = init_bt_gap();
|
||||
if (ret) {
|
||||
@@ -722,19 +736,17 @@ static esp_err_t init_low_level(uint8_t mode)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_BT_BLE_ENABLED
|
||||
if (mode & ESP_BT_MODE_BLE) {
|
||||
ret = init_ble_gap();
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_BLE_ENABLED */
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
esp_err_t esp_hid_gap_init(uint8_t mode)
|
||||
{
|
||||
esp_err_t ret;
|
||||
@@ -781,16 +793,21 @@ esp_err_t esp_hid_scan(uint32_t seconds, size_t *num_results, esp_hid_scan_resul
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_BLE_ENABLED
|
||||
if (start_ble_scan(seconds) == ESP_OK) {
|
||||
#if CONFIG_BT_CLASSIC_ENABLED
|
||||
if (start_bt_scan(seconds) == ESP_OK) {
|
||||
WAIT_BT_CB();
|
||||
}
|
||||
#endif
|
||||
WAIT_BLE_CB();
|
||||
} else {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif /* CONFIG_BT_BLE_ENABLED */
|
||||
|
||||
#if CONFIG_BT_HID_DEVICE_ENABLED
|
||||
if (start_bt_scan(seconds) == ESP_OK) {
|
||||
WAIT_BT_CB();
|
||||
} else {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
*num_results = num_bt_scan_results + num_ble_scan_results;
|
||||
*results = bt_scan_results;
|
||||
|
@@ -15,17 +15,36 @@
|
||||
#ifndef _ESP_HID_GAP_H_
|
||||
#define _ESP_HID_GAP_H_
|
||||
|
||||
#define HIDD_IDLE_MODE 0x00
|
||||
#define HIDD_BLE_MODE 0x01
|
||||
#define HIDD_BT_MODE 0x02
|
||||
#define HIDD_BTDM_MODE 0x03
|
||||
|
||||
#if CONFIG_BT_HID_DEVICE_ENABLED
|
||||
#if CONFIG_BT_BLE_ENABLED
|
||||
#define HID_DEV_MODE HIDD_BTDM_MODE
|
||||
#else
|
||||
#define HID_DEV_MODE HIDD_BT_MODE
|
||||
#endif
|
||||
#elif CONFIG_BT_BLE_ENABLED
|
||||
#define HID_DEV_MODE HIDD_BLE_MODE
|
||||
#else
|
||||
#define HID_DEV_MODE HIDD_IDLE_MODE
|
||||
#endif
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "esp_bt.h"
|
||||
#include "esp_bt_defs.h"
|
||||
#include "esp_bt_main.h"
|
||||
#include "esp_gap_bt_api.h"
|
||||
#include "esp_hid_common.h"
|
||||
#if CONFIG_BT_BLE_ENABLED
|
||||
#include "esp_gattc_api.h"
|
||||
#include "esp_gatt_defs.h"
|
||||
#include "esp_gap_ble_api.h"
|
||||
#include "esp_gap_bt_api.h"
|
||||
#include "esp_hid_common.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@@ -3,4 +3,6 @@ CONFIG_BTDM_CTRL_MODE_BTDM=y
|
||||
CONFIG_BTDM_CTRL_HCI_MODE_VHCI=y
|
||||
CONFIG_BT_BLUEDROID_ENABLED=y
|
||||
CONFIG_BT_CLASSIC_ENABLED=y
|
||||
CONFIG_BT_HID_HOST_ENABLED=y
|
||||
CONFIG_BT_BLE_ENABLED=y
|
||||
CONFIG_BT_HID_ENABLED=y
|
||||
CONFIG_BT_HID_DEVICE_ENABLED=y
|
||||
|
@@ -1,14 +1,4 @@
|
||||
#
|
||||
# Automatically generated file. DO NOT EDIT.
|
||||
# Espressif IoT Development Framework (ESP-IDF) Project Configuration
|
||||
#
|
||||
CONFIG_IDF_CMAKE=y
|
||||
CONFIG_IDF_TARGET_ARCH_RISCV=y
|
||||
CONFIG_IDF_TARGET="esp32c3"
|
||||
CONFIG_IDF_TARGET_ESP32C3=y
|
||||
CONFIG_IDF_FIRMWARE_CHIP_ID=0x0005
|
||||
|
||||
#
|
||||
# Bluetooth
|
||||
#
|
||||
CONFIG_BT_ENABLED=y
|
||||
CONFIG_BT_BLUEDROID_ENABLED=y
|
||||
CONFIG_BT_BLE_ENABLED=y
|
||||
CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y
|
||||
|
@@ -1,14 +1,4 @@
|
||||
#
|
||||
# Automatically generated file. DO NOT EDIT.
|
||||
# Espressif IoT Development Framework (ESP-IDF) Project Configuration
|
||||
#
|
||||
CONFIG_IDF_CMAKE=y
|
||||
CONFIG_IDF_TARGET_ARCH_RISCV=y
|
||||
CONFIG_IDF_TARGET="esp32c3"
|
||||
CONFIG_IDF_TARGET_ESP32C3=y
|
||||
CONFIG_IDF_FIRMWARE_CHIP_ID=0x0005
|
||||
|
||||
#
|
||||
# Bluetooth
|
||||
#
|
||||
CONFIG_BT_ENABLED=y
|
||||
CONFIG_BT_BLUEDROID_ENABLED=y
|
||||
CONFIG_BT_BLE_ENABLED=y
|
||||
CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y
|
||||
|
@@ -2,3 +2,5 @@
|
||||
| ----------------- | ----- |
|
||||
|
||||
# ESP-IDF BT/BLE HID Host Demo
|
||||
|
||||
This demo use APIs which esp_hid component provided to create a Bluetooth dual mode hid host. After the program is started, the HID host will scan the surrounding Bluetooth HID device, and try to connect to the last device which has been scanned. When the connection is successfully established, the HID host will dump the HID device information, and can receive the data sent by the HID device.
|
||||
|
@@ -1,6 +1,5 @@
|
||||
set(srcs "esp_hid_host_main.c"
|
||||
"esp_hid_gap.c")
|
||||
|
||||
set(include_dirs ".")
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
|
@@ -24,8 +24,11 @@
|
||||
static const char *TAG = "ESP_HID_GAP";
|
||||
|
||||
// uncomment to print all devices that were seen during a scan
|
||||
#define GAP_DBG_PRINTF(...) //printf(__VA_ARGS__)
|
||||
//static const char * gap_bt_prop_type_names[5] = {"","BDNAME","COD","RSSI","EIR"};
|
||||
#define GAP_DBG_PRINTF(...) printf(__VA_ARGS__)
|
||||
|
||||
#if CONFIG_BT_HID_HOST_ENABLED
|
||||
static const char * gap_bt_prop_type_names[5] = {"","BDNAME","COD","RSSI","EIR"};
|
||||
#endif
|
||||
|
||||
static esp_hid_scan_result_t *bt_scan_results = NULL;
|
||||
static size_t num_bt_scan_results = 0;
|
||||
@@ -71,6 +74,7 @@ const char *bt_gap_evt_str(uint8_t event)
|
||||
return bt_gap_evt_names[event];
|
||||
}
|
||||
|
||||
#if CONFIG_BT_BLE_ENABLED
|
||||
const char *esp_ble_key_type_str(esp_ble_key_type_t key_type)
|
||||
{
|
||||
const char *key_str = NULL;
|
||||
@@ -109,6 +113,7 @@ const char *esp_ble_key_type_str(esp_ble_key_type_t key_type)
|
||||
}
|
||||
return key_str;
|
||||
}
|
||||
#endif /* CONFIG_BT_BLE_ENABLED */
|
||||
|
||||
void esp_hid_scan_results_free(esp_hid_scan_result_t *results)
|
||||
{
|
||||
@@ -123,6 +128,7 @@ void esp_hid_scan_results_free(esp_hid_scan_result_t *results)
|
||||
}
|
||||
}
|
||||
|
||||
#if (CONFIG_BT_HID_HOST_ENABLED || CONFIG_BT_BLE_ENABLED)
|
||||
static esp_hid_scan_result_t *find_scan_result(esp_bd_addr_t bda, esp_hid_scan_result_t *results)
|
||||
{
|
||||
esp_hid_scan_result_t *r = results;
|
||||
@@ -134,8 +140,9 @@ static esp_hid_scan_result_t *find_scan_result(esp_bd_addr_t bda, esp_hid_scan_r
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif /* (CONFIG_BT_HID_HOST_ENABLED || CONFIG_BT_BLE_ENABLED) */
|
||||
|
||||
#if CONFIG_BT_CLASSIC_ENABLED
|
||||
#if CONFIG_BT_HID_HOST_ENABLED
|
||||
static void add_bt_scan_result(esp_bd_addr_t bda, esp_bt_cod_t *cod, esp_bt_uuid_t *uuid, uint8_t *name, uint8_t name_len, int rssi)
|
||||
{
|
||||
esp_hid_scan_result_t *r = find_scan_result(bda, bt_scan_results);
|
||||
@@ -189,6 +196,7 @@ static void add_bt_scan_result(esp_bd_addr_t bda, esp_bt_cod_t *cod, esp_bt_uuid
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_BT_BLE_ENABLED
|
||||
static void add_ble_scan_result(esp_bd_addr_t bda, esp_ble_addr_type_t addr_type, uint16_t appearance, uint8_t *name, uint8_t name_len, int rssi)
|
||||
{
|
||||
if (find_scan_result(bda, ble_scan_results)) {
|
||||
@@ -222,6 +230,7 @@ static void add_ble_scan_result(esp_bd_addr_t bda, esp_ble_addr_type_t addr_type
|
||||
ble_scan_results = r;
|
||||
num_ble_scan_results++;
|
||||
}
|
||||
#endif /* CONFIG_BT_BLE_ENABLED */
|
||||
|
||||
void print_uuid(esp_bt_uuid_t *uuid)
|
||||
{
|
||||
@@ -239,7 +248,7 @@ void print_uuid(esp_bt_uuid_t *uuid)
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_BT_CLASSIC_ENABLED
|
||||
#if CONFIG_BT_HID_HOST_ENABLED
|
||||
static void handle_bt_device_result(struct disc_res_param *disc_res)
|
||||
{
|
||||
GAP_DBG_PRINTF("BT : " ESP_BD_ADDR_STR, ESP_BD_ADDR_HEX(disc_res->bda));
|
||||
@@ -330,6 +339,7 @@ static void handle_bt_device_result(struct disc_res_param *disc_res)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_BT_BLE_ENABLED
|
||||
static void handle_ble_device_result(struct ble_scan_result_evt_param *scan_rst)
|
||||
{
|
||||
|
||||
@@ -375,8 +385,9 @@ static void handle_ble_device_result(struct ble_scan_result_evt_param *scan_rst)
|
||||
add_ble_scan_result(scan_rst->bda, scan_rst->ble_addr_type, appearance, adv_name, adv_name_len, scan_rst->rssi);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_BLE_ENABLED */
|
||||
|
||||
#if CONFIG_BT_CLASSIC_ENABLED
|
||||
#if CONFIG_BT_HID_HOST_ENABLED
|
||||
/*
|
||||
* BT GAP
|
||||
* */
|
||||
@@ -398,6 +409,9 @@ static void bt_gap_event_handler(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_para
|
||||
case ESP_BT_GAP_KEY_NOTIF_EVT:
|
||||
ESP_LOGI(TAG, "BT GAP KEY_NOTIF passkey:%d", param->key_notif.passkey);
|
||||
break;
|
||||
case ESP_BT_GAP_MODE_CHG_EVT:
|
||||
ESP_LOGI(TAG, "BT GAP MODE_CHG_EVT mode:%d", param->mode_chg.mode);
|
||||
break;
|
||||
default:
|
||||
ESP_LOGV(TAG, "BT GAP EVENT %s", bt_gap_evt_str(event));
|
||||
break;
|
||||
@@ -446,6 +460,7 @@ static esp_err_t start_bt_scan(uint32_t seconds)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_BT_BLE_ENABLED
|
||||
/*
|
||||
* BLE GAP
|
||||
* */
|
||||
@@ -667,6 +682,7 @@ esp_err_t esp_hid_ble_gap_adv_start(void)
|
||||
};
|
||||
return esp_ble_gap_start_advertising(&hidd_adv_params);
|
||||
}
|
||||
#endif /* CONFIG_BT_BLE_ENABLED */
|
||||
|
||||
/*
|
||||
* CONTROLLER INIT
|
||||
@@ -676,9 +692,11 @@ static esp_err_t init_low_level(uint8_t mode)
|
||||
{
|
||||
esp_err_t ret;
|
||||
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||
#if CONFIG_BT_CLASSIC_ENABLED
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
bt_cfg.mode = mode;
|
||||
#endif
|
||||
#if CONFIG_BT_HID_HOST_ENABLED
|
||||
if (mode & ESP_BT_MODE_CLASSIC_BT) {
|
||||
bt_cfg.mode = mode;
|
||||
bt_cfg.bt_max_acl_conn = 3;
|
||||
bt_cfg.bt_max_sync_conn = 3;
|
||||
} else
|
||||
@@ -713,7 +731,7 @@ static esp_err_t init_low_level(uint8_t mode)
|
||||
ESP_LOGE(TAG, "esp_bluedroid_enable failed: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
#if CONFIG_BT_CLASSIC_ENABLED
|
||||
#if CONFIG_BT_HID_HOST_ENABLED
|
||||
if (mode & ESP_BT_MODE_CLASSIC_BT) {
|
||||
ret = init_bt_gap();
|
||||
if (ret) {
|
||||
@@ -721,18 +739,17 @@ static esp_err_t init_low_level(uint8_t mode)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_BT_BLE_ENABLED
|
||||
if (mode & ESP_BT_MODE_BLE) {
|
||||
ret = init_ble_gap();
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_BLE_ENABLED */
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
esp_err_t esp_hid_gap_init(uint8_t mode)
|
||||
{
|
||||
esp_err_t ret;
|
||||
@@ -779,16 +796,21 @@ esp_err_t esp_hid_scan(uint32_t seconds, size_t *num_results, esp_hid_scan_resul
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_BLE_ENABLED
|
||||
if (start_ble_scan(seconds) == ESP_OK) {
|
||||
#if CONFIG_BT_CLASSIC_ENABLED
|
||||
if (start_bt_scan(seconds) == ESP_OK) {
|
||||
WAIT_BT_CB();
|
||||
}
|
||||
#endif
|
||||
WAIT_BLE_CB();
|
||||
} else {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif /* CONFIG_BT_BLE_ENABLED */
|
||||
|
||||
#if CONFIG_BT_HID_HOST_ENABLED
|
||||
if (start_bt_scan(seconds) == ESP_OK) {
|
||||
WAIT_BT_CB();
|
||||
} else {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
*num_results = num_bt_scan_results + num_ble_scan_results;
|
||||
*results = bt_scan_results;
|
||||
|
@@ -15,17 +15,36 @@
|
||||
#ifndef _ESP_HID_GAP_H_
|
||||
#define _ESP_HID_GAP_H_
|
||||
|
||||
#define HIDH_IDLE_MODE 0x00
|
||||
#define HIDH_BLE_MODE 0x01
|
||||
#define HIDH_BT_MODE 0x02
|
||||
#define HIDH_BTDM_MODE 0x03
|
||||
|
||||
#if CONFIG_BT_HID_HOST_ENABLED
|
||||
#if CONFIG_BT_BLE_ENABLED
|
||||
#define HID_HOST_MODE HIDH_BTDM_MODE
|
||||
#else
|
||||
#define HID_HOST_MODE HIDH_BT_MODE
|
||||
#endif
|
||||
#elif CONFIG_BT_BLE_ENABLED
|
||||
#define HID_HOST_MODE HIDH_BLE_MODE
|
||||
#else
|
||||
#define HID_HOST_MODE HIDH_IDLE_MODE
|
||||
#endif
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "esp_bt.h"
|
||||
#include "esp_bt_defs.h"
|
||||
#include "esp_bt_main.h"
|
||||
#include "esp_gap_bt_api.h"
|
||||
#include "esp_hid_common.h"
|
||||
#if CONFIG_BT_BLE_ENABLED
|
||||
#include "esp_gattc_api.h"
|
||||
#include "esp_gatt_defs.h"
|
||||
#include "esp_gap_ble_api.h"
|
||||
#include "esp_gap_bt_api.h"
|
||||
#include "esp_hid_common.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@@ -36,9 +36,13 @@ void hidh_callback(void *handler_args, esp_event_base_t base, int32_t id, void *
|
||||
|
||||
switch (event) {
|
||||
case ESP_HIDH_OPEN_EVENT: {
|
||||
const uint8_t *bda = esp_hidh_dev_bda_get(param->open.dev);
|
||||
ESP_LOGI(TAG, ESP_BD_ADDR_STR " OPEN: %s", ESP_BD_ADDR_HEX(bda), esp_hidh_dev_name_get(param->open.dev));
|
||||
esp_hidh_dev_dump(param->open.dev, stdout);
|
||||
if (param->open.status == ESP_OK) {
|
||||
const uint8_t *bda = esp_hidh_dev_bda_get(param->open.dev);
|
||||
ESP_LOGI(TAG, ESP_BD_ADDR_STR " OPEN: %s", ESP_BD_ADDR_HEX(bda), esp_hidh_dev_name_get(param->open.dev));
|
||||
esp_hidh_dev_dump(param->open.dev, stdout);
|
||||
} else {
|
||||
ESP_LOGE(TAG, " OPEN failed!");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_HIDH_BATTERY_EVENT: {
|
||||
@@ -54,15 +58,15 @@ void hidh_callback(void *handler_args, esp_event_base_t base, int32_t id, void *
|
||||
}
|
||||
case ESP_HIDH_FEATURE_EVENT: {
|
||||
const uint8_t *bda = esp_hidh_dev_bda_get(param->feature.dev);
|
||||
ESP_LOGI(TAG, ESP_BD_ADDR_STR " FEATURE: %8s, MAP: %2u, ID: %3u, Len: %d", ESP_BD_ADDR_HEX(bda), esp_hid_usage_str(param->feature.usage), param->feature.map_index, param->feature.report_id, param->feature.length);
|
||||
ESP_LOGI(TAG, ESP_BD_ADDR_STR " FEATURE: %8s, MAP: %2u, ID: %3u, Len: %d", ESP_BD_ADDR_HEX(bda),
|
||||
esp_hid_usage_str(param->feature.usage), param->feature.map_index, param->feature.report_id,
|
||||
param->feature.length);
|
||||
ESP_LOG_BUFFER_HEX(TAG, param->feature.data, param->feature.length);
|
||||
break;
|
||||
}
|
||||
case ESP_HIDH_CLOSE_EVENT: {
|
||||
const uint8_t *bda = esp_hidh_dev_bda_get(param->close.dev);
|
||||
ESP_LOGI(TAG, ESP_BD_ADDR_STR " CLOSE: '%s' %s", ESP_BD_ADDR_HEX(bda), esp_hidh_dev_name_get(param->close.dev), esp_hid_disconnect_reason_str(esp_hidh_dev_transport_get(param->close.dev), param->close.reason));
|
||||
//MUST call this function to free all allocated memory by this device
|
||||
esp_hidh_dev_free(param->close.dev);
|
||||
ESP_LOGI(TAG, ESP_BD_ADDR_STR " CLOSE: %s", ESP_BD_ADDR_HEX(bda), esp_hidh_dev_name_get(param->close.dev));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -88,11 +92,15 @@ void hid_demo_task(void *pvParameters)
|
||||
printf(" %s: " ESP_BD_ADDR_STR ", ", (r->transport == ESP_HID_TRANSPORT_BLE) ? "BLE" : "BT ", ESP_BD_ADDR_HEX(r->bda));
|
||||
printf("RSSI: %d, ", r->rssi);
|
||||
printf("USAGE: %s, ", esp_hid_usage_str(r->usage));
|
||||
#if CONFIG_BT_BLE_ENABLED
|
||||
if (r->transport == ESP_HID_TRANSPORT_BLE) {
|
||||
cr = r;
|
||||
printf("APPEARANCE: 0x%04x, ", r->ble.appearance);
|
||||
printf("ADDR_TYPE: '%s', ", ble_addr_type_str(r->ble.addr_type));
|
||||
} else {
|
||||
}
|
||||
#endif /* CONFIG_BT_BLE_ENABLED */
|
||||
#if CONFIG_BT_HID_HOST_ENABLED
|
||||
if (r->transport == ESP_HID_TRANSPORT_BT) {
|
||||
cr = r;
|
||||
printf("COD: %s[", esp_hid_cod_major_str(r->bt.cod.major));
|
||||
esp_hid_cod_minor_print(r->bt.cod.minor, stdout);
|
||||
@@ -100,6 +108,7 @@ void hid_demo_task(void *pvParameters)
|
||||
print_uuid(&r->bt.uuid);
|
||||
printf(", ");
|
||||
}
|
||||
#endif /* CONFIG_BT_HID_HOST_ENABLED */
|
||||
printf("NAME: %s ", r->name ? r->name : "");
|
||||
printf("\n");
|
||||
r = r->next;
|
||||
@@ -117,21 +126,25 @@ void hid_demo_task(void *pvParameters)
|
||||
void app_main(void)
|
||||
{
|
||||
esp_err_t ret;
|
||||
#if HID_HOST_MODE == HIDH_IDLE_MODE
|
||||
ESP_LOGE(TAG, "Please turn on BT HID host or BLE!");
|
||||
return;
|
||||
#endif
|
||||
ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK( ret );
|
||||
#if CONFIG_BT_CLASSIC_ENABLED
|
||||
ESP_ERROR_CHECK( esp_hid_gap_init(ESP_BT_MODE_BTDM) );
|
||||
#else
|
||||
ESP_ERROR_CHECK( esp_hid_gap_init(ESP_BT_MODE_BLE) );
|
||||
#endif
|
||||
ESP_LOGI(TAG, "setting hid gap, mode:%d", HID_HOST_MODE);
|
||||
ESP_ERROR_CHECK( esp_hid_gap_init(HID_HOST_MODE) );
|
||||
#if CONFIG_BT_BLE_ENABLED
|
||||
ESP_ERROR_CHECK( esp_ble_gattc_register_callback(esp_hidh_gattc_event_handler) );
|
||||
#endif /* CONFIG_BT_BLE_ENABLED */
|
||||
esp_hidh_config_t config = {
|
||||
.callback = hidh_callback,
|
||||
.event_stack_size = 4096
|
||||
.event_stack_size = 4096,
|
||||
.callback_arg = NULL,
|
||||
};
|
||||
ESP_ERROR_CHECK( esp_hidh_init(&config) );
|
||||
|
||||
|
@@ -3,4 +3,6 @@ CONFIG_BTDM_CTRL_MODE_BTDM=y
|
||||
CONFIG_BTDM_CTRL_HCI_MODE_VHCI=y
|
||||
CONFIG_BT_BLUEDROID_ENABLED=y
|
||||
CONFIG_BT_CLASSIC_ENABLED=y
|
||||
CONFIG_BT_BLE_ENABLED=y
|
||||
CONFIG_BT_HID_ENABLED=y
|
||||
CONFIG_BT_HID_HOST_ENABLED=y
|
||||
|
@@ -1,14 +1,4 @@
|
||||
#
|
||||
# Automatically generated file. DO NOT EDIT.
|
||||
# Espressif IoT Development Framework (ESP-IDF) Project Configuration
|
||||
#
|
||||
CONFIG_IDF_CMAKE=y
|
||||
CONFIG_IDF_TARGET_ARCH_RISCV=y
|
||||
CONFIG_IDF_TARGET="esp32c3"
|
||||
CONFIG_IDF_TARGET_ESP32C3=y
|
||||
CONFIG_IDF_FIRMWARE_CHIP_ID=0x0005
|
||||
|
||||
#
|
||||
# Bluetooth
|
||||
#
|
||||
CONFIG_BT_ENABLED=y
|
||||
CONFIG_BT_BLUEDROID_ENABLED=y
|
||||
CONFIG_BT_BLE_ENABLED=y
|
||||
CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y
|
||||
|
@@ -1,14 +1,4 @@
|
||||
#
|
||||
# Automatically generated file. DO NOT EDIT.
|
||||
# Espressif IoT Development Framework (ESP-IDF) Project Configuration
|
||||
#
|
||||
CONFIG_IDF_CMAKE=y
|
||||
CONFIG_IDF_TARGET_ARCH_RISCV=y
|
||||
CONFIG_IDF_TARGET="esp32c3"
|
||||
CONFIG_IDF_TARGET_ESP32C3=y
|
||||
CONFIG_IDF_FIRMWARE_CHIP_ID=0x0005
|
||||
|
||||
#
|
||||
# Bluetooth
|
||||
#
|
||||
CONFIG_BT_ENABLED=y
|
||||
CONFIG_BT_BLUEDROID_ENABLED=y
|
||||
CONFIG_BT_BLE_ENABLED=y
|
||||
CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y
|
||||
|
Reference in New Issue
Block a user