component bt:Added the create attribute table method to the new API

This commit is contained in:
Yulong 2016-12-23 11:28:47 -05:00 committed by Tian Hao
parent 0c01ef68f1
commit d512d6100c
37 changed files with 2360 additions and 671 deletions

View File

@ -22,6 +22,7 @@
#define COPY_TO_GATTS_ARGS(_gatt_args, _arg, _arg_type) memcpy(_gatt_args, _arg, sizeof(_arg_type))
esp_err_t esp_ble_gatts_register_callback(esp_gatts_cb_t callback)
{
if (esp_bluedroid_get_status() == ESP_BLUEDROID_STATUS_UNINITIALIZED) {
@ -90,6 +91,26 @@ esp_err_t esp_ble_gatts_create_service(esp_gatt_if_t gatts_if,
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_gatts_create_attr_tab(const esp_gatts_attr_db_t *gatts_attr_db,
esp_gatt_if_t gatts_if,
uint8_t max_nb_attr,
uint8_t srvc_inst_id)
{
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_CREATE_ATTR_TAB;
arg.create_attr_tab.gatts_if = gatts_if;
arg.create_attr_tab.max_nb_attr = max_nb_attr;
arg.create_attr_tab.srvc_inst_id = srvc_inst_id;
arg.create_attr_tab.gatts_attr_db = (esp_gatts_attr_db_t *)gatts_attr_db;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), btc_gatts_arg_deep_copy)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_gatts_add_included_service(uint16_t service_handle, uint16_t included_service_handle)
{
@ -111,7 +132,8 @@ esp_err_t esp_ble_gatts_add_included_service(uint16_t service_handle, uint16_t i
esp_err_t esp_ble_gatts_add_char(uint16_t service_handle, esp_bt_uuid_t *char_uuid,
esp_gatt_perm_t perm, esp_gatt_char_prop_t property)
esp_gatt_perm_t perm, esp_gatt_char_prop_t property, esp_attr_value_t *char_val,
esp_attr_control_t *control)
{
btc_msg_t msg;
btc_ble_gatts_args_t arg;
@ -120,21 +142,32 @@ esp_err_t esp_ble_gatts_add_char(uint16_t service_handle, esp_bt_uuid_t *char_
return ESP_ERR_INVALID_STATE;
}
memset(&arg, 0, sizeof(btc_ble_gatts_args_t));
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_GATTS;
msg.act = BTC_GATTS_ACT_ADD_CHAR;
arg.add_char.service_handle = service_handle;
arg.add_char.perm = perm;
arg.add_char.property = property;
if (char_val != NULL) {
arg.add_char.char_val.attr_max_len = char_val->attr_max_len;
arg.add_char.char_val.attr_len = char_val->attr_len;
arg.add_char.char_val.attr_value = char_val->attr_value;
}
if (control != NULL) {
arg.add_char.attr_control.auto_rsp = control->auto_rsp;
}
memcpy(&arg.add_char.char_uuid, char_uuid, sizeof(esp_bt_uuid_t));
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_gatts_add_char_descr (uint16_t service_handle,
esp_bt_uuid_t *descr_uuid,
esp_gatt_perm_t perm)
esp_gatt_perm_t perm, esp_attr_value_t *char_descr_val,
esp_attr_control_t *control)
{
btc_msg_t msg;
btc_ble_gatts_args_t arg;
@ -143,14 +176,25 @@ esp_err_t esp_ble_gatts_add_char_descr (uint16_t service_handle,
return ESP_ERR_INVALID_STATE;
}
memset(&arg, 0, sizeof(btc_ble_gatts_args_t));
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_GATTS;
msg.act = BTC_GATTS_ACT_ADD_CHAR_DESCR;
arg.add_descr.service_handle = service_handle;
arg.add_descr.perm = perm;
if (char_descr_val != NULL) {
arg.add_descr.descr_val.attr_max_len = char_descr_val->attr_max_len;
arg.add_descr.descr_val.attr_len = char_descr_val->attr_len;
arg.add_descr.descr_val.attr_value = char_descr_val->attr_value;
}
if (control != NULL) {
arg.add_descr.attr_control.auto_rsp = control->auto_rsp;
}
memcpy(&arg.add_descr.descr_uuid, descr_uuid, sizeof(esp_bt_uuid_t));
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_gatts_delete_service(uint16_t service_handle)
@ -224,7 +268,8 @@ esp_err_t esp_ble_gatts_send_indicate(esp_gatt_if_t gatts_if, uint16_t conn_id,
arg.send_ind.value_len = value_len;
arg.send_ind.value = value;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t),
btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_gatts_send_response(esp_gatt_if_t gatts_if, uint16_t conn_id, uint32_t trans_id,
@ -245,7 +290,32 @@ esp_err_t esp_ble_gatts_send_response(esp_gatt_if_t gatts_if, uint16_t conn_id,
arg.send_rsp.status = status;
arg.send_rsp.rsp = rsp;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t),
btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_gatts_set_attr_value(uint16_t attr_handle, uint16_t length, const uint8_t *value)
{
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_SET_ATTR_VALUE;
arg.set_attr_val.length = length;
arg.set_attr_val.value = (uint8_t *)value;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t),
btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_gatts_get_attr_value(uint16_t attr_handle, uint16_t *length, const uint8_t **value)
{
if (attr_handle == ESP_GATT_ILLEGAL_HANDLE) {
return ESP_FAIL;
}
btc_gatts_get_attr_value(attr_handle, length, (uint8_t **)value);
return ESP_OK;
}
esp_err_t esp_ble_gatts_open(esp_gatt_if_t gatts_if, esp_bd_addr_t remote_bda, bool is_direct)
@ -264,7 +334,8 @@ esp_err_t esp_ble_gatts_open(esp_gatt_if_t gatts_if, esp_bd_addr_t remote_bda, b
arg.open.is_direct = is_direct;
memcpy(&arg.open.remote_bda, remote_bda, sizeof(esp_bd_addr_t));
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_gatts_close(esp_gatt_if_t gatts_if, uint16_t conn_id)
@ -281,5 +352,6 @@ esp_err_t esp_ble_gatts_close(esp_gatt_if_t gatts_if, uint16_t conn_id)
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) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}

View File

@ -41,13 +41,15 @@ extern "C" {
/// GAP BLE callback event type
typedef enum {
ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT = 0, /*!< When advertising data set complete, the event comes */
ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT , /*!< When scan response data set complete, the event comes */
ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT, /*!< When scan response data set complete, the event comes */
ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT, /*!< When scan parameters set complete, the event comes */
ESP_GAP_BLE_SCAN_RESULT_EVT, /*!< When one scan result ready, the event comes each time */
} esp_gap_ble_cb_event_t;
/// Advertising data maximum length
#define ESP_BLE_ADV_DATA_LEN_MAX 31
/// Scan response data maximum length
#define ESP_BLE_SCAN_RSP_DATA_LEN_MAX 31
/// The type of advertising data(not adv_type)
typedef enum {
@ -264,7 +266,7 @@ typedef union {
esp_ble_addr_type_t ble_addr_type; /*!< Ble device address type */
esp_ble_evt_type_t ble_evt_type; /*!< Ble scan result event type */
int rssi; /*!< Searched device's RSSI */
uint8_t ble_adv[ESP_BLE_ADV_DATA_LEN_MAX]; /*!< Received EIR */
uint8_t ble_adv[ESP_BLE_ADV_DATA_LEN_MAX + ESP_BLE_SCAN_RSP_DATA_LEN_MAX]; /*!< Received EIR */
int flag; /*!< Advertising data flag bit */
int num_resps; /*!< Scan result number */
} scan_rst; /*!< Event parameter of ESP_GAP_BLE_SCAN_RESULT_EVT */
@ -440,7 +442,8 @@ esp_err_t esp_ble_gap_set_device_name(const char *name);
* @param[in] type - finding ADV data type
* @param[out] length - return the length of ADV data not including type
*
* @return pointer of ADV data
* @return - ESP_OK : success
* - other : failed
*
*/
uint8_t *esp_ble_resolve_adv_data(uint8_t *adv_data, uint8_t type, uint8_t *length);

View File

@ -23,10 +23,38 @@ extern "C" {
/// GATT INVALID UUID
#define ESP_GATT_ILLEGAL_UUID 0
/// GATT INVALID HANDLE
#define ESP_GATT_ILLEGAL_HANDLE 0
/// GATT attribute max handle
#define ESP_GATT_ATTR_HANDLE_MAX 100
/**@{
* All "ESP_GATT_UUID_xxx" is attribute types
*/
#define ESP_GATT_UUID_IMMEDIATE_ALERT_SVC 0x1802 /* Immediate alert Service*/
#define ESP_GATT_UUID_LINK_LOSS_SVC 0x1803 /* Link Loss Service*/
#define ESP_GATT_UUID_TX_POWER_SVC 0x1804 /* TX Power Service*/
#define ESP_GATT_UUID_CURRENT_TIME_SVC 0x1805 /* Current Time Service Service*/
#define ESP_GATT_UUID_REF_TIME_UPDATE_SVC 0x1806 /* Reference Time Update Service*/
#define ESP_GATT_UUID_NEXT_DST_CHANGE_SVC 0x1807 /* Next DST Change Service*/
#define ESP_GATT_UUID_GLUCOSE_SVC 0x1808 /* Glucose Service*/
#define ESP_GATT_UUID_HEALTH_THERMOM_SVC 0x1809 /* Health Thermometer Service*/
#define ESP_GATT_UUID_DEVICE_INFO_SVC 0x180A /* Device Information Service*/
#define ESP_GATT_UUID_HEART_RATE_SVC 0x180D /* Heart Rate Service*/
#define ESP_GATT_UUID_PHONE_ALERT_STATUS_SVC 0x180E /* Phone Alert Status Service*/
#define ESP_GATT_UUID_BATTERY_SERVICE_SVC 0x180F /* Battery Service*/
#define ESP_GATT_UUID_BLOOD_PRESSURE_SVC 0x1810 /* Blood Pressure Service*/
#define ESP_GATT_UUID_ALERT_NTF_SVC 0x1811 /* Alert Notification Service*/
#define ESP_GATT_UUID_HID_SVC 0x1812 /* HID Service*/
#define ESP_GATT_UUID_SCAN_PARAMETERS_SVC 0x1813 /* Scan Parameters Service*/
#define ESP_GATT_UUID_RUNNING_SPEED_CADENCE_SVC 0x1814 /* Running Speed and Cadence Service*/
#define ESP_GATT_UUID_CYCLING_SPEED_CADENCE_SVC 0x1816 /* Cycling Speed and Cadence Service*/
#define ESP_GATT_UUID_CYCLING_POWER_SVC 0x1818 /* Cycling Power Service*/
#define ESP_GATT_UUID_LOCATION_AND_NAVIGATION_SVC 0x1819 /* Location and Navigation Service*/
#define ESP_GATT_UUID_USER_DATA_SVC 0x181C /* User Data Service*/
#define ESP_GATT_UUID_WEIGHT_SCALE_SVC 0x181D /* Weight Scale Service*/
#define ESP_GATT_UUID_PRI_SERVICE 0x2800
#define ESP_GATT_UUID_SEC_SERVICE 0x2801
#define ESP_GATT_UUID_INCLUDE_SERVICE 0x2802
@ -96,6 +124,13 @@ extern "C" {
#define ESP_GATT_UUID_HID_BT_KB_OUTPUT 0x2A32
#define ESP_GATT_UUID_HID_BT_MOUSE_INPUT 0x2A33
/// Heart Rate Measurement
#define ESP_GATT_HEART_RATE_MEAS 0x2A37
/// Body Sensor Location
#define ESP_GATT_BODY_SENSOR_LOCATION 0x2A38
/// Heart Rate Control Point
#define ESP_GATT_HEART_RATE_CNTL_POINT 0x2A39
/* Battery Service characteristics */
#define ESP_GATT_UUID_BATTERY_LEVEL 0x2A19
@ -246,6 +281,83 @@ typedef enum {
/// GATT maximum attribute length
#define ESP_GATT_MAX_ATTR_LEN 600 //as same as GATT_MAX_ATTR_LEN
/**
* @brief Attribute description (used to create database)
*/
typedef struct
{
esp_bt_uuid_t uuid; /*!< Element UUID */
uint16_t perm; /*!< Attribute permission */
uint16_t max_length; /*!< Maximum length of the element*/
uint16_t length; /*!< Current length of the element*/
uint8_t* value; /*!< Element value array*/
}esp_attr_desc_t;
/**
* @brief attribute auto respose flag
*/
typedef struct
{
#define ESP_GATT_RSP_BY_APP 0
#define ESP_GATT_AUTO_RSP 1
uint8_t auto_rsp; /*!< need the app response to the client if need_rsp set to 1*/
}esp_attr_control_t;
/**
* @brief attribute type added to the gatt server database
*/
typedef struct
{
esp_attr_control_t attr_control; /*!< The attribue control type*/
esp_attr_desc_t att_desc; /*!< The attribue type*/
}esp_gatts_attr_db_t;
/**
* @brief set the attribute value type
*/
typedef struct
{
uint16_t attr_max_len; /*!< attribute max value length */
uint16_t attr_len; /*!< attribute current value length */
uint8_t *attr_value; /*!< the pointer to attribute value */
}esp_attr_value_t;
/**
* @brief Gatt include service entry element
*/
typedef struct
{
uint16_t start_hdl; /*!< Gatt start handle value of included service */
uint16_t end_hdl; /*!< Gatt end handle value of included service */
uint16_t uuid; /*!< Gatt attribute value UUID of included service */
}esp_gatts_incl_svc_desc_t; /*!< Gatt include service entry element */
/**
* @brief Gatt include 128 bit service entry element
*/
typedef struct
{
uint16_t start_hdl; /*!< Gatt start handle value of included 128 bit service */
uint16_t end_hdl; /*!< Gatt end handle value of included 128 bit service */
}esp_gatts_incl128_svc_desc_t; /*!< Gatt include 128 bit service entry element */
/**
* @brief Gatt characteristic entry element
*/
typedef struct
{
uint8_t prop; /*!< Gatt attribute properties */
uint16_t attr_hdl; /*!< Gatt attribute handle */
esp_bt_uuid_t attr_uuid; /*!< Gatt attribute uuid typedle */
}esp_gatts_char_desc_t; /*!< Gatt characteristic value descriptor */
/// Gatt attribute value
typedef struct {
uint8_t value[ESP_GATT_MAX_ATTR_LEN]; /*!< Gatt attribute value */

View File

@ -48,6 +48,8 @@ typedef enum {
ESP_GATTS_CONGEST_EVT = 20, /*!< When congest happen, the event comes */
/* following is extra event */
ESP_GATTS_RESPONSE_EVT = 21, /*!< When gatt send response complete, the event comes */
ESP_GATTS_CREAT_ATTR_TAB_EVT = 22,
ESP_GATTS_SET_ATTR_VAL_EVT = 23,
} esp_gatts_cb_event_t;
/**
@ -96,8 +98,8 @@ typedef union {
uint16_t conn_id; /*!< Connection id */
uint32_t trans_id; /*!< Transfer id */
esp_bd_addr_t bda; /*!< The bluetooth device address which been written */
#define ESP_GATT_PREP_WRITE_CANCEL 0x00
#define ESP_GATT_PREP_WRITE_EXEC 0x01
#define ESP_GATT_PREP_WRITE_CANCEL 0x00 /*!< Prepare write flag to indicate cancel prepare write */
#define ESP_GATT_PREP_WRITE_EXEC 0x01 /*!< Prepare write flag to indicate execute prepare write */
uint8_t exec_write_flag; /*!< Execute write flag */
} exec_write; /*!< Gatt server callback param of ESP_GATTS_EXEC_WRITE_EVT */
@ -228,6 +230,27 @@ typedef union {
esp_gatt_status_t status; /*!< Operation status */
uint16_t handle; /*!< Attribute handle which send response */
} rsp; /*!< Gatt server callback param of ESP_GATTS_RESPONSE_EVT */
/**
* @brief ESP_GATTS_CREAT_ATTR_TAB_EVT
*/
struct gatts_add_attr_tab_evt_param{
esp_gatt_status_t status; /*!< Operation status */
esp_bt_uuid_t svc_uuid; /*!< Service uuid type */
uint16_t num_handle; /*!< The number of the attribute handle to be added to the gatts database */
uint16_t *handles; /*!< The number to the handles */
} add_attr_tab; /*!< Gatt server callback param of ESP_GATTS_CREAT_ATTR_TAB_EVT */
/**
* @brief ESP_GATTS_SET_ATTR_VAL_EVT
*/
struct gatts_set_attr_val_evt_param{
uint16_t srvc_handle; /*!< The service handle */
uint16_t attr_handle; /*!< The attribute handle */
esp_gatt_status_t status; /*!< Operation status*/
} set_attr_val; /*!< Gatt server callback param of ESP_GATTS_SET_ATTR_VAL_EVT */
} esp_ble_gatts_cb_param_t;
/**
@ -294,7 +317,22 @@ esp_err_t esp_ble_gatts_create_service(esp_gatt_if_t gatts_if,
esp_gatt_srvc_id_t *service_id, uint16_t num_handle);
/**
* @brief Create a service attribute tab.
* @param[in] gatts_attr_db: the pointer to the service attr tab
* @param[in] gatts_if: GATT server access interface
* @param[in] max_nb_attr: the number of attribute to be added to the service database.
* @param[in] srvc_inst_id: the instance id of the service
*
* @return
* - ESP_OK : success
* - other : failed
*
*/
esp_err_t esp_ble_gatts_create_attr_tab(const esp_gatts_attr_db_t *gatts_attr_db,
esp_gatt_if_t gatts_if,
uint8_t max_nb_attr,
uint8_t srvc_inst_id);
/**
* @brief This function is called to add an included service. After included
* service is included, a callback event BTA_GATTS_ADD_INCL_SRVC_EVT
@ -321,6 +359,8 @@ esp_err_t esp_ble_gatts_add_included_service(uint16_t service_handle, uint16_t i
* @param[in] char_uuid : Characteristic UUID.
* @param[in] perm : Characteristic value declaration attribute permission.
* @param[in] property : Characteristic Properties
* @param[in] char_val : Characteristic value
* @param[in] control : attribute response control byte
*
* @return
* - ESP_OK : success
@ -328,7 +368,8 @@ esp_err_t esp_ble_gatts_add_included_service(uint16_t service_handle, uint16_t i
*
*/
esp_err_t esp_ble_gatts_add_char(uint16_t service_handle, esp_bt_uuid_t *char_uuid,
esp_gatt_perm_t perm, esp_gatt_char_prop_t property);
esp_gatt_perm_t perm, esp_gatt_char_prop_t property, esp_attr_value_t *char_val,
esp_attr_control_t *control);
/**
@ -340,7 +381,8 @@ esp_err_t esp_ble_gatts_add_char(uint16_t service_handle, esp_bt_uuid_t *char_
* be added.
* @param[in] perm: descriptor access permission.
* @param[in] descr_uuid: descriptor UUID.
*
* @param[in] char_descr_val : Characteristic descriptor value
* @param[in] control : attribute response control byte
* @return
* - ESP_OK : success
* - other : failed
@ -348,7 +390,8 @@ esp_err_t esp_ble_gatts_add_char(uint16_t service_handle, esp_bt_uuid_t *char_
*/
esp_err_t esp_ble_gatts_add_char_descr (uint16_t service_handle,
esp_bt_uuid_t *descr_uuid,
esp_gatt_perm_t perm);
esp_gatt_perm_t perm, esp_attr_value_t *char_descr_val,
esp_attr_control_t *control);
@ -432,6 +475,35 @@ esp_err_t esp_ble_gatts_send_response(esp_gatt_if_t gatts_if, uint16_t conn_id,
esp_gatt_status_t status, esp_gatt_rsp_t *rsp);
/**
* @brief This function is called to set the attribute value by the application
*
* @param[in] attr_handle: the attribute handle which to be set
* @param[in] length: the value length
* @param[in] value: the pointer to the attribute value
*
* @return
* - ESP_OK : success
* - other : failed
*
*/
esp_err_t esp_ble_gatts_set_attr_value(uint16_t attr_handle, uint16_t length, const uint8_t *value);
/**
* @brief Retrieve attribute value
*
* @param[in] attr_handle: Attribute handle.
* @param[out] length: pointer to the attribute value length
* @param[out] value: Pointer to attribute value payload, the value cannot be modified by user
*
* @return
* - ESP_OK : success
* - other : failed
*
*/
esp_err_t esp_ble_gatts_get_attr_value(uint16_t attr_handle, uint16_t *length, const uint8_t **value);
/**
* @brief Open a direct open connection or add a background auto connection
*

View File

@ -34,7 +34,6 @@
#include "bta_gatts_int.h"
#include "bta_gatts_co.h"
#include "btm_ble_api.h"
// #include "btif/include/btif_debug_conn.h"
#include <string.h>
static void bta_gatts_nv_save_cback(BOOLEAN is_saved, tGATTS_HNDL_RANGE *p_hndl_range);
@ -404,10 +403,20 @@ void bta_gatts_add_char(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg)
UINT16 attr_id = 0;
tBTA_GATTS cb_data;
tGATT_ATTR_VAL *p_attr_val = NULL;
tGATTS_ATTR_CONTROL *p_control = NULL;
if (p_msg->api_add_char_descr.attr_val.attr_max_len != 0) {
p_attr_val = &p_msg->api_add_char_descr.attr_val;
}
if (p_msg->api_add_char_descr.control.auto_rsp != 0) {
p_control = &p_msg->api_add_char_descr.control;
}
attr_id = GATTS_AddCharacteristic(p_msg->api_add_char.hdr.layer_specific,
&p_msg->api_add_char.char_uuid,
p_msg->api_add_char.perm,
p_msg->api_add_char.property);
p_msg->api_add_char.property, p_attr_val, p_control);
cb_data.add_result.server_if = p_rcb->gatt_if;
cb_data.add_result.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
cb_data.add_result.attr_id = attr_id;
@ -425,6 +434,7 @@ void bta_gatts_add_char(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg)
(*p_rcb->p_cback)(BTA_GATTS_ADD_CHAR_EVT, &cb_data);
}
}
/*******************************************************************************
**
** Function bta_gatts_add_char_descr
@ -439,10 +449,20 @@ void bta_gatts_add_char_descr(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_
tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
UINT16 attr_id = 0;
tBTA_GATTS cb_data;
tGATT_ATTR_VAL *p_attr_val = NULL;
tGATTS_ATTR_CONTROL *p_control = NULL;
if (p_msg->api_add_char_descr.attr_val.attr_max_len != 0) {
p_attr_val = &p_msg->api_add_char_descr.attr_val;
}
if (p_msg->api_add_char_descr.control.auto_rsp != 0) {
p_control = &p_msg->api_add_char_descr.control;
}
attr_id = GATTS_AddCharDescriptor(p_msg->api_add_char_descr.hdr.layer_specific,
p_msg->api_add_char_descr.perm,
&p_msg->api_add_char_descr.descr_uuid);
&p_msg->api_add_char_descr.descr_uuid, p_attr_val,
p_control);
cb_data.add_result.server_if = p_rcb->gatt_if;
cb_data.add_result.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
@ -462,6 +482,41 @@ void bta_gatts_add_char_descr(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_
}
}
/*******************************************************************************
**
** Function bta_gatts_add_char_descr
**
** Description action function to add characteristic descriptor.
**
** Returns none.
**
*******************************************************************************/
void bta_gatts_set_attr_value(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg)
{
tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
UINT16 attr_id = 0;
tBTA_GATTS cb_data;
tBTA_GATT_STATUS gatts_status;
gatts_status = GATTS_SetAttributeValue(p_msg->api_add_char_descr.hdr.layer_specific,
p_msg->api_set_val.length,
p_msg->api_set_val.value);
cb_data.attr_val.server_if = p_rcb->gatt_if;
cb_data.attr_val.service_id = p_msg->api_set_val.hdr.layer_specific;
cb_data.attr_val.attr_id = attr_id;
cb_data.attr_val.status = gatts_status;
if (p_rcb->p_cback) {
(*p_rcb->p_cback)(BTA_GATTS_SET_ATTR_VAL_EVT, &cb_data);
}
}
void bta_gatts_get_attr_value(UINT16 attr_handle, UINT16 *length, UINT8 **value)
{
GATTS_GetAttributeValue(attr_handle, length, value);
}
/*******************************************************************************
**
** Function bta_gatts_delete_service

View File

@ -215,10 +215,14 @@ void BTA_GATTS_AddIncludeService(UINT16 service_id, UINT16 included_service_id)
**
*******************************************************************************/
void BTA_GATTS_AddCharacteristic (UINT16 service_id, tBT_UUID *p_char_uuid,
tBTA_GATT_PERM perm, tBTA_GATT_CHAR_PROP property)
tBTA_GATT_PERM perm, tBTA_GATT_CHAR_PROP property, tGATT_ATTR_VAL *attr_val,
tBTA_GATTS_ATTR_CONTROL *control)
{
tBTA_GATTS_API_ADD_CHAR *p_buf;
UINT16 len = 0;
if(attr_val != NULL){
len = attr_val->attr_len;
}
if ((p_buf = (tBTA_GATTS_API_ADD_CHAR *) GKI_getbuf(sizeof(tBTA_GATTS_API_ADD_CHAR))) != NULL) {
memset(p_buf, 0, sizeof(tBTA_GATTS_API_ADD_CHAR));
@ -226,6 +230,19 @@ void BTA_GATTS_AddCharacteristic (UINT16 service_id, tBT_UUID *p_char_uuid,
p_buf->hdr.layer_specific = service_id;
p_buf->perm = perm;
p_buf->property = property;
if(control !=NULL){
p_buf->control.auto_rsp = control->auto_rsp;
}
if(attr_val != NULL){
APPL_TRACE_DEBUG("!!!!!!attr_val->attr_len = %x\n",attr_val->attr_len);
APPL_TRACE_DEBUG("!!!!!!!attr_val->attr_max_len = %x\n",attr_val->attr_max_len);
p_buf->attr_val.attr_len = attr_val->attr_len;
p_buf->attr_val.attr_max_len = attr_val->attr_max_len;
p_buf->attr_val.attr_val = (uint8_t *)GKI_getbuf(len);
if(p_buf->attr_val.attr_val != NULL){
memcpy(p_buf->attr_val.attr_val, attr_val->attr_val, attr_val->attr_len);
}
}
if (p_char_uuid) {
memcpy(&p_buf->char_uuid, p_char_uuid, sizeof(tBT_UUID));
@ -253,11 +270,16 @@ void BTA_GATTS_AddCharacteristic (UINT16 service_id, tBT_UUID *p_char_uuid,
*******************************************************************************/
void BTA_GATTS_AddCharDescriptor (UINT16 service_id,
tBTA_GATT_PERM perm,
tBT_UUID *p_descr_uuid)
tBT_UUID *p_descr_uuid, tBTA_GATT_ATTR_VAL *attr_val,
tBTA_GATTS_ATTR_CONTROL *control)
{
tBTA_GATTS_API_ADD_DESCR *p_buf;
UINT16 len = sizeof(tBTA_GATTS_API_ADD_DESCR);
UINT16 len = 0;
if(attr_val != NULL) {
len = sizeof(tBTA_GATTS_API_ADD_DESCR) + attr_val->attr_len;
} else {
len = sizeof(tBTA_GATTS_API_ADD_DESCR);
}
if ((p_buf = (tBTA_GATTS_API_ADD_DESCR *) GKI_getbuf(len)) != NULL) {
memset(p_buf, 0, len);
@ -269,10 +291,19 @@ void BTA_GATTS_AddCharDescriptor (UINT16 service_id,
if (p_descr_uuid) {
memcpy(&p_buf->descr_uuid, p_descr_uuid, sizeof(tBT_UUID));
}
if(attr_val->attr_len != 0) {
p_buf->attr_val.attr_len = attr_val->attr_len;
p_buf->attr_val.attr_max_len= attr_val->attr_max_len;
memcpy(p_buf->attr_val.attr_val, attr_val->attr_val, attr_val->attr_len);
}
if(control != NULL) {
p_buf->control.auto_rsp = control->auto_rsp;
}
bta_sys_sendmsg(p_buf);
}
return;
}
/*******************************************************************************
@ -433,6 +464,29 @@ void BTA_GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id,
}
void BTA_SetAttributeValue(UINT16 attr_handle, UINT16 length, UINT8 *value)
{
tBTA_GATTS_API_SET_ATTR_VAL *p_buf;
if((p_buf = (tBTA_GATTS_API_SET_ATTR_VAL *)GKI_getbuf(
sizeof(tBTA_GATTS_API_SET_ATTR_VAL))) != NULL){
p_buf->hdr.event = BTA_GATTS_API_SET_ATTR_VAL_EVT;
p_buf->hdr.layer_specific = attr_handle;
p_buf->length = length;
if(value != NULL){
if((p_buf->value = (UINT8 *)GKI_getbuf(length)) != NULL){
memcpy(p_buf->value, value, length);
}
}
bta_sys_sendmsg(p_buf);
}
}
void BTA_GetAttributeValue(UINT16 attr_handle, UINT16 *length, UINT8 **value)
{
bta_gatts_get_attr_value(attr_handle, length, value);
}
/*******************************************************************************
**

View File

@ -104,29 +104,30 @@ BOOLEAN bta_gatts_hdl_event(BT_HDR *p_msg)
case BTA_GATTS_API_RSP_EVT:
bta_gatts_send_rsp(p_cb, (tBTA_GATTS_DATA *) p_msg);
break;
case BTA_GATTS_API_SET_ATTR_VAL_EVT:{
UINT16 attr_id = ((tBTA_GATTS_DATA *) p_msg)->api_set_val.hdr.layer_specific;
p_srvc_cb = bta_gatts_find_srvc_cb_by_attr_id(p_cb, attr_id);
bta_gatts_set_attr_value(p_srvc_cb, (tBTA_GATTS_DATA *) p_msg);
break;
}
case BTA_GATTS_API_LISTEN_EVT:
bta_gatts_listen(p_cb, (tBTA_GATTS_DATA *) p_msg);
break;
case BTA_GATTS_API_ADD_INCL_SRVC_EVT:
case BTA_GATTS_API_ADD_CHAR_EVT:
case BTA_GATTS_API_ADD_DESCR_EVT:
case BTA_GATTS_API_DEL_SRVC_EVT:
case BTA_GATTS_API_START_SRVC_EVT:
case BTA_GATTS_API_STOP_SRVC_EVT:
p_srvc_cb = bta_gatts_find_srvc_cb_by_srvc_id(p_cb,
((tBTA_GATTS_DATA *)p_msg)->api_add_incl_srvc.hdr.layer_specific);
if (p_srvc_cb != NULL) {
bta_gatts_srvc_build_act[p_msg->event - BTA_GATTS_API_ADD_INCL_SRVC_EVT](p_srvc_cb, (tBTA_GATTS_DATA *) p_msg);
} else {
APPL_TRACE_ERROR("service not created");
APPL_TRACE_ERROR("service not created\n");
}
break;
default:
break;
}

View File

@ -395,7 +395,6 @@ typedef void (tBTA_GATTC_ENB_CBACK)(tBTA_GATT_STATUS status);
/* Client callback function */
typedef void (tBTA_GATTC_CBACK)(tBTA_GATTC_EVT event, tBTA_GATTC *p_data);
/* GATT Server Data Structure */
/* Server callback function events */
#define BTA_GATTS_REG_EVT 0
@ -419,6 +418,7 @@ typedef void (tBTA_GATTC_CBACK)(tBTA_GATTC_EVT event, tBTA_GATTC *p_data);
#define BTA_GATTS_CLOSE_EVT 18
#define BTA_GATTS_LISTEN_EVT 19
#define BTA_GATTS_CONGEST_EVT 20
#define BTA_GATTS_SET_ATTR_VAL_EVT 21
typedef UINT8 tBTA_GATTS_EVT;
typedef tGATT_IF tBTA_GATTS_IF;
@ -434,6 +434,8 @@ typedef tGATT_IF tBTA_GATTS_IF;
#define BTA_GATT_PERM_WRITE_SIGNED GATT_PERM_WRITE_SIGNED /* bit 7 - 0x0080 */
#define BTA_GATT_PERM_WRITE_SIGNED_MITM GATT_PERM_WRITE_SIGNED_MITM /* bit 8 - 0x0100 */
typedef UINT16 tBTA_GATT_PERM;
typedef tGATT_ATTR_VAL tBTA_GATT_ATTR_VAL;
typedef tGATTS_ATTR_CONTROL tBTA_GATTS_ATTR_CONTROL;
#define BTA_GATTS_INVALID_APP 0xff
@ -539,6 +541,13 @@ typedef struct {
// btla-specific --
} tBTA_GATTS_ADD_RESULT;
typedef struct{
tBTA_GATTS_IF server_if;
UINT16 service_id;
UINT16 attr_id;
tBTA_GATT_STATUS status;
}tBAT_GATTS_ATTR_VAL_RESULT;
typedef struct {
tBTA_GATTS_IF server_if;
UINT16 service_id;
@ -573,6 +582,7 @@ typedef union {
tBTA_GATTS_ADD_RESULT add_result; /* add included service: BTA_GATTS_ADD_INCL_SRVC_EVT
add char : BTA_GATTS_ADD_CHAR_EVT
add char descriptor: BTA_GATTS_ADD_CHAR_DESCR_EVT */
tBAT_GATTS_ATTR_VAL_RESULT attr_val;
tBTA_GATTS_REQ req_data;
tBTA_GATTS_CONN conn; /* BTA_GATTS_CONN_EVT */
tBTA_GATTS_CONGEST congest; /* BTA_GATTS_CONGEST_EVT callback data */
@ -1194,7 +1204,8 @@ extern void BTA_GATTS_AddIncludeService(UINT16 service_id, UINT16 included_servi
**
*******************************************************************************/
extern void BTA_GATTS_AddCharacteristic (UINT16 service_id, tBT_UUID *p_char_uuid,
tBTA_GATT_PERM perm, tBTA_GATT_CHAR_PROP property);
tBTA_GATT_PERM perm, tBTA_GATT_CHAR_PROP property, tGATT_ATTR_VAL *attr_val,
tBTA_GATTS_ATTR_CONTROL *control);
/*******************************************************************************
**
@ -1215,7 +1226,8 @@ extern void BTA_GATTS_AddCharacteristic (UINT16 service_id, tBT_UUID *p_char_
*******************************************************************************/
extern void BTA_GATTS_AddCharDescriptor (UINT16 service_id,
tBTA_GATT_PERM perm,
tBT_UUID *p_descr_uuid);
tBT_UUID *p_descr_uuid, tBTA_GATT_ATTR_VAL *attr_val,
tBTA_GATTS_ATTR_CONTROL *control);
/*******************************************************************************
**
@ -1296,6 +1308,38 @@ extern void BTA_GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id,
tBTA_GATT_STATUS status, tBTA_GATTS_RSP *p_msg);
/*******************************************************************************
**
** Function BTA_SetAttributeValue
**
** Description This function is called to set the attribute value in the gatt database
**
** Parameters attr_handle - the attribute value handle.
** length - the value length which has been set to the attribute.
** value - the pointer to the value
**
** Returns None
**
*******************************************************************************/
extern void BTA_SetAttributeValue(UINT16 attr_handle, UINT16 length, UINT8 *value);
/*******************************************************************************
**
** Function BTA_GetAttributeValue
**
** Description This function is called to get the attribute value in the gatt database
**
** Parameters attr_handle - the attribute value handle.
** length - the value length which has been set to the attribute.
** value - the pointer to the value
**
** Returns None
**
*******************************************************************************/
extern void BTA_GetAttributeValue(UINT16 attr_handle, UINT16 *length, UINT8 **value);
/*******************************************************************************
**
** Function BTA_GATTS_Open

View File

@ -48,6 +48,7 @@ enum {
BTA_GATTS_API_START_SRVC_EVT,
BTA_GATTS_API_STOP_SRVC_EVT,
BTA_GATTS_API_RSP_EVT,
BTA_GATTS_API_SET_ATTR_VAL_EVT,
BTA_GATTS_API_OPEN_EVT,
BTA_GATTS_API_CANCEL_OPEN_EVT,
BTA_GATTS_API_CLOSE_EVT,
@ -91,19 +92,21 @@ typedef struct {
tBT_UUID char_uuid;
tBTA_GATT_PERM perm;
tBTA_GATT_CHAR_PROP property;
tBTA_GATTS_ATTR_CONTROL control;
tBTA_GATT_ATTR_VAL attr_val;
} tBTA_GATTS_API_ADD_CHAR;
typedef struct {
BT_HDR hdr;
UINT16 included_service_id;
} tBTA_GATTS_API_ADD_INCL_SRVC;
typedef struct {
BT_HDR hdr;
tBT_UUID descr_uuid;
tBTA_GATT_PERM perm;
tBTA_GATTS_ATTR_CONTROL control;
tBTA_GATT_ATTR_VAL attr_val;
} tBTA_GATTS_API_ADD_DESCR;
typedef struct {
@ -121,6 +124,12 @@ typedef struct {
tBTA_GATTS_RSP *p_rsp;
} tBTA_GATTS_API_RSP;
typedef struct{
BT_HDR hdr;
UINT16 length;
UINT8 *value;
}tBTA_GATTS_API_SET_ATTR_VAL;
typedef struct {
BT_HDR hdr;
tBTA_GATT_TRANSPORT transport;
@ -156,6 +165,7 @@ typedef union {
tBTA_GATTS_API_START api_start;
tBTA_GATTS_API_INDICATION api_indicate;
tBTA_GATTS_API_RSP api_rsp;
tBTA_GATTS_API_SET_ATTR_VAL api_set_val;
tBTA_GATTS_API_OPEN api_open;
tBTA_GATTS_API_CANCEL_OPEN api_cancel_open;
@ -219,6 +229,8 @@ extern void bta_gatts_create_srvc(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_add_include_srvc(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_add_char(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_add_char_descr(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_set_attr_value(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_get_attr_value(UINT16 attr_handle, UINT16 *length, UINT8 **value);
extern void bta_gatts_delete_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_start_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_stop_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg);

View File

@ -88,6 +88,7 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
tBTA_GATTS_RSP rsp;
LOG_DEBUG("blufi profile cb event = %x\n", event);
switch (event) {
case BTA_GATTS_REG_EVT:
LOG_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);
@ -187,7 +188,8 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
//add the frist blufi characteristic --> write characteristic
BTA_GATTS_AddCharacteristic(blufi_env.handle_srvc, &blufi_char_uuid_p2e,
(GATT_PERM_WRITE),
(GATT_CHAR_PROP_BIT_WRITE));
(GATT_CHAR_PROP_BIT_WRITE),
NULL, NULL);
break;
case BTA_GATTS_ADD_CHAR_EVT:
switch (p_data->add_result.char_uuid.uu.uuid16) {
@ -196,14 +198,16 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
BTA_GATTS_AddCharacteristic(blufi_env.handle_srvc, &blufi_char_uuid_e2p,
(GATT_PERM_READ),
(GATT_PERM_READ | GATT_CHAR_PROP_BIT_NOTIFY));
(GATT_PERM_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);
&blufi_descr_uuid_e2p,
NULL, NULL);
break;
default:
break;

View File

@ -20,12 +20,25 @@
#include "btc_manage.h"
#include "btc_gatts.h"
#include "btc_gatt_util.h"
#include "future.h"
#include "btc_main.h"
#include "esp_gatts_api.h"
#define A2C_GATTS_EVT(_bta_event) (_bta_event) //BTA TO BTC EVT
#define C2A_GATTS_EVT(_btc_event) (_btc_event) //BTC TO BTA EVT
typedef struct {
future_t *complete_future;
uint16_t svc_start_hdl;
esp_bt_uuid_t svc_uuid;
bool is_tab_creat_svc;
uint8_t num_handle;
uint8_t handle_idx;
uint16_t handles[ESP_GATT_ATTR_HANDLE_MAX];
} esp_btc_creat_tab_t;
static esp_btc_creat_tab_t btc_creat_tab_env;
static inline void btc_gatts_cb_to_app(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
{
esp_gatts_cb_t btc_gatts_cb = (esp_gatts_cb_t)btc_profile_cb_get(BTC_PID_GATTS);
@ -59,6 +72,56 @@ void btc_gatts_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
}
}
break;
}
case BTC_GATTS_ACT_ADD_CHAR:{
if (src->add_char.char_val.attr_value != NULL){
dst->add_char.char_val.attr_value = (uint8_t *)GKI_getbuf(src->add_char.char_val.attr_len);
if(dst->add_char.char_val.attr_value != NULL){
memcpy(dst->add_char.char_val.attr_value, src->add_char.char_val.attr_value,
src->add_char.char_val.attr_len);
}else{
LOG_ERROR("%s %d no mem\n", __func__, msg->act);
}
}
break;
}
case BTC_GATTS_ACT_ADD_CHAR_DESCR:{
if(src->add_descr.descr_val.attr_value != NULL){
dst->add_descr.descr_val.attr_value = (uint8_t *)GKI_getbuf(src->add_descr.descr_val.attr_len);
if(dst->add_descr.descr_val.attr_value != NULL){
memcpy(dst->add_descr.descr_val.attr_value, src->add_descr.descr_val.attr_value,
src->add_descr.descr_val.attr_len);
}else{
LOG_ERROR("%s %d no mem\n", __func__, msg->act);
}
}
break;
}
case BTC_GATTS_ACT_CREATE_ATTR_TAB:{
uint8_t num_attr = src->create_attr_tab.max_nb_attr;
if(src->create_attr_tab.gatts_attr_db != NULL){
dst->create_attr_tab.gatts_attr_db = (esp_gatts_attr_db_t *)GKI_getbuf(sizeof(esp_gatts_attr_db_t)*num_attr);
if(dst->create_attr_tab.gatts_attr_db != NULL){
memcpy(dst->create_attr_tab.gatts_attr_db, src->create_attr_tab.gatts_attr_db,
sizeof(esp_gatts_attr_db_t)*num_attr);
}else{
LOG_ERROR("%s %d no mem\n",__func__, msg->act);
}
}
break;
}
case BTC_GATTS_ACT_SET_ATTR_VALUE:{
uint8_t len = src->set_attr_val.length;
if(src->set_attr_val.value){
dst->set_attr_val.value = (uint8_t *)GKI_getbuf(len);
if(dst->set_attr_val.value != NULL){
memcpy(dst->set_attr_val.value, src->set_attr_val.value, len);
}else{
LOG_ERROR("%s %d no mem\n",__func__, msg->act);
}
}
break;
}
default:
LOG_DEBUG("%s Unhandled deep copy %d\n", __func__, msg->act);
@ -91,6 +154,163 @@ void btc_gatts_arg_deep_free(btc_msg_t *msg)
}
static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db,
esp_gatt_if_t gatts_if,
uint8_t max_nb_attr,
uint8_t srvc_inst_id)
{
uint16_t uuid = 0;
future_t *future_p;
esp_ble_gatts_cb_param_t param;
//set the attribute table create service flag to ture
btc_creat_tab_env.is_tab_creat_svc = true;
btc_creat_tab_env.num_handle = max_nb_attr;
for(int i = 0; i < max_nb_attr; i++){
if(gatts_attr_db[i].att_desc.uuid.len == ESP_UUID_LEN_16){
uuid = gatts_attr_db[i].att_desc.uuid.uuid.uuid16;
}
future_p = future_new();
if (future_p == NULL) {
LOG_ERROR("%s failed:no mem\n", __func__);
return ;
}
btc_creat_tab_env.complete_future = future_p;
btc_creat_tab_env.handle_idx = i;
switch(uuid)
{
case ESP_GATT_UUID_PRI_SERVICE:{
tBTA_GATT_SRVC_ID srvc_id;
esp_gatt_srvc_id_t esp_srvc_id;
esp_srvc_id.id.inst_id = srvc_inst_id;
memcpy(&esp_srvc_id.id.uuid, &gatts_attr_db[i].att_desc.uuid, sizeof(esp_bt_uuid_t));
btc_to_bta_srvc_id(&srvc_id, &esp_srvc_id);
BTA_GATTS_CreateService(gatts_if, &srvc_id.id.uuid,
srvc_inst_id, max_nb_attr, true);
if (future_await(future_p) == FUTURE_FAIL) {
LOG_ERROR("%s failed\n", __func__);
return;
}
break;
}
case ESP_GATT_UUID_SEC_SERVICE:{
tBTA_GATT_SRVC_ID srvc_id;
esp_gatt_srvc_id_t esp_srvc_id;
esp_srvc_id.id.inst_id = srvc_inst_id;
memcpy(&esp_srvc_id.id.uuid, &gatts_attr_db[i].att_desc.uuid, sizeof(esp_bt_uuid_t));
btc_to_bta_srvc_id(&srvc_id, &esp_srvc_id);
BTA_GATTS_CreateService(gatts_if, &srvc_id.id.uuid,
srvc_inst_id, max_nb_attr, false);
if (future_await(future_p) == FUTURE_FAIL) {
LOG_ERROR("%s failed\n", __func__);
return;
}
break;
}
case ESP_GATT_UUID_INCLUDE_SERVICE:{
esp_gatts_incl_svc_desc_t *incl_svc_desc = (esp_gatts_incl_svc_desc_t *)gatts_attr_db[i].att_desc.value;
if(incl_svc_desc!= NULL){
if(btc_creat_tab_env.svc_start_hdl != 0){
BTA_GATTS_AddIncludeService(btc_creat_tab_env.svc_start_hdl,
incl_svc_desc->start_hdl);
if (future_await(future_p) == FUTURE_FAIL) {
LOG_ERROR("%s failed\n", __func__);
return;
}
}
}
break;
}
case ESP_GATT_UUID_CHAR_DECLARE:{
uint16_t svc_hal = 0;
tBT_UUID bta_char_uuid;
tGATT_ATTR_VAL attr_val;
tBTA_GATT_PERM perm;
tBTA_GATTS_ATTR_CONTROL control;
if(btc_creat_tab_env.svc_start_hdl != 0){
svc_hal = btc_creat_tab_env.svc_start_hdl;
esp_gatts_char_desc_t *char_desc = (esp_gatts_char_desc_t *)gatts_attr_db[i].att_desc.value;
if(char_desc != NULL){
perm = gatts_attr_db[i+1].att_desc.perm;
attr_val.attr_len = gatts_attr_db[i+1].att_desc.length;
attr_val.attr_max_len = gatts_attr_db[i+1].att_desc.max_length;
btc_to_bta_uuid(&bta_char_uuid, &char_desc->attr_uuid);
attr_val.attr_val = gatts_attr_db[i+1].att_desc.value;
control.auto_rsp = gatts_attr_db[i+1].attr_control.auto_rsp;
BTA_GATTS_AddCharacteristic (svc_hal, &bta_char_uuid,
perm, char_desc->prop, &attr_val, &control);
if (future_await(future_p) == FUTURE_FAIL) {
LOG_ERROR("%s failed\n", __func__);
return;
}
}
}
break;
}
case ESP_GATT_UUID_CHAR_EXT_PROP:
case ESP_GATT_UUID_CHAR_DESCRIPTION:
case ESP_GATT_UUID_CHAR_CLIENT_CONFIG:
case ESP_GATT_UUID_CHAR_SRVR_CONFIG:
case ESP_GATT_UUID_CHAR_PRESENT_FORMAT:
case ESP_GATT_UUID_CHAR_AGG_FORMAT:
case ESP_GATT_UUID_CHAR_VALID_RANGE:
case ESP_GATT_UUID_EXT_RPT_REF_DESCR:
case ESP_GATT_UUID_RPT_REF_DESCR:{
uint16_t svc_hal = btc_creat_tab_env.svc_start_hdl;
tBT_UUID bta_char_uuid;
tGATT_ATTR_VAL attr_val;
tBTA_GATT_PERM perm = gatts_attr_db[i].att_desc.perm;
tBTA_GATTS_ATTR_CONTROL control;
if(svc_hal != 0){
attr_val.attr_len = gatts_attr_db[i].att_desc.length;
attr_val.attr_max_len = gatts_attr_db[i].att_desc.max_length;
attr_val.attr_val = gatts_attr_db[i].att_desc.value;
btc_to_bta_uuid(&bta_char_uuid, &gatts_attr_db[i].att_desc.uuid);
control.auto_rsp = gatts_attr_db[i].attr_control.auto_rsp;
BTA_GATTS_AddCharDescriptor(svc_hal, perm, &bta_char_uuid, &attr_val, &control);
if (future_await(future_p) == FUTURE_FAIL) {
LOG_ERROR("%s failed\n", __func__);
return;
}
}
break;
}
default:
break;
}
}
param.add_attr_tab.status = ESP_GATT_OK;
param.add_attr_tab.num_handle = max_nb_attr;
param.add_attr_tab.handles = btc_creat_tab_env.handles;
memcpy(&param.add_attr_tab.svc_uuid, &btc_creat_tab_env.svc_uuid, sizeof(esp_bt_uuid_t));
btc_gatts_cb_to_app(ESP_GATTS_CREAT_ATTR_TAB_EVT, gatts_if, &param);
//reset the env after sent the data to app
memset(&btc_creat_tab_env, 0, sizeof(esp_btc_creat_tab_t));
//release the flag vaule to false after finish the service created.
btc_creat_tab_env.is_tab_creat_svc = false;
}
void btc_gatts_get_attr_value(uint16_t attr_handle, uint16_t *length, uint8_t **value)
{
BTA_GetAttributeValue(attr_handle, length, value);
}
static void btc_gatts_cb_param_copy_req(btc_msg_t *msg, void *p_dest, void *p_src)
{
@ -137,7 +357,6 @@ static void btc_gatts_cb_param_copy_free(btc_msg_t *msg, tBTA_GATTS *p_data)
GKI_freebuf(p_data->req_data.p_data);
}
break;
default:
break;
}
@ -152,7 +371,39 @@ static void btc_gatts_inter_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
msg.sig = BTC_SIG_API_CB;
msg.pid = BTC_PID_GATTS;
msg.act = event;
if(btc_creat_tab_env.is_tab_creat_svc && btc_creat_tab_env.complete_future){
switch(event){
case BTA_GATTS_CREATE_EVT:{
//save the service handle to the btc module after used
//the attribute table method to creat a service
bta_to_btc_uuid(&btc_creat_tab_env.svc_uuid, &p_data->create.uuid);
uint8_t index = btc_creat_tab_env.handle_idx;
btc_creat_tab_env.svc_start_hdl = p_data->create.service_id;
btc_creat_tab_env.handles[index] = p_data->create.service_id;
break;
}
case BTA_GATTS_ADD_INCL_SRVC_EVT:{
uint8_t index = btc_creat_tab_env.handle_idx;
btc_creat_tab_env.handles[index] = p_data->add_result.attr_id;
break;
}
case BTA_GATTS_ADD_CHAR_EVT:{
uint8_t index = btc_creat_tab_env.handle_idx;
btc_creat_tab_env.handles[index] = p_data->add_result.attr_id - 1;
btc_creat_tab_env.handles[index+1] = p_data->add_result.attr_id;
break;
}
case BTA_GATTS_ADD_CHAR_DESCR_EVT:{
uint8_t index = btc_creat_tab_env.handle_idx;
btc_creat_tab_env.handles[index] = p_data->add_result.attr_id;
break;
}
default:
break;
}
future_ready(btc_creat_tab_env.complete_future, FUTURE_SUCCESS);
}
status = btc_transfer_context(&msg, p_data,
sizeof(tBTA_GATTS), btc_gatts_cb_param_copy_req);
@ -187,6 +438,12 @@ void btc_gatts_call_handler(btc_msg_t *msg)
srvc_id.is_primary);
break;
}
case BTC_GATTS_ACT_CREATE_ATTR_TAB:
btc_gatts_act_create_attr_tab(arg->create_attr_tab.gatts_attr_db,
arg->create_attr_tab.gatts_if,
arg->create_attr_tab.max_nb_attr,
arg->create_attr_tab.srvc_inst_id);
break;
case BTC_GATTS_ACT_DELETE_SERVICE:
BTA_GATTS_DeleteService(arg->delete_srvc.service_handle);
break;
@ -204,13 +461,17 @@ void btc_gatts_call_handler(btc_msg_t *msg)
btc_to_bta_uuid(&uuid, &arg->add_char.char_uuid);
BTA_GATTS_AddCharacteristic(arg->add_char.service_handle, &uuid,
arg->add_char.perm, arg->add_char.property);
arg->add_char.perm, arg->add_char.property,
(tGATT_ATTR_VAL *)&arg->add_char.char_val,
(tBTA_GATTS_ATTR_CONTROL *)&arg->add_char.attr_control);
break;
}
case BTC_GATTS_ACT_ADD_CHAR_DESCR: {
tBT_UUID uuid;
btc_to_bta_uuid(&uuid, &arg->add_descr.descr_uuid);
BTA_GATTS_AddCharDescriptor(arg->add_descr.service_handle, arg->add_descr.perm, &uuid);
BTA_GATTS_AddCharDescriptor(arg->add_descr.service_handle, arg->add_descr.perm, &uuid,
(tBTA_GATT_ATTR_VAL *)&arg->add_descr.descr_val,
(tBTA_GATTS_ATTR_CONTROL *)&arg->add_descr.attr_control);
break;
}
case BTC_GATTS_ACT_SEND_INDICATE:
@ -236,6 +497,9 @@ void btc_gatts_call_handler(btc_msg_t *msg)
btc_gatts_cb_to_app(ESP_GATTS_RESPONSE_EVT, BTC_GATT_GET_GATT_IF(arg->send_rsp.conn_id), &param);
break;
}
case BTC_GATTS_ACT_SET_ATTR_VALUE:
break;
case BTC_GATTS_ACT_OPEN: {
// Ensure device is in inquiry database
tBTA_GATT_TRANSPORT transport = BTA_GATT_TRANSPORT_LE;
@ -359,6 +623,7 @@ void btc_gatts_cb_handler(btc_msg_t *msg)
param.create.service_id.is_primary = p_data->create.is_primary;
param.create.service_id.id.inst_id = p_data->create.svc_instance;
bta_to_btc_uuid(&param.create.service_id.id.uuid, &p_data->create.uuid);
btc_gatts_cb_to_app(ESP_GATTS_CREATE_EVT, gatts_if, &param);
break;
case BTA_GATTS_ADD_INCL_SRVC_EVT:
@ -391,6 +656,7 @@ void btc_gatts_cb_handler(btc_msg_t *msg)
gatts_if = p_data->srvc_oper.server_if;
param.del.status = p_data->srvc_oper.status;
param.del.service_handle = p_data->srvc_oper.service_id;
btc_gatts_cb_to_app(ESP_GATTS_DELETE_EVT, gatts_if, &param);
break;
case BTA_GATTS_START_EVT:
@ -438,6 +704,13 @@ void btc_gatts_cb_handler(btc_msg_t *msg)
param.congest.congested = p_data->congest.congested;
btc_gatts_cb_to_app(ESP_GATTS_CONGEST_EVT, gatts_if, &param);
break;
case BTA_GATTS_SET_ATTR_VAL_EVT:
gatts_if = p_data->attr_val.server_if;
param.set_attr_val.srvc_handle = p_data->attr_val.service_id;
param.set_attr_val.attr_handle = p_data->attr_val.attr_id;
param.set_attr_val.status = p_data->attr_val.status;
btc_gatts_cb_to_app(ESP_GATTS_SET_ATTR_VAL_EVT, gatts_if, &param);
break;
default:
// do nothing
break;

View File

@ -24,6 +24,7 @@ typedef enum {
BTC_GATTS_ACT_APP_REGISTER = 0,
BTC_GATTS_ACT_APP_UNREGISTER,
BTC_GATTS_ACT_CREATE_SERVICE,
BTC_GATTS_ACT_CREATE_ATTR_TAB,
BTC_GATTS_ACT_DELETE_SERVICE,
BTC_GATTS_ACT_START_SERVICE,
BTC_GATTS_ACT_STOP_SERVICE,
@ -32,6 +33,7 @@ typedef enum {
BTC_GATTS_ACT_ADD_CHAR_DESCR,
BTC_GATTS_ACT_SEND_INDICATE,
BTC_GATTS_ACT_SEND_RESPONSE,
BTC_GATTS_ACT_SET_ATTR_VALUE,
BTC_GATTS_ACT_OPEN,
BTC_GATTS_ACT_CLOSE,
} btc_gatts_act_t;
@ -42,46 +44,67 @@ typedef union {
struct app_reg_args {
uint16_t app_id;
} app_reg;
//BTC_GATTS_ACT_APP_UNREGISTER,
struct app_unreg_args {
esp_gatt_if_t gatts_if;
} app_unreg;
//BTC_GATTS_ACT_CREATE_SERVICE,
struct create_srvc_args {
esp_gatt_if_t gatts_if;
esp_gatt_srvc_id_t service_id;
uint16_t num_handle;
} create_srvc;
//BTC_GATTS_ACT_CREATE_ATTR_TAB
struct create_attr_tab_args{
esp_gatt_if_t gatts_if;
uint8_t srvc_inst_id;
uint8_t max_nb_attr;
esp_gatts_attr_db_t *gatts_attr_db;
}create_attr_tab;
//BTC_GATTS_ACT_DELETE_SERVICE,
struct delete_srvc_args {
uint16_t service_handle;
} delete_srvc;
//BTC_GATTS_ACT_START_SERVICE,
struct start_srvc_args {
uint16_t service_handle;
} start_srvc;
//BTC_GATTS_ACT_STOP_SERVICE,
struct stop_srvc_args {
uint16_t service_handle;
} stop_srvc;
//BTC_GATTS_ACT_ADD_INCLUDE_SERVICE,
struct add_incl_srvc_args {
uint16_t service_handle;
uint16_t included_service_handle;
} add_incl_srvc;
//BTC_GATTS_ACT_ADD_CHAR,
struct add_char_args {
uint16_t service_handle;
esp_bt_uuid_t char_uuid;
esp_gatt_perm_t perm;
esp_gatt_char_prop_t property;
esp_attr_control_t attr_control;
esp_attr_value_t char_val;
} add_char;
//BTC_GATTS_ACT_ADD_CHAR_DESCR,
struct add_descr_args {
uint16_t service_handle;
esp_bt_uuid_t descr_uuid;
esp_gatt_perm_t perm;
esp_attr_control_t attr_control;
esp_attr_value_t descr_val;
} add_descr;
//BTC_GATTS_ACT_SEND_INDICATE,
struct send_indicate_args {
uint16_t conn_id;
@ -90,6 +113,7 @@ typedef union {
uint16_t value_len;
uint8_t *value;
} send_ind;
//BTC_GATTS_ACT_SEND_RESPONSE,
struct send_rsp_args {
uint16_t conn_id;
@ -97,21 +121,32 @@ typedef union {
esp_gatt_status_t status;
esp_gatt_rsp_t *rsp;
} send_rsp;
//BTC_GATTS_SET_ATTR_VALUE
struct set_attr_val_args{
uint16_t length;
uint8_t *value;
} set_attr_val;
//BTC_GATTS_ACT_OPEN,
struct open_args {
esp_gatt_if_t gatts_if;
esp_bd_addr_t remote_bda;
bool is_direct;
} open;
//BTC_GATTS_ACT_CLOSE,
struct close_args {
uint16_t conn_id;
} close;
} btc_ble_gatts_args_t;
void btc_gatts_call_handler(btc_msg_t *msg);
void btc_gatts_cb_handler(btc_msg_t *msg);
void btc_gatts_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src);
void btc_gatts_get_attr_value(uint16_t attr_handle, uint16_t *length, uint8_t **value);
#endif /* __BTC_GATTS_H__ */

View File

@ -150,13 +150,10 @@ static void reassemble_and_dispatch(BT_HDR *packet)
LOG_DEBUG("%s found unfinished packet for handle with start packet. Dropping old.\n", __func__);
LOG_DEBUG("partial_packet->len = %x, offset = %x\n", partial_packet->len, partial_packet->len);
//for (int i = 0; i < partial_packet->len; i++) {
// LOG_ERROR("%x", partial_packet->data[i]);
//}
//LOG_ERROR("\n");
hash_map_erase(partial_packets, (void *)(uintptr_t)handle);
//buffer_allocator->free(partial_packet);
//LOG_ERROR("+++++++++++++++++++\n");
}
uint16_t full_length = l2cap_length + L2CAP_HEADER_SIZE + HCI_ACL_PREAMBLE_SIZE;

View File

@ -392,7 +392,8 @@ void gap_attr_db_init(void)
*/
uuid.len = LEN_UUID_16;
uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_DEVICE_NAME;
p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid, GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ);
p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid, GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ,
NULL, NULL);
p_db_attr ++;
/* add Icon characteristic
@ -401,7 +402,8 @@ void gap_attr_db_init(void)
p_db_attr->handle = GATTS_AddCharacteristic(service_handle,
&uuid,
GATT_PERM_READ,
GATT_CHAR_PROP_BIT_READ);
GATT_CHAR_PROP_BIT_READ,
NULL, NULL);
p_db_attr ++;
#if ((defined BTM_PERIPHERAL_ENABLED) && (BTM_PERIPHERAL_ENABLED == TRUE))
@ -416,7 +418,8 @@ void gap_attr_db_init(void)
p_db_attr->handle = GATTS_AddCharacteristic(service_handle,
&uuid,
GATT_PERM_READ,
GATT_CHAR_PROP_BIT_READ);
GATT_CHAR_PROP_BIT_READ,
NULL, NULL);
p_db_attr ++;
#endif
@ -424,7 +427,8 @@ void gap_attr_db_init(void)
uuid.len = LEN_UUID_16;
uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_CENTRAL_ADDR_RESOL;
p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid,
GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ);
GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ,
NULL, NULL);
p_db_attr->attr_value.addr_resolution = 0;
p_db_attr++;

View File

@ -151,10 +151,10 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
tBT_UUID *p_app_uuid128;
GATT_TRACE_API ("GATTS_CreateService" );
GATT_TRACE_API ("GATTS_CreateService\n" );
if (p_reg == NULL) {
GATT_TRACE_ERROR ("Inavlid gatt_if=%d", gatt_if);
GATT_TRACE_ERROR ("Inavlid gatt_if=%d\n", gatt_if);
return (0);
}
@ -162,7 +162,7 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
if ((p_list = gatt_find_hdl_buffer_by_app_id(p_app_uuid128, p_svc_uuid, svc_inst)) != NULL) {
s_hdl = p_list->asgn_range.s_handle;
GATT_TRACE_DEBUG ("Service already been created!!");
GATT_TRACE_DEBUG ("Service already been created!!\n");
} else {
if ( (p_svc_uuid->len == LEN_UUID_16) && (p_svc_uuid->uu.uuid16 == UUID_SERVCLASS_GATT_SERVER)) {
s_hdl = gatt_cb.hdl_cfg.gatt_start_hdl;
@ -184,13 +184,13 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
/* check for space */
if (num_handles > (0xFFFF - s_hdl + 1)) {
GATT_TRACE_ERROR ("GATTS_ReserveHandles: no handles, s_hdl: %u needed: %u", s_hdl, num_handles);
GATT_TRACE_ERROR ("GATTS_ReserveHandles: no handles, s_hdl: %u needed: %u\n", s_hdl, num_handles);
return (0);
}
if ( (p_list = gatt_alloc_hdl_buffer()) == NULL) {
/* No free entry */
GATT_TRACE_ERROR ("GATTS_ReserveHandles: no free handle blocks");
GATT_TRACE_ERROR ("GATTS_ReserveHandles: no free handle blocks\n");
return (0);
}
@ -210,7 +210,7 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
/* add a pending new service change item to the list */
if ( (p_buf = gatt_add_pending_new_srv_start(&p_list->asgn_range)) == NULL) {
/* No free entry */
GATT_TRACE_ERROR ("gatt_add_pending_new_srv_start: no free blocks");
GATT_TRACE_ERROR ("gatt_add_pending_new_srv_start: no free blocks\n");
if (p_list) {
gatt_remove_an_item_from_list(p_list_info, p_list);
@ -219,12 +219,12 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
return (0);
}
GATT_TRACE_DEBUG ("Add a new srv chg item");
GATT_TRACE_DEBUG ("Add a new srv chg item\n");
}
}
if (!gatts_init_service_db(&p_list->svc_db, p_svc_uuid, is_pri, s_hdl , num_handles)) {
GATT_TRACE_ERROR ("GATTS_ReserveHandles: service DB initialization failed");
GATT_TRACE_ERROR ("GATTS_ReserveHandles: service DB initialization failed\n");
if (p_list) {
gatt_remove_an_item_from_list(p_list_info, p_list);
gatt_free_hdl_buffer(p_list);
@ -236,12 +236,6 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
return (0);
}
GATT_TRACE_DEBUG ("GATTS_CreateService(success): handles needed:%u s_hdl=%u e_hdl=%u %s[%x] is_primary=%d",
num_handles, p_list->asgn_range.s_handle , p_list->asgn_range.e_handle,
((p_list->asgn_range.svc_uuid.len == 2) ? "uuid16" : "uuid128" ),
p_list->asgn_range.svc_uuid.uu.uuid16,
p_list->asgn_range.is_primary);
return (s_hdl);
}
@ -295,25 +289,27 @@ UINT16 GATTS_AddIncludeService (UINT16 service_handle, UINT16 include_svc_handle
**
*******************************************************************************/
UINT16 GATTS_AddCharacteristic (UINT16 service_handle, tBT_UUID *p_char_uuid,
tGATT_PERM perm, tGATT_CHAR_PROP property)
tGATT_PERM perm, tGATT_CHAR_PROP property,
tGATT_ATTR_VAL *attr_val, tGATTS_ATTR_CONTROL *control)
{
tGATT_HDL_LIST_ELEM *p_decl;
if ((p_decl = gatt_find_hdl_buffer_by_handle(service_handle)) == NULL) {
GATT_TRACE_DEBUG("Service not created");
GATT_TRACE_DEBUG("Service not created\n");
return 0;
}
/* data validity checking */
if ( ((property & GATT_CHAR_PROP_BIT_AUTH) && !(perm & GATT_WRITE_SIGNED_PERM)) ||
((perm & GATT_WRITE_SIGNED_PERM) && !(property & GATT_CHAR_PROP_BIT_AUTH)) ) {
GATT_TRACE_DEBUG("Invalid configuration property=0x%x perm=0x%x ", property, perm);
GATT_TRACE_DEBUG("Invalid configuration property=0x%x perm=0x%x\n ", property, perm);
return 0;
}
return gatts_add_characteristic(&p_decl->svc_db,
perm,
property,
p_char_uuid);
p_char_uuid,
attr_val, control);
}
/*******************************************************************************
**
@ -336,7 +332,7 @@ UINT16 GATTS_AddCharacteristic (UINT16 service_handle, tBT_UUID *p_char_uuid,
*******************************************************************************/
UINT16 GATTS_AddCharDescriptor (UINT16 service_handle,
tGATT_PERM perm,
tBT_UUID *p_descr_uuid)
tBT_UUID *p_descr_uuid, tGATT_ATTR_VAL *attr_val, tGATTS_ATTR_CONTROL *control)
{
tGATT_HDL_LIST_ELEM *p_decl;
@ -353,7 +349,8 @@ UINT16 GATTS_AddCharDescriptor (UINT16 service_handle,
return gatts_add_char_descr(&p_decl->svc_db,
perm,
p_descr_uuid);
p_descr_uuid,
attr_val, control);
}
/*******************************************************************************
@ -493,9 +490,9 @@ tGATT_STATUS GATTS_StartService (tGATT_IF gatt_if, UINT16 service_handle,
gatt_add_a_srv_to_list(&gatt_cb.srv_list_info, &gatt_cb.srv_list[i_sreg]);
GATT_TRACE_DEBUG ("allocated i_sreg=%d ", i_sreg);
GATT_TRACE_DEBUG ("allocated i_sreg=%d\n", i_sreg);
GATT_TRACE_DEBUG ("s_hdl=%d e_hdl=%d type=0x%x svc_inst=%d sdp_hdl=0x%x",
GATT_TRACE_DEBUG ("s_hdl=%d e_hdl=%d type=0x%x svc_inst=%d sdp_hdl=0x%x\n",
p_sreg->s_hdl, p_sreg->e_hdl,
p_sreg->type, p_sreg->service_instance,
p_sreg->sdp_handle);
@ -676,16 +673,16 @@ tGATT_STATUS GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id,
tGATT_REG *p_reg = gatt_get_regcb(gatt_if);
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(tcb_idx);
GATT_TRACE_API ("GATTS_SendRsp: conn_id: %u trans_id: %u Status: 0x%04x",
GATT_TRACE_API ("GATTS_SendRsp: conn_id: %u trans_id: %u Status: 0x%04x\n",
conn_id, trans_id, status);
if ( (p_reg == NULL) || (p_tcb == NULL)) {
GATT_TRACE_ERROR ("GATTS_SendRsp Unknown conn_id: %u ", conn_id);
GATT_TRACE_ERROR ("GATTS_SendRsp Unknown conn_id: %u\n", conn_id);
return (tGATT_STATUS) GATT_INVALID_CONN_ID;
}
if (p_tcb->sr_cmd.trans_id != trans_id) {
GATT_TRACE_ERROR ("GATTS_SendRsp conn_id: %u waiting for op_code = %02x",
GATT_TRACE_ERROR ("GATTS_SendRsp conn_id: %u waiting for op_code = %02x\n",
conn_id, p_tcb->sr_cmd.op_code);
return (GATT_WRONG_STATE);
@ -696,6 +693,69 @@ tGATT_STATUS GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id,
return cmd_sent;
}
/*******************************************************************************
**
** Function GATTS_SetAttributeValue
**
** Description This function sends to set the attribute value .
**
** Parameter attr_handle:the attribute handle
** length: the attribute length
** value: the value to be set to the attribute in the database
**
** Returns GATT_SUCCESS if successfully sent; otherwise error code.
**
*******************************************************************************/
tGATT_STATUS GATTS_SetAttributeValue(UINT16 attr_handle, UINT16 length, UINT8 *value)
{
tGATT_STATUS status;
tGATT_HDL_LIST_ELEM *p_decl = NULL;
GATT_TRACE_DEBUG("GATTS_SetAttributeValue: attr_handle: %u length: %u \n",
attr_handle, length);
if ((p_decl = gatt_find_hdl_buffer_by_attr_handle(attr_handle)) == NULL) {
GATT_TRACE_DEBUG("Service not created\n");
return GATT_INVALID_HANDLE;
}
status = gatts_set_attribute_value(&p_decl->svc_db, attr_handle, length, value);
return status;
}
/*******************************************************************************
**
** Function GATTS_GetAttributeValue
**
** Description This function sends to set the attribute value .
**
** Parameter attr_handle: the attribute handle
** length:the attribute value length in the database
** value: the attribute value out put
**
** Returns GATT_SUCCESS if successfully sent; otherwise error code.
**
*******************************************************************************/
tGATT_STATUS GATTS_GetAttributeValue(UINT16 attr_handle, UINT16 *length, UINT8 **value)
{
tGATT_STATUS status;
tGATT_HDL_LIST_ELEM *p_decl;
GATT_TRACE_DEBUG("GATTS_GetAttributeValue: attr_handle: %u\n",
attr_handle);
if ((p_decl = gatt_find_hdl_buffer_by_attr_handle(attr_handle)) == NULL) {
GATT_TRACE_ERROR("Service not created\n");
return GATT_INVALID_HANDLE;
}
status = gatts_get_attribute_value(&p_decl->svc_db, attr_handle, length, value);
return status;
}
/*******************************************************************************/
/* GATT Profile Srvr Functions */
/*******************************************************************************/
@ -1132,7 +1192,7 @@ tGATT_IF GATT_Register (tBT_UUID *p_app_uuid128, tGATT_CBACK *p_cb_info)
break;
}
}
GATT_TRACE_API ("allocated gatt_if=%d", gatt_if);
GATT_TRACE_API ("allocated gatt_if=%d\n", gatt_if);
return gatt_if;
}

View File

@ -279,21 +279,24 @@ void gatt_profile_db_init (void)
GATT_StartIf(gatt_cb.gatt_if);
service_handle = GATTS_CreateService (gatt_cb.gatt_if , &uuid, 0, GATTP_MAX_ATTR_NUM, TRUE);
GATT_TRACE_ERROR ("GATTS_CreateService: handle of service handle%x", service_handle);
/* add Service Changed characteristic
*/
uuid.uu.uuid16 = gatt_cb.gattp_attr.uuid = GATT_UUID_GATT_SRV_CHGD;
gatt_cb.gattp_attr.service_change = 0;
gatt_cb.gattp_attr.handle =
gatt_cb.handle_of_h_r = GATTS_AddCharacteristic(service_handle, &uuid, 0, GATT_CHAR_PROP_BIT_INDICATE);
gatt_cb.handle_of_h_r = GATTS_AddCharacteristic(service_handle, &uuid, 0, GATT_CHAR_PROP_BIT_INDICATE,
NULL, NULL);
GATT_TRACE_DEBUG ("gatt_profile_db_init: handle of service changed%d",
gatt_cb.handle_of_h_r );
GATT_TRACE_DEBUG ("gatt_profile_db_init: handle of service changed%d\n",
gatt_cb.handle_of_h_r);
/* start service
*/
status = GATTS_StartService (gatt_cb.gatt_if, service_handle, GATTP_TRANSPORT_SUPPORTED );
GATT_TRACE_DEBUG ("gatt_profile_db_init: gatt_if=%d start status%d",
GATT_TRACE_DEBUG ("gatt_profile_db_init: gatt_if=%d start status%d\n",
gatt_cb.gatt_if, status);
}

View File

@ -65,12 +65,12 @@ BOOLEAN gatts_init_service_db (tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN
GKI_init_q(&p_db->svc_buffer);
if (!allocate_svc_db_buf(p_db)) {
GATT_TRACE_ERROR("gatts_init_service_db failed, no resources");
GATT_TRACE_ERROR("gatts_init_service_db failed, no resources\n");
return FALSE;
}
GATT_TRACE_DEBUG("gatts_init_service_db");
GATT_TRACE_DEBUG("s_hdl = %d num_handle = %d", s_hdl, num_handle );
GATT_TRACE_DEBUG("gatts_init_service_db\n");
GATT_TRACE_DEBUG("s_hdl = %d num_handle = %d\n", s_hdl, num_handle );
/* update service database information */
p_db->next_handle = s_hdl;
@ -94,7 +94,7 @@ BOOLEAN gatts_init_service_db (tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN
tBT_UUID *gatts_get_service_uuid (tGATT_SVC_DB *p_db)
{
if (!p_db || !p_db->p_attr_list) {
GATT_TRACE_ERROR("service DB empty");
GATT_TRACE_ERROR("service DB empty\n");
return NULL;
} else {
@ -127,28 +127,28 @@ static tGATT_STATUS gatts_check_attr_readability(tGATT_ATTR16 *p_attr,
}
if (!(perm & GATT_READ_ALLOWED)) {
GATT_TRACE_ERROR( "GATT_READ_NOT_PERMIT");
GATT_TRACE_ERROR( "GATT_READ_NOT_PERMIT\n");
return GATT_READ_NOT_PERMIT;
}
if ((perm & GATT_READ_AUTH_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED) &&
!(sec_flag & BTM_SEC_FLAG_ENCRYPTED)) {
GATT_TRACE_ERROR( "GATT_INSUF_AUTHENTICATION");
GATT_TRACE_ERROR( "GATT_INSUF_AUTHENTICATION\n");
return GATT_INSUF_AUTHENTICATION;
}
if ((perm & GATT_READ_MITM_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_AUTHED)) {
GATT_TRACE_ERROR( "GATT_INSUF_AUTHENTICATION: MITM Required");
GATT_TRACE_ERROR( "GATT_INSUF_AUTHENTICATION: MITM Required\n");
return GATT_INSUF_AUTHENTICATION;
}
if ((perm & GATT_READ_ENCRYPTED_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_ENCRYPTED)) {
GATT_TRACE_ERROR( "GATT_INSUF_ENCRYPTION");
GATT_TRACE_ERROR( "GATT_INSUF_ENCRYPTION\n");
return GATT_INSUF_ENCRYPTION;
}
if ( (perm & GATT_READ_ENCRYPTED_REQUIRED) && (sec_flag & GATT_SEC_FLAG_ENCRYPTED) && (key_size < min_key_size)) {
GATT_TRACE_ERROR( "GATT_INSUF_KEY_SIZE");
GATT_TRACE_ERROR( "GATT_INSUF_KEY_SIZE\n");
return GATT_INSUF_KEY_SIZE;
}
@ -163,7 +163,7 @@ static tGATT_STATUS gatts_check_attr_readability(tGATT_ATTR16 *p_attr,
case GATT_UUID_CHAR_CLIENT_CONFIG:
case GATT_UUID_CHAR_SRVR_CONFIG:
case GATT_UUID_CHAR_PRESENT_FORMAT:
GATT_TRACE_ERROR("GATT_NOT_LONG");
GATT_TRACE_ERROR("GATT_NOT_LONG\n");
return GATT_NOT_LONG;
default:
@ -206,7 +206,7 @@ static tGATT_STATUS read_attr_value (void *p_attr,
tGATT_STATUS status;
tGATT_ATTR16 *p_attr16 = (tGATT_ATTR16 *)p_attr;
GATT_TRACE_DEBUG("read_attr_value uuid=0x%04x perm=0x%0x sec_flag=0x%x offset=%d read_long=%d",
GATT_TRACE_DEBUG("read_attr_value uuid=0x%04x perm=0x%0x sec_flag=0x%x offset=%d read_long=%d\n",
p_attr16->uuid,
p_attr16->permission,
sec_flag,
@ -268,8 +268,23 @@ static tGATT_STATUS read_attr_value (void *p_attr,
status = GATT_SUCCESS;
}
} else { /* characteristic description or characteristic value */
if (p_attr16->control.auto_rsp == GATT_RSP_BY_STACK) {
GATT_TRACE_DEBUG("before characteristic description or characteristic value\n");
if (p_attr16->p_value != NULL && p_attr16->p_value->attr_val.attr_val != NULL) {
uint8_t *value = p_attr16->p_value->attr_val.attr_val + offset;
GATT_TRACE_DEBUG("after characteristic description or characteristic value\n");
if (mtu >= p_attr16->p_value->attr_val.attr_len) {
ARRAY_TO_STREAM(p, value, p_attr16->p_value->attr_val.attr_len);
} else {
ARRAY_TO_STREAM(p, value, mtu);
}
}
status = GATT_STACK_RSP;
} else {
status = GATT_PENDING;
}
}
*p_len = len;
*p_data = p;
@ -341,7 +356,7 @@ tGATT_STATUS gatts_db_read_attr_value_by_type (tGATT_TCB *p_tcb,
status = read_attr_value ((void *)p_attr, 0, &p, FALSE, (UINT16)(*p_len - 2), &len, sec_flag, key_size);
if (status == GATT_PENDING) {
if (status == GATT_PENDING || status == GATT_STACK_RSP) {
status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, 0, trans_id);
/* one callback at a time */
@ -445,12 +460,12 @@ UINT16 gatts_add_included_service (tGATT_SVC_DB *p_db, UINT16 s_handle, UINT16 e
*******************************************************************************/
UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm,
tGATT_CHAR_PROP property,
tBT_UUID *p_char_uuid)
tBT_UUID *p_char_uuid, tGATT_ATTR_VAL *attr_val, tGATTS_ATTR_CONTROL *control)
{
tGATT_ATTR16 *p_char_decl, *p_char_val;
tBT_UUID uuid = {LEN_UUID_16, {GATT_UUID_CHAR_DECLARE}};
GATT_TRACE_DEBUG("gatts_add_characteristic perm=0x%0x property=0x%0x", perm, property);
GATT_TRACE_DEBUG("gatts_add_characteristic perm=0x%0x property=0x%0x\n", perm, property);
if ((p_char_decl = (tGATT_ATTR16 *)allocate_attr_in_db(p_db, &uuid, GATT_PERM_READ)) != NULL) {
if (!copy_extra_byte_in_db(p_db, (void **)&p_char_decl->p_value, sizeof(tGATT_CHAR_DECL))) {
@ -467,8 +482,30 @@ UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm,
p_char_decl->p_value->char_decl.property = property;
p_char_decl->p_value->char_decl.char_val_handle = p_char_val->handle;
if (control != NULL) {
p_char_val->control.auto_rsp = control->auto_rsp;
} else {
p_char_val->control.auto_rsp = GATT_RSP_DEFAULT;
}
if (attr_val != NULL) {
if (!copy_extra_byte_in_db(p_db, (void **)&p_char_val->p_value, sizeof(tGATT_ATTR_VAL))) {
deallocate_attr_in_db(p_db, p_char_val);
return 0;
}
GATT_TRACE_DEBUG("attr_val->attr_len = %x, attr_val->attr_max_len = %x\n", attr_val->attr_len, attr_val->attr_max_len);
GATT_TRACE_DEBUG("attribute handle = %x\n", p_char_val->handle);
p_char_val->p_value->attr_val.attr_len = attr_val->attr_len;
p_char_val->p_value->attr_val.attr_max_len = attr_val->attr_max_len;
p_char_val->p_value->attr_val.attr_val = GKI_getbuf(attr_val->attr_max_len);
if (p_char_val->p_value->attr_val.attr_val != NULL) {
GATT_TRACE_DEBUG("attribute value not NULL");
memcpy(p_char_val->p_value->attr_val.attr_val, attr_val->attr_val, attr_val->attr_len);
}
} else {
p_char_val->p_value = NULL;
}
return p_char_val->handle;
}
@ -542,24 +579,221 @@ UINT8 gatt_convertchar_descr_type(tBT_UUID *p_descr_uuid)
**
*******************************************************************************/
UINT16 gatts_add_char_descr (tGATT_SVC_DB *p_db, tGATT_PERM perm,
tBT_UUID *p_descr_uuid)
tBT_UUID *p_descr_uuid, tGATT_ATTR_VAL *attr_val, tGATTS_ATTR_CONTROL *control)
{
tGATT_ATTR16 *p_char_dscptr;
GATT_TRACE_DEBUG("gatts_add_char_descr uuid=0x%04x", p_descr_uuid->uu.uuid16);
GATT_TRACE_DEBUG("gatts_add_char_descr uuid=0x%04x\n", p_descr_uuid->uu.uuid16);
/* Add characteristic descriptors */
if ((p_char_dscptr = (tGATT_ATTR16 *)allocate_attr_in_db(p_db,
p_descr_uuid,
perm))
== NULL) {
if ((p_char_dscptr = (tGATT_ATTR16 *)allocate_attr_in_db(p_db, p_descr_uuid, perm)) == NULL) {
GATT_TRACE_DEBUG("gatts_add_char_descr Fail for adding char descriptors.");
return 0;
} else {
if (control != NULL) {
p_char_dscptr->control.auto_rsp = control->auto_rsp;
}
if (attr_val != NULL) {
if (!copy_extra_byte_in_db(p_db, (void **)&p_char_dscptr->p_value, sizeof(tGATT_ATTR_VAL))) {
deallocate_attr_in_db(p_db, p_char_dscptr);
return 0;
}
p_char_dscptr->p_value->attr_val.attr_len = attr_val->attr_len;
p_char_dscptr->p_value->attr_val.attr_max_len = attr_val->attr_max_len;
if (attr_val->attr_val != NULL) {
p_char_dscptr->p_value->attr_val.attr_val = GKI_getbuf(attr_val->attr_max_len);
if (p_char_dscptr->p_value->attr_val.attr_val != NULL) {
memset(p_char_dscptr->p_value->attr_val.attr_val, 0, attr_val->attr_max_len);
memcpy(p_char_dscptr->p_value->attr_val.attr_val, attr_val->attr_val, attr_val->attr_len);
}
}
}
return p_char_dscptr->handle;
}
}
/*******************************************************************************
**
** Function gatts_set_attribute_value
**
** Description This function add the attribute value in the database
**
** Parameter p_db: database pointer.
** attr_handle: the attribute handle
** length: the attribute value length
** value: the pointer to the data to be set to the attribute value in the database
**
** Returns Status of the operation.
**
*******************************************************************************/
tGATT_STATUS gatts_set_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle,
UINT16 length, UINT8 *value)
{
tGATT_ATTR16 *p_cur, *p_next;
if (p_db == NULL) {
GATT_TRACE_DEBUG("gatts_set_attribute_value Fail:p_db is NULL.\n");
return GATT_INVALID_PDU;
}
if (p_db->p_attr_list == NULL) {
GATT_TRACE_DEBUG("gatts_set_attribute_value Fail:p_db->p_attr_list is NULL.\n");
return GATT_INVALID_PDU;
}
p_cur = (tGATT_ATTR16 *) p_db->p_attr_list;
p_next = (tGATT_ATTR16 *) p_cur->p_next;
for (; p_cur != NULL; p_cur = p_next, p_next = (tGATT_ATTR16 *)p_next->p_next) {
if (p_cur->handle == attr_handle) {
if (p_cur->uuid_type == GATT_ATTR_UUID_TYPE_16) {
switch (p_cur->uuid) {
case GATT_UUID_CHAR_DECLARE:
case GATT_UUID_INCLUDE_SERVICE:
return GATT_NOT_FOUND;
default:
if (p_cur->p_value->attr_val.attr_max_len < length) {
GATT_TRACE_ERROR("gatts_set_attribute_vaule failt:Invalid value length");
} else {
memcpy(p_cur->p_value->attr_val.attr_val, value, length);
p_cur->p_value->attr_val.attr_len = length;
}
break;
}
} else {
if (p_cur->p_value->attr_val.attr_max_len < length) {
GATT_TRACE_ERROR("gatts_set_attribute_vaule failt:Invalid value length");
} else {
memcpy(p_cur->p_value->attr_val.attr_val, value, length);
p_cur->p_value->attr_val.attr_len = length;
}
}
break;
}
}
return GATT_SUCCESS;
}
/*******************************************************************************
**
** Function gatts_get_attribute_value
**
** Description This function get the attribute value in the database
**
** Parameter p_db: database pointer.
** attr_handle: the attribute handle
** length: the attribute value length
** value: the pointer to the data to be get to the attribute value in the database
**
** Returns Status of the operation.
**
*******************************************************************************/
tGATT_STATUS gatts_get_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle,
UINT16 *length, UINT8 **value)
{
tGATT_ATTR16 *p_cur, *p_next;
GATT_TRACE_DEBUG("***********%s*************\n", __func__);
GATT_TRACE_DEBUG("attr_handle = %x\n", attr_handle);
if (p_db == NULL) {
GATT_TRACE_ERROR("gatts_get_attribute_value Fail:p_db is NULL.\n");
return GATT_INVALID_PDU;
}
if (p_db->p_attr_list == NULL) {
GATT_TRACE_ERROR("gatts_get_attribute_value Fail:p_db->p_attr_list is NULL.\n");
return GATT_INVALID_PDU;
}
p_cur = (tGATT_ATTR16 *) p_db->p_attr_list;
p_next = (tGATT_ATTR16 *) p_cur->p_next;
for (; p_cur != NULL; p_cur = p_next, p_next = (tGATT_ATTR16 *)p_next->p_next) {
LOG_ERROR("p_ur->handle = %x\n", p_cur->handle);
if (p_cur->handle == attr_handle) {
if (p_cur->uuid_type == GATT_ATTR_UUID_TYPE_16) {
switch (p_cur->uuid) {
case GATT_UUID_CHAR_DECLARE:
case GATT_UUID_INCLUDE_SERVICE:
break;
default:
if (p_cur->p_value->attr_val.attr_len != 0) {
*length = p_cur->p_value->attr_val.attr_len;
*value = p_cur->p_value->attr_val.attr_val;
return GATT_SUCCESS;
} else {
GATT_TRACE_ERROR("gatts_get_attribute_vaule failt:the value length is 0");
return GATT_INVALID_ATTR_LEN;
}
break;
}
} else {
if (p_cur->p_value->attr_val.attr_len != 0) {
*length = p_cur->p_value->attr_val.attr_len;
*value = p_cur->p_value->attr_val.attr_val;
return GATT_SUCCESS;
} else {
GATT_TRACE_ERROR("gatts_get_attribute_vaule failt:the value length is 0");
return GATT_INVALID_ATTR_LEN;
}
}
break;
}
}
return GATT_SUCCESS;
}
BOOLEAN gatts_is_auto_response(UINT16 attr_handle)
{
tGATT_HDL_LIST_ELEM *p_decl = NULL;
BOOLEAN rsp = FALSE;
tGATT_SVC_DB *p_db = NULL;
if ((p_decl = gatt_find_hdl_buffer_by_attr_handle(attr_handle)) == NULL) {
GATT_TRACE_DEBUG("Service not created\n");
return rsp;
}
p_db = &p_decl->svc_db;
tGATT_ATTR16 *p_cur, *p_next;
if (p_db == NULL) {
GATT_TRACE_DEBUG("gatts_get_attribute_value Fail:p_db is NULL.\n");
return rsp;
}
if (p_db->p_attr_list == NULL) {
GATT_TRACE_DEBUG("gatts_get_attribute_value Fail:p_db->p_attr_list is NULL.\n");
return rsp;
}
p_cur = (tGATT_ATTR16 *) p_db->p_attr_list;
p_next = (tGATT_ATTR16 *) p_cur->p_next;
for (; p_cur != NULL && p_next != NULL;
p_cur = p_next, p_next = (tGATT_ATTR16 *)p_next->p_next) {
if (p_cur->handle == attr_handle) {
if (p_cur->p_value != NULL && p_cur->control.auto_rsp == GATT_RSP_BY_STACK) {
rsp = true;
return rsp;
}
}
}
return rsp;
}
/*******************************************************************************/
/* Service Attribute Database Query Utility Functions */
/*******************************************************************************/
@ -617,6 +851,41 @@ tGATT_STATUS gatts_read_attr_value_by_handle(tGATT_TCB *p_tcb,
return status;
}
tGATT_STATUS gatts_write_attr_value_by_handle(tGATT_SVC_DB *p_db,
UINT16 handle, UINT16 offset,
UINT8 *p_value, UINT16 len)
{
tGATT_STATUS status = GATT_NOT_FOUND;
tGATT_ATTR16 *p_attr;
if (p_db && p_db->p_attr_list) {
p_attr = (tGATT_ATTR16 *)p_db->p_attr_list;
while (p_attr && handle >= p_attr->handle) {
if (p_attr->handle == handle ) {
if (p_attr->control.auto_rsp == GATT_RSP_BY_APP) {
return GATT_APP_RSP;
}
if (p_attr->p_value != NULL && (p_attr->p_value->attr_val.attr_max_len >
offset + len)) {
memcpy(p_attr->p_value->attr_val.attr_val + offset, p_value, len);
p_attr->p_value->attr_val.attr_len = len + offset;
return GATT_SUCCESS;
} else {
return GATT_NOT_LONG;
}
}
p_attr = (tGATT_ATTR16 *)p_attr->p_next;
}
}
return status;
}
/*******************************************************************************
**
** Function gatts_read_attr_perm_check
@ -661,6 +930,8 @@ tGATT_STATUS gatts_read_attr_perm_check(tGATT_SVC_DB *p_db,
return status;
}
/*******************************************************************************
**
** Function gatts_write_attr_perm_check
@ -835,7 +1106,7 @@ static void *allocate_attr_in_db(tGATT_SVC_DB *p_db, tBT_UUID *p_uuid, tGATT_PER
UINT16 len = sizeof(tGATT_ATTR128);
if (p_uuid == NULL) {
GATT_TRACE_ERROR("illegal UUID");
GATT_TRACE_ERROR("illegal UUID\n");
return NULL;
}
@ -845,17 +1116,17 @@ static void *allocate_attr_in_db(tGATT_SVC_DB *p_db, tBT_UUID *p_uuid, tGATT_PER
len = sizeof(tGATT_ATTR32);
}
GATT_TRACE_DEBUG("allocate attr %d bytes ", len);
GATT_TRACE_DEBUG("allocate attr %d bytes\n", len);
if (p_db->end_handle <= p_db->next_handle) {
GATT_TRACE_DEBUG("handle space full. handle_max = %d next_handle = %d",
GATT_TRACE_DEBUG("handle space full. handle_max = %d next_handle = %d\n",
p_db->end_handle, p_db->next_handle);
return NULL;
}
if (p_db->mem_free < len) {
if (!allocate_svc_db_buf(p_db)) {
GATT_TRACE_ERROR("allocate_attr_in_db failed, no resources");
GATT_TRACE_ERROR("allocate_attr_in_db failed, no resources\n");
return NULL;
}
}
@ -896,19 +1167,21 @@ static void *allocate_attr_in_db(tGATT_SVC_DB *p_db, tBT_UUID *p_uuid, tGATT_PER
}
if (p_attr16->uuid_type == GATT_ATTR_UUID_TYPE_16) {
GATT_TRACE_DEBUG("=====> handle = [0x%04x] uuid16 = [0x%04x] perm=0x%02x ",
GATT_TRACE_DEBUG("=====> handle = [0x%04x] uuid16 = [0x%04x] perm=0x%02x\n",
p_attr16->handle, p_attr16->uuid, p_attr16->permission);
} else if (p_attr16->uuid_type == GATT_ATTR_UUID_TYPE_32) {
GATT_TRACE_DEBUG("=====> handle = [0x%04x] uuid32 = [0x%08x] perm=0x%02x ",
GATT_TRACE_DEBUG("=====> handle = [0x%04x] uuid32 = [0x%08x] perm=0x%02x\n",
p_attr32->handle, p_attr32->uuid, p_attr32->permission);
} else {
GATT_TRACE_DEBUG("=====> handle = [0x%04x] uuid128 = [0x%02x:0x%02x] perm=0x%02x ",
GATT_TRACE_DEBUG("=====> handle = [0x%04x] uuid128 = [0x%02x:0x%02x] perm=0x%02x\n",
p_attr128->handle, p_attr128->uuid[0], p_attr128->uuid[1],
p_attr128->permission);
}
return (void *)p_attr16;
}
/*******************************************************************************
**
** Function deallocate_attr_in_db
@ -974,7 +1247,7 @@ static BOOLEAN copy_extra_byte_in_db(tGATT_SVC_DB *p_db, void **p_dst, UINT16 le
if (p_db->mem_free < len) {
if (!allocate_svc_db_buf(p_db)) {
GATT_TRACE_ERROR("copy_extra_byte_in_db failed, no resources");
GATT_TRACE_ERROR("copy_extra_byte_in_db failed, no resources\n");
return FALSE;
}
}

View File

@ -508,7 +508,7 @@ static void gatt_le_data_ind (UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf)
GKI_freebuf (p_buf);
if (p_tcb != NULL) {
GATT_TRACE_WARNING ("ATT - Ignored L2CAP data while in state: %d",
GATT_TRACE_WARNING ("ATT - Ignored L2CAP data while in state: %d\n",
gatt_get_ch_state(p_tcb));
}
}
@ -906,10 +906,10 @@ void gatt_data_process (tGATT_TCB *p_tcb, BT_HDR *p_buf)
}
}
} else {
GATT_TRACE_ERROR ("ATT - Rcvd L2CAP data, unknown cmd: 0x%x", op_code);
GATT_TRACE_ERROR ("ATT - Rcvd L2CAP data, unknown cmd: 0x%x\n", op_code);
}
} else {
GATT_TRACE_ERROR ("invalid data length, ignore");
GATT_TRACE_ERROR ("invalid data length, ignore\n");
}
GKI_freebuf (p_buf);

View File

@ -239,7 +239,7 @@ tGATT_STATUS gatt_sr_process_app_rsp (tGATT_TCB *p_tcb, tGATT_IF gatt_if,
tGATT_STATUS ret_code = GATT_SUCCESS;
UNUSED(trans_id);
GATT_TRACE_DEBUG("gatt_sr_process_app_rsp gatt_if=%d", gatt_if);
GATT_TRACE_DEBUG("gatt_sr_process_app_rsp gatt_if=%d\n", gatt_if);
gatt_sr_update_cback_cnt(p_tcb, gatt_if, FALSE, FALSE);
@ -264,7 +264,7 @@ tGATT_STATUS gatt_sr_process_app_rsp (tGATT_TCB *p_tcb, tGATT_IF gatt_if,
if (p_tcb->sr_cmd.p_rsp_msg == NULL) {
p_tcb->sr_cmd.p_rsp_msg = attp_build_sr_msg (p_tcb, (UINT8)(op_code + 1), (tGATT_SR_MSG *)p_msg);
} else {
GATT_TRACE_ERROR("Exception!!! already has respond message");
GATT_TRACE_ERROR("Exception!!! already has respond message\n");
}
}
}
@ -279,7 +279,7 @@ tGATT_STATUS gatt_sr_process_app_rsp (tGATT_TCB *p_tcb, tGATT_IF gatt_if,
gatt_dequeue_sr_cmd(p_tcb);
}
GATT_TRACE_DEBUG("gatt_sr_process_app_rsp ret_code=%d", ret_code);
GATT_TRACE_DEBUG("gatt_sr_process_app_rsp ret_code=%d\n", ret_code);
return ret_code;
}
@ -371,7 +371,7 @@ void gatt_process_read_multi_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U
#if GATT_CONFORMANCE_TESTING == TRUE
if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code) {
GATT_TRACE_DEBUG("Conformance tst: forced err rspvofr ReadMultiple: error status=%d", gatt_cb.err_status);
GATT_TRACE_DEBUG("Conformance tst: forced err rspvofr ReadMultiple: error status=%d\n", gatt_cb.err_status);
STREAM_TO_UINT16(handle, p);
@ -889,10 +889,10 @@ void gatts_process_read_by_type_req(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len,
tGATT_SRV_LIST_ELEM *p_srv = NULL;
reason = gatts_validate_packet_format(op_code, &len, &p_data, &uuid, &s_hdl, &e_hdl);
GATT_TRACE_DEBUG("%s, op_code =%x, len = %x\n", __func__, op_code, len);
#if GATT_CONFORMANCE_TESTING == TRUE
if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code) {
GATT_TRACE_DEBUG("Conformance tst: forced err rsp for ReadByType: error status=%d", gatt_cb.err_status);
GATT_TRACE_DEBUG("Conformance tst: forced err rsp for ReadByType: error status=%d\n", gatt_cb.err_status);
gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, s_hdl, FALSE);
@ -902,7 +902,7 @@ void gatts_process_read_by_type_req(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len,
if (reason == GATT_SUCCESS) {
if ((p_msg = (BT_HDR *)GKI_getbuf(msg_len)) == NULL) {
GATT_TRACE_ERROR("gatts_process_find_info failed. no resources.");
GATT_TRACE_ERROR("gatts_process_find_info failed. no resources.\n");
reason = GATT_NO_RESOURCES;
} else {
@ -959,7 +959,7 @@ void gatts_process_read_by_type_req(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len,
p_msg->offset = L2CAP_MIN_OFFSET;
}
}
if (reason != GATT_SUCCESS) {
if (reason != GATT_SUCCESS && reason != GATT_STACK_RSP) {
if (p_msg) {
GKI_freebuf(p_msg);
}
@ -987,19 +987,32 @@ void gatts_process_read_by_type_req(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len,
void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle,
UINT8 op_code, UINT16 len, UINT8 *p_data)
{
UINT16 buf_len = (UINT16)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET);
tGATTS_DATA sr_data;
UINT32 trans_id;
tGATT_STATUS status;
UINT8 sec_flag, key_size, *p = p_data;
UINT8 sec_flag, key_size, *p = p_data, *p_m;
tGATT_SR_REG *p_sreg;
UINT16 conn_id;
UINT16 conn_id, offset = 0;
BT_HDR *p_msg = NULL;
memset(&sr_data, 0, sizeof(tGATTS_DATA));
if ((p_msg = (BT_HDR *)GKI_getbuf(buf_len)) == NULL) {
GATT_TRACE_ERROR("gatts_process_write_req failed. no resources.\n");
}
memset(p_msg, 0, buf_len);
p_m = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
*p_m ++ = op_code + 1;
p_msg->len = 1;
buf_len = p_tcb->payload_size - 1;
switch (op_code) {
case GATT_REQ_PREPARE_WRITE:
sr_data.write_req.is_prep = TRUE;
STREAM_TO_UINT16(sr_data.write_req.offset, p);
UINT16_TO_STREAM(p_m, sr_data.write_req.is_prep);
offset = sr_data.write_req.offset;
len -= 2;
/* fall through */
case GATT_SIGN_CMD_WRITE:
@ -1012,11 +1025,16 @@ void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle,
case GATT_REQ_WRITE:
if (op_code == GATT_REQ_WRITE || op_code == GATT_REQ_PREPARE_WRITE) {
sr_data.write_req.need_rsp = TRUE;
if(op_code == GATT_REQ_PREPARE_WRITE){
memcpy(p_m, p, len);
p_msg->len += len;
}
}
sr_data.write_req.handle = handle;
sr_data.write_req.len = len;
if (len != 0 && p != NULL) {
memcpy (sr_data.write_req.value, p, len);
}
break;
}
@ -1035,18 +1053,26 @@ void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle,
sec_flag,
key_size);
p_msg->len += len;
if (status == GATT_SUCCESS) {
if ((trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, handle)) != 0) {
p_sreg = &gatt_cb.sr_reg[i_rcb];
conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_sreg->gatt_if);
status = gatts_write_attr_value_by_handle(gatt_cb.sr_reg[i_rcb].p_db,
handle, offset, p, len);
gatt_sr_send_req_callback(conn_id,
trans_id,
GATTS_REQ_TYPE_WRITE,
&sr_data);
if(status == GATT_SUCCESS){
attp_send_sr_msg(p_tcb, p_msg);
}else if(status == GATT_NOT_LONG){
gatt_send_error_rsp (p_tcb, status, op_code, handle, FALSE);
}
status = GATT_PENDING;
} else {
GATT_TRACE_ERROR("max pending command, send error");
GATT_TRACE_ERROR("max pending command, send error\n");
status = GATT_BUSY; /* max pending command, application error */
}
}
@ -1080,7 +1106,7 @@ static void gatts_process_read_req(tGATT_TCB *p_tcb, tGATT_SR_REG *p_rcb, UINT8
UNUSED (len);
if ((p_msg = (BT_HDR *)GKI_getbuf(buf_len)) == NULL) {
GATT_TRACE_ERROR("gatts_process_find_info failed. no resources.");
GATT_TRACE_ERROR("gatts_process_find_info failed. no resources.\n");
reason = GATT_NO_RESOURCES;
} else {
@ -1114,13 +1140,13 @@ static void gatts_process_read_req(tGATT_TCB *p_tcb, tGATT_SR_REG *p_rcb, UINT8
p_msg->len += value_len;
}
if (reason != GATT_SUCCESS) {
if (reason != GATT_SUCCESS && reason != GATT_PENDING) {
if (p_msg) {
GKI_freebuf(p_msg);
}
/* in theroy BUSY is not possible(should already been checked), protected check */
if (reason != GATT_PENDING && reason != GATT_BUSY) {
if (reason != GATT_BUSY) {
gatt_send_error_rsp (p_tcb, reason, op_code, handle, FALSE);
}
} else {
@ -1149,7 +1175,7 @@ void gatts_process_attribute_req (tGATT_TCB *p_tcb, UINT8 op_code,
tGATT_ATTR16 *p_attr;
if (len < 2) {
GATT_TRACE_ERROR("Illegal PDU length, discard request");
GATT_TRACE_ERROR("Illegal PDU length, discard request\n");
status = GATT_INVALID_PDU;
} else {
STREAM_TO_UINT16(handle, p);
@ -1159,7 +1185,7 @@ void gatts_process_attribute_req (tGATT_TCB *p_tcb, UINT8 op_code,
#if GATT_CONFORMANCE_TESTING == TRUE
gatt_cb.handle = handle;
if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code) {
GATT_TRACE_DEBUG("Conformance tst: forced err rsp: error status=%d", gatt_cb.err_status);
GATT_TRACE_DEBUG("Conformance tst: forced err rsp: error status=%d\n", gatt_cb.err_status);
gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, handle, FALSE);
@ -1355,7 +1381,7 @@ void gatt_server_handle_client_req (tGATT_TCB *p_tcb, UINT8 op_code,
gatts_process_primary_service_req (p_tcb, op_code, len, p_data);
break;
case GATT_REQ_FIND_INFO:/* discover char descrptor */
case GATT_REQ_FIND_INFO: /* discover char descrptor */
gatts_process_find_info(p_tcb, op_code, len, p_data);
break;

View File

@ -318,6 +318,34 @@ tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_handle(UINT16 handle)
}
return NULL;
}
/*******************************************************************************
**
** Function gatt_find_hdl_buffer_by_attr_handle
**
** Description Find handle range buffer by attribute handle.
**
** Returns Pointer to the buffer, NULL no buffer available
**
*******************************************************************************/
tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_attr_handle(UINT16 attr_handle)
{
tGATT_HDL_LIST_INFO *p_list_info = &gatt_cb.hdl_list_info;
tGATT_HDL_LIST_ELEM *p_list = NULL;
p_list = p_list_info->p_first;
while (p_list != NULL) {
if (p_list->in_use && (p_list->asgn_range.s_handle <= attr_handle)
&& (p_list->asgn_range.e_handle >= attr_handle)) {
return (p_list);
}
p_list = p_list->p_next;
}
return NULL;
}
/*******************************************************************************
**
** Function gatt_find_hdl_buffer_by_app_id
@ -1476,7 +1504,7 @@ tGATT_REG *gatt_get_regcb (tGATT_IF gatt_if)
p_reg = &gatt_cb.cl_rcb[ii - 1];
if (!p_reg->in_use) {
GATT_TRACE_WARNING("gatt_if found but not in use.");
GATT_TRACE_WARNING("gatt_if found but not in use.\n");
return NULL;
}

View File

@ -36,6 +36,9 @@
#define GATT_GET_SR_REG_PTR(index) (&gatt_cb.sr_reg[(UINT8) (index)]);
#define GATT_TRANS_ID_MAX 0x0fffffff /* 4 MSB is reserved */
#define GATT_RSP_BY_APP 0x00
#define GATT_RSP_BY_STACK 0x01
#define GATT_RSP_DEFAULT GATT_RSP_BY_APP //need to rsp by the app.
/* security action for GATT write and read request */
#define GATT_SEC_NONE 0
@ -154,7 +157,7 @@ typedef union {
tBT_UUID uuid; /* service declaration */
tGATT_CHAR_DECL char_decl; /* characteristic declaration */
tGATT_INCL_SRVC incl_handle; /* included service */
tGATT_ATTR_VAL attr_val;
} tGATT_ATTR_VALUE;
/* Attribute UUID type
@ -167,11 +170,11 @@ typedef UINT8 tGATT_ATTR_UUID_TYPE;
/* 16 bits UUID Attribute in server database
*/
typedef struct {
void *p_next; /* pointer to the next attribute,
either tGATT_ATTR16 or tGATT_ATTR128 */
void *p_next; /* pointer to the next attribute, either tGATT_ATTR16 or tGATT_ATTR128 */
tGATT_ATTR_VALUE *p_value;
tGATT_ATTR_UUID_TYPE uuid_type;
tGATT_PERM permission;
tGATTS_ATTR_CONTROL control;
UINT16 handle;
UINT16 uuid;
} tGATT_ATTR16;
@ -179,11 +182,11 @@ typedef struct {
/* 32 bits UUID Attribute in server database
*/
typedef struct {
void *p_next; /* pointer to the next attribute,
either tGATT_ATTR16, tGATT_ATTR32 or tGATT_ATTR128 */
void *p_next; /* pointer to the next attribute, either tGATT_ATTR16, tGATT_ATTR32 or tGATT_ATTR128 */
tGATT_ATTR_VALUE *p_value;
tGATT_ATTR_UUID_TYPE uuid_type;
tGATT_PERM permission;
tGATTS_ATTR_CONTROL control;
UINT16 handle;
UINT32 uuid;
} tGATT_ATTR32;
@ -192,11 +195,11 @@ typedef struct {
/* 128 bits UUID Attribute in server database
*/
typedef struct {
void *p_next; /* pointer to the next attribute,
either tGATT_ATTR16 or tGATT_ATTR128 */
void *p_next; /* pointer to the next attribute, either tGATT_ATTR16 or tGATT_ATTR128 */
tGATT_ATTR_VALUE *p_value;
tGATT_ATTR_UUID_TYPE uuid_type;
tGATT_PERM permission;
tGATTS_ATTR_CONTROL control;
UINT16 handle;
UINT8 uuid[LEN_UUID_128];
} tGATT_ATTR128;
@ -204,8 +207,7 @@ typedef struct {
/* Service Database definition
*/
typedef struct {
void *p_attr_list; /* pointer to the first attribute,
either tGATT_ATTR16 or tGATT_ATTR128 */
void *p_attr_list; /* pointer to the first attribute, either tGATT_ATTR16 or tGATT_ATTR128 */
UINT8 *p_free_mem; /* Pointer to free memory */
BUFFER_Q svc_buffer; /* buffer queue used for service database */
UINT32 mem_free; /* Memory still available */
@ -579,6 +581,7 @@ extern BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb);
/* reserved handle list */
extern tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_app_id (tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 svc_inst);
extern tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_handle(UINT16 handle);
extern tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_attr_handle(UINT16 attr_handle);
extern tGATT_HDL_LIST_ELEM *gatt_alloc_hdl_buffer(void);
extern void gatt_free_hdl_buffer(tGATT_HDL_LIST_ELEM *p);
extern BOOLEAN gatt_is_last_attribute(tGATT_SRV_LIST_INFO *p_list, tGATT_SRV_LIST_ELEM *p_start, tBT_UUID value);
@ -664,12 +667,27 @@ extern void gatt_set_sec_act(tGATT_TCB *p_tcb, tGATT_SEC_ACTION sec_act);
/* gatt_db.c */
extern BOOLEAN gatts_init_service_db (tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN is_pri, UINT16 s_hdl, UINT16 num_handle);
extern UINT16 gatts_add_included_service (tGATT_SVC_DB *p_db, UINT16 s_handle, UINT16 e_handle, tBT_UUID service);
extern UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm, tGATT_CHAR_PROP property, tBT_UUID *p_char_uuid);
extern UINT16 gatts_add_char_descr (tGATT_SVC_DB *p_db, tGATT_PERM perm, tBT_UUID *p_dscp_uuid);
extern UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm,
tGATT_CHAR_PROP property,
tBT_UUID *p_char_uuid, tGATT_ATTR_VAL *attr_val,
tGATTS_ATTR_CONTROL *control);
extern UINT16 gatts_add_char_descr (tGATT_SVC_DB *p_db, tGATT_PERM perm,
tBT_UUID *p_dscp_uuid, tGATT_ATTR_VAL *attr_val,
tGATTS_ATTR_CONTROL *control);
extern tGATT_STATUS gatts_set_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle,
UINT16 length, UINT8 *value);
extern tGATT_STATUS gatts_get_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle,
UINT16 *length, UINT8 **value);
extern BOOLEAN gatts_is_auto_response(UINT16 attr_handle);
extern tGATT_STATUS gatts_db_read_attr_value_by_type (tGATT_TCB *p_tcb, tGATT_SVC_DB *p_db, UINT8 op_code, BT_HDR *p_rsp, UINT16 s_handle,
UINT16 e_handle, tBT_UUID type, UINT16 *p_len, tGATT_SEC_FLAG sec_flag, UINT8 key_size, UINT32 trans_id, UINT16 *p_cur_handle);
extern tGATT_STATUS gatts_read_attr_value_by_handle(tGATT_TCB *p_tcb, tGATT_SVC_DB *p_db, UINT8 op_code, UINT16 handle, UINT16 offset,
UINT8 *p_value, UINT16 *p_len, UINT16 mtu, tGATT_SEC_FLAG sec_flag, UINT8 key_size, UINT32 trans_id);
extern tGATT_STATUS gatts_write_attr_value_by_handle(tGATT_SVC_DB *p_db,
UINT16 handle, UINT16 offset,
UINT8 *p_value, UINT16 len);
extern tGATT_STATUS gatts_write_attr_perm_check (tGATT_SVC_DB *p_db, UINT8 op_code, UINT16 handle, UINT16 offset, UINT8 *p_data,
UINT16 len, tGATT_SEC_FLAG sec_flag, UINT8 key_size);
extern tGATT_STATUS gatts_read_attr_perm_check(tGATT_SVC_DB *p_db, BOOLEAN is_long, UINT16 handle, tGATT_SEC_FLAG sec_flag, UINT8 key_size);

View File

@ -63,6 +63,8 @@
#define GATT_ENCRYPED_NO_MITM 0x8d
#define GATT_NOT_ENCRYPTED 0x8e
#define GATT_CONGESTED 0x8f
#define GATT_STACK_RSP 0x90
#define GATT_APP_RSP 0x91
/* 0xE0 ~ 0xFC reserved for future use */
#define GATT_CCC_CFG_ERR 0xFD /* Client Characteristic Configuration Descriptor Improperly Configured */
@ -312,6 +314,16 @@ typedef struct {
UINT8 value[GATT_MAX_ATTR_LEN]; /* the actual attribute value */
} tGATT_VALUE;
typedef struct{
UINT16 attr_max_len;
UINT16 attr_len;
UINT8 *attr_val;
}tGATT_ATTR_VAL;
typedef struct{
uint8_t auto_rsp;
}tGATTS_ATTR_CONTROL;
/* Union of the event data which is used in the server respond API to carry the server response information
*/
typedef union {
@ -740,8 +752,9 @@ extern UINT16 GATTS_AddIncludeService (UINT16 service_handle,
** characteristic failed.
**
*******************************************************************************/
extern UINT16 GATTS_AddCharacteristic (UINT16 service_handle, tBT_UUID *char_uuid,
tGATT_PERM perm, tGATT_CHAR_PROP property);
extern UINT16 GATTS_AddCharacteristic (UINT16 service_handle, tBT_UUID *p_char_uuid,
tGATT_PERM perm, tGATT_CHAR_PROP property,
tGATT_ATTR_VAL *attr_val, tGATTS_ATTR_CONTROL *control);
/*******************************************************************************
**
@ -763,7 +776,8 @@ extern UINT16 GATTS_AddCharacteristic (UINT16 service_handle, tBT_UUID *char_uui
**
*******************************************************************************/
extern UINT16 GATTS_AddCharDescriptor (UINT16 service_handle, tGATT_PERM perm,
tBT_UUID *p_descr_uuid);
tBT_UUID *p_descr_uuid, tGATT_ATTR_VAL *attr_val,
tGATTS_ATTR_CONTROL *control);
/*******************************************************************************
**
@ -866,6 +880,39 @@ extern tGATT_STATUS GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id,
tGATT_STATUS status, tGATTS_RSP *p_msg);
/*******************************************************************************
**
** Function GATTS_SetAttributeValue
**
** Description This function sends to set the attribute value .
**
** Parameter attr_handle:the attribute handle
** length: the attribute length
** value: the value to be set to the attribute in the database
**
** Returns GATT_SUCCESS if sucessfully sent; otherwise error code.
**
*******************************************************************************/
tGATT_STATUS GATTS_SetAttributeValue(UINT16 attr_handle, UINT16 length, UINT8 *value);
/*******************************************************************************
**
** Function GATTS_GetAttributeValue
**
** Description This function sends to set the attribute value .
**
** Parameter attr_handle: the attribute handle
** length:the attribute value length in the database
** value: the attribute value out put
**
** Returns GATT_SUCCESS if sucessfully sent; otherwise error code.
**
*******************************************************************************/
tGATT_STATUS GATTS_GetAttributeValue(UINT16 attr_handle, UINT16 *length, UINT8 **value);
/*******************************************************************************/
/* GATT Profile Client Functions */
/*******************************************************************************/

View File

@ -419,7 +419,7 @@ static const UINT8 smp_master_create_local_sec_conn_oob_data[][SMP_SM_NUM_COLS]
static const UINT8 smp_slave_entry_map[][SMP_STATE_MAX] = {
/* state name: Idle WaitApp SecReq Pair Wait Confirm Rand PublKey SCPhs1 Wait Wait SCPhs2 Wait DHKChk Enc Bond CrLocSc
Rsp Pend ReqRsp Cfm Exch Strt Cmtm Nonce Strt DHKChk Pend Pend OobData */
/* PAIR_REQ */{ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* PAIR_REQ */{ 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* PAIR_RSP */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* CONFIRM */{ 0, 4, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* RAND */{ 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },

View File

@ -6,8 +6,7 @@ Overview
BLUFI is a profile based GATT to config ESP32 WIFI to connect/disconnect AP or setup a softap and etc.
Use should concern these things:
1. The event sent from profile. Then you need to do something as the event indicate.
2. Security reference. You can write your own Security functions such as symmetrical encryption/decryption and checksum functions.
Even you can define the "Key Exchange/Negotiation" procedure.
2. Security reference. You can write your own Security functions such as symmetrical encryption/decryption and checksum functions. Even you can define the "Key Exchange/Negotiation" procedure.
Application Example
-------------------

View File

@ -84,6 +84,8 @@ Macros
.. doxygendefine:: ESP_GATT_UUID_SCAN_INT_WINDOW
.. doxygendefine:: ESP_GATT_UUID_SCAN_REFRESH
.. doxygendefine:: ESP_GATT_ILLEGAL_UUID
.. doxygendefine:: ESP_GATT_ILLEGAL_HANDLE
.. doxygendefine:: ESP_GATT_ATTR_HANDLE_MAX
.. doxygendefine:: ESP_GATT_MAX_ATTR_LEN
.. doxygendefine:: ESP_GATT_IF_NONE
@ -106,6 +108,27 @@ Enumerations
Structures
^^^^^^^^^^
.. doxygenstruct:: esp_attr_desc_t
:members:
.. doxygenstruct:: esp_attr_control_t
:members:
.. doxygenstruct:: esp_gatts_attr_db_t
:members:
.. doxygenstruct:: esp_attr_value_t
:members:
.. doxygenstruct:: esp_gatts_incl_svc_desc_t
:members:
.. doxygenstruct:: esp_gatts_incl128_svc_desc_t
:members:
.. doxygenstruct:: esp_gatts_char_desc_t
:members:
.. doxygenstruct:: esp_gatt_value_t
:members:

View File

@ -80,6 +80,9 @@ Structures
.. doxygenstruct:: esp_ble_gatts_cb_param_t::gatts_add_char_descr_evt_param
:members:
.. doxygenstruct:: esp_ble_gatts_cb_param_t::gatts_add_attr_tab_evt_param
:members:
.. doxygenstruct:: esp_ble_gatts_cb_param_t::gatts_delete_evt_param
:members:
@ -101,6 +104,9 @@ Structures
.. doxygenstruct:: esp_ble_gatts_cb_param_t::gatts_rsp_evt_param
:members:
.. doxygenstruct:: esp_ble_gatts_cb_param_t::gatts_set_attr_val_evt_param
:members:
Functions
^^^^^^^^^
@ -109,6 +115,7 @@ Functions
.. doxygenfunction:: esp_ble_gatts_app_register
.. doxygenfunction:: esp_ble_gatts_app_unregister
.. doxygenfunction:: esp_ble_gatts_create_service
.. doxygenfunction:: esp_ble_gatts_create_attr_tab
.. doxygenfunction:: esp_ble_gatts_add_included_service
.. doxygenfunction:: esp_ble_gatts_add_char
.. doxygenfunction:: esp_ble_gatts_add_char_descr
@ -117,6 +124,8 @@ Functions
.. doxygenfunction:: esp_ble_gatts_stop_service
.. doxygenfunction:: esp_ble_gatts_send_indicate
.. doxygenfunction:: esp_ble_gatts_send_response
.. doxygenfunction:: esp_ble_gatts_set_attr_value
.. doxygenfunction:: esp_ble_gatts_get_attr_value
.. doxygenfunction:: esp_ble_gatts_open
.. doxygenfunction:: esp_ble_gatts_close

View File

@ -48,6 +48,19 @@ static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_i
#define TEST_DEVICE_NAME "ESP_GATTS_DEMO"
#define TEST_MANUFACTURER_DATA_LEN 17
#define GATTS_DEMO_CHAR_VAL_LEN_MAX 0x40
uint8_t char1_str[] ={0x11,0x22,0x33};
esp_attr_value_t gatts_demo_char1_val =
{
.attr_max_len = GATTS_DEMO_CHAR_VAL_LEN_MAX,
.attr_len = sizeof(char1_str),
.attr_value = char1_str,
};
static uint8_t test_service_uuid128[32] = {
/* LSB <--------------------------------------------------------------------------------> MSB */
//first uuid, 16bit, [12],[13] is the value
@ -175,20 +188,30 @@ static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_i
esp_ble_gatts_add_char(gl_profile_tab[PROFILE_A_APP_ID].service_handle, &gl_profile_tab[PROFILE_A_APP_ID].char_uuid,
ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY);
ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY,
&gatts_demo_char1_val, NULL);
break;
case ESP_GATTS_ADD_INCL_SRVC_EVT:
break;
case ESP_GATTS_ADD_CHAR_EVT:
case ESP_GATTS_ADD_CHAR_EVT: {
uint16_t length = 0;
const uint8_t *prf_char;
ESP_LOGI(GATTS_TAG, "ADD_CHAR_EVT, status %d, attr_handle %d, service_handle %d\n",
param->add_char.status, param->add_char.attr_handle, param->add_char.service_handle);
gl_profile_tab[PROFILE_A_APP_ID].char_handle = param->add_char.attr_handle;
gl_profile_tab[PROFILE_A_APP_ID].descr_uuid.len = ESP_UUID_LEN_16;
gl_profile_tab[PROFILE_A_APP_ID].descr_uuid.uuid.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG;
esp_ble_gatts_get_attr_value(param->add_char.attr_handle, &length, &prf_char);
ESP_LOGI(GATTS_TAG, "the gatts demo char length = %x\n", length);
for(int i = 0; i < length; i++){
ESP_LOGI(GATTS_TAG, "prf_char[%x] =%x\n",i,prf_char[i]);
}
esp_ble_gatts_add_char_descr(gl_profile_tab[PROFILE_A_APP_ID].service_handle, &gl_profile_tab[PROFILE_A_APP_ID].descr_uuid,
ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE);
ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, NULL, NULL);
break;
}
case ESP_GATTS_ADD_CHAR_DESCR_EVT:
ESP_LOGI(GATTS_TAG, "ADD_DESCR_EVT, status %d, attr_handle %d, service_handle %d\n",
param->add_char.status, param->add_char.attr_handle, param->add_char.service_handle);
@ -269,7 +292,8 @@ static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_i
esp_ble_gatts_add_char(gl_profile_tab[PROFILE_A_APP_ID].service_handle, &gl_profile_tab[PROFILE_A_APP_ID].char_uuid,
ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY);
ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY,
NULL, NULL);
break;
case ESP_GATTS_ADD_INCL_SRVC_EVT:
break;
@ -281,7 +305,8 @@ static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_i
gl_profile_tab[PROFILE_A_APP_ID].descr_uuid.len = ESP_UUID_LEN_16;
gl_profile_tab[PROFILE_A_APP_ID].descr_uuid.uuid.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG;
esp_ble_gatts_add_char_descr(gl_profile_tab[PROFILE_A_APP_ID].service_handle, &gl_profile_tab[PROFILE_A_APP_ID].descr_uuid,
ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE);
ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
NULL, NULL);
break;
case ESP_GATTS_ADD_CHAR_DESCR_EVT:
ESP_LOGI(GATTS_TAG, "ADD_DESCR_EVT, status %d, attr_handle %d, service_handle %d\n",

View File

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

View File

@ -0,0 +1,10 @@
ESP-IDF GATT SERVER create attribute table demo
===============================================
This is the demo for user to use ESP_APIs to create a GATT Server attribute table.
The table is easy to use to create GATT server service database without use each "attribute create" functions.
Actually, there are two way to create server service and characteristics.
One is use the esp_gatts_create_service or esp_ble_gatts_add_char and etc.
The other way is use esp_ble_gatts_create_attr_tab.
The important things: the two ways cannot use in the same service, but can use in different service.

View File

@ -0,0 +1,8 @@
#
# 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.
#

View File

@ -0,0 +1,340 @@
// Copyright 2015-2016 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 "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "bt.h"
#include "bta_api.h"
#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
#include "esp_bt_defs.h"
#include "esp_bt_main.h"
#include "esp_bt_main.h"
#include "gatts_table_creat_demo.h"
#define HEART_PROFILE_NUM 1
#define HEART_PROFILE_APP_IDX 0
#define ESP_HEART_RATE_APP_ID 0x55
#define SAMPLE_DEVICE_NAME "ESP_HEART_RATE"
#define SAMPLE_MANUFACTURER_DATA_LEN 17
#define HEART_RATE_SVC_INST_ID 0
#define GATTS_DEMO_CHAR_VAL_LEN_MAX 0x40
uint8_t char1_str[] ={0x11,0x22,0x33};
uint16_t heart_rate_handle_table[HRS_IDX_NB];
esp_attr_value_t gatts_demo_char1_val =
{
.attr_max_len = GATTS_DEMO_CHAR_VAL_LEN_MAX,
.attr_len = sizeof(char1_str),
.attr_value = char1_str,
};
static uint8_t heart_rate_service_uuid[16] = {
/* LSB <--------------------------------------------------------------------------------> MSB */
//first uuid, 16bit, [12],[13] is the value
0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x18, 0x0D, 0x00, 0x00,
};
static esp_ble_adv_data_t heart_rate_adv_config = {
.set_scan_rsp = false,
.include_name = true,
.include_txpower = true,
.min_interval = 0x20,
.max_interval = 0x40,
.appearance = 0x00,
.manufacturer_len = 0, //TEST_MANUFACTURER_DATA_LEN,
.p_manufacturer_data = NULL, //&test_manufacturer[0],
.service_data_len = 0,
.p_service_data = NULL,
.service_uuid_len = 32,
.p_service_uuid = heart_rate_service_uuid,
.flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
};
static esp_ble_adv_params_t heart_rate_adv_params = {
.adv_int_min = 0x20,
.adv_int_max = 0x40,
.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,
};
struct gatts_profile_inst {
esp_gatts_cb_t gatts_cb;
uint16_t gatts_if;
uint16_t app_id;
uint16_t conn_id;
uint16_t service_handle;
esp_gatt_srvc_id_t service_id;
uint16_t char_handle;
esp_bt_uuid_t char_uuid;
esp_gatt_perm_t perm;
esp_gatt_char_prop_t property;
uint16_t descr_handle;
esp_bt_uuid_t descr_uuid;
};
static void gatts_profile_event_handler(esp_gatts_cb_event_t event,
esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);
/* One gatt-based profile one app_id and one gatts_if, this array will store the gatts_if returned by ESP_GATTS_REG_EVT */
static struct gatts_profile_inst heart_rate_profile_tab[HEART_PROFILE_NUM] = {
[HEART_PROFILE_APP_IDX] = {
.gatts_cb = gatts_profile_event_handler,
.gatts_if = ESP_GATT_IF_NONE, /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */
},
};
/*
* HTPT PROFILE ATTRIBUTES
****************************************************************************************
*/
/// Full HRS Database Description - Used to add attributes into the database
const esp_gatts_attr_db_t heart_rate_gatt_db[HRS_IDX_NB] =
{
// Heart Rate Service Declaration
[HRS_IDX_SVC] = {{ESP_GATT_AUTO_RSP}, {
{ESP_UUID_LEN_16, {ESP_GATT_UUID_PRI_SERVICE}},
ESP_GATT_PERM_READ,
sizeof(heart_rate_svc),
sizeof(heart_rate_svc), (uint8_t *)&heart_rate_svc}},
// Heart Rate Measurement Characteristic Declaration
[HRS_IDX_HR_MEAS_CHAR] = {{ESP_GATT_AUTO_RSP}, {
{ESP_UUID_LEN_16, {ESP_GATT_UUID_CHAR_DECLARE}},
ESP_GATT_PERM_READ,
sizeof(heart_rate_meas_char),
sizeof(heart_rate_meas_char), (uint8_t *)&heart_rate_meas_char}},
// Heart Rate Measurement Characteristic Value
[HRS_IDX_HR_MEAS_VAL] = {{ESP_GATT_AUTO_RSP}, {
{ESP_UUID_LEN_16, {ESP_GATT_HEART_RATE_MEAS}},
ESP_GATT_PERM_READ,
HRPS_HT_MEAS_MAX_LEN,
0, NULL}},
// Heart Rate Measurement Characteristic - Client Characteristic Configuration Descriptor
[HRS_IDX_HR_MEAS_NTF_CFG] = {{ESP_GATT_AUTO_RSP}, {
{ESP_UUID_LEN_16, {ESP_GATT_UUID_CHAR_SRVR_CONFIG}},
ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,
sizeof(uint16_t),
0, NULL}},
// Body Sensor Location Characteristic Declaration
[HRS_IDX_BOBY_SENSOR_LOC_CHAR] = {{ESP_GATT_AUTO_RSP}, {
{ESP_UUID_LEN_16, {ESP_GATT_UUID_CHAR_DECLARE}},
ESP_GATT_PERM_READ,
sizeof(heart_rate_body_sensor_loc_char),
sizeof(heart_rate_body_sensor_loc_char), (uint8_t *)&heart_rate_body_sensor_loc_char}},
// Body Sensor Location Characteristic Value
[HRS_IDX_BOBY_SENSOR_LOC_VAL] = {{ESP_GATT_AUTO_RSP}, {
{ESP_UUID_LEN_16, {ESP_GATT_BODY_SENSOR_LOCATION}},
ESP_GATT_PERM_READ,
sizeof(uint8_t),
0, NULL}},
// Heart Rate Control Point Characteristic Declaration
[HRS_IDX_HR_CTNL_PT_CHAR] = {{ESP_GATT_AUTO_RSP}, {
{ESP_UUID_LEN_16, {ESP_GATT_UUID_CHAR_DECLARE}},
ESP_GATT_PERM_READ,
sizeof(heart_rate_cntl_point_char),
sizeof(heart_rate_cntl_point_char), (uint8_t *)&heart_rate_cntl_point_char}},
// Heart Rate Control Point Characteristic Value
[HRS_IDX_HR_CTNL_PT_VAL] = {{ESP_GATT_AUTO_RSP}, {
{ESP_UUID_LEN_16, {ESP_GATT_HEART_RATE_CNTL_POINT}},
ESP_GATT_PERM_WRITE,
sizeof(uint8_t),
0, NULL}},
};
/*
* Heart Rate PROFILE ATTRIBUTES
****************************************************************************************
*/
/// Heart Rate Sensor Service
const uint16_t heart_rate_svc = ESP_GATT_UUID_HEART_RATE_SVC;
/// Heart Rate Sensor Service - Heart Rate Measurement Characteristic
const esp_gatts_char_desc_t heart_rate_meas_char =
{
.prop = ESP_GATT_CHAR_PROP_BIT_NOTIFY,
.attr_hdl = 0,
.attr_uuid = {ESP_UUID_LEN_16, {ESP_GATT_HEART_RATE_MEAS}},
};
/// Heart Rate Sensor Service -Body Sensor Location characteristic
const esp_gatts_char_desc_t heart_rate_body_sensor_loc_char =
{
.prop = ESP_GATT_CHAR_PROP_BIT_READ,
.attr_hdl = 0,
.attr_uuid = {ESP_UUID_LEN_16, {ESP_GATT_BODY_SENSOR_LOCATION}},
};
/// Heart Rate Sensor Service - Heart Rate Control Point characteristic
const esp_gatts_char_desc_t heart_rate_cntl_point_char =
{
.prop = ESP_GATT_CHAR_PROP_BIT_WRITE,
.attr_hdl = 0,
.attr_uuid = {ESP_UUID_LEN_16, {ESP_GATT_HEART_RATE_CNTL_POINT}},
};
static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
LOG_ERROR("GAP_EVT, event %d\n", event);
switch (event) {
case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
esp_ble_gap_start_advertising(&heart_rate_adv_params);
break;
default:
break;
}
}
static void gatts_profile_event_handler(esp_gatts_cb_event_t event,
esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
{
LOG_ERROR("event = %x\n",event);
switch (event) {
case ESP_GATTS_REG_EVT:
LOG_INFO("%s %d\n", __func__, __LINE__);
esp_ble_gap_set_device_name(SAMPLE_DEVICE_NAME);
LOG_INFO("%s %d\n", __func__, __LINE__);
esp_ble_gap_config_adv_data(&heart_rate_adv_config);
LOG_INFO("%s %d\n", __func__, __LINE__);
esp_ble_gatts_create_attr_tab(heart_rate_gatt_db, gatts_if,
HRS_IDX_NB, HEART_RATE_SVC_INST_ID);
break;
case ESP_GATTS_READ_EVT:
break;
case ESP_GATTS_WRITE_EVT:
break;
case ESP_GATTS_EXEC_WRITE_EVT:
break;
case ESP_GATTS_MTU_EVT:
break;
case ESP_GATTS_CONF_EVT:
break;
case ESP_GATTS_UNREG_EVT:
break;
case ESP_GATTS_DELETE_EVT:
break;
case ESP_GATTS_START_EVT:
break;
case ESP_GATTS_STOP_EVT:
break;
case ESP_GATTS_CONNECT_EVT:
break;
case ESP_GATTS_DISCONNECT_EVT:
break;
case ESP_GATTS_OPEN_EVT:
break;
case ESP_GATTS_CANCEL_OPEN_EVT:
break;
case ESP_GATTS_CLOSE_EVT:
break;
case ESP_GATTS_LISTEN_EVT:
break;
case ESP_GATTS_CONGEST_EVT:
break;
case ESP_GATTS_CREAT_ATTR_TAB_EVT:{
LOG_ERROR("The number handle =%x\n",param->add_attr_tab.num_handle);
if(param->add_attr_tab.num_handle == HRS_IDX_NB){
memcpy(heart_rate_handle_table, param->add_attr_tab.handles,
sizeof(heart_rate_handle_table));
esp_ble_gatts_start_service(heart_rate_handle_table[HRS_IDX_SVC]);
}
break;
}
default:
break;
}
}
static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
esp_ble_gatts_cb_param_t *param)
{
LOG_INFO("EVT %d, gatts if %d\n", event, gatts_if);
/* If event is register event, store the gatts_if for each profile */
if (event == ESP_GATTS_REG_EVT) {
if (param->reg.status == ESP_GATT_OK) {
heart_rate_profile_tab[HEART_PROFILE_APP_IDX].gatts_if = gatts_if;
} else {
LOG_INFO("Reg app failed, app_id %04x, status %d\n",
param->reg.app_id,
param->reg.status);
return;
}
}
do {
int idx;
for (idx = 0; idx < HEART_PROFILE_NUM; idx++) {
if (gatts_if == ESP_GATT_IF_NONE || /* ESP_GATT_IF_NONE, not specify a certain gatt_if, need to call every profile cb function */
gatts_if == heart_rate_profile_tab[idx].gatts_if) {
if (heart_rate_profile_tab[idx].gatts_cb) {
heart_rate_profile_tab[idx].gatts_cb(event, gatts_if, param);
}
}
}
} while (0);
}
void app_main()
{
esp_err_t ret;
esp_bt_controller_init();
LOG_INFO("%s init bluetooth\n", __func__);
ret = esp_bluedroid_init();
if (ret) {
LOG_ERROR("%s init bluetooth failed\n", __func__);
return;
}
ret = esp_bluedroid_enable();
if (ret) {
LOG_ERROR("%s enable bluetooth failed\n", __func__);
return;
}
esp_ble_gatts_register_callback(gatts_event_handler);
esp_ble_gap_register_callback(gap_event_handler);
esp_ble_gatts_app_register(ESP_HEART_RATE_APP_ID);
return;
}

View File

@ -0,0 +1,57 @@
// Copyright 2015-2016 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* DEFINES
****************************************************************************************
*/
#define HRPS_HT_MEAS_MAX_LEN (13)
#define HRPS_MANDATORY_MASK (0x0F)
#define HRPS_BODY_SENSOR_LOC_MASK (0x30)
#define HRPS_HR_CTNL_PT_MASK (0xC0)
///Attributes State Machine
enum
{
HRS_IDX_SVC,
HRS_IDX_HR_MEAS_CHAR,
HRS_IDX_HR_MEAS_VAL,
HRS_IDX_HR_MEAS_NTF_CFG,
HRS_IDX_BOBY_SENSOR_LOC_CHAR,
HRS_IDX_BOBY_SENSOR_LOC_VAL,
HRS_IDX_HR_CTNL_PT_CHAR,
HRS_IDX_HR_CTNL_PT_VAL,
HRS_IDX_NB,
};
extern const esp_gatts_attr_db_t heart_rate_gatt_db[HRS_IDX_NB];
/// Heart Rate Sensor Service - only one instance for now
extern const uint16_t heart_rate_svc;
extern const esp_gatts_char_desc_t heart_rate_meas_char;
extern const esp_gatts_char_desc_t heart_rate_body_sensor_loc_char;
extern const esp_gatts_char_desc_t heart_rate_cntl_point_char;

View File

@ -0,0 +1,14 @@
# Override some defaults so BT stack is enabled
# in this example
#
# BT config
#
CONFIG_BT_ENABLED=y
#
# ESP32-specific config
#
CONFIG_ESP32_ENABLE_STACK_BT=y
# CONFIG_ESP32_ENABLE_STACK_NONE is not set
CONFIG_MEMMAP_BT=y