1 /*
2 * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdint.h>
8 #include <string.h>
9 #include <stdbool.h>
10 #include <stdio.h>
11
12 //#include "bluedroid_test.h"
13 #include "bta/bta_api.h"
14 #include "bta/bta_gatt_api.h"
15 #include "device/controller.h"
16
17 #include "gatt_int.h"
18 #include "common/bt_trace.h"
19 #include "stack/btm_api.h"
20 #include "stack/bt_types.h"
21 #include "dis_api.h"
22
23 #if BLE_INCLUDED == true
24
25 #define BA_MAX_CHAR_NUM 1
26 #define BA_MAX_ATTR_NUM (BA_MAX_CHAR_NUM * 5 + 1)
27 /*max 3 descriptors, 1 desclaration and 1 value*/
28
29 #ifndef BATTER_LEVEL_PROP
30 #define BATTER_LEVEL_PROP (GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY)
31 #endif
32
33 #ifndef BATTER_LEVEL_PERM
34 #define BATTER_LEVEL_PERM (GATT_PERM_READ)
35 #endif
36
37 #define BT_BD_ADDR_STR "%02x:%02x:%02x:%02x:%02x:%02x"
38 #define BT_BD_ADDR_HEX(addr) addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]
39 esp_gatts_if_t server_if;
40
41 tBATTERY_CB battery_cb;
42 tGATT_CHAR_PROP prop = GATT_CHAR_PROP_BIT_READ;
43 tBA_REG_INFO ba_reg_info;
44 UINT8 attr_handle_bit = 0x00;
45
46 extern tDIS_CB dis_cb;
47 esp_bt_uuid_t bas_uuid = {LEN_UUID_16, {UUID_SERVCLASS_BATTERY}};
48 /******************************************************************************
49 ** Function bas_gatts_callback
50 **
51 ** Description battery service register callback function
52 *******************************************************************************/
bas_gatts_callback(esp_gatts_evt_t event,tBTA_GATTS * p_data)53 static void bas_gatts_callback(esp_gatts_evt_t event, tBTA_GATTS *p_data)
54 {
55 switch (event) {
56 case ESP_GATTS_REG_EVT: {
57 esp_gatt_status_t status = p_data->reg_oper.status;
58 server_if = p_data->reg_oper.server_if;
59 BTC_TRACE_ERROR("BAS register completed: event=%d, status=%d, server_if=%d\n",
60 event, status, server_if);
61
62 UINT8 app_id = 0xff;
63 bas_init(server_if, app_id);
64
65 tDIS_ATTR_MASK mask = 0x01ff;
66 DIS_Init(server_if, mask);
67 }
68 break;
69
70 /*connect callback*/
71 case ESP_GATTS_CONNECT_EVT: {
72 BTC_TRACE_ERROR("\ndevice is connected "BT_BD_ADDR_STR", server_if=%d,reason=0x%x,connect_id=%d\n",
73 BT_BD_ADDR_HEX(p_data->conn.remote_bda), p_data->conn.server_if,
74 p_data->conn.reason, p_data->conn.conn_id);
75 /*return whether the remote device is currently connected*/
76 int is_connected = BTA_DmGetConnectionState(p_data->conn.remote_bda);
77 BTC_TRACE_ERROR("is_connected=%d\n", is_connected);
78 }
79 break;
80
81 /*create service callback*/
82 case ESP_GATTS_CREATE_EVT: {
83 BTC_TRACE_ERROR("create service:server_if=%d,service_id=0x%x,service_uuid=0x%x\n",
84 p_data->create.server_if, p_data->create.service_id,
85 p_data->create.uuid.uu.uuid16);
86 UINT16 service_uuid = p_data->create.uuid.uu.uuid16;
87 UINT16 service_id = p_data->create.service_id;
88 if (service_uuid == 0x180f) {
89 tBT_UUID uuid = {LEN_UUID_16, {GATT_UUID_BATTERY_LEVEL}};
90 bas_AddChar(service_id, &uuid);
91 }
92 if (service_uuid == 0x180a) {
93 dis_cb.service_handle = service_id;
94 dis_cb.max_handle = service_id + DIS_MAX_ATTR_NUM;
95 dis_AddChar(service_id);
96 }
97
98 }
99 break;
100
101 case ESP_GATTS_ADD_CHAR_EVT: {
102 BTC_TRACE_ERROR("create characteristic:server_if=%d,service_id=0x%x,char_uuid=0x%x\n",
103 p_data->add_result.server_if, p_data->add_result.service_id,
104 p_data->add_result.char_uuid.uu.uuid16);
105 UINT16 char_uuid = p_data->add_result.char_uuid.uu.uuid16;
106 UINT16 service_id = p_data->add_result.service_id;
107 UINT16 uuid_len = p_data->add_result.char_uuid.len;
108
109 if (uuid_len == ESP_UUID_LEN_16) {
110 if (char_uuid == GATT_UUID_BATTERY_LEVEL) {
111 bas_AddCharDescr(service_id, p_data->add_result.attr_id);
112 }
113
114 switch (char_uuid) {
115 case GATT_UUID_SYSTEM_ID:
116 dis_cb.dis_attr[0].handle = service_id; break;
117 case GATT_UUID_MODEL_NUMBER_STR:
118 dis_cb.dis_attr[1].handle = service_id; break;
119 case GATT_UUID_SERIAL_NUMBER_STR:
120 dis_cb.dis_attr[2].handle = service_id; break;
121 case GATT_UUID_FW_VERSION_STR:
122 dis_cb.dis_attr[3].handle = service_id; break;
123 case GATT_UUID_HW_VERSION_STR:
124 dis_cb.dis_attr[4].handle = service_id; break;
125 case GATT_UUID_SW_VERSION_STR:
126 dis_cb.dis_attr[5].handle = service_id; break;
127 case GATT_UUID_MANU_NAME:
128 dis_cb.dis_attr[6].handle = service_id; break;
129 case GATT_UUID_IEEE_DATA:
130 dis_cb.dis_attr[7].handle = service_id; break;
131 case GATT_UUID_PNP_ID:
132 dis_cb.dis_attr[8].handle = service_id; break;
133 }
134 default:
135 break;
136 }
137 }
138 break;
139
140 case ESP_GATTS_ADD_CHAR_DESCR_EVT: {
141
142 BTC_TRACE_ERROR("create descriptor:server_if=%d,service_id=0x%x,attr_id=0x%x,char_uuid=0x%x\n",
143 p_data->add_result.server_if, p_data->add_result.service_id,
144 p_data->add_result.attr_id, p_data->add_result.char_uuid.uu.uuid16);
145 bas_AddCharDescr(p_data->add_result.service_id, p_data->add_result.attr_id);
146 }
147 break;
148
149 case ESP_GATTS_START_EVT: {
150 BTC_TRACE_ERROR("start service:server_if=%d,service_id=0x%x\n", p_data->srvc_oper.server_if,
151 p_data->srvc_oper.service_id);
152 bas_service_cmpl(p_data->srvc_oper.service_id, p_data->srvc_oper.status);
153
154 /*start advertising*/
155 //if(p_data->srvc_oper.status == GATT_SUCCESS)
156 // BTA_GATTS_Listen(server_if, true, NULL);
157 // BTA_GATTC_Broadcast(client_if, true); //non-connectable
158 }
159 break;
160
161 case ESP_GATTS_READ_EVT: {
162 UINT32 trans_id = p_data->req_data.trans_id;
163 UINT16 conn_id = p_data->req_data.conn_id;
164 UINT16 handle = p_data->req_data.p_data->read_req.handle;
165 bool is_long = p_data->req_data.p_data->read_req.is_long;
166 BTC_TRACE_ERROR("read request:event=0x%x,handle=0x%x,trans_id=0x%x,conn_id=0x%x\n",
167 event, handle, trans_id, conn_id);
168
169 if (dis_valid_handle_range(handle)) {
170 tGATT_VALUE p_value;
171 p_value.handle = handle;
172 p_value.conn_id = conn_id;
173 p_value.offset = p_data->req_data.p_data->read_req.offset;
174 dis_s_read_attr_value(p_data->req_data.p_data, &p_value, trans_id, conn_id);
175 } else {
176 bas_s_read_attr_value(p_data->req_data.p_data, trans_id, conn_id);
177 }
178 }
179 break;
180
181 case ESP_GATTS_WRITE_EVT: {
182
183 UINT32 trans_id = p_data->req_data.trans_id;
184 UINT16 conn_id = p_data->req_data.conn_id;
185 UINT16 handle = p_data->req_data.p_data->write_req.handle;
186 BTC_TRACE_ERROR("write request:event=0x%x,handle=0x%x,trans_id=0x%x,conn_id=0x%x\n",
187 event, handle, trans_id, conn_id);
188 bas_s_write_attr_value(p_data->req_data.p_data, trans_id, conn_id,
189 p_data->req_data.remote_bda);
190 }
191 break;
192
193 case ESP_GATTS_EXEC_WRITE_EVT: {
194 UINT32 trans_id = p_data->req_data.trans_id;
195 UINT16 conn_id = p_data->req_data.conn_id;
196 UINT8 exec_write = p_data->req_data.p_data->exec_write;
197 BTC_TRACE_ERROR("execute write request:event=0x%x,exce_write=0x%x,trans_id=0x%x,conn_id=0x%x\n",
198 event, exec_write, trans_id, conn_id);
199 }
200 break;
201
202 case ESP_GATTS_MTU_EVT: {
203 UINT32 trans_id = p_data->req_data.trans_id;
204 UINT16 conn_id = p_data->req_data.conn_id;
205 UINT16 mtu = p_data->req_data.p_data->mtu;
206 BTC_TRACE_ERROR("exchange mtu request:event=0x%x,mtu=0x%x,trans_id=0x%x,conn_id=0x%x\n",
207 event, mtu, trans_id, conn_id);
208 }
209 break;
210
211 case ESP_GATTS_CFM_EVT: {
212
213 UINT32 trans_id = p_data->req_data.trans_id;
214 UINT16 conn_id = p_data->req_data.conn_id;
215 BTC_TRACE_ERROR("configue request:trans_id=0x%x,conn_id=0x%x\n",
216 trans_id, conn_id);
217 }
218 break;
219
220 default:
221 BTC_TRACE_ERROR("unsettled event: %d\n", event);
222 break;
223 }
224
225 }
226 /******************************************************************************
227 ** Function bas_callback
228 **
229 ** Description battery service callback for client request
230 *******************************************************************************/
bas_callback(UINT32 trans_id,UINT16 conn_id,UINT8 app_id,UINT8 event,tBA_WRITE_DATA * p_data)231 static void bas_callback(UINT32 trans_id, UINT16 conn_id, UINT8 app_id,
232 UINT8 event, tBA_WRITE_DATA *p_data)
233 {
234 tBA_RSP_DATA p_rsp;
235 tGATT_STATUS st = ESP_GATT_OK;
236 switch (event) {
237 case BA_READ_LEVEL_REQ : {
238 BTC_TRACE_ERROR("read battery level\n");
239 p_rsp.ba_level = 60; //battery level
240 Battery_Rsp(trans_id, conn_id, app_id, st, event, &p_rsp);
241 }
242 break;
243
244 case BA_READ_PRE_FMT_REQ : {
245 BTC_TRACE_ERROR("read presentation format\n");
246 }
247 break;
248
249 case BA_READ_CLT_CFG_REQ : {
250 BTC_TRACE_ERROR("read client characteristic configuration request\n");
251 p_rsp.clt_cfg = 0x0001; //notification
252 Battery_Rsp(trans_id, conn_id, app_id, st, event, &p_rsp);
253 }
254 break;
255
256 case BA_READ_RPT_REF_REQ : {
257 BTC_TRACE_ERROR("read report reference descriptor\n");
258 }
259 break;
260
261 /*battery level notify*/
262 case BA_WRITE_CLT_CFG_REQ : {
263 BTC_TRACE_ERROR("write client characteristic configuration request\n");
264 Battery_Rsp(trans_id, conn_id, app_id, st, event, NULL);
265
266 int battery_level = 50;
267 Battery_Notify(conn_id, app_id, p_data->remote_bda, battery_level);
268 }
269 break;
270
271 default:
272 break;
273 }
274
275 return;
276 }
277 /*****************************************************************************
278 ** Function bas_s_read_attr_value
279 **
280 ** Description it will be called when client sends a read request
281 ******************************************************************************/
bas_s_read_attr_value(tGATTS_DATA * p_data,UINT32 trans_id,UINT16 conn_id)282 void bas_s_read_attr_value(tGATTS_DATA *p_data, UINT32 trans_id, UINT16 conn_id)
283 {
284
285 tBA_INST *p_inst = &battery_cb.battery_inst[0];
286 UINT8 i;
287 esp_gatt_status_t st = ESP_GATT_NOT_FOUND;
288 UINT16 handle = p_data->read_req.handle;
289
290
291 for (i = 0; i < BA_MAX_INT_NUM; i ++, p_inst ++) {
292 // read battery level
293 if (handle == p_inst->ba_level_hdl ||
294 handle == p_inst->clt_cfg_hdl ||
295 handle == p_inst->rpt_ref_hdl ||
296 handle == p_inst->pres_fmt_hdl) {
297 if (p_data->read_req.is_long) {
298 st = ESP_GATT_NOT_LONG;
299 }
300
301 if (p_inst->p_cback) {
302 if (handle == p_inst->ba_level_hdl) {
303 p_inst->pending_evt = BA_READ_LEVEL_REQ;
304 }
305 if (handle == p_inst->clt_cfg_hdl) {
306 p_inst->pending_evt = BA_READ_CLT_CFG_REQ;
307 }
308 if (handle == p_inst->pres_fmt_hdl) {
309 p_inst->pending_evt = BA_READ_PRE_FMT_REQ;
310 }
311 if (handle == p_inst->rpt_ref_hdl) {
312 p_inst->pending_evt = BA_READ_RPT_REF_REQ ;
313 }
314
315 // p_inst->pending_clcb_idx = clcb_idx;
316 p_inst->pending_handle = handle;
317 //act = SRVC_ACT_PENDING;
318 (*p_inst->p_cback)(trans_id, conn_id, p_inst->app_id, p_inst->pending_evt, NULL);
319 } else { /* application is not registered */
320 st = ESP_GATT_ERR_UNLIKELY;
321 }
322 break;
323 }
324 /* else attribute not found */
325 }
326 }
327
328 /*****************************************************************************
329 ** Function bas_s_write_attr_value
330 **
331 ** Description it will be called when client sends a write request
332 ******************************************************************************/
bas_s_write_attr_value(tGATTS_DATA * p_data,UINT32 trans_id,UINT16 conn_id,BD_ADDR bd_addr)333 void bas_s_write_attr_value(tGATTS_DATA *p_data, UINT32 trans_id, UINT16 conn_id, BD_ADDR bd_addr)
334 {
335 tBA_WRITE_DATA cfg;
336 UINT8 *p = p_data->write_req.value;
337 tBA_INST *p_inst = &battery_cb.battery_inst[0];
338 UINT8 i;
339 esp_gatt_status_t st = ESP_GATT_NOT_FOUND;
340 UINT16 handle = p_data->write_req.handle;
341
342
343 for (i = 0; i < BA_MAX_INT_NUM; i ++, p_inst ++) {
344 if (handle == p_inst->clt_cfg_hdl) {
345 memcpy(cfg.remote_bda, bd_addr, BD_ADDR_LEN);
346 STREAM_TO_UINT16(cfg.clt_cfg, p);
347
348 if (p_inst->p_cback) {
349 p_inst->pending_evt = BA_WRITE_CLT_CFG_REQ;
350 p_inst->pending_handle = handle;
351 cfg.need_rsp = p_data->write_req.need_rsp;
352 (*p_inst->p_cback)(trans_id, conn_id, p_inst->app_id, p_inst->pending_evt, &cfg);
353 } else { /* all other handle is not writable */
354 st = ESP_GATT_WRITE_NOT_PERMIT;
355 }
356 break;
357 }
358
359 }
360 }
361 /***************************************************************
362 **
363 ** Function bas_register
364 **
365 ** Description register app for battery service
366 **
367 ****************************************************************/
bas_register(void)368 void bas_register(void)
369 {
370 esp_ble_gatts_app_register(&bas_uuid, bas_gatts_callback);
371
372 }
373 /***************************************************************
374 **
375 ** Function bas_init
376 **
377 ** Description register battery service
378 **
379 ****************************************************************/
bas_init(tBTA_GATTS_IF gatt_if,UINT16 app_id)380 void bas_init(tBTA_GATTS_IF gatt_if, UINT16 app_id)
381 {
382
383 tBA_INST *p_inst;
384
385 ba_reg_info.is_pri = true;
386 ba_reg_info.ba_level_descr = BA_LEVEL_NOTIFY;
387 ba_reg_info.transport = GATT_TRANSPORT_LE;
388 ba_reg_info.p_cback = bas_callback;
389 if (battery_cb.inst_id == BA_MAX_INT_NUM) {
390 GATT_TRACE_ERROR("MAX battery service has been reached\n");
391 return;
392 }
393
394 p_inst = &battery_cb.battery_inst[battery_cb.inst_id];
395
396 BTC_TRACE_ERROR("create battery service\n");
397 BTC_TRACE_ERROR("inst_id=%d\n", battery_cb.inst_id);
398 esp_ble_gatts_create_srvc (gatt_if, &bas_uuid, battery_cb.inst_id ,
399 BA_MAX_ATTR_NUM, ba_reg_info.is_pri);
400
401 battery_cb.inst_id ++;
402
403 p_inst->app_id = app_id;
404 p_inst->p_cback = ba_reg_info.p_cback;
405
406 }
407
408 /***************************************************************
409 **
410 ** Function bas_AddChar
411 **
412 ** Description add characteristic for battery service
413 **
414 ****************************************************************/
bas_AddChar(UINT16 service_id,tBT_UUID * char_uuid)415 void bas_AddChar(UINT16 service_id, tBT_UUID *char_uuid)
416 {
417 if (ba_reg_info.ba_level_descr & BA_LEVEL_NOTIFY) {
418 prop |= GATT_CHAR_PROP_BIT_NOTIFY;
419 }
420 attr_handle_bit = 0x01;
421 esp_ble_gatts_add_char(service_id, char_uuid, BATTER_LEVEL_PERM, prop);
422
423 }
424
425 /***************************************************************
426 **
427 ** Function bas_AddCharDescr
428 **
429 ** Description add descriptor for battery service if needed
430 **
431 ****************************************************************/
bas_AddCharDescr(UINT16 service_id,UINT16 attr_id)432 void bas_AddCharDescr(UINT16 service_id, UINT16 attr_id)
433 {
434 tBT_UUID uuid;
435 uuid.len = LEN_UUID_16;
436
437 battery_cb.inst_id --;
438 tBA_INST *p_inst = &battery_cb.battery_inst[battery_cb.inst_id++];
439 /*store the attribute handles*/
440 if (attr_handle_bit == 0x01) {
441 p_inst->ba_level_hdl = attr_id;
442 } else if (attr_handle_bit == 0x02) {
443 p_inst->clt_cfg_hdl = attr_id;
444 } else if (attr_handle_bit == 0x04) {
445 p_inst->pres_fmt_hdl = attr_id;
446 } else if (attr_handle_bit == 0x08) {
447 p_inst->rpt_ref_hdl = attr_id;
448 }
449
450
451 if (ba_reg_info.ba_level_descr != 0) {
452 if (ba_reg_info.ba_level_descr & BA_LEVEL_NOTIFY) {
453 uuid.uu.uuid16 = GATT_UUID_CHAR_CLIENT_CONFIG;
454 ba_reg_info.ba_level_descr &= 0xfe;
455 attr_handle_bit = 0x02;
456 esp_ble_gatts_add_char_descr(service_id, (GATT_PERM_READ | GATT_PERM_WRITE), &uuid);
457 return;
458 }
459
460 /* need presentation format descriptor? */
461 if (ba_reg_info.ba_level_descr & BA_LEVEL_PRE_FMT) {
462 uuid.uu.uuid16 = GATT_UUID_CHAR_PRESENT_FORMAT;
463 esp_ble_gatts_add_char_descr(service_id, GATT_PERM_READ, &uuid);
464 ba_reg_info.ba_level_descr &= 0xfd;
465 attr_handle_bit = 0x04;
466 return;
467 }
468 /* need report reference format descriptor? */
469 if (ba_reg_info.ba_level_descr & BA_LEVEL_RPT_REF) {
470 uuid.uu.uuid16 = GATT_UUID_RPT_REF_DESCR;
471 ba_reg_info.ba_level_descr &= 0xfb;
472 esp_ble_gatts_add_char_descr(service_id, GATT_PERM_READ, &uuid);
473 attr_handle_bit = 0x08;
474 return;
475 }
476 }
477
478 else {
479 esp_ble_gatts_start_srvc(service_id);
480 }
481
482 }
483
484 /***************************************************************
485 **
486 ** Function bas_service_cmpl
487 **
488 ** Description create battery service complete
489 **
490 ****************************************************************/
bas_service_cmpl(UINT16 service_id,esp_gatt_status_t status)491 void bas_service_cmpl(UINT16 service_id, esp_gatt_status_t status)
492 {
493 if (status != ESP_GATT_OK) {
494 battery_cb.inst_id --;
495 esp_ble_gatts_dele_srvc(service_id);
496 }
497
498 }
499 /*******************************************************************************
500 **
501 ** Function Battery_Rsp
502 **
503 ** Description Respond to a battery service request
504 **
505 *******************************************************************************/
Battery_Rsp(UINT32 trans_id,UINT16 conn_id,UINT8 app_id,esp_gatt_status_t st,UINT8 event,tBA_RSP_DATA * p_rsp)506 void Battery_Rsp (UINT32 trans_id, UINT16 conn_id, UINT8 app_id,
507 esp_gatt_status_t st, UINT8 event, tBA_RSP_DATA *p_rsp)
508 {
509 tBA_INST *p_inst = &battery_cb.battery_inst[0];
510 tGATTS_RSP rsp;
511 UINT8 *pp;
512
513 UINT8 i = 0;
514 while (i < BA_MAX_INT_NUM) {
515 if (p_inst->app_id == app_id && p_inst->ba_level_hdl != 0) {
516 break;
517 }
518 i ++;
519 }
520
521 if (i == BA_MAX_INT_NUM) {
522 return;
523 }
524
525 memset(&rsp, 0, sizeof(tGATTS_RSP));
526
527 if (p_inst->pending_evt == event) {
528 switch (event) {
529 case BA_READ_CLT_CFG_REQ:
530 rsp.attr_value.handle = p_inst->pending_handle;
531 rsp.attr_value.len = 2;
532 pp = rsp.attr_value.value;
533 UINT16_TO_STREAM(pp, p_rsp->clt_cfg);
534 esp_ble_gatts_send_rsp(conn_id, trans_id, st, &rsp);
535 //srvc_sr_rsp(p_inst->pending_clcb_idx, st, &rsp);
536 break;
537
538 case BA_READ_LEVEL_REQ:
539 rsp.attr_value.handle = p_inst->pending_handle;
540 rsp.attr_value.len = 1;
541 pp = rsp.attr_value.value;
542 UINT8_TO_STREAM(pp, p_rsp->ba_level);
543 esp_ble_gatts_send_rsp(conn_id, trans_id, st, &rsp);
544 //srvc_sr_rsp(p_inst->pending_clcb_idx, st, &rsp);
545 break;
546
547 case BA_WRITE_CLT_CFG_REQ:
548 esp_ble_gatts_send_rsp(conn_id, trans_id, st, NULL);
549 //srvc_sr_rsp(p_inst->pending_clcb_idx, st, NULL);
550 break;
551
552 case BA_READ_RPT_REF_REQ:
553 rsp.attr_value.handle = p_inst->pending_handle;
554 rsp.attr_value.len = 2;
555 pp = rsp.attr_value.value;
556 UINT8_TO_STREAM(pp, p_rsp->rpt_ref.rpt_id);
557 UINT8_TO_STREAM(pp, p_rsp->rpt_ref.rpt_type);
558 esp_ble_gatts_send_rsp(conn_id, trans_id, st, &rsp);
559 //srvc_sr_rsp(p_inst->pending_clcb_idx, st, &rsp);
560 break;
561
562 default:
563 break;
564 }
565 // p_inst->pending_clcb_idx = 0;
566 p_inst->pending_evt = 0;
567 p_inst->pending_handle = 0;
568 }
569 return;
570 }
571 /*******************************************************************************
572 **
573 ** Function Battery_Notify
574 **
575 ** Description Send battery level notification
576 **
577 *******************************************************************************/
Battery_Notify(UINT16 conn_id,UINT8 app_id,BD_ADDR remote_bda,UINT8 battery_level)578 void Battery_Notify (UINT16 conn_id, UINT8 app_id, BD_ADDR remote_bda, UINT8 battery_level)
579 {
580 tBA_INST *p_inst = &battery_cb.battery_inst[0];
581 UINT8 i = 0;
582
583 while (i < BA_MAX_INT_NUM) {
584 if (p_inst->app_id == app_id && p_inst->ba_level_hdl != 0) {
585 break;
586 }
587 i ++;
588 }
589
590 if (i == BA_MAX_INT_NUM || p_inst->clt_cfg_hdl == 0) {
591 return;
592 }
593 esp_ble_gatts_hdl_val_indica(conn_id, p_inst->ba_level_hdl, 1, &battery_level, false);
594 //srvc_sr_notify(remote_bda, p_inst->ba_level_hdl, 1, &battery_level);
595
596 }
597 #endif
598