example/hid: Added the BLE hid device profile.

demo/hid: Change the license validity period & some unreasonable LOG print.

example/hid: Added the Vendor Report output support.
This commit is contained in:
Yulong 2018-03-09 03:25:23 -05:00 committed by yulong
parent fe907bde60
commit efb747d167
10 changed files with 2155 additions and 0 deletions

View File

@ -0,0 +1,11 @@
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := hidd_demos
COMPONENT_ADD_INCLUDEDIRS := components/include \
include $(IDF_PATH)/make/project.mk

View File

@ -0,0 +1,317 @@
/* This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this software is
distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_bt.h"
#include "esp_hidd_prf_api.h"
#include "esp_bt_defs.h"
#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
#include "esp_gatt_defs.h"
#include "esp_bt_main.h"
#include "esp_bt_device.h"
#include "bt_trace.h"
#include "driver/gpio.h"
#include "hid_dev.h"
/**
* Brief:
* This test code shows how to configure gpio and how to use gpio interrupt.
*
* GPIO status:
* GPIO18: output
* GPIO19: output
* GPIO4: input, pulled up, interrupt from rising edge and falling edge
* GPIO5: input, pulled up, interrupt from rising edge.
*
* Test:
* Connect GPIO18 with GPIO4
* Connect GPIO19 with GPIO5
* Generate pulses on GPIO18/19, that triggers interrupt on GPIO4/5
*
*/
#define GATTS_TAG "HID_DEMO"
#define GPIO_OUTPUT_IO_0 18
#define GPIO_OUTPUT_IO_1 19
#define GPIO_OUTPUT_PIN_SEL ((1<<GPIO_OUTPUT_IO_0) | (1<<GPIO_OUTPUT_IO_1))
#define GPIO_INPUT_IO_0 21
#define GPIO_INPUT_IO_1 27
#define GPIO_INPUT_PIN_SEL ((1<<GPIO_INPUT_IO_0) | (1<<GPIO_INPUT_IO_1))
#define ESP_INTR_FLAG_DEFAULT 0
static xQueueHandle gpio_evt_queue = NULL;
static uint16_t hid_conn_id = 0;
static bool sec_conn = false;
static bool send_volum_up = false;
#define CHAR_DECLARATION_SIZE (sizeof(uint8_t))
static void hidd_event_callback(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param);
#define HIDD_DEVICE_NAME "HID"
static uint8_t hidd_service_uuid128[] = {
/* LSB <--------------------------------------------------------------------------------> MSB */
//first uuid, 16bit, [12],[13] is the value
0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x12, 0x18, 0x00, 0x00,
};
static esp_ble_adv_data_t hidd_adv_data = {
.set_scan_rsp = false,
.include_name = true,
.include_txpower = true,
.min_interval = 0x20,
.max_interval = 0x30,
.appearance = 0x03c0, //HID Generic,
.manufacturer_len = 0,
.p_manufacturer_data = NULL,
.service_data_len = 0,
.p_service_data = NULL,
.service_uuid_len = sizeof(hidd_service_uuid128),
.p_service_uuid = hidd_service_uuid128,
.flag = 0x6,
};
static esp_ble_adv_params_t hidd_adv_params = {
.adv_int_min = 0x20,
.adv_int_max = 0x30,
.adv_type = ADV_TYPE_IND,
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
//.peer_addr =
//.peer_addr_type =
.channel_map = ADV_CHNL_ALL,
.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
};
void IRAM_ATTR gpio_isr_handler(void* arg)
{
uint32_t gpio_num = (uint32_t) arg;
xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}
void gpio_task_example(void* arg)
{
static uint8_t i = 0;
uint32_t io_num;
for(;;) {
if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
ESP_LOGI(GATTS_TAG, "GPIO[%d] intr, val: %d\n", io_num, gpio_get_level(io_num));
if(i == 0) {
++i;
}
}
}
}
static void gpio_demo_init(void)
{
gpio_config_t io_conf;
//disable interrupt
io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
//set as output mode
io_conf.mode = GPIO_MODE_OUTPUT;
//bit mask of the pins that you want to set,e.g.GPIO18/19
io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;
//disable pull-down mode
io_conf.pull_down_en = 0;
//disable pull-up mode
io_conf.pull_up_en = 0;
//configure GPIO with the given settings
gpio_config(&io_conf);
//interrupt of rising edge
io_conf.intr_type = GPIO_PIN_INTR_POSEDGE;
//bit mask of the pins, use GPIO4/5 here
io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
//set as input mode
io_conf.mode = GPIO_MODE_INPUT;
//enable pull-up mode
io_conf.pull_up_en = 1;
gpio_config(&io_conf);
//change gpio intrrupt type for one pin
gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_ANYEDGE);
//create a queue to handle gpio event from isr
gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
//start gpio task
xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL);
//install gpio isr service
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
//hook isr handler for specific gpio pin
gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);
//hook isr handler for specific gpio pin
gpio_isr_handler_add(GPIO_INPUT_IO_1, gpio_isr_handler, (void*) GPIO_INPUT_IO_1);
//remove isr handler for gpio number.
gpio_isr_handler_remove(GPIO_INPUT_IO_0);
//hook isr handler for specific gpio pin again
gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);
}
static void hidd_event_callback(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param)
{
switch(event) {
case ESP_HIDD_EVENT_REG_FINISH: {
if (param->init_finish.state == ESP_HIDD_INIT_OK) {
//esp_bd_addr_t rand_addr = {0x04,0x11,0x11,0x11,0x11,0x05};
esp_ble_gap_set_device_name(HIDD_DEVICE_NAME);
esp_ble_gap_config_adv_data(&hidd_adv_data);
}
break;
}
case ESP_BAT_EVENT_REG: {
break;
}
case ESP_HIDD_EVENT_DEINIT_FINISH:
break;
case ESP_HIDD_EVENT_BLE_CONNECT: {
hid_conn_id = param->connect.conn_id;
break;
}
case ESP_HIDD_EVENT_BLE_DISCONNECT: {
sec_conn = false;
LOG_ERROR("%s(), ESP_HIDD_EVENT_BLE_DISCONNECT", __func__);
esp_ble_gap_start_advertising(&hidd_adv_params);
break;
}
case ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT: {
LOG_ERROR("%s, ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT", __func__);
ESP_LOG_BUFFER_HEX(GATTS_TAG, param->vendor_write.data, param->vendor_write.length);
}
default:
break;
}
return;
}
static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
switch (event) {
case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
esp_ble_gap_start_advertising(&hidd_adv_params);
break;
case ESP_GAP_BLE_SEC_REQ_EVT:
for(int i = 0; i < ESP_BD_ADDR_LEN; i++) {
LOG_DEBUG("%x:",param->ble_security.ble_req.bd_addr[i]);
}
esp_ble_gap_security_rsp(param->ble_security.ble_req.bd_addr, true);
break;
case ESP_GAP_BLE_AUTH_CMPL_EVT:
sec_conn = true;
LOG_ERROR("staus =%s, ESP_GAP_BLE_AUTH_CMPL_EVT",param->ble_security.auth_cmpl.success ? "success" : "fail");
break;
default:
break;
}
}
void hid_demo_task(void *pvParameters)
{
vTaskDelay(1000 / portTICK_PERIOD_MS);
while(1) {
vTaskDelay(2000 / portTICK_PERIOD_MS);
if (sec_conn) {
LOG_ERROR("Send the volume");
//send_volum_up = true;
uint8_t key_vaule = {HID_KEY_A};
esp_hidd_send_keyboard_value(hid_conn_id, 0, &key_vaule, 1);
//esp_hidd_send_consumer_value(hid_conn_id, HID_CONSUMER_VOLUME_UP, true);
vTaskDelay(3000 / portTICK_PERIOD_MS);
if (send_volum_up) {
send_volum_up = false;
//esp_hidd_send_consumer_value(hid_conn_id, HID_CONSUMER_VOLUME_UP, false);
esp_hidd_send_consumer_value(hid_conn_id, HID_CONSUMER_VOLUME_DOWN, true);
}
}
}
}
void app_main()
{
esp_err_t ret;
// Initialize NVS.
ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK( ret );
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
ret = esp_bt_controller_init(&bt_cfg);
if (ret) {
ESP_LOGE(GATTS_TAG, "%s initialize controller failed\n", __func__);
return;
}
ret = esp_bt_controller_enable(ESP_BT_MODE_BTDM);
if (ret) {
ESP_LOGE(GATTS_TAG, "%s enable controller failed\n", __func__);
return;
}
ret = esp_bluedroid_init();
if (ret) {
LOG_ERROR("%s init bluedroid failed\n", __func__);
return;
}
ret = esp_bluedroid_enable();
if (ret) {
LOG_ERROR("%s init bluedroid failed\n", __func__);
return;
}
if((ret = esp_hidd_profile_init()) != ESP_OK) {
LOG_ERROR("%s init bluedroid failed\n", __func__);
}
///register the callback function to the gap module
esp_ble_gap_register_callback(gap_event_handler);
esp_hidd_register_callbacks(hidd_event_callback);
/* set the security iocap & auth_req & key size & init key response key parameters to the stack*/
esp_ble_auth_req_t auth_req = ESP_LE_AUTH_BOND; //bonding with peer device after authentication
esp_ble_io_cap_t iocap = ESP_IO_CAP_NONE; //set the IO capability to No output No input
uint8_t key_size = 16; //the key size should be 7~16 bytes
uint8_t init_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
uint8_t rsp_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &auth_req, sizeof(uint8_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &iocap, sizeof(uint8_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &key_size, sizeof(uint8_t));
/* If your BLE device act as a Slave, the init_key means you hope which types of key of the master should distribut to you,
and the response key means which key you can distribut to the Master;
If your BLE device act as a master, the response key means you hope which types of key of the slave should distribut to you,
and the init key means which key you can distribut to the slave. */
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_INIT_KEY, &init_key, sizeof(uint8_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_RSP_KEY, &rsp_key, sizeof(uint8_t));
//init the gpio pin
gpio_demo_init();
xTaskCreate(&hid_demo_task, "hid_task", 2048, NULL, 5, NULL);
}

View File

@ -0,0 +1,10 @@
#
# Main Makefile. This is basically the same as a component makefile.
#
# This Makefile should, at the very least, just include $(SDK_PATH)/make/component_common.mk. By default,
# this will take the sources in the src/ directory, compile them and link them into
# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
# please read the ESP-IDF documents if you need to do this.
#
# include $(IDF_PATH)/make/component_common.mk

View File

@ -0,0 +1,146 @@
// Copyright 2017-2018 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 "esp_hidd_prf_api.h"
#include "hidd_le_prf_int.h"
#include "hid_dev.h"
#include <stdlib.h>
#include <string.h>
#include "bt_trace.h"
// HID keyboard input report length
#define HID_KEYBOARD_IN_RPT_LEN 8
// HID LED output report length
#define HID_LED_OUT_RPT_LEN 1
// HID mouse input report length
#define HID_MOUSE_IN_RPT_LEN 5
// HID consumer control input report length
#define HID_CC_IN_RPT_LEN 2
esp_err_t esp_hidd_register_callbacks(esp_hidd_event_cb_t callbacks)
{
esp_err_t hidd_status;
if(callbacks != NULL) {
hidd_le_env.hidd_cb = callbacks;
} else {
return ESP_FAIL;
}
if((hidd_status = hidd_register_cb()) != ESP_OK) {
return hidd_status;
}
esp_ble_gatts_app_register(BATTRAY_APP_ID);
if((hidd_status = esp_ble_gatts_app_register(HIDD_APP_ID)) != ESP_OK) {
return hidd_status;
}
return hidd_status;
}
esp_err_t esp_hidd_profile_init(void)
{
if (hidd_le_env.enabled) {
LOG_ERROR("HID device profile already initialized");
return ESP_FAIL;
}
// Reset the hid device target environment
memset(&hidd_le_env, 0, sizeof(hidd_le_env_t));
hidd_le_env.enabled = true;
return ESP_OK;
}
esp_err_t esp_hidd_profile_deinit(void)
{
uint16_t hidd_svc_hdl = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_SVC];
if (!hidd_le_env.enabled) {
LOG_ERROR("HID device profile already initialized");
return ESP_OK;
}
if(hidd_svc_hdl != 0) {
esp_ble_gatts_stop_service(hidd_svc_hdl);
esp_ble_gatts_delete_service(hidd_svc_hdl);
} else {
return ESP_FAIL;
}
/* register the HID device profile to the BTA_GATTS module*/
esp_ble_gatts_app_unregister(hidd_le_env.gatt_if);
return ESP_OK;
}
uint16_t esp_hidd_get_version(void)
{
return HIDD_VERSION;
}
void esp_hidd_send_consumer_value(uint16_t conn_id, uint8_t key_cmd, bool key_pressed)
{
uint8_t buffer[HID_CC_IN_RPT_LEN] = {0, 0};
if (key_pressed) {
LOG_DEBUG("hid_consumer_build_report");
hid_consumer_build_report(buffer, key_cmd);
}
LOG_DEBUG("buffer[0] = %x, buffer[1] = %x", buffer[0], buffer[1]);
hid_dev_send_report(hidd_le_env.gatt_if, conn_id,
HID_RPT_ID_CC_IN, HID_REPORT_TYPE_INPUT, HID_CC_IN_RPT_LEN, buffer);
return;
}
void esp_hidd_send_keyboard_value(uint16_t conn_id, key_mask_t special_key_mask, uint8_t *keyboard_cmd, uint8_t num_key)
{
if (num_key > HID_KEYBOARD_IN_RPT_LEN - 2) {
LOG_ERROR("%s(), the number key should not be more than %d", __func__, HID_KEYBOARD_IN_RPT_LEN);
return;
}
uint8_t buffer[HID_KEYBOARD_IN_RPT_LEN] = {0};
buffer[0] = special_key_mask;
for (int i = 0; i < num_key; i++) {
buffer[i+2] = keyboard_cmd[i];
}
LOG_DEBUG("the key vaule = %d,%d,%d, %d, %d, %d,%d, %d", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7]);
hid_dev_send_report(hidd_le_env.gatt_if, conn_id,
HID_RPT_ID_KEY_IN, HID_REPORT_TYPE_INPUT, HID_KEYBOARD_IN_RPT_LEN, buffer);
return;
}
void esp_hidd_send_mouse_value(uint16_t conn_id, uint8_t mouse_button, int8_t mickeys_x, int8_t mickeys_y)
{
uint8_t buffer[HID_MOUSE_IN_RPT_LEN];
buffer[0] = mouse_button; // Buttons
buffer[1] = mickeys_x; // X
buffer[2] = mickeys_y; // Y
buffer[3] = 0; // Wheel
buffer[4] = 0; // AC Pan
hid_dev_send_report(hidd_le_env.gatt_if, conn_id,
HID_RPT_ID_MOUSE_IN, HID_REPORT_TYPE_INPUT, HID_MOUSE_IN_RPT_LEN, buffer);
return;
}

View File

@ -0,0 +1,167 @@
// Copyright 2017-2018 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.
#ifndef __ESP_HIDD_API_H__
#define __ESP_HIDD_API_H__
#include "esp_bt_defs.h"
#include "esp_gatt_defs.h"
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
ESP_HIDD_EVENT_REG_FINISH = 0,
ESP_BAT_EVENT_REG,
ESP_HIDD_EVENT_DEINIT_FINISH,
ESP_HIDD_EVENT_BLE_CONNECT,
ESP_HIDD_EVENT_BLE_DISCONNECT,
ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT,
} esp_hidd_cb_event_t;
/// HID config status
typedef enum {
ESP_HIDD_STA_CONN_SUCCESS = 0x00,
ESP_HIDD_STA_CONN_FAIL = 0x01,
} esp_hidd_sta_conn_state_t;
/// HID init status
typedef enum {
ESP_HIDD_INIT_OK = 0,
ESP_HIDD_INIT_FAILED = 1,
} esp_hidd_init_state_t;
/// HID deinit status
typedef enum {
ESP_HIDD_DEINIT_OK = 0,
ESP_HIDD_DEINIT_FAILED = 0,
} esp_hidd_deinit_state_t;
#define LEFT_CONTROL_KEY_MASK (1 >> 0)
#define LEFT_SHIFT_KEY_MASK (1 >> 1)
#define LEFT_ALT_KEY_MASK (1 >> 2)
#define LEFT_GUI_KEY_MASK (1 >> 3)
#define RIGHT_CONTROL_KEY_MASK (1 >> 4)
#define RIGHT_SHIFT_KEY_MASK (1 >> 5)
#define RIGHT_ALT_KEY_MASK (1 >> 6)
#define RIGHT_GUI_KEY_MASK (1 >> 7)
typedef uint8_t key_mask_t;
/**
* @brief HIDD callback parameters union
*/
typedef union {
/**
* @brief ESP_HIDD_EVENT_INIT_FINISH
*/
struct hidd_init_finish_evt_param {
esp_hidd_init_state_t state; /*!< Initial status */
esp_gatt_if_t gatts_if;
} init_finish; /*!< HID callback param of ESP_HIDD_EVENT_INIT_FINISH */
/**
* @brief ESP_HIDD_EVENT_DEINIT_FINISH
*/
struct hidd_deinit_finish_evt_param {
esp_hidd_deinit_state_t state; /*!< De-initial status */
} deinit_finish; /*!< HID callback param of ESP_HIDD_EVENT_DEINIT_FINISH */
/**
* @brief ESP_HIDD_EVENT_CONNECT
*/
struct hidd_connect_evt_param {
uint16_t conn_id;
esp_bd_addr_t remote_bda; /*!< HID Remote bluetooth connection index */
} connect; /*!< HID callback param of ESP_HIDD_EVENT_CONNECT */
/**
* @brief ESP_HIDD_EVENT_DISCONNECT
*/
struct hidd_disconnect_evt_param {
esp_bd_addr_t remote_bda; /*!< HID Remote bluetooth device address */
} disconnect; /*!< HID callback param of ESP_HIDD_EVENT_DISCONNECT */
/**
* @brief ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT
*/
struct hidd_vendor_write_evt_param {
uint16_t conn_id; /*!< HID connection index */
uint16_t report_id; /*!< HID report index */
uint16_t length; /*!< data length */
uint8_t *data; /*!< The pointer to the data */
} vendor_write; /*!< HID callback param of ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT */
} esp_hidd_cb_param_t;
/**
* @brief HID device event callback function type
* @param event : Event type
* @param param : Point to callback parameter, currently is union type
*/
typedef void (*esp_hidd_event_cb_t) (esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param);
/**
*
* @brief This function is called to receive hid device callback event
*
* @param[in] callbacks: callback functions
*
* @return ESP_OK - success, other - failed
*
*/
esp_err_t esp_hidd_register_callbacks(esp_hidd_event_cb_t callbacks);
/**
*
* @brief This function is called to initialize hid device profile
*
* @return ESP_OK - success, other - failed
*
*/
esp_err_t esp_hidd_profile_init(void);
/**
*
* @brief This function is called to de-initialize hid device profile
*
* @return ESP_OK - success, other - failed
*
*/
esp_err_t esp_hidd_profile_deinit(void);
/**
*
* @brief Get hidd profile version
*
* @return Most 8bit significant is Great version, Least 8bit is Sub version
*
*/
uint16_t esp_hidd_get_version(void);
void esp_hidd_send_consumer_value(uint16_t conn_id, uint8_t key_cmd, bool key_pressed);
void esp_hidd_send_keyboard_value(uint16_t conn_id, key_mask_t special_key_mask, uint8_t *keyboard_cmd, uint8_t num_key);
void esp_hidd_send_mouse_value(uint16_t conn_id, uint8_t mouse_button, int8_t mickeys_x, int8_t mickeys_y);
#ifdef __cplusplus
}
#endif
#endif /* __ESP_HIDD_API_H__ */

View File

@ -0,0 +1,143 @@
// Copyright 2017-2018 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 "hid_dev.h"
#include "bt_trace.h"
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
static hid_report_map_t *hid_dev_rpt_tbl;
static uint8_t hid_dev_rpt_tbl_Len;
static hid_report_map_t *hid_dev_rpt_by_id(uint8_t id, uint8_t type)
{
hid_report_map_t *rpt = hid_dev_rpt_tbl;
for (uint8_t i = hid_dev_rpt_tbl_Len; i > 0; i--, rpt++) {
if (rpt->id == id && rpt->type == type && rpt->mode == hidProtocolMode) {
return rpt;
}
}
return NULL;
}
void hid_dev_register_reports(uint8_t num_reports, hid_report_map_t *p_report)
{
hid_dev_rpt_tbl = p_report;
hid_dev_rpt_tbl_Len = num_reports;
return;
}
void hid_dev_send_report(esp_gatt_if_t gatts_if, uint16_t conn_id,
uint8_t id, uint8_t type, uint8_t length, uint8_t *data)
{
hid_report_map_t *p_rpt;
// get att handle for report
if ((p_rpt = hid_dev_rpt_by_id(id, type)) != NULL) {
// if notifications are enabled
LOG_DEBUG("%s(), send the report, handle = %d", __func__, p_rpt->handle);
esp_ble_gatts_send_indicate(gatts_if, conn_id, p_rpt->handle, length, data, false);
}
return;
}
void hid_consumer_build_report(uint8_t *buffer, consumer_cmd_t cmd)
{
if (!buffer) {
LOG_ERROR("%s(), the buffer is NULL, hid build report failed.", __func__);
return;
}
switch (cmd) {
case HID_CONSUMER_CHANNEL_UP:
HID_CC_RPT_SET_CHANNEL(buffer, HID_CC_RPT_CHANNEL_UP);
break;
case HID_CONSUMER_CHANNEL_DOWN:
HID_CC_RPT_SET_CHANNEL(buffer, HID_CC_RPT_CHANNEL_DOWN);
break;
case HID_CONSUMER_VOLUME_UP:
HID_CC_RPT_SET_VOLUME_UP(buffer);
break;
case HID_CONSUMER_VOLUME_DOWN:
HID_CC_RPT_SET_VOLUME_DOWN(buffer);
break;
case HID_CONSUMER_MUTE:
HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_MUTE);
break;
case HID_CONSUMER_POWER:
HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_POWER);
break;
case HID_CONSUMER_RECALL_LAST:
HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_LAST);
break;
case HID_CONSUMER_ASSIGN_SEL:
HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_ASSIGN_SEL);
break;
case HID_CONSUMER_PLAY:
HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_PLAY);
break;
case HID_CONSUMER_PAUSE:
HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_PAUSE);
break;
case HID_CONSUMER_RECORD:
HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_RECORD);
break;
case HID_CONSUMER_FAST_FORWARD:
HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_FAST_FWD);
break;
case HID_CONSUMER_REWIND:
HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_REWIND);
break;
case HID_CONSUMER_SCAN_NEXT_TRK:
HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_SCAN_NEXT_TRK);
break;
case HID_CONSUMER_SCAN_PREV_TRK:
HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_SCAN_PREV_TRK);
break;
case HID_CONSUMER_STOP:
HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_STOP);
break;
default:
break;
}
return;
}

View File

@ -0,0 +1,257 @@
// Copyright 2017-2018 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.
#ifndef HID_DEV_H__
#define HID_DEV_H__
#include "hidd_le_prf_int.h"
#ifdef __cplusplus
extern "C" {
#endif
/* HID Report type */
#define HID_TYPE_INPUT 1
#define HID_TYPE_OUTPUT 2
#define HID_TYPE_FEATURE 3
// HID Keyboard/Keypad Usage IDs (subset of the codes available in the USB HID Usage Tables spec)
#define HID_KEY_RESERVED 0 // No event inidicated
#define HID_KEY_A 4 // Keyboard a and A
#define HID_KEY_B 5 // Keyboard b and B
#define HID_KEY_C 6 // Keyboard c and C
#define HID_KEY_D 7 // Keyboard d and D
#define HID_KEY_E 8 // Keyboard e and E
#define HID_KEY_F 9 // Keyboard f and F
#define HID_KEY_G 10 // Keyboard g and G
#define HID_KEY_H 11 // Keyboard h and H
#define HID_KEY_I 12 // Keyboard i and I
#define HID_KEY_J 13 // Keyboard j and J
#define HID_KEY_K 14 // Keyboard k and K
#define HID_KEY_L 15 // Keyboard l and L
#define HID_KEY_M 16 // Keyboard m and M
#define HID_KEY_N 17 // Keyboard n and N
#define HID_KEY_O 18 // Keyboard o and O
#define HID_KEY_P 19 // Keyboard p and p
#define HID_KEY_Q 20 // Keyboard q and Q
#define HID_KEY_R 21 // Keyboard r and R
#define HID_KEY_S 22 // Keyboard s and S
#define HID_KEY_T 23 // Keyboard t and T
#define HID_KEY_U 24 // Keyboard u and U
#define HID_KEY_V 25 // Keyboard v and V
#define HID_KEY_W 26 // Keyboard w and W
#define HID_KEY_X 27 // Keyboard x and X
#define HID_KEY_Y 28 // Keyboard y and Y
#define HID_KEY_Z 29 // Keyboard z and Z
#define HID_KEY_1 30 // Keyboard 1 and !
#define HID_KEY_2 31 // Keyboard 2 and @
#define HID_KEY_3 32 // Keyboard 3 and #
#define HID_KEY_4 33 // Keyboard 4 and %
#define HID_KEY_5 34 // Keyboard 5 and %
#define HID_KEY_6 35 // Keyboard 6 and ^
#define HID_KEY_7 36 // Keyboard 7 and &
#define HID_KEY_8 37 // Keyboard 8 and *
#define HID_KEY_9 38 // Keyboard 9 and (
#define HID_KEY_0 39 // Keyboard 0 and )
#define HID_KEY_RETURN 40 // Keyboard Return (ENTER)
#define HID_KEY_ESCAPE 41 // Keyboard ESCAPE
#define HID_KEY_DELETE 42 // Keyboard DELETE (Backspace)
#define HID_KEY_TAB 43 // Keyboard Tab
#define HID_KEY_SPACEBAR 44 // Keyboard Spacebar
#define HID_KEY_MINUS 45 // Keyboard - and (underscore)
#define HID_KEY_EQUAL 46 // Keyboard = and +
#define HID_KEY_LEFT_BRKT 47 // Keyboard [ and {
#define HID_KEY_RIGHT_BRKT 48 // Keyboard ] and }
#define HID_KEY_BACK_SLASH 49 // Keyboard \ and |
#define HID_KEY_SEMI_COLON 51 // Keyboard ; and :
#define HID_KEY_SGL_QUOTE 52 // Keyboard ' and "
#define HID_KEY_GRV_ACCENT 53 // Keyboard Grave Accent and Tilde
#define HID_KEY_COMMA 54 // Keyboard , and <
#define HID_KEY_DOT 55 // Keyboard . and >
#define HID_KEY_FWD_SLASH 56 // Keyboard / and ?
#define HID_KEY_CAPS_LOCK 57 // Keyboard Caps Lock
#define HID_KEY_F1 58 // Keyboard F1
#define HID_KEY_F2 59 // Keyboard F2
#define HID_KEY_F3 60 // Keyboard F3
#define HID_KEY_F4 61 // Keyboard F4
#define HID_KEY_F5 62 // Keyboard F5
#define HID_KEY_F6 63 // Keyboard F6
#define HID_KEY_F7 64 // Keyboard F7
#define HID_KEY_F8 65 // Keyboard F8
#define HID_KEY_F9 66 // Keyboard F9
#define HID_KEY_F10 67 // Keyboard F10
#define HID_KEY_F11 68 // Keyboard F11
#define HID_KEY_F12 69 // Keyboard F12
#define HID_KEY_PRNT_SCREEN 70 // Keyboard Print Screen
#define HID_KEY_SCROLL_LOCK 71 // Keyboard Scroll Lock
#define HID_KEY_PAUSE 72 // Keyboard Pause
#define HID_KEY_INSERT 73 // Keyboard Insert
#define HID_KEY_HOME 74 // Keyboard Home
#define HID_KEY_PAGE_UP 75 // Keyboard PageUp
#define HID_KEY_DELETE_FWD 76 // Keyboard Delete Forward
#define HID_KEY_END 77 // Keyboard End
#define HID_KEY_PAGE_DOWN 78 // Keyboard PageDown
#define HID_KEY_RIGHT_ARROW 79 // Keyboard RightArrow
#define HID_KEY_LEFT_ARROW 80 // Keyboard LeftArrow
#define HID_KEY_DOWN_ARROW 81 // Keyboard DownArrow
#define HID_KEY_UP_ARROW 82 // Keyboard UpArrow
#define HID_KEY_NUM_LOCK 83 // Keypad Num Lock and Clear
#define HID_KEY_DIVIDE 84 // Keypad /
#define HID_KEY_MULTIPLY 85 // Keypad *
#define HID_KEY_SUBTRACT 86 // Keypad -
#define HID_KEY_ADD 87 // Keypad +
#define HID_KEY_ENTER 88 // Keypad ENTER
#define HID_KEYPAD_1 89 // Keypad 1 and End
#define HID_KEYPAD_2 90 // Keypad 2 and Down Arrow
#define HID_KEYPAD_3 91 // Keypad 3 and PageDn
#define HID_KEYPAD_4 92 // Keypad 4 and Lfet Arrow
#define HID_KEYPAD_5 93 // Keypad 5
#define HID_KEYPAD_6 94 // Keypad 6 and Right Arrow
#define HID_KEYPAD_7 95 // Keypad 7 and Home
#define HID_KEYPAD_8 96 // Keypad 8 and Up Arrow
#define HID_KEYPAD_9 97 // Keypad 9 and PageUp
#define HID_KEYPAD_0 98 // Keypad 0 and Insert
#define HID_KEYPAD_DOT 99 // Keypad . and Delete
#define HID_KEY_MUTE 127 // Keyboard Mute
#define HID_KEY_VOLUME_UP 128 // Keyboard Volume up
#define HID_KEY_VOLUME_DOWN 129 // Keyboard Volume down
#define HID_KEY_LEFT_CTRL 224 // Keyboard LeftContorl
#define HID_KEY_LEFT_SHIFT 225 // Keyboard LeftShift
#define HID_KEY_LEFT_ALT 226 // Keyboard LeftAlt
#define HID_KEY_LEFT_GUI 227 // Keyboard LeftGUI
#define HID_KEY_RIGHT_CTRL 228 // Keyboard LeftContorl
#define HID_KEY_RIGHT_SHIFT 229 // Keyboard LeftShift
#define HID_KEY_RIGHT_ALT 230 // Keyboard LeftAlt
#define HID_KEY_RIGHT_GUI 231 // Keyboard RightGUI
typedef uint8_t keyboard_cmd_t;
#define HID_MOUSE_LEFT 253
#define HID_MOUSE_MIDDLE 254
#define HID_MOUSE_RIGHT 255
typedef uint8_t mouse_cmd_t;
// HID Consumer Usage IDs (subset of the codes available in the USB HID Usage Tables spec)
#define HID_CONSUMER_POWER 48 // Power
#define HID_CONSUMER_RESET 49 // Reset
#define HID_CONSUMER_SLEEP 50 // Sleep
#define HID_CONSUMER_MENU 64 // Menu
#define HID_CONSUMER_SELECTION 128 // Selection
#define HID_CONSUMER_ASSIGN_SEL 129 // Assign Selection
#define HID_CONSUMER_MODE_STEP 130 // Mode Step
#define HID_CONSUMER_RECALL_LAST 131 // Recall Last
#define HID_CONSUMER_QUIT 148 // Quit
#define HID_CONSUMER_HELP 149 // Help
#define HID_CONSUMER_CHANNEL_UP 156 // Channel Increment
#define HID_CONSUMER_CHANNEL_DOWN 157 // Channel Decrement
#define HID_CONSUMER_PLAY 176 // Play
#define HID_CONSUMER_PAUSE 177 // Pause
#define HID_CONSUMER_RECORD 178 // Record
#define HID_CONSUMER_FAST_FORWARD 179 // Fast Forward
#define HID_CONSUMER_REWIND 180 // Rewind
#define HID_CONSUMER_SCAN_NEXT_TRK 181 // Scan Next Track
#define HID_CONSUMER_SCAN_PREV_TRK 182 // Scan Previous Track
#define HID_CONSUMER_STOP 183 // Stop
#define HID_CONSUMER_EJECT 184 // Eject
#define HID_CONSUMER_RANDOM_PLAY 185 // Random Play
#define HID_CONSUMER_SELECT_DISC 186 // Select Disk
#define HID_CONSUMER_ENTER_DISC 187 // Enter Disc
#define HID_CONSUMER_REPEAT 188 // Repeat
#define HID_CONSUMER_STOP_EJECT 204 // Stop/Eject
#define HID_CONSUMER_PLAY_PAUSE 205 // Play/Pause
#define HID_CONSUMER_PLAY_SKIP 206 // Play/Skip
#define HID_CONSUMER_VOLUME 224 // Volume
#define HID_CONSUMER_BALANCE 225 // Balance
#define HID_CONSUMER_MUTE 226 // Mute
#define HID_CONSUMER_BASS 227 // Bass
#define HID_CONSUMER_VOLUME_UP 233 // Volume Increment
#define HID_CONSUMER_VOLUME_DOWN 234 // Volume Decrement
typedef uint8_t consumer_cmd_t;
#define HID_CC_RPT_MUTE 1
#define HID_CC_RPT_POWER 2
#define HID_CC_RPT_LAST 3
#define HID_CC_RPT_ASSIGN_SEL 4
#define HID_CC_RPT_PLAY 5
#define HID_CC_RPT_PAUSE 6
#define HID_CC_RPT_RECORD 7
#define HID_CC_RPT_FAST_FWD 8
#define HID_CC_RPT_REWIND 9
#define HID_CC_RPT_SCAN_NEXT_TRK 10
#define HID_CC_RPT_SCAN_PREV_TRK 11
#define HID_CC_RPT_STOP 12
#define HID_CC_RPT_CHANNEL_UP 0x01
#define HID_CC_RPT_CHANNEL_DOWN 0x03
#define HID_CC_RPT_VOLUME_UP 0x40
#define HID_CC_RPT_VOLUME_DOWN 0x80
// HID Consumer Control report bitmasks
#define HID_CC_RPT_NUMERIC_BITS 0xF0
#define HID_CC_RPT_CHANNEL_BITS 0xCF
#define HID_CC_RPT_VOLUME_BITS 0x3F
#define HID_CC_RPT_BUTTON_BITS 0xF0
#define HID_CC_RPT_SELECTION_BITS 0xCF
// Macros for the HID Consumer Control 2-byte report
#define HID_CC_RPT_SET_NUMERIC(s, x) (s)[0] &= HID_CC_RPT_NUMERIC_BITS; \
(s)[0] = (x)
#define HID_CC_RPT_SET_CHANNEL(s, x) (s)[0] &= HID_CC_RPT_CHANNEL_BITS; \
(s)[0] |= ((x) & 0x03) << 4
#define HID_CC_RPT_SET_VOLUME_UP(s) (s)[0] &= HID_CC_RPT_VOLUME_BITS; \
(s)[0] |= 0x40
#define HID_CC_RPT_SET_VOLUME_DOWN(s) (s)[0] &= HID_CC_RPT_VOLUME_BITS; \
(s)[0] |= 0x80
#define HID_CC_RPT_SET_BUTTON(s, x) (s)[1] &= HID_CC_RPT_BUTTON_BITS; \
(s)[1] |= (x)
#define HID_CC_RPT_SET_SELECTION(s, x) (s)[1] &= HID_CC_RPT_SELECTION_BITS; \
(s)[1] |= ((x) & 0x03) << 4
// HID report mapping table
typedef struct
{
uint16_t handle; // Handle of report characteristic
uint16_t cccdHandle; // Handle of CCCD for report characteristic
uint8_t id; // Report ID
uint8_t type; // Report type
uint8_t mode; // Protocol mode (report or boot)
} hid_report_map_t;
// HID dev configuration structure
typedef struct
{
uint32_t idleTimeout; // Idle timeout in milliseconds
uint8_t hidFlags; // HID feature flags
} hid_dev_cfg_t;
void hid_dev_register_reports(uint8_t num_reports, hid_report_map_t *p_report);
void hid_dev_send_report(esp_gatt_if_t gatts_if, uint16_t conn_id,
uint8_t id, uint8_t type, uint8_t length, uint8_t *data);
void hid_consumer_build_report(uint8_t *buffer, consumer_cmd_t cmd);
void hid_keyboard_build_report(uint8_t *buffer, keyboard_cmd_t cmd);
void hid_mouse_build_report(uint8_t *buffer, mouse_cmd_t cmd);
#endif /* HID_DEV_H__ */

View File

@ -0,0 +1,762 @@
// Copyright 2017-2018 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 "hidd_le_prf_int.h"
#include <string.h>
#include "bt_types.h"
#include "bt_trace.h"
//#include "esp_gap_ble_api.h"
/// characteristic presentation information
struct prf_char_pres_fmt
{
/// Unit (The Unit is a UUID)
uint16_t unit;
/// Description
uint16_t description;
/// Format
uint8_t format;
/// Exponent
uint8_t exponent;
/// Name space
uint8_t name_space;
};
// HID report mapping table
static hid_report_map_t hid_rpt_map[HID_NUM_REPORTS];
// HID Report Map characteristic value
// Keyboard report descriptor (using format for Boot interface descriptor)
static const uint8_t hidReportMap[] = {
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application)
0x85, 0x01, // Report Id (1)
0x09, 0x01, // Usage (Pointer)
0xA1, 0x00, // Collection (Physical)
0x05, 0x09, // Usage Page (Buttons)
0x19, 0x01, // Usage Minimum (01) - Button 1
0x29, 0x03, // Usage Maximum (03) - Button 3
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x03, // Report Count (3)
0x81, 0x02, // Input (Data, Variable, Absolute) - Button states
0x75, 0x05, // Report Size (5)
0x95, 0x01, // Report Count (1)
0x81, 0x01, // Input (Constant) - Padding or Reserved bits
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, Variable, Relative) - X & Y coordinate
0xC0, // End Collection
0xC0, // End Collection
0x05, 0x01, // Usage Pg (Generic Desktop)
0x09, 0x06, // Usage (Keyboard)
0xA1, 0x01, // Collection: (Application)
0x85, 0x02, // Report Id (2)
//
0x05, 0x07, // Usage Pg (Key Codes)
0x19, 0xE0, // Usage Min (224)
0x29, 0xE7, // Usage Max (231)
0x15, 0x00, // Log Min (0)
0x25, 0x01, // Log Max (1)
//
// Modifier byte
0x75, 0x01, // Report Size (1)
0x95, 0x08, // Report Count (8)
0x81, 0x02, // Input: (Data, Variable, Absolute)
//
// Reserved byte
0x95, 0x01, // Report Count (1)
0x75, 0x08, // Report Size (8)
0x81, 0x01, // Input: (Constant)
//
// LED report
0x95, 0x05, // Report Count (5)
0x75, 0x01, // Report Size (1)
0x05, 0x08, // Usage Pg (LEDs)
0x19, 0x01, // Usage Min (1)
0x29, 0x05, // Usage Max (5)
0x91, 0x02, // Output: (Data, Variable, Absolute)
//
// LED report padding
0x95, 0x01, // Report Count (1)
0x75, 0x03, // Report Size (3)
0x91, 0x01, // Output: (Constant)
//
// Key arrays (6 bytes)
0x95, 0x06, // Report Count (6)
0x75, 0x08, // Report Size (8)
0x15, 0x00, // Log Min (0)
0x25, 0x65, // Log Max (101)
0x05, 0x07, // Usage Pg (Key Codes)
0x19, 0x00, // Usage Min (0)
0x29, 0x65, // Usage Max (101)
0x81, 0x00, // Input: (Data, Array)
//
0xC0, // End Collection
//
0x05, 0x0C, // Usage Pg (Consumer Devices)
0x09, 0x01, // Usage (Consumer Control)
0xA1, 0x01, // Collection (Application)
0x85, 0x03, // Report Id (3)
0x09, 0x02, // Usage (Numeric Key Pad)
0xA1, 0x02, // Collection (Logical)
0x05, 0x09, // Usage Pg (Button)
0x19, 0x01, // Usage Min (Button 1)
0x29, 0x0A, // Usage Max (Button 10)
0x15, 0x01, // Logical Min (1)
0x25, 0x0A, // Logical Max (10)
0x75, 0x04, // Report Size (4)
0x95, 0x01, // Report Count (1)
0x81, 0x00, // Input (Data, Ary, Abs)
0xC0, // End Collection
0x05, 0x0C, // Usage Pg (Consumer Devices)
0x09, 0x86, // Usage (Channel)
0x15, 0xFF, // Logical Min (-1)
0x25, 0x01, // Logical Max (1)
0x75, 0x02, // Report Size (2)
0x95, 0x01, // Report Count (1)
0x81, 0x46, // Input (Data, Var, Rel, Null)
0x09, 0xE9, // Usage (Volume Up)
0x09, 0xEA, // Usage (Volume Down)
0x15, 0x00, // Logical Min (0)
0x75, 0x01, // Report Size (1)
0x95, 0x02, // Report Count (2)
0x81, 0x02, // Input (Data, Var, Abs)
0x09, 0xE2, // Usage (Mute)
0x09, 0x30, // Usage (Power)
0x09, 0x83, // Usage (Recall Last)
0x09, 0x81, // Usage (Assign Selection)
0x09, 0xB0, // Usage (Play)
0x09, 0xB1, // Usage (Pause)
0x09, 0xB2, // Usage (Record)
0x09, 0xB3, // Usage (Fast Forward)
0x09, 0xB4, // Usage (Rewind)
0x09, 0xB5, // Usage (Scan Next)
0x09, 0xB6, // Usage (Scan Prev)
0x09, 0xB7, // Usage (Stop)
0x15, 0x01, // Logical Min (1)
0x25, 0x0C, // Logical Max (12)
0x75, 0x04, // Report Size (4)
0x95, 0x01, // Report Count (1)
0x81, 0x00, // Input (Data, Ary, Abs)
0x09, 0x80, // Usage (Selection)
0xA1, 0x02, // Collection (Logical)
0x05, 0x09, // Usage Pg (Button)
0x19, 0x01, // Usage Min (Button 1)
0x29, 0x03, // Usage Max (Button 3)
0x15, 0x01, // Logical Min (1)
0x25, 0x03, // Logical Max (3)
0x75, 0x02, // Report Size (2)
0x81, 0x00, // Input (Data, Ary, Abs)
0xC0, // End Collection
0x81, 0x03, // Input (Const, Var, Abs)
0xC0, // End Collection
0x06, 0xFF, 0xFF, // Usage Page(Vendor defined)
0x09, 0xA5, // Usage(Vendor Defined)
0xA1, 0x01, // Collection(Application)
0x85, 0x04, // Report Id (4)
0x09, 0xA6, // Usage(Vendor defined)
0x09, 0xA9, // Usage(Vendor defined)
0x75, 0x08, // Report Size
0x95, 0x7F, // Report Count = 127 Btyes
0x91, 0x02, // Output(Data, Variable, Absolute)
0xC0, // End Collection
};
/// Battery Service Attributes Indexes
enum
{
BAS_IDX_SVC,
BAS_IDX_BATT_LVL_CHAR,
BAS_IDX_BATT_LVL_VAL,
BAS_IDX_BATT_LVL_NTF_CFG,
BAS_IDX_BATT_LVL_PRES_FMT,
BAS_IDX_NB,
};
#define HI_UINT16(a) (((a) >> 8) & 0xFF)
#define LO_UINT16(a) ((a) & 0xFF)
hidd_le_env_t hidd_le_env;
// HID report map length
uint8_t hidReportMapLen = sizeof(hidReportMap);
uint8_t hidProtocolMode = HID_PROTOCOL_MODE_REPORT;
// HID report mapping table
//static hidRptMap_t hidRptMap[HID_NUM_REPORTS];
// HID Information characteristic value
static const uint8_t hidInfo[HID_INFORMATION_LEN] = {
LO_UINT16(0x0111), HI_UINT16(0x0111), // bcdHID (USB HID version)
0x00, // bCountryCode
HID_KBD_FLAGS // Flags
};
// HID External Report Reference Descriptor
static uint16_t hidExtReportRefDesc = ESP_GATT_UUID_BATTERY_LEVEL;
// HID Report Reference characteristic descriptor, mouse input
static uint8_t hidReportRefMouseIn[HID_REPORT_REF_LEN] =
{ HID_RPT_ID_MOUSE_IN, HID_REPORT_TYPE_INPUT };
// HID Report Reference characteristic descriptor, key input
static uint8_t hidReportRefKeyIn[HID_REPORT_REF_LEN] =
{ HID_RPT_ID_KEY_IN, HID_REPORT_TYPE_INPUT };
// HID Report Reference characteristic descriptor, LED output
static uint8_t hidReportRefLedOut[HID_REPORT_REF_LEN] =
{ HID_RPT_ID_LED_OUT, HID_REPORT_TYPE_OUTPUT };
static uint8_t hidReportRefVendorOut[HID_REPORT_REF_LEN] =
{HID_RPT_ID_VENDOR_OUT, HID_REPORT_TYPE_OUTPUT};
// HID Report Reference characteristic descriptor, Feature
static uint8_t hidReportRefFeature[HID_REPORT_REF_LEN] =
{ HID_RPT_ID_FEATURE, HID_REPORT_TYPE_FEATURE };
// HID Report Reference characteristic descriptor, consumer control input
static uint8_t hidReportRefCCIn[HID_REPORT_REF_LEN] =
{ HID_RPT_ID_CC_IN, HID_REPORT_TYPE_INPUT };
/*
* Heart Rate PROFILE ATTRIBUTES
****************************************************************************************
*/
/// hid Service uuid
static uint16_t hid_le_svc = ATT_SVC_HID;
uint16_t hid_count = 0;
esp_gatts_incl_svc_desc_t incl_svc = {0};
#define CHAR_DECLARATION_SIZE (sizeof(uint8_t))
///the uuid definition
static const uint16_t primary_service_uuid = ESP_GATT_UUID_PRI_SERVICE;
static const uint16_t include_service_uuid = ESP_GATT_UUID_INCLUDE_SERVICE;
static const uint16_t character_declaration_uuid = ESP_GATT_UUID_CHAR_DECLARE;
static const uint16_t character_client_config_uuid = ESP_GATT_UUID_CHAR_CLIENT_CONFIG;
static const uint16_t hid_info_char_uuid = ESP_GATT_UUID_HID_INFORMATION;
static const uint16_t hid_report_map_uuid = ESP_GATT_UUID_HID_REPORT_MAP;
static const uint16_t hid_control_point_uuid = ESP_GATT_UUID_HID_CONTROL_POINT;
static const uint16_t hid_report_uuid = ESP_GATT_UUID_HID_REPORT;
static const uint16_t hid_proto_mode_uuid = ESP_GATT_UUID_HID_PROTO_MODE;
static const uint16_t hid_kb_input_uuid = ESP_GATT_UUID_HID_BT_KB_INPUT;
static const uint16_t hid_kb_output_uuid = ESP_GATT_UUID_HID_BT_KB_OUTPUT;
static const uint16_t hid_mouse_input_uuid = ESP_GATT_UUID_HID_BT_MOUSE_INPUT;
static const uint16_t hid_repot_map_ext_desc_uuid = ESP_GATT_UUID_EXT_RPT_REF_DESCR;
static const uint16_t hid_report_ref_descr_uuid = ESP_GATT_UUID_RPT_REF_DESCR;
///the propoty definition
static const uint8_t char_prop_notify = ESP_GATT_CHAR_PROP_BIT_NOTIFY;
static const uint8_t char_prop_read = ESP_GATT_CHAR_PROP_BIT_READ;
static const uint8_t char_prop_write = ESP_GATT_CHAR_PROP_BIT_WRITE;
static const uint8_t char_prop_read_write = ESP_GATT_CHAR_PROP_BIT_WRITE|ESP_GATT_CHAR_PROP_BIT_READ;
static const uint8_t char_prop_read_notify = ESP_GATT_CHAR_PROP_BIT_READ|ESP_GATT_CHAR_PROP_BIT_NOTIFY;
static const uint8_t char_prop_read_write_notify = ESP_GATT_CHAR_PROP_BIT_READ|ESP_GATT_CHAR_PROP_BIT_WRITE|ESP_GATT_CHAR_PROP_BIT_NOTIFY;
/// battary Service
static const uint16_t battary_svc = ESP_GATT_UUID_BATTERY_SERVICE_SVC;
static const uint16_t bat_lev_uuid = ESP_GATT_UUID_BATTERY_LEVEL;
static const uint8_t bat_lev_ccc[2] ={ 0x00, 0x00};
static const uint16_t char_format_uuid = ESP_GATT_UUID_CHAR_PRESENT_FORMAT;
static uint8_t battary_lev = 50;
/// Full HRS Database Description - Used to add attributes into the database
static const esp_gatts_attr_db_t bas_att_db[BAS_IDX_NB] =
{
// Battary Service Declaration
[BAS_IDX_SVC] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ,
sizeof(uint16_t), sizeof(battary_svc), (uint8_t *)&battary_svc}},
// Battary level Characteristic Declaration
[BAS_IDX_BATT_LVL_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}},
// Battary level Characteristic Value
[BAS_IDX_BATT_LVL_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&bat_lev_uuid, ESP_GATT_PERM_READ,
sizeof(uint8_t),sizeof(uint8_t), &battary_lev}},
// Battary level Characteristic - Client Characteristic Configuration Descriptor
[BAS_IDX_BATT_LVL_NTF_CFG] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,
sizeof(uint16_t),sizeof(bat_lev_ccc), (uint8_t *)bat_lev_ccc}},
// Battary level report Characteristic Declaration
[BAS_IDX_BATT_LVL_PRES_FMT] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&char_format_uuid, ESP_GATT_PERM_READ,
sizeof(struct prf_char_pres_fmt), 0, NULL}},
};
/// Full Hid device Database Description - Used to add attributes into the database
static esp_gatts_attr_db_t hidd_le_gatt_db[HIDD_LE_IDX_NB] =
{
// HID Service Declaration
[HIDD_LE_IDX_SVC] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid,
ESP_GATT_PERM_READ_ENCRYPTED, sizeof(uint16_t), sizeof(hid_le_svc),
(uint8_t *)&hid_le_svc}},
// HID Service Declaration
[HIDD_LE_IDX_INCL_SVC] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&include_service_uuid,
ESP_GATT_PERM_READ,
sizeof(esp_gatts_incl_svc_desc_t), sizeof(esp_gatts_incl_svc_desc_t),
(uint8_t *)&incl_svc}},
// HID Information Characteristic Declaration
[HIDD_LE_IDX_HID_INFO_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
ESP_GATT_PERM_READ,
CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
(uint8_t *)&char_prop_read_write}},
// HID Information Characteristic Value
[HIDD_LE_IDX_HID_INFO_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_info_char_uuid,
ESP_GATT_PERM_READ,
sizeof(hids_hid_info_t), sizeof(hidInfo),
(uint8_t *)&hidInfo}},
// HID Control Point Characteristic Declaration
[HIDD_LE_IDX_HID_CTNL_PT_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
ESP_GATT_PERM_READ,
CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
(uint8_t *)&char_prop_write}},
// HID Control Point Characteristic Value
[HIDD_LE_IDX_HID_CTNL_PT_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_control_point_uuid,
ESP_GATT_PERM_WRITE,
sizeof(uint8_t), 0,
NULL}},
// Report Map Characteristic Declaration
[HIDD_LE_IDX_REPORT_MAP_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
ESP_GATT_PERM_READ,
CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
(uint8_t *)&char_prop_read}},
// Report Map Characteristic Value
[HIDD_LE_IDX_REPORT_MAP_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_map_uuid,
ESP_GATT_PERM_READ,
HIDD_LE_REPORT_MAP_MAX_LEN, sizeof(hidReportMap),
(uint8_t *)&hidReportMap}},
// Report Map Characteristic - External Report Reference Descriptor
[HIDD_LE_IDX_REPORT_MAP_EXT_REP_REF] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_repot_map_ext_desc_uuid,
ESP_GATT_PERM_READ,
sizeof(uint16_t), sizeof(uint16_t),
(uint8_t *)&hidExtReportRefDesc}},
// Protocol Mode Characteristic Declaration
[HIDD_LE_IDX_PROTO_MODE_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
ESP_GATT_PERM_READ,
CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
(uint8_t *)&char_prop_read_write}},
// Protocol Mode Characteristic Value
[HIDD_LE_IDX_PROTO_MODE_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_proto_mode_uuid,
(ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE),
sizeof(uint8_t), sizeof(hidProtocolMode),
(uint8_t *)&hidProtocolMode}},
[HIDD_LE_IDX_REPORT_MOUSE_IN_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
ESP_GATT_PERM_READ,
CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
(uint8_t *)&char_prop_read_notify}},
[HIDD_LE_IDX_REPORT_MOUSE_IN_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_uuid,
ESP_GATT_PERM_READ,
HIDD_LE_REPORT_MAX_LEN, 0,
NULL}},
[HIDD_LE_IDX_REPORT_MOUSE_IN_CCC] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid,
(ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE),
sizeof(uint16_t), 0,
NULL}},
[HIDD_LE_IDX_REPORT_MOUSE_REP_REF] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_ref_descr_uuid,
ESP_GATT_PERM_READ,
sizeof(hidReportRefMouseIn), sizeof(hidReportRefMouseIn),
hidReportRefMouseIn}},
// Report Characteristic Declaration
[HIDD_LE_IDX_REPORT_KEY_IN_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
ESP_GATT_PERM_READ,
CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
(uint8_t *)&char_prop_read_notify}},
// Report Characteristic Value
[HIDD_LE_IDX_REPORT_KEY_IN_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_uuid,
ESP_GATT_PERM_READ,
HIDD_LE_REPORT_MAX_LEN, 0,
NULL}},
// Report KEY INPUT Characteristic - Client Characteristic Configuration Descriptor
[HIDD_LE_IDX_REPORT_KEY_IN_CCC] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid,
(ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE),
sizeof(uint16_t), 0,
NULL}},
// Report Characteristic - Report Reference Descriptor
[HIDD_LE_IDX_REPORT_KEY_IN_REP_REF] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_ref_descr_uuid,
ESP_GATT_PERM_READ,
sizeof(hidReportRefKeyIn), sizeof(hidReportRefKeyIn),
hidReportRefKeyIn}},
// Report Characteristic Declaration
[HIDD_LE_IDX_REPORT_LED_OUT_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
ESP_GATT_PERM_READ,
CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
(uint8_t *)&char_prop_read_write}},
[HIDD_LE_IDX_REPORT_LED_OUT_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_uuid,
ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,
HIDD_LE_REPORT_MAX_LEN, 0,
NULL}},
[HIDD_LE_IDX_REPORT_LED_OUT_REP_REF] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_ref_descr_uuid,
ESP_GATT_PERM_READ,
sizeof(hidReportRefLedOut), sizeof(hidReportRefLedOut),
hidReportRefLedOut}},
// Report Characteristic Declaration
[HIDD_LE_IDX_REPORT_VENDOR_OUT_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
ESP_GATT_PERM_READ,
CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
(uint8_t *)&char_prop_read_write_notify}},
[HIDD_LE_IDX_REPORT_VENDOR_OUT_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_uuid,
ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,
HIDD_LE_REPORT_MAX_LEN, 0,
NULL}},
[HIDD_LE_IDX_REPORT_VENDOR_OUT_REP_REF] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_ref_descr_uuid,
ESP_GATT_PERM_READ,
sizeof(hidReportRefVendorOut), sizeof(hidReportRefVendorOut),
hidReportRefVendorOut}},
// Report Characteristic Declaration
[HIDD_LE_IDX_REPORT_CC_IN_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
ESP_GATT_PERM_READ,
CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
(uint8_t *)&char_prop_read_notify}},
// Report Characteristic Value
[HIDD_LE_IDX_REPORT_CC_IN_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_uuid,
ESP_GATT_PERM_READ,
HIDD_LE_REPORT_MAX_LEN, 0,
NULL}},
// Report KEY INPUT Characteristic - Client Characteristic Configuration Descriptor
[HIDD_LE_IDX_REPORT_CC_IN_CCC] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid,
(ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE),
sizeof(uint16_t), 0,
NULL}},
// Report Characteristic - Report Reference Descriptor
[HIDD_LE_IDX_REPORT_CC_IN_REP_REF] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_ref_descr_uuid,
ESP_GATT_PERM_READ,
sizeof(hidReportRefCCIn), sizeof(hidReportRefCCIn),
hidReportRefCCIn}},
// Boot Keyboard Input Report Characteristic Declaration
[HIDD_LE_IDX_BOOT_KB_IN_REPORT_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
ESP_GATT_PERM_READ,
CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
(uint8_t *)&char_prop_read_notify}},
// Boot Keyboard Input Report Characteristic Value
[HIDD_LE_IDX_BOOT_KB_IN_REPORT_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_kb_input_uuid,
ESP_GATT_PERM_READ,
HIDD_LE_BOOT_REPORT_MAX_LEN, 0,
NULL}},
// Boot Keyboard Input Report Characteristic - Client Characteristic Configuration Descriptor
[HIDD_LE_IDX_BOOT_KB_IN_REPORT_NTF_CFG] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid,
(ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE),
sizeof(uint16_t), 0,
NULL}},
// Boot Keyboard Output Report Characteristic Declaration
[HIDD_LE_IDX_BOOT_KB_OUT_REPORT_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
ESP_GATT_PERM_READ,
CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
(uint8_t *)&char_prop_read_write}},
// Boot Keyboard Output Report Characteristic Value
[HIDD_LE_IDX_BOOT_KB_OUT_REPORT_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_kb_output_uuid,
(ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE),
HIDD_LE_BOOT_REPORT_MAX_LEN, 0,
NULL}},
// Boot Mouse Input Report Characteristic Declaration
[HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
ESP_GATT_PERM_READ,
CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
(uint8_t *)&char_prop_read_notify}},
// Boot Mouse Input Report Characteristic Value
[HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_mouse_input_uuid,
ESP_GATT_PERM_READ,
HIDD_LE_BOOT_REPORT_MAX_LEN, 0,
NULL}},
// Boot Mouse Input Report Characteristic - Client Characteristic Configuration Descriptor
[HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_NTF_CFG] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid,
(ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE),
sizeof(uint16_t), 0,
NULL}},
// Report Characteristic Declaration
[HIDD_LE_IDX_REPORT_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
ESP_GATT_PERM_READ,
CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
(uint8_t *)&char_prop_read_write}},
// Report Characteristic Value
[HIDD_LE_IDX_REPORT_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_uuid,
ESP_GATT_PERM_READ,
HIDD_LE_REPORT_MAX_LEN, 0,
NULL}},
// Report Characteristic - Report Reference Descriptor
[HIDD_LE_IDX_REPORT_REP_REF] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_ref_descr_uuid,
ESP_GATT_PERM_READ,
sizeof(hidReportRefFeature), sizeof(hidReportRefFeature),
hidReportRefFeature}},
};
static void hid_add_id_tbl(void);
void esp_hidd_prf_cb_hdl(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
esp_ble_gatts_cb_param_t *param)
{
switch(event) {
case ESP_GATTS_REG_EVT: {
esp_hidd_cb_param_t hidd_param;
hidd_param.init_finish.state = param->reg.status;
if(param->reg.app_id == HIDD_APP_ID) {
hidd_le_env.gatt_if = gatts_if;
if(hidd_le_env.hidd_cb != NULL) {
(hidd_le_env.hidd_cb)(ESP_HIDD_EVENT_REG_FINISH, &hidd_param);
hidd_le_create_service(hidd_le_env.gatt_if);
}
}
if(param->reg.app_id == BATTRAY_APP_ID) {
hidd_param.init_finish.gatts_if = gatts_if;
if(hidd_le_env.hidd_cb != NULL) {
(hidd_le_env.hidd_cb)(ESP_BAT_EVENT_REG, &hidd_param);
}
}
break;
}
case ESP_GATTS_CONF_EVT: {
break;
}
case ESP_GATTS_CREATE_EVT:
break;
case ESP_GATTS_CONNECT_EVT: {
esp_hidd_cb_param_t cb_param = {0};
LOG_ERROR("the connection establish, conn_id = %x",param->connect.conn_id);
memcpy(cb_param.connect.remote_bda, param->connect.remote_bda, sizeof(esp_bd_addr_t));
cb_param.connect.conn_id = param->connect.conn_id;
hidd_clcb_alloc(param->connect.conn_id, param->connect.remote_bda);
//esp_ble_set_encryption(param->connect.remote_bda, ESP_BLE_SEC_ENCRYPT_NO_MITM);
if(hidd_le_env.hidd_cb != NULL) {
(hidd_le_env.hidd_cb)(ESP_HIDD_EVENT_BLE_CONNECT, &cb_param);
}
break;
}
case ESP_GATTS_DISCONNECT_EVT: {
if(hidd_le_env.hidd_cb != NULL) {
(hidd_le_env.hidd_cb)(ESP_HIDD_EVENT_BLE_DISCONNECT, NULL);
}
hidd_clcb_dealloc(param->disconnect.conn_id);
break;
}
case ESP_GATTS_CLOSE_EVT:
break;
case ESP_GATTS_WRITE_EVT: {
esp_hidd_cb_param_t cb_param = {0};
if (param->write.handle == hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_VENDOR_OUT_VAL] &&
hidd_le_env.hidd_cb != NULL) {
cb_param.vendor_write.conn_id = param->write.conn_id;
cb_param.vendor_write.report_id = HID_RPT_ID_VENDOR_OUT;
cb_param.vendor_write.length = param->write.len;
cb_param.vendor_write.data = param->write.value;
(hidd_le_env.hidd_cb)(ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT, &cb_param);
}
break;
}
case ESP_GATTS_CREAT_ATTR_TAB_EVT: {
if (param->add_attr_tab.num_handle == BAS_IDX_NB &&
param->add_attr_tab.svc_uuid.uuid.uuid16 == ESP_GATT_UUID_BATTERY_SERVICE_SVC &&
param->add_attr_tab.status == ESP_GATT_OK) {
incl_svc.start_hdl = param->add_attr_tab.handles[BAS_IDX_SVC];
incl_svc.end_hdl = incl_svc.start_hdl + BAS_IDX_NB -1;
LOG_ERROR("%s(), start added the hid service to the stack database. incl_handle = %d",
__func__, incl_svc.start_hdl);
esp_ble_gatts_create_attr_tab(hidd_le_gatt_db, gatts_if, HIDD_LE_IDX_NB, 0);
}
if (param->add_attr_tab.num_handle == HIDD_LE_IDX_NB &&
param->add_attr_tab.status == ESP_GATT_OK) {
memcpy(hidd_le_env.hidd_inst.att_tbl, param->add_attr_tab.handles,
HIDD_LE_IDX_NB*sizeof(uint16_t));
LOG_ERROR("hid svc handle = %x",hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_SVC]);
hid_add_id_tbl();
esp_ble_gatts_start_service(hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_SVC]);
} else {
esp_ble_gatts_start_service(param->add_attr_tab.handles[0]);
}
break;
}
default:
break;
}
}
void hidd_le_create_service(esp_gatt_if_t gatts_if)
{
/* Here should added the battery service first, because the hid service should include the battery service.
After finish to added the battery service then can added the hid service. */
esp_ble_gatts_create_attr_tab(bas_att_db, gatts_if, BAS_IDX_NB, 0);
}
void hidd_le_init(void)
{
// Reset the hid device target environment
memset(&hidd_le_env, 0, sizeof(hidd_le_env_t));
}
void hidd_clcb_alloc (uint16_t conn_id, esp_bd_addr_t bda)
{
uint8_t i_clcb = 0;
hidd_clcb_t *p_clcb = NULL;
for (i_clcb = 0, p_clcb= hidd_le_env.hidd_clcb; i_clcb < HID_MAX_APPS; i_clcb++, p_clcb++) {
if (!p_clcb->in_use) {
p_clcb->in_use = TRUE;
p_clcb->conn_id = conn_id;
p_clcb->connected = TRUE;
memcpy (p_clcb->remote_bda, bda, ESP_BD_ADDR_LEN);
break;
}
}
return;
}
bool hidd_clcb_dealloc (uint16_t conn_id)
{
uint8_t i_clcb = 0;
hidd_clcb_t *p_clcb = NULL;
for (i_clcb = 0, p_clcb= hidd_le_env.hidd_clcb; i_clcb < HID_MAX_APPS; i_clcb++, p_clcb++) {
memset(p_clcb, 0, sizeof(hidd_clcb_t));
return TRUE;
}
return FALSE;
}
esp_err_t hidd_register_cb(void)
{
esp_err_t status;
status = esp_ble_gatts_register_callback(esp_hidd_prf_cb_hdl);
return status;
}
void hidd_set_attr_value(uint16_t handle, uint16_t val_len, const uint8_t *value)
{
hidd_inst_t *hidd_inst = &hidd_le_env.hidd_inst;
if(hidd_inst->att_tbl[HIDD_LE_IDX_HID_INFO_VAL] <= handle &&
hidd_inst->att_tbl[HIDD_LE_IDX_REPORT_REP_REF] >= handle) {
esp_ble_gatts_set_attr_value(handle, val_len, value);
} else {
LOG_ERROR("%s error:Invalid handle value.",__func__);
}
return;
}
void hidd_get_attr_value(uint16_t handle, uint16_t *length, uint8_t **value)
{
hidd_inst_t *hidd_inst = &hidd_le_env.hidd_inst;
if(hidd_inst->att_tbl[HIDD_LE_IDX_HID_INFO_VAL] <= handle &&
hidd_inst->att_tbl[HIDD_LE_IDX_REPORT_REP_REF] >= handle){
esp_ble_gatts_get_attr_value(handle, length, (const uint8_t **)value);
} else {
LOG_ERROR("%s error:Invalid handle value.", __func__);
}
return;
}
static void hid_add_id_tbl(void)
{
// Mouse input report
hid_rpt_map[0].id = hidReportRefMouseIn[0];
hid_rpt_map[0].type = hidReportRefMouseIn[1];
hid_rpt_map[0].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_MOUSE_IN_VAL];
hid_rpt_map[0].cccdHandle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_MOUSE_IN_VAL];
hid_rpt_map[0].mode = HID_PROTOCOL_MODE_REPORT;
// Key input report
hid_rpt_map[1].id = hidReportRefKeyIn[0];
hid_rpt_map[1].type = hidReportRefKeyIn[1];
hid_rpt_map[1].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_KEY_IN_VAL];
hid_rpt_map[1].cccdHandle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_KEY_IN_CCC];
hid_rpt_map[1].mode = HID_PROTOCOL_MODE_REPORT;
// Consumer Control input report
hid_rpt_map[2].id = hidReportRefCCIn[0];
hid_rpt_map[2].type = hidReportRefCCIn[1];
hid_rpt_map[2].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_CC_IN_VAL];
hid_rpt_map[2].cccdHandle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_CC_IN_CCC];
hid_rpt_map[2].mode = HID_PROTOCOL_MODE_REPORT;
// LED output report
hid_rpt_map[3].id = hidReportRefLedOut[0];
hid_rpt_map[3].type = hidReportRefLedOut[1];
hid_rpt_map[3].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_LED_OUT_VAL];
hid_rpt_map[3].cccdHandle = 0;
hid_rpt_map[3].mode = HID_PROTOCOL_MODE_REPORT;
// Boot keyboard input report
// Use same ID and type as key input report
hid_rpt_map[4].id = hidReportRefKeyIn[0];
hid_rpt_map[4].type = hidReportRefKeyIn[1];
hid_rpt_map[4].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_BOOT_KB_IN_REPORT_VAL];
hid_rpt_map[4].cccdHandle = 0;
hid_rpt_map[4].mode = HID_PROTOCOL_MODE_BOOT;
// Boot keyboard output report
// Use same ID and type as LED output report
hid_rpt_map[5].id = hidReportRefLedOut[0];
hid_rpt_map[5].type = hidReportRefLedOut[1];
hid_rpt_map[5].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_BOOT_KB_OUT_REPORT_VAL];
hid_rpt_map[5].cccdHandle = 0;
hid_rpt_map[5].mode = HID_PROTOCOL_MODE_BOOT;
// Boot mouse input report
// Use same ID and type as mouse input report
hid_rpt_map[6].id = hidReportRefMouseIn[0];
hid_rpt_map[6].type = hidReportRefMouseIn[1];
hid_rpt_map[6].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_VAL];
hid_rpt_map[6].cccdHandle = 0;
hid_rpt_map[6].mode = HID_PROTOCOL_MODE_BOOT;
// Feature report
hid_rpt_map[7].id = hidReportRefFeature[0];
hid_rpt_map[7].type = hidReportRefFeature[1];
hid_rpt_map[7].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_VAL];
hid_rpt_map[7].cccdHandle = 0;
hid_rpt_map[7].mode = HID_PROTOCOL_MODE_REPORT;
// Setup report ID map
hid_dev_register_reports(HID_NUM_REPORTS, hid_rpt_map);
}

View File

@ -0,0 +1,339 @@
// Copyright 2017-2018 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.
#ifndef __HID_DEVICE_LE_PRF__
#define __HID_DEVICE_LE_PRF__
#include "esp_gatts_api.h"
#include "esp_gatt_defs.h"
#include "esp_hidd_prf_api.h"
#include "esp_gap_ble_api.h"
#include "hid_dev.h"
/// Maximal number of HIDS that can be added in the DB
#ifndef USE_ONE_HIDS_INSTANCE
#define HIDD_LE_NB_HIDS_INST_MAX (2)
#else
#define HIDD_LE_NB_HIDS_INST_MAX (1)
#endif
#define HIDD_GREAT_VER 0x01 //Version + Subversion
#define HIDD_SUB_VER 0x00 //Version + Subversion
#define HIDD_VERSION ((HIDD_GREAT_VER<<8)|HIDD_SUB_VER) //Version + Subversion
#define HID_MAX_APPS 1
// Number of HID reports defined in the service
#define HID_NUM_REPORTS 9
// HID Report IDs for the service
#define HID_RPT_ID_MOUSE_IN 1 // Mouse input report ID
#define HID_RPT_ID_KEY_IN 2 // Keyboard input report ID
#define HID_RPT_ID_CC_IN 3 //Consumer Control input report ID
#define HID_RPT_ID_VENDOR_OUT 4 // Vendor output report ID
#define HID_RPT_ID_LED_OUT 0 // LED output report ID
#define HID_RPT_ID_FEATURE 0 // Feature report ID
#define HIDD_APP_ID 0x1812//ATT_SVC_HID
#define BATTRAY_APP_ID 0x180f
#define ATT_SVC_HID 0x1812
/// Maximal number of Report Char. that can be added in the DB for one HIDS - Up to 11
#define HIDD_LE_NB_REPORT_INST_MAX (5)
/// Maximal length of Report Char. Value
#define HIDD_LE_REPORT_MAX_LEN (255)
/// Maximal length of Report Map Char. Value
#define HIDD_LE_REPORT_MAP_MAX_LEN (512)
/// Length of Boot Report Char. Value Maximal Length
#define HIDD_LE_BOOT_REPORT_MAX_LEN (8)
/// Boot KB Input Report Notification Configuration Bit Mask
#define HIDD_LE_BOOT_KB_IN_NTF_CFG_MASK (0x40)
/// Boot KB Input Report Notification Configuration Bit Mask
#define HIDD_LE_BOOT_MOUSE_IN_NTF_CFG_MASK (0x80)
/// Boot Report Notification Configuration Bit Mask
#define HIDD_LE_REPORT_NTF_CFG_MASK (0x20)
/* HID information flags */
#define HID_FLAGS_REMOTE_WAKE 0x01 // RemoteWake
#define HID_FLAGS_NORMALLY_CONNECTABLE 0x02 // NormallyConnectable
/* Control point commands */
#define HID_CMD_SUSPEND 0x00 // Suspend
#define HID_CMD_EXIT_SUSPEND 0x01 // Exit Suspend
/* HID protocol mode values */
#define HID_PROTOCOL_MODE_BOOT 0x00 // Boot Protocol Mode
#define HID_PROTOCOL_MODE_REPORT 0x01 // Report Protocol Mode
/* Attribute value lengths */
#define HID_PROTOCOL_MODE_LEN 1 // HID Protocol Mode
#define HID_INFORMATION_LEN 4 // HID Information
#define HID_REPORT_REF_LEN 2 // HID Report Reference Descriptor
#define HID_EXT_REPORT_REF_LEN 2 // External Report Reference Descriptor
// HID feature flags
#define HID_KBD_FLAGS HID_FLAGS_REMOTE_WAKE
/* HID Report type */
#define HID_REPORT_TYPE_INPUT 1
#define HID_REPORT_TYPE_OUTPUT 2
#define HID_REPORT_TYPE_FEATURE 3
/// HID Service Attributes Indexes
enum {
HIDD_LE_IDX_SVC,
// Included Service
HIDD_LE_IDX_INCL_SVC,
// HID Information
HIDD_LE_IDX_HID_INFO_CHAR,
HIDD_LE_IDX_HID_INFO_VAL,
// HID Control Point
HIDD_LE_IDX_HID_CTNL_PT_CHAR,
HIDD_LE_IDX_HID_CTNL_PT_VAL,
// Report Map
HIDD_LE_IDX_REPORT_MAP_CHAR,
HIDD_LE_IDX_REPORT_MAP_VAL,
HIDD_LE_IDX_REPORT_MAP_EXT_REP_REF,
// Protocol Mode
HIDD_LE_IDX_PROTO_MODE_CHAR,
HIDD_LE_IDX_PROTO_MODE_VAL,
// Report mouse input
HIDD_LE_IDX_REPORT_MOUSE_IN_CHAR,
HIDD_LE_IDX_REPORT_MOUSE_IN_VAL,
HIDD_LE_IDX_REPORT_MOUSE_IN_CCC,
HIDD_LE_IDX_REPORT_MOUSE_REP_REF,
//Report Key input
HIDD_LE_IDX_REPORT_KEY_IN_CHAR,
HIDD_LE_IDX_REPORT_KEY_IN_VAL,
HIDD_LE_IDX_REPORT_KEY_IN_CCC,
HIDD_LE_IDX_REPORT_KEY_IN_REP_REF,
///Report Led output
HIDD_LE_IDX_REPORT_LED_OUT_CHAR,
HIDD_LE_IDX_REPORT_LED_OUT_VAL,
HIDD_LE_IDX_REPORT_LED_OUT_REP_REF,
/// Report Vendor
HIDD_LE_IDX_REPORT_VENDOR_OUT_CHAR,
HIDD_LE_IDX_REPORT_VENDOR_OUT_VAL,
HIDD_LE_IDX_REPORT_VENDOR_OUT_REP_REF,
HIDD_LE_IDX_REPORT_CC_IN_CHAR,
HIDD_LE_IDX_REPORT_CC_IN_VAL,
HIDD_LE_IDX_REPORT_CC_IN_CCC,
HIDD_LE_IDX_REPORT_CC_IN_REP_REF,
// Boot Keyboard Input Report
HIDD_LE_IDX_BOOT_KB_IN_REPORT_CHAR,
HIDD_LE_IDX_BOOT_KB_IN_REPORT_VAL,
HIDD_LE_IDX_BOOT_KB_IN_REPORT_NTF_CFG,
// Boot Keyboard Output Report
HIDD_LE_IDX_BOOT_KB_OUT_REPORT_CHAR,
HIDD_LE_IDX_BOOT_KB_OUT_REPORT_VAL,
// Boot Mouse Input Report
HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_CHAR,
HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_VAL,
HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_NTF_CFG,
// Report
HIDD_LE_IDX_REPORT_CHAR,
HIDD_LE_IDX_REPORT_VAL,
HIDD_LE_IDX_REPORT_REP_REF,
//HIDD_LE_IDX_REPORT_NTF_CFG,
HIDD_LE_IDX_NB,
};
/// Attribute Table Indexes
enum {
HIDD_LE_INFO_CHAR,
HIDD_LE_CTNL_PT_CHAR,
HIDD_LE_REPORT_MAP_CHAR,
HIDD_LE_REPORT_CHAR,
HIDD_LE_PROTO_MODE_CHAR,
HIDD_LE_BOOT_KB_IN_REPORT_CHAR,
HIDD_LE_BOOT_KB_OUT_REPORT_CHAR,
HIDD_LE_BOOT_MOUSE_IN_REPORT_CHAR,
HIDD_LE_CHAR_MAX //= HIDD_LE_REPORT_CHAR + HIDD_LE_NB_REPORT_INST_MAX,
};
///att read event table Indexs
enum {
HIDD_LE_READ_INFO_EVT,
HIDD_LE_READ_CTNL_PT_EVT,
HIDD_LE_READ_REPORT_MAP_EVT,
HIDD_LE_READ_REPORT_EVT,
HIDD_LE_READ_PROTO_MODE_EVT,
HIDD_LE_BOOT_KB_IN_REPORT_EVT,
HIDD_LE_BOOT_KB_OUT_REPORT_EVT,
HIDD_LE_BOOT_MOUSE_IN_REPORT_EVT,
HID_LE_EVT_MAX
};
/// Client Characteristic Configuration Codes
enum {
HIDD_LE_DESC_MASK = 0x10,
HIDD_LE_BOOT_KB_IN_REPORT_CFG = HIDD_LE_BOOT_KB_IN_REPORT_CHAR | HIDD_LE_DESC_MASK,
HIDD_LE_BOOT_MOUSE_IN_REPORT_CFG = HIDD_LE_BOOT_MOUSE_IN_REPORT_CHAR | HIDD_LE_DESC_MASK,
HIDD_LE_REPORT_CFG = HIDD_LE_REPORT_CHAR | HIDD_LE_DESC_MASK,
};
/// Features Flag Values
enum {
HIDD_LE_CFG_KEYBOARD = 0x01,
HIDD_LE_CFG_MOUSE = 0x02,
HIDD_LE_CFG_PROTO_MODE = 0x04,
HIDD_LE_CFG_MAP_EXT_REF = 0x08,
HIDD_LE_CFG_BOOT_KB_WR = 0x10,
HIDD_LE_CFG_BOOT_MOUSE_WR = 0x20,
};
/// Report Char. Configuration Flag Values
enum {
HIDD_LE_CFG_REPORT_IN = 0x01,
HIDD_LE_CFG_REPORT_OUT = 0x02,
//HOGPD_CFG_REPORT_FEAT can be used as a mask to check Report type
HIDD_LE_CFG_REPORT_FEAT = 0x03,
HIDD_LE_CFG_REPORT_WR = 0x10,
};
/// Pointer to the connection clean-up function
#define HIDD_LE_CLEANUP_FNCT (NULL)
/*
* TYPE DEFINITIONS
****************************************************************************************
*/
/// HIDD Features structure
typedef struct {
/// Service Features
uint8_t svc_features;
/// Number of Report Char. instances to add in the database
uint8_t report_nb;
/// Report Char. Configuration
uint8_t report_char_cfg[HIDD_LE_NB_REPORT_INST_MAX];
} hidd_feature_t;
typedef struct {
bool in_use;
bool congest;
uint16_t conn_id;
bool connected;
esp_bd_addr_t remote_bda;
uint32_t trans_id;
uint8_t cur_srvc_id;
} hidd_clcb_t;
// HID report mapping table
typedef struct {
uint16_t handle; // Handle of report characteristic
uint16_t cccdHandle; // Handle of CCCD for report characteristic
uint8_t id; // Report ID
uint8_t type; // Report type
uint8_t mode; // Protocol mode (report or boot)
} hidRptMap_t;
typedef struct {
/// hidd profile id
uint8_t app_id;
/// Notified handle
uint16_t ntf_handle;
///Attribute handle Table
uint16_t att_tbl[HIDD_LE_IDX_NB];
/// Supported Features
hidd_feature_t hidd_feature[HIDD_LE_NB_HIDS_INST_MAX];
/// Current Protocol Mode
uint8_t proto_mode[HIDD_LE_NB_HIDS_INST_MAX];
/// Number of HIDS added in the database
uint8_t hids_nb;
uint8_t pending_evt;
uint16_t pending_hal;
} hidd_inst_t;
/// Report Reference structure
typedef struct
{
///Report ID
uint8_t report_id;
///Report Type
uint8_t report_type;
}hids_report_ref_t;
/// HID Information structure
typedef struct
{
/// bcdHID
uint16_t bcdHID;
/// bCountryCode
uint8_t bCountryCode;
/// Flags
uint8_t flags;
}hids_hid_info_t;
/* service engine control block */
typedef struct {
hidd_clcb_t hidd_clcb[HID_MAX_APPS]; /* connection link*/
esp_gatt_if_t gatt_if;
bool enabled;
bool is_take;
bool is_primery;
hidd_inst_t hidd_inst;
esp_hidd_event_cb_t hidd_cb;
uint8_t inst_id;
} hidd_le_env_t;
extern hidd_le_env_t hidd_le_env;
extern uint8_t hidProtocolMode;
void hidd_clcb_alloc (uint16_t conn_id, esp_bd_addr_t bda);
bool hidd_clcb_dealloc (uint16_t conn_id);
void hidd_le_create_service(esp_gatt_if_t gatts_if);
void hidd_set_attr_value(uint16_t handle, uint16_t val_len, const uint8_t *value);
void hidd_get_attr_value(uint16_t handle, uint16_t *length, uint8_t **value);
esp_err_t hidd_register_cb(void);
#endif ///__HID_DEVICE_LE_PRF__

View File

@ -0,0 +1,3 @@
# Override some defaults so BT stack is enabled
# by default in this example
CONFIG_BT_ENABLED=y