Home | History | Annotate | Download | only in src
      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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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