1 /******************************************************************************
2 *
3 * Copyright (C) 2009-2013 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19
20 /************************************************************************************
21 *
22 * Filename: btif_gatt_server.c
23 *
24 * Description: GATT server implementation
25 *
26 ***********************************************************************************/
27
28 #include <hardware/bluetooth.h>
29 #include <hardware/bt_gatt.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <errno.h>
33 #include <string.h>
34
35 #define LOG_TAG "BtGatt.btif"
36
37 #include "btif_common.h"
38 #include "btif_util.h"
39
40 #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
41
42 #include "gki.h"
43 #include "bta_api.h"
44 #include "bta_gatt_api.h"
45 #include "bd.h"
46 #include "btif_dm.h"
47 #include "btif_storage.h"
48
49 #include "btif_gatt.h"
50 #include "btif_gatt_util.h"
51
52 /************************************************************************************
53 ** Constants & Macros
54 ************************************************************************************/
55
56 #define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
57 {\
58 ALOGW("%s: BTGATT not initialized", __FUNCTION__);\
59 return BT_STATUS_NOT_READY;\
60 } else {\
61 ALOGD("%s", __FUNCTION__);\
62 }
63
64
65 typedef enum {
66 BTIF_GATTS_REGISTER_APP = 2000,
67 BTIF_GATTS_UNREGISTER_APP,
68 BTIF_GATTS_OPEN,
69 BTIF_GATTS_CLOSE,
70 BTIF_GATTS_CREATE_SERVICE,
71 BTIF_GATTS_ADD_INCLUDED_SERVICE,
72 BTIF_GATTS_ADD_CHARACTERISTIC,
73 BTIF_GATTS_ADD_DESCRIPTOR,
74 BTIF_GATTS_START_SERVICE,
75 BTIF_GATTS_STOP_SERVICE,
76 BTIF_GATTS_DELETE_SERVICE,
77 BTIF_GATTS_SEND_INDICATION,
78 BTIF_GATTS_SEND_RESPONSE
79 } btif_gatts_event_t;
80
81 /************************************************************************************
82 ** Local type definitions
83 ************************************************************************************/
84
85 typedef struct
86 {
87 uint8_t value[BTGATT_MAX_ATTR_LEN];
88 btgatt_response_t response;
89 btgatt_srvc_id_t srvc_id;
90 bt_bdaddr_t bd_addr;
91 bt_uuid_t uuid;
92 uint32_t trans_id;
93 uint16_t conn_id;
94 uint16_t srvc_handle;
95 uint16_t incl_handle;
96 uint16_t attr_handle;
97 uint16_t permissions;
98 uint16_t len;
99 uint8_t server_if;
100 uint8_t is_direct;
101 uint8_t num_handles;
102 uint8_t properties;
103 uint8_t transport;
104 uint8_t confirm;
105 uint8_t status;
106 } __attribute__((packed)) btif_gatts_cb_t;
107
108
109 /************************************************************************************
110 ** Static variables
111 ************************************************************************************/
112
113 extern const btgatt_callbacks_t *bt_gatt_callbacks;
114
115
116 /************************************************************************************
117 ** Static functions
118 ************************************************************************************/
119
btapp_gatts_copy_req_data(UINT16 event,char * p_dest,char * p_src)120 static void btapp_gatts_copy_req_data(UINT16 event, char *p_dest, char *p_src)
121 {
122 tBTA_GATTS *p_dest_data = (tBTA_GATTS*) p_dest;
123 tBTA_GATTS *p_src_data = (tBTA_GATTS*) p_src;
124
125 if (!p_src_data || !p_dest_data)
126 return;
127
128 // Copy basic structure first
129 memcpy(p_dest_data, p_src_data, sizeof(tBTA_GATTS));
130
131 // Allocate buffer for request data if necessary
132 switch (event)
133 {
134 case BTA_GATTS_READ_EVT:
135 case BTA_GATTS_WRITE_EVT:
136 case BTA_GATTS_EXEC_WRITE_EVT:
137 case BTA_GATTS_MTU_EVT:
138 p_dest_data->req_data.p_data = GKI_getbuf(sizeof(tBTA_GATTS_REQ_DATA));
139 if (p_dest_data->req_data.p_data != NULL)
140 {
141 memcpy(p_dest_data->req_data.p_data, p_src_data->req_data.p_data,
142 sizeof(tBTA_GATTS_REQ_DATA));
143 }
144 break;
145
146 default:
147 break;
148 }
149 }
150
btapp_gatts_free_req_data(UINT16 event,tBTA_GATTS * p_data)151 static void btapp_gatts_free_req_data(UINT16 event, tBTA_GATTS *p_data)
152 {
153 switch (event)
154 {
155 case BTA_GATTS_READ_EVT:
156 case BTA_GATTS_WRITE_EVT:
157 case BTA_GATTS_EXEC_WRITE_EVT:
158 case BTA_GATTS_MTU_EVT:
159 if (p_data && p_data->req_data.p_data)
160 GKI_freebuf(p_data->req_data.p_data);
161 break;
162
163 default:
164 break;
165 }
166 }
167
btapp_gatts_handle_cback(uint16_t event,char * p_param)168 static void btapp_gatts_handle_cback(uint16_t event, char* p_param)
169 {
170 ALOGD("%s: Event %d", __FUNCTION__, event);
171
172 tBTA_GATTS *p_data = (tBTA_GATTS*)p_param;
173 switch (event)
174 {
175 case BTA_GATTS_REG_EVT:
176 {
177 bt_uuid_t app_uuid;
178 bta_to_btif_uuid(&app_uuid, &p_data->reg_oper.uuid);
179 HAL_CBACK(bt_gatt_callbacks, server->register_server_cb
180 , p_data->reg_oper.status
181 , p_data->reg_oper.server_if
182 , &app_uuid
183 );
184 break;
185 }
186
187 case BTA_GATTS_DEREG_EVT:
188 break;
189
190 case BTA_GATTS_CONNECT_EVT:
191 {
192 bt_bdaddr_t bda;
193 bdcpy(bda.address, p_data->conn.remote_bda);
194
195 btif_gatt_check_encrypted_link(p_data->conn.remote_bda);
196
197 HAL_CBACK(bt_gatt_callbacks, server->connection_cb,
198 p_data->conn.conn_id, p_data->conn.server_if, TRUE, &bda);
199 break;
200 }
201
202 case BTA_GATTS_DISCONNECT_EVT:
203 {
204 bt_bdaddr_t bda;
205 bdcpy(bda.address, p_data->conn.remote_bda);
206
207 HAL_CBACK(bt_gatt_callbacks, server->connection_cb,
208 p_data->conn.conn_id, p_data->conn.server_if, FALSE, &bda);
209
210 btif_gatt_remove_encrypted_link(p_data->conn.remote_bda);
211 break;
212 }
213
214 case BTA_GATTS_CREATE_EVT:
215 {
216 btgatt_srvc_id_t srvc_id;
217 srvc_id.is_primary = p_data->create.is_primary;
218 srvc_id.id.inst_id = p_data->create.svc_instance;
219 bta_to_btif_uuid(&srvc_id.id.uuid, &p_data->create.uuid);
220
221 HAL_CBACK(bt_gatt_callbacks, server->service_added_cb,
222 p_data->create.status, p_data->create.server_if, &srvc_id,
223 p_data->create.service_id
224 );
225 }
226 break;
227
228 case BTA_GATTS_ADD_INCL_SRVC_EVT:
229 HAL_CBACK(bt_gatt_callbacks, server->included_service_added_cb,
230 p_data->add_result.status,
231 p_data->add_result.server_if,
232 p_data->add_result.service_id,
233 p_data->add_result.attr_id);
234 break;
235
236 case BTA_GATTS_ADD_CHAR_EVT:
237 {
238 bt_uuid_t uuid;
239 bta_to_btif_uuid(&uuid, &p_data->add_result.char_uuid);
240
241 HAL_CBACK(bt_gatt_callbacks, server->characteristic_added_cb,
242 p_data->add_result.status,
243 p_data->add_result.server_if,
244 &uuid,
245 p_data->add_result.service_id,
246 p_data->add_result.attr_id);
247 break;
248 }
249
250 case BTA_GATTS_ADD_CHAR_DESCR_EVT:
251 {
252 bt_uuid_t uuid;
253 bta_to_btif_uuid(&uuid, &p_data->add_result.char_uuid);
254
255 HAL_CBACK(bt_gatt_callbacks, server->descriptor_added_cb,
256 p_data->add_result.status,
257 p_data->add_result.server_if,
258 &uuid,
259 p_data->add_result.service_id,
260 p_data->add_result.attr_id);
261 break;
262 }
263
264 case BTA_GATTS_START_EVT:
265 HAL_CBACK(bt_gatt_callbacks, server->service_started_cb,
266 p_data->srvc_oper.status,
267 p_data->srvc_oper.server_if,
268 p_data->srvc_oper.service_id);
269 break;
270
271 case BTA_GATTS_STOP_EVT:
272 HAL_CBACK(bt_gatt_callbacks, server->service_stopped_cb,
273 p_data->srvc_oper.status,
274 p_data->srvc_oper.server_if,
275 p_data->srvc_oper.service_id);
276 break;
277
278 case BTA_GATTS_DELELTE_EVT:
279 HAL_CBACK(bt_gatt_callbacks, server->service_deleted_cb,
280 p_data->srvc_oper.status,
281 p_data->srvc_oper.server_if,
282 p_data->srvc_oper.service_id);
283 break;
284
285 case BTA_GATTS_READ_EVT:
286 {
287 bt_bdaddr_t bda;
288 bdcpy(bda.address, p_data->req_data.remote_bda);
289
290 HAL_CBACK(bt_gatt_callbacks, server->request_read_cb,
291 p_data->req_data.conn_id,p_data->req_data.trans_id, &bda,
292 p_data->req_data.p_data->read_req.handle,
293 p_data->req_data.p_data->read_req.offset,
294 p_data->req_data.p_data->read_req.is_long);
295 break;
296 }
297
298 case BTA_GATTS_WRITE_EVT:
299 {
300 bt_bdaddr_t bda;
301 bdcpy(bda.address, p_data->req_data.remote_bda);
302
303 HAL_CBACK(bt_gatt_callbacks, server->request_write_cb,
304 p_data->req_data.conn_id,p_data->req_data.trans_id, &bda,
305 p_data->req_data.p_data->write_req.handle,
306 p_data->req_data.p_data->write_req.offset,
307 p_data->req_data.p_data->write_req.len,
308 p_data->req_data.p_data->write_req.need_rsp,
309 p_data->req_data.p_data->write_req.is_prep,
310 p_data->req_data.p_data->write_req.value);
311 break;
312 }
313
314 case BTA_GATTS_EXEC_WRITE_EVT:
315 {
316 bt_bdaddr_t bda;
317 bdcpy(bda.address, p_data->req_data.remote_bda);
318
319 HAL_CBACK(bt_gatt_callbacks, server->request_exec_write_cb,
320 p_data->req_data.conn_id,p_data->req_data.trans_id, &bda,
321 p_data->req_data.p_data->exec_write);
322 break;
323 }
324
325 case BTA_GATTS_MTU_EVT:
326 case BTA_GATTS_OPEN_EVT:
327 case BTA_GATTS_CANCEL_OPEN_EVT:
328 case BTA_GATTS_CLOSE_EVT:
329 ALOGD("%s: Empty event (%d)!", __FUNCTION__, event);
330 break;
331
332 default:
333 ALOGE("%s: Unhandled event (%d)!", __FUNCTION__, event);
334 break;
335 }
336
337 btapp_gatts_free_req_data(event, p_data);
338 }
339
btapp_gatts_cback(tBTA_GATTS_EVT event,tBTA_GATTS * p_data)340 static void btapp_gatts_cback(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
341 {
342 bt_status_t status;
343 status = btif_transfer_context(btapp_gatts_handle_cback, (uint16_t) event,
344 (void*)p_data, sizeof(tBTA_GATTS), btapp_gatts_copy_req_data);
345 ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
346 }
347
btgatts_handle_event(uint16_t event,char * p_param)348 static void btgatts_handle_event(uint16_t event, char* p_param)
349 {
350 btif_gatts_cb_t* p_cb = (btif_gatts_cb_t*)p_param;
351 if (!p_cb) return;
352
353 ALOGD("%s: Event %d", __FUNCTION__, event);
354
355 switch (event)
356 {
357 case BTIF_GATTS_REGISTER_APP:
358 {
359 tBT_UUID uuid;
360 btif_to_bta_uuid(&uuid, &p_cb->uuid);
361 BTA_GATTS_AppRegister(&uuid, btapp_gatts_cback);
362 break;
363 }
364
365 case BTIF_GATTS_UNREGISTER_APP:
366 BTA_GATTS_AppDeregister(p_cb->server_if);
367 break;
368
369 case BTIF_GATTS_OPEN:
370 if (!p_cb->is_direct)
371 BTA_DmBleSetBgConnType(BTM_BLE_CONN_AUTO, NULL);
372 BTA_GATTS_Open(p_cb->server_if, p_cb->bd_addr.address,
373 p_cb->is_direct);
374 break;
375
376 case BTIF_GATTS_CLOSE:
377 // Cancel pending foreground/background connections
378 BTA_GATTS_CancelOpen(p_cb->server_if, p_cb->bd_addr.address, TRUE);
379 BTA_GATTS_CancelOpen(p_cb->server_if, p_cb->bd_addr.address, FALSE);
380
381 // Close active connection
382 if (p_cb->conn_id != 0)
383 BTA_GATTS_Close(p_cb->conn_id);
384 break;
385
386 case BTIF_GATTS_CREATE_SERVICE:
387 {
388 tBTA_GATT_SRVC_ID srvc_id;
389 btif_to_bta_srvc_id(&srvc_id, &p_cb->srvc_id);
390 BTA_GATTS_CreateService(p_cb->server_if, &srvc_id.id.uuid,
391 srvc_id.id.inst_id, p_cb->num_handles,
392 srvc_id.is_primary);
393 break;
394 }
395
396 case BTIF_GATTS_ADD_INCLUDED_SERVICE:
397 BTA_GATTS_AddIncludeService(p_cb->srvc_handle, p_cb->incl_handle);
398 break;
399
400 case BTIF_GATTS_ADD_CHARACTERISTIC:
401 {
402 tBT_UUID uuid;
403 btif_to_bta_uuid(&uuid, &p_cb->uuid);
404
405 BTA_GATTS_AddCharacteristic(p_cb->srvc_handle, &uuid,
406 p_cb->permissions, p_cb->properties);
407 break;
408 }
409
410 case BTIF_GATTS_ADD_DESCRIPTOR:
411 {
412 tBT_UUID uuid;
413 btif_to_bta_uuid(&uuid, &p_cb->uuid);
414
415 BTA_GATTS_AddCharDescriptor(p_cb->srvc_handle, p_cb->permissions,
416 &uuid);
417 break;
418 }
419
420 case BTIF_GATTS_START_SERVICE:
421 BTA_GATTS_StartService(p_cb->srvc_handle, p_cb->transport);
422 break;
423
424 case BTIF_GATTS_STOP_SERVICE:
425 BTA_GATTS_StopService(p_cb->srvc_handle);
426 break;
427
428 case BTIF_GATTS_DELETE_SERVICE:
429 BTA_GATTS_DeleteService(p_cb->srvc_handle);
430 break;
431
432 case BTIF_GATTS_SEND_INDICATION:
433 BTA_GATTS_HandleValueIndication(p_cb->conn_id, p_cb->attr_handle,
434 p_cb->len, p_cb->value, p_cb->confirm);
435 // TODO: Might need to send an ACK if handle value indication is
436 // invoked without need for confirmation.
437 break;
438
439 case BTIF_GATTS_SEND_RESPONSE:
440 {
441 tBTA_GATTS_RSP rsp_struct;
442 btgatt_response_t *p_rsp = &p_cb->response;
443 btif_to_bta_response(&rsp_struct, p_rsp);
444
445 BTA_GATTS_SendRsp(p_cb->conn_id, p_cb->trans_id,
446 p_cb->status, &rsp_struct);
447
448 HAL_CBACK(bt_gatt_callbacks, server->response_confirmation_cb,
449 0, rsp_struct.attr_value.handle);
450 break;
451 }
452
453 default:
454 ALOGE("%s: Unknown event (%d)!", __FUNCTION__, event);
455 break;
456 }
457 }
458
459 /************************************************************************************
460 ** Server API Functions
461 ************************************************************************************/
462
btif_gatts_register_app(bt_uuid_t * uuid)463 static bt_status_t btif_gatts_register_app(bt_uuid_t *uuid)
464 {
465 CHECK_BTGATT_INIT();
466 btif_gatts_cb_t btif_cb;
467 memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
468 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_REGISTER_APP,
469 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
470 }
471
btif_gatts_unregister_app(int server_if)472 static bt_status_t btif_gatts_unregister_app( int server_if )
473 {
474 CHECK_BTGATT_INIT();
475 btif_gatts_cb_t btif_cb;
476 btif_cb.server_if = (uint8_t) server_if;
477 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_UNREGISTER_APP,
478 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
479 }
480
btif_gatts_open(int server_if,const bt_bdaddr_t * bd_addr,bool is_direct)481 static bt_status_t btif_gatts_open( int server_if, const bt_bdaddr_t *bd_addr, bool is_direct )
482 {
483 CHECK_BTGATT_INIT();
484 btif_gatts_cb_t btif_cb;
485 btif_cb.server_if = (uint8_t) server_if;
486 btif_cb.is_direct = is_direct ? 1 : 0;
487 bdcpy(btif_cb.bd_addr.address, bd_addr->address);
488 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_OPEN,
489 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
490 }
491
btif_gatts_close(int server_if,const bt_bdaddr_t * bd_addr,int conn_id)492 static bt_status_t btif_gatts_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
493 {
494 CHECK_BTGATT_INIT();
495 btif_gatts_cb_t btif_cb;
496 btif_cb.server_if = (uint8_t) server_if;
497 btif_cb.conn_id = (uint16_t) conn_id;
498 bdcpy(btif_cb.bd_addr.address, bd_addr->address);
499 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_CLOSE,
500 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
501 }
502
btif_gatts_add_service(int server_if,btgatt_srvc_id_t * srvc_id,int num_handles)503 static bt_status_t btif_gatts_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
504 int num_handles)
505 {
506 CHECK_BTGATT_INIT();
507 btif_gatts_cb_t btif_cb;
508 btif_cb.server_if = (uint8_t) server_if;
509 btif_cb.num_handles = (uint8_t) num_handles;
510 memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
511 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_CREATE_SERVICE,
512 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
513 }
514
btif_gatts_add_included_service(int server_if,int service_handle,int included_handle)515 static bt_status_t btif_gatts_add_included_service(int server_if, int service_handle,
516 int included_handle)
517 {
518 CHECK_BTGATT_INIT();
519 btif_gatts_cb_t btif_cb;
520 btif_cb.server_if = (uint8_t) server_if;
521 btif_cb.srvc_handle = (uint16_t) service_handle;
522 btif_cb.incl_handle = (uint16_t) included_handle;
523 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_ADD_INCLUDED_SERVICE,
524 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
525 }
526
btif_gatts_add_characteristic(int server_if,int service_handle,bt_uuid_t * uuid,int properties,int permissions)527 static bt_status_t btif_gatts_add_characteristic(int server_if, int service_handle,
528 bt_uuid_t *uuid, int properties,
529 int permissions)
530 {
531 CHECK_BTGATT_INIT();
532 btif_gatts_cb_t btif_cb;
533 btif_cb.server_if = (uint8_t) server_if;
534 btif_cb.srvc_handle = (uint16_t) service_handle;
535 btif_cb.properties = (uint8_t) properties;
536 btif_cb.permissions = (uint16_t) permissions;
537 memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
538 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_ADD_CHARACTERISTIC,
539 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
540 }
541
btif_gatts_add_descriptor(int server_if,int service_handle,bt_uuid_t * uuid,int permissions)542 static bt_status_t btif_gatts_add_descriptor(int server_if, int service_handle, bt_uuid_t *uuid,
543 int permissions)
544 {
545 CHECK_BTGATT_INIT();
546 btif_gatts_cb_t btif_cb;
547 btif_cb.server_if = (uint8_t) server_if;
548 btif_cb.srvc_handle = (uint16_t) service_handle;
549 btif_cb.permissions = (uint16_t) permissions;
550 memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
551 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_ADD_DESCRIPTOR,
552 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
553 }
554
btif_gatts_start_service(int server_if,int service_handle,int transport)555 static bt_status_t btif_gatts_start_service(int server_if, int service_handle, int transport)
556 {
557 CHECK_BTGATT_INIT();
558 btif_gatts_cb_t btif_cb;
559 btif_cb.server_if = (uint8_t) server_if;
560 btif_cb.srvc_handle = (uint16_t) service_handle;
561 btif_cb.transport = (uint8_t) transport;
562 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_START_SERVICE,
563 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
564 }
565
btif_gatts_stop_service(int server_if,int service_handle)566 static bt_status_t btif_gatts_stop_service(int server_if, int service_handle)
567 {
568 CHECK_BTGATT_INIT();
569 btif_gatts_cb_t btif_cb;
570 btif_cb.server_if = (uint8_t) server_if;
571 btif_cb.srvc_handle = (uint16_t) service_handle;
572 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_STOP_SERVICE,
573 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
574 }
575
btif_gatts_delete_service(int server_if,int service_handle)576 static bt_status_t btif_gatts_delete_service(int server_if, int service_handle)
577 {
578 CHECK_BTGATT_INIT();
579 btif_gatts_cb_t btif_cb;
580 btif_cb.server_if = (uint8_t) server_if;
581 btif_cb.srvc_handle = (uint16_t) service_handle;
582 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_DELETE_SERVICE,
583 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
584 }
585
btif_gatts_send_indication(int server_if,int attribute_handle,int conn_id,int len,int confirm,char * p_value)586 static bt_status_t btif_gatts_send_indication(int server_if, int attribute_handle, int conn_id,
587 int len, int confirm, char* p_value)
588 {
589 CHECK_BTGATT_INIT();
590 btif_gatts_cb_t btif_cb;
591 btif_cb.server_if = (uint8_t) server_if;
592 btif_cb.conn_id = (uint16_t) conn_id;
593 btif_cb.attr_handle = attribute_handle;
594 btif_cb.confirm = confirm;
595 btif_cb.len = len;
596 memcpy(btif_cb.value, p_value, len > BTGATT_MAX_ATTR_LEN ? BTGATT_MAX_ATTR_LEN : len);
597 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_SEND_INDICATION,
598 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
599 }
600
btif_gatts_send_response(int conn_id,int trans_id,int status,btgatt_response_t * response)601 static bt_status_t btif_gatts_send_response(int conn_id, int trans_id,
602 int status, btgatt_response_t *response)
603 {
604 CHECK_BTGATT_INIT();
605 btif_gatts_cb_t btif_cb;
606 btif_cb.conn_id = (uint16_t) conn_id;
607 btif_cb.trans_id = (uint32_t) trans_id;
608 btif_cb.status = (uint8_t) status;
609 memcpy(&btif_cb.response, response, sizeof(btgatt_response_t));
610 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_SEND_RESPONSE,
611 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
612 }
613
614 const btgatt_server_interface_t btgattServerInterface = {
615 btif_gatts_register_app,
616 btif_gatts_unregister_app,
617 btif_gatts_open,
618 btif_gatts_close,
619 btif_gatts_add_service,
620 btif_gatts_add_included_service,
621 btif_gatts_add_characteristic,
622 btif_gatts_add_descriptor,
623 btif_gatts_start_service,
624 btif_gatts_stop_service,
625 btif_gatts_delete_service,
626 btif_gatts_send_indication,
627 btif_gatts_send_response
628 };
629
630 #endif
631