]> granicus.if.org Git - esp-idf/commitdiff
example/hid: Added the BLE hid device profile.
authorYulong <huangyulong@espressif.com>
Fri, 9 Mar 2018 08:25:23 +0000 (03:25 -0500)
committeryulong <huangyulong@espressif.com>
Thu, 19 Apr 2018 03:44:51 +0000 (11:44 +0800)
demo/hid: Change the license validity period & some unreasonable LOG print.

example/hid: Added the Vendor Report output support.

examples/bluetooth/ble_hid_device_demo/Makefile [new file with mode: 0644]
examples/bluetooth/ble_hid_device_demo/main/ble_hidd_demo_main.c [new file with mode: 0644]
examples/bluetooth/ble_hid_device_demo/main/component.mk [new file with mode: 0644]
examples/bluetooth/ble_hid_device_demo/main/esp_hidd_prf_api.c [new file with mode: 0644]
examples/bluetooth/ble_hid_device_demo/main/esp_hidd_prf_api.h [new file with mode: 0644]
examples/bluetooth/ble_hid_device_demo/main/hid_dev.c [new file with mode: 0644]
examples/bluetooth/ble_hid_device_demo/main/hid_dev.h [new file with mode: 0644]
examples/bluetooth/ble_hid_device_demo/main/hid_device_le_prf.c [new file with mode: 0644]
examples/bluetooth/ble_hid_device_demo/main/hidd_le_prf_int.h [new file with mode: 0644]
examples/bluetooth/ble_hid_device_demo/sdkconfig.defaults [new file with mode: 0644]

diff --git a/examples/bluetooth/ble_hid_device_demo/Makefile b/examples/bluetooth/ble_hid_device_demo/Makefile
new file mode 100644 (file)
index 0000000..8604de3
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# This is a project Makefile. It is assumed the directory this Makefile resides in is a
+# project subdirectory.
+#
+
+PROJECT_NAME := hidd_demos
+
+COMPONENT_ADD_INCLUDEDIRS := components/include        \
+                                                               
+
+include $(IDF_PATH)/make/project.mk
diff --git a/examples/bluetooth/ble_hid_device_demo/main/ble_hidd_demo_main.c b/examples/bluetooth/ble_hid_device_demo/main/ble_hidd_demo_main.c
new file mode 100644 (file)
index 0000000..626d69c
--- /dev/null
@@ -0,0 +1,317 @@
+/* This example code is in the Public Domain (or CC0 licensed, at your option.)
+   Unless required by applicable law or agreed to in writing, this software is 
+   distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  
+   CONDITIONS OF ANY KIND, either express or implied.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/event_groups.h"
+#include "esp_system.h"
+#include "esp_wifi.h"
+#include "esp_event_loop.h"
+#include "esp_log.h"
+#include "nvs_flash.h"
+#include "esp_bt.h"
+
+#include "esp_hidd_prf_api.h"
+#include "esp_bt_defs.h"
+#include "esp_gap_ble_api.h"
+#include "esp_gatts_api.h"
+#include "esp_gatt_defs.h"
+#include "esp_bt_main.h"
+#include "esp_bt_device.h"
+#include "bt_trace.h"
+#include "driver/gpio.h"
+#include "hid_dev.h"
+
+/**
+ * Brief:
+ * This test code shows how to configure gpio and how to use gpio interrupt.
+ *
+ * GPIO status:
+ * GPIO18: output
+ * GPIO19: output
+ * GPIO4:  input, pulled up, interrupt from rising edge and falling edge
+ * GPIO5:  input, pulled up, interrupt from rising edge.
+ *
+ * Test:
+ * Connect GPIO18 with GPIO4
+ * Connect GPIO19 with GPIO5
+ * Generate pulses on GPIO18/19, that triggers interrupt on GPIO4/5
+ *
+ */
+
+#define GATTS_TAG "HID_DEMO"
+
+
+#define GPIO_OUTPUT_IO_0    18
+#define GPIO_OUTPUT_IO_1    19
+#define GPIO_OUTPUT_PIN_SEL  ((1<<GPIO_OUTPUT_IO_0) | (1<<GPIO_OUTPUT_IO_1))
+#define GPIO_INPUT_IO_0     21
+#define GPIO_INPUT_IO_1     27
+#define GPIO_INPUT_PIN_SEL  ((1<<GPIO_INPUT_IO_0) | (1<<GPIO_INPUT_IO_1))
+#define ESP_INTR_FLAG_DEFAULT 0
+
+static xQueueHandle gpio_evt_queue = NULL;
+static uint16_t hid_conn_id = 0;
+static bool sec_conn = false;
+static bool send_volum_up = false;
+#define CHAR_DECLARATION_SIZE   (sizeof(uint8_t))
+
+static void hidd_event_callback(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param);
+
+#define HIDD_DEVICE_NAME            "HID"
+static uint8_t hidd_service_uuid128[] = {
+    /* LSB <--------------------------------------------------------------------------------> MSB */
+    //first uuid, 16bit, [12],[13] is the value
+    0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x12, 0x18, 0x00, 0x00,
+};
+
+static esp_ble_adv_data_t hidd_adv_data = {
+    .set_scan_rsp = false,
+    .include_name = true,
+    .include_txpower = true,
+    .min_interval = 0x20,
+    .max_interval = 0x30,
+    .appearance = 0x03c0,       //HID Generic,
+    .manufacturer_len = 0,
+    .p_manufacturer_data =  NULL,
+    .service_data_len = 0,
+    .p_service_data = NULL,
+    .service_uuid_len = sizeof(hidd_service_uuid128),
+    .p_service_uuid = hidd_service_uuid128,
+    .flag = 0x6,
+};
+
+static esp_ble_adv_params_t hidd_adv_params = {
+    .adv_int_min        = 0x20,
+    .adv_int_max        = 0x30,
+    .adv_type           = ADV_TYPE_IND,
+    .own_addr_type      = BLE_ADDR_TYPE_PUBLIC,
+    //.peer_addr            =
+    //.peer_addr_type       =
+    .channel_map        = ADV_CHNL_ALL,
+    .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
+};
+
+void IRAM_ATTR gpio_isr_handler(void* arg)
+{
+    uint32_t gpio_num = (uint32_t) arg;
+    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
+}
+
+void gpio_task_example(void* arg)
+{
+    static uint8_t i = 0;
+    uint32_t io_num;
+    for(;;) {
+        if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
+            ESP_LOGI(GATTS_TAG, "GPIO[%d] intr, val: %d\n", io_num, gpio_get_level(io_num));
+            if(i == 0) {
+            ++i;
+            }
+        }
+    }
+}
+
+static void gpio_demo_init(void)
+{
+    gpio_config_t io_conf;
+    //disable interrupt
+    io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
+    //set as output mode        
+    io_conf.mode = GPIO_MODE_OUTPUT;
+    //bit mask of the pins that you want to set,e.g.GPIO18/19
+    io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;
+    //disable pull-down mode
+    io_conf.pull_down_en = 0;
+    //disable pull-up mode
+    io_conf.pull_up_en = 0;
+    //configure GPIO with the given settings
+    gpio_config(&io_conf);
+
+    //interrupt of rising edge
+    io_conf.intr_type = GPIO_PIN_INTR_POSEDGE;
+    //bit mask of the pins, use GPIO4/5 here
+    io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
+    //set as input mode    
+    io_conf.mode = GPIO_MODE_INPUT;
+    //enable pull-up mode
+    io_conf.pull_up_en = 1;
+    gpio_config(&io_conf);
+
+    //change gpio intrrupt type for one pin
+    gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_ANYEDGE);
+
+    //create a queue to handle gpio event from isr
+    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
+    //start gpio task
+    xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL);
+
+    //install gpio isr service
+    gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
+    //hook isr handler for specific gpio pin
+    gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);
+    //hook isr handler for specific gpio pin
+    gpio_isr_handler_add(GPIO_INPUT_IO_1, gpio_isr_handler, (void*) GPIO_INPUT_IO_1);
+
+    //remove isr handler for gpio number.
+    gpio_isr_handler_remove(GPIO_INPUT_IO_0);
+    //hook isr handler for specific gpio pin again
+    gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);
+
+}
+
+
+
+static void hidd_event_callback(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param)
+{
+    switch(event) {
+        case ESP_HIDD_EVENT_REG_FINISH: {
+            if (param->init_finish.state == ESP_HIDD_INIT_OK) {
+                //esp_bd_addr_t rand_addr = {0x04,0x11,0x11,0x11,0x11,0x05};
+                esp_ble_gap_set_device_name(HIDD_DEVICE_NAME);
+                esp_ble_gap_config_adv_data(&hidd_adv_data);
+                
+            }
+            break;
+        }
+        case ESP_BAT_EVENT_REG: {
+            break;
+        }
+        case ESP_HIDD_EVENT_DEINIT_FINISH:
+            break;
+               case ESP_HIDD_EVENT_BLE_CONNECT: {
+            hid_conn_id = param->connect.conn_id;
+            break;
+        }
+        case ESP_HIDD_EVENT_BLE_DISCONNECT: {
+            sec_conn = false;
+            LOG_ERROR("%s(), ESP_HIDD_EVENT_BLE_DISCONNECT", __func__);
+            esp_ble_gap_start_advertising(&hidd_adv_params);
+            break;
+        }
+        case ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT: {
+            LOG_ERROR("%s, ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT", __func__);
+            ESP_LOG_BUFFER_HEX(GATTS_TAG, param->vendor_write.data, param->vendor_write.length);
+        }    
+        default:
+            break;
+    }
+    return;
+}
+
+static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
+{
+    switch (event) {
+    case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
+        esp_ble_gap_start_advertising(&hidd_adv_params);
+        break;
+     case ESP_GAP_BLE_SEC_REQ_EVT:
+        for(int i = 0; i < ESP_BD_ADDR_LEN; i++) {
+             LOG_DEBUG("%x:",param->ble_security.ble_req.bd_addr[i]);
+        }
+        esp_ble_gap_security_rsp(param->ble_security.ble_req.bd_addr, true);
+        break;
+     case ESP_GAP_BLE_AUTH_CMPL_EVT:
+        sec_conn = true;
+        LOG_ERROR("staus =%s, ESP_GAP_BLE_AUTH_CMPL_EVT",param->ble_security.auth_cmpl.success ? "success" : "fail");
+        break;
+    default:
+        break;
+    }
+}
+
+void hid_demo_task(void *pvParameters)
+{
+    vTaskDelay(1000 / portTICK_PERIOD_MS);
+    while(1) {
+        vTaskDelay(2000 / portTICK_PERIOD_MS);
+        if (sec_conn) {
+            LOG_ERROR("Send the volume");
+            //send_volum_up = true;
+            uint8_t key_vaule = {HID_KEY_A};
+            esp_hidd_send_keyboard_value(hid_conn_id, 0, &key_vaule, 1);
+            //esp_hidd_send_consumer_value(hid_conn_id, HID_CONSUMER_VOLUME_UP, true);
+            vTaskDelay(3000 / portTICK_PERIOD_MS);
+            if (send_volum_up) {
+                send_volum_up = false;
+                //esp_hidd_send_consumer_value(hid_conn_id, HID_CONSUMER_VOLUME_UP, false);
+                esp_hidd_send_consumer_value(hid_conn_id, HID_CONSUMER_VOLUME_DOWN, true);
+            }
+        }
+    }
+}
+
+
+void app_main()
+{
+    esp_err_t ret;
+
+    // Initialize NVS.
+    ret = nvs_flash_init();
+    if (ret == ESP_ERR_NVS_NO_FREE_PAGES) {
+        ESP_ERROR_CHECK(nvs_flash_erase());
+        ret = nvs_flash_init();
+    }
+    ESP_ERROR_CHECK( ret );
+
+    esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
+    ret = esp_bt_controller_init(&bt_cfg);
+    if (ret) {
+        ESP_LOGE(GATTS_TAG, "%s initialize controller failed\n", __func__);
+        return;
+    }
+
+    ret = esp_bt_controller_enable(ESP_BT_MODE_BTDM);
+    if (ret) {
+        ESP_LOGE(GATTS_TAG, "%s enable controller failed\n", __func__);
+        return;
+    }
+
+    ret = esp_bluedroid_init();
+    if (ret) {
+        LOG_ERROR("%s init bluedroid failed\n", __func__);
+        return;
+    }
+
+    ret = esp_bluedroid_enable();
+    if (ret) {
+        LOG_ERROR("%s init bluedroid failed\n", __func__);
+        return;
+    }
+
+    if((ret = esp_hidd_profile_init()) != ESP_OK) {
+        LOG_ERROR("%s init bluedroid failed\n", __func__);
+    }
+
+    ///register the callback function to the gap module
+    esp_ble_gap_register_callback(gap_event_handler);
+    esp_hidd_register_callbacks(hidd_event_callback);
+
+    /* set the security iocap & auth_req & key size & init key response key parameters to the stack*/
+    esp_ble_auth_req_t auth_req = ESP_LE_AUTH_BOND;     //bonding with peer device after authentication
+    esp_ble_io_cap_t iocap = ESP_IO_CAP_NONE;           //set the IO capability to No output No input
+    uint8_t key_size = 16;      //the key size should be 7~16 bytes
+    uint8_t init_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
+    uint8_t rsp_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
+    esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &auth_req, sizeof(uint8_t));
+    esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &iocap, sizeof(uint8_t));
+    esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &key_size, sizeof(uint8_t));
+    /* If your BLE device act as a Slave, the init_key means you hope which types of key of the master should distribut to you,
+    and the response key means which key you can distribut to the Master;
+    If your BLE device act as a master, the response key means you hope which types of key of the slave should distribut to you, 
+    and the init key means which key you can distribut to the slave. */
+    esp_ble_gap_set_security_param(ESP_BLE_SM_SET_INIT_KEY, &init_key, sizeof(uint8_t));
+    esp_ble_gap_set_security_param(ESP_BLE_SM_SET_RSP_KEY, &rsp_key, sizeof(uint8_t));
+
+    //init the gpio pin
+    gpio_demo_init();
+   xTaskCreate(&hid_demo_task, "hid_task", 2048, NULL, 5, NULL);
+
+}
+
diff --git a/examples/bluetooth/ble_hid_device_demo/main/component.mk b/examples/bluetooth/ble_hid_device_demo/main/component.mk
new file mode 100644 (file)
index 0000000..48adb59
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Main Makefile. This is basically the same as a component makefile.
+#
+# This Makefile should, at the very least, just include $(SDK_PATH)/make/component_common.mk. By default, 
+# this will take the sources in the src/ directory, compile them and link them into 
+# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
+# please read the ESP-IDF documents if you need to do this.
+#
+
+# include $(IDF_PATH)/make/component_common.mk
diff --git a/examples/bluetooth/ble_hid_device_demo/main/esp_hidd_prf_api.c b/examples/bluetooth/ble_hid_device_demo/main/esp_hidd_prf_api.c
new file mode 100644 (file)
index 0000000..b3ee517
--- /dev/null
@@ -0,0 +1,146 @@
+// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "esp_hidd_prf_api.h"
+#include "hidd_le_prf_int.h"
+#include "hid_dev.h"
+#include <stdlib.h>
+#include <string.h>
+#include "bt_trace.h"
+
+// HID keyboard input report length
+#define HID_KEYBOARD_IN_RPT_LEN     8
+
+// HID LED output report length
+#define HID_LED_OUT_RPT_LEN         1
+
+// HID mouse input report length
+#define HID_MOUSE_IN_RPT_LEN        5
+
+// HID consumer control input report length
+#define HID_CC_IN_RPT_LEN           2
+
+
+esp_err_t esp_hidd_register_callbacks(esp_hidd_event_cb_t callbacks)
+{
+    esp_err_t hidd_status;
+
+    if(callbacks != NULL) {
+           hidd_le_env.hidd_cb = callbacks;
+    } else {
+        return ESP_FAIL;
+    }
+
+    if((hidd_status = hidd_register_cb()) != ESP_OK) {
+        return hidd_status;
+    }
+
+    esp_ble_gatts_app_register(BATTRAY_APP_ID);
+    
+    if((hidd_status = esp_ble_gatts_app_register(HIDD_APP_ID)) != ESP_OK) {
+        return hidd_status;
+    }
+   
+    return hidd_status;
+}
+
+esp_err_t esp_hidd_profile_init(void)
+{
+     if (hidd_le_env.enabled) {
+        LOG_ERROR("HID device profile already initialized");
+        return ESP_FAIL;
+    }
+    // Reset the hid device target environment
+    memset(&hidd_le_env, 0, sizeof(hidd_le_env_t));
+    hidd_le_env.enabled = true;
+    return ESP_OK;
+}
+
+esp_err_t esp_hidd_profile_deinit(void)
+{
+    uint16_t hidd_svc_hdl = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_SVC];
+    if (!hidd_le_env.enabled) {
+        LOG_ERROR("HID device profile already initialized");
+        return ESP_OK;
+    }
+
+    if(hidd_svc_hdl != 0) {
+       esp_ble_gatts_stop_service(hidd_svc_hdl);
+       esp_ble_gatts_delete_service(hidd_svc_hdl);
+    } else {
+       return ESP_FAIL;
+   }
+    
+    /* register the HID device profile to the BTA_GATTS module*/
+    esp_ble_gatts_app_unregister(hidd_le_env.gatt_if);
+
+    return ESP_OK;
+}
+
+uint16_t esp_hidd_get_version(void)
+{
+       return HIDD_VERSION;
+}
+
+void esp_hidd_send_consumer_value(uint16_t conn_id, uint8_t key_cmd, bool key_pressed)
+{
+    uint8_t buffer[HID_CC_IN_RPT_LEN] = {0, 0};
+    if (key_pressed) {
+        LOG_DEBUG("hid_consumer_build_report");
+        hid_consumer_build_report(buffer, key_cmd);
+    }
+    LOG_DEBUG("buffer[0] = %x, buffer[1] = %x", buffer[0], buffer[1]);
+    hid_dev_send_report(hidd_le_env.gatt_if, conn_id,
+                        HID_RPT_ID_CC_IN, HID_REPORT_TYPE_INPUT, HID_CC_IN_RPT_LEN, buffer);
+    return;
+}
+
+void esp_hidd_send_keyboard_value(uint16_t conn_id, key_mask_t special_key_mask, uint8_t *keyboard_cmd, uint8_t num_key)
+{
+    if (num_key > HID_KEYBOARD_IN_RPT_LEN - 2) {
+        LOG_ERROR("%s(), the number key should not be more than %d", __func__, HID_KEYBOARD_IN_RPT_LEN);
+        return;
+    }
+   
+    uint8_t buffer[HID_KEYBOARD_IN_RPT_LEN] = {0};
+   
+    buffer[0] = special_key_mask;
+    
+    for (int i = 0; i < num_key; i++) {
+        buffer[i+2] = keyboard_cmd[i];
+    }
+
+    LOG_DEBUG("the key vaule = %d,%d,%d, %d, %d, %d,%d, %d", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7]);
+    hid_dev_send_report(hidd_le_env.gatt_if, conn_id,
+                        HID_RPT_ID_KEY_IN, HID_REPORT_TYPE_INPUT, HID_KEYBOARD_IN_RPT_LEN, buffer);
+    return;
+}
+
+void esp_hidd_send_mouse_value(uint16_t conn_id, uint8_t mouse_button, int8_t mickeys_x, int8_t mickeys_y)
+{
+    uint8_t buffer[HID_MOUSE_IN_RPT_LEN];
+    
+    buffer[0] = mouse_button;   // Buttons
+    buffer[1] = mickeys_x;           // X
+    buffer[2] = mickeys_y;           // Y
+    buffer[3] = 0;           // Wheel
+    buffer[4] = 0;           // AC Pan
+
+    hid_dev_send_report(hidd_le_env.gatt_if, conn_id,
+                        HID_RPT_ID_MOUSE_IN, HID_REPORT_TYPE_INPUT, HID_MOUSE_IN_RPT_LEN, buffer);
+    return;
+}
+
+
+
diff --git a/examples/bluetooth/ble_hid_device_demo/main/esp_hidd_prf_api.h b/examples/bluetooth/ble_hid_device_demo/main/esp_hidd_prf_api.h
new file mode 100644 (file)
index 0000000..32c8c6c
--- /dev/null
@@ -0,0 +1,167 @@
+// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef __ESP_HIDD_API_H__
+#define __ESP_HIDD_API_H__
+
+#include "esp_bt_defs.h"
+#include "esp_gatt_defs.h"
+#include "esp_err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    ESP_HIDD_EVENT_REG_FINISH = 0,                     
+    ESP_BAT_EVENT_REG,
+    ESP_HIDD_EVENT_DEINIT_FINISH,                       
+    ESP_HIDD_EVENT_BLE_CONNECT,                         
+    ESP_HIDD_EVENT_BLE_DISCONNECT,
+    ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT,
+} esp_hidd_cb_event_t;
+
+/// HID config status
+typedef enum {
+    ESP_HIDD_STA_CONN_SUCCESS = 0x00,
+    ESP_HIDD_STA_CONN_FAIL    = 0x01,
+} esp_hidd_sta_conn_state_t;
+
+/// HID init status
+typedef enum {
+    ESP_HIDD_INIT_OK = 0,
+    ESP_HIDD_INIT_FAILED = 1,
+} esp_hidd_init_state_t;
+
+/// HID deinit status
+typedef enum {
+    ESP_HIDD_DEINIT_OK = 0,
+    ESP_HIDD_DEINIT_FAILED = 0,
+} esp_hidd_deinit_state_t;
+
+#define LEFT_CONTROL_KEY_MASK        (1 >> 0)
+#define LEFT_SHIFT_KEY_MASK              (1 >> 1)
+#define LEFT_ALT_KEY_MASK            (1 >> 2)
+#define LEFT_GUI_KEY_MASK            (1 >> 3)
+#define RIGHT_CONTROL_KEY_MASK       (1 >> 4)
+#define RIGHT_SHIFT_KEY_MASK         (1 >> 5)
+#define RIGHT_ALT_KEY_MASK           (1 >> 6)
+#define RIGHT_GUI_KEY_MASK           (1 >> 7)
+typedef uint8_t key_mask_t;
+/**
+ * @brief HIDD callback parameters union 
+ */
+typedef union {
+    /**
+        * @brief ESP_HIDD_EVENT_INIT_FINISH
+        */
+    struct hidd_init_finish_evt_param {
+        esp_hidd_init_state_t state;                           /*!< Initial status */
+        esp_gatt_if_t gatts_if;
+    } init_finish;                                                           /*!< HID callback param of ESP_HIDD_EVENT_INIT_FINISH */
+
+    /**
+        * @brief ESP_HIDD_EVENT_DEINIT_FINISH
+        */
+    struct hidd_deinit_finish_evt_param {
+        esp_hidd_deinit_state_t state;                         /*!< De-initial status */
+    } deinit_finish;                                                           /*!< HID callback param of ESP_HIDD_EVENT_DEINIT_FINISH */
+
+    /**
+     * @brief ESP_HIDD_EVENT_CONNECT
+        */
+    struct hidd_connect_evt_param {
+        uint16_t conn_id;
+        esp_bd_addr_t remote_bda;                   /*!< HID Remote bluetooth connection index */
+    } connect;                                                                     /*!< HID callback param of ESP_HIDD_EVENT_CONNECT */
+
+    /**
+     * @brief ESP_HIDD_EVENT_DISCONNECT
+        */
+    struct hidd_disconnect_evt_param {
+        esp_bd_addr_t remote_bda;                   /*!< HID Remote bluetooth device address */
+    } disconnect;                                                                      /*!< HID callback param of ESP_HIDD_EVENT_DISCONNECT */
+
+    /**
+     * @brief ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT
+        */
+    struct hidd_vendor_write_evt_param {
+        uint16_t conn_id;                           /*!< HID connection index */
+        uint16_t report_id;                         /*!< HID report index */
+        uint16_t length;                            /*!< data length */
+        uint8_t  *data;                             /*!< The pointer to the data */
+    } vendor_write;                                                                    /*!< HID callback param of ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT */
+
+} esp_hidd_cb_param_t;
+
+
+/**
+ * @brief HID device event callback function type
+ * @param event : Event type
+ * @param param : Point to callback parameter, currently is union type
+ */
+typedef void (*esp_hidd_event_cb_t) (esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param);
+
+
+
+/**
+ *
+ * @brief           This function is called to receive hid device callback event
+ *
+ * @param[in]    callbacks: callback functions
+ *
+ * @return         ESP_OK - success, other - failed
+ *
+ */
+esp_err_t esp_hidd_register_callbacks(esp_hidd_event_cb_t callbacks);
+
+/**
+ *
+ * @brief           This function is called to initialize hid device profile
+ *
+ * @return          ESP_OK - success, other - failed
+ *
+ */
+esp_err_t esp_hidd_profile_init(void);
+
+/**
+ *
+ * @brief           This function is called to de-initialize hid device profile
+ *
+ * @return          ESP_OK - success, other - failed
+ *
+ */
+esp_err_t esp_hidd_profile_deinit(void);
+
+/**
+ *
+ * @brief           Get hidd profile version
+ * 
+ * @return          Most 8bit significant is Great version, Least 8bit is Sub version
+ *
+ */
+uint16_t esp_hidd_get_version(void);
+
+void esp_hidd_send_consumer_value(uint16_t conn_id, uint8_t key_cmd, bool key_pressed);
+
+void esp_hidd_send_keyboard_value(uint16_t conn_id, key_mask_t special_key_mask, uint8_t *keyboard_cmd, uint8_t num_key);
+
+void esp_hidd_send_mouse_value(uint16_t conn_id, uint8_t mouse_button, int8_t mickeys_x, int8_t mickeys_y);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ESP_HIDD_API_H__ */
+
diff --git a/examples/bluetooth/ble_hid_device_demo/main/hid_dev.c b/examples/bluetooth/ble_hid_device_demo/main/hid_dev.c
new file mode 100644 (file)
index 0000000..aba5724
--- /dev/null
@@ -0,0 +1,143 @@
+// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "hid_dev.h"
+#include "bt_trace.h"
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static hid_report_map_t *hid_dev_rpt_tbl;
+static uint8_t hid_dev_rpt_tbl_Len;
+
+static hid_report_map_t *hid_dev_rpt_by_id(uint8_t id, uint8_t type)
+{
+    hid_report_map_t *rpt = hid_dev_rpt_tbl;
+
+    for (uint8_t i = hid_dev_rpt_tbl_Len; i > 0; i--, rpt++) {
+        if (rpt->id == id && rpt->type == type && rpt->mode == hidProtocolMode) {
+            return rpt;
+        }
+    }
+
+    return NULL;
+}
+
+void hid_dev_register_reports(uint8_t num_reports, hid_report_map_t *p_report)
+{
+    hid_dev_rpt_tbl = p_report;
+    hid_dev_rpt_tbl_Len = num_reports;
+    return;
+}
+
+void hid_dev_send_report(esp_gatt_if_t gatts_if, uint16_t conn_id,
+                                    uint8_t id, uint8_t type, uint8_t length, uint8_t *data)
+{
+    hid_report_map_t *p_rpt;
+
+    // get att handle for report
+    if ((p_rpt = hid_dev_rpt_by_id(id, type)) != NULL) {
+        // if notifications are enabled
+        LOG_DEBUG("%s(), send the report, handle = %d", __func__, p_rpt->handle);
+        esp_ble_gatts_send_indicate(gatts_if, conn_id, p_rpt->handle, length, data, false);
+    }
+    
+    return;
+}
+
+void hid_consumer_build_report(uint8_t *buffer, consumer_cmd_t cmd)
+{
+    if (!buffer) {
+        LOG_ERROR("%s(), the buffer is NULL, hid build report failed.", __func__);
+        return;
+    }
+    
+    switch (cmd) {
+        case HID_CONSUMER_CHANNEL_UP:
+            HID_CC_RPT_SET_CHANNEL(buffer, HID_CC_RPT_CHANNEL_UP);
+            break;
+
+        case HID_CONSUMER_CHANNEL_DOWN:
+            HID_CC_RPT_SET_CHANNEL(buffer, HID_CC_RPT_CHANNEL_DOWN);
+            break;
+
+        case HID_CONSUMER_VOLUME_UP:
+            HID_CC_RPT_SET_VOLUME_UP(buffer);
+            break;
+
+        case HID_CONSUMER_VOLUME_DOWN:
+            HID_CC_RPT_SET_VOLUME_DOWN(buffer);
+            break;
+
+        case HID_CONSUMER_MUTE:
+            HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_MUTE);
+            break;
+
+        case HID_CONSUMER_POWER:
+            HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_POWER);
+            break;
+
+        case HID_CONSUMER_RECALL_LAST:
+            HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_LAST);
+            break;
+
+        case HID_CONSUMER_ASSIGN_SEL:
+            HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_ASSIGN_SEL);
+            break;
+
+        case HID_CONSUMER_PLAY:
+            HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_PLAY);
+            break;
+
+        case HID_CONSUMER_PAUSE:
+            HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_PAUSE);
+            break;
+
+        case HID_CONSUMER_RECORD:
+            HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_RECORD);
+            break;
+
+        case HID_CONSUMER_FAST_FORWARD:
+            HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_FAST_FWD);
+            break;
+
+        case HID_CONSUMER_REWIND:
+            HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_REWIND);
+            break;
+
+        case HID_CONSUMER_SCAN_NEXT_TRK:
+            HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_SCAN_NEXT_TRK);
+            break;
+
+        case HID_CONSUMER_SCAN_PREV_TRK:
+            HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_SCAN_PREV_TRK);
+            break;
+
+        case HID_CONSUMER_STOP:
+            HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_STOP);
+            break;
+
+        default:
+            break;
+    }
+
+    return;
+}
+
diff --git a/examples/bluetooth/ble_hid_device_demo/main/hid_dev.h b/examples/bluetooth/ble_hid_device_demo/main/hid_dev.h
new file mode 100644 (file)
index 0000000..17b406b
--- /dev/null
@@ -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__ */
+
diff --git a/examples/bluetooth/ble_hid_device_demo/main/hid_device_le_prf.c b/examples/bluetooth/ble_hid_device_demo/main/hid_device_le_prf.c
new file mode 100644 (file)
index 0000000..b938c50
--- /dev/null
@@ -0,0 +1,762 @@
+// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "hidd_le_prf_int.h"
+#include <string.h>
+#include "bt_types.h"
+#include "bt_trace.h"
+//#include "esp_gap_ble_api.h"
+
+
+/// characteristic presentation information
+struct prf_char_pres_fmt
+{
+    /// Unit (The Unit is a UUID)
+    uint16_t unit;
+    /// Description
+    uint16_t description;
+    /// Format
+    uint8_t format;
+    /// Exponent
+    uint8_t exponent;
+    /// Name space
+    uint8_t name_space;
+};
+
+// HID report mapping table
+static hid_report_map_t hid_rpt_map[HID_NUM_REPORTS];
+
+// HID Report Map characteristic value
+// Keyboard report descriptor (using format for Boot interface descriptor)
+static const uint8_t hidReportMap[] = {
+    0x05, 0x01,  // Usage Page (Generic Desktop)
+    0x09, 0x02,  // Usage (Mouse)
+    0xA1, 0x01,  // Collection (Application)
+    0x85, 0x01,  // Report Id (1)
+    0x09, 0x01,  //   Usage (Pointer)
+    0xA1, 0x00,  //   Collection (Physical)
+    0x05, 0x09,  //     Usage Page (Buttons)
+    0x19, 0x01,  //     Usage Minimum (01) - Button 1
+    0x29, 0x03,  //     Usage Maximum (03) - Button 3
+    0x15, 0x00,  //     Logical Minimum (0)
+    0x25, 0x01,  //     Logical Maximum (1)
+    0x75, 0x01,  //     Report Size (1)
+    0x95, 0x03,  //     Report Count (3)
+    0x81, 0x02,  //     Input (Data, Variable, Absolute) - Button states
+    0x75, 0x05,  //     Report Size (5)
+    0x95, 0x01,  //     Report Count (1)
+    0x81, 0x01,  //     Input (Constant) - Padding or Reserved bits
+    0x05, 0x01,  //     Usage Page (Generic Desktop)
+    0x09, 0x30,  //     Usage (X)
+    0x09, 0x31,  //     Usage (Y)
+    0x09, 0x38,  //     Usage (Wheel)
+    0x15, 0x81,  //     Logical Minimum (-127)
+    0x25, 0x7F,  //     Logical Maximum (127)
+    0x75, 0x08,  //     Report Size (8)
+    0x95, 0x03,  //     Report Count (3)
+    0x81, 0x06,  //     Input (Data, Variable, Relative) - X & Y coordinate
+    0xC0,        //   End Collection
+    0xC0,        // End Collection
+
+    0x05, 0x01,  // Usage Pg (Generic Desktop)
+    0x09, 0x06,  // Usage (Keyboard)
+    0xA1, 0x01,  // Collection: (Application)
+    0x85, 0x02,  // Report Id (2)
+    //
+    0x05, 0x07,  //   Usage Pg (Key Codes)
+    0x19, 0xE0,  //   Usage Min (224)
+    0x29, 0xE7,  //   Usage Max (231)
+    0x15, 0x00,  //   Log Min (0)
+    0x25, 0x01,  //   Log Max (1)
+    //
+    //   Modifier byte
+    0x75, 0x01,  //   Report Size (1)
+    0x95, 0x08,  //   Report Count (8)
+    0x81, 0x02,  //   Input: (Data, Variable, Absolute)
+    //
+    //   Reserved byte
+    0x95, 0x01,  //   Report Count (1)
+    0x75, 0x08,  //   Report Size (8)
+    0x81, 0x01,  //   Input: (Constant)
+    //
+    //   LED report
+    0x95, 0x05,  //   Report Count (5)
+    0x75, 0x01,  //   Report Size (1)
+    0x05, 0x08,  //   Usage Pg (LEDs)
+    0x19, 0x01,  //   Usage Min (1)
+    0x29, 0x05,  //   Usage Max (5)
+    0x91, 0x02,  //   Output: (Data, Variable, Absolute)
+    //
+    //   LED report padding
+    0x95, 0x01,  //   Report Count (1)
+    0x75, 0x03,  //   Report Size (3)
+    0x91, 0x01,  //   Output: (Constant)
+    //
+    //   Key arrays (6 bytes)
+    0x95, 0x06,  //   Report Count (6)
+    0x75, 0x08,  //   Report Size (8)
+    0x15, 0x00,  //   Log Min (0)
+    0x25, 0x65,  //   Log Max (101)
+    0x05, 0x07,  //   Usage Pg (Key Codes)
+    0x19, 0x00,  //   Usage Min (0)
+    0x29, 0x65,  //   Usage Max (101)
+    0x81, 0x00,  //   Input: (Data, Array)
+    //
+    0xC0,        // End Collection
+    //
+    0x05, 0x0C,   // Usage Pg (Consumer Devices)
+    0x09, 0x01,   // Usage (Consumer Control)
+    0xA1, 0x01,   // Collection (Application)
+    0x85, 0x03,   // Report Id (3)
+    0x09, 0x02,   //   Usage (Numeric Key Pad)
+    0xA1, 0x02,   //   Collection (Logical)
+    0x05, 0x09,   //     Usage Pg (Button)
+    0x19, 0x01,   //     Usage Min (Button 1)
+    0x29, 0x0A,   //     Usage Max (Button 10)
+    0x15, 0x01,   //     Logical Min (1)
+    0x25, 0x0A,   //     Logical Max (10)
+    0x75, 0x04,   //     Report Size (4)
+    0x95, 0x01,   //     Report Count (1)
+    0x81, 0x00,   //     Input (Data, Ary, Abs)
+    0xC0,         //   End Collection
+    0x05, 0x0C,   //   Usage Pg (Consumer Devices)
+    0x09, 0x86,   //   Usage (Channel)
+    0x15, 0xFF,   //   Logical Min (-1)
+    0x25, 0x01,   //   Logical Max (1)
+    0x75, 0x02,   //   Report Size (2)
+    0x95, 0x01,   //   Report Count (1)
+    0x81, 0x46,   //   Input (Data, Var, Rel, Null)
+    0x09, 0xE9,   //   Usage (Volume Up)
+    0x09, 0xEA,   //   Usage (Volume Down)
+    0x15, 0x00,   //   Logical Min (0)
+    0x75, 0x01,   //   Report Size (1)
+    0x95, 0x02,   //   Report Count (2)
+    0x81, 0x02,   //   Input (Data, Var, Abs)
+    0x09, 0xE2,   //   Usage (Mute)
+    0x09, 0x30,   //   Usage (Power)
+    0x09, 0x83,   //   Usage (Recall Last)
+    0x09, 0x81,   //   Usage (Assign Selection)
+    0x09, 0xB0,   //   Usage (Play)
+    0x09, 0xB1,   //   Usage (Pause)
+    0x09, 0xB2,   //   Usage (Record)
+    0x09, 0xB3,   //   Usage (Fast Forward)
+    0x09, 0xB4,   //   Usage (Rewind)
+    0x09, 0xB5,   //   Usage (Scan Next)
+    0x09, 0xB6,   //   Usage (Scan Prev)
+    0x09, 0xB7,   //   Usage (Stop)
+    0x15, 0x01,   //   Logical Min (1)
+    0x25, 0x0C,   //   Logical Max (12)
+    0x75, 0x04,   //   Report Size (4)
+    0x95, 0x01,   //   Report Count (1)
+    0x81, 0x00,   //   Input (Data, Ary, Abs)
+    0x09, 0x80,   //   Usage (Selection)
+    0xA1, 0x02,   //   Collection (Logical)
+    0x05, 0x09,   //     Usage Pg (Button)
+    0x19, 0x01,   //     Usage Min (Button 1)
+    0x29, 0x03,   //     Usage Max (Button 3)
+    0x15, 0x01,   //     Logical Min (1)
+    0x25, 0x03,   //     Logical Max (3)
+    0x75, 0x02,   //     Report Size (2)
+    0x81, 0x00,   //     Input (Data, Ary, Abs)
+    0xC0,           //   End Collection
+    0x81, 0x03,   //   Input (Const, Var, Abs)
+    0xC0,            // End Collection
+    0x06, 0xFF, 0xFF, // Usage Page(Vendor defined)
+    0x09, 0xA5,       // Usage(Vendor Defined)
+    0xA1, 0x01,       // Collection(Application)
+    0x85, 0x04,   // Report Id (4)
+    0x09, 0xA6,   // Usage(Vendor defined)
+    0x09, 0xA9,   // Usage(Vendor defined)
+    0x75, 0x08,   // Report Size
+    0x95, 0x7F,   // Report Count = 127 Btyes
+    0x91, 0x02,   // Output(Data, Variable, Absolute)
+    0xC0,         // End Collection
+};
+
+/// Battery Service Attributes Indexes
+enum
+{
+    BAS_IDX_SVC,
+
+    BAS_IDX_BATT_LVL_CHAR,
+    BAS_IDX_BATT_LVL_VAL,
+    BAS_IDX_BATT_LVL_NTF_CFG,
+    BAS_IDX_BATT_LVL_PRES_FMT,
+
+    BAS_IDX_NB,
+};
+
+#define HI_UINT16(a) (((a) >> 8) & 0xFF)
+#define LO_UINT16(a) ((a) & 0xFF)
+
+hidd_le_env_t hidd_le_env;
+
+// HID report map length
+uint8_t hidReportMapLen = sizeof(hidReportMap);
+uint8_t hidProtocolMode = HID_PROTOCOL_MODE_REPORT;
+
+// HID report mapping table
+//static hidRptMap_t  hidRptMap[HID_NUM_REPORTS];
+
+// HID Information characteristic value
+static const uint8_t hidInfo[HID_INFORMATION_LEN] = {
+    LO_UINT16(0x0111), HI_UINT16(0x0111),             // bcdHID (USB HID version)
+    0x00,                                             // bCountryCode
+    HID_KBD_FLAGS                                     // Flags
+};
+
+
+// HID External Report Reference Descriptor
+static uint16_t hidExtReportRefDesc = ESP_GATT_UUID_BATTERY_LEVEL;
+
+// HID Report Reference characteristic descriptor, mouse input
+static uint8_t hidReportRefMouseIn[HID_REPORT_REF_LEN] =
+             { HID_RPT_ID_MOUSE_IN, HID_REPORT_TYPE_INPUT };
+
+
+// HID Report Reference characteristic descriptor, key input
+static uint8_t hidReportRefKeyIn[HID_REPORT_REF_LEN] =
+             { HID_RPT_ID_KEY_IN, HID_REPORT_TYPE_INPUT };
+
+// HID Report Reference characteristic descriptor, LED output
+static uint8_t hidReportRefLedOut[HID_REPORT_REF_LEN] =
+             { HID_RPT_ID_LED_OUT, HID_REPORT_TYPE_OUTPUT };
+
+static uint8_t hidReportRefVendorOut[HID_REPORT_REF_LEN] = 
+             {HID_RPT_ID_VENDOR_OUT, HID_REPORT_TYPE_OUTPUT};
+
+// HID Report Reference characteristic descriptor, Feature
+static uint8_t hidReportRefFeature[HID_REPORT_REF_LEN] =
+             { HID_RPT_ID_FEATURE, HID_REPORT_TYPE_FEATURE };
+
+// HID Report Reference characteristic descriptor, consumer control input
+static uint8_t hidReportRefCCIn[HID_REPORT_REF_LEN] =
+             { HID_RPT_ID_CC_IN, HID_REPORT_TYPE_INPUT };
+
+
+/*
+ *  Heart Rate PROFILE ATTRIBUTES
+ ****************************************************************************************
+ */
+
+/// hid Service uuid
+static uint16_t hid_le_svc = ATT_SVC_HID;
+uint16_t            hid_count = 0;
+esp_gatts_incl_svc_desc_t incl_svc = {0};
+
+#define CHAR_DECLARATION_SIZE   (sizeof(uint8_t))
+///the uuid definition
+static const uint16_t primary_service_uuid = ESP_GATT_UUID_PRI_SERVICE;
+static const uint16_t include_service_uuid = ESP_GATT_UUID_INCLUDE_SERVICE;
+static const uint16_t character_declaration_uuid = ESP_GATT_UUID_CHAR_DECLARE;
+static const uint16_t character_client_config_uuid = ESP_GATT_UUID_CHAR_CLIENT_CONFIG;
+static const uint16_t hid_info_char_uuid = ESP_GATT_UUID_HID_INFORMATION;
+static const uint16_t hid_report_map_uuid    = ESP_GATT_UUID_HID_REPORT_MAP;
+static const uint16_t hid_control_point_uuid = ESP_GATT_UUID_HID_CONTROL_POINT;
+static const uint16_t hid_report_uuid = ESP_GATT_UUID_HID_REPORT;
+static const uint16_t hid_proto_mode_uuid = ESP_GATT_UUID_HID_PROTO_MODE;
+static const uint16_t hid_kb_input_uuid = ESP_GATT_UUID_HID_BT_KB_INPUT;
+static const uint16_t hid_kb_output_uuid = ESP_GATT_UUID_HID_BT_KB_OUTPUT;
+static const uint16_t hid_mouse_input_uuid = ESP_GATT_UUID_HID_BT_MOUSE_INPUT;
+static const uint16_t hid_repot_map_ext_desc_uuid = ESP_GATT_UUID_EXT_RPT_REF_DESCR;
+static const uint16_t hid_report_ref_descr_uuid = ESP_GATT_UUID_RPT_REF_DESCR;
+///the propoty definition
+static const uint8_t char_prop_notify = ESP_GATT_CHAR_PROP_BIT_NOTIFY;
+static const uint8_t char_prop_read = ESP_GATT_CHAR_PROP_BIT_READ;
+static const uint8_t char_prop_write = ESP_GATT_CHAR_PROP_BIT_WRITE;
+static const uint8_t char_prop_read_write = ESP_GATT_CHAR_PROP_BIT_WRITE|ESP_GATT_CHAR_PROP_BIT_READ;
+static const uint8_t char_prop_read_notify = ESP_GATT_CHAR_PROP_BIT_READ|ESP_GATT_CHAR_PROP_BIT_NOTIFY;
+static const uint8_t char_prop_read_write_notify = ESP_GATT_CHAR_PROP_BIT_READ|ESP_GATT_CHAR_PROP_BIT_WRITE|ESP_GATT_CHAR_PROP_BIT_NOTIFY;
+
+/// battary Service
+static const uint16_t battary_svc = ESP_GATT_UUID_BATTERY_SERVICE_SVC;
+
+static const uint16_t bat_lev_uuid = ESP_GATT_UUID_BATTERY_LEVEL;
+static const uint8_t   bat_lev_ccc[2] ={ 0x00, 0x00};
+static const uint16_t char_format_uuid = ESP_GATT_UUID_CHAR_PRESENT_FORMAT;
+
+static uint8_t battary_lev = 50;
+/// Full HRS Database Description - Used to add attributes into the database
+static const esp_gatts_attr_db_t bas_att_db[BAS_IDX_NB] =
+{
+    // Battary Service Declaration
+    [BAS_IDX_SVC]               =  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ,
+                                            sizeof(uint16_t), sizeof(battary_svc), (uint8_t *)&battary_svc}},
+
+    // Battary level Characteristic Declaration
+    [BAS_IDX_BATT_LVL_CHAR]    = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
+                                                   CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}},
+      
+    // Battary level Characteristic Value
+    [BAS_IDX_BATT_LVL_VAL]                     = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&bat_lev_uuid, ESP_GATT_PERM_READ,
+                                                                sizeof(uint8_t),sizeof(uint8_t), &battary_lev}},
+
+    // Battary level Characteristic - Client Characteristic Configuration Descriptor
+    [BAS_IDX_BATT_LVL_NTF_CFG]         =  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,
+                                                          sizeof(uint16_t),sizeof(bat_lev_ccc), (uint8_t *)bat_lev_ccc}},
+
+    // Battary level report Characteristic Declaration
+    [BAS_IDX_BATT_LVL_PRES_FMT]  = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&char_format_uuid, ESP_GATT_PERM_READ,
+                                                        sizeof(struct prf_char_pres_fmt), 0, NULL}},
+};
+
+
+/// Full Hid device Database Description - Used to add attributes into the database
+static esp_gatts_attr_db_t hidd_le_gatt_db[HIDD_LE_IDX_NB] =
+{
+            // HID Service Declaration
+    [HIDD_LE_IDX_SVC]                       = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, 
+                                                             ESP_GATT_PERM_READ_ENCRYPTED, sizeof(uint16_t), sizeof(hid_le_svc), 
+                                                            (uint8_t *)&hid_le_svc}},
+
+    // HID Service Declaration
+    [HIDD_LE_IDX_INCL_SVC]               = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&include_service_uuid,
+                                                            ESP_GATT_PERM_READ,
+                                                            sizeof(esp_gatts_incl_svc_desc_t), sizeof(esp_gatts_incl_svc_desc_t),
+                                                            (uint8_t *)&incl_svc}},
+
+    // HID Information Characteristic Declaration
+    [HIDD_LE_IDX_HID_INFO_CHAR]     = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
+                                                            ESP_GATT_PERM_READ,
+                                                            CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
+                                                            (uint8_t *)&char_prop_read_write}},
+    // HID Information Characteristic Value
+    [HIDD_LE_IDX_HID_INFO_VAL]       = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_info_char_uuid,
+                                                            ESP_GATT_PERM_READ,
+                                                            sizeof(hids_hid_info_t), sizeof(hidInfo),
+                                                            (uint8_t *)&hidInfo}},
+
+    // HID Control Point Characteristic Declaration
+    [HIDD_LE_IDX_HID_CTNL_PT_CHAR]  = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
+                                                              ESP_GATT_PERM_READ,
+                                                              CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
+                                                              (uint8_t *)&char_prop_write}},
+    // HID Control Point Characteristic Value
+    [HIDD_LE_IDX_HID_CTNL_PT_VAL]    = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_control_point_uuid,
+                                                             ESP_GATT_PERM_WRITE,
+                                                             sizeof(uint8_t), 0,
+                                                             NULL}},
+
+    // Report Map Characteristic Declaration
+    [HIDD_LE_IDX_REPORT_MAP_CHAR]   = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
+                                                              ESP_GATT_PERM_READ,
+                                                              CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
+                                                              (uint8_t *)&char_prop_read}},
+    // Report Map Characteristic Value
+    [HIDD_LE_IDX_REPORT_MAP_VAL]     = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_map_uuid,
+                                                              ESP_GATT_PERM_READ,
+                                                              HIDD_LE_REPORT_MAP_MAX_LEN, sizeof(hidReportMap),
+                                                              (uint8_t *)&hidReportMap}},
+
+    // Report Map Characteristic - External Report Reference Descriptor
+    [HIDD_LE_IDX_REPORT_MAP_EXT_REP_REF]  = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_repot_map_ext_desc_uuid,
+                                                                        ESP_GATT_PERM_READ,
+                                                                        sizeof(uint16_t), sizeof(uint16_t),
+                                                                        (uint8_t *)&hidExtReportRefDesc}},
+
+    // Protocol Mode Characteristic Declaration
+    [HIDD_LE_IDX_PROTO_MODE_CHAR]            = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
+                                                                        ESP_GATT_PERM_READ,
+                                                                        CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
+                                                                        (uint8_t *)&char_prop_read_write}},
+    // Protocol Mode Characteristic Value
+    [HIDD_LE_IDX_PROTO_MODE_VAL]               = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_proto_mode_uuid,
+                                                                        (ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE),
+                                                                        sizeof(uint8_t), sizeof(hidProtocolMode),
+                                                                        (uint8_t *)&hidProtocolMode}},
+    
+    [HIDD_LE_IDX_REPORT_MOUSE_IN_CHAR]       = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
+                                                                         ESP_GATT_PERM_READ,
+                                                                         CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
+                                                                         (uint8_t *)&char_prop_read_notify}},
+    
+    [HIDD_LE_IDX_REPORT_MOUSE_IN_VAL]        = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_uuid,
+                                                                       ESP_GATT_PERM_READ,
+                                                                       HIDD_LE_REPORT_MAX_LEN, 0,
+                                                                       NULL}},
+    
+    [HIDD_LE_IDX_REPORT_MOUSE_IN_CCC]        = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid,
+                                                                      (ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE),
+                                                                      sizeof(uint16_t), 0,
+                                                                      NULL}},
+    
+    [HIDD_LE_IDX_REPORT_MOUSE_REP_REF]       = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_ref_descr_uuid,
+                                                                       ESP_GATT_PERM_READ,
+                                                                       sizeof(hidReportRefMouseIn), sizeof(hidReportRefMouseIn),
+                                                                       hidReportRefMouseIn}},
+    // Report Characteristic Declaration
+    [HIDD_LE_IDX_REPORT_KEY_IN_CHAR]         = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
+                                                                         ESP_GATT_PERM_READ,
+                                                                         CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
+                                                                         (uint8_t *)&char_prop_read_notify}},
+    // Report Characteristic Value
+    [HIDD_LE_IDX_REPORT_KEY_IN_VAL]            = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_uuid,
+                                                                       ESP_GATT_PERM_READ,
+                                                                       HIDD_LE_REPORT_MAX_LEN, 0,
+                                                                       NULL}},
+    // Report KEY INPUT Characteristic - Client Characteristic Configuration Descriptor
+    [HIDD_LE_IDX_REPORT_KEY_IN_CCC]              = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid,
+                                                                      (ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE),
+                                                                      sizeof(uint16_t), 0,
+                                                                      NULL}},
+     // Report Characteristic - Report Reference Descriptor
+    [HIDD_LE_IDX_REPORT_KEY_IN_REP_REF]       = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_ref_descr_uuid,
+                                                                       ESP_GATT_PERM_READ,
+                                                                       sizeof(hidReportRefKeyIn), sizeof(hidReportRefKeyIn),
+                                                                       hidReportRefKeyIn}},
+
+     // Report Characteristic Declaration
+    [HIDD_LE_IDX_REPORT_LED_OUT_CHAR]         = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
+                                                                         ESP_GATT_PERM_READ,
+                                                                         CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
+                                                                         (uint8_t *)&char_prop_read_write}},
+
+    [HIDD_LE_IDX_REPORT_LED_OUT_VAL]            = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_uuid,
+                                                                       ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,
+                                                                       HIDD_LE_REPORT_MAX_LEN, 0,
+                                                                       NULL}},
+    [HIDD_LE_IDX_REPORT_LED_OUT_REP_REF]      =  {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_ref_descr_uuid,
+                                                                       ESP_GATT_PERM_READ,
+                                                                       sizeof(hidReportRefLedOut), sizeof(hidReportRefLedOut),
+                                                                       hidReportRefLedOut}},
+    // Report Characteristic Declaration
+    [HIDD_LE_IDX_REPORT_VENDOR_OUT_CHAR]        = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
+                                                                         ESP_GATT_PERM_READ,
+                                                                         CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
+                                                                         (uint8_t *)&char_prop_read_write_notify}},
+    [HIDD_LE_IDX_REPORT_VENDOR_OUT_VAL]         = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_uuid,
+                                                                       ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,
+                                                                       HIDD_LE_REPORT_MAX_LEN, 0,
+                                                                       NULL}},
+    [HIDD_LE_IDX_REPORT_VENDOR_OUT_REP_REF]     = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_ref_descr_uuid,
+                                                                       ESP_GATT_PERM_READ,
+                                                                       sizeof(hidReportRefVendorOut), sizeof(hidReportRefVendorOut),
+                                                                       hidReportRefVendorOut}},
+
+        // Report Characteristic Declaration
+    [HIDD_LE_IDX_REPORT_CC_IN_CHAR]         = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
+                                                                         ESP_GATT_PERM_READ,
+                                                                         CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
+                                                                         (uint8_t *)&char_prop_read_notify}},
+    // Report Characteristic Value
+    [HIDD_LE_IDX_REPORT_CC_IN_VAL]            = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_uuid,
+                                                                       ESP_GATT_PERM_READ,
+                                                                       HIDD_LE_REPORT_MAX_LEN, 0,
+                                                                       NULL}},
+    // Report KEY INPUT Characteristic - Client Characteristic Configuration Descriptor
+    [HIDD_LE_IDX_REPORT_CC_IN_CCC]              = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid,
+                                                                      (ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE),
+                                                                      sizeof(uint16_t), 0,
+                                                                      NULL}},
+     // Report Characteristic - Report Reference Descriptor
+    [HIDD_LE_IDX_REPORT_CC_IN_REP_REF]       = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_ref_descr_uuid,
+                                                                       ESP_GATT_PERM_READ,
+                                                                       sizeof(hidReportRefCCIn), sizeof(hidReportRefCCIn),
+                                                                       hidReportRefCCIn}},
+    
+    // Boot Keyboard Input Report Characteristic Declaration
+    [HIDD_LE_IDX_BOOT_KB_IN_REPORT_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
+                                                                        ESP_GATT_PERM_READ,
+                                                                        CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
+                                                                        (uint8_t *)&char_prop_read_notify}},
+    // Boot Keyboard Input Report Characteristic Value
+    [HIDD_LE_IDX_BOOT_KB_IN_REPORT_VAL]   = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_kb_input_uuid,
+                                                                        ESP_GATT_PERM_READ,
+                                                                        HIDD_LE_BOOT_REPORT_MAX_LEN, 0,
+                                                                        NULL}},
+    // Boot Keyboard Input Report Characteristic - Client Characteristic Configuration Descriptor
+    [HIDD_LE_IDX_BOOT_KB_IN_REPORT_NTF_CFG]  = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid,
+                                                                              (ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE),
+                                                                              sizeof(uint16_t), 0,
+                                                                              NULL}},
+
+    // Boot Keyboard Output Report Characteristic Declaration
+    [HIDD_LE_IDX_BOOT_KB_OUT_REPORT_CHAR]    = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
+                                                                              ESP_GATT_PERM_READ,
+                                                                              CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
+                                                                              (uint8_t *)&char_prop_read_write}},
+    // Boot Keyboard Output Report Characteristic Value
+    [HIDD_LE_IDX_BOOT_KB_OUT_REPORT_VAL]      = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_kb_output_uuid,
+                                                                              (ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE),
+                                                                              HIDD_LE_BOOT_REPORT_MAX_LEN, 0,
+                                                                              NULL}},
+
+    // Boot Mouse Input Report Characteristic Declaration
+    [HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
+                                                                              ESP_GATT_PERM_READ,
+                                                                              CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
+                                                                              (uint8_t *)&char_prop_read_notify}},
+    // Boot Mouse Input Report Characteristic Value
+    [HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_VAL]   = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_mouse_input_uuid,
+                                                                              ESP_GATT_PERM_READ,
+                                                                              HIDD_LE_BOOT_REPORT_MAX_LEN, 0,
+                                                                              NULL}},
+    // Boot Mouse Input Report Characteristic - Client Characteristic Configuration Descriptor
+    [HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_NTF_CFG]    = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid,
+                                                                                      (ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE),
+                                                                                      sizeof(uint16_t), 0,
+                                                                                      NULL}},
+
+    // Report Characteristic Declaration
+    [HIDD_LE_IDX_REPORT_CHAR]                    = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
+                                                                         ESP_GATT_PERM_READ,
+                                                                         CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
+                                                                         (uint8_t *)&char_prop_read_write}},
+    // Report Characteristic Value
+    [HIDD_LE_IDX_REPORT_VAL]                      = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_uuid,
+                                                                       ESP_GATT_PERM_READ,
+                                                                       HIDD_LE_REPORT_MAX_LEN, 0,
+                                                                       NULL}},
+    // Report Characteristic - Report Reference Descriptor
+    [HIDD_LE_IDX_REPORT_REP_REF]               = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_ref_descr_uuid,
+                                                                       ESP_GATT_PERM_READ,
+                                                                       sizeof(hidReportRefFeature), sizeof(hidReportRefFeature),
+                                                                       hidReportRefFeature}},
+};
+
+static void hid_add_id_tbl(void);
+
+void esp_hidd_prf_cb_hdl(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, 
+                                                                       esp_ble_gatts_cb_param_t *param)
+{
+    switch(event) {
+        case ESP_GATTS_REG_EVT: {
+            esp_hidd_cb_param_t hidd_param;
+            hidd_param.init_finish.state = param->reg.status;
+            if(param->reg.app_id == HIDD_APP_ID) {
+                hidd_le_env.gatt_if = gatts_if;
+                if(hidd_le_env.hidd_cb != NULL) {
+                    (hidd_le_env.hidd_cb)(ESP_HIDD_EVENT_REG_FINISH, &hidd_param);
+                    hidd_le_create_service(hidd_le_env.gatt_if);
+                }
+            }
+            if(param->reg.app_id == BATTRAY_APP_ID) {
+                hidd_param.init_finish.gatts_if = gatts_if;
+                 if(hidd_le_env.hidd_cb != NULL) {
+                    (hidd_le_env.hidd_cb)(ESP_BAT_EVENT_REG, &hidd_param);
+                }
+                
+            }
+           
+            break;
+        }
+        case ESP_GATTS_CONF_EVT: {
+            break;
+        }    
+        case ESP_GATTS_CREATE_EVT:
+            break;
+        case ESP_GATTS_CONNECT_EVT: {
+            esp_hidd_cb_param_t cb_param = {0};
+                       LOG_ERROR("the connection establish, conn_id = %x",param->connect.conn_id);
+                       memcpy(cb_param.connect.remote_bda, param->connect.remote_bda, sizeof(esp_bd_addr_t));
+            cb_param.connect.conn_id = param->connect.conn_id;
+            hidd_clcb_alloc(param->connect.conn_id, param->connect.remote_bda);
+            //esp_ble_set_encryption(param->connect.remote_bda, ESP_BLE_SEC_ENCRYPT_NO_MITM);
+            if(hidd_le_env.hidd_cb != NULL) {
+                (hidd_le_env.hidd_cb)(ESP_HIDD_EVENT_BLE_CONNECT, &cb_param);
+            }
+            break;
+        }
+        case ESP_GATTS_DISCONNECT_EVT: {
+                        if(hidd_le_env.hidd_cb != NULL) {
+                    (hidd_le_env.hidd_cb)(ESP_HIDD_EVENT_BLE_DISCONNECT, NULL);
+             }
+            hidd_clcb_dealloc(param->disconnect.conn_id);
+            break;
+        }
+        case ESP_GATTS_CLOSE_EVT:
+            break;
+        case ESP_GATTS_WRITE_EVT: {
+            esp_hidd_cb_param_t cb_param = {0};
+            if (param->write.handle == hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_VENDOR_OUT_VAL] &&
+                hidd_le_env.hidd_cb != NULL) {
+                cb_param.vendor_write.conn_id = param->write.conn_id;
+                cb_param.vendor_write.report_id = HID_RPT_ID_VENDOR_OUT;
+                cb_param.vendor_write.length = param->write.len;
+                cb_param.vendor_write.data = param->write.value;
+                (hidd_le_env.hidd_cb)(ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT, &cb_param);
+            }
+            break;
+        }
+        case ESP_GATTS_CREAT_ATTR_TAB_EVT: {
+            if (param->add_attr_tab.num_handle == BAS_IDX_NB && 
+                param->add_attr_tab.svc_uuid.uuid.uuid16 == ESP_GATT_UUID_BATTERY_SERVICE_SVC &&
+                param->add_attr_tab.status == ESP_GATT_OK) {
+                incl_svc.start_hdl = param->add_attr_tab.handles[BAS_IDX_SVC];
+                incl_svc.end_hdl = incl_svc.start_hdl + BAS_IDX_NB -1;
+                LOG_ERROR("%s(), start added the hid service to the stack database. incl_handle = %d", 
+                           __func__, incl_svc.start_hdl);
+                esp_ble_gatts_create_attr_tab(hidd_le_gatt_db, gatts_if, HIDD_LE_IDX_NB, 0);
+            }
+            if (param->add_attr_tab.num_handle == HIDD_LE_IDX_NB && 
+                param->add_attr_tab.status == ESP_GATT_OK) {
+                memcpy(hidd_le_env.hidd_inst.att_tbl, param->add_attr_tab.handles, 
+                            HIDD_LE_IDX_NB*sizeof(uint16_t));
+                LOG_ERROR("hid svc handle = %x",hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_SVC]);
+                hid_add_id_tbl();
+                       esp_ble_gatts_start_service(hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_SVC]);
+            } else {
+                esp_ble_gatts_start_service(param->add_attr_tab.handles[0]);
+            }
+            break;
+         }
+        
+        default:
+            break;
+    }
+}
+
+void hidd_le_create_service(esp_gatt_if_t gatts_if)
+{
+    /* Here should added the battery service first, because the hid service should include the battery service.
+       After finish to added the battery service then can added the hid service. */
+    esp_ble_gatts_create_attr_tab(bas_att_db, gatts_if, BAS_IDX_NB, 0);
+   
+}
+
+void hidd_le_init(void)
+{ 
+    
+    // Reset the hid device target environment
+    memset(&hidd_le_env, 0, sizeof(hidd_le_env_t));
+}
+
+void hidd_clcb_alloc (uint16_t conn_id, esp_bd_addr_t bda)
+{
+    uint8_t                   i_clcb = 0;
+    hidd_clcb_t      *p_clcb = NULL;
+
+    for (i_clcb = 0, p_clcb= hidd_le_env.hidd_clcb; i_clcb < HID_MAX_APPS; i_clcb++, p_clcb++) {
+        if (!p_clcb->in_use) {
+            p_clcb->in_use      = TRUE;
+            p_clcb->conn_id     = conn_id;
+            p_clcb->connected   = TRUE;
+            memcpy (p_clcb->remote_bda, bda, ESP_BD_ADDR_LEN);
+            break;
+        }
+    }
+    return;
+}
+
+bool hidd_clcb_dealloc (uint16_t conn_id)
+{
+    uint8_t              i_clcb = 0;
+    hidd_clcb_t      *p_clcb = NULL;
+
+    for (i_clcb = 0, p_clcb= hidd_le_env.hidd_clcb; i_clcb < HID_MAX_APPS; i_clcb++, p_clcb++) {
+            memset(p_clcb, 0, sizeof(hidd_clcb_t));
+            return TRUE;
+    }
+    
+    return FALSE;
+}
+
+esp_err_t hidd_register_cb(void)
+{
+       esp_err_t status;
+       status = esp_ble_gatts_register_callback(esp_hidd_prf_cb_hdl);
+       return status;
+}
+
+void hidd_set_attr_value(uint16_t handle, uint16_t val_len, const uint8_t *value)
+{
+    hidd_inst_t *hidd_inst = &hidd_le_env.hidd_inst;
+    if(hidd_inst->att_tbl[HIDD_LE_IDX_HID_INFO_VAL] <= handle && 
+        hidd_inst->att_tbl[HIDD_LE_IDX_REPORT_REP_REF] >= handle) {
+        esp_ble_gatts_set_attr_value(handle, val_len, value);
+    } else {
+        LOG_ERROR("%s error:Invalid handle value.",__func__);
+    }
+    return;
+}
+
+void hidd_get_attr_value(uint16_t handle, uint16_t *length, uint8_t **value)
+{
+    hidd_inst_t *hidd_inst = &hidd_le_env.hidd_inst;
+    if(hidd_inst->att_tbl[HIDD_LE_IDX_HID_INFO_VAL] <= handle && 
+        hidd_inst->att_tbl[HIDD_LE_IDX_REPORT_REP_REF] >= handle){
+        esp_ble_gatts_get_attr_value(handle, length, (const uint8_t **)value);
+    } else {
+        LOG_ERROR("%s error:Invalid handle value.", __func__);
+    }
+
+    return;
+}
+
+static void hid_add_id_tbl(void)
+{
+     // Mouse input report
+      hid_rpt_map[0].id = hidReportRefMouseIn[0];
+      hid_rpt_map[0].type = hidReportRefMouseIn[1];
+      hid_rpt_map[0].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_MOUSE_IN_VAL];
+      hid_rpt_map[0].cccdHandle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_MOUSE_IN_VAL];
+      hid_rpt_map[0].mode = HID_PROTOCOL_MODE_REPORT;
+     
+      // Key input report
+      hid_rpt_map[1].id = hidReportRefKeyIn[0];
+      hid_rpt_map[1].type = hidReportRefKeyIn[1];
+      hid_rpt_map[1].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_KEY_IN_VAL];
+      hid_rpt_map[1].cccdHandle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_KEY_IN_CCC];
+      hid_rpt_map[1].mode = HID_PROTOCOL_MODE_REPORT;
+     
+      // Consumer Control input report
+      hid_rpt_map[2].id = hidReportRefCCIn[0];
+      hid_rpt_map[2].type = hidReportRefCCIn[1];
+      hid_rpt_map[2].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_CC_IN_VAL];
+      hid_rpt_map[2].cccdHandle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_CC_IN_CCC];
+      hid_rpt_map[2].mode = HID_PROTOCOL_MODE_REPORT;
+     
+      // LED output report
+      hid_rpt_map[3].id = hidReportRefLedOut[0];
+      hid_rpt_map[3].type = hidReportRefLedOut[1];
+      hid_rpt_map[3].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_LED_OUT_VAL];
+      hid_rpt_map[3].cccdHandle = 0;
+      hid_rpt_map[3].mode = HID_PROTOCOL_MODE_REPORT;
+     
+      // Boot keyboard input report
+      // Use same ID and type as key input report
+      hid_rpt_map[4].id = hidReportRefKeyIn[0];
+      hid_rpt_map[4].type = hidReportRefKeyIn[1];
+      hid_rpt_map[4].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_BOOT_KB_IN_REPORT_VAL];
+      hid_rpt_map[4].cccdHandle = 0;
+      hid_rpt_map[4].mode = HID_PROTOCOL_MODE_BOOT;
+     
+      // Boot keyboard output report
+      // Use same ID and type as LED output report
+      hid_rpt_map[5].id = hidReportRefLedOut[0];
+      hid_rpt_map[5].type = hidReportRefLedOut[1];
+      hid_rpt_map[5].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_BOOT_KB_OUT_REPORT_VAL];
+      hid_rpt_map[5].cccdHandle = 0;
+      hid_rpt_map[5].mode = HID_PROTOCOL_MODE_BOOT;
+     
+      // Boot mouse input report
+      // Use same ID and type as mouse input report
+      hid_rpt_map[6].id = hidReportRefMouseIn[0];
+      hid_rpt_map[6].type = hidReportRefMouseIn[1];
+      hid_rpt_map[6].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_VAL];
+      hid_rpt_map[6].cccdHandle = 0;
+      hid_rpt_map[6].mode = HID_PROTOCOL_MODE_BOOT;
+     
+      // Feature report
+      hid_rpt_map[7].id = hidReportRefFeature[0];
+      hid_rpt_map[7].type = hidReportRefFeature[1];
+      hid_rpt_map[7].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_VAL];
+      hid_rpt_map[7].cccdHandle = 0;
+      hid_rpt_map[7].mode = HID_PROTOCOL_MODE_REPORT;
+
+
+  // Setup report ID map
+  hid_dev_register_reports(HID_NUM_REPORTS, hid_rpt_map);
+}
+
diff --git a/examples/bluetooth/ble_hid_device_demo/main/hidd_le_prf_int.h b/examples/bluetooth/ble_hid_device_demo/main/hidd_le_prf_int.h
new file mode 100644 (file)
index 0000000..311279a
--- /dev/null
@@ -0,0 +1,339 @@
+// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+
+
+#ifndef __HID_DEVICE_LE_PRF__
+#define __HID_DEVICE_LE_PRF__
+#include "esp_gatts_api.h"
+#include "esp_gatt_defs.h"
+#include "esp_hidd_prf_api.h"
+#include "esp_gap_ble_api.h"
+#include "hid_dev.h"
+
+
+/// Maximal number of HIDS that can be added in the DB
+#ifndef USE_ONE_HIDS_INSTANCE
+#define HIDD_LE_NB_HIDS_INST_MAX              (2)
+#else
+#define HIDD_LE_NB_HIDS_INST_MAX              (1)
+#endif
+
+#define HIDD_GREAT_VER   0x01  //Version + Subversion
+#define HIDD_SUB_VER     0x00  //Version + Subversion
+#define HIDD_VERSION     ((HIDD_GREAT_VER<<8)|HIDD_SUB_VER)  //Version + Subversion
+
+#define HID_MAX_APPS                 1
+
+// Number of HID reports defined in the service
+#define HID_NUM_REPORTS          9
+
+// HID Report IDs for the service
+#define HID_RPT_ID_MOUSE_IN      1   // Mouse input report ID
+#define HID_RPT_ID_KEY_IN        2   // Keyboard input report ID
+#define HID_RPT_ID_CC_IN         3   //Consumer Control input report ID
+#define HID_RPT_ID_VENDOR_OUT    4   // Vendor output report ID
+#define HID_RPT_ID_LED_OUT       0  // LED output report ID
+#define HID_RPT_ID_FEATURE       0  // Feature report ID
+
+#define HIDD_APP_ID                    0x1812//ATT_SVC_HID
+
+#define BATTRAY_APP_ID       0x180f
+
+
+#define ATT_SVC_HID          0x1812
+
+/// Maximal number of Report Char. that can be added in the DB for one HIDS - Up to 11
+#define HIDD_LE_NB_REPORT_INST_MAX            (5)
+
+/// Maximal length of Report Char. Value
+#define HIDD_LE_REPORT_MAX_LEN                (255)
+/// Maximal length of Report Map Char. Value
+#define HIDD_LE_REPORT_MAP_MAX_LEN            (512)
+
+/// Length of Boot Report Char. Value Maximal Length
+#define HIDD_LE_BOOT_REPORT_MAX_LEN           (8)
+
+/// Boot KB Input Report Notification Configuration Bit Mask
+#define HIDD_LE_BOOT_KB_IN_NTF_CFG_MASK       (0x40)
+/// Boot KB Input Report Notification Configuration Bit Mask
+#define HIDD_LE_BOOT_MOUSE_IN_NTF_CFG_MASK    (0x80)
+/// Boot Report Notification Configuration Bit Mask
+#define HIDD_LE_REPORT_NTF_CFG_MASK           (0x20)
+
+
+/* HID information flags */
+#define HID_FLAGS_REMOTE_WAKE           0x01      // RemoteWake
+#define HID_FLAGS_NORMALLY_CONNECTABLE  0x02      // NormallyConnectable
+
+/* Control point commands */
+#define HID_CMD_SUSPEND                 0x00      // Suspend
+#define HID_CMD_EXIT_SUSPEND            0x01      // Exit Suspend
+
+/* HID protocol mode values */
+#define HID_PROTOCOL_MODE_BOOT          0x00      // Boot Protocol Mode
+#define HID_PROTOCOL_MODE_REPORT        0x01      // Report Protocol Mode
+
+/* Attribute value lengths */
+#define HID_PROTOCOL_MODE_LEN           1         // HID Protocol Mode
+#define HID_INFORMATION_LEN             4         // HID Information
+#define HID_REPORT_REF_LEN              2         // HID Report Reference Descriptor
+#define HID_EXT_REPORT_REF_LEN          2         // External Report Reference Descriptor
+
+// HID feature flags
+#define HID_KBD_FLAGS             HID_FLAGS_REMOTE_WAKE
+
+/* HID Report type */
+#define HID_REPORT_TYPE_INPUT       1
+#define HID_REPORT_TYPE_OUTPUT      2
+#define HID_REPORT_TYPE_FEATURE     3
+
+
+/// HID Service Attributes Indexes
+enum {
+    HIDD_LE_IDX_SVC,
+
+    // Included Service
+    HIDD_LE_IDX_INCL_SVC,
+
+    // HID Information
+    HIDD_LE_IDX_HID_INFO_CHAR,
+    HIDD_LE_IDX_HID_INFO_VAL,
+
+    // HID Control Point
+    HIDD_LE_IDX_HID_CTNL_PT_CHAR,
+    HIDD_LE_IDX_HID_CTNL_PT_VAL,
+
+    // Report Map
+    HIDD_LE_IDX_REPORT_MAP_CHAR,
+    HIDD_LE_IDX_REPORT_MAP_VAL,
+    HIDD_LE_IDX_REPORT_MAP_EXT_REP_REF,
+
+    // Protocol Mode
+    HIDD_LE_IDX_PROTO_MODE_CHAR,
+    HIDD_LE_IDX_PROTO_MODE_VAL,
+
+    // Report mouse input
+    HIDD_LE_IDX_REPORT_MOUSE_IN_CHAR,
+    HIDD_LE_IDX_REPORT_MOUSE_IN_VAL,
+    HIDD_LE_IDX_REPORT_MOUSE_IN_CCC,
+    HIDD_LE_IDX_REPORT_MOUSE_REP_REF,
+    //Report Key input
+    HIDD_LE_IDX_REPORT_KEY_IN_CHAR,
+    HIDD_LE_IDX_REPORT_KEY_IN_VAL,
+    HIDD_LE_IDX_REPORT_KEY_IN_CCC,
+    HIDD_LE_IDX_REPORT_KEY_IN_REP_REF,
+    ///Report Led output
+    HIDD_LE_IDX_REPORT_LED_OUT_CHAR,
+    HIDD_LE_IDX_REPORT_LED_OUT_VAL,
+    HIDD_LE_IDX_REPORT_LED_OUT_REP_REF,
+
+    /// Report Vendor
+    HIDD_LE_IDX_REPORT_VENDOR_OUT_CHAR,
+    HIDD_LE_IDX_REPORT_VENDOR_OUT_VAL,
+    HIDD_LE_IDX_REPORT_VENDOR_OUT_REP_REF,
+
+    HIDD_LE_IDX_REPORT_CC_IN_CHAR,
+    HIDD_LE_IDX_REPORT_CC_IN_VAL,
+    HIDD_LE_IDX_REPORT_CC_IN_CCC,
+    HIDD_LE_IDX_REPORT_CC_IN_REP_REF,
+    
+    // Boot Keyboard Input Report
+    HIDD_LE_IDX_BOOT_KB_IN_REPORT_CHAR,
+    HIDD_LE_IDX_BOOT_KB_IN_REPORT_VAL,
+    HIDD_LE_IDX_BOOT_KB_IN_REPORT_NTF_CFG,
+
+    // Boot Keyboard Output Report
+    HIDD_LE_IDX_BOOT_KB_OUT_REPORT_CHAR,
+    HIDD_LE_IDX_BOOT_KB_OUT_REPORT_VAL,
+
+    // Boot Mouse Input Report
+    HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_CHAR,
+    HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_VAL,
+    HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_NTF_CFG,
+
+    // Report
+    HIDD_LE_IDX_REPORT_CHAR,
+    HIDD_LE_IDX_REPORT_VAL,
+    HIDD_LE_IDX_REPORT_REP_REF,
+    //HIDD_LE_IDX_REPORT_NTF_CFG,
+
+    HIDD_LE_IDX_NB,
+};
+
+
+/// Attribute Table Indexes
+enum {
+    HIDD_LE_INFO_CHAR,
+    HIDD_LE_CTNL_PT_CHAR,
+    HIDD_LE_REPORT_MAP_CHAR,
+    HIDD_LE_REPORT_CHAR,
+    HIDD_LE_PROTO_MODE_CHAR,
+    HIDD_LE_BOOT_KB_IN_REPORT_CHAR,
+    HIDD_LE_BOOT_KB_OUT_REPORT_CHAR,
+    HIDD_LE_BOOT_MOUSE_IN_REPORT_CHAR,
+    HIDD_LE_CHAR_MAX //= HIDD_LE_REPORT_CHAR + HIDD_LE_NB_REPORT_INST_MAX,
+};
+
+///att read event table Indexs
+enum {
+    HIDD_LE_READ_INFO_EVT,
+    HIDD_LE_READ_CTNL_PT_EVT,
+    HIDD_LE_READ_REPORT_MAP_EVT,
+    HIDD_LE_READ_REPORT_EVT,
+    HIDD_LE_READ_PROTO_MODE_EVT,
+    HIDD_LE_BOOT_KB_IN_REPORT_EVT,
+    HIDD_LE_BOOT_KB_OUT_REPORT_EVT,
+    HIDD_LE_BOOT_MOUSE_IN_REPORT_EVT,
+
+    HID_LE_EVT_MAX
+};
+
+/// Client Characteristic Configuration Codes
+enum {
+    HIDD_LE_DESC_MASK = 0x10,
+
+    HIDD_LE_BOOT_KB_IN_REPORT_CFG     = HIDD_LE_BOOT_KB_IN_REPORT_CHAR | HIDD_LE_DESC_MASK,
+    HIDD_LE_BOOT_MOUSE_IN_REPORT_CFG  = HIDD_LE_BOOT_MOUSE_IN_REPORT_CHAR | HIDD_LE_DESC_MASK,
+    HIDD_LE_REPORT_CFG                = HIDD_LE_REPORT_CHAR | HIDD_LE_DESC_MASK,
+};
+
+/// Features Flag Values
+enum {
+    HIDD_LE_CFG_KEYBOARD      = 0x01,
+    HIDD_LE_CFG_MOUSE         = 0x02,
+    HIDD_LE_CFG_PROTO_MODE    = 0x04,
+    HIDD_LE_CFG_MAP_EXT_REF   = 0x08,
+    HIDD_LE_CFG_BOOT_KB_WR    = 0x10,
+    HIDD_LE_CFG_BOOT_MOUSE_WR = 0x20,
+};
+
+/// Report Char. Configuration Flag Values
+enum {
+    HIDD_LE_CFG_REPORT_IN     = 0x01,
+    HIDD_LE_CFG_REPORT_OUT    = 0x02,
+    //HOGPD_CFG_REPORT_FEAT can be used as a mask to check Report type
+    HIDD_LE_CFG_REPORT_FEAT   = 0x03,
+    HIDD_LE_CFG_REPORT_WR     = 0x10,
+};
+
+/// Pointer to the connection clean-up function
+#define HIDD_LE_CLEANUP_FNCT        (NULL)
+
+/*
+ * TYPE DEFINITIONS
+ ****************************************************************************************
+ */
+
+/// HIDD Features structure
+typedef struct {
+    /// Service Features
+    uint8_t svc_features;
+    /// Number of Report Char. instances to add in the database
+    uint8_t report_nb;
+    /// Report Char. Configuration
+    uint8_t report_char_cfg[HIDD_LE_NB_REPORT_INST_MAX];
+} hidd_feature_t;
+
+
+typedef struct {
+    bool                        in_use;
+    bool                        congest;
+    uint16_t                  conn_id;
+    bool                        connected;
+    esp_bd_addr_t         remote_bda;
+    uint32_t                  trans_id;
+    uint8_t                    cur_srvc_id;
+
+} hidd_clcb_t;
+
+// HID report mapping table
+typedef struct {
+    uint16_t    handle;           // Handle of report characteristic
+    uint16_t    cccdHandle;       // Handle of CCCD for report characteristic
+    uint8_t     id;               // Report ID
+    uint8_t     type;             // Report type
+    uint8_t     mode;             // Protocol mode (report or boot)
+} hidRptMap_t;
+
+
+typedef struct {
+    /// hidd profile id
+    uint8_t app_id;
+    /// Notified handle
+    uint16_t ntf_handle;
+    ///Attribute handle Table
+    uint16_t att_tbl[HIDD_LE_IDX_NB];
+    /// Supported Features
+    hidd_feature_t   hidd_feature[HIDD_LE_NB_HIDS_INST_MAX];
+    /// Current Protocol Mode
+    uint8_t proto_mode[HIDD_LE_NB_HIDS_INST_MAX];
+    /// Number of HIDS added in the database
+    uint8_t hids_nb;
+    uint8_t pending_evt;
+    uint16_t pending_hal;
+} hidd_inst_t;
+
+/// Report Reference structure
+typedef struct
+{
+    ///Report ID
+    uint8_t report_id;
+    ///Report Type
+    uint8_t report_type;
+}hids_report_ref_t;
+
+/// HID Information structure
+typedef struct
+{
+    /// bcdHID
+    uint16_t bcdHID;
+    /// bCountryCode
+    uint8_t bCountryCode;
+    /// Flags
+    uint8_t flags;
+}hids_hid_info_t;
+
+
+/* service engine control block */
+typedef struct {
+    hidd_clcb_t                  hidd_clcb[HID_MAX_APPS];          /* connection link*/
+    esp_gatt_if_t                gatt_if;
+    bool                         enabled;
+    bool                         is_take;
+    bool                         is_primery;
+    hidd_inst_t                  hidd_inst;
+    esp_hidd_event_cb_t          hidd_cb;
+    uint8_t                      inst_id;
+} hidd_le_env_t;
+
+extern hidd_le_env_t hidd_le_env;
+extern uint8_t hidProtocolMode;
+
+
+void hidd_clcb_alloc (uint16_t conn_id, esp_bd_addr_t bda);
+
+bool hidd_clcb_dealloc (uint16_t conn_id);
+
+void hidd_le_create_service(esp_gatt_if_t gatts_if);
+
+void hidd_set_attr_value(uint16_t handle, uint16_t val_len, const uint8_t *value);
+
+void hidd_get_attr_value(uint16_t handle, uint16_t *length, uint8_t **value);
+
+esp_err_t hidd_register_cb(void);
+
+
+#endif  ///__HID_DEVICE_LE_PRF__
+
diff --git a/examples/bluetooth/ble_hid_device_demo/sdkconfig.defaults b/examples/bluetooth/ble_hid_device_demo/sdkconfig.defaults
new file mode 100644 (file)
index 0000000..14f5546
--- /dev/null
@@ -0,0 +1,3 @@
+# Override some defaults so BT stack is enabled
+# by default in this example
+CONFIG_BT_ENABLED=y