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