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  *  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 
    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 
    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 
    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 
    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     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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