• 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  *  Filename:      btif_gatt_server.c
22  *
23  *  Description:   GATT server implementation
24  *
25  ***********************************************************************************/
26 
27 #define LOG_TAG "bt_btif_gatt"
28 
29 #include <errno.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 
34 #include <hardware/bluetooth.h>
35 #include <hardware/bt_gatt.h>
36 
37 #include "btif_common.h"
38 #include "btif_util.h"
39 
40 #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
41 
42 #include "bta_api.h"
43 #include "bta_gatt_api.h"
44 #include "btif_config.h"
45 #include "btif_dm.h"
46 #include "btif_gatt.h"
47 #include "btif_gatt_util.h"
48 #include "btif_storage.h"
49 #include "bt_common.h"
50 #include "osi/include/log.h"
51 
52 /************************************************************************************
53 **  Constants & Macros
54 ************************************************************************************/
55 
56 #define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
57     {\
58         LOG_WARN(LOG_TAG, "%s: BTGATT not initialized", __FUNCTION__);\
59         return BT_STATUS_NOT_READY;\
60     } else {\
61         LOG_VERBOSE(LOG_TAG, "%s", __FUNCTION__);\
62     }
63 
64 typedef enum {
65     BTIF_GATTS_REGISTER_APP = 2000,
66     BTIF_GATTS_UNREGISTER_APP,
67     BTIF_GATTS_OPEN,
68     BTIF_GATTS_CLOSE,
69     BTIF_GATTS_CREATE_SERVICE,
70     BTIF_GATTS_ADD_INCLUDED_SERVICE,
71     BTIF_GATTS_ADD_CHARACTERISTIC,
72     BTIF_GATTS_ADD_DESCRIPTOR,
73     BTIF_GATTS_START_SERVICE,
74     BTIF_GATTS_STOP_SERVICE,
75     BTIF_GATTS_DELETE_SERVICE,
76     BTIF_GATTS_SEND_INDICATION,
77     BTIF_GATTS_SEND_RESPONSE
78 } btif_gatts_event_t;
79 
80 /************************************************************************************
81 **  Local type definitions
82 ************************************************************************************/
83 
84 typedef struct
85 {
86     uint8_t             value[BTGATT_MAX_ATTR_LEN];
87     btgatt_response_t   response;
88     btgatt_srvc_id_t    srvc_id;
89     bt_bdaddr_t         bd_addr;
90     bt_uuid_t           uuid;
91     uint32_t            trans_id;
92     uint16_t            conn_id;
93     uint16_t            srvc_handle;
94     uint16_t            incl_handle;
95     uint16_t            attr_handle;
96     uint16_t            permissions;
97     uint16_t            len;
98     uint8_t             server_if;
99     uint8_t             is_direct;
100     uint8_t             num_handles;
101     uint8_t             properties;
102     uint8_t             confirm;
103     uint8_t             status;
104     btgatt_transport_t  transport;
105 
106 } __attribute__((packed)) btif_gatts_cb_t;
107 
108 /************************************************************************************
109 **  Static variables
110 ************************************************************************************/
111 
112 extern const btgatt_callbacks_t *bt_gatt_callbacks;
113 
114 /************************************************************************************
115 **  Static functions
116 ************************************************************************************/
117 
btapp_gatts_copy_req_data(UINT16 event,char * p_dest,char * p_src)118 static void btapp_gatts_copy_req_data(UINT16 event, char *p_dest, char *p_src)
119 {
120     tBTA_GATTS *p_dest_data = (tBTA_GATTS*) p_dest;
121     tBTA_GATTS *p_src_data = (tBTA_GATTS*) p_src;
122 
123     if (!p_src_data || !p_dest_data)
124         return;
125 
126     // Copy basic structure first
127     maybe_non_aligned_memcpy(p_dest_data, p_src_data, sizeof(*p_src_data));
128 
129     // Allocate buffer for request data if necessary
130     switch (event)
131     {
132         case BTA_GATTS_READ_EVT:
133         case BTA_GATTS_WRITE_EVT:
134         case BTA_GATTS_EXEC_WRITE_EVT:
135         case BTA_GATTS_MTU_EVT:
136             p_dest_data->req_data.p_data = osi_malloc(sizeof(tBTA_GATTS_REQ_DATA));
137             memcpy(p_dest_data->req_data.p_data, p_src_data->req_data.p_data,
138                    sizeof(tBTA_GATTS_REQ_DATA));
139             break;
140 
141         default:
142             break;
143     }
144 }
145 
btapp_gatts_free_req_data(UINT16 event,tBTA_GATTS * p_data)146 static void btapp_gatts_free_req_data(UINT16 event, tBTA_GATTS *p_data)
147 {
148     switch (event)
149     {
150         case BTA_GATTS_READ_EVT:
151         case BTA_GATTS_WRITE_EVT:
152         case BTA_GATTS_EXEC_WRITE_EVT:
153         case BTA_GATTS_MTU_EVT:
154             if (p_data != NULL)
155                 osi_free_and_reset((void **)&p_data->req_data.p_data);
156             break;
157 
158         default:
159             break;
160     }
161 }
162 
btapp_gatts_handle_cback(uint16_t event,char * p_param)163 static void btapp_gatts_handle_cback(uint16_t event, char* p_param)
164 {
165     LOG_VERBOSE(LOG_TAG, "%s: Event %d", __FUNCTION__, event);
166 
167     tBTA_GATTS *p_data = (tBTA_GATTS*)p_param;
168     switch (event)
169     {
170         case BTA_GATTS_REG_EVT:
171         {
172             bt_uuid_t app_uuid;
173             bta_to_btif_uuid(&app_uuid, &p_data->reg_oper.uuid);
174             HAL_CBACK(bt_gatt_callbacks, server->register_server_cb
175                 , p_data->reg_oper.status
176                 , p_data->reg_oper.server_if
177                 , &app_uuid
178             );
179             break;
180         }
181 
182         case BTA_GATTS_DEREG_EVT:
183             break;
184 
185         case BTA_GATTS_CONNECT_EVT:
186         {
187             bt_bdaddr_t bda;
188             bdcpy(bda.address, p_data->conn.remote_bda);
189 
190             btif_gatt_check_encrypted_link(p_data->conn.remote_bda, p_data->conn.transport);
191 
192             HAL_CBACK(bt_gatt_callbacks, server->connection_cb,
193                       p_data->conn.conn_id, p_data->conn.server_if, TRUE, &bda);
194             break;
195         }
196 
197         case BTA_GATTS_DISCONNECT_EVT:
198         {
199             bt_bdaddr_t bda;
200             bdcpy(bda.address, p_data->conn.remote_bda);
201 
202             HAL_CBACK(bt_gatt_callbacks, server->connection_cb,
203                       p_data->conn.conn_id, p_data->conn.server_if, FALSE, &bda);
204             break;
205         }
206 
207         case BTA_GATTS_CREATE_EVT:
208         {
209             btgatt_srvc_id_t srvc_id;
210             srvc_id.is_primary = p_data->create.is_primary;
211             srvc_id.id.inst_id = p_data->create.svc_instance;
212             bta_to_btif_uuid(&srvc_id.id.uuid, &p_data->create.uuid);
213 
214             HAL_CBACK(bt_gatt_callbacks, server->service_added_cb,
215                       p_data->create.status, p_data->create.server_if, &srvc_id,
216                       p_data->create.service_id
217             );
218         }
219         break;
220 
221         case BTA_GATTS_ADD_INCL_SRVC_EVT:
222             HAL_CBACK(bt_gatt_callbacks, server->included_service_added_cb,
223                       p_data->add_result.status,
224                       p_data->add_result.server_if,
225                       p_data->add_result.service_id,
226                       p_data->add_result.attr_id);
227             break;
228 
229         case BTA_GATTS_ADD_CHAR_EVT:
230         {
231             bt_uuid_t uuid;
232             bta_to_btif_uuid(&uuid, &p_data->add_result.char_uuid);
233 
234             HAL_CBACK(bt_gatt_callbacks, server->characteristic_added_cb,
235                       p_data->add_result.status,
236                       p_data->add_result.server_if,
237                       &uuid,
238                       p_data->add_result.service_id,
239                       p_data->add_result.attr_id);
240             break;
241         }
242 
243         case BTA_GATTS_ADD_CHAR_DESCR_EVT:
244         {
245             bt_uuid_t uuid;
246             bta_to_btif_uuid(&uuid, &p_data->add_result.char_uuid);
247 
248             HAL_CBACK(bt_gatt_callbacks, server->descriptor_added_cb,
249                       p_data->add_result.status,
250                       p_data->add_result.server_if,
251                       &uuid,
252                       p_data->add_result.service_id,
253                       p_data->add_result.attr_id);
254             break;
255         }
256 
257         case BTA_GATTS_START_EVT:
258             HAL_CBACK(bt_gatt_callbacks, server->service_started_cb,
259                       p_data->srvc_oper.status,
260                       p_data->srvc_oper.server_if,
261                       p_data->srvc_oper.service_id);
262             break;
263 
264         case BTA_GATTS_STOP_EVT:
265             HAL_CBACK(bt_gatt_callbacks, server->service_stopped_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_DELELTE_EVT:
272             HAL_CBACK(bt_gatt_callbacks, server->service_deleted_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_READ_EVT:
279         {
280             bt_bdaddr_t bda;
281             bdcpy(bda.address, p_data->req_data.remote_bda);
282 
283             HAL_CBACK(bt_gatt_callbacks, server->request_read_cb,
284                       p_data->req_data.conn_id,p_data->req_data.trans_id, &bda,
285                       p_data->req_data.p_data->read_req.handle,
286                       p_data->req_data.p_data->read_req.offset,
287                       p_data->req_data.p_data->read_req.is_long);
288             break;
289         }
290 
291         case BTA_GATTS_WRITE_EVT:
292         {
293             bt_bdaddr_t bda;
294             bdcpy(bda.address, p_data->req_data.remote_bda);
295 
296             HAL_CBACK(bt_gatt_callbacks, server->request_write_cb,
297                       p_data->req_data.conn_id,p_data->req_data.trans_id, &bda,
298                       p_data->req_data.p_data->write_req.handle,
299                       p_data->req_data.p_data->write_req.offset,
300                       p_data->req_data.p_data->write_req.len,
301                       p_data->req_data.p_data->write_req.need_rsp,
302                       p_data->req_data.p_data->write_req.is_prep,
303                       p_data->req_data.p_data->write_req.value);
304             break;
305         }
306 
307         case BTA_GATTS_EXEC_WRITE_EVT:
308         {
309             bt_bdaddr_t bda;
310             bdcpy(bda.address, p_data->req_data.remote_bda);
311 
312             HAL_CBACK(bt_gatt_callbacks, server->request_exec_write_cb,
313                       p_data->req_data.conn_id,p_data->req_data.trans_id, &bda,
314                       p_data->req_data.p_data->exec_write);
315             break;
316         }
317 
318         case BTA_GATTS_CONF_EVT:
319             HAL_CBACK(bt_gatt_callbacks, server->indication_sent_cb,
320                       p_data->req_data.conn_id, p_data->req_data.status);
321             break;
322 
323         case BTA_GATTS_CONGEST_EVT:
324             HAL_CBACK(bt_gatt_callbacks, server->congestion_cb
325                 , p_data->congest.conn_id
326                 , p_data->congest.congested
327             );
328             break;
329 
330         case BTA_GATTS_MTU_EVT:
331             HAL_CBACK(bt_gatt_callbacks, server->mtu_changed_cb
332                 , p_data->req_data.conn_id
333                 , p_data->req_data.p_data->mtu
334             );
335             break;
336 
337         case BTA_GATTS_OPEN_EVT:
338         case BTA_GATTS_CANCEL_OPEN_EVT:
339         case BTA_GATTS_CLOSE_EVT:
340             LOG_DEBUG(LOG_TAG, "%s: Empty event (%d)!", __FUNCTION__, event);
341             break;
342 
343         default:
344             LOG_ERROR(LOG_TAG, "%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     LOG_VERBOSE(LOG_TAG, "%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_address_type(p_cb->bd_addr.address, &addr_type) &&
388                 btif_get_device_type(p_cb->bd_addr.address, &device_type) &&
389                 device_type != BT_DEVICE_TYPE_BREDR)
390             {
391                 BTA_DmAddBleDevice(p_cb->bd_addr.address, addr_type, device_type);
392             }
393 
394             // Mark background connections
395             if (!p_cb->is_direct)
396                 BTA_DmBleSetBgConnType(BTM_BLE_CONN_AUTO, NULL);
397 
398             // Determine transport
399             if (p_cb->transport != GATT_TRANSPORT_AUTO)
400             {
401                 transport = p_cb->transport;
402             } else {
403                 switch(device_type)
404                 {
405                     case BT_DEVICE_TYPE_BREDR:
406                         transport = BTA_GATT_TRANSPORT_BR_EDR;
407                         break;
408 
409                     case BT_DEVICE_TYPE_BLE:
410                         transport = BTA_GATT_TRANSPORT_LE;
411                         break;
412 
413                     case BT_DEVICE_TYPE_DUMO:
414                         if (p_cb->transport == GATT_TRANSPORT_LE)
415                             transport = BTA_GATT_TRANSPORT_LE;
416                         else
417                             transport = BTA_GATT_TRANSPORT_BR_EDR;
418                         break;
419 
420                     default:
421                         BTIF_TRACE_ERROR ("%s: Invalid device type %d", __func__, device_type);
422                         return;
423                 }
424             }
425 
426             // Connect!
427             BTA_GATTS_Open(p_cb->server_if, p_cb->bd_addr.address,
428                            p_cb->is_direct, transport);
429             break;
430         }
431 
432         case BTIF_GATTS_CLOSE:
433             // Cancel pending foreground/background connections
434             BTA_GATTS_CancelOpen(p_cb->server_if, p_cb->bd_addr.address, TRUE);
435             BTA_GATTS_CancelOpen(p_cb->server_if, p_cb->bd_addr.address, FALSE);
436 
437             // Close active connection
438             if (p_cb->conn_id != 0)
439                 BTA_GATTS_Close(p_cb->conn_id);
440             break;
441 
442         case BTIF_GATTS_CREATE_SERVICE:
443         {
444             tBT_UUID uuid;
445             btif_to_bta_uuid(&uuid, &p_cb->srvc_id.id.uuid);
446 
447             BTA_GATTS_CreateService(p_cb->server_if, &uuid,
448                                     p_cb->srvc_id.id.inst_id, p_cb->num_handles,
449                                     p_cb->srvc_id.is_primary);
450 
451             break;
452         }
453 
454         case BTIF_GATTS_ADD_INCLUDED_SERVICE:
455             BTA_GATTS_AddIncludeService(p_cb->srvc_handle, p_cb->incl_handle);
456             break;
457 
458         case BTIF_GATTS_ADD_CHARACTERISTIC:
459         {
460             tBT_UUID uuid;
461             btif_to_bta_uuid(&uuid, &p_cb->uuid);
462 
463             BTA_GATTS_AddCharacteristic(p_cb->srvc_handle, &uuid,
464                                         p_cb->permissions, p_cb->properties);
465             break;
466         }
467 
468         case BTIF_GATTS_ADD_DESCRIPTOR:
469         {
470             tBT_UUID uuid;
471             btif_to_bta_uuid(&uuid, &p_cb->uuid);
472 
473             BTA_GATTS_AddCharDescriptor(p_cb->srvc_handle, p_cb->permissions,
474                                          &uuid);
475             break;
476         }
477 
478         case BTIF_GATTS_START_SERVICE:
479             BTA_GATTS_StartService(p_cb->srvc_handle, p_cb->transport);
480             break;
481 
482         case BTIF_GATTS_STOP_SERVICE:
483             BTA_GATTS_StopService(p_cb->srvc_handle);
484             break;
485 
486         case BTIF_GATTS_DELETE_SERVICE:
487             BTA_GATTS_DeleteService(p_cb->srvc_handle);
488             break;
489 
490         case BTIF_GATTS_SEND_INDICATION:
491             BTA_GATTS_HandleValueIndication(p_cb->conn_id, p_cb->attr_handle,
492                                         p_cb->len, p_cb->value, p_cb->confirm);
493             // TODO: Might need to send an ACK if handle value indication is
494             //       invoked without need for confirmation.
495             break;
496 
497         case BTIF_GATTS_SEND_RESPONSE:
498         {
499             tBTA_GATTS_RSP rsp_struct;
500             btgatt_response_t *p_rsp = &p_cb->response;
501             btif_to_bta_response(&rsp_struct, p_rsp);
502 
503             BTA_GATTS_SendRsp(p_cb->conn_id, p_cb->trans_id,
504                               p_cb->status, &rsp_struct);
505 
506             HAL_CBACK(bt_gatt_callbacks, server->response_confirmation_cb,
507                       0, rsp_struct.attr_value.handle);
508             break;
509         }
510 
511         default:
512             LOG_ERROR(LOG_TAG, "%s: Unknown event (%d)!", __FUNCTION__, event);
513             break;
514     }
515 }
516 
517 /************************************************************************************
518 **  Server API Functions
519 ************************************************************************************/
520 
btif_gatts_register_app(bt_uuid_t * uuid)521 static bt_status_t btif_gatts_register_app(bt_uuid_t *uuid)
522 {
523     CHECK_BTGATT_INIT();
524     btif_gatts_cb_t btif_cb;
525     memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
526     return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_REGISTER_APP,
527                                  (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
528 }
529 
btif_gatts_unregister_app(int server_if)530 static bt_status_t btif_gatts_unregister_app( int server_if )
531 {
532     CHECK_BTGATT_INIT();
533     btif_gatts_cb_t btif_cb;
534     btif_cb.server_if = (uint8_t) server_if;
535     return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_UNREGISTER_APP,
536                                  (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
537 }
538 
btif_gatts_open(int server_if,const bt_bdaddr_t * bd_addr,bool is_direct,int transport)539 static bt_status_t btif_gatts_open( int server_if, const bt_bdaddr_t *bd_addr,
540                                       bool is_direct, int transport )
541 {
542     CHECK_BTGATT_INIT();
543     btif_gatts_cb_t btif_cb;
544     btif_cb.server_if = (uint8_t) server_if;
545     btif_cb.is_direct = is_direct ? 1 : 0;
546     btif_cb.transport = (btgatt_transport_t)transport;
547     bdcpy(btif_cb.bd_addr.address, bd_addr->address);
548     return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_OPEN,
549                                  (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
550 }
551 
btif_gatts_close(int server_if,const bt_bdaddr_t * bd_addr,int conn_id)552 static bt_status_t btif_gatts_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
553 {
554     CHECK_BTGATT_INIT();
555     btif_gatts_cb_t btif_cb;
556     btif_cb.server_if = (uint8_t) server_if;
557     btif_cb.conn_id = (uint16_t) conn_id;
558     bdcpy(btif_cb.bd_addr.address, bd_addr->address);
559     return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_CLOSE,
560                                  (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
561 }
562 
btif_gatts_add_service(int server_if,btgatt_srvc_id_t * srvc_id,int num_handles)563 static bt_status_t btif_gatts_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
564                                           int num_handles)
565 {
566     CHECK_BTGATT_INIT();
567     btif_gatts_cb_t btif_cb;
568     btif_cb.server_if = (uint8_t) server_if;
569     btif_cb.num_handles = (uint8_t) num_handles;
570     memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
571     return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_CREATE_SERVICE,
572                                  (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
573 }
574 
btif_gatts_add_included_service(int server_if,int service_handle,int included_handle)575 static bt_status_t btif_gatts_add_included_service(int server_if, int service_handle,
576                                                    int included_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     btif_cb.incl_handle = (uint16_t) included_handle;
583     return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_ADD_INCLUDED_SERVICE,
584                                  (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
585 }
586 
btif_gatts_add_characteristic(int server_if,int service_handle,bt_uuid_t * uuid,int properties,int permissions)587 static bt_status_t btif_gatts_add_characteristic(int server_if, int service_handle,
588                                                  bt_uuid_t *uuid, int properties,
589                                                  int permissions)
590 {
591     CHECK_BTGATT_INIT();
592     btif_gatts_cb_t btif_cb;
593     btif_cb.server_if = (uint8_t) server_if;
594     btif_cb.srvc_handle = (uint16_t) service_handle;
595     btif_cb.properties = (uint8_t) properties;
596     btif_cb.permissions = (uint16_t) permissions;
597     memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
598     return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_ADD_CHARACTERISTIC,
599                                  (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
600 }
601 
btif_gatts_add_descriptor(int server_if,int service_handle,bt_uuid_t * uuid,int permissions)602 static bt_status_t btif_gatts_add_descriptor(int server_if, int service_handle, bt_uuid_t *uuid,
603                                              int permissions)
604 {
605     CHECK_BTGATT_INIT();
606     btif_gatts_cb_t btif_cb;
607     btif_cb.server_if = (uint8_t) server_if;
608     btif_cb.srvc_handle = (uint16_t) service_handle;
609     btif_cb.permissions = (uint16_t) permissions;
610     memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
611     return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_ADD_DESCRIPTOR,
612                                  (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
613 }
614 
btif_gatts_start_service(int server_if,int service_handle,int transport)615 static bt_status_t btif_gatts_start_service(int server_if, int service_handle, int transport)
616 {
617     CHECK_BTGATT_INIT();
618     btif_gatts_cb_t btif_cb;
619     btif_cb.server_if = (uint8_t) server_if;
620     btif_cb.srvc_handle = (uint16_t) service_handle;
621     btif_cb.transport = (uint8_t) transport;
622     return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_START_SERVICE,
623                                  (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
624 }
625 
btif_gatts_stop_service(int server_if,int service_handle)626 static bt_status_t btif_gatts_stop_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_STOP_SERVICE,
633                                  (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
634 }
635 
btif_gatts_delete_service(int server_if,int service_handle)636 static bt_status_t btif_gatts_delete_service(int server_if, int service_handle)
637 {
638     CHECK_BTGATT_INIT();
639     btif_gatts_cb_t btif_cb;
640     btif_cb.server_if = (uint8_t) server_if;
641     btif_cb.srvc_handle = (uint16_t) service_handle;
642     return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_DELETE_SERVICE,
643                                  (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
644 }
645 
btif_gatts_send_indication(int server_if,int attribute_handle,int conn_id,int len,int confirm,char * p_value)646 static bt_status_t btif_gatts_send_indication(int server_if, int attribute_handle, int conn_id,
647                                               int len, int confirm, char* p_value)
648 {
649     CHECK_BTGATT_INIT();
650     btif_gatts_cb_t btif_cb;
651     btif_cb.server_if = (uint8_t) server_if;
652     btif_cb.conn_id = (uint16_t) conn_id;
653     btif_cb.attr_handle = attribute_handle;
654     btif_cb.confirm = confirm;
655     btif_cb.len = len;
656     memcpy(btif_cb.value, p_value, len > BTGATT_MAX_ATTR_LEN ? BTGATT_MAX_ATTR_LEN : len);
657     return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_SEND_INDICATION,
658                                  (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
659 }
660 
btif_gatts_send_response(int conn_id,int trans_id,int status,btgatt_response_t * response)661 static bt_status_t btif_gatts_send_response(int conn_id, int trans_id,
662                                             int status, btgatt_response_t *response)
663 {
664     CHECK_BTGATT_INIT();
665     btif_gatts_cb_t btif_cb;
666     btif_cb.conn_id = (uint16_t) conn_id;
667     btif_cb.trans_id = (uint32_t) trans_id;
668     btif_cb.status = (uint8_t) status;
669     memcpy(&btif_cb.response, response, sizeof(btgatt_response_t));
670     return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_SEND_RESPONSE,
671                                  (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
672 }
673 
674 const btgatt_server_interface_t btgattServerInterface = {
675     btif_gatts_register_app,
676     btif_gatts_unregister_app,
677     btif_gatts_open,
678     btif_gatts_close,
679     btif_gatts_add_service,
680     btif_gatts_add_included_service,
681     btif_gatts_add_characteristic,
682     btif_gatts_add_descriptor,
683     btif_gatts_start_service,
684     btif_gatts_stop_service,
685     btif_gatts_delete_service,
686     btif_gatts_send_indication,
687     btif_gatts_send_response
688 };
689 
690 #endif
691