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