kopia lustrzana https://github.com/espressif/esp-idf
423 wiersze
15 KiB
C
423 wiersze
15 KiB
C
/*
|
|
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include "osi/allocator.h"
|
|
#include "btc/btc_task.h"
|
|
#include "btc/btc_manage.h"
|
|
#include "blufi_int.h"
|
|
#include "btc_blufi_prf.h"
|
|
#include "esp_log.h"
|
|
#include "esp_blufi_api.h"
|
|
|
|
#include "common/bt_target.h"
|
|
#include "common/bt_trace.h"
|
|
#include "stack/bt_types.h"
|
|
#include "stack/gatt_api.h"
|
|
#include "bta/bta_api.h"
|
|
#include "bta/bta_gatt_api.h"
|
|
#include "bta_gatts_int.h"
|
|
#include "btc_gatt_util.h"
|
|
#include "btc_gatts.h"
|
|
|
|
#include "esp_bt_defs.h"
|
|
#include "esp_gap_ble_api.h"
|
|
#include "esp_gatt_common_api.h"
|
|
#include "esp_bt_main.h"
|
|
#include "esp_bt_device.h"
|
|
#include "esp_err.h"
|
|
#include "esp_blufi.h"
|
|
|
|
#if (BLUFI_INCLUDED == TRUE)
|
|
|
|
static uint8_t server_if;
|
|
static uint16_t conn_id;
|
|
static uint8_t blufi_service_uuid128[32] = {
|
|
/* LSB <--------------------------------------------------------------------------------> MSB */
|
|
//first uuid, 16bit, [12],[13] is the value
|
|
0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
|
|
};
|
|
|
|
static esp_ble_adv_data_t blufi_adv_data = {
|
|
.set_scan_rsp = false,
|
|
.include_name = true,
|
|
.include_txpower = true,
|
|
.min_interval = 0x0006, //slave connection min interval, Time = min_interval * 1.25 msec
|
|
.max_interval = 0x0010, //slave connection max interval, Time = max_interval * 1.25 msec
|
|
.appearance = 0x00,
|
|
.manufacturer_len = 0,
|
|
.p_manufacturer_data = NULL,
|
|
.service_data_len = 0,
|
|
.p_service_data = NULL,
|
|
.service_uuid_len = 16,
|
|
.p_service_uuid = blufi_service_uuid128,
|
|
.flag = 0x6,
|
|
};
|
|
|
|
static esp_ble_adv_params_t blufi_adv_params = {
|
|
.adv_int_min = 0x100,
|
|
.adv_int_max = 0x100,
|
|
.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 esp_blufi_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(&blufi_adv_params);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// static functions declare
|
|
static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data);
|
|
|
|
void blufi_create_service(void)
|
|
{
|
|
if (!blufi_env.enabled) {
|
|
BTC_TRACE_ERROR("blufi service added error.");
|
|
return;
|
|
}
|
|
|
|
blufi_env.srvc_inst = 0x00;
|
|
BTA_GATTS_CreateService(blufi_env.gatt_if, &blufi_srvc_uuid, blufi_env.srvc_inst, BLUFI_HDL_NUM, true);
|
|
}
|
|
|
|
uint8_t esp_blufi_init(void)
|
|
{
|
|
|
|
/* register the BLUFI profile to the BTA_GATTS module*/
|
|
BTA_GATTS_AppRegister(&blufi_app_uuid, blufi_profile_cb);
|
|
return GATT_SUCCESS;
|
|
}
|
|
|
|
static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
|
|
{
|
|
tBTA_GATTS_RSP rsp;
|
|
BLUFI_TRACE_DEBUG("blufi profile cb event = %x\n", event);
|
|
|
|
switch (event) {
|
|
case BTA_GATTS_REG_EVT:
|
|
BLUFI_TRACE_DEBUG("REG: status %d, app_uuid %04x, gatt_if %d\n", p_data->reg_oper.status, p_data->reg_oper.uuid.uu.uuid16, p_data->reg_oper.server_if);
|
|
|
|
if (p_data->reg_oper.status != BTA_GATT_OK) {
|
|
BLUFI_TRACE_ERROR("BLUFI profile register failed\n");
|
|
return;
|
|
}
|
|
|
|
blufi_env.gatt_if = p_data->reg_oper.server_if;
|
|
blufi_env.enabled = true;
|
|
|
|
//create the blufi service to the service data base.
|
|
if (p_data->reg_oper.uuid.uu.uuid16 == BLUFI_APP_UUID) {
|
|
BLUFI_TRACE_DEBUG("%s %d\n", __func__, __LINE__);
|
|
blufi_create_service();
|
|
}
|
|
break;
|
|
case BTA_GATTS_DEREG_EVT: {
|
|
esp_blufi_cb_param_t param;
|
|
btc_msg_t msg;
|
|
|
|
BLUFI_TRACE_DEBUG("DEREG: status %d, gatt_if %d\n", p_data->reg_oper.status, p_data->reg_oper.server_if);
|
|
|
|
if (p_data->reg_oper.status != BTA_GATT_OK) {
|
|
BLUFI_TRACE_ERROR("BLUFI profile unregister failed\n");
|
|
return;
|
|
}
|
|
|
|
blufi_env.enabled = false;
|
|
|
|
msg.sig = BTC_SIG_API_CB;
|
|
msg.pid = BTC_PID_BLUFI;
|
|
msg.act = ESP_BLUFI_EVENT_DEINIT_FINISH;
|
|
param.deinit_finish.state = ESP_BLUFI_DEINIT_OK;
|
|
|
|
btc_transfer_context(&msg, ¶m, sizeof(esp_blufi_cb_param_t), NULL, NULL);
|
|
|
|
break;
|
|
}
|
|
case BTA_GATTS_READ_EVT:
|
|
memset(&rsp, 0, sizeof(tBTA_GATTS_API_RSP));
|
|
rsp.attr_value.handle = p_data->req_data.p_data->read_req.handle;
|
|
rsp.attr_value.len = 1;
|
|
rsp.attr_value.value[0] = 0x00;
|
|
BTA_GATTS_SendRsp(p_data->req_data.conn_id, p_data->req_data.trans_id,
|
|
p_data->req_data.status, &rsp);
|
|
break;
|
|
case BTA_GATTS_WRITE_EVT: {
|
|
if (p_data->req_data.p_data->write_req.is_prep) {
|
|
tBTA_GATT_STATUS status = GATT_SUCCESS;
|
|
|
|
if (blufi_env.prepare_buf == NULL) {
|
|
blufi_env.prepare_buf = osi_malloc(BLUFI_PREPAIR_BUF_MAX_SIZE);
|
|
blufi_env.prepare_len = 0;
|
|
if (blufi_env.prepare_buf == NULL) {
|
|
BLUFI_TRACE_ERROR("Blufi prep no mem\n");
|
|
status = GATT_NO_RESOURCES;
|
|
}
|
|
} else {
|
|
if (p_data->req_data.p_data->write_req.offset > BLUFI_PREPAIR_BUF_MAX_SIZE) {
|
|
status = GATT_INVALID_OFFSET;
|
|
} else if ((p_data->req_data.p_data->write_req.offset + p_data->req_data.p_data->write_req.len) > BLUFI_PREPAIR_BUF_MAX_SIZE) {
|
|
status = GATT_INVALID_ATTR_LEN;
|
|
}
|
|
}
|
|
|
|
memset(&rsp, 0, sizeof(tGATTS_RSP));
|
|
rsp.attr_value.handle = p_data->req_data.p_data->write_req.handle;
|
|
rsp.attr_value.len = p_data->req_data.p_data->write_req.len;
|
|
rsp.attr_value.offset = p_data->req_data.p_data->write_req.offset;
|
|
memcpy(rsp.attr_value.value, p_data->req_data.p_data->write_req.value, p_data->req_data.p_data->write_req.len);
|
|
|
|
BLUFI_TRACE_DEBUG("prep write, len=%d, offset=%d\n", p_data->req_data.p_data->write_req.len, p_data->req_data.p_data->write_req.offset);
|
|
|
|
BTA_GATTS_SendRsp(p_data->req_data.conn_id, p_data->req_data.trans_id,
|
|
status, &rsp);
|
|
|
|
if (status != GATT_SUCCESS) {
|
|
if (blufi_env.prepare_buf) {
|
|
osi_free(blufi_env.prepare_buf);
|
|
blufi_env.prepare_buf = NULL;
|
|
blufi_env.prepare_len = 0;
|
|
}
|
|
BLUFI_TRACE_ERROR("write data error , error code 0x%x\n", status);
|
|
return;
|
|
}
|
|
memcpy(blufi_env.prepare_buf + p_data->req_data.p_data->write_req.offset,
|
|
p_data->req_data.p_data->write_req.value,
|
|
p_data->req_data.p_data->write_req.len);
|
|
blufi_env.prepare_len += p_data->req_data.p_data->write_req.len;
|
|
|
|
return;
|
|
} else {
|
|
BLUFI_TRACE_DEBUG("norm write, len=%d, offset=%d\n", p_data->req_data.p_data->write_req.len, p_data->req_data.p_data->write_req.offset);
|
|
BTA_GATTS_SendRsp(p_data->req_data.conn_id, p_data->req_data.trans_id,
|
|
p_data->req_data.status, NULL);
|
|
}
|
|
|
|
if (p_data->req_data.p_data->write_req.handle == blufi_env.handle_char_p2e) {
|
|
btc_blufi_recv_handler(&p_data->req_data.p_data->write_req.value[0],
|
|
p_data->req_data.p_data->write_req.len);
|
|
}
|
|
break;
|
|
}
|
|
case BTA_GATTS_EXEC_WRITE_EVT:
|
|
BLUFI_TRACE_DEBUG("exec write exec %d\n", p_data->req_data.p_data->exec_write);
|
|
|
|
BTA_GATTS_SendRsp(p_data->req_data.conn_id, p_data->req_data.trans_id,
|
|
GATT_SUCCESS, NULL);
|
|
|
|
if (blufi_env.prepare_buf && p_data->req_data.p_data->exec_write == GATT_PREP_WRITE_EXEC) {
|
|
btc_blufi_recv_handler(blufi_env.prepare_buf, blufi_env.prepare_len);
|
|
}
|
|
|
|
if (blufi_env.prepare_buf) {
|
|
osi_free(blufi_env.prepare_buf);
|
|
blufi_env.prepare_buf = NULL;
|
|
blufi_env.prepare_len = 0;
|
|
}
|
|
|
|
break;
|
|
case BTA_GATTS_MTU_EVT:
|
|
BLUFI_TRACE_DEBUG("MTU size %d\n", p_data->req_data.p_data->mtu);
|
|
blufi_env.frag_size = (p_data->req_data.p_data->mtu < BLUFI_MAX_DATA_LEN ? p_data->req_data.p_data->mtu : BLUFI_MAX_DATA_LEN) - BLUFI_MTU_RESERVED_SIZE;
|
|
break;
|
|
case BTA_GATTS_CONF_EVT:
|
|
BLUFI_TRACE_DEBUG("CONFIRM EVT\n");
|
|
/* Nothing */
|
|
break;
|
|
case BTA_GATTS_CREATE_EVT:
|
|
blufi_env.handle_srvc = p_data->create.service_id;
|
|
|
|
//add the first blufi characteristic --> write characteristic
|
|
BTA_GATTS_AddCharacteristic(blufi_env.handle_srvc, &blufi_char_uuid_p2e,
|
|
(GATT_PERM_WRITE),
|
|
(GATT_CHAR_PROP_BIT_WRITE),
|
|
NULL, NULL);
|
|
break;
|
|
case BTA_GATTS_ADD_CHAR_EVT:
|
|
switch (p_data->add_result.char_uuid.uu.uuid16) {
|
|
case BLUFI_CHAR_P2E_UUID: /* Phone to ESP32 */
|
|
blufi_env.handle_char_p2e = p_data->add_result.attr_id;
|
|
|
|
BTA_GATTS_AddCharacteristic(blufi_env.handle_srvc, &blufi_char_uuid_e2p,
|
|
(GATT_PERM_READ),
|
|
(GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY),
|
|
NULL, NULL);
|
|
break;
|
|
case BLUFI_CHAR_E2P_UUID: /* ESP32 to Phone */
|
|
blufi_env.handle_char_e2p = p_data->add_result.attr_id;
|
|
|
|
BTA_GATTS_AddCharDescriptor (blufi_env.handle_srvc,
|
|
(GATT_PERM_READ | GATT_PERM_WRITE),
|
|
&blufi_descr_uuid_e2p,
|
|
NULL, NULL);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case BTA_GATTS_ADD_CHAR_DESCR_EVT: {
|
|
/* call init finish */
|
|
esp_blufi_cb_param_t param;
|
|
btc_msg_t msg;
|
|
|
|
blufi_env.handle_descr_e2p = p_data->add_result.attr_id;
|
|
//start the blufi service after created
|
|
BTA_GATTS_StartService(blufi_env.handle_srvc, BTA_GATT_TRANSPORT_LE);
|
|
|
|
msg.sig = BTC_SIG_API_CB;
|
|
msg.pid = BTC_PID_BLUFI;
|
|
msg.act = ESP_BLUFI_EVENT_INIT_FINISH;
|
|
param.init_finish.state = ESP_BLUFI_INIT_OK;
|
|
|
|
btc_transfer_context(&msg, ¶m, sizeof(esp_blufi_cb_param_t), NULL, NULL);
|
|
break;
|
|
}
|
|
case BTA_GATTS_CONNECT_EVT: {
|
|
btc_msg_t msg;
|
|
esp_blufi_cb_param_t param;
|
|
|
|
//set the connection flag to true
|
|
BLUFI_TRACE_API("\ndevice is connected "BT_BD_ADDR_STR", server_if=%d,reason=0x%x,connect_id=%d\n",
|
|
BT_BD_ADDR_HEX(p_data->conn.remote_bda), p_data->conn.server_if,
|
|
p_data->conn.reason, p_data->conn.conn_id);
|
|
|
|
memcpy(blufi_env.remote_bda, p_data->conn.remote_bda, ESP_BLUFI_BD_ADDR_LEN);
|
|
blufi_env.conn_id = p_data->conn.conn_id;
|
|
blufi_env.is_connected = true;
|
|
blufi_env.recv_seq = blufi_env.send_seq = 0;
|
|
|
|
msg.sig = BTC_SIG_API_CB;
|
|
msg.pid = BTC_PID_BLUFI;
|
|
msg.act = ESP_BLUFI_EVENT_BLE_CONNECT;
|
|
memcpy(param.connect.remote_bda, p_data->conn.remote_bda, ESP_BLUFI_BD_ADDR_LEN);
|
|
param.connect.conn_id = BTC_GATT_GET_CONN_ID(p_data->conn.conn_id);
|
|
conn_id = param.connect.conn_id;
|
|
server_if = p_data->conn.server_if;
|
|
btc_transfer_context(&msg, ¶m, sizeof(esp_blufi_cb_param_t), NULL, NULL);
|
|
break;
|
|
}
|
|
case BTA_GATTS_DISCONNECT_EVT: {
|
|
btc_msg_t msg;
|
|
esp_blufi_cb_param_t param;
|
|
|
|
blufi_env.is_connected = false;
|
|
//set the connection flag to true
|
|
BLUFI_TRACE_API("\ndevice is disconnected "BT_BD_ADDR_STR", server_if=%d,reason=0x%x,connect_id=%d\n",
|
|
BT_BD_ADDR_HEX(p_data->conn.remote_bda), p_data->conn.server_if,
|
|
p_data->conn.reason, p_data->conn.conn_id);
|
|
|
|
memcpy(blufi_env.remote_bda, p_data->conn.remote_bda, ESP_BLUFI_BD_ADDR_LEN);
|
|
blufi_env.conn_id = p_data->conn.conn_id;
|
|
blufi_env.recv_seq = blufi_env.send_seq = 0;
|
|
blufi_env.sec_mode = 0x0;
|
|
blufi_env.offset = 0;
|
|
|
|
if (blufi_env.aggr_buf != NULL) {
|
|
osi_free(blufi_env.aggr_buf);
|
|
blufi_env.aggr_buf = NULL;
|
|
}
|
|
|
|
msg.sig = BTC_SIG_API_CB;
|
|
msg.pid = BTC_PID_BLUFI;
|
|
msg.act = ESP_BLUFI_EVENT_BLE_DISCONNECT;
|
|
memcpy(param.disconnect.remote_bda, p_data->conn.remote_bda, ESP_BLUFI_BD_ADDR_LEN);
|
|
btc_transfer_context(&msg, ¶m, sizeof(esp_blufi_cb_param_t), NULL, NULL);
|
|
break;
|
|
}
|
|
case BTA_GATTS_OPEN_EVT:
|
|
break;
|
|
case BTA_GATTS_CLOSE_EVT:
|
|
break;
|
|
case BTA_GATTS_CONGEST_EVT:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void esp_blufi_send_notify(void *arg)
|
|
{
|
|
struct pkt_info *pkts = (struct pkt_info *) arg;
|
|
uint16_t conn_id = blufi_env.conn_id;
|
|
uint16_t attr_id = blufi_env.handle_char_e2p;
|
|
bool rsp = false;
|
|
BTA_GATTS_HandleValueIndication(conn_id, attr_id, pkts->pkt_len,
|
|
pkts->pkt, rsp);
|
|
|
|
}
|
|
|
|
void esp_blufi_deinit(void)
|
|
{
|
|
BTA_GATTS_StopService(blufi_env.handle_srvc);
|
|
BTA_GATTS_DeleteService(blufi_env.handle_srvc);
|
|
/* register the BLUFI profile to the BTA_GATTS module*/
|
|
BTA_GATTS_AppDeregister(blufi_env.gatt_if);
|
|
}
|
|
|
|
void esp_blufi_adv_start(void)
|
|
{
|
|
esp_ble_gap_set_device_name(BLUFI_DEVICE_NAME);
|
|
esp_ble_gap_config_adv_data(&blufi_adv_data);
|
|
}
|
|
|
|
void esp_blufi_adv_stop(void)
|
|
{
|
|
esp_ble_gap_stop_advertising();
|
|
}
|
|
|
|
void esp_blufi_send_encap(void *arg)
|
|
{
|
|
struct blufi_hdr *hdr = (struct blufi_hdr *)arg;
|
|
retry:
|
|
if (blufi_env.is_connected == false) {
|
|
BTC_TRACE_WARNING("%s ble connection is broken\n", __func__);
|
|
return;
|
|
}
|
|
if (esp_ble_get_cur_sendable_packets_num(BTC_GATT_GET_CONN_ID(blufi_env.conn_id)) > 0) {
|
|
btc_blufi_send_notify((uint8_t *)hdr,
|
|
((hdr->fc & BLUFI_FC_CHECK) ?
|
|
hdr->data_len + sizeof(struct blufi_hdr) + 2 :
|
|
hdr->data_len + sizeof(struct blufi_hdr)));
|
|
} else {
|
|
BTC_TRACE_WARNING("%s wait to send blufi custom data\n", __func__);
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
goto retry;
|
|
}
|
|
}
|
|
|
|
esp_err_t esp_blufi_close(esp_gatt_if_t gatts_if, uint16_t conn_id)
|
|
{
|
|
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
|
|
btc_msg_t msg;
|
|
btc_ble_gatts_args_t arg;
|
|
msg.sig = BTC_SIG_API_CALL;
|
|
msg.pid = BTC_PID_GATTS;
|
|
msg.act = BTC_GATTS_ACT_CLOSE;
|
|
arg.close.conn_id = BTC_GATT_CREATE_CONN_ID(gatts_if, conn_id);
|
|
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL, NULL)
|
|
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
|
}
|
|
|
|
void esp_blufi_disconnect()
|
|
{
|
|
int rc;
|
|
rc = esp_blufi_close(server_if, conn_id);
|
|
assert (rc == 0);
|
|
}
|
|
|
|
#endif
|