• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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