* @brief Attribute description (used to create database)
*/
typedef struct
- {
- esp_bt_uuid_t uuid; /*!< Element UUID */
+ {
+ uint16_t uuid_length; /*!< UUID length */
+ uint8_t *uuid_p; /*!< UUID value */
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;
+ uint8_t *value; /*!< Element value array*/
+ } esp_attr_desc_t;
/**
#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;
+} esp_attr_control_t;
/**
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;
+ esp_attr_desc_t att_desc; /*!< The attribue type*/
+} esp_gatts_attr_db_t;
/**
{
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;
+ uint8_t *attr_value; /*!< the pointer to attribute value */
+} esp_attr_value_t;
/**
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 */
+} esp_gatts_incl_svc_desc_t; /*!< Gatt include service entry element */
/**
* @brief Gatt include 128 bit service entry element
{
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 */
+} 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
uint16_t handle; /*!< The attribute handle */
uint16_t offset; /*!< Offset of the value, if the value is too long */
bool is_long; /*!< The value is too long or not */
+ bool need_rsp; /*!< The read operation need to do response */
} read; /*!< Gatt server callback param of ESP_GATTS_READ_EVT */
+
/**
* @brief ESP_GATTS_WRITE_EVT
*/
* @brief ESP_GATTS_RESPONSE_EVT
*/
struct gatts_rsp_evt_param {
- esp_gatt_status_t status; /*!< Operation status */
+ 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 */
UINT16 attr_id = 0;
tBTA_GATTS cb_data;
- tGATT_ATTR_VAL *p_attr_val = NULL;
+ 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.attr_val.attr_max_len != 0){
+ p_attr_val = &p_msg->api_add_char.attr_val;
}
- if (p_msg->api_add_char_descr.control.auto_rsp != 0) {
- p_control = &p_msg->api_add_char_descr.control;
+ if(p_msg->api_add_char.control.auto_rsp != 0){
+ p_control = &p_msg->api_add_char.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,
} else {
cb_data.add_result.status = BTA_GATT_ERROR;
}
+ if((p_attr_val != NULL) && (p_attr_val->attr_val != NULL)){
+ GKI_freebuf(p_attr_val->attr_val);
+ }
if (p_rcb->p_cback) {
(*p_rcb->p_cback)(BTA_GATTS_ADD_CHAR_EVT, &cb_data);
} else {
cb_data.add_result.status = BTA_GATT_ERROR;
}
+ if((p_attr_val != NULL) && (p_attr_val->attr_val != NULL)){
+ GKI_freebuf(p_attr_val->attr_val);
+ }
if (p_rcb->p_cback) {
(*p_rcb->p_cback)(BTA_GATTS_ADD_CHAR_DESCR_EVT, &cb_data);
tBTA_GATTS_ATTR_CONTROL *control)
{
tBTA_GATTS_API_ADD_DESCR *p_buf;
- 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);
- }
+ UINT16 value_len = 0;
- if ((p_buf = (tBTA_GATTS_API_ADD_DESCR *) GKI_getbuf(len)) != NULL) {
- memset(p_buf, 0, len);
+ if ((p_buf = (tBTA_GATTS_API_ADD_DESCR *) GKI_getbuf(sizeof(tBTA_GATTS_API_ADD_DESCR))) != NULL) {
+ memset(p_buf, 0, sizeof(tBTA_GATTS_API_ADD_DESCR));
p_buf->hdr.event = BTA_GATTS_API_ADD_DESCR_EVT;
p_buf->hdr.layer_specific = service_id;
p_buf->perm = perm;
+ if(control != NULL){
+ p_buf->control.auto_rsp = control->auto_rsp;
+ }
+
if (p_descr_uuid) {
memcpy(&p_buf->descr_uuid, p_descr_uuid, sizeof(tBT_UUID));
}
- if(attr_val->attr_len != 0) {
+ if(attr_val != NULL){
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);
+ p_buf->attr_val.attr_max_len = attr_val->attr_max_len;
+ value_len = attr_val->attr_len;
+ if (value_len != 0){
+ p_buf->attr_val.attr_val = (uint8_t*)GKI_getbuf(value_len);
+ if(p_buf->attr_val.attr_val != NULL){
+ memcpy(p_buf->attr_val.attr_val, attr_val->attr_val, value_len);
+ }
+ else{
+ APPL_TRACE_ERROR("Allocate fail for %s\n", __func__);
+
+ }
+ }
}
- if(control != NULL) {
- p_buf->control.auto_rsp = control->auto_rsp;
- }
bta_sys_sendmsg(p_buf);
}
return;
+
}
/*******************************************************************************
-**
-** Function BTA_GATTS_DeleteService
-**
-** Description This function is called to delete a service. When this is done,
-** a callback event BTA_GATTS_DELETE_EVT is report with the status.
-**
-** Parameters service_id: service_id to be deleted.
-**
+ **
+ ** Function BTA_GATTS_DeleteService
+ **
+ ** Description This function is called to delete a service. When this is done,
+ ** a callback event BTA_GATTS_DELETE_EVT is report with the status.
+ **
+ ** Parameters service_id: service_id to be deleted.
+ **
** Returns returns none.
**
*******************************************************************************/
}
}
+static inline void btc_gatts_uuid_format_convert(esp_bt_uuid_t* dest_uuid, uint16_t src_uuid_len, uint8_t* src_uuid_p)
+{
+ dest_uuid->len = src_uuid_len;
+ if(src_uuid_len == ESP_UUID_LEN_16){
+ dest_uuid->uuid.uuid16 = src_uuid_p[0] + (src_uuid_p[1]<<8);
+ }
+ else if(src_uuid_len == ESP_UUID_LEN_32){
+ dest_uuid->uuid.uuid32 = src_uuid_p[0] + (src_uuid_p[1]<<8) + (src_uuid_p[2]<<16) + (src_uuid_p[3]<<24);
+ }
+ else if(src_uuid_len == ESP_UUID_LEN_128){
+ memcpy(dest_uuid->uuid.uuid128, src_uuid_p, src_uuid_len);
+ }
+ else{
+ LOG_ERROR("%s wrong uuid length %d\n", __func__, src_uuid_len);
+ }
+
+}
+
+
void btc_gatts_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
{
btc_ble_gatts_args_t *dst = (btc_ble_gatts_args_t *) p_dest;
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;
+ if(gatts_attr_db[i].att_desc.uuid_length== ESP_UUID_LEN_16){
+ uuid = (gatts_attr_db[i].att_desc.uuid_p[1] << 8) + (gatts_attr_db[i].att_desc.uuid_p[0]);
}
future_p = future_new();
if (future_p == NULL) {
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);
+ btc_gatts_uuid_format_convert(&esp_srvc_id.id.uuid,gatts_attr_db[i].att_desc.uuid_length,
+ gatts_attr_db[i].att_desc.uuid_p);
+
+ 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);
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);
+ btc_gatts_uuid_format_convert(&esp_srvc_id.id.uuid,gatts_attr_db[i].att_desc.uuid_length,
+ gatts_attr_db[i].att_desc.uuid_p);
+ 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) {
uint16_t svc_hal = 0;
tBT_UUID bta_char_uuid;
tGATT_ATTR_VAL attr_val;
+ esp_bt_uuid_t uuid_temp;
tBTA_GATT_PERM perm;
tBTA_GATTS_ATTR_CONTROL control;
+ uint8_t char_property;
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){
+ if((gatts_attr_db[i].att_desc.value) == NULL){
+ LOG_ERROR("%s Characteristic declaration should not be NULL\n", __func__);
+ }
+ else{
+ char_property = (uint8_t)(*(uint8_t*)(gatts_attr_db[i].att_desc.value));
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);
+ btc_gatts_uuid_format_convert(&uuid_temp, gatts_attr_db[i+1].att_desc.uuid_length,gatts_attr_db[i+1].att_desc.uuid_p);
+ btc_to_bta_uuid(&bta_char_uuid, &uuid_temp);
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);
+ perm, char_property, &attr_val, &control);
if (future_await(future_p) == FUTURE_FAIL) {
LOG_ERROR("%s failed\n", __func__);
return;
}
- }
+ }
}
break;
case ESP_GATT_UUID_RPT_REF_DESCR:{
uint16_t svc_hal = btc_creat_tab_env.svc_start_hdl;
tBT_UUID bta_char_uuid;
+ esp_bt_uuid_t uuid_temp;
tGATT_ATTR_VAL attr_val;
tBTA_GATT_PERM perm = gatts_attr_db[i].att_desc.perm;
tBTA_GATTS_ATTR_CONTROL control;
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);
+ btc_gatts_uuid_format_convert(&uuid_temp, gatts_attr_db[i].att_desc.uuid_length,
+ gatts_attr_db[i].att_desc.uuid_p);
+ btc_to_bta_uuid(&bta_char_uuid, &uuid_temp);
control.auto_rsp = gatts_attr_db[i].attr_control.auto_rsp;
BTA_GATTS_AddCharDescriptor(svc_hal, perm, &bta_char_uuid, &attr_val, &control);
param.read.offset = p_data->req_data.p_data->read_req.offset;
param.read.is_long = p_data->req_data.p_data->read_req.is_long;
+ param.read.need_rsp = p_data->req_data.p_data->read_req.need_rsp;
btc_gatts_cb_to_app(ESP_GATTS_READ_EVT, gatts_if, ¶m);
break;
}
static BOOLEAN gatts_db_add_service_declaration(tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN is_pri);
static tGATT_STATUS gatts_send_app_read_request(tGATT_TCB *p_tcb, UINT8 op_code,
- UINT16 handle, UINT16 offset, UINT32 trans_id);
+ UINT16 handle, UINT16 offset, UINT32 trans_id, BOOLEAN need_rsp);
/*******************************************************************************
**
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);
- }
+ len = (mtu >= p_attr16->p_value->attr_val.attr_len) ? (p_attr16->p_value->attr_val.attr_len) : mtu;
+ ARRAY_TO_STREAM(p, value, len);
}
status = GATT_STACK_RSP;
status = read_attr_value ((void *)p_attr, 0, &p, FALSE, (UINT16)(*p_len - 2), &len, sec_flag, key_size);
if (status == GATT_PENDING || status == GATT_STACK_RSP) {
- status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, 0, trans_id);
+ BOOLEAN need_rsp = (status != GATT_STACK_RSP);
+ status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, 0, trans_id, need_rsp);
/* one callback at a time */
break;
tGATT_STATUS gatts_set_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle,
UINT16 length, UINT8 *value)
{
- tGATT_ATTR16 *p_cur, *p_next;
+ tGATT_ATTR16 *p_cur;
if (p_db == NULL) {
GATT_TRACE_DEBUG("gatts_set_attribute_value Fail:p_db is NULL.\n");
}
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) {
+ while (p_cur != NULL) {
if (p_cur->handle == attr_handle) {
+
if (p_cur->uuid_type == GATT_ATTR_UUID_TYPE_16) {
switch (p_cur->uuid) {
+ case GATT_UUID_PRI_SERVICE:
+ case GATT_UUID_SEC_SERVICE:
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");
+ return GATT_INVALID_ATTR_LEN;
} else {
memcpy(p_cur->p_value->attr_val.attr_val, value, length);
p_cur->p_value->attr_val.attr_len = length;
memcpy(p_cur->p_value->attr_val.attr_val, value, length);
p_cur->p_value->attr_val.attr_len = length;
}
+
}
+
break;
+
}
+
+ p_cur = p_cur->p_next;
}
return GATT_SUCCESS;
tGATT_STATUS gatts_get_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle,
UINT16 *length, UINT8 **value)
{
- tGATT_ATTR16 *p_cur, *p_next;
+ tGATT_ATTR16 *p_cur;
GATT_TRACE_DEBUG("***********%s*************\n", __func__);
GATT_TRACE_DEBUG("attr_handle = %x\n", attr_handle);
if (p_db == NULL) {
}
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) {
+ while (p_cur != NULL) {
LOG_ERROR("p_ur->handle = %x\n", p_cur->handle);
if (p_cur->handle == attr_handle) {
*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");
+ GATT_TRACE_ERROR("gatts_get_attribute_vaule failed:the value length is 0");
return GATT_INVALID_ATTR_LEN;
}
}
+ p_cur = p_cur->p_next;
}
- return GATT_SUCCESS;
+ return GATT_NOT_FOUND;
}
BOOLEAN gatts_is_auto_response(UINT16 attr_handle)
(BOOLEAN)(op_code == GATT_REQ_READ_BLOB),
mtu, p_len, sec_flag, key_size);
- if (status == GATT_PENDING) {
- status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, offset, trans_id);
+ if ((status == GATT_PENDING) || (status == GATT_STACK_RSP)) {
+ BOOLEAN need_rsp = (status != GATT_STACK_RSP);
+ status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, offset, trans_id, need_rsp);
}
break;
}
}
}
+
return status;
}
return GATT_APP_RSP;
}
- if (p_attr->p_value != NULL && (p_attr->p_value->attr_val.attr_max_len >
+ 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;
**
*******************************************************************************/
static tGATT_STATUS gatts_send_app_read_request(tGATT_TCB *p_tcb, UINT8 op_code,
- UINT16 handle, UINT16 offset, UINT32 trans_id)
+ UINT16 handle, UINT16 offset, UINT32 trans_id, BOOLEAN need_rsp)
{
tGATTS_DATA sr_data;
UINT8 i_rcb;
sr_data.read_req.handle = handle;
sr_data.read_req.is_long = (BOOLEAN)(op_code == GATT_REQ_READ_BLOB);
sr_data.read_req.offset = offset;
+ sr_data.read_req.need_rsp = need_rsp;
gatt_sr_send_req_callback(conn_id,
trans_id, GATTS_REQ_TYPE_READ, &sr_data);
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, *p_m;
- tGATT_SR_REG *p_sreg;
- UINT16 conn_id, offset = 0;
- BT_HDR *p_msg = NULL;
+ 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, *p_m;
+ tGATT_SR_REG *p_sreg;
+ 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) {
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;
+ UINT16_TO_STREAM(p_m, sr_data.write_req.is_prep);
+ offset = sr_data.write_req.offset;
len -= 2;
- /* fall through */
+ /* fall through */
case GATT_SIGN_CMD_WRITE:
if (op_code == GATT_SIGN_CMD_WRITE) {
GATT_TRACE_DEBUG("Write CMD with data sigining" );
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;
- }
+ 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;
}
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);
+ status = gatts_write_attr_value_by_handle(gatt_cb.sr_reg[i_rcb].p_db,
+ handle, offset, p, len);
+ if((sr_data.write_req.need_rsp == TRUE) && (status == GATT_APP_RSP)){
+ sr_data.write_req.need_rsp = TRUE;
+ status = GATT_PENDING;
+ }
+
+ else{
+ sr_data.write_req.need_rsp = FALSE;
+ }
+
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;
+ trans_id,
+ GATTS_REQ_TYPE_WRITE,
+ &sr_data);
+
+ if(status == GATT_SUCCESS){
+ attp_send_sr_msg(p_tcb, p_msg);
+ gatt_dequeue_sr_cmd(p_tcb);
+ }
+
} else {
GATT_TRACE_ERROR("max pending command, send error\n");
status = GATT_BUSY; /* max pending command, application error */
}
/* in theroy BUSY is not possible(should already been checked), protected check */
- if (status != GATT_PENDING && status != GATT_BUSY &&
+ if (status != GATT_PENDING && status != GATT_BUSY && status != GATT_SUCCESS &&
(op_code == GATT_REQ_PREPARE_WRITE || op_code == GATT_REQ_WRITE)) {
gatt_send_error_rsp (p_tcb, status, op_code, handle, FALSE);
+ gatt_dequeue_sr_cmd(p_tcb);
}
return;
}
/*******************************************************************************
-**
-** Function gatts_process_read_req
-**
-** Description This function is called to process the read request
-** from client.
-**
-** Returns void
-**
-*******************************************************************************/
+ **
+ ** Function gatts_process_read_req
+ **
+ ** Description This function is called to process the read request
+ ** from client.
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
static void gatts_process_read_req(tGATT_TCB *p_tcb, tGATT_SR_REG *p_rcb, UINT8 op_code,
UINT16 handle, UINT16 len, UINT8 *p_data)
{
p_msg->len += value_len;
}
- if (reason != GATT_SUCCESS && reason != GATT_PENDING) {
+
+ if (reason != GATT_SUCCESS && reason != GATT_PENDING && reason != GATT_STACK_RSP) {
if (p_msg) {
GKI_freebuf(p_msg);
}
/* in theroy BUSY is not possible(should already been checked), protected check */
if (reason != GATT_BUSY) {
gatt_send_error_rsp (p_tcb, reason, op_code, handle, FALSE);
+ gatt_dequeue_sr_cmd(p_tcb);
}
} else {
attp_send_sr_msg(p_tcb, p_msg);
+ gatt_dequeue_sr_cmd(p_tcb);
}
}
/* otherwise, ignore the pkt */
} else {
switch (op_code) {
- case GATT_REQ_READ_BY_GRP_TYPE: /* discover primary services */
- case GATT_REQ_FIND_TYPE_VALUE: /* discover service by UUID */
+ case GATT_REQ_READ_BY_GRP_TYPE: /* discover primary services */
+ case GATT_REQ_FIND_TYPE_VALUE: /* discover service by UUID */
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;
- case GATT_REQ_READ_BY_TYPE: /* read characteristic value, char descriptor value */
+ case GATT_REQ_READ_BY_TYPE: /* read characteristic value, char descriptor value */
/* discover characteristic, discover char by UUID */
gatts_process_read_by_type_req(p_tcb, op_code, len, p_data);
break;
- case GATT_REQ_READ: /* read char/char descriptor value */
+ case GATT_REQ_READ: /* read char/char descriptor value */
case GATT_REQ_READ_BLOB:
- case GATT_REQ_WRITE: /* write char/char descriptor value */
+ case GATT_REQ_WRITE: /* write char/char descriptor value */
case GATT_CMD_WRITE:
case GATT_SIGN_CMD_WRITE:
case GATT_REQ_PREPARE_WRITE:
UINT16 handle;
UINT16 offset;
BOOLEAN is_long;
+ BOOLEAN need_rsp;
} tGATT_READ_REQ;
/* write request data */
Macros
^^^^^^
+
+.. doxygendefine:: ESP_GATT_UUID_IMMEDIATE_ALERT_SVC
+.. doxygendefine:: ESP_GATT_UUID_LINK_LOSS_SVC
+.. doxygendefine:: ESP_GATT_UUID_TX_POWER_SVC
+.. doxygendefine:: ESP_GATT_UUID_CURRENT_TIME_SVC
+.. doxygendefine:: ESP_GATT_UUID_REF_TIME_UPDATE_SVC
+.. doxygendefine:: ESP_GATT_UUID_NEXT_DST_CHANGE_SVC
+.. doxygendefine:: ESP_GATT_UUID_GLUCOSE_SVC
+.. doxygendefine:: ESP_GATT_UUID_HEALTH_THERMOM_SVC
+.. doxygendefine:: ESP_GATT_UUID_DEVICE_INFO_SVC
+.. doxygendefine:: ESP_GATT_UUID_HEART_RATE_SVC
+.. doxygendefine:: ESP_GATT_UUID_PHONE_ALERT_STATUS_SVC
+.. doxygendefine:: ESP_GATT_UUID_BATTERY_SERVICE_SVC
+.. doxygendefine:: ESP_GATT_UUID_BLOOD_PRESSURE_SVC
+.. doxygendefine:: ESP_GATT_UUID_ALERT_NTF_SVC
+.. doxygendefine:: ESP_GATT_UUID_HID_SVC
+.. doxygendefine:: ESP_GATT_UUID_SCAN_PARAMETERS_SVC
+.. doxygendefine:: ESP_GATT_UUID_RUNNING_SPEED_CADENCE_SVC
+.. doxygendefine:: ESP_GATT_UUID_CYCLING_SPEED_CADENCE_SVC
+.. doxygendefine:: ESP_GATT_UUID_CYCLING_POWER_SVC
+.. doxygendefine:: ESP_GATT_UUID_LOCATION_AND_NAVIGATION_SVC
+.. doxygendefine:: ESP_GATT_UUID_USER_DATA_SVC
+.. doxygendefine:: ESP_GATT_UUID_WEIGHT_SCALE_SVC
.. doxygendefine:: ESP_GATT_UUID_PRI_SERVICE
.. doxygendefine:: ESP_GATT_UUID_SEC_SERVICE
.. doxygendefine:: ESP_GATT_UUID_INCLUDE_SERVICE
.. doxygendefine:: ESP_GATT_UUID_HID_BT_KB_INPUT
.. doxygendefine:: ESP_GATT_UUID_HID_BT_KB_OUTPUT
.. doxygendefine:: ESP_GATT_UUID_HID_BT_MOUSE_INPUT
+.. doxygendefine:: ESP_GATT_HEART_RATE_MEAS
+.. doxygendefine:: ESP_GATT_BODY_SENSOR_LOCATION
+.. doxygendefine:: ESP_GATT_HEART_RATE_CNTL_POINT
.. doxygendefine:: ESP_GATT_UUID_BATTERY_LEVEL
.. doxygendefine:: ESP_GATT_UUID_SC_CONTROL_POINT
.. doxygendefine:: ESP_GATT_UUID_SENSOR_LOCATION
.. doxygendefine:: ESP_GATT_ILLEGAL_HANDLE
.. doxygendefine:: ESP_GATT_ATTR_HANDLE_MAX
.. doxygendefine:: ESP_GATT_MAX_ATTR_LEN
+.. doxygendefine:: ESP_GATT_RSP_BY_APP
+.. doxygendefine:: ESP_GATT_AUTO_RSP
.. doxygendefine:: ESP_GATT_IF_NONE
Type Definitions
.. doxygenstruct:: esp_gatts_incl128_svc_desc_t
:members:
-.. doxygenstruct:: esp_gatts_char_desc_t
- :members:
-
.. doxygenstruct:: esp_gatt_value_t
:members:
.. 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:
.. doxygenstruct:: esp_ble_gatts_cb_param_t::gatts_rsp_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_set_attr_val_evt_param
:members:
****************************************************************************************
*/
+
+/*
+ * Heart Rate PROFILE ATTRIBUTES
+ ****************************************************************************************
+ */
+
+/// Heart Rate Sensor Service
+static const uint16_t heart_rate_svc = ESP_GATT_UUID_HEART_RATE_SVC;
+
+#define CHAR_DECLARATION_SIZE (sizeof(uint8_t))
+static const uint16_t primary_service_uuid = ESP_GATT_UUID_PRI_SERVICE;
+static const uint16_t character_declaration_uuid = ESP_GATT_UUID_CHAR_DECLARE;
+static const uint16_t character_client_config_uuid = ESP_GATT_UUID_CHAR_CLIENT_CONFIG;
+static const uint8_t char_prop_notify = ESP_GATT_CHAR_PROP_BIT_NOTIFY;
+static const uint8_t char_prop_read = ESP_GATT_CHAR_PROP_BIT_READ;
+static const uint8_t char_prop_read_write = ESP_GATT_CHAR_PROP_BIT_WRITE|ESP_GATT_CHAR_PROP_BIT_READ;
+
+/// Heart Rate Sensor Service - Heart Rate Measurement Characteristic, notify
+static const uint16_t heart_rate_meas_uuid = ESP_GATT_HEART_RATE_MEAS;
+static const uint8_t heart_measurement_ccc[2] ={ 0x00, 0x00};
+
+
+/// Heart Rate Sensor Service -Body Sensor Location characteristic, read
+static const uint16_t body_sensor_location_uuid = ESP_GATT_BODY_SENSOR_LOCATION;
+static const uint8_t body_sensor_loc_val[1] = {0x00};
+
+
+/// Heart Rate Sensor Service - Heart Rate Control Point characteristic, write&read
+static const uint16_t heart_rate_ctrl_point = ESP_GATT_HEART_RATE_CNTL_POINT;
+static const uint8_t heart_ctrl_point[1] = {0x00};
+
/// Full HRS Database Description - Used to add attributes into the database
-const esp_gatts_attr_db_t heart_rate_gatt_db[HRS_IDX_NB] =
+static 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}},
+ [HRS_IDX_SVC] =
+ {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ,
+ sizeof(uint16_t), 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}},
+ [HRS_IDX_HR_MEAS_CHAR] =
+ {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
+ CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_notify}},
+
// 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}},
+ [HRS_IDX_HR_MEAS_VAL] =
+ {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&heart_rate_meas_uuid, 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}},
+ [HRS_IDX_HR_MEAS_NTF_CFG] =
+ {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,
+ sizeof(uint16_t),sizeof(heart_measurement_ccc), (uint8_t *)heart_measurement_ccc}},
// 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}},
+ [HRS_IDX_BOBY_SENSOR_LOC_CHAR] =
+ {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
+ CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read}},
// 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}},
+ [HRS_IDX_BOBY_SENSOR_LOC_VAL] =
+ {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&body_sensor_location_uuid, ESP_GATT_PERM_READ,
+ sizeof(uint8_t), sizeof(body_sensor_loc_val), (uint8_t *)body_sensor_loc_val}},
// 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}},
+ [HRS_IDX_HR_CTNL_PT_CHAR] =
+ {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
+ CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_write}},
// 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}},
+ [HRS_IDX_HR_CTNL_PT_VAL] =
+ {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&heart_rate_ctrl_point, ESP_GATT_PERM_WRITE|ESP_GATT_PERM_READ,
+ sizeof(uint8_t), sizeof(heart_ctrl_point), (uint8_t *)heart_ctrl_point}},
};
-/*
- * 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)
{
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)
-{\r
+{
LOG_ERROR("event = %x\n",event);
switch (event) {
case ESP_GATTS_REG_EVT:
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;