1. update esp_hid component to use esp HID API

2. add esp_hidh_config_t::callback_arg
pull/7554/head
liqigan 2021-09-07 17:08:43 +08:00
rodzic 1c15c9207c
commit 2078dfe293
31 zmienionych plików z 2985 dodań i 992 usunięć

Wyświetl plik

@ -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()

Wyświetl plik

@ -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
*/

Wyświetl plik

@ -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 */
/**

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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_ */

Wyświetl plik

@ -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);

Wyświetl plik

@ -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,17 +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

Wyświetl plik

@ -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;
@ -872,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;
}
@ -898,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);
@ -941,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)

Wyświetl plik

@ -534,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;
@ -659,7 +662,7 @@ esp_err_t esp_ble_hidh_init(const esp_hidh_config_t *config)
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,
NULL);
config->callback_arg);
} while (0);
if (ret != ESP_OK) {
@ -706,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;
@ -713,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;
}
@ -721,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;
}
@ -734,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);
}

Wyświetl plik

@ -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 */

Wyświetl plik

@ -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;

Wyświetl plik

@ -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;

Wyświetl plik

@ -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 devices 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;
@ -508,6 +829,20 @@ void esp_hidh_process_event_data_handler(void *event_handler_arg, esp_event_base
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;
}

Wyświetl plik

@ -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.

Wyświetl plik

@ -1,6 +1,5 @@
set(srcs "esp_hid_device_main.c"
"esp_hid_gap.c")
set(include_dirs ".")
idf_component_register(SRCS "${srcs}"

Wyświetl plik

@ -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
}

Wyświetl plik

@ -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;

Wyświetl plik

@ -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" {

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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.

Wyświetl plik

@ -1,6 +1,5 @@
set(srcs "esp_hid_host_main.c"
"esp_hid_gap.c")
set(include_dirs ".")
idf_component_register(SRCS "${srcs}"

Wyświetl plik

@ -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;

Wyświetl plik

@ -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" {

Wyświetl plik

@ -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) );

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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