a3b5a23b87
This change adds a check for compatibility between the nvs version found on nvs flash and the one assumed by running code during nvs initialization. Any mismatch is reported to the user using new error code ESP_ERR_NVS_NEW_VERSION_FOUND.
328 lines
11 KiB
C
328 lines
11 KiB
C
/* 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 "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 HID_DEMO_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(HID_DEMO_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: {
|
|
ESP_LOGI(HID_DEMO_TAG, "ESP_HIDD_EVENT_BLE_CONNECT");
|
|
hid_conn_id = param->connect.conn_id;
|
|
break;
|
|
}
|
|
case ESP_HIDD_EVENT_BLE_DISCONNECT: {
|
|
sec_conn = false;
|
|
ESP_LOGI(HID_DEMO_TAG, "ESP_HIDD_EVENT_BLE_DISCONNECT");
|
|
esp_ble_gap_start_advertising(&hidd_adv_params);
|
|
break;
|
|
}
|
|
case ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT: {
|
|
ESP_LOGI(HID_DEMO_TAG, "%s, ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT", __func__);
|
|
ESP_LOG_BUFFER_HEX(HID_DEMO_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++) {
|
|
ESP_LOGD(HID_DEMO_TAG, "%x:",param->ble_security.ble_req.bd_addr[i]);
|
|
}
|
|
esp_ble_gap_security_rsp(param->ble_security.ble_req.bd_addr, true);
|
|
break;
|
|
case ESP_GAP_BLE_AUTH_CMPL_EVT:
|
|
sec_conn = true;
|
|
esp_bd_addr_t bd_addr;
|
|
memcpy(bd_addr, param->ble_security.auth_cmpl.bd_addr, sizeof(esp_bd_addr_t));
|
|
ESP_LOGI(HID_DEMO_TAG, "remote BD_ADDR: %08x%04x",\
|
|
(bd_addr[0] << 24) + (bd_addr[1] << 16) + (bd_addr[2] << 8) + bd_addr[3],
|
|
(bd_addr[4] << 8) + bd_addr[5]);
|
|
ESP_LOGI(HID_DEMO_TAG, "address type = %d", param->ble_security.auth_cmpl.addr_type);
|
|
ESP_LOGI(HID_DEMO_TAG, "pair status = %s",param->ble_security.auth_cmpl.success ? "success" : "fail");
|
|
if(!param->ble_security.auth_cmpl.success) {
|
|
ESP_LOGE(HID_DEMO_TAG, "fail reason = 0x%x",param->ble_security.auth_cmpl.fail_reason);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void hid_demo_task(void *pvParameters)
|
|
{
|
|
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
|
while(1) {
|
|
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
|
if (sec_conn) {
|
|
ESP_LOGI(HID_DEMO_TAG, "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);
|
|
vTaskDelay(3000 / portTICK_PERIOD_MS);
|
|
esp_hidd_send_consumer_value(hid_conn_id, HID_CONSUMER_VOLUME_DOWN, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void app_main()
|
|
{
|
|
esp_err_t ret;
|
|
|
|
// Initialize NVS.
|
|
ret = nvs_flash_init();
|
|
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
|
ESP_ERROR_CHECK(nvs_flash_erase());
|
|
ret = nvs_flash_init();
|
|
}
|
|
ESP_ERROR_CHECK( ret );
|
|
|
|
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
|
ret = esp_bt_controller_init(&bt_cfg);
|
|
if (ret) {
|
|
ESP_LOGE(HID_DEMO_TAG, "%s initialize controller failed\n", __func__);
|
|
return;
|
|
}
|
|
|
|
ret = esp_bt_controller_enable(ESP_BT_MODE_BTDM);
|
|
if (ret) {
|
|
ESP_LOGE(HID_DEMO_TAG, "%s enable controller failed\n", __func__);
|
|
return;
|
|
}
|
|
|
|
ret = esp_bluedroid_init();
|
|
if (ret) {
|
|
ESP_LOGE(HID_DEMO_TAG, "%s init bluedroid failed\n", __func__);
|
|
return;
|
|
}
|
|
|
|
ret = esp_bluedroid_enable();
|
|
if (ret) {
|
|
ESP_LOGE(HID_DEMO_TAG, "%s init bluedroid failed\n", __func__);
|
|
return;
|
|
}
|
|
|
|
if((ret = esp_hidd_profile_init()) != ESP_OK) {
|
|
ESP_LOGE(HID_DEMO_TAG, "%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);
|
|
|
|
}
|
|
|