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 "bt_btif_gatt"
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 "btif_dm.h"
46 #include "btif_storage.h"
47 #include "btif_config.h"
48
49 #include "btif_gatt.h"
50 #include "btif_gatt_util.h"
51 #include "osi/include/log.h"
52
53 /************************************************************************************
54 ** Constants & Macros
55 ************************************************************************************/
56
57 #define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
58 {\
59 LOG_WARN("%s: BTGATT not initialized", __FUNCTION__);\
60 return BT_STATUS_NOT_READY;\
61 } else {\
62 LOG_VERBOSE("%s", __FUNCTION__);\
63 }
64
65
66 typedef enum {
67 BTIF_GATTS_REGISTER_APP = 2000,
68 BTIF_GATTS_UNREGISTER_APP,
69 BTIF_GATTS_OPEN,
70 BTIF_GATTS_CLOSE,
71 BTIF_GATTS_CREATE_SERVICE,
72 BTIF_GATTS_ADD_INCLUDED_SERVICE,
73 BTIF_GATTS_ADD_CHARACTERISTIC,
74 BTIF_GATTS_ADD_DESCRIPTOR,
75 BTIF_GATTS_START_SERVICE,
76 BTIF_GATTS_STOP_SERVICE,
77 BTIF_GATTS_DELETE_SERVICE,
78 BTIF_GATTS_SEND_INDICATION,
79 BTIF_GATTS_SEND_RESPONSE
80 } btif_gatts_event_t;
81
82 /************************************************************************************
83 ** Local type definitions
84 ************************************************************************************/
85
86 typedef struct
87 {
88 uint8_t value[BTGATT_MAX_ATTR_LEN];
89 btgatt_response_t response;
90 btgatt_srvc_id_t srvc_id;
91 bt_bdaddr_t bd_addr;
92 bt_uuid_t uuid;
93 uint32_t trans_id;
94 uint16_t conn_id;
95 uint16_t srvc_handle;
96 uint16_t incl_handle;
97 uint16_t attr_handle;
98 uint16_t permissions;
99 uint16_t len;
100 uint8_t server_if;
101 uint8_t is_direct;
102 uint8_t num_handles;
103 uint8_t properties;
104 uint8_t confirm;
105 uint8_t status;
106 btgatt_transport_t transport;
107
108 } __attribute__((packed)) btif_gatts_cb_t;
109
110
111 /************************************************************************************
112 ** Static variables
113 ************************************************************************************/
114
115 extern const btgatt_callbacks_t *bt_gatt_callbacks;
116
117
118 /************************************************************************************
119 ** Static functions
120 ************************************************************************************/
121
btapp_gatts_copy_req_data(UINT16 event,char * p_dest,char * p_src)122 static void btapp_gatts_copy_req_data(UINT16 event, char *p_dest, char *p_src)
123 {
124 tBTA_GATTS *p_dest_data = (tBTA_GATTS*) p_dest;
125 tBTA_GATTS *p_src_data = (tBTA_GATTS*) p_src;
126
127 if (!p_src_data || !p_dest_data)
128 return;
129
130 // Copy basic structure first
131 memcpy(p_dest_data, p_src_data, sizeof(tBTA_GATTS));
132
133 // Allocate buffer for request data if necessary
134 switch (event)
135 {
136 case BTA_GATTS_READ_EVT:
137 case BTA_GATTS_WRITE_EVT:
138 case BTA_GATTS_EXEC_WRITE_EVT:
139 case BTA_GATTS_MTU_EVT:
140 p_dest_data->req_data.p_data = GKI_getbuf(sizeof(tBTA_GATTS_REQ_DATA));
141 if (p_dest_data->req_data.p_data != NULL)
142 {
143 memcpy(p_dest_data->req_data.p_data, p_src_data->req_data.p_data,
144 sizeof(tBTA_GATTS_REQ_DATA));
145 }
146 break;
147
148 default:
149 break;
150 }
151 }
152
btapp_gatts_free_req_data(UINT16 event,tBTA_GATTS * p_data)153 static void btapp_gatts_free_req_data(UINT16 event, tBTA_GATTS *p_data)
154 {
155 switch (event)
156 {
157 case BTA_GATTS_READ_EVT:
158 case BTA_GATTS_WRITE_EVT:
159 case BTA_GATTS_EXEC_WRITE_EVT:
160 case BTA_GATTS_MTU_EVT:
161 if (p_data && p_data->req_data.p_data)
162 GKI_freebuf(p_data->req_data.p_data);
163 break;
164
165 default:
166 break;
167 }
168 }
169
btapp_gatts_handle_cback(uint16_t event,char * p_param)170 static void btapp_gatts_handle_cback(uint16_t event, char* p_param)
171 {
172 LOG_VERBOSE("%s: Event %d", __FUNCTION__, event);
173
174 tBTA_GATTS *p_data = (tBTA_GATTS*)p_param;
175 switch (event)
176 {
177 case BTA_GATTS_REG_EVT:
178 {
179 bt_uuid_t app_uuid;
180 bta_to_btif_uuid(&app_uuid, &p_data->reg_oper.uuid);
181 HAL_CBACK(bt_gatt_callbacks, server->register_server_cb
182 , p_data->reg_oper.status
183 , p_data->reg_oper.server_if
184 , &app_uuid
185 );
186 break;
187 }
188
189 case BTA_GATTS_DEREG_EVT:
190 break;
191
192 case BTA_GATTS_CONNECT_EVT:
193 {
194 bt_bdaddr_t bda;
195 bdcpy(bda.address, p_data->conn.remote_bda);
196
197 btif_gatt_check_encrypted_link(p_data->conn.remote_bda, p_data->conn.transport);
198
199 HAL_CBACK(bt_gatt_callbacks, server->connection_cb,
200 p_data->conn.conn_id, p_data->conn.server_if, TRUE, &bda);
201 break;
202 }
203
204 case BTA_GATTS_DISCONNECT_EVT:
205 {
206 bt_bdaddr_t bda;
207 bdcpy(bda.address, p_data->conn.remote_bda);
208
209 HAL_CBACK(bt_gatt_callbacks, server->connection_cb,
210 p_data->conn.conn_id, p_data->conn.server_if, FALSE, &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_CONF_EVT:
326 HAL_CBACK(bt_gatt_callbacks, server->indication_sent_cb,
327 p_data->req_data.conn_id, p_data->req_data.status);
328 break;
329
330 case BTA_GATTS_CONGEST_EVT:
331 HAL_CBACK(bt_gatt_callbacks, server->congestion_cb
332 , p_data->congest.conn_id
333 , p_data->congest.congested
334 );
335 break;
336
337 case BTA_GATTS_MTU_EVT:
338 HAL_CBACK(bt_gatt_callbacks, server->mtu_changed_cb
339 , p_data->req_data.conn_id
340 , p_data->req_data.p_data->mtu
341 );
342 break;
343
344 case BTA_GATTS_OPEN_EVT:
345 case BTA_GATTS_CANCEL_OPEN_EVT:
346 case BTA_GATTS_CLOSE_EVT:
347 LOG_DEBUG("%s: Empty event (%d)!", __FUNCTION__, event);
348 break;
349
350 default:
351 LOG_ERROR("%s: Unhandled event (%d)!", __FUNCTION__, event);
352 break;
353 }
354
355 btapp_gatts_free_req_data(event, p_data);
356 }
357
btapp_gatts_cback(tBTA_GATTS_EVT event,tBTA_GATTS * p_data)358 static void btapp_gatts_cback(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
359 {
360 bt_status_t status;
361 status = btif_transfer_context(btapp_gatts_handle_cback, (uint16_t) event,
362 (void*)p_data, sizeof(tBTA_GATTS), btapp_gatts_copy_req_data);
363 ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
364 }
365
btgatts_handle_event(uint16_t event,char * p_param)366 static void btgatts_handle_event(uint16_t event, char* p_param)
367 {
368 btif_gatts_cb_t* p_cb = (btif_gatts_cb_t*)p_param;
369 if (!p_cb) return;
370
371 LOG_VERBOSE("%s: Event %d", __FUNCTION__, event);
372
373 switch (event)
374 {
375 case BTIF_GATTS_REGISTER_APP:
376 {
377 tBT_UUID uuid;
378 btif_to_bta_uuid(&uuid, &p_cb->uuid);
379 BTA_GATTS_AppRegister(&uuid, btapp_gatts_cback);
380 break;
381 }
382
383 case BTIF_GATTS_UNREGISTER_APP:
384 BTA_GATTS_AppDeregister(p_cb->server_if);
385 break;
386
387 case BTIF_GATTS_OPEN:
388 {
389 // Ensure device is in inquiry database
390 int addr_type = 0;
391 int device_type = 0;
392 tBTA_GATT_TRANSPORT transport = BTA_GATT_TRANSPORT_LE;
393
394 if (btif_get_address_type(p_cb->bd_addr.address, &addr_type) &&
395 btif_get_device_type(p_cb->bd_addr.address, &device_type) &&
396 device_type != BT_DEVICE_TYPE_BREDR)
397 {
398 BTA_DmAddBleDevice(p_cb->bd_addr.address, addr_type, device_type);
399 }
400
401 // Mark background connections
402 if (!p_cb->is_direct)
403 BTA_DmBleSetBgConnType(BTM_BLE_CONN_AUTO, NULL);
404
405 switch(device_type)
406 {
407 case BT_DEVICE_TYPE_BREDR:
408 transport = BTA_GATT_TRANSPORT_BR_EDR;
409 break;
410
411 case BT_DEVICE_TYPE_BLE:
412 transport = BTA_GATT_TRANSPORT_LE;
413 break;
414
415 case BT_DEVICE_TYPE_DUMO:
416 if (p_cb->transport == GATT_TRANSPORT_LE)
417 transport = BTA_GATT_TRANSPORT_LE;
418 else
419 transport = BTA_GATT_TRANSPORT_BR_EDR;
420 break;
421
422 default:
423 BTIF_TRACE_ERROR (" GATT Open :Invalid device type %d",device_type);
424 return;
425 }
426
427 // Connect!
428 BTA_GATTS_Open(p_cb->server_if, p_cb->bd_addr.address,
429 p_cb->is_direct, transport);
430 break;
431 }
432
433 case BTIF_GATTS_CLOSE:
434 // Cancel pending foreground/background connections
435 BTA_GATTS_CancelOpen(p_cb->server_if, p_cb->bd_addr.address, TRUE);
436 BTA_GATTS_CancelOpen(p_cb->server_if, p_cb->bd_addr.address, FALSE);
437
438 // Close active connection
439 if (p_cb->conn_id != 0)
440 BTA_GATTS_Close(p_cb->conn_id);
441 break;
442
443 case BTIF_GATTS_CREATE_SERVICE:
444 {
445 tBTA_GATT_SRVC_ID srvc_id;
446 btif_to_bta_srvc_id(&srvc_id, &p_cb->srvc_id);
447 BTA_GATTS_CreateService(p_cb->server_if, &srvc_id.id.uuid,
448 srvc_id.id.inst_id, p_cb->num_handles,
449 srvc_id.is_primary);
450 break;
451 }
452
453 case BTIF_GATTS_ADD_INCLUDED_SERVICE:
454 BTA_GATTS_AddIncludeService(p_cb->srvc_handle, p_cb->incl_handle);
455 break;
456
457 case BTIF_GATTS_ADD_CHARACTERISTIC:
458 {
459 tBT_UUID uuid;
460 btif_to_bta_uuid(&uuid, &p_cb->uuid);
461
462 BTA_GATTS_AddCharacteristic(p_cb->srvc_handle, &uuid,
463 p_cb->permissions, p_cb->properties);
464 break;
465 }
466
467 case BTIF_GATTS_ADD_DESCRIPTOR:
468 {
469 tBT_UUID uuid;
470 btif_to_bta_uuid(&uuid, &p_cb->uuid);
471
472 BTA_GATTS_AddCharDescriptor(p_cb->srvc_handle, p_cb->permissions,
473 &uuid);
474 break;
475 }
476
477 case BTIF_GATTS_START_SERVICE:
478 BTA_GATTS_StartService(p_cb->srvc_handle, p_cb->transport);
479 break;
480
481 case BTIF_GATTS_STOP_SERVICE:
482 BTA_GATTS_StopService(p_cb->srvc_handle);
483 break;
484
485 case BTIF_GATTS_DELETE_SERVICE:
486 BTA_GATTS_DeleteService(p_cb->srvc_handle);
487 break;
488
489 case BTIF_GATTS_SEND_INDICATION:
490 BTA_GATTS_HandleValueIndication(p_cb->conn_id, p_cb->attr_handle,
491 p_cb->len, p_cb->value, p_cb->confirm);
492 // TODO: Might need to send an ACK if handle value indication is
493 // invoked without need for confirmation.
494 break;
495
496 case BTIF_GATTS_SEND_RESPONSE:
497 {
498 tBTA_GATTS_RSP rsp_struct;
499 btgatt_response_t *p_rsp = &p_cb->response;
500 btif_to_bta_response(&rsp_struct, p_rsp);
501
502 BTA_GATTS_SendRsp(p_cb->conn_id, p_cb->trans_id,
503 p_cb->status, &rsp_struct);
504
505 HAL_CBACK(bt_gatt_callbacks, server->response_confirmation_cb,
506 0, rsp_struct.attr_value.handle);
507 break;
508 }
509
510 default:
511 LOG_ERROR("%s: Unknown event (%d)!", __FUNCTION__, event);
512 break;
513 }
514 }
515
516 /************************************************************************************
517 ** Server API Functions
518 ************************************************************************************/
519
btif_gatts_register_app(bt_uuid_t * uuid)520 static bt_status_t btif_gatts_register_app(bt_uuid_t *uuid)
521 {
522 CHECK_BTGATT_INIT();
523 btif_gatts_cb_t btif_cb;
524 memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
525 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_REGISTER_APP,
526 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
527 }
528
btif_gatts_unregister_app(int server_if)529 static bt_status_t btif_gatts_unregister_app( int server_if )
530 {
531 CHECK_BTGATT_INIT();
532 btif_gatts_cb_t btif_cb;
533 btif_cb.server_if = (uint8_t) server_if;
534 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_UNREGISTER_APP,
535 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
536 }
537
btif_gatts_open(int server_if,const bt_bdaddr_t * bd_addr,bool is_direct,int transport)538 static bt_status_t btif_gatts_open( int server_if, const bt_bdaddr_t *bd_addr,
539 bool is_direct, int transport )
540 {
541 CHECK_BTGATT_INIT();
542 btif_gatts_cb_t btif_cb;
543 btif_cb.server_if = (uint8_t) server_if;
544 btif_cb.is_direct = is_direct ? 1 : 0;
545 btif_cb.transport = (btgatt_transport_t)transport;
546 bdcpy(btif_cb.bd_addr.address, bd_addr->address);
547 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_OPEN,
548 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
549 }
550
btif_gatts_close(int server_if,const bt_bdaddr_t * bd_addr,int conn_id)551 static bt_status_t btif_gatts_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
552 {
553 CHECK_BTGATT_INIT();
554 btif_gatts_cb_t btif_cb;
555 btif_cb.server_if = (uint8_t) server_if;
556 btif_cb.conn_id = (uint16_t) conn_id;
557 bdcpy(btif_cb.bd_addr.address, bd_addr->address);
558 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_CLOSE,
559 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
560 }
561
btif_gatts_add_service(int server_if,btgatt_srvc_id_t * srvc_id,int num_handles)562 static bt_status_t btif_gatts_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
563 int num_handles)
564 {
565 CHECK_BTGATT_INIT();
566 btif_gatts_cb_t btif_cb;
567 btif_cb.server_if = (uint8_t) server_if;
568 btif_cb.num_handles = (uint8_t) num_handles;
569 memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
570 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_CREATE_SERVICE,
571 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
572 }
573
btif_gatts_add_included_service(int server_if,int service_handle,int included_handle)574 static bt_status_t btif_gatts_add_included_service(int server_if, int service_handle,
575 int included_handle)
576 {
577 CHECK_BTGATT_INIT();
578 btif_gatts_cb_t btif_cb;
579 btif_cb.server_if = (uint8_t) server_if;
580 btif_cb.srvc_handle = (uint16_t) service_handle;
581 btif_cb.incl_handle = (uint16_t) included_handle;
582 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_ADD_INCLUDED_SERVICE,
583 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
584 }
585
btif_gatts_add_characteristic(int server_if,int service_handle,bt_uuid_t * uuid,int properties,int permissions)586 static bt_status_t btif_gatts_add_characteristic(int server_if, int service_handle,
587 bt_uuid_t *uuid, int properties,
588 int permissions)
589 {
590 CHECK_BTGATT_INIT();
591 btif_gatts_cb_t btif_cb;
592 btif_cb.server_if = (uint8_t) server_if;
593 btif_cb.srvc_handle = (uint16_t) service_handle;
594 btif_cb.properties = (uint8_t) properties;
595 btif_cb.permissions = (uint16_t) permissions;
596 memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
597 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_ADD_CHARACTERISTIC,
598 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
599 }
600
btif_gatts_add_descriptor(int server_if,int service_handle,bt_uuid_t * uuid,int permissions)601 static bt_status_t btif_gatts_add_descriptor(int server_if, int service_handle, bt_uuid_t *uuid,
602 int permissions)
603 {
604 CHECK_BTGATT_INIT();
605 btif_gatts_cb_t btif_cb;
606 btif_cb.server_if = (uint8_t) server_if;
607 btif_cb.srvc_handle = (uint16_t) service_handle;
608 btif_cb.permissions = (uint16_t) permissions;
609 memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
610 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_ADD_DESCRIPTOR,
611 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
612 }
613
btif_gatts_start_service(int server_if,int service_handle,int transport)614 static bt_status_t btif_gatts_start_service(int server_if, int service_handle, int transport)
615 {
616 CHECK_BTGATT_INIT();
617 btif_gatts_cb_t btif_cb;
618 btif_cb.server_if = (uint8_t) server_if;
619 btif_cb.srvc_handle = (uint16_t) service_handle;
620 btif_cb.transport = (uint8_t) transport;
621 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_START_SERVICE,
622 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
623 }
624
btif_gatts_stop_service(int server_if,int service_handle)625 static bt_status_t btif_gatts_stop_service(int server_if, int service_handle)
626 {
627 CHECK_BTGATT_INIT();
628 btif_gatts_cb_t btif_cb;
629 btif_cb.server_if = (uint8_t) server_if;
630 btif_cb.srvc_handle = (uint16_t) service_handle;
631 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_STOP_SERVICE,
632 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
633 }
634
btif_gatts_delete_service(int server_if,int service_handle)635 static bt_status_t btif_gatts_delete_service(int server_if, int service_handle)
636 {
637 CHECK_BTGATT_INIT();
638 btif_gatts_cb_t btif_cb;
639 btif_cb.server_if = (uint8_t) server_if;
640 btif_cb.srvc_handle = (uint16_t) service_handle;
641 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_DELETE_SERVICE,
642 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
643 }
644
btif_gatts_send_indication(int server_if,int attribute_handle,int conn_id,int len,int confirm,char * p_value)645 static bt_status_t btif_gatts_send_indication(int server_if, int attribute_handle, int conn_id,
646 int len, int confirm, char* p_value)
647 {
648 CHECK_BTGATT_INIT();
649 btif_gatts_cb_t btif_cb;
650 btif_cb.server_if = (uint8_t) server_if;
651 btif_cb.conn_id = (uint16_t) conn_id;
652 btif_cb.attr_handle = attribute_handle;
653 btif_cb.confirm = confirm;
654 btif_cb.len = len;
655 memcpy(btif_cb.value, p_value, len > BTGATT_MAX_ATTR_LEN ? BTGATT_MAX_ATTR_LEN : len);
656 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_SEND_INDICATION,
657 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
658 }
659
btif_gatts_send_response(int conn_id,int trans_id,int status,btgatt_response_t * response)660 static bt_status_t btif_gatts_send_response(int conn_id, int trans_id,
661 int status, btgatt_response_t *response)
662 {
663 CHECK_BTGATT_INIT();
664 btif_gatts_cb_t btif_cb;
665 btif_cb.conn_id = (uint16_t) conn_id;
666 btif_cb.trans_id = (uint32_t) trans_id;
667 btif_cb.status = (uint8_t) status;
668 memcpy(&btif_cb.response, response, sizeof(btgatt_response_t));
669 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_SEND_RESPONSE,
670 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
671 }
672
673 const btgatt_server_interface_t btgattServerInterface = {
674 btif_gatts_register_app,
675 btif_gatts_unregister_app,
676 btif_gatts_open,
677 btif_gatts_close,
678 btif_gatts_add_service,
679 btif_gatts_add_included_service,
680 btif_gatts_add_characteristic,
681 btif_gatts_add_descriptor,
682 btif_gatts_start_service,
683 btif_gatts_stop_service,
684 btif_gatts_delete_service,
685 btif_gatts_send_indication,
686 btif_gatts_send_response
687 };
688
689 #endif
690