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#include "btif_config.h"
49
50#include "btif_gatt.h"
51#include "btif_gatt_util.h"
52
53/************************************************************************************
54**  Constants & Macros
55************************************************************************************/
56
57#define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
58    {\
59        ALOGW("%s: BTGATT not initialized", __FUNCTION__);\
60        return BT_STATUS_NOT_READY;\
61    } else {\
62        ALOGD("%s", __FUNCTION__);\
63    }
64
65
66typedef enum {
67    BTIF_GATTS_REGISTER_APP = 2000,
68    BTIF_GATTS_UNREGISTER_APP,
69    BTIF_GATTS_OPEN,
70    BTIF_GATTS_CLOSE,
71    BTIF_GATTS_CREATE_SERVICE,
72    BTIF_GATTS_ADD_INCLUDED_SERVICE,
73    BTIF_GATTS_ADD_CHARACTERISTIC,
74    BTIF_GATTS_ADD_DESCRIPTOR,
75    BTIF_GATTS_START_SERVICE,
76    BTIF_GATTS_STOP_SERVICE,
77    BTIF_GATTS_DELETE_SERVICE,
78    BTIF_GATTS_SEND_INDICATION,
79    BTIF_GATTS_SEND_RESPONSE
80} btif_gatts_event_t;
81
82/************************************************************************************
83**  Local type definitions
84************************************************************************************/
85
86typedef struct
87{
88    uint8_t             value[BTGATT_MAX_ATTR_LEN];
89    btgatt_response_t   response;
90    btgatt_srvc_id_t    srvc_id;
91    bt_bdaddr_t         bd_addr;
92    bt_uuid_t           uuid;
93    uint32_t            trans_id;
94    uint16_t            conn_id;
95    uint16_t            srvc_handle;
96    uint16_t            incl_handle;
97    uint16_t            attr_handle;
98    uint16_t            permissions;
99    uint16_t            len;
100    uint8_t             server_if;
101    uint8_t             is_direct;
102    uint8_t             num_handles;
103    uint8_t             properties;
104    uint8_t             confirm;
105    uint8_t             status;
106    btgatt_transport_t  transport;
107
108} __attribute__((packed)) btif_gatts_cb_t;
109
110
111/************************************************************************************
112**  Static variables
113************************************************************************************/
114
115extern const btgatt_callbacks_t *bt_gatt_callbacks;
116
117
118/************************************************************************************
119**  Static functions
120************************************************************************************/
121
122static void btapp_gatts_copy_req_data(UINT16 event, char *p_dest, char *p_src)
123{
124    tBTA_GATTS *p_dest_data = (tBTA_GATTS*) p_dest;
125    tBTA_GATTS *p_src_data = (tBTA_GATTS*) p_src;
126
127    if (!p_src_data || !p_dest_data)
128        return;
129
130    // Copy basic structure first
131    memcpy(p_dest_data, p_src_data, sizeof(tBTA_GATTS));
132
133    // Allocate buffer for request data if necessary
134    switch (event)
135    {
136        case BTA_GATTS_READ_EVT:
137        case BTA_GATTS_WRITE_EVT:
138        case BTA_GATTS_EXEC_WRITE_EVT:
139        case BTA_GATTS_MTU_EVT:
140            p_dest_data->req_data.p_data = GKI_getbuf(sizeof(tBTA_GATTS_REQ_DATA));
141            if (p_dest_data->req_data.p_data != NULL)
142            {
143                memcpy(p_dest_data->req_data.p_data, p_src_data->req_data.p_data,
144                    sizeof(tBTA_GATTS_REQ_DATA));
145            }
146            break;
147
148        default:
149            break;
150    }
151}
152
153static void btapp_gatts_free_req_data(UINT16 event, tBTA_GATTS *p_data)
154{
155    switch (event)
156    {
157        case BTA_GATTS_READ_EVT:
158        case BTA_GATTS_WRITE_EVT:
159        case BTA_GATTS_EXEC_WRITE_EVT:
160        case BTA_GATTS_MTU_EVT:
161            if (p_data && p_data->req_data.p_data)
162                GKI_freebuf(p_data->req_data.p_data);
163            break;
164
165        default:
166            break;
167    }
168}
169
170static void btapp_gatts_handle_cback(uint16_t event, char* p_param)
171{
172    ALOGD("%s: Event %d", __FUNCTION__, event);
173
174    tBTA_GATTS *p_data = (tBTA_GATTS*)p_param;
175    switch (event)
176    {
177        case BTA_GATTS_REG_EVT:
178        {
179            bt_uuid_t app_uuid;
180            bta_to_btif_uuid(&app_uuid, &p_data->reg_oper.uuid);
181            HAL_CBACK(bt_gatt_callbacks, server->register_server_cb
182                , p_data->reg_oper.status
183                , p_data->reg_oper.server_if
184                , &app_uuid
185            );
186            break;
187        }
188
189        case BTA_GATTS_DEREG_EVT:
190            break;
191
192        case BTA_GATTS_CONNECT_EVT:
193        {
194            bt_bdaddr_t bda;
195            bdcpy(bda.address, p_data->conn.remote_bda);
196
197            btif_gatt_check_encrypted_link(p_data->conn.remote_bda);
198
199            HAL_CBACK(bt_gatt_callbacks, server->connection_cb,
200                      p_data->conn.conn_id, p_data->conn.server_if, TRUE, &bda);
201            break;
202        }
203
204        case BTA_GATTS_DISCONNECT_EVT:
205        {
206            bt_bdaddr_t bda;
207            bdcpy(bda.address, p_data->conn.remote_bda);
208
209            HAL_CBACK(bt_gatt_callbacks, server->connection_cb,
210                      p_data->conn.conn_id, p_data->conn.server_if, FALSE, &bda);
211            break;
212        }
213
214        case BTA_GATTS_CREATE_EVT:
215        {
216            btgatt_srvc_id_t srvc_id;
217            srvc_id.is_primary = p_data->create.is_primary;
218            srvc_id.id.inst_id = p_data->create.svc_instance;
219            bta_to_btif_uuid(&srvc_id.id.uuid, &p_data->create.uuid);
220
221            HAL_CBACK(bt_gatt_callbacks, server->service_added_cb,
222                      p_data->create.status, p_data->create.server_if, &srvc_id,
223                      p_data->create.service_id
224            );
225        }
226        break;
227
228        case BTA_GATTS_ADD_INCL_SRVC_EVT:
229            HAL_CBACK(bt_gatt_callbacks, server->included_service_added_cb,
230                      p_data->add_result.status,
231                      p_data->add_result.server_if,
232                      p_data->add_result.service_id,
233                      p_data->add_result.attr_id);
234            break;
235
236        case BTA_GATTS_ADD_CHAR_EVT:
237        {
238            bt_uuid_t uuid;
239            bta_to_btif_uuid(&uuid, &p_data->add_result.char_uuid);
240
241            HAL_CBACK(bt_gatt_callbacks, server->characteristic_added_cb,
242                      p_data->add_result.status,
243                      p_data->add_result.server_if,
244                      &uuid,
245                      p_data->add_result.service_id,
246                      p_data->add_result.attr_id);
247            break;
248        }
249
250        case BTA_GATTS_ADD_CHAR_DESCR_EVT:
251        {
252            bt_uuid_t uuid;
253            bta_to_btif_uuid(&uuid, &p_data->add_result.char_uuid);
254
255            HAL_CBACK(bt_gatt_callbacks, server->descriptor_added_cb,
256                      p_data->add_result.status,
257                      p_data->add_result.server_if,
258                      &uuid,
259                      p_data->add_result.service_id,
260                      p_data->add_result.attr_id);
261            break;
262        }
263
264        case BTA_GATTS_START_EVT:
265            HAL_CBACK(bt_gatt_callbacks, server->service_started_cb,
266                      p_data->srvc_oper.status,
267                      p_data->srvc_oper.server_if,
268                      p_data->srvc_oper.service_id);
269            break;
270
271        case BTA_GATTS_STOP_EVT:
272            HAL_CBACK(bt_gatt_callbacks, server->service_stopped_cb,
273                      p_data->srvc_oper.status,
274                      p_data->srvc_oper.server_if,
275                      p_data->srvc_oper.service_id);
276            break;
277
278        case BTA_GATTS_DELELTE_EVT:
279            HAL_CBACK(bt_gatt_callbacks, server->service_deleted_cb,
280                      p_data->srvc_oper.status,
281                      p_data->srvc_oper.server_if,
282                      p_data->srvc_oper.service_id);
283            break;
284
285        case BTA_GATTS_READ_EVT:
286        {
287            bt_bdaddr_t bda;
288            bdcpy(bda.address, p_data->req_data.remote_bda);
289
290            HAL_CBACK(bt_gatt_callbacks, server->request_read_cb,
291                      p_data->req_data.conn_id,p_data->req_data.trans_id, &bda,
292                      p_data->req_data.p_data->read_req.handle,
293                      p_data->req_data.p_data->read_req.offset,
294                      p_data->req_data.p_data->read_req.is_long);
295            break;
296        }
297
298        case BTA_GATTS_WRITE_EVT:
299        {
300            bt_bdaddr_t bda;
301            bdcpy(bda.address, p_data->req_data.remote_bda);
302
303            HAL_CBACK(bt_gatt_callbacks, server->request_write_cb,
304                      p_data->req_data.conn_id,p_data->req_data.trans_id, &bda,
305                      p_data->req_data.p_data->write_req.handle,
306                      p_data->req_data.p_data->write_req.offset,
307                      p_data->req_data.p_data->write_req.len,
308                      p_data->req_data.p_data->write_req.need_rsp,
309                      p_data->req_data.p_data->write_req.is_prep,
310                      p_data->req_data.p_data->write_req.value);
311            break;
312        }
313
314        case BTA_GATTS_EXEC_WRITE_EVT:
315        {
316            bt_bdaddr_t bda;
317            bdcpy(bda.address, p_data->req_data.remote_bda);
318
319            HAL_CBACK(bt_gatt_callbacks, server->request_exec_write_cb,
320                      p_data->req_data.conn_id,p_data->req_data.trans_id, &bda,
321                      p_data->req_data.p_data->exec_write);
322            break;
323        }
324
325        case BTA_GATTS_CONF_EVT:
326            HAL_CBACK(bt_gatt_callbacks, server->indication_sent_cb,
327                      p_data->req_data.conn_id, p_data->req_data.status);
328            break;
329
330        case BTA_GATTS_CONGEST_EVT:
331            HAL_CBACK(bt_gatt_callbacks, server->congestion_cb
332                , p_data->congest.conn_id
333                , p_data->congest.congested
334            );
335            break;
336
337        case BTA_GATTS_MTU_EVT:
338            HAL_CBACK(bt_gatt_callbacks, server->mtu_changed_cb
339                , p_data->req_data.conn_id
340                , p_data->req_data.p_data->mtu
341            );
342            break;
343
344        case BTA_GATTS_OPEN_EVT:
345        case BTA_GATTS_CANCEL_OPEN_EVT:
346        case BTA_GATTS_CLOSE_EVT:
347            ALOGD("%s: Empty event (%d)!", __FUNCTION__, event);
348            break;
349
350        default:
351            ALOGE("%s: Unhandled event (%d)!", __FUNCTION__, event);
352            break;
353    }
354
355    btapp_gatts_free_req_data(event, p_data);
356}
357
358static void btapp_gatts_cback(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
359{
360    bt_status_t status;
361    status = btif_transfer_context(btapp_gatts_handle_cback, (uint16_t) event,
362        (void*)p_data, sizeof(tBTA_GATTS), btapp_gatts_copy_req_data);
363    ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
364}
365
366static void btgatts_handle_event(uint16_t event, char* p_param)
367{
368    btif_gatts_cb_t* p_cb = (btif_gatts_cb_t*)p_param;
369    if (!p_cb) return;
370
371    ALOGD("%s: Event %d", __FUNCTION__, event);
372
373    switch (event)
374    {
375        case BTIF_GATTS_REGISTER_APP:
376        {
377            tBT_UUID uuid;
378            btif_to_bta_uuid(&uuid, &p_cb->uuid);
379            BTA_GATTS_AppRegister(&uuid, btapp_gatts_cback);
380            break;
381        }
382
383        case BTIF_GATTS_UNREGISTER_APP:
384            BTA_GATTS_AppDeregister(p_cb->server_if);
385            break;
386
387        case BTIF_GATTS_OPEN:
388        {
389            // Ensure device is in inquiry database
390            int addr_type = 0;
391            int device_type = 0;
392            tBTA_GATT_TRANSPORT transport = BTA_GATT_TRANSPORT_LE;
393
394            if (btif_get_address_type(p_cb->bd_addr.address, &addr_type) &&
395                btif_get_device_type(p_cb->bd_addr.address, &device_type) &&
396                device_type != BT_DEVICE_TYPE_BREDR)
397            {
398                BTA_DmAddBleDevice(p_cb->bd_addr.address, addr_type, device_type);
399            }
400
401            // Mark background connections
402            if (!p_cb->is_direct)
403                BTA_DmBleSetBgConnType(BTM_BLE_CONN_AUTO, NULL);
404
405            switch(device_type)
406            {
407                case BT_DEVICE_TYPE_BREDR:
408                    transport = BTA_GATT_TRANSPORT_BR_EDR;
409                    break;
410
411                case BT_DEVICE_TYPE_BLE:
412                    transport = BTA_GATT_TRANSPORT_LE;
413                    break;
414
415                case BT_DEVICE_TYPE_DUMO:
416                    if ((p_cb->transport == GATT_TRANSPORT_LE) &&
417                        (btif_storage_is_dmt_supported_device(&(p_cb->bd_addr)) == TRUE))
418                        transport = BTA_GATT_TRANSPORT_LE;
419                    else
420                        transport = BTA_GATT_TRANSPORT_BR_EDR;
421                    break;
422
423                default:
424                    BTIF_TRACE_ERROR (" GATT Open :Invalid device type %d",device_type);
425                    return;
426            }
427
428            // Connect!
429            BTA_GATTS_Open(p_cb->server_if, p_cb->bd_addr.address,
430                           p_cb->is_direct, transport);
431            break;
432        }
433
434        case BTIF_GATTS_CLOSE:
435            // Cancel pending foreground/background connections
436            BTA_GATTS_CancelOpen(p_cb->server_if, p_cb->bd_addr.address, TRUE);
437            BTA_GATTS_CancelOpen(p_cb->server_if, p_cb->bd_addr.address, FALSE);
438
439            // Close active connection
440            if (p_cb->conn_id != 0)
441                BTA_GATTS_Close(p_cb->conn_id);
442            break;
443
444        case BTIF_GATTS_CREATE_SERVICE:
445        {
446            tBTA_GATT_SRVC_ID srvc_id;
447            btif_to_bta_srvc_id(&srvc_id, &p_cb->srvc_id);
448            BTA_GATTS_CreateService(p_cb->server_if, &srvc_id.id.uuid,
449                                    srvc_id.id.inst_id, p_cb->num_handles,
450                                    srvc_id.is_primary);
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            ALOGE("%s: Unknown event (%d)!", __FUNCTION__, event);
513            break;
514    }
515}
516
517/************************************************************************************
518**  Server API Functions
519************************************************************************************/
520
521static 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
530static 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
539static 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
552static 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
563static 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
575static 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
587static 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
602static 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
615static 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
626static 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
636static 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
646static 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
661static 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
674const 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