1 // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "string.h"
16 #include "esp_gatt_defs.h"
17 #include "esp_gatts_api.h"
18 #include "esp_bt_main.h"
19 #include "btc/btc_manage.h"
20 #include "btc_gatts.h"
21 #include "btc_gatt_util.h"
22 #include "common/bt_target.h"
23 #include "stack/l2cdefs.h"
24 #include "stack/l2c_api.h"
25 #include "gatt_int.h"
26 #include "esp_log.h"
27
28 #if (GATTS_INCLUDED == 1)
29 #define COPY_TO_GATTS_ARGS(_gatt_args, _arg, _arg_type) memcpy(_gatt_args, _arg, sizeof(_arg_type))
30
31 static esp_err_t esp_ble_gatts_add_char_desc_param_check(esp_attr_value_t *char_val, esp_attr_control_t *control);
32
33
esp_ble_gatts_register_callback(esp_gatts_cb_t callback)34 esp_err_t esp_ble_gatts_register_callback(esp_gatts_cb_t callback)
35 {
36 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
37
38 return (btc_profile_cb_set(BTC_PID_GATTS, callback) == 0 ? ESP_OK : ESP_FAIL);
39 }
40
esp_ble_gatts_app_register(uint16_t app_id)41 esp_err_t esp_ble_gatts_app_register(uint16_t app_id)
42 {
43 btc_msg_t msg;
44 btc_ble_gatts_args_t arg;
45
46 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
47
48 //if (app_id < ESP_APP_ID_MIN || app_id > ESP_APP_ID_MAX) {
49 if (app_id > ESP_APP_ID_MAX) {
50 return ESP_ERR_INVALID_ARG;
51 }
52
53 msg.sig = BTC_SIG_API_CALL;
54 msg.pid = BTC_PID_GATTS;
55 msg.act = BTC_GATTS_ACT_APP_REGISTER;
56 arg.app_reg.app_id = app_id;
57
58 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
59 }
60
61
esp_ble_gatts_app_unregister(esp_gatt_if_t gatts_if)62 esp_err_t esp_ble_gatts_app_unregister(esp_gatt_if_t gatts_if)
63 {
64 btc_msg_t msg;
65 btc_ble_gatts_args_t arg;
66
67 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
68
69 msg.sig = BTC_SIG_API_CALL;
70 msg.pid = BTC_PID_GATTS;
71 msg.act = BTC_GATTS_ACT_APP_UNREGISTER;
72 arg.app_unreg.gatts_if = gatts_if;
73
74 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
75 }
76
esp_ble_gatts_create_service(esp_gatt_if_t gatts_if,esp_gatt_srvc_id_t * service_id,uint16_t num_handle)77 esp_err_t esp_ble_gatts_create_service(esp_gatt_if_t gatts_if,
78 esp_gatt_srvc_id_t *service_id, uint16_t num_handle)
79 {
80 btc_msg_t msg;
81 btc_ble_gatts_args_t arg;
82
83 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
84
85 msg.sig = BTC_SIG_API_CALL;
86 msg.pid = BTC_PID_GATTS;
87 msg.act = BTC_GATTS_ACT_CREATE_SERVICE;
88 arg.create_srvc.gatts_if = gatts_if;
89 arg.create_srvc.num_handle = num_handle;
90 memcpy(&arg.create_srvc.service_id, service_id, sizeof(esp_gatt_srvc_id_t));
91
92 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
93 }
94
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)95 esp_err_t esp_ble_gatts_create_attr_tab(const esp_gatts_attr_db_t *gatts_attr_db,
96 esp_gatt_if_t gatts_if,
97 uint8_t max_nb_attr,
98 uint8_t srvc_inst_id)
99 {
100 btc_msg_t msg;
101 btc_ble_gatts_args_t arg;
102
103 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
104
105 msg.sig = BTC_SIG_API_CALL;
106 msg.pid = BTC_PID_GATTS;
107 msg.act = BTC_GATTS_ACT_CREATE_ATTR_TAB;
108 arg.create_attr_tab.gatts_if = gatts_if;
109 arg.create_attr_tab.max_nb_attr = max_nb_attr;
110 arg.create_attr_tab.srvc_inst_id = srvc_inst_id;
111 arg.create_attr_tab.gatts_attr_db = (esp_gatts_attr_db_t *)gatts_attr_db;
112
113 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), btc_gatts_arg_deep_copy)
114 == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
115 }
116
117
esp_ble_gatts_add_included_service(uint16_t service_handle,uint16_t included_service_handle)118 esp_err_t esp_ble_gatts_add_included_service(uint16_t service_handle, uint16_t included_service_handle)
119 {
120 btc_msg_t msg;
121 btc_ble_gatts_args_t arg;
122
123 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
124
125 msg.sig = BTC_SIG_API_CALL;
126 msg.pid = BTC_PID_GATTS;
127 msg.act = BTC_GATTS_ACT_ADD_INCLUDE_SERVICE;
128 arg.add_incl_srvc.service_handle = service_handle;
129 arg.add_incl_srvc.included_service_handle = included_service_handle;
130
131 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
132 }
133
134
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_attr_value_t * char_val,esp_attr_control_t * control)135 esp_err_t esp_ble_gatts_add_char(uint16_t service_handle, esp_bt_uuid_t *char_uuid,
136 esp_gatt_perm_t perm, esp_gatt_char_prop_t property, esp_attr_value_t *char_val,
137 esp_attr_control_t *control)
138 {
139 btc_msg_t msg;
140 btc_ble_gatts_args_t arg;
141 esp_err_t status;
142
143 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
144
145 /* parameter validation check */
146 status = esp_ble_gatts_add_char_desc_param_check(char_val, control);
147 if (status != ESP_OK){
148 return status;
149 }
150
151 memset(&arg, 0, sizeof(btc_ble_gatts_args_t));
152 msg.sig = BTC_SIG_API_CALL;
153 msg.pid = BTC_PID_GATTS;
154 msg.act = BTC_GATTS_ACT_ADD_CHAR;
155 arg.add_char.service_handle = service_handle;
156 arg.add_char.perm = perm;
157 arg.add_char.property = property;
158 if (char_val != NULL) {
159 arg.add_char.char_val.attr_max_len = char_val->attr_max_len;
160 arg.add_char.char_val.attr_len = char_val->attr_len;
161 arg.add_char.char_val.attr_value = char_val->attr_value;
162 }
163
164 if (control != NULL) {
165 arg.add_char.attr_control.auto_rsp = control->auto_rsp;
166 }
167 memcpy(&arg.add_char.char_uuid, char_uuid, sizeof(esp_bt_uuid_t));
168
169 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
170 }
171
172
esp_ble_gatts_add_char_descr(uint16_t service_handle,esp_bt_uuid_t * descr_uuid,esp_gatt_perm_t perm,esp_attr_value_t * char_descr_val,esp_attr_control_t * control)173 esp_err_t esp_ble_gatts_add_char_descr (uint16_t service_handle,
174 esp_bt_uuid_t *descr_uuid,
175 esp_gatt_perm_t perm, esp_attr_value_t *char_descr_val,
176 esp_attr_control_t *control)
177 {
178 btc_msg_t msg;
179 btc_ble_gatts_args_t arg;
180 esp_err_t status;
181
182 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
183
184 /* parameter validation check */
185 status = esp_ble_gatts_add_char_desc_param_check(char_descr_val, control);
186 if (status != ESP_OK){
187 return status;
188 }
189
190 memset(&arg, 0, sizeof(btc_ble_gatts_args_t));
191 msg.sig = BTC_SIG_API_CALL;
192 msg.pid = BTC_PID_GATTS;
193 msg.act = BTC_GATTS_ACT_ADD_CHAR_DESCR;
194 arg.add_descr.service_handle = service_handle;
195 arg.add_descr.perm = perm;
196
197 if (char_descr_val != NULL) {
198 arg.add_descr.descr_val.attr_max_len = char_descr_val->attr_max_len;
199 arg.add_descr.descr_val.attr_len = char_descr_val->attr_len;
200 arg.add_descr.descr_val.attr_value = char_descr_val->attr_value;
201 }
202
203 if (control != NULL) {
204 arg.add_descr.attr_control.auto_rsp = control->auto_rsp;
205 }
206 memcpy(&arg.add_descr.descr_uuid, descr_uuid, sizeof(esp_bt_uuid_t));
207
208 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
209 }
210
esp_ble_gatts_delete_service(uint16_t service_handle)211 esp_err_t esp_ble_gatts_delete_service(uint16_t service_handle)
212 {
213 btc_msg_t msg;
214 btc_ble_gatts_args_t arg;
215
216 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
217
218 msg.sig = BTC_SIG_API_CALL;
219 msg.pid = BTC_PID_GATTS;
220 msg.act = BTC_GATTS_ACT_DELETE_SERVICE;
221 arg.delete_srvc.service_handle = service_handle;
222
223 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
224 }
225
esp_ble_gatts_start_service(uint16_t service_handle)226 esp_err_t esp_ble_gatts_start_service(uint16_t service_handle)
227 {
228 btc_msg_t msg;
229 btc_ble_gatts_args_t arg;
230
231 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
232
233 msg.sig = BTC_SIG_API_CALL;
234 msg.pid = BTC_PID_GATTS;
235 msg.act = BTC_GATTS_ACT_START_SERVICE;
236 arg.start_srvc.service_handle = service_handle;
237
238 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
239 }
240
esp_ble_gatts_stop_service(uint16_t service_handle)241 esp_err_t esp_ble_gatts_stop_service(uint16_t service_handle)
242 {
243 btc_msg_t msg;
244 btc_ble_gatts_args_t arg;
245
246 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
247
248 msg.sig = BTC_SIG_API_CALL;
249 msg.pid = BTC_PID_GATTS;
250 msg.act = BTC_GATTS_ACT_STOP_SERVICE;
251 arg.stop_srvc.service_handle = service_handle;
252
253 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
254 }
255
256
esp_ble_gatts_send_indicate(esp_gatt_if_t gatts_if,uint16_t conn_id,uint16_t attr_handle,uint16_t value_len,uint8_t * value,bool need_confirm)257 esp_err_t esp_ble_gatts_send_indicate(esp_gatt_if_t gatts_if, uint16_t conn_id, uint16_t attr_handle,
258 uint16_t value_len, uint8_t *value, bool need_confirm)
259 {
260 btc_msg_t msg;
261 btc_ble_gatts_args_t arg;
262
263 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
264
265 tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
266 if (!p_tcb) {
267 LOG_WARN("%s, The connection not created.", __func__);
268 return ESP_ERR_INVALID_STATE;
269 }
270
271 if (L2CA_CheckIsCongest(L2CAP_ATT_CID, p_tcb->peer_bda)) {
272 LOG_DEBUG("%s, the l2cap chanel is congest.", __func__);
273 return ESP_FAIL;
274 }
275
276 msg.sig = BTC_SIG_API_CALL;
277 msg.pid = BTC_PID_GATTS;
278 msg.act = BTC_GATTS_ACT_SEND_INDICATE;
279 arg.send_ind.conn_id = BTC_GATT_CREATE_CONN_ID(gatts_if, conn_id);
280 arg.send_ind.attr_handle = attr_handle;
281 arg.send_ind.need_confirm = need_confirm;
282 arg.send_ind.value_len = value_len;
283 arg.send_ind.value = value;
284 if(need_confirm == false){
285 l2ble_update_att_acl_pkt_num(L2CA_ADD_BTC_NUM, NULL);
286 }
287 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t),
288 btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
289 }
290
esp_ble_gatts_send_response(esp_gatt_if_t gatts_if,uint16_t conn_id,uint32_t trans_id,esp_gatt_status_t status,esp_gatt_rsp_t * rsp)291 esp_err_t esp_ble_gatts_send_response(esp_gatt_if_t gatts_if, uint16_t conn_id, uint32_t trans_id,
292 esp_gatt_status_t status, esp_gatt_rsp_t *rsp)
293 {
294 btc_msg_t msg;
295 btc_ble_gatts_args_t arg;
296
297 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
298
299 msg.sig = BTC_SIG_API_CALL;
300 msg.pid = BTC_PID_GATTS;
301 msg.act = BTC_GATTS_ACT_SEND_RESPONSE;
302 arg.send_rsp.conn_id = BTC_GATT_CREATE_CONN_ID(gatts_if, conn_id);
303 arg.send_rsp.trans_id = trans_id;
304 arg.send_rsp.status = status;
305 arg.send_rsp.rsp = rsp;
306
307 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t),
308 btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
309 }
310
esp_ble_gatts_set_attr_value(uint16_t attr_handle,uint16_t length,const uint8_t * value)311 esp_err_t esp_ble_gatts_set_attr_value(uint16_t attr_handle, uint16_t length, const uint8_t *value)
312 {
313 btc_msg_t msg;
314 btc_ble_gatts_args_t arg;
315
316 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
317
318 msg.sig = BTC_SIG_API_CALL;
319 msg.pid = BTC_PID_GATTS;
320 msg.act = BTC_GATTS_ACT_SET_ATTR_VALUE;
321 arg.set_attr_val.handle = attr_handle;
322 arg.set_attr_val.length = length;
323 arg.set_attr_val.value = (uint8_t *)value;
324
325 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t),
326 btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
327 }
328
esp_ble_gatts_get_attr_value(uint16_t attr_handle,uint16_t * length,const uint8_t ** value)329 esp_gatt_status_t esp_ble_gatts_get_attr_value(uint16_t attr_handle, uint16_t *length, const uint8_t **value)
330 {
331 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
332
333 if (attr_handle == ESP_GATT_ILLEGAL_HANDLE) {
334 *length = 0;
335 return ESP_GATT_INVALID_HANDLE;
336 }
337
338 return btc_gatts_get_attr_value(attr_handle, length, (uint8_t **)value);
339 }
340
esp_ble_gatts_open(esp_gatt_if_t gatts_if,esp_bd_addr_t remote_bda,bool is_direct)341 esp_err_t esp_ble_gatts_open(esp_gatt_if_t gatts_if, esp_bd_addr_t remote_bda, bool is_direct)
342 {
343 btc_msg_t msg;
344 btc_ble_gatts_args_t arg;
345
346 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
347
348 msg.sig = BTC_SIG_API_CALL;
349 msg.pid = BTC_PID_GATTS;
350 msg.act = BTC_GATTS_ACT_OPEN;
351 arg.open.gatts_if = gatts_if;
352 arg.open.is_direct = is_direct;
353 memcpy(&arg.open.remote_bda, remote_bda, sizeof(esp_bd_addr_t));
354
355 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL)
356 == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
357 }
358
esp_ble_gatts_close(esp_gatt_if_t gatts_if,uint16_t conn_id)359 esp_err_t esp_ble_gatts_close(esp_gatt_if_t gatts_if, uint16_t conn_id)
360 {
361 btc_msg_t msg;
362 btc_ble_gatts_args_t arg;
363
364 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
365
366 msg.sig = BTC_SIG_API_CALL;
367 msg.pid = BTC_PID_GATTS;
368 msg.act = BTC_GATTS_ACT_CLOSE;
369 arg.close.conn_id = BTC_GATT_CREATE_CONN_ID(gatts_if, conn_id);
370
371 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL)
372 == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
373 }
374
esp_ble_gatts_send_service_change_indication(esp_gatt_if_t gatts_if,esp_bd_addr_t remote_bda)375 esp_err_t esp_ble_gatts_send_service_change_indication(esp_gatt_if_t gatts_if, esp_bd_addr_t remote_bda)
376 {
377 btc_msg_t msg;
378 btc_ble_gatts_args_t arg;
379
380 ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
381
382 msg.sig = BTC_SIG_API_CALL;
383 msg.pid = BTC_PID_GATTS;
384 msg.act = BTC_GATTS_ACT_SEND_SERVICE_CHANGE;
385 arg.send_service_change.gatts_if = gatts_if;
386 if(remote_bda) {
387 memcpy(&arg.send_service_change.remote_bda, remote_bda, sizeof(esp_bd_addr_t));
388 } else {
389 memset(arg.send_service_change.remote_bda, 0, sizeof(esp_bd_addr_t));
390 }
391
392
393 return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL)
394 == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
395 }
396
esp_ble_gatts_add_char_desc_param_check(esp_attr_value_t * char_val,esp_attr_control_t * control)397 static esp_err_t esp_ble_gatts_add_char_desc_param_check(esp_attr_value_t *char_val, esp_attr_control_t *control)
398 {
399 if ((control != NULL) && ((control->auto_rsp != ESP_GATT_AUTO_RSP) && (control->auto_rsp != ESP_GATT_RSP_BY_APP))){
400 LOG_ERROR("Error in %s, line=%d, control->auto_rsp should be set to ESP_GATT_AUTO_RSP or ESP_GATT_RSP_BY_APP\n",\
401 __func__, __LINE__);
402 return ESP_ERR_INVALID_ARG;
403 }
404
405 if ((control != NULL) && (control->auto_rsp == ESP_GATT_AUTO_RSP)){
406 if (char_val == NULL){
407 LOG_ERROR("Error in %s, line=%d, for stack respond attribute, char_val should not be NULL here\n",\
408 __func__, __LINE__);
409 return ESP_ERR_INVALID_ARG;
410 } else if (char_val->attr_max_len == 0){
411 LOG_ERROR("Error in %s, line=%d, for stack respond attribute, attribute max length should not be 0\n",\
412 __func__, __LINE__);
413 return ESP_ERR_INVALID_ARG;
414 }
415 }
416
417 return ESP_OK;
418 }
419
420 #endif ///GATTS_INCLUDED
421