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 confirm;
104 uint8_t status;
105 btgatt_transport_t transport;
106
107 } __attribute__((packed)) btif_gatts_cb_t;
108
109
110 /************************************************************************************
111 ** Static variables
112 ************************************************************************************/
113
114 extern const btgatt_callbacks_t *bt_gatt_callbacks;
115
116
117 /************************************************************************************
118 ** Static functions
119 ************************************************************************************/
120
btapp_gatts_copy_req_data(UINT16 event,char * p_dest,char * p_src)121 static void btapp_gatts_copy_req_data(UINT16 event, char *p_dest, char *p_src)
122 {
123 tBTA_GATTS *p_dest_data = (tBTA_GATTS*) p_dest;
124 tBTA_GATTS *p_src_data = (tBTA_GATTS*) p_src;
125
126 if (!p_src_data || !p_dest_data)
127 return;
128
129 // Copy basic structure first
130 memcpy(p_dest_data, p_src_data, sizeof(tBTA_GATTS));
131
132 // Allocate buffer for request data if necessary
133 switch (event)
134 {
135 case BTA_GATTS_READ_EVT:
136 case BTA_GATTS_WRITE_EVT:
137 case BTA_GATTS_EXEC_WRITE_EVT:
138 case BTA_GATTS_MTU_EVT:
139 p_dest_data->req_data.p_data = GKI_getbuf(sizeof(tBTA_GATTS_REQ_DATA));
140 if (p_dest_data->req_data.p_data != NULL)
141 {
142 memcpy(p_dest_data->req_data.p_data, p_src_data->req_data.p_data,
143 sizeof(tBTA_GATTS_REQ_DATA));
144 }
145 break;
146
147 default:
148 break;
149 }
150 }
151
btapp_gatts_free_req_data(UINT16 event,tBTA_GATTS * p_data)152 static void btapp_gatts_free_req_data(UINT16 event, tBTA_GATTS *p_data)
153 {
154 switch (event)
155 {
156 case BTA_GATTS_READ_EVT:
157 case BTA_GATTS_WRITE_EVT:
158 case BTA_GATTS_EXEC_WRITE_EVT:
159 case BTA_GATTS_MTU_EVT:
160 if (p_data && p_data->req_data.p_data)
161 GKI_freebuf(p_data->req_data.p_data);
162 break;
163
164 default:
165 break;
166 }
167 }
168
btapp_gatts_handle_cback(uint16_t event,char * p_param)169 static void btapp_gatts_handle_cback(uint16_t event, char* p_param)
170 {
171 ALOGD("%s: Event %d", __FUNCTION__, event);
172
173 tBTA_GATTS *p_data = (tBTA_GATTS*)p_param;
174 switch (event)
175 {
176 case BTA_GATTS_REG_EVT:
177 {
178 bt_uuid_t app_uuid;
179 bta_to_btif_uuid(&app_uuid, &p_data->reg_oper.uuid);
180 HAL_CBACK(bt_gatt_callbacks, server->register_server_cb
181 , p_data->reg_oper.status
182 , p_data->reg_oper.server_if
183 , &app_uuid
184 );
185 break;
186 }
187
188 case BTA_GATTS_DEREG_EVT:
189 break;
190
191 case BTA_GATTS_CONNECT_EVT:
192 {
193 bt_bdaddr_t bda;
194 bdcpy(bda.address, p_data->conn.remote_bda);
195
196 btif_gatt_check_encrypted_link(p_data->conn.remote_bda);
197
198 HAL_CBACK(bt_gatt_callbacks, server->connection_cb,
199 p_data->conn.conn_id, p_data->conn.server_if, TRUE, &bda);
200 break;
201 }
202
203 case BTA_GATTS_DISCONNECT_EVT:
204 {
205 bt_bdaddr_t bda;
206 bdcpy(bda.address, p_data->conn.remote_bda);
207
208 HAL_CBACK(bt_gatt_callbacks, server->connection_cb,
209 p_data->conn.conn_id, p_data->conn.server_if, FALSE, &bda);
210 break;
211 }
212
213 case BTA_GATTS_CREATE_EVT:
214 {
215 btgatt_srvc_id_t srvc_id;
216 srvc_id.is_primary = p_data->create.is_primary;
217 srvc_id.id.inst_id = p_data->create.svc_instance;
218 bta_to_btif_uuid(&srvc_id.id.uuid, &p_data->create.uuid);
219
220 HAL_CBACK(bt_gatt_callbacks, server->service_added_cb,
221 p_data->create.status, p_data->create.server_if, &srvc_id,
222 p_data->create.service_id
223 );
224 }
225 break;
226
227 case BTA_GATTS_ADD_INCL_SRVC_EVT:
228 HAL_CBACK(bt_gatt_callbacks, server->included_service_added_cb,
229 p_data->add_result.status,
230 p_data->add_result.server_if,
231 p_data->add_result.service_id,
232 p_data->add_result.attr_id);
233 break;
234
235 case BTA_GATTS_ADD_CHAR_EVT:
236 {
237 bt_uuid_t uuid;
238 bta_to_btif_uuid(&uuid, &p_data->add_result.char_uuid);
239
240 HAL_CBACK(bt_gatt_callbacks, server->characteristic_added_cb,
241 p_data->add_result.status,
242 p_data->add_result.server_if,
243 &uuid,
244 p_data->add_result.service_id,
245 p_data->add_result.attr_id);
246 break;
247 }
248
249 case BTA_GATTS_ADD_CHAR_DESCR_EVT:
250 {
251 bt_uuid_t uuid;
252 bta_to_btif_uuid(&uuid, &p_data->add_result.char_uuid);
253
254 HAL_CBACK(bt_gatt_callbacks, server->descriptor_added_cb,
255 p_data->add_result.status,
256 p_data->add_result.server_if,
257 &uuid,
258 p_data->add_result.service_id,
259 p_data->add_result.attr_id);
260 break;
261 }
262
263 case BTA_GATTS_START_EVT:
264 HAL_CBACK(bt_gatt_callbacks, server->service_started_cb,
265 p_data->srvc_oper.status,
266 p_data->srvc_oper.server_if,
267 p_data->srvc_oper.service_id);
268 break;
269
270 case BTA_GATTS_STOP_EVT:
271 HAL_CBACK(bt_gatt_callbacks, server->service_stopped_cb,
272 p_data->srvc_oper.status,
273 p_data->srvc_oper.server_if,
274 p_data->srvc_oper.service_id);
275 break;
276
277 case BTA_GATTS_DELELTE_EVT:
278 HAL_CBACK(bt_gatt_callbacks, server->service_deleted_cb,
279 p_data->srvc_oper.status,
280 p_data->srvc_oper.server_if,
281 p_data->srvc_oper.service_id);
282 break;
283
284 case BTA_GATTS_READ_EVT:
285 {
286 bt_bdaddr_t bda;
287 bdcpy(bda.address, p_data->req_data.remote_bda);
288
289 HAL_CBACK(bt_gatt_callbacks, server->request_read_cb,
290 p_data->req_data.conn_id,p_data->req_data.trans_id, &bda,
291 p_data->req_data.p_data->read_req.handle,
292 p_data->req_data.p_data->read_req.offset,
293 p_data->req_data.p_data->read_req.is_long);
294 break;
295 }
296
297 case BTA_GATTS_WRITE_EVT:
298 {
299 bt_bdaddr_t bda;
300 bdcpy(bda.address, p_data->req_data.remote_bda);
301
302 HAL_CBACK(bt_gatt_callbacks, server->request_write_cb,
303 p_data->req_data.conn_id,p_data->req_data.trans_id, &bda,
304 p_data->req_data.p_data->write_req.handle,
305 p_data->req_data.p_data->write_req.offset,
306 p_data->req_data.p_data->write_req.len,
307 p_data->req_data.p_data->write_req.need_rsp,
308 p_data->req_data.p_data->write_req.is_prep,
309 p_data->req_data.p_data->write_req.value);
310 break;
311 }
312
313 case BTA_GATTS_EXEC_WRITE_EVT:
314 {
315 bt_bdaddr_t bda;
316 bdcpy(bda.address, p_data->req_data.remote_bda);
317
318 HAL_CBACK(bt_gatt_callbacks, server->request_exec_write_cb,
319 p_data->req_data.conn_id,p_data->req_data.trans_id, &bda,
320 p_data->req_data.p_data->exec_write);
321 break;
322 }
323
324 case BTA_GATTS_CONF_EVT:
325 HAL_CBACK(bt_gatt_callbacks, server->indication_sent_cb,
326 p_data->req_data.conn_id, p_data->req_data.status);
327 break;
328
329 case BTA_GATTS_CONGEST_EVT:
330 HAL_CBACK(bt_gatt_callbacks, server->congestion_cb
331 , p_data->congest.conn_id
332 , p_data->congest.congested
333 );
334 break;
335
336 case BTA_GATTS_MTU_EVT:
337 case BTA_GATTS_OPEN_EVT:
338 case BTA_GATTS_CANCEL_OPEN_EVT:
339 case BTA_GATTS_CLOSE_EVT:
340 ALOGD("%s: Empty event (%d)!", __FUNCTION__, event);
341 break;
342
343 default:
344 ALOGE("%s: Unhandled event (%d)!", __FUNCTION__, event);
345 break;
346 }
347
348 btapp_gatts_free_req_data(event, p_data);
349 }
350
btapp_gatts_cback(tBTA_GATTS_EVT event,tBTA_GATTS * p_data)351 static void btapp_gatts_cback(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
352 {
353 bt_status_t status;
354 status = btif_transfer_context(btapp_gatts_handle_cback, (uint16_t) event,
355 (void*)p_data, sizeof(tBTA_GATTS), btapp_gatts_copy_req_data);
356 ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
357 }
358
btgatts_handle_event(uint16_t event,char * p_param)359 static void btgatts_handle_event(uint16_t event, char* p_param)
360 {
361 btif_gatts_cb_t* p_cb = (btif_gatts_cb_t*)p_param;
362 if (!p_cb) return;
363
364 ALOGD("%s: Event %d", __FUNCTION__, event);
365
366 switch (event)
367 {
368 case BTIF_GATTS_REGISTER_APP:
369 {
370 tBT_UUID uuid;
371 btif_to_bta_uuid(&uuid, &p_cb->uuid);
372 BTA_GATTS_AppRegister(&uuid, btapp_gatts_cback);
373 break;
374 }
375
376 case BTIF_GATTS_UNREGISTER_APP:
377 BTA_GATTS_AppDeregister(p_cb->server_if);
378 break;
379
380 case BTIF_GATTS_OPEN:
381 {
382 // Ensure device is in inquiry database
383 int addr_type = 0;
384 int device_type = 0;
385 tBTA_GATT_TRANSPORT transport = BTA_GATT_TRANSPORT_LE;
386
387 if (btif_get_device_type(p_cb->bd_addr.address, &addr_type, &device_type) == TRUE
388 && device_type != BT_DEVICE_TYPE_BREDR)
389 BTA_DmAddBleDevice(p_cb->bd_addr.address, addr_type, device_type);
390
391 // Mark background connections
392 if (!p_cb->is_direct)
393 BTA_DmBleSetBgConnType(BTM_BLE_CONN_AUTO, NULL);
394
395 switch(device_type)
396 {
397 case BT_DEVICE_TYPE_BREDR:
398 transport = BTA_GATT_TRANSPORT_BR_EDR;
399 break;
400
401 case BT_DEVICE_TYPE_BLE:
402 transport = BTA_GATT_TRANSPORT_LE;
403 break;
404
405 case BT_DEVICE_TYPE_DUMO:
406 if ((p_cb->transport == GATT_TRANSPORT_LE) &&
407 (btif_storage_is_dmt_supported_device(&(p_cb->bd_addr)) == TRUE))
408 transport = BTA_GATT_TRANSPORT_LE;
409 else
410 transport = BTA_GATT_TRANSPORT_BR_EDR;
411 break;
412
413 default:
414 BTIF_TRACE_ERROR (" GATT Open :Invalid device type %d",device_type);
415 return;
416 }
417
418 // Connect!
419 BTA_GATTS_Open(p_cb->server_if, p_cb->bd_addr.address,
420 p_cb->is_direct, transport);
421 break;
422 }
423
424 case BTIF_GATTS_CLOSE:
425 // Cancel pending foreground/background connections
426 BTA_GATTS_CancelOpen(p_cb->server_if, p_cb->bd_addr.address, TRUE);
427 BTA_GATTS_CancelOpen(p_cb->server_if, p_cb->bd_addr.address, FALSE);
428
429 // Close active connection
430 if (p_cb->conn_id != 0)
431 BTA_GATTS_Close(p_cb->conn_id);
432 break;
433
434 case BTIF_GATTS_CREATE_SERVICE:
435 {
436 tBTA_GATT_SRVC_ID srvc_id;
437 btif_to_bta_srvc_id(&srvc_id, &p_cb->srvc_id);
438 BTA_GATTS_CreateService(p_cb->server_if, &srvc_id.id.uuid,
439 srvc_id.id.inst_id, p_cb->num_handles,
440 srvc_id.is_primary);
441 break;
442 }
443
444 case BTIF_GATTS_ADD_INCLUDED_SERVICE:
445 BTA_GATTS_AddIncludeService(p_cb->srvc_handle, p_cb->incl_handle);
446 break;
447
448 case BTIF_GATTS_ADD_CHARACTERISTIC:
449 {
450 tBT_UUID uuid;
451 btif_to_bta_uuid(&uuid, &p_cb->uuid);
452
453 BTA_GATTS_AddCharacteristic(p_cb->srvc_handle, &uuid,
454 p_cb->permissions, p_cb->properties);
455 break;
456 }
457
458 case BTIF_GATTS_ADD_DESCRIPTOR:
459 {
460 tBT_UUID uuid;
461 btif_to_bta_uuid(&uuid, &p_cb->uuid);
462
463 BTA_GATTS_AddCharDescriptor(p_cb->srvc_handle, p_cb->permissions,
464 &uuid);
465 break;
466 }
467
468 case BTIF_GATTS_START_SERVICE:
469 BTA_GATTS_StartService(p_cb->srvc_handle, p_cb->transport);
470 break;
471
472 case BTIF_GATTS_STOP_SERVICE:
473 BTA_GATTS_StopService(p_cb->srvc_handle);
474 break;
475
476 case BTIF_GATTS_DELETE_SERVICE:
477 BTA_GATTS_DeleteService(p_cb->srvc_handle);
478 break;
479
480 case BTIF_GATTS_SEND_INDICATION:
481 BTA_GATTS_HandleValueIndication(p_cb->conn_id, p_cb->attr_handle,
482 p_cb->len, p_cb->value, p_cb->confirm);
483 // TODO: Might need to send an ACK if handle value indication is
484 // invoked without need for confirmation.
485 break;
486
487 case BTIF_GATTS_SEND_RESPONSE:
488 {
489 tBTA_GATTS_RSP rsp_struct;
490 btgatt_response_t *p_rsp = &p_cb->response;
491 btif_to_bta_response(&rsp_struct, p_rsp);
492
493 BTA_GATTS_SendRsp(p_cb->conn_id, p_cb->trans_id,
494 p_cb->status, &rsp_struct);
495
496 HAL_CBACK(bt_gatt_callbacks, server->response_confirmation_cb,
497 0, rsp_struct.attr_value.handle);
498 break;
499 }
500
501 default:
502 ALOGE("%s: Unknown event (%d)!", __FUNCTION__, event);
503 break;
504 }
505 }
506
507 /************************************************************************************
508 ** Server API Functions
509 ************************************************************************************/
510
btif_gatts_register_app(bt_uuid_t * uuid)511 static bt_status_t btif_gatts_register_app(bt_uuid_t *uuid)
512 {
513 CHECK_BTGATT_INIT();
514 btif_gatts_cb_t btif_cb;
515 memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
516 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_REGISTER_APP,
517 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
518 }
519
btif_gatts_unregister_app(int server_if)520 static bt_status_t btif_gatts_unregister_app( int server_if )
521 {
522 CHECK_BTGATT_INIT();
523 btif_gatts_cb_t btif_cb;
524 btif_cb.server_if = (uint8_t) server_if;
525 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_UNREGISTER_APP,
526 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
527 }
528
btif_gatts_open(int server_if,const bt_bdaddr_t * bd_addr,bool is_direct,int transport)529 static bt_status_t btif_gatts_open( int server_if, const bt_bdaddr_t *bd_addr,
530 bool is_direct, int transport )
531 {
532 CHECK_BTGATT_INIT();
533 btif_gatts_cb_t btif_cb;
534 btif_cb.server_if = (uint8_t) server_if;
535 btif_cb.is_direct = is_direct ? 1 : 0;
536 btif_cb.transport = (btgatt_transport_t)transport;
537 bdcpy(btif_cb.bd_addr.address, bd_addr->address);
538 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_OPEN,
539 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
540 }
541
btif_gatts_close(int server_if,const bt_bdaddr_t * bd_addr,int conn_id)542 static bt_status_t btif_gatts_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
543 {
544 CHECK_BTGATT_INIT();
545 btif_gatts_cb_t btif_cb;
546 btif_cb.server_if = (uint8_t) server_if;
547 btif_cb.conn_id = (uint16_t) conn_id;
548 bdcpy(btif_cb.bd_addr.address, bd_addr->address);
549 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_CLOSE,
550 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
551 }
552
btif_gatts_add_service(int server_if,btgatt_srvc_id_t * srvc_id,int num_handles)553 static bt_status_t btif_gatts_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
554 int num_handles)
555 {
556 CHECK_BTGATT_INIT();
557 btif_gatts_cb_t btif_cb;
558 btif_cb.server_if = (uint8_t) server_if;
559 btif_cb.num_handles = (uint8_t) num_handles;
560 memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
561 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_CREATE_SERVICE,
562 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
563 }
564
btif_gatts_add_included_service(int server_if,int service_handle,int included_handle)565 static bt_status_t btif_gatts_add_included_service(int server_if, int service_handle,
566 int included_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 btif_cb.incl_handle = (uint16_t) included_handle;
573 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_ADD_INCLUDED_SERVICE,
574 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
575 }
576
btif_gatts_add_characteristic(int server_if,int service_handle,bt_uuid_t * uuid,int properties,int permissions)577 static bt_status_t btif_gatts_add_characteristic(int server_if, int service_handle,
578 bt_uuid_t *uuid, int properties,
579 int permissions)
580 {
581 CHECK_BTGATT_INIT();
582 btif_gatts_cb_t btif_cb;
583 btif_cb.server_if = (uint8_t) server_if;
584 btif_cb.srvc_handle = (uint16_t) service_handle;
585 btif_cb.properties = (uint8_t) properties;
586 btif_cb.permissions = (uint16_t) permissions;
587 memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
588 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_ADD_CHARACTERISTIC,
589 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
590 }
591
btif_gatts_add_descriptor(int server_if,int service_handle,bt_uuid_t * uuid,int permissions)592 static bt_status_t btif_gatts_add_descriptor(int server_if, int service_handle, bt_uuid_t *uuid,
593 int permissions)
594 {
595 CHECK_BTGATT_INIT();
596 btif_gatts_cb_t btif_cb;
597 btif_cb.server_if = (uint8_t) server_if;
598 btif_cb.srvc_handle = (uint16_t) service_handle;
599 btif_cb.permissions = (uint16_t) permissions;
600 memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
601 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_ADD_DESCRIPTOR,
602 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
603 }
604
btif_gatts_start_service(int server_if,int service_handle,int transport)605 static bt_status_t btif_gatts_start_service(int server_if, int service_handle, int transport)
606 {
607 CHECK_BTGATT_INIT();
608 btif_gatts_cb_t btif_cb;
609 btif_cb.server_if = (uint8_t) server_if;
610 btif_cb.srvc_handle = (uint16_t) service_handle;
611 btif_cb.transport = (uint8_t) transport;
612 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_START_SERVICE,
613 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
614 }
615
btif_gatts_stop_service(int server_if,int service_handle)616 static bt_status_t btif_gatts_stop_service(int server_if, int service_handle)
617 {
618 CHECK_BTGATT_INIT();
619 btif_gatts_cb_t btif_cb;
620 btif_cb.server_if = (uint8_t) server_if;
621 btif_cb.srvc_handle = (uint16_t) service_handle;
622 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_STOP_SERVICE,
623 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
624 }
625
btif_gatts_delete_service(int server_if,int service_handle)626 static bt_status_t btif_gatts_delete_service(int server_if, int service_handle)
627 {
628 CHECK_BTGATT_INIT();
629 btif_gatts_cb_t btif_cb;
630 btif_cb.server_if = (uint8_t) server_if;
631 btif_cb.srvc_handle = (uint16_t) service_handle;
632 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_DELETE_SERVICE,
633 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
634 }
635
btif_gatts_send_indication(int server_if,int attribute_handle,int conn_id,int len,int confirm,char * p_value)636 static bt_status_t btif_gatts_send_indication(int server_if, int attribute_handle, int conn_id,
637 int len, int confirm, char* p_value)
638 {
639 CHECK_BTGATT_INIT();
640 btif_gatts_cb_t btif_cb;
641 btif_cb.server_if = (uint8_t) server_if;
642 btif_cb.conn_id = (uint16_t) conn_id;
643 btif_cb.attr_handle = attribute_handle;
644 btif_cb.confirm = confirm;
645 btif_cb.len = len;
646 memcpy(btif_cb.value, p_value, len > BTGATT_MAX_ATTR_LEN ? BTGATT_MAX_ATTR_LEN : len);
647 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_SEND_INDICATION,
648 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
649 }
650
btif_gatts_send_response(int conn_id,int trans_id,int status,btgatt_response_t * response)651 static bt_status_t btif_gatts_send_response(int conn_id, int trans_id,
652 int status, btgatt_response_t *response)
653 {
654 CHECK_BTGATT_INIT();
655 btif_gatts_cb_t btif_cb;
656 btif_cb.conn_id = (uint16_t) conn_id;
657 btif_cb.trans_id = (uint32_t) trans_id;
658 btif_cb.status = (uint8_t) status;
659 memcpy(&btif_cb.response, response, sizeof(btgatt_response_t));
660 return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_SEND_RESPONSE,
661 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
662 }
663
664 const btgatt_server_interface_t btgattServerInterface = {
665 btif_gatts_register_app,
666 btif_gatts_unregister_app,
667 btif_gatts_open,
668 btif_gatts_close,
669 btif_gatts_add_service,
670 btif_gatts_add_included_service,
671 btif_gatts_add_characteristic,
672 btif_gatts_add_descriptor,
673 btif_gatts_start_service,
674 btif_gatts_stop_service,
675 btif_gatts_delete_service,
676 btif_gatts_send_indication,
677 btif_gatts_send_response
678 };
679
680 #endif
681