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
65typedef 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
85typedef 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
114extern const btgatt_callbacks_t *bt_gatt_callbacks;
115
116
117/************************************************************************************
118**  Static functions
119************************************************************************************/
120
121static 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
152static 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
169static 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
351static 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
359static 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
511static 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
520static 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
529static 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
542static 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
553static 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
565static 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
577static 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
592static 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
605static 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
616static 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
626static 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
636static 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
651static 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
664const 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