mirror of
https://github.com/0015/ThatProject.git
synced 2026-01-12 09:17:42 +03:00
ESP32 | BLE HID - Camera Shutter App for the smartphone [Part. 3/3 ADD BLE HID]
This commit is contained in:
90
ESP32_LVGL/ESP-IDF_Camera_Timer_For_Smartphone_LVGL7/Part.3/camera_timer_ble_hid/.gitignore
vendored
Normal file
90
ESP32_LVGL/ESP-IDF_Camera_Timer_For_Smartphone_LVGL7/Part.3/camera_timer_ble_hid/.gitignore
vendored
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
.config
|
||||||
|
*.o
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# gtags
|
||||||
|
GTAGS
|
||||||
|
GRTAGS
|
||||||
|
GPATH
|
||||||
|
|
||||||
|
# emacs
|
||||||
|
.dir-locals.el
|
||||||
|
|
||||||
|
# emacs temp file suffixes
|
||||||
|
*~
|
||||||
|
.#*
|
||||||
|
\#*#
|
||||||
|
|
||||||
|
# eclipse setting
|
||||||
|
.settings
|
||||||
|
|
||||||
|
# MacOS directory files
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Components Unit Test Apps files
|
||||||
|
components/**/build
|
||||||
|
components/**/sdkconfig
|
||||||
|
components/**/sdkconfig.old
|
||||||
|
|
||||||
|
# Example project files
|
||||||
|
examples/**/sdkconfig
|
||||||
|
examples/**/sdkconfig.old
|
||||||
|
examples/**/build
|
||||||
|
|
||||||
|
# Doc build artifacts
|
||||||
|
docs/_build/
|
||||||
|
docs/doxygen_sqlite3.db
|
||||||
|
|
||||||
|
# Downloaded font files
|
||||||
|
docs/_static/DejaVuSans.ttf
|
||||||
|
docs/_static/NotoSansSC-Regular.otf
|
||||||
|
|
||||||
|
# Unit test app files
|
||||||
|
tools/unit-test-app/sdkconfig
|
||||||
|
tools/unit-test-app/sdkconfig.old
|
||||||
|
tools/unit-test-app/build
|
||||||
|
tools/unit-test-app/builds
|
||||||
|
tools/unit-test-app/output
|
||||||
|
tools/unit-test-app/test_configs
|
||||||
|
|
||||||
|
# Unit Test CMake compile log folder
|
||||||
|
log_ut_cmake
|
||||||
|
|
||||||
|
# test application build files
|
||||||
|
tools/test_apps/**/build
|
||||||
|
tools/test_apps/**/sdkconfig
|
||||||
|
tools/test_apps/**/sdkconfig.old
|
||||||
|
|
||||||
|
# IDF monitor test
|
||||||
|
tools/test_idf_monitor/outputs
|
||||||
|
|
||||||
|
TEST_LOGS
|
||||||
|
|
||||||
|
# gcov coverage reports
|
||||||
|
*.gcda
|
||||||
|
*.gcno
|
||||||
|
coverage.info
|
||||||
|
coverage_report/
|
||||||
|
|
||||||
|
test_multi_heap_host
|
||||||
|
|
||||||
|
# VS Code Settings
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
# VIM files
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# Clion IDE CMake build & config
|
||||||
|
.idea/
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Results for the checking of the Python coding style and static analysis
|
||||||
|
.mypy_cache
|
||||||
|
flake8_output.txt
|
||||||
|
|
||||||
|
# ESP-IDF default build directory name
|
||||||
|
build
|
||||||
|
|
||||||
|
# lock files for examples and components
|
||||||
|
dependencies.lock
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
include(/Users/sil0/Workspace/01_Dev_Libraries/esp-idf/tools/cmake/project.cmake)
|
||||||
|
list(APPEND EXTRA_COMPONENT_DIRS components/lvgl_esp32_drivers components/lvgl_esp32_drivers/lvgl_touch components/lvgl_esp32_drivers/lvgl_tft)
|
||||||
|
|
||||||
|
project(camera_timer_ble_hid)
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
PROJECT_NAME := camera_timer_ble_hid
|
||||||
|
|
||||||
|
IDF_PATH = /Users/sil0/Workspace/01_Dev_Libraries/esp-idf
|
||||||
|
|
||||||
|
include $(IDF_PATH)/make/project.mk
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
idf_component_register(SRCS "main.c"
|
||||||
|
"esp_hidd_prf_api.c"
|
||||||
|
"hid_dev.c"
|
||||||
|
"hid_device_le_prf.c"
|
||||||
|
INCLUDE_DIRS ".")
|
||||||
|
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-unused-const-variable)
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
#
|
||||||
|
# "main" pseudo-component makefile.
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
// 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 "esp_log.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) {
|
||||||
|
ESP_LOGE(HID_LE_PRF_TAG, "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) {
|
||||||
|
ESP_LOGE(HID_LE_PRF_TAG, "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) {
|
||||||
|
ESP_LOGD(HID_LE_PRF_TAG, "hid_consumer_build_report");
|
||||||
|
hid_consumer_build_report(buffer, key_cmd);
|
||||||
|
}
|
||||||
|
ESP_LOGD(HID_LE_PRF_TAG, "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) {
|
||||||
|
ESP_LOGE(HID_LE_PRF_TAG, "%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];
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGD(HID_LE_PRF_TAG, "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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,168 @@
|
|||||||
|
// 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__ */
|
||||||
|
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
// 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 <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "esp_log.h"
|
||||||
|
|
||||||
|
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
|
||||||
|
ESP_LOGD(HID_LE_PRF_TAG, "%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) {
|
||||||
|
ESP_LOGE(HID_LE_PRF_TAG, "%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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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__ */
|
||||||
|
|
||||||
@@ -0,0 +1,816 @@
|
|||||||
|
// 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 "esp_log.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 Collectionq
|
||||||
|
|
||||||
|
#if (SUPPORT_REPORT_VENDOR == true)
|
||||||
|
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
|
||||||
|
#endif
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/// 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)
|
||||||
|
#define PROFILE_NUM 1
|
||||||
|
#define PROFILE_APP_IDX 0
|
||||||
|
|
||||||
|
struct gatts_profile_inst {
|
||||||
|
esp_gatts_cb_t gatts_cb;
|
||||||
|
uint16_t gatts_if;
|
||||||
|
uint16_t app_id;
|
||||||
|
uint16_t conn_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
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 };
|
||||||
|
|
||||||
|
#if (SUPPORT_REPORT_VENDOR == true)
|
||||||
|
|
||||||
|
static uint8_t hidReportRefVendorOut[HID_REPORT_REF_LEN] =
|
||||||
|
{HID_RPT_ID_VENDOR_OUT, HID_REPORT_TYPE_OUTPUT};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 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_nr = ESP_GATT_CHAR_PROP_BIT_WRITE_NR;
|
||||||
|
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}},
|
||||||
|
// 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_nr}},
|
||||||
|
// 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}},
|
||||||
|
#if (SUPPORT_REPORT_VENDOR == true)
|
||||||
|
// 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}},
|
||||||
|
#endif
|
||||||
|
// 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_ENCRYPTED),
|
||||||
|
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_ble_gap_config_local_icon (ESP_BLE_APPEARANCE_GENERIC_HID);
|
||||||
|
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};
|
||||||
|
ESP_LOGI(HID_LE_PRF_TAG, "HID 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: {
|
||||||
|
#if (SUPPORT_REPORT_VENDOR == true)
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
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;
|
||||||
|
ESP_LOGI(HID_LE_PRF_TAG, "%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));
|
||||||
|
ESP_LOGI(HID_LE_PRF_TAG, "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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct gatts_profile_inst heart_rate_profile_tab[PROFILE_NUM] = {
|
||||||
|
[PROFILE_APP_IDX] = {
|
||||||
|
.gatts_cb = esp_hidd_prf_cb_hdl,
|
||||||
|
.gatts_if = ESP_GATT_IF_NONE, /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
|
||||||
|
esp_ble_gatts_cb_param_t *param)
|
||||||
|
{
|
||||||
|
/* If event is register event, store the gatts_if for each profile */
|
||||||
|
if (event == ESP_GATTS_REG_EVT) {
|
||||||
|
if (param->reg.status == ESP_GATT_OK) {
|
||||||
|
heart_rate_profile_tab[PROFILE_APP_IDX].gatts_if = gatts_if;
|
||||||
|
} else {
|
||||||
|
ESP_LOGI(HID_LE_PRF_TAG, "Reg app failed, app_id %04x, status %d\n",
|
||||||
|
param->reg.app_id,
|
||||||
|
param->reg.status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
int idx;
|
||||||
|
for (idx = 0; idx < PROFILE_NUM; idx++) {
|
||||||
|
if (gatts_if == ESP_GATT_IF_NONE || /* ESP_GATT_IF_NONE, not specify a certain gatt_if, need to call every profile cb function */
|
||||||
|
gatts_if == heart_rate_profile_tab[idx].gatts_if) {
|
||||||
|
if (heart_rate_profile_tab[idx].gatts_cb) {
|
||||||
|
heart_rate_profile_tab[idx].gatts_cb(event, gatts_if, param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
esp_err_t hidd_register_cb(void)
|
||||||
|
{
|
||||||
|
esp_err_t status;
|
||||||
|
status = esp_ble_gatts_register_callback(gatts_event_handler);
|
||||||
|
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 {
|
||||||
|
ESP_LOGE(HID_LE_PRF_TAG, "%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 {
|
||||||
|
ESP_LOGE(HID_LE_PRF_TAG, "%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);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,344 @@
|
|||||||
|
// 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 <stdbool.h>
|
||||||
|
#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"
|
||||||
|
|
||||||
|
#define SUPPORT_REPORT_VENDOR false
|
||||||
|
//HID BLE profile log tag
|
||||||
|
#define HID_LE_PRF_TAG "HID_LE_PRF"
|
||||||
|
|
||||||
|
/// 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,
|
||||||
|
|
||||||
|
#if (SUPPORT_REPORT_VENDOR == true)
|
||||||
|
/// Report Vendor
|
||||||
|
HIDD_LE_IDX_REPORT_VENDOR_OUT_CHAR,
|
||||||
|
HIDD_LE_IDX_REPORT_VENDOR_OUT_VAL,
|
||||||
|
HIDD_LE_IDX_REPORT_VENDOR_OUT_REP_REF,
|
||||||
|
#endif
|
||||||
|
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__
|
||||||
|
|
||||||
@@ -0,0 +1,504 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#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.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 "driver/gpio.h"
|
||||||
|
#include "hid_dev.h"
|
||||||
|
|
||||||
|
/* Littlevgl specific */
|
||||||
|
#include "lvgl/lvgl.h"
|
||||||
|
#include "lvgl_helpers.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#define LV_TICK_PERIOD_MS 1
|
||||||
|
#define PROJECT_TAG "BLE_HID"
|
||||||
|
#define HIDD_DEVICE_NAME "MY_CAMERA_TIMER"
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
static void lv_tick_task(void *arg);
|
||||||
|
static void guiTask(void *pvParameter);
|
||||||
|
static void lv_layout(void);
|
||||||
|
static void lv_update_status_label(const char *status_msg);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
static lv_obj_t *lmeter_label;
|
||||||
|
static lv_obj_t *lmeter;
|
||||||
|
static lv_obj_t *status_label;
|
||||||
|
static lv_anim_t a;
|
||||||
|
static int userSetTime;
|
||||||
|
|
||||||
|
static uint16_t hid_conn_id = 0;
|
||||||
|
static bool sec_conn = false;
|
||||||
|
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 = 0x0006, //slave connection min interval, Time = min_interval * 1.25 msec
|
||||||
|
.max_interval = 0x0010, //slave connection max interval, Time = max_interval * 1.25 msec
|
||||||
|
.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,
|
||||||
|
};
|
||||||
|
/**********************
|
||||||
|
* STATIC CALLBACKS
|
||||||
|
**********************/
|
||||||
|
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_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:
|
||||||
|
{
|
||||||
|
ESP_LOGI(PROJECT_TAG, "ESP_HIDD_EVENT_BLE_CONNECT");
|
||||||
|
hid_conn_id = param->connect.conn_id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ESP_HIDD_EVENT_BLE_DISCONNECT:
|
||||||
|
{
|
||||||
|
sec_conn = false;
|
||||||
|
ESP_LOGI(PROJECT_TAG, "ESP_HIDD_EVENT_BLE_DISCONNECT");
|
||||||
|
esp_ble_gap_start_advertising(&hidd_adv_params);
|
||||||
|
lv_update_status_label("Device Disconnected!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT:
|
||||||
|
{
|
||||||
|
ESP_LOGI(PROJECT_TAG, "%s, ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT", __func__);
|
||||||
|
ESP_LOG_BUFFER_HEX(PROJECT_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);
|
||||||
|
lv_update_status_label("Start Advertising!");
|
||||||
|
break;
|
||||||
|
case ESP_GAP_BLE_SEC_REQ_EVT:
|
||||||
|
for (int i = 0; i < ESP_BD_ADDR_LEN; i++)
|
||||||
|
{
|
||||||
|
ESP_LOGD(PROJECT_TAG, "%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;
|
||||||
|
esp_bd_addr_t bd_addr;
|
||||||
|
memcpy(bd_addr, param->ble_security.auth_cmpl.bd_addr, sizeof(esp_bd_addr_t));
|
||||||
|
ESP_LOGI(PROJECT_TAG, "remote BD_ADDR: %08x%04x",
|
||||||
|
(bd_addr[0] << 24) + (bd_addr[1] << 16) + (bd_addr[2] << 8) + bd_addr[3],
|
||||||
|
(bd_addr[4] << 8) + bd_addr[5]);
|
||||||
|
ESP_LOGI(PROJECT_TAG, "address type = %d", param->ble_security.auth_cmpl.addr_type);
|
||||||
|
ESP_LOGI(PROJECT_TAG, "pair status = %s", param->ble_security.auth_cmpl.success ? "success" : "fail");
|
||||||
|
|
||||||
|
lv_update_status_label("Device Connected!");
|
||||||
|
if (!param->ble_security.auth_cmpl.success)
|
||||||
|
{
|
||||||
|
ESP_LOGE(PROJECT_TAG, "fail reason = 0x%x", param->ble_security.auth_cmpl.fail_reason);
|
||||||
|
lv_update_status_label("Auth Failed!");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* APPLICATION MAIN
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void ble_hid_init()
|
||||||
|
{
|
||||||
|
esp_err_t ret;
|
||||||
|
// Initialize NVS.
|
||||||
|
ret = nvs_flash_init();
|
||||||
|
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
|
||||||
|
{
|
||||||
|
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||||
|
ret = nvs_flash_init();
|
||||||
|
}
|
||||||
|
ESP_ERROR_CHECK(ret);
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));
|
||||||
|
|
||||||
|
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||||
|
ret = esp_bt_controller_init(&bt_cfg);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ESP_LOGE(PROJECT_TAG, "%s initialize controller failed\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ESP_LOGE(PROJECT_TAG, "%s enable controller failed\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = esp_bluedroid_init();
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ESP_LOGE(PROJECT_TAG, "%s init bluedroid failed\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = esp_bluedroid_enable();
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ESP_LOGE(PROJECT_TAG, "%s init bluedroid failed\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = esp_hidd_profile_init()) != ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_LOGE(PROJECT_TAG, "%s init bluedroid failed\n", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_update_status_label("BLE INIT DONE!");
|
||||||
|
//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 distribute to you,
|
||||||
|
and the response key means which key you can distribute 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 distribute to you,
|
||||||
|
and the init key means which key you can distribute 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_main()
|
||||||
|
{
|
||||||
|
xTaskCreatePinnedToCore(guiTask, "gui", 4096 * 2, NULL, 0, NULL, 1);
|
||||||
|
ble_hid_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
SemaphoreHandle_t xGuiSemaphore;
|
||||||
|
|
||||||
|
static void guiTask(void *pvParameter)
|
||||||
|
{
|
||||||
|
|
||||||
|
(void)pvParameter;
|
||||||
|
xGuiSemaphore = xSemaphoreCreateMutex();
|
||||||
|
|
||||||
|
lv_init();
|
||||||
|
|
||||||
|
/* Initialize SPI or I2C bus used by the drivers */
|
||||||
|
lvgl_driver_init();
|
||||||
|
|
||||||
|
static lv_color_t buf1[DISP_BUF_SIZE];
|
||||||
|
static lv_color_t *buf2 = NULL;
|
||||||
|
static lv_disp_buf_t disp_buf;
|
||||||
|
uint32_t size_in_px = DISP_BUF_SIZE;
|
||||||
|
lv_disp_buf_init(&disp_buf, buf1, buf2, size_in_px);
|
||||||
|
|
||||||
|
lv_disp_drv_t disp_drv;
|
||||||
|
lv_disp_drv_init(&disp_drv);
|
||||||
|
disp_drv.flush_cb = disp_driver_flush;
|
||||||
|
disp_drv.buffer = &disp_buf;
|
||||||
|
lv_disp_drv_register(&disp_drv);
|
||||||
|
|
||||||
|
/* Register an input device when enabled on the menuconfig */
|
||||||
|
#if CONFIG_LV_TOUCH_CONTROLLER != TOUCH_CONTROLLER_NONE
|
||||||
|
lv_indev_drv_t indev_drv;
|
||||||
|
lv_indev_drv_init(&indev_drv);
|
||||||
|
indev_drv.read_cb = touch_driver_read;
|
||||||
|
indev_drv.type = LV_INDEV_TYPE_POINTER;
|
||||||
|
lv_indev_drv_register(&indev_drv);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Create and start a periodic timer interrupt to call lv_tick_inc */
|
||||||
|
const esp_timer_create_args_t periodic_timer_args = {
|
||||||
|
.callback = &lv_tick_task,
|
||||||
|
.name = "periodic_gui"};
|
||||||
|
esp_timer_handle_t periodic_timer;
|
||||||
|
ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer));
|
||||||
|
ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, LV_TICK_PERIOD_MS * 1000));
|
||||||
|
|
||||||
|
lv_layout();
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
|
||||||
|
if (pdTRUE == xSemaphoreTake(xGuiSemaphore, portMAX_DELAY))
|
||||||
|
{
|
||||||
|
lv_task_handler();
|
||||||
|
xSemaphoreGive(xGuiSemaphore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lv_tick_task(void *arg)
|
||||||
|
{
|
||||||
|
(void)arg;
|
||||||
|
lv_tick_inc(LV_TICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void startTimer(int second)
|
||||||
|
{
|
||||||
|
lv_anim_set_time(&a, second);
|
||||||
|
lv_anim_start(&a);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void shotTrigger(bool isTriggered)
|
||||||
|
{
|
||||||
|
if(!sec_conn)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (userSetTime == 0)
|
||||||
|
{
|
||||||
|
esp_hidd_send_consumer_value(hid_conn_id, HID_CONSUMER_VOLUME_UP, isTriggered);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
startTimer(userSetTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void button_event_handler(lv_obj_t *obj, lv_event_t event)
|
||||||
|
{
|
||||||
|
switch (event)
|
||||||
|
{
|
||||||
|
case LV_EVENT_PRESSED:
|
||||||
|
printf("Pressed\n");
|
||||||
|
shotTrigger(true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LV_EVENT_RELEASED:
|
||||||
|
printf("Released\n");
|
||||||
|
shotTrigger(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ddlist_event_handler(lv_obj_t *obj, lv_event_t event)
|
||||||
|
{
|
||||||
|
if (event == LV_EVENT_VALUE_CHANGED)
|
||||||
|
{
|
||||||
|
uint16_t itemIdx = lv_dropdown_get_selected(obj);
|
||||||
|
printf("itemIdx: %d\n", itemIdx);
|
||||||
|
|
||||||
|
switch (itemIdx)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
userSetTime = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
userSetTime = 3000;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
userSetTime = 5000;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
userSetTime = 10000;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
userSetTime = 20000;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
userSetTime = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[6];
|
||||||
|
lv_dropdown_get_selected_str(obj, buf, sizeof(buf));
|
||||||
|
lv_label_set_text(lmeter_label, buf);
|
||||||
|
lv_obj_align(lmeter_label, lmeter, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void linemeter_anim(lv_obj_t *linemeter, lv_anim_value_t value)
|
||||||
|
{
|
||||||
|
lv_linemeter_set_value(linemeter, value);
|
||||||
|
float timeValue = userSetTime / 100 * value;
|
||||||
|
float remainingSec = (userSetTime - timeValue) / 1000;
|
||||||
|
static char buf[64];
|
||||||
|
lv_snprintf(buf, sizeof(buf), "%.2f sec", remainingSec);
|
||||||
|
lv_obj_t *label = lv_obj_get_child(linemeter, NULL);
|
||||||
|
lv_label_set_text(label, buf);
|
||||||
|
lv_obj_align(label, linemeter, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
|
||||||
|
if (value > 99)
|
||||||
|
{
|
||||||
|
esp_hidd_send_consumer_value(hid_conn_id, HID_CONSUMER_VOLUME_UP, true);
|
||||||
|
vTaskDelay(10);
|
||||||
|
esp_hidd_send_consumer_value(hid_conn_id, HID_CONSUMER_VOLUME_UP, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lv_layout(void)
|
||||||
|
{
|
||||||
|
lv_obj_t *scr = lv_obj_create(NULL, NULL);
|
||||||
|
lv_scr_load(scr);
|
||||||
|
|
||||||
|
lv_obj_t *bg_top = lv_obj_create(scr, NULL);
|
||||||
|
lv_obj_clean_style_list(bg_top, LV_OBJ_PART_MAIN);
|
||||||
|
lv_obj_set_size(bg_top, LV_HOR_RES, 40);
|
||||||
|
|
||||||
|
status_label = lv_label_create(bg_top, NULL);
|
||||||
|
lv_label_set_long_mode(status_label, LV_LABEL_LONG_SROLL_CIRC);
|
||||||
|
lv_obj_set_width(status_label, LV_HOR_RES / 2);
|
||||||
|
lv_label_set_text(status_label, "Status Label");
|
||||||
|
lv_obj_align(status_label, NULL, LV_ALIGN_IN_LEFT_MID, 20, 0);
|
||||||
|
|
||||||
|
lv_obj_t *ddlist = lv_dropdown_create(bg_top, NULL);
|
||||||
|
lv_obj_clean_style_list(ddlist, LV_OBJ_PART_MAIN);
|
||||||
|
lv_dropdown_set_options(ddlist, "None\n"
|
||||||
|
"3s\n"
|
||||||
|
"5s\n"
|
||||||
|
"10s\n"
|
||||||
|
"20s");
|
||||||
|
|
||||||
|
lv_obj_align(ddlist, NULL, LV_ALIGN_IN_RIGHT_MID, -10, 8);
|
||||||
|
lv_obj_set_event_cb(ddlist, ddlist_event_handler);
|
||||||
|
|
||||||
|
static lv_style_t button_style;
|
||||||
|
lv_style_init(&button_style);
|
||||||
|
lv_style_set_radius(&button_style, LV_STATE_DEFAULT, 0);
|
||||||
|
lv_style_set_bg_color(&button_style, LV_STATE_DEFAULT, LV_COLOR_GRAY);
|
||||||
|
lv_style_set_border_color(&button_style, LV_STATE_DEFAULT, LV_COLOR_GRAY);
|
||||||
|
lv_style_set_bg_color(&button_style, LV_STATE_PRESSED, LV_COLOR_RED);
|
||||||
|
lv_style_set_border_color(&button_style, LV_STATE_PRESSED, LV_COLOR_RED);
|
||||||
|
|
||||||
|
static lv_style_t button_label_style;
|
||||||
|
lv_style_init(&button_label_style);
|
||||||
|
lv_style_set_text_opa(&button_label_style, LV_STATE_DEFAULT, LV_OPA_50);
|
||||||
|
lv_style_set_text_color(&button_label_style, LV_STATE_DEFAULT, LV_COLOR_WHITE);
|
||||||
|
|
||||||
|
lv_obj_t *shot_btn = lv_btn_create(scr, NULL);
|
||||||
|
lv_obj_add_style(shot_btn, LV_BTN_PART_MAIN, &button_style);
|
||||||
|
lv_obj_set_event_cb(shot_btn, button_event_handler);
|
||||||
|
lv_obj_set_size(shot_btn, 144, 64);
|
||||||
|
lv_obj_align(shot_btn, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, -80);
|
||||||
|
|
||||||
|
lv_obj_t *shot_btn_label = lv_label_create(shot_btn, NULL);
|
||||||
|
lv_obj_add_style(shot_btn_label, LV_LABEL_PART_MAIN, &button_label_style);
|
||||||
|
lv_label_set_text(shot_btn_label, "Shot");
|
||||||
|
|
||||||
|
lmeter = lv_linemeter_create(scr, NULL);
|
||||||
|
lv_obj_set_drag_parent(lmeter, true);
|
||||||
|
lv_linemeter_set_value(lmeter, 0);
|
||||||
|
lv_obj_set_size(lmeter, 160, 160);
|
||||||
|
lv_obj_align(lmeter, NULL, LV_ALIGN_CENTER, 0, -40);
|
||||||
|
|
||||||
|
lmeter_label = lv_label_create(lmeter, NULL);
|
||||||
|
lv_label_set_text(lmeter_label, "Timer");
|
||||||
|
lv_obj_align(lmeter_label, lmeter, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
lv_obj_set_style_local_text_font(lmeter_label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_theme_get_font_title());
|
||||||
|
|
||||||
|
lv_anim_init(&a);
|
||||||
|
lv_anim_set_var(&a, lmeter);
|
||||||
|
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)linemeter_anim);
|
||||||
|
lv_anim_set_values(&a, 0, 100);
|
||||||
|
lv_anim_set_playback_time(&a, 400);
|
||||||
|
lv_anim_set_repeat_count(&a, 1);
|
||||||
|
|
||||||
|
lv_update_status_label("LVGL Done!");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lv_update_status_label(const char *status_msg)
|
||||||
|
{
|
||||||
|
if (status_label != NULL)
|
||||||
|
{
|
||||||
|
lv_label_set_text(status_label, status_msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -25,6 +25,8 @@ Implement your project in an exquisite combination of hardware and software.
|
|||||||
|
|
||||||
* [Youtube ESP32 Project](https://www.youtube.com/playlist?list=PLnq7JUnBumAyhSBBp95MsQ5-chBAYheZw)
|
* [Youtube ESP32 Project](https://www.youtube.com/playlist?list=PLnq7JUnBumAyhSBBp95MsQ5-chBAYheZw)
|
||||||
|
|
||||||
|
* [ESP32 | BLE HID - Camera Shutter App for the smartphone [Part. 3/3 ADD BLE HID]][[Video]](https://youtu.be/I6rlpXpBimc)[[Source Code]](https://github.com/0015/IdeasNProjects/tree/master/ESP32_LVGL/ESP-IDF_Camera_Timer_For_Smartphone_LVGL7/Part.3/camera_timer_ble_hid)
|
||||||
|
|
||||||
* [ESP32 | BLE HID - Camera Shutter App for the smartphone [Part. 2/3 UI Design in LVGL]][[Video]](https://youtu.be/IQsND5MwSEQ)[[Source Code]](https://github.com/0015/IdeasNProjects/tree/master/ESP32_LVGL/ESP-IDF_Camera_Timer_For_Smartphone_LVGL7/Part.2/camera_timer_ble_hid)
|
* [ESP32 | BLE HID - Camera Shutter App for the smartphone [Part. 2/3 UI Design in LVGL]][[Video]](https://youtu.be/IQsND5MwSEQ)[[Source Code]](https://github.com/0015/IdeasNProjects/tree/master/ESP32_LVGL/ESP-IDF_Camera_Timer_For_Smartphone_LVGL7/Part.2/camera_timer_ble_hid)
|
||||||
|
|
||||||
* [ESP32 | BLE HID - Camera Shutter App for the smartphone [Part. 1/3 LVGL on ESP-IDF]][[Video]](https://youtu.be/7-QiGUAWkys)[[Source Code]](https://github.com/0015/IdeasNProjects/tree/master/ESP32_LVGL/ESP-IDF_Camera_Timer_For_Smartphone_LVGL7/Part.1/camera_timer_ble_hid)
|
* [ESP32 | BLE HID - Camera Shutter App for the smartphone [Part. 1/3 LVGL on ESP-IDF]][[Video]](https://youtu.be/7-QiGUAWkys)[[Source Code]](https://github.com/0015/IdeasNProjects/tree/master/ESP32_LVGL/ESP-IDF_Camera_Timer_For_Smartphone_LVGL7/Part.1/camera_timer_ble_hid)
|
||||||
|
|||||||
Reference in New Issue
Block a user