btif_gatt_server.c revision 17b04bd498405f2bb109a85562ebbdcb6bb06e95
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_ERROR1 (" 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