1 /*
2 * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <string.h>
8
9 #include "bta/bta_gatt_api.h"
10
11 #include "btc/btc_task.h"
12 #include "btc/btc_manage.h"
13 #include "btc_gatts.h"
14 #include "btc_gatt_util.h"
15 #include "osi/future.h"
16 #include "osi/allocator.h"
17 #include "btc/btc_main.h"
18 #include "esp_gatts_api.h"
19
20 #if (GATTS_INCLUDED == TRUE)
21
22 #define A2C_GATTS_EVT(_bta_event) (_bta_event) //BTA TO BTC EVT
23 #define C2A_GATTS_EVT(_btc_event) (_btc_event) //BTC TO BTA EVT
24
25 #if GATT_DYNAMIC_MEMORY == FALSE
26 static esp_btc_creat_tab_t btc_creat_tab_env;
27 #else
28 esp_btc_creat_tab_t *btc_creat_tab_env_ptr;
29 #endif
30
31 static esp_gatt_status_t btc_gatts_check_valid_attr_tab(esp_gatts_attr_db_t *gatts_attr_db,
32 uint8_t max_nb_attr);
33
btc_gatts_cb_to_app(esp_gatts_cb_event_t event,esp_gatt_if_t gatts_if,esp_ble_gatts_cb_param_t * param)34 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)
35 {
36 esp_gatts_cb_t btc_gatts_cb = (esp_gatts_cb_t)btc_profile_cb_get(BTC_PID_GATTS);
37 if (btc_gatts_cb) {
38 btc_gatts_cb(event, gatts_if, param);
39 }
40 }
41
btc_gatts_uuid_format_convert(esp_bt_uuid_t * dest_uuid,uint16_t src_uuid_len,uint8_t * src_uuid_p)42 static inline void btc_gatts_uuid_format_convert(esp_bt_uuid_t* dest_uuid, uint16_t src_uuid_len, uint8_t* src_uuid_p)
43 {
44 dest_uuid->len = src_uuid_len;
45 if(src_uuid_len == ESP_UUID_LEN_16){
46 dest_uuid->uuid.uuid16 = src_uuid_p[0] + (src_uuid_p[1]<<8);
47 }
48 else if(src_uuid_len == ESP_UUID_LEN_32){
49 dest_uuid->uuid.uuid32 = src_uuid_p[0] + (src_uuid_p[1]<<8) + (src_uuid_p[2]<<16) + (src_uuid_p[3]<<24);
50 }
51 else if(src_uuid_len == ESP_UUID_LEN_128){
52 memcpy(dest_uuid->uuid.uuid128, src_uuid_p, src_uuid_len);
53 }
54 else{
55 BTC_TRACE_ERROR("%s wrong uuid length %d\n", __func__, src_uuid_len);
56 }
57
58 }
59
60
btc_gatts_arg_deep_copy(btc_msg_t * msg,void * p_dest,void * p_src)61 void btc_gatts_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
62 {
63 btc_ble_gatts_args_t *dst = (btc_ble_gatts_args_t *) p_dest;
64 btc_ble_gatts_args_t *src = (btc_ble_gatts_args_t *)p_src;
65
66 switch (msg->act) {
67 case BTC_GATTS_ACT_SEND_INDICATE: {
68 if (src->send_ind.value && (src->send_ind.value_len > 0)) {
69 dst->send_ind.value = (uint8_t *) osi_malloc(src->send_ind.value_len);
70 if (dst->send_ind.value) {
71 memcpy(dst->send_ind.value, src->send_ind.value, src->send_ind.value_len);
72 } else {
73 BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act);
74 }
75 } else {
76 dst->send_ind.value = NULL;
77 if (src->send_ind.value) {
78 BTC_TRACE_ERROR("%s %d, invalid length", __func__, msg->act);
79 }
80 }
81 break;
82 }
83 case BTC_GATTS_ACT_SEND_RESPONSE: {
84 if (src->send_rsp.rsp) {
85 dst->send_rsp.rsp = (esp_gatt_rsp_t *) osi_malloc(sizeof(esp_gatt_rsp_t));
86 if (dst->send_rsp.rsp) {
87 memcpy(dst->send_rsp.rsp, src->send_rsp.rsp, sizeof(esp_gatt_rsp_t));
88 } else {
89 BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act);
90 }
91 }
92 break;
93
94 }
95 case BTC_GATTS_ACT_ADD_CHAR: {
96 if (src->add_char.char_val.attr_value && (src->add_char.char_val.attr_len > 0)) {
97 dst->add_char.char_val.attr_value = (uint8_t *) osi_malloc(src->add_char.char_val.attr_len);
98 if (dst->add_char.char_val.attr_value) {
99 memcpy(dst->add_char.char_val.attr_value, src->add_char.char_val.attr_value,
100 src->add_char.char_val.attr_len);
101 } else {
102 BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act);
103 }
104 } else {
105 dst->add_char.char_val.attr_value = NULL;
106 if (src->add_char.char_val.attr_value) {
107 BTC_TRACE_ERROR("%s %d, invalid length", __func__, msg->act);
108 }
109 }
110 break;
111 }
112 case BTC_GATTS_ACT_ADD_CHAR_DESCR: {
113 if (src->add_descr.descr_val.attr_value && (src->add_descr.descr_val.attr_len > 0)) {
114 dst->add_descr.descr_val.attr_value = (uint8_t *) osi_malloc(src->add_descr.descr_val.attr_len);
115 if (dst->add_descr.descr_val.attr_value) {
116 memcpy(dst->add_descr.descr_val.attr_value, src->add_descr.descr_val.attr_value,
117 src->add_descr.descr_val.attr_len);
118 } else {
119 BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act);
120 }
121 } else {
122 dst->add_descr.descr_val.attr_value = NULL;
123 if (src->add_descr.descr_val.attr_value) {
124 BTC_TRACE_ERROR("%s %d, invalid length", __func__, msg->act);
125 }
126 }
127 break;
128 }
129 case BTC_GATTS_ACT_CREATE_ATTR_TAB: {
130 uint8_t num_attr = src->create_attr_tab.max_nb_attr;
131 if (src->create_attr_tab.gatts_attr_db && (num_attr > 0)) {
132 dst->create_attr_tab.gatts_attr_db = (esp_gatts_attr_db_t *) osi_malloc(sizeof(esp_gatts_attr_db_t) * num_attr);
133 if (dst->create_attr_tab.gatts_attr_db) {
134 memcpy(dst->create_attr_tab.gatts_attr_db, src->create_attr_tab.gatts_attr_db,
135 sizeof(esp_gatts_attr_db_t) * num_attr);
136 } else {
137 BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act);
138 }
139 } else {
140 BTC_TRACE_ERROR("%s %d, NULL data", __func__, msg->act);
141 }
142 break;
143 }
144 case BTC_GATTS_ACT_SET_ATTR_VALUE: {
145 if (src->set_attr_val.value && (src->set_attr_val.length > 0)) {
146 dst->set_attr_val.value = (uint8_t *) osi_malloc(src->set_attr_val.length);
147 if (dst->set_attr_val.value) {
148 memcpy(dst->set_attr_val.value, src->set_attr_val.value, src->set_attr_val.length);
149 } else {
150 BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act);
151 }
152 } else {
153 dst->set_attr_val.value = NULL;
154 if (src->set_attr_val.value) {
155 BTC_TRACE_ERROR("%s %d, invalid length", __func__, msg->act);
156 } else {
157 BTC_TRACE_WARNING("%s %d, NULL value", __func__, msg->act);
158 }
159 }
160 break;
161 }
162 default:
163 BTC_TRACE_DEBUG("%s Unhandled deep copy %d\n", __func__, msg->act);
164 break;
165 }
166
167 }
168
btc_gatts_arg_deep_free(btc_msg_t * msg)169 void btc_gatts_arg_deep_free(btc_msg_t *msg)
170 {
171 btc_ble_gatts_args_t *arg = (btc_ble_gatts_args_t *)msg->arg;
172
173 switch (msg->act) {
174 case BTC_GATTS_ACT_SEND_INDICATE: {
175 if (arg->send_ind.value) {
176 osi_free(arg->send_ind.value);
177 }
178 break;
179 }
180 case BTC_GATTS_ACT_SEND_RESPONSE: {
181 if (arg->send_rsp.rsp) {
182 osi_free(arg->send_rsp.rsp);
183 }
184 break;
185 }
186 case BTC_GATTS_ACT_ADD_CHAR:{
187 if (arg->add_char.char_val.attr_value != NULL) {
188 osi_free(arg->add_char.char_val.attr_value);
189 }
190 break;
191 }
192 case BTC_GATTS_ACT_ADD_CHAR_DESCR:{
193 if (arg->add_descr.descr_val.attr_value != NULL){
194 osi_free(arg->add_descr.descr_val.attr_value);
195 }
196 break;
197 }
198 case BTC_GATTS_ACT_CREATE_ATTR_TAB:{
199 if (arg->create_attr_tab.gatts_attr_db != NULL){
200 osi_free(arg->create_attr_tab.gatts_attr_db);
201 }
202 break;
203 }
204 case BTC_GATTS_ACT_SET_ATTR_VALUE:{
205 if (arg->set_attr_val.value != NULL){
206 osi_free(arg->set_attr_val.value);
207 }
208 }
209 break;
210
211 default:
212 BTC_TRACE_DEBUG("%s Unhandled deep free %d\n", __func__, msg->act);
213 break;
214 }
215
216 }
217
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)218 static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db,
219 esp_gatt_if_t gatts_if,
220 uint8_t max_nb_attr,
221 uint8_t srvc_inst_id)
222 {
223 uint16_t uuid = 0;
224 future_t *future_p;
225 esp_ble_gatts_cb_param_t param;
226 param.add_attr_tab.status = ESP_GATT_OK;
227 param.add_attr_tab.num_handle = max_nb_attr;
228
229 if (param.add_attr_tab.status != ESP_GATT_OK) {
230 btc_gatts_cb_to_app(ESP_GATTS_CREAT_ATTR_TAB_EVT, gatts_if, ¶m);
231 //reset the env after sent the data to app
232 memset(&btc_creat_tab_env, 0, sizeof(esp_btc_creat_tab_t));
233 return;
234 }
235
236 // Check the attribute table is valid or not
237 if ((param.add_attr_tab.status = btc_gatts_check_valid_attr_tab(gatts_attr_db, max_nb_attr)) != ESP_GATT_OK) {
238 //sent the callback event to the application
239 btc_gatts_cb_to_app(ESP_GATTS_CREAT_ATTR_TAB_EVT, gatts_if, ¶m);
240 return;
241 }
242
243
244 //set the attribute table create service flag to true
245 btc_creat_tab_env.is_tab_creat_svc = true;
246 btc_creat_tab_env.num_handle = max_nb_attr;
247 for(int i = 0; i < max_nb_attr; i++){
248 if(gatts_attr_db[i].att_desc.uuid_length == ESP_UUID_LEN_16){
249 uuid = (gatts_attr_db[i].att_desc.uuid_p[1] << 8) + (gatts_attr_db[i].att_desc.uuid_p[0]);
250 }
251 else{
252 continue;
253 }
254 future_p = future_new();
255 if (future_p == NULL) {
256 BTC_TRACE_ERROR("%s failed:no mem\n", __func__);
257 return ;
258 }
259 btc_creat_tab_env.complete_future = future_p;
260 btc_creat_tab_env.handle_idx = i;
261 switch(uuid)
262 {
263 case ESP_GATT_UUID_PRI_SERVICE:{
264 tBTA_GATT_SRVC_ID srvc_id;
265 esp_gatt_srvc_id_t esp_srvc_id;
266
267 esp_srvc_id.id.inst_id = srvc_inst_id;
268 btc_gatts_uuid_format_convert(&esp_srvc_id.id.uuid,gatts_attr_db[i].att_desc.length,
269 gatts_attr_db[i].att_desc.value);
270
271 btc_to_bta_srvc_id(&srvc_id, &esp_srvc_id);
272 if (btc_creat_tab_env.is_use_svc != true) {
273 BTA_GATTS_CreateService(gatts_if, &srvc_id.id.uuid,
274 srvc_inst_id, max_nb_attr, true);
275 btc_creat_tab_env.is_use_svc = true;
276 } else {
277 BTC_TRACE_ERROR("Each service table can only created one primary service.");
278 param.add_attr_tab.status = ESP_GATT_ERROR;
279 btc_gatts_cb_to_app(ESP_GATTS_CREAT_ATTR_TAB_EVT, gatts_if, ¶m);
280 //reset the env after sent the data to app
281 memset(&btc_creat_tab_env, 0, sizeof(esp_btc_creat_tab_t));
282 return;
283 }
284
285 if (future_await(future_p) == FUTURE_FAIL) {
286 BTC_TRACE_ERROR("%s failed\n", __func__);
287 return;
288 }
289 break;
290 }
291 case ESP_GATT_UUID_SEC_SERVICE:{
292 tBTA_GATT_SRVC_ID srvc_id = {0};
293 esp_gatt_srvc_id_t esp_srvc_id;
294
295 esp_srvc_id.id.inst_id = srvc_inst_id;
296 btc_gatts_uuid_format_convert(&esp_srvc_id.id.uuid,gatts_attr_db[i].att_desc.length,
297 gatts_attr_db[i].att_desc.value);
298 btc_to_bta_srvc_id(&srvc_id, &esp_srvc_id);
299 if (btc_creat_tab_env.is_use_svc != true) {
300 BTA_GATTS_CreateService(gatts_if, &srvc_id.id.uuid,
301 srvc_inst_id, max_nb_attr, false);
302 btc_creat_tab_env.is_use_svc = true;
303 } else {
304 BTC_TRACE_ERROR("Each service table can only created one secondary service.");
305 param.add_attr_tab.status = ESP_GATT_ERROR;
306 btc_gatts_cb_to_app(ESP_GATTS_CREAT_ATTR_TAB_EVT, gatts_if, ¶m);
307 //reset the env after sent the data to app
308 memset(&btc_creat_tab_env, 0, sizeof(esp_btc_creat_tab_t));
309 return;
310 }
311 if (future_await(future_p) == FUTURE_FAIL) {
312 BTC_TRACE_ERROR("%s failed\n", __func__);
313 return;
314 }
315 break;
316 }
317 case ESP_GATT_UUID_INCLUDE_SERVICE:{
318 esp_gatts_incl_svc_desc_t *incl_svc_desc = (esp_gatts_incl_svc_desc_t *)gatts_attr_db[i].att_desc.value;
319
320 if(incl_svc_desc!= NULL){
321 if(btc_creat_tab_env.svc_start_hdl != 0){
322 BTA_GATTS_AddIncludeService(btc_creat_tab_env.svc_start_hdl,
323 incl_svc_desc->start_hdl);
324
325 if (future_await(future_p) == FUTURE_FAIL) {
326 BTC_TRACE_ERROR("%s failed\n", __func__);
327 return;
328 }
329 }
330 }
331 break;
332 }
333 case ESP_GATT_UUID_CHAR_DECLARE:{
334 uint16_t svc_hal = 0;
335 tBT_UUID bta_char_uuid;
336 tGATT_ATTR_VAL attr_val;
337 esp_bt_uuid_t uuid_temp;
338 tBTA_GATT_PERM perm;
339 tBTA_GATTS_ATTR_CONTROL control;
340 uint8_t char_property;
341
342 if(btc_creat_tab_env.svc_start_hdl != 0){
343 svc_hal = btc_creat_tab_env.svc_start_hdl;
344 if((gatts_attr_db[i].att_desc.value) == NULL){
345 BTC_TRACE_ERROR("%s Characteristic declaration should not be NULL\n", __func__);
346 }
347 else{
348 char_property = (uint8_t)(*(uint8_t*)(gatts_attr_db[i].att_desc.value));
349 perm = gatts_attr_db[i+1].att_desc.perm;
350 attr_val.attr_len = gatts_attr_db[i+1].att_desc.length;
351 attr_val.attr_max_len = gatts_attr_db[i+1].att_desc.max_length;
352 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);
353 btc_to_bta_uuid(&bta_char_uuid, &uuid_temp);
354 attr_val.attr_val = gatts_attr_db[i+1].att_desc.value;
355 control.auto_rsp = gatts_attr_db[i+1].attr_control.auto_rsp;
356 BTA_GATTS_AddCharacteristic (svc_hal, &bta_char_uuid,
357 perm, char_property, &attr_val, &control);
358
359 if (future_await(future_p) == FUTURE_FAIL) {
360 BTC_TRACE_ERROR("%s failed\n", __func__);
361 return;
362 }
363 }
364 }
365
366 break;
367 }
368 case ESP_GATT_UUID_CHAR_EXT_PROP:
369 case ESP_GATT_UUID_CHAR_DESCRIPTION:
370 case ESP_GATT_UUID_CHAR_CLIENT_CONFIG:
371 case ESP_GATT_UUID_CHAR_SRVR_CONFIG:
372 case ESP_GATT_UUID_CHAR_PRESENT_FORMAT:
373 case ESP_GATT_UUID_CHAR_AGG_FORMAT:
374 case ESP_GATT_UUID_CHAR_VALID_RANGE:
375 case ESP_GATT_UUID_EXT_RPT_REF_DESCR:
376 case ESP_GATT_UUID_RPT_REF_DESCR:
377 case ESP_GATT_UUID_NUM_DIGITALS_DESCR:
378 case ESP_GATT_UUID_VALUE_TRIGGER_DESCR:
379 case ESP_GATT_UUID_ENV_SENSING_CONFIG_DESCR:
380 case ESP_GATT_UUID_ENV_SENSING_MEASUREMENT_DESCR:
381 case ESP_GATT_UUID_ENV_SENSING_TRIGGER_DESCR:
382 case ESP_GATT_UUID_TIME_TRIGGER_DESCR: {
383 uint16_t svc_hal = btc_creat_tab_env.svc_start_hdl;
384 tBT_UUID bta_char_uuid;
385 esp_bt_uuid_t uuid_temp;
386 tGATT_ATTR_VAL attr_val;
387 tBTA_GATT_PERM perm = gatts_attr_db[i].att_desc.perm;
388 tBTA_GATTS_ATTR_CONTROL control;
389
390 if(svc_hal != 0){
391 attr_val.attr_len = gatts_attr_db[i].att_desc.length;
392 attr_val.attr_max_len = gatts_attr_db[i].att_desc.max_length;
393 attr_val.attr_val = gatts_attr_db[i].att_desc.value;
394 btc_gatts_uuid_format_convert(&uuid_temp, gatts_attr_db[i].att_desc.uuid_length,
395 gatts_attr_db[i].att_desc.uuid_p);
396 btc_to_bta_uuid(&bta_char_uuid, &uuid_temp);
397 control.auto_rsp = gatts_attr_db[i].attr_control.auto_rsp;
398 BTA_GATTS_AddCharDescriptor(svc_hal, perm, &bta_char_uuid, &attr_val, &control);
399
400 if (future_await(future_p) == FUTURE_FAIL) {
401 BTC_TRACE_ERROR("%s failed\n", __func__);
402 return;
403 }
404 }
405 break;
406 }
407 default:
408 future_free(future_p);
409 break;
410 }
411
412
413 }
414
415 param.add_attr_tab.handles = btc_creat_tab_env.handles;
416 memcpy(¶m.add_attr_tab.svc_uuid, &btc_creat_tab_env.svc_uuid, sizeof(esp_bt_uuid_t));
417
418 param.add_attr_tab.svc_inst_id = srvc_inst_id;
419
420 btc_gatts_cb_to_app(ESP_GATTS_CREAT_ATTR_TAB_EVT, gatts_if, ¶m);
421 //reset the env after sent the data to app
422 memset(&btc_creat_tab_env, 0, sizeof(esp_btc_creat_tab_t));
423
424 //set the flag value to false after the service is created.
425 btc_creat_tab_env.is_tab_creat_svc = false;
426 }
427
btc_gatts_check_valid_attr_tab(esp_gatts_attr_db_t * gatts_attr_db,uint8_t max_nb_attr)428 static esp_gatt_status_t btc_gatts_check_valid_attr_tab(esp_gatts_attr_db_t *gatts_attr_db,
429 uint8_t max_nb_attr)
430 {
431 uint8_t svc_num = 0;
432 uint16_t uuid = 0;
433
434 for(int i = 0; i < max_nb_attr; i++) {
435 if(gatts_attr_db[i].att_desc.uuid_length != ESP_UUID_LEN_16) {
436 continue;
437 }
438
439 uuid = (gatts_attr_db[i].att_desc.uuid_p[1] << 8) + (gatts_attr_db[i].att_desc.uuid_p[0]);
440 switch(uuid) {
441 case ESP_GATT_UUID_PRI_SERVICE:
442 case ESP_GATT_UUID_SEC_SERVICE:
443 if (++svc_num > 1) {
444 BTC_TRACE_ERROR("Each service table can only created one primary service or secondary service.");
445 return ESP_GATT_ERROR;
446 }
447 break;
448 case ESP_GATT_UUID_INCLUDE_SERVICE: {
449 esp_gatts_incl_svc_desc_t *svc_desc = (esp_gatts_incl_svc_desc_t *)gatts_attr_db[i].att_desc.value;
450 if(svc_desc == NULL) {
451 BTC_TRACE_ERROR("%s, The include service attribute should not be NULL.", __func__);
452 return ESP_GATT_INVALID_PDU;
453 } else if((svc_desc->start_hdl == 0) || (svc_desc->end_hdl == 0) ||
454 (svc_desc->start_hdl == svc_desc->end_hdl)) {
455 BTC_TRACE_ERROR("%s, The include service attribute handle is invalid, start_hanlde = %d, end_handle = %d",\
456 __func__, svc_desc->start_hdl, svc_desc->end_hdl);
457 return ESP_GATT_INVALID_HANDLE;
458 }
459 break;
460 }
461 case ESP_GATT_UUID_CHAR_DECLARE:
462 if((gatts_attr_db[i].att_desc.value) == NULL) {
463 BTC_TRACE_ERROR("%s, Characteristic declaration should not be NULL.", __func__);
464 return ESP_GATT_INVALID_PDU;
465 }
466
467 if(gatts_attr_db[i+1].att_desc.uuid_length != ESP_UUID_LEN_16 &&
468 gatts_attr_db[i+1].att_desc.uuid_length != ESP_UUID_LEN_32 &&
469 gatts_attr_db[i+1].att_desc.uuid_length != ESP_UUID_LEN_128) {
470 BTC_TRACE_ERROR("%s, The Charateristic uuid length = %d is invalid", __func__,\
471 gatts_attr_db[i+1].att_desc.uuid_length);
472 return ESP_GATT_INVALID_ATTR_LEN;
473 }
474
475 if(gatts_attr_db[i+1].att_desc.uuid_length == ESP_UUID_LEN_16) {
476 uuid = (gatts_attr_db[i+1].att_desc.uuid_p[1] << 8) + (gatts_attr_db[i+1].att_desc.uuid_p[0]);
477 if(uuid == ESP_GATT_UUID_CHAR_DECLARE || uuid == ESP_GATT_UUID_CHAR_EXT_PROP ||
478 uuid == ESP_GATT_UUID_CHAR_DESCRIPTION || uuid == ESP_GATT_UUID_CHAR_CLIENT_CONFIG ||
479 uuid == ESP_GATT_UUID_CHAR_SRVR_CONFIG || uuid == ESP_GATT_UUID_CHAR_PRESENT_FORMAT ||
480 uuid == ESP_GATT_UUID_CHAR_AGG_FORMAT || uuid == ESP_GATT_UUID_CHAR_VALID_RANGE ||
481 uuid == ESP_GATT_UUID_EXT_RPT_REF_DESCR || uuid == ESP_GATT_UUID_RPT_REF_DESCR) {
482 BTC_TRACE_ERROR("%s, The charateristic value uuid = %d is invalid", __func__, uuid);
483 return ESP_GATT_INVALID_PDU;
484 }
485 }
486 break;
487 default:
488 break;
489 }
490 }
491
492 return ESP_GATT_OK;
493 }
494
btc_gatts_get_attr_value(uint16_t attr_handle,uint16_t * length,uint8_t ** value)495 esp_gatt_status_t btc_gatts_get_attr_value(uint16_t attr_handle, uint16_t *length, uint8_t **value)
496 {
497
498 return BTA_GetAttributeValue(attr_handle, length, value);
499 }
500
501
btc_gatts_cb_param_copy_req(btc_msg_t * msg,void * p_dest,void * p_src)502 static void btc_gatts_cb_param_copy_req(btc_msg_t *msg, void *p_dest, void *p_src)
503 {
504 uint16_t event = msg->act;
505
506 tBTA_GATTS *p_dest_data = (tBTA_GATTS *) p_dest;
507 tBTA_GATTS *p_src_data = (tBTA_GATTS *) p_src;
508
509 if (!p_src_data || !p_dest_data) {
510 return;
511 }
512
513 // Copy basic structure first
514 memcpy(p_dest_data, p_src_data, sizeof(tBTA_GATTS));
515
516 // Allocate buffer for request data if necessary
517 switch (event) {
518 case BTA_GATTS_READ_EVT:
519 case BTA_GATTS_WRITE_EVT:
520 case BTA_GATTS_EXEC_WRITE_EVT:
521 case BTA_GATTS_MTU_EVT:
522 p_dest_data->req_data.p_data = osi_malloc(sizeof(tBTA_GATTS_REQ_DATA));
523 if (p_dest_data->req_data.p_data != NULL) {
524 memcpy(p_dest_data->req_data.p_data, p_src_data->req_data.p_data,
525 sizeof(tBTA_GATTS_REQ_DATA));
526 } else {
527 BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act);
528 }
529 break;
530
531 default:
532 break;
533 }
534 }
535
btc_gatts_cb_param_copy_free(btc_msg_t * msg,tBTA_GATTS * p_data)536 static void btc_gatts_cb_param_copy_free(btc_msg_t *msg, tBTA_GATTS *p_data)
537 {
538 uint16_t event = msg->act;
539
540 switch (event) {
541 case BTA_GATTS_READ_EVT:
542 case BTA_GATTS_WRITE_EVT:
543 case BTA_GATTS_EXEC_WRITE_EVT:
544 case BTA_GATTS_MTU_EVT:
545 if (p_data && p_data->req_data.p_data) {
546 osi_free(p_data->req_data.p_data);
547 }
548 break;
549 case BTA_GATTS_CONF_EVT:
550 break;
551 default:
552 break;
553 }
554 }
555
556
btc_gatts_inter_cb(tBTA_GATTS_EVT event,tBTA_GATTS * p_data)557 static void btc_gatts_inter_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
558 {
559 bt_status_t status;
560 btc_msg_t msg = {0};
561
562 msg.sig = BTC_SIG_API_CB;
563 msg.pid = BTC_PID_GATTS;
564 msg.act = event;
565 if(btc_creat_tab_env.is_tab_creat_svc && btc_creat_tab_env.complete_future) {
566 switch(event) {
567 case BTA_GATTS_CREATE_EVT: {
568 //save the service handle to the btc module after used
569 //the attribute table method to creat a service
570 bta_to_btc_uuid(&btc_creat_tab_env.svc_uuid, &p_data->create.uuid);
571 uint8_t index = btc_creat_tab_env.handle_idx;
572 btc_creat_tab_env.svc_start_hdl = p_data->create.service_id;
573 btc_creat_tab_env.handles[index] = p_data->create.service_id;
574 break;
575 }
576 case BTA_GATTS_ADD_INCL_SRVC_EVT: {
577 uint8_t index = btc_creat_tab_env.handle_idx;
578 btc_creat_tab_env.handles[index] = p_data->add_result.attr_id;
579 break;
580 }
581 case BTA_GATTS_ADD_CHAR_EVT: {
582 uint8_t index = btc_creat_tab_env.handle_idx;
583 btc_creat_tab_env.handles[index] = p_data->add_result.attr_id - 1;
584 btc_creat_tab_env.handles[index+1] = p_data->add_result.attr_id;
585 break;
586 }
587 case BTA_GATTS_ADD_CHAR_DESCR_EVT: {
588 uint8_t index = btc_creat_tab_env.handle_idx;
589 btc_creat_tab_env.handles[index] = p_data->add_result.attr_id;
590 break;
591 }
592 default:
593 break;
594 }
595
596 future_ready(btc_creat_tab_env.complete_future, FUTURE_SUCCESS);
597 return;
598 }
599 status = btc_transfer_context(&msg, p_data,
600 sizeof(tBTA_GATTS), btc_gatts_cb_param_copy_req);
601
602 if (status != BT_STATUS_SUCCESS) {
603 BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__);
604 }
605 }
606
btc_gatts_call_handler(btc_msg_t * msg)607 void btc_gatts_call_handler(btc_msg_t *msg)
608 {
609 btc_ble_gatts_args_t *arg = (btc_ble_gatts_args_t *)msg->arg;
610
611 switch (msg->act) {
612 case BTC_GATTS_ACT_APP_REGISTER: {
613 tBT_UUID uuid;
614
615 uuid.len = LEN_UUID_16;
616 uuid.uu.uuid16 = arg->app_reg.app_id;
617
618 BTA_GATTS_AppRegister(&uuid, btc_gatts_inter_cb);
619
620 break;
621 }
622 case BTC_GATTS_ACT_APP_UNREGISTER:
623 BTA_GATTS_AppDeregister(arg->app_unreg.gatts_if);
624 break;
625 case BTC_GATTS_ACT_CREATE_SERVICE: {
626 tBTA_GATT_SRVC_ID srvc_id;
627 btc_to_bta_srvc_id(&srvc_id, &arg->create_srvc.service_id);
628 BTA_GATTS_CreateService(arg->create_srvc.gatts_if, &srvc_id.id.uuid,
629 srvc_id.id.inst_id, arg->create_srvc.num_handle,
630 srvc_id.is_primary);
631 break;
632 }
633 case BTC_GATTS_ACT_CREATE_ATTR_TAB:
634 btc_gatts_act_create_attr_tab(arg->create_attr_tab.gatts_attr_db,
635 arg->create_attr_tab.gatts_if,
636 arg->create_attr_tab.max_nb_attr,
637 arg->create_attr_tab.srvc_inst_id);
638 break;
639 case BTC_GATTS_ACT_DELETE_SERVICE:
640 BTA_GATTS_DeleteService(arg->delete_srvc.service_handle);
641 break;
642 case BTC_GATTS_ACT_START_SERVICE:
643 BTA_GATTS_StartService(arg->start_srvc.service_handle, BTA_GATT_TRANSPORT_LE);
644 break;
645 case BTC_GATTS_ACT_STOP_SERVICE:
646 BTA_GATTS_StopService(arg->stop_srvc.service_handle);
647 break;
648 case BTC_GATTS_ACT_ADD_INCLUDE_SERVICE:
649 BTA_GATTS_AddIncludeService(arg->add_incl_srvc.service_handle, arg->add_incl_srvc.included_service_handle);
650 break;
651 case BTC_GATTS_ACT_ADD_CHAR: {
652 tBT_UUID uuid;
653 btc_to_bta_uuid(&uuid, &arg->add_char.char_uuid);
654
655 BTA_GATTS_AddCharacteristic(arg->add_char.service_handle, &uuid,
656 arg->add_char.perm, arg->add_char.property,
657 (tGATT_ATTR_VAL *)&arg->add_char.char_val,
658 (tBTA_GATTS_ATTR_CONTROL *)&arg->add_char.attr_control);
659 break;
660 }
661 case BTC_GATTS_ACT_ADD_CHAR_DESCR: {
662 tBT_UUID uuid;
663 btc_to_bta_uuid(&uuid, &arg->add_descr.descr_uuid);
664 BTA_GATTS_AddCharDescriptor(arg->add_descr.service_handle, arg->add_descr.perm, &uuid,
665 (tBTA_GATT_ATTR_VAL *)&arg->add_descr.descr_val,
666 (tBTA_GATTS_ATTR_CONTROL *)&arg->add_descr.attr_control);
667 break;
668 }
669 case BTC_GATTS_ACT_SEND_INDICATE:
670 BTA_GATTS_HandleValueIndication(arg->send_ind.conn_id, arg->send_ind.attr_handle,
671 arg->send_ind.value_len, arg->send_ind.value, arg->send_ind.need_confirm);
672 break;
673 case BTC_GATTS_ACT_SEND_RESPONSE: {
674 esp_ble_gatts_cb_param_t param;
675 esp_gatt_rsp_t *p_rsp = arg->send_rsp.rsp;
676
677 if (p_rsp) {
678 tBTA_GATTS_RSP rsp_struct;
679 btc_to_bta_response(&rsp_struct, p_rsp);
680 BTA_GATTS_SendRsp(arg->send_rsp.conn_id, arg->send_rsp.trans_id,
681 arg->send_rsp.status, &rsp_struct);
682 param.rsp.handle = rsp_struct.attr_value.handle;
683 } else {
684 BTA_GATTS_SendRsp(arg->send_rsp.conn_id, arg->send_rsp.trans_id,
685 arg->send_rsp.status, NULL);
686 }
687
688 param.rsp.status = 0;
689 btc_gatts_cb_to_app(ESP_GATTS_RESPONSE_EVT, BTC_GATT_GET_GATT_IF(arg->send_rsp.conn_id), ¶m);
690 break;
691 }
692 case BTC_GATTS_ACT_SET_ATTR_VALUE:
693 BTA_SetAttributeValue(arg->set_attr_val.handle, arg->set_attr_val.length,
694 arg->set_attr_val.value);
695 break;
696 case BTC_GATTS_ACT_OPEN: {
697 // Ensure device is in inquiry database
698 tBTA_GATT_TRANSPORT transport = BTA_GATT_TRANSPORT_LE;
699
700 //TODO : implement address type and device type
701 #if 0
702 if (_get_address_type(arg->remote_bda, &addr_type) &&
703 btif_get_device_type(arg->remote_bda, &device_type) &&
704 device_type != BT_DEVICE_TYPE_BREDR) {
705 BTA_DmAddBleDevice(p_cb->bd_addr.address, addr_type, device_type);
706 }
707 #else
708 //BTA_DmAddBleDevice(p_cb->bd_addr.address, addr_type, device_type);
709 #endif
710 /*
711 not support background connection
712 // Mark background connections
713 if (!arg->open.is_direct) {
714 BTA_DmBleSetBgConnType(BTM_BLE_CONN_AUTO, NULL);
715 }
716 */
717
718 transport = BTA_GATT_TRANSPORT_LE;
719
720 // Connect!
721 BTA_GATTS_Open(arg->open.gatts_if, arg->open.remote_bda,
722 arg->open.is_direct, transport);
723 break;
724 }
725 case BTC_GATTS_ACT_CLOSE:
726 // TODO : implement cancel open
727 // Cancel pending foreground/background connections
728 //BTA_GATTS_CancelOpen(p_cb->server_if, p_cb->bd_addr.address, TRUE);
729 //BTA_GATTS_CancelOpen(p_cb->server_if, p_cb->bd_addr.address, FALSE);
730
731 // Close active connection
732 if (arg->close.conn_id != 0) {
733 BTA_GATTS_Close(arg->close.conn_id);
734 }
735
736 break;
737 case BTC_GATTS_ACT_SEND_SERVICE_CHANGE: {
738 BD_ADDR remote_bda;
739 memcpy(remote_bda, arg->send_service_change.remote_bda, BD_ADDR_LEN);
740 BTA_GATTS_SendServiceChangeIndication(arg->send_service_change.gatts_if, remote_bda);
741 break;
742 }
743 default:
744 break;
745 }
746 btc_gatts_arg_deep_free(msg);
747 }
748
btc_gatts_cb_handler(btc_msg_t * msg)749 void btc_gatts_cb_handler(btc_msg_t *msg)
750 {
751 esp_ble_gatts_cb_param_t param;
752 tBTA_GATTS *p_data = (tBTA_GATTS *)msg->arg;
753 esp_gatt_if_t gatts_if;
754
755 switch (msg->act) {
756 case BTA_GATTS_REG_EVT: {
757 gatts_if = p_data->reg_oper.server_if;
758 param.reg.status = p_data->reg_oper.status;
759 param.reg.app_id = p_data->reg_oper.uuid.uu.uuid16;
760
761 btc_gatts_cb_to_app(ESP_GATTS_REG_EVT, gatts_if, ¶m);
762 break;
763 }
764 case BTA_GATTS_DEREG_EVT: {
765 gatts_if = p_data->reg_oper.server_if;
766 btc_gatts_cb_to_app(ESP_GATTS_UNREG_EVT, gatts_if, NULL);
767 break;
768 }
769 case BTA_GATTS_READ_EVT: {
770 gatts_if = BTC_GATT_GET_GATT_IF(p_data->req_data.conn_id);
771 param.read.conn_id = BTC_GATT_GET_CONN_ID(p_data->req_data.conn_id);
772 param.read.trans_id = p_data->req_data.trans_id;
773 memcpy(param.read.bda, p_data->req_data.remote_bda, ESP_BD_ADDR_LEN);
774 param.read.handle = p_data->req_data.p_data->read_req.handle;
775 param.read.offset = p_data->req_data.p_data->read_req.offset;
776 param.read.is_long = p_data->req_data.p_data->read_req.is_long;
777
778 param.read.need_rsp = p_data->req_data.p_data->read_req.need_rsp;
779 btc_gatts_cb_to_app(ESP_GATTS_READ_EVT, gatts_if, ¶m);
780 break;
781 }
782 case BTA_GATTS_WRITE_EVT: {
783 gatts_if = BTC_GATT_GET_GATT_IF(p_data->req_data.conn_id);
784 param.write.conn_id = BTC_GATT_GET_CONN_ID(p_data->req_data.conn_id);
785 param.write.trans_id = p_data->req_data.trans_id;
786 memcpy(param.write.bda, p_data->req_data.remote_bda, ESP_BD_ADDR_LEN);
787 if (p_data->req_data.p_data == NULL) {
788 break;
789 }
790 param.write.handle = p_data->req_data.p_data->write_req.handle;
791 param.write.offset = p_data->req_data.p_data->write_req.offset;
792 param.write.need_rsp = p_data->req_data.p_data->write_req.need_rsp;
793 param.write.is_prep = p_data->req_data.p_data->write_req.is_prep;
794 param.write.len = p_data->req_data.p_data->write_req.len;
795 param.write.value = p_data->req_data.p_data->write_req.value;
796
797 btc_gatts_cb_to_app(ESP_GATTS_WRITE_EVT, gatts_if, ¶m);
798
799 break;
800 }
801 case BTA_GATTS_EXEC_WRITE_EVT: {
802 gatts_if = BTC_GATT_GET_GATT_IF(p_data->req_data.conn_id);
803 param.exec_write.conn_id = BTC_GATT_GET_CONN_ID(p_data->req_data.conn_id);
804 param.exec_write.trans_id = p_data->req_data.trans_id;
805 memcpy(param.exec_write.bda, p_data->req_data.remote_bda, ESP_BD_ADDR_LEN);
806 if (p_data->req_data.p_data == NULL) {
807 break;
808 }
809 param.exec_write.exec_write_flag = p_data->req_data.p_data->exec_write;
810
811 btc_gatts_cb_to_app(ESP_GATTS_EXEC_WRITE_EVT, gatts_if, ¶m);
812 break;
813 }
814 case BTA_GATTS_MTU_EVT:
815 gatts_if = BTC_GATT_GET_GATT_IF(p_data->req_data.conn_id);
816 param.mtu.conn_id = BTC_GATT_GET_CONN_ID(p_data->req_data.conn_id);
817 param.mtu.mtu = p_data->req_data.p_data->mtu;
818
819 btc_gatts_cb_to_app(ESP_GATTS_MTU_EVT, gatts_if, ¶m);
820 break;
821 case BTA_GATTS_CONF_EVT:
822 gatts_if = BTC_GATT_GET_GATT_IF(p_data->req_data.conn_id);
823 param.conf.conn_id = BTC_GATT_GET_CONN_ID(p_data->req_data.conn_id);
824 param.conf.status = p_data->req_data.status;
825 param.conf.handle = p_data->req_data.handle;
826
827 if (p_data->req_data.status != ESP_GATT_OK && p_data->req_data.value){
828 param.conf.len = p_data->req_data.data_len;
829 param.conf.value = p_data->req_data.value;
830 }else{
831 param.conf.len = 0;
832 }
833 btc_gatts_cb_to_app(ESP_GATTS_CONF_EVT, gatts_if, ¶m);
834 break;
835 case BTA_GATTS_CREATE_EVT:
836 gatts_if = p_data->create.server_if;
837 param.create.status = p_data->create.status;
838 param.create.service_handle = p_data->create.service_id;
839 param.create.service_id.is_primary = p_data->create.is_primary;
840 param.create.service_id.id.inst_id = p_data->create.svc_instance;
841 bta_to_btc_uuid(¶m.create.service_id.id.uuid, &p_data->create.uuid);
842
843 btc_gatts_cb_to_app(ESP_GATTS_CREATE_EVT, gatts_if, ¶m);
844 break;
845 case BTA_GATTS_ADD_INCL_SRVC_EVT:
846 gatts_if = p_data->add_result.server_if;
847 param.add_incl_srvc.status = p_data->add_result.status;
848 param.add_incl_srvc.attr_handle = p_data->add_result.attr_id;
849 param.add_incl_srvc.service_handle = p_data->add_result.service_id;
850
851 btc_gatts_cb_to_app(ESP_GATTS_ADD_INCL_SRVC_EVT, gatts_if, ¶m);
852 break;
853 case BTA_GATTS_ADD_CHAR_EVT:
854 gatts_if = p_data->add_result.server_if;
855 param.add_char.status = p_data->add_result.status;
856 param.add_char.attr_handle = p_data->add_result.attr_id;
857 param.add_char.service_handle = p_data->add_result.service_id;
858 bta_to_btc_uuid(¶m.add_char.char_uuid, &p_data->add_result.char_uuid);
859
860 btc_gatts_cb_to_app(ESP_GATTS_ADD_CHAR_EVT, gatts_if, ¶m);
861 break;
862 case BTA_GATTS_ADD_CHAR_DESCR_EVT:
863 gatts_if = p_data->add_result.server_if;
864 param.add_char_descr.status = p_data->add_result.status;
865 param.add_char_descr.attr_handle = p_data->add_result.attr_id;
866 param.add_char_descr.service_handle = p_data->add_result.service_id;
867 bta_to_btc_uuid(¶m.add_char_descr.descr_uuid, &p_data->add_result.char_uuid);
868
869 btc_gatts_cb_to_app(ESP_GATTS_ADD_CHAR_DESCR_EVT, gatts_if, ¶m);
870 break;
871 case BTA_GATTS_DELELTE_EVT:
872 gatts_if = p_data->srvc_oper.server_if;
873 param.del.status = p_data->srvc_oper.status;
874 param.del.service_handle = p_data->srvc_oper.service_id;
875
876 btc_gatts_cb_to_app(ESP_GATTS_DELETE_EVT, gatts_if, ¶m);
877 break;
878 case BTA_GATTS_START_EVT:
879 gatts_if = p_data->srvc_oper.server_if;
880 param.start.status = p_data->srvc_oper.status;
881 param.start.service_handle = p_data->srvc_oper.service_id;
882
883 btc_gatts_cb_to_app(ESP_GATTS_START_EVT, gatts_if, ¶m);
884 break;
885 case BTA_GATTS_STOP_EVT:
886 gatts_if = p_data->srvc_oper.server_if;
887 param.stop.status = p_data->srvc_oper.status;
888 param.stop.service_handle = p_data->srvc_oper.service_id;
889
890 btc_gatts_cb_to_app(ESP_GATTS_STOP_EVT, gatts_if, ¶m);
891 break;
892 case BTA_GATTS_CONNECT_EVT:
893 gatts_if = p_data->conn.server_if;
894 param.connect.conn_id = BTC_GATT_GET_CONN_ID(p_data->conn.conn_id);
895 param.connect.link_role = p_data->conn.link_role;
896 memcpy(param.connect.remote_bda, p_data->conn.remote_bda, ESP_BD_ADDR_LEN);
897 param.connect.conn_params.interval = p_data->conn.conn_params.interval;
898 param.connect.conn_params.latency = p_data->conn.conn_params.latency;
899 param.connect.conn_params.timeout = p_data->conn.conn_params.timeout;
900 btc_gatts_cb_to_app(ESP_GATTS_CONNECT_EVT, gatts_if, ¶m);
901 break;
902 case BTA_GATTS_DISCONNECT_EVT:
903 gatts_if = p_data->conn.server_if;
904 param.disconnect.conn_id = BTC_GATT_GET_CONN_ID(p_data->conn.conn_id);
905 param.disconnect.reason = p_data->conn.reason;
906 memcpy(param.disconnect.remote_bda, p_data->conn.remote_bda, ESP_BD_ADDR_LEN);
907
908 btc_gatts_cb_to_app(ESP_GATTS_DISCONNECT_EVT, gatts_if, ¶m);
909 break;
910 case BTA_GATTS_OPEN_EVT:
911 gatts_if = p_data->open.server_if;
912 param.open.status = p_data->open.status;
913
914 btc_gatts_cb_to_app(BTA_GATTS_OPEN_EVT, gatts_if, ¶m);
915 break;
916 case BTA_GATTS_CANCEL_OPEN_EVT:
917 gatts_if = p_data->cancel_open.server_if;
918 param.cancel_open.status = p_data->cancel_open.status;
919
920 btc_gatts_cb_to_app(BTA_GATTS_CANCEL_OPEN_EVT, gatts_if, ¶m);
921 break;
922
923 case BTA_GATTS_CLOSE_EVT:
924 gatts_if = BTC_GATT_GET_GATT_IF(p_data->close.conn_id);
925 param.close.status = p_data->close.status;
926 param.close.conn_id = BTC_GATT_GET_CONN_ID(p_data->close.conn_id);
927
928 btc_gatts_cb_to_app(BTA_GATTS_CLOSE_EVT, gatts_if, ¶m);
929 break;
930 case BTA_GATTS_SEND_SERVICE_CHANGE_EVT:
931 gatts_if = p_data->service_change.server_if;
932 param.service_change.status = p_data->service_change.status;
933 btc_gatts_cb_to_app(ESP_GATTS_SEND_SERVICE_CHANGE_EVT, gatts_if, ¶m);
934 break;
935 case BTA_GATTS_LISTEN_EVT:
936 // do nothing
937 break;
938 case BTA_GATTS_CONGEST_EVT:
939 gatts_if = BTC_GATT_GET_GATT_IF(p_data->congest.conn_id);
940 param.congest.conn_id = BTC_GATT_GET_CONN_ID(p_data->congest.conn_id);
941 param.congest.congested = p_data->congest.congested;
942 btc_gatts_cb_to_app(ESP_GATTS_CONGEST_EVT, gatts_if, ¶m);
943 break;
944 case BTA_GATTS_SET_ATTR_VAL_EVT:
945 gatts_if = p_data->attr_val.server_if;
946 param.set_attr_val.srvc_handle = p_data->attr_val.service_id;
947 param.set_attr_val.attr_handle = p_data->attr_val.attr_id;
948 param.set_attr_val.status = p_data->attr_val.status;
949 btc_gatts_cb_to_app(ESP_GATTS_SET_ATTR_VAL_EVT, gatts_if, ¶m);
950 break;
951 default:
952 // do nothing
953 break;
954 }
955
956 btc_gatts_cb_param_copy_free(msg, p_data);
957 }
958
btc_congest_callback(tBTA_GATTS * param)959 void btc_congest_callback(tBTA_GATTS *param)
960 {
961 esp_ble_gatts_cb_param_t esp_param;
962 esp_gatt_if_t gatts_if = BTC_GATT_GET_GATT_IF(param->congest.conn_id);
963 esp_param.congest.conn_id = BTC_GATT_GET_CONN_ID(param->congest.conn_id);
964 esp_param.congest.congested = param->congest.congested;
965 btc_gatts_cb_to_app(ESP_GATTS_CONGEST_EVT, gatts_if, &esp_param);
966 }
967
968 #endif ///GATTS_INCLUDED
969