1 /****************************************************************************** 2 * 3 * Copyright (C) 2008-2012 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 * this file contains the GATT server functions 22 * 23 ******************************************************************************/ 24 25 #include "bt_target.h" 26 #include "bt_utils.h" 27 28 #if BLE_INCLUDED == TRUE 29 #include <string.h> 30 #include "gatt_int.h" 31 #include "l2c_api.h" 32 #include "l2c_int.h" 33 #define GATT_MTU_REQ_MIN_LEN 2 34 35 36 /******************************************************************************* 37 ** 38 ** Function gatt_sr_enqueue_cmd 39 ** 40 ** Description This function enqueue the request from client which needs a 41 ** application response, and update the transaction ID. 42 ** 43 ** Returns void 44 ** 45 *******************************************************************************/ 46 UINT32 gatt_sr_enqueue_cmd (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 handle) 47 { 48 tGATT_SR_CMD *p_cmd = &p_tcb->sr_cmd; 49 UINT32 trans_id = 0; 50 51 if ( (p_cmd->op_code == 0) || 52 (op_code == GATT_HANDLE_VALUE_CONF)) /* no pending request */ 53 { 54 if (op_code == GATT_CMD_WRITE || 55 op_code == GATT_SIGN_CMD_WRITE || 56 op_code == GATT_REQ_MTU || 57 op_code == GATT_HANDLE_VALUE_CONF) 58 { 59 trans_id = ++p_tcb->trans_id; 60 } 61 else 62 { 63 p_cmd->trans_id = ++p_tcb->trans_id; 64 p_cmd->op_code = op_code; 65 p_cmd->handle = handle; 66 p_cmd->status = GATT_NOT_FOUND; 67 p_tcb->trans_id %= GATT_TRANS_ID_MAX; 68 trans_id = p_cmd->trans_id; 69 } 70 } 71 72 return trans_id; 73 } 74 75 /******************************************************************************* 76 ** 77 ** Function gatt_sr_cmd_empty 78 ** 79 ** Description This function check the server command queue is empty or not. 80 ** 81 ** Returns TRUE if empty, FALSE if there is pending command. 82 ** 83 *******************************************************************************/ 84 BOOLEAN gatt_sr_cmd_empty (tGATT_TCB *p_tcb) 85 { 86 return(p_tcb->sr_cmd.op_code == 0); 87 } 88 89 /******************************************************************************* 90 ** 91 ** Function gatt_dequeue_sr_cmd 92 ** 93 ** Description This function dequeue the request from command queue. 94 ** 95 ** Returns void 96 ** 97 *******************************************************************************/ 98 void gatt_dequeue_sr_cmd (tGATT_TCB *p_tcb) 99 { 100 /* Double check in case any buffers are queued */ 101 GATT_TRACE_DEBUG("gatt_dequeue_sr_cmd" ); 102 if (p_tcb->sr_cmd.p_rsp_msg) 103 GATT_TRACE_ERROR("free p_tcb->sr_cmd.p_rsp_msg = %d", p_tcb->sr_cmd.p_rsp_msg); 104 osi_free_and_reset((void **)&p_tcb->sr_cmd.p_rsp_msg); 105 106 while (!fixed_queue_is_empty(p_tcb->sr_cmd.multi_rsp_q)) 107 osi_free(fixed_queue_try_dequeue(p_tcb->sr_cmd.multi_rsp_q)); 108 fixed_queue_free(p_tcb->sr_cmd.multi_rsp_q, NULL); 109 memset( &p_tcb->sr_cmd, 0, sizeof(tGATT_SR_CMD)); 110 } 111 112 /******************************************************************************* 113 ** 114 ** Function process_read_multi_rsp 115 ** 116 ** Description This function check the read multiple response. 117 ** 118 ** Returns BOOLEAN if all replies have been received 119 ** 120 *******************************************************************************/ 121 static BOOLEAN process_read_multi_rsp (tGATT_SR_CMD *p_cmd, tGATT_STATUS status, 122 tGATTS_RSP *p_msg, UINT16 mtu) 123 { 124 UINT16 ii, total_len, len; 125 BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(tGATTS_RSP)); 126 UINT8 *p; 127 BOOLEAN is_overflow = FALSE; 128 129 GATT_TRACE_DEBUG ("process_read_multi_rsp status=%d mtu=%d", status, mtu); 130 131 /* Enqueue the response */ 132 memcpy((void *)p_buf, (const void *)p_msg, sizeof(tGATTS_RSP)); 133 fixed_queue_enqueue(p_cmd->multi_rsp_q, p_buf); 134 135 p_cmd->status = status; 136 if (status == GATT_SUCCESS) 137 { 138 GATT_TRACE_DEBUG("Multi read count=%d num_hdls=%d", 139 fixed_queue_length(p_cmd->multi_rsp_q), 140 p_cmd->multi_req.num_handles); 141 /* Wait till we get all the responses */ 142 if (fixed_queue_length(p_cmd->multi_rsp_q) == p_cmd->multi_req.num_handles) 143 { 144 len = sizeof(BT_HDR) + L2CAP_MIN_OFFSET + mtu; 145 p_buf = (BT_HDR *)osi_calloc(len); 146 p_buf->offset = L2CAP_MIN_OFFSET; 147 p = (UINT8 *)(p_buf + 1) + p_buf->offset; 148 149 /* First byte in the response is the opcode */ 150 *p++ = GATT_RSP_READ_MULTI; 151 p_buf->len = 1; 152 153 /* Now walk through the buffers puting the data into the response in order */ 154 list_t *list = NULL; 155 const list_node_t *node = NULL; 156 if (! fixed_queue_is_empty(p_cmd->multi_rsp_q)) 157 list = fixed_queue_get_list(p_cmd->multi_rsp_q); 158 for (ii = 0; ii < p_cmd->multi_req.num_handles; ii++) 159 { 160 tGATTS_RSP *p_rsp = NULL; 161 162 if (list != NULL) { 163 if (ii == 0) 164 node = list_begin(list); 165 else 166 node = list_next(node); 167 if (node != list_end(list)) 168 p_rsp = (tGATTS_RSP *)list_node(node); 169 } 170 171 if (p_rsp != NULL) 172 { 173 174 total_len = (p_buf->len + p_rsp->attr_value.len); 175 176 if (total_len > mtu) 177 { 178 /* just send the partial response for the overflow case */ 179 len = p_rsp->attr_value.len - (total_len - mtu); 180 is_overflow = TRUE; 181 GATT_TRACE_DEBUG ("multi read overflow available len=%d val_len=%d", len, p_rsp->attr_value.len ); 182 } 183 else 184 { 185 len = p_rsp->attr_value.len; 186 } 187 188 if (p_rsp->attr_value.handle == p_cmd->multi_req.handles[ii]) 189 { 190 memcpy (p, p_rsp->attr_value.value, len); 191 if (!is_overflow) 192 p += len; 193 p_buf->len += len; 194 } 195 else 196 { 197 p_cmd->status = GATT_NOT_FOUND; 198 break; 199 } 200 201 if (is_overflow) 202 break; 203 204 } 205 else 206 { 207 p_cmd->status = GATT_NOT_FOUND; 208 break; 209 } 210 211 } /* loop through all handles*/ 212 213 214 /* Sanity check on the buffer length */ 215 if (p_buf->len == 0) 216 { 217 GATT_TRACE_ERROR("process_read_multi_rsp - nothing found!!"); 218 p_cmd->status = GATT_NOT_FOUND; 219 osi_free(p_buf); 220 GATT_TRACE_DEBUG("osi_free(p_buf)"); 221 } 222 else if (p_cmd->p_rsp_msg != NULL) 223 { 224 osi_free(p_buf); 225 } 226 else 227 { 228 p_cmd->p_rsp_msg = p_buf; 229 } 230 231 return(TRUE); 232 } 233 } 234 else /* any handle read exception occurs, return error */ 235 { 236 return(TRUE); 237 } 238 239 /* If here, still waiting */ 240 return(FALSE); 241 } 242 243 /******************************************************************************* 244 ** 245 ** Function gatt_sr_process_app_rsp 246 ** 247 ** Description This function checks whether the response message from application 248 ** match any pending request or not. 249 ** 250 ** Returns void 251 ** 252 *******************************************************************************/ 253 tGATT_STATUS gatt_sr_process_app_rsp (tGATT_TCB *p_tcb, tGATT_IF gatt_if, 254 UINT32 trans_id, UINT8 op_code, 255 tGATT_STATUS status, tGATTS_RSP *p_msg) 256 { 257 tGATT_STATUS ret_code = GATT_SUCCESS; 258 UNUSED(trans_id); 259 260 GATT_TRACE_DEBUG("gatt_sr_process_app_rsp gatt_if=%d", gatt_if); 261 262 gatt_sr_update_cback_cnt(p_tcb, gatt_if, FALSE, FALSE); 263 264 if (op_code == GATT_REQ_READ_MULTI) 265 { 266 /* If no error and still waiting, just return */ 267 if (!process_read_multi_rsp (&p_tcb->sr_cmd, status, p_msg, p_tcb->payload_size)) 268 return(GATT_SUCCESS); 269 } 270 else 271 { 272 if (op_code == GATT_REQ_PREPARE_WRITE && status == GATT_SUCCESS) 273 gatt_sr_update_prep_cnt(p_tcb, gatt_if, TRUE, FALSE); 274 275 if (op_code == GATT_REQ_EXEC_WRITE && status != GATT_SUCCESS) 276 gatt_sr_reset_cback_cnt(p_tcb); 277 278 p_tcb->sr_cmd.status = status; 279 280 if (gatt_sr_is_cback_cnt_zero(p_tcb) 281 && status == GATT_SUCCESS) 282 { 283 if (p_tcb->sr_cmd.p_rsp_msg == NULL) 284 { 285 p_tcb->sr_cmd.p_rsp_msg = attp_build_sr_msg (p_tcb, (UINT8)(op_code + 1), (tGATT_SR_MSG *)p_msg); 286 } 287 else 288 { 289 GATT_TRACE_ERROR("Exception!!! already has respond message"); 290 } 291 } 292 } 293 if (gatt_sr_is_cback_cnt_zero(p_tcb)) 294 { 295 if ( (p_tcb->sr_cmd.status == GATT_SUCCESS) && (p_tcb->sr_cmd.p_rsp_msg) ) 296 { 297 ret_code = attp_send_sr_msg (p_tcb, p_tcb->sr_cmd.p_rsp_msg); 298 p_tcb->sr_cmd.p_rsp_msg = NULL; 299 } 300 else 301 { 302 ret_code = gatt_send_error_rsp (p_tcb, status, op_code, p_tcb->sr_cmd.handle, FALSE); 303 } 304 305 gatt_dequeue_sr_cmd(p_tcb); 306 } 307 308 GATT_TRACE_DEBUG("gatt_sr_process_app_rsp ret_code=%d", ret_code); 309 310 return ret_code; 311 } 312 313 /******************************************************************************* 314 ** 315 ** Function gatt_process_exec_write_req 316 ** 317 ** Description This function is called to process the execute write request 318 ** from client. 319 ** 320 ** Returns void 321 ** 322 *******************************************************************************/ 323 void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data) 324 { 325 UINT8 *p = p_data, flag, i = 0; 326 UINT32 trans_id = 0; 327 tGATT_IF gatt_if; 328 UINT16 conn_id; 329 330 UNUSED(len); 331 332 #if GATT_CONFORMANCE_TESTING == TRUE 333 if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code) 334 { 335 GATT_TRACE_DEBUG("Conformance tst: forced err rspv for Execute Write: error status=%d", 336 gatt_cb.err_status); 337 338 gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, gatt_cb.handle, FALSE); 339 340 return; 341 } 342 #endif 343 344 STREAM_TO_UINT8(flag, p); 345 346 /* mask the flag */ 347 flag &= GATT_PREP_WRITE_EXEC; 348 349 350 /* no prep write is queued */ 351 if (!gatt_sr_is_prep_cnt_zero(p_tcb)) 352 { 353 trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, 0); 354 gatt_sr_copy_prep_cnt_to_cback_cnt(p_tcb); 355 356 for (i=0; i<GATT_MAX_APPS; i++) 357 { 358 if (p_tcb->prep_cnt[i]) 359 { 360 gatt_if = (tGATT_IF) (i+1); 361 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if); 362 gatt_sr_send_req_callback(conn_id, 363 trans_id, 364 GATTS_REQ_TYPE_WRITE_EXEC, 365 (tGATTS_DATA *)&flag); 366 p_tcb->prep_cnt[i]= 0; 367 } 368 } 369 } 370 else /* nothing needs to be executed , send response now */ 371 { 372 GATT_TRACE_ERROR("gatt_process_exec_write_req: no prepare write pending"); 373 gatt_send_error_rsp(p_tcb, GATT_ERROR, GATT_REQ_EXEC_WRITE, 0, FALSE); 374 } 375 } 376 377 /******************************************************************************* 378 ** 379 ** Function gatt_process_read_multi_req 380 ** 381 ** Description This function is called to process the read multiple request 382 ** from client. 383 ** 384 ** Returns void 385 ** 386 *******************************************************************************/ 387 void gatt_process_read_multi_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data) 388 { 389 UINT32 trans_id; 390 UINT16 handle = 0, ll = len; 391 UINT8 *p = p_data, i_rcb; 392 tGATT_STATUS err = GATT_SUCCESS; 393 UINT8 sec_flag, key_size; 394 395 GATT_TRACE_DEBUG("gatt_process_read_multi_req" ); 396 p_tcb->sr_cmd.multi_req.num_handles = 0; 397 398 gatt_sr_get_sec_info(p_tcb->peer_bda, 399 p_tcb->transport, 400 &sec_flag, 401 &key_size); 402 403 #if GATT_CONFORMANCE_TESTING == TRUE 404 if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code) 405 { 406 GATT_TRACE_DEBUG("Conformance tst: forced err rspvofr ReadMultiple: error status=%d", gatt_cb.err_status); 407 408 STREAM_TO_UINT16(handle, p); 409 410 gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, handle, FALSE); 411 412 return; 413 } 414 #endif 415 416 while (ll >= 2 && p_tcb->sr_cmd.multi_req.num_handles < GATT_MAX_READ_MULTI_HANDLES) 417 { 418 STREAM_TO_UINT16(handle, p); 419 420 if ((i_rcb = gatt_sr_find_i_rcb_by_handle(handle)) < GATT_MAX_SR_PROFILES) 421 { 422 p_tcb->sr_cmd.multi_req.handles[p_tcb->sr_cmd.multi_req.num_handles++] = handle; 423 424 /* check read permission */ 425 if ((err = gatts_read_attr_perm_check( gatt_cb.sr_reg[i_rcb].p_db, 426 FALSE, 427 handle, 428 sec_flag, 429 key_size)) 430 != GATT_SUCCESS) 431 { 432 GATT_TRACE_DEBUG("read permission denied : 0x%02x", err); 433 break; 434 } 435 } 436 else 437 { 438 /* invalid handle */ 439 err = GATT_INVALID_HANDLE; 440 break; 441 } 442 ll -= 2; 443 } 444 445 if (ll != 0) 446 { 447 GATT_TRACE_ERROR("max attribute handle reached in ReadMultiple Request."); 448 } 449 450 if (p_tcb->sr_cmd.multi_req.num_handles == 0) 451 err = GATT_INVALID_HANDLE; 452 453 if (err == GATT_SUCCESS) 454 { 455 if ((trans_id = gatt_sr_enqueue_cmd (p_tcb, op_code, p_tcb->sr_cmd.multi_req.handles[0])) != 0) 456 { 457 gatt_sr_reset_cback_cnt(p_tcb); /* read multiple use multi_rsp_q's count*/ 458 459 for (ll = 0; ll < p_tcb->sr_cmd.multi_req.num_handles; ll ++) { 460 tGATTS_RSP *p_msg = (tGATTS_RSP *)osi_calloc(sizeof(tGATTS_RSP)); 461 handle = p_tcb->sr_cmd.multi_req.handles[ll]; 462 i_rcb = gatt_sr_find_i_rcb_by_handle(handle); 463 464 p_msg->attr_value.handle = handle; 465 err = gatts_read_attr_value_by_handle(p_tcb, 466 gatt_cb.sr_reg[i_rcb].p_db, 467 op_code, 468 handle, 469 0, 470 p_msg->attr_value.value, 471 &p_msg->attr_value.len, 472 GATT_MAX_ATTR_LEN, 473 sec_flag, 474 key_size, 475 trans_id); 476 477 if (err == GATT_SUCCESS) { 478 gatt_sr_process_app_rsp(p_tcb, gatt_cb.sr_reg[i_rcb].gatt_if ,trans_id, op_code, GATT_SUCCESS, p_msg); 479 } 480 /* either not using or done using the buffer, release it now */ 481 osi_free(p_msg); 482 } 483 } 484 else 485 err = GATT_NO_RESOURCES; 486 } 487 488 /* in theroy BUSY is not possible(should already been checked), protected check */ 489 if (err != GATT_SUCCESS && err != GATT_PENDING && err != GATT_BUSY) 490 gatt_send_error_rsp(p_tcb, err, op_code, handle, FALSE); 491 } 492 493 /******************************************************************************* 494 ** 495 ** Function gatt_build_primary_service_rsp 496 ** 497 ** Description Primamry service request processed internally. Theretically 498 ** only deal with ReadByTypeVAlue and ReadByGroupType. 499 ** 500 ** Returns void 501 ** 502 *******************************************************************************/ 503 static tGATT_STATUS gatt_build_primary_service_rsp (BT_HDR *p_msg, tGATT_TCB *p_tcb, 504 UINT8 op_code, UINT16 s_hdl, 505 UINT16 e_hdl, UINT8 *p_data, tBT_UUID value) 506 { 507 tGATT_STATUS status = GATT_NOT_FOUND; 508 UINT8 handle_len =4, *p ; 509 tGATT_SR_REG *p_rcb; 510 tGATT_SRV_LIST_INFO *p_list= &gatt_cb.srv_list_info; 511 tGATT_SRV_LIST_ELEM *p_srv=NULL; 512 tBT_UUID *p_uuid; 513 514 UNUSED(p_data); 515 516 p = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET; 517 518 p_srv = p_list->p_first; 519 520 while (p_srv) 521 { 522 p_rcb = GATT_GET_SR_REG_PTR(p_srv->i_sreg); 523 524 if (p_rcb->in_use && 525 p_rcb->s_hdl >= s_hdl && 526 p_rcb->s_hdl <= e_hdl && 527 p_rcb->type == GATT_UUID_PRI_SERVICE) 528 { 529 if ((p_uuid = gatts_get_service_uuid (p_rcb->p_db)) != NULL) 530 { 531 if (op_code == GATT_REQ_READ_BY_GRP_TYPE) 532 handle_len = 4 + p_uuid->len; 533 534 /* get the length byte in the repsonse */ 535 if (p_msg->offset ==0) 536 { 537 *p ++ = op_code + 1; 538 p_msg->len ++; 539 p_msg->offset = handle_len; 540 541 if (op_code == GATT_REQ_READ_BY_GRP_TYPE) 542 { 543 *p ++ = (UINT8)p_msg->offset; /* length byte */ 544 p_msg->len ++; 545 } 546 } 547 548 if (p_msg->len + p_msg->offset <= p_tcb->payload_size && 549 handle_len == p_msg->offset) 550 { 551 if (op_code != GATT_REQ_FIND_TYPE_VALUE || 552 gatt_uuid_compare(value, *p_uuid)) 553 { 554 UINT16_TO_STREAM(p, p_rcb->s_hdl); 555 556 if (p_list->p_last_primary == p_srv && 557 p_list->p_last_primary == p_list->p_last) 558 { 559 GATT_TRACE_DEBUG("Use 0xFFFF for the last primary attribute"); 560 UINT16_TO_STREAM(p, 0xFFFF); /* see GATT ERRATA 4065, 4063, ATT ERRATA 4062 */ 561 } 562 else 563 { 564 UINT16_TO_STREAM(p, p_rcb->e_hdl); 565 } 566 567 if (op_code == GATT_REQ_READ_BY_GRP_TYPE) 568 gatt_build_uuid_to_stream(&p, *p_uuid); 569 570 status = GATT_SUCCESS; 571 p_msg->len += p_msg->offset; 572 } 573 } 574 else 575 break; 576 } 577 } 578 p_srv = p_srv->p_next; 579 } 580 p_msg->offset = L2CAP_MIN_OFFSET; 581 582 return status; 583 } 584 585 /******************************************************************************* 586 ** 587 ** Function gatt_build_find_info_rsp 588 ** 589 ** Description fill the find information response information in the given 590 ** buffer. 591 ** 592 ** Returns TRUE: if data filled sucessfully. 593 ** FALSE: packet full, or format mismatch. 594 ** 595 *******************************************************************************/ 596 static tGATT_STATUS gatt_build_find_info_rsp(tGATT_SR_REG *p_rcb, BT_HDR *p_msg, UINT16 *p_len, 597 UINT16 s_hdl, UINT16 e_hdl) 598 { 599 tGATT_STATUS status = GATT_NOT_FOUND; 600 UINT8 *p; 601 UINT16 len = *p_len; 602 tGATT_ATTR16 *p_attr = NULL; 603 UINT8 info_pair_len[2] = {4, 18}; 604 605 if (!p_rcb->p_db || !p_rcb->p_db->p_attr_list) 606 return status; 607 608 /* check the attribute database */ 609 p_attr = (tGATT_ATTR16 *) p_rcb->p_db->p_attr_list; 610 611 p = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET + p_msg->len; 612 613 while (p_attr) 614 { 615 if (p_attr->handle > e_hdl) 616 { 617 break; 618 } 619 620 if (p_attr->handle >= s_hdl) 621 { 622 if (p_msg->offset == 0) 623 p_msg->offset = (p_attr->uuid_type == GATT_ATTR_UUID_TYPE_16) ? GATT_INFO_TYPE_PAIR_16 : GATT_INFO_TYPE_PAIR_128; 624 625 if (len >= info_pair_len[p_msg->offset - 1]) 626 { 627 if (p_msg->offset == GATT_INFO_TYPE_PAIR_16 && p_attr->uuid_type == GATT_ATTR_UUID_TYPE_16) 628 { 629 UINT16_TO_STREAM(p, p_attr->handle); 630 UINT16_TO_STREAM(p, p_attr->uuid); 631 } 632 else if (p_msg->offset == GATT_INFO_TYPE_PAIR_128 && p_attr->uuid_type == GATT_ATTR_UUID_TYPE_128 ) 633 { 634 UINT16_TO_STREAM(p, p_attr->handle); 635 ARRAY_TO_STREAM (p, ((tGATT_ATTR128 *) p_attr)->uuid, LEN_UUID_128); 636 } 637 else if (p_msg->offset == GATT_INFO_TYPE_PAIR_128 && p_attr->uuid_type == GATT_ATTR_UUID_TYPE_32) 638 { 639 UINT16_TO_STREAM(p, p_attr->handle); 640 gatt_convert_uuid32_to_uuid128(p, ((tGATT_ATTR32 *) p_attr)->uuid); 641 p += LEN_UUID_128; 642 } 643 else 644 { 645 GATT_TRACE_ERROR("format mismatch"); 646 status = GATT_NO_RESOURCES; 647 break; 648 /* format mismatch */ 649 } 650 p_msg->len += info_pair_len[p_msg->offset - 1]; 651 len -= info_pair_len[p_msg->offset - 1]; 652 status = GATT_SUCCESS; 653 654 } 655 else 656 { 657 status = GATT_NO_RESOURCES; 658 break; 659 } 660 } 661 p_attr = (tGATT_ATTR16 *)p_attr->p_next; 662 } 663 664 *p_len = len; 665 return status; 666 } 667 668 /******************************************************************************* 669 ** 670 ** Function gatts_internal_read_by_type_req 671 ** 672 ** Description check to see if the ReadByType request can be handled internally. 673 ** 674 ** Returns void 675 ** 676 *******************************************************************************/ 677 static tGATT_STATUS gatts_validate_packet_format(UINT8 op_code, UINT16 *p_len, 678 UINT8 **p_data, tBT_UUID *p_uuid_filter, 679 UINT16 *p_s_hdl, UINT16 *p_e_hdl) 680 { 681 tGATT_STATUS reason = GATT_SUCCESS; 682 UINT16 uuid_len, s_hdl = 0, e_hdl = 0; 683 UINT16 len = *p_len; 684 UINT8 *p = *p_data; 685 686 if (len >= 4) 687 { 688 /* obtain starting handle, and ending handle */ 689 STREAM_TO_UINT16(s_hdl, p); 690 STREAM_TO_UINT16(e_hdl, p); 691 len -= 4; 692 693 if (s_hdl > e_hdl || !GATT_HANDLE_IS_VALID(s_hdl) || !GATT_HANDLE_IS_VALID(e_hdl)) 694 { 695 reason = GATT_INVALID_HANDLE; 696 } 697 /* for these PDUs, uuid filter must present */ 698 else if (op_code == GATT_REQ_READ_BY_GRP_TYPE || 699 op_code == GATT_REQ_FIND_TYPE_VALUE || 700 op_code == GATT_REQ_READ_BY_TYPE) 701 { 702 if (len >= 2 && p_uuid_filter != NULL) 703 { 704 uuid_len = (op_code == GATT_REQ_FIND_TYPE_VALUE) ? 2 : len; 705 706 /* parse uuid now */ 707 if (gatt_parse_uuid_from_cmd (p_uuid_filter, uuid_len, &p) == FALSE || 708 p_uuid_filter->len == 0) 709 { 710 GATT_TRACE_DEBUG("UUID filter does not exsit"); 711 reason = GATT_INVALID_PDU; 712 } 713 else 714 len -= p_uuid_filter->len; 715 } 716 else 717 reason = GATT_INVALID_PDU; 718 } 719 } 720 else 721 reason = GATT_INVALID_PDU; 722 723 *p_data = p; 724 *p_len = len; 725 *p_s_hdl = s_hdl; 726 *p_e_hdl = e_hdl; 727 728 return reason; 729 } 730 731 /******************************************************************************* 732 ** 733 ** Function gatts_process_primary_service_req 734 ** 735 ** Description process ReadByGroupType/ReadByTypeValue request, for discover 736 ** all primary services or discover primary service by UUID request. 737 ** 738 ** Returns void 739 ** 740 *******************************************************************************/ 741 void gatts_process_primary_service_req(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data) 742 { 743 UINT8 reason = GATT_INVALID_PDU; 744 UINT16 s_hdl = 0, e_hdl = 0; 745 tBT_UUID uuid, value, primary_service = {LEN_UUID_16, {GATT_UUID_PRI_SERVICE}}; 746 BT_HDR *p_msg = NULL; 747 UINT16 msg_len = (UINT16)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET); 748 749 memset (&value, 0, sizeof(tBT_UUID)); 750 reason = gatts_validate_packet_format(op_code, &len, &p_data, &uuid, &s_hdl, &e_hdl); 751 752 if (reason == GATT_SUCCESS) 753 { 754 if (gatt_uuid_compare(uuid, primary_service)) 755 { 756 if (op_code == GATT_REQ_FIND_TYPE_VALUE) 757 { 758 if (gatt_parse_uuid_from_cmd(&value, len, &p_data) == FALSE) 759 reason = GATT_INVALID_PDU; 760 } 761 762 if (reason == GATT_SUCCESS) { 763 p_msg = (BT_HDR *)osi_calloc(msg_len); 764 reason = gatt_build_primary_service_rsp (p_msg, p_tcb, op_code, 765 s_hdl, e_hdl, p_data, 766 value); 767 } 768 } 769 else 770 { 771 if (op_code == GATT_REQ_READ_BY_GRP_TYPE) 772 { 773 reason = GATT_UNSUPPORT_GRP_TYPE; 774 GATT_TRACE_DEBUG("unexpected ReadByGrpType Group: 0x%04x", uuid.uu.uuid16); 775 } 776 else 777 { 778 /* we do not support ReadByTypeValue with any non-primamry_service type */ 779 reason = GATT_NOT_FOUND; 780 GATT_TRACE_DEBUG("unexpected ReadByTypeValue type: 0x%04x", uuid.uu.uuid16); 781 } 782 } 783 } 784 785 if (reason != GATT_SUCCESS) 786 { 787 osi_free(p_msg); 788 gatt_send_error_rsp (p_tcb, reason, op_code, s_hdl, FALSE); 789 } 790 else 791 attp_send_sr_msg(p_tcb, p_msg); 792 793 } 794 795 /******************************************************************************* 796 ** 797 ** Function gatts_process_find_info 798 ** 799 ** Description process find information request, for discover character 800 ** descriptors. 801 ** 802 ** Returns void 803 ** 804 *******************************************************************************/ 805 static void gatts_process_find_info(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data) 806 { 807 UINT8 reason = GATT_INVALID_PDU, *p; 808 UINT16 s_hdl = 0, e_hdl = 0, buf_len; 809 BT_HDR *p_msg = NULL; 810 tGATT_SR_REG *p_rcb; 811 tGATT_SRV_LIST_INFO *p_list= &gatt_cb.srv_list_info; 812 tGATT_SRV_LIST_ELEM *p_srv=NULL; 813 814 reason = gatts_validate_packet_format(op_code, &len, &p_data, NULL, &s_hdl, &e_hdl); 815 816 if (reason == GATT_SUCCESS) 817 { 818 buf_len = (UINT16)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET); 819 820 p_msg = (BT_HDR *)osi_calloc(buf_len); 821 reason = GATT_NOT_FOUND; 822 823 p = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET; 824 *p ++ = op_code + 1; 825 p_msg->len = 2; 826 827 buf_len = p_tcb->payload_size - 2; 828 829 p_srv = p_list->p_first; 830 831 while (p_srv) { 832 p_rcb = GATT_GET_SR_REG_PTR(p_srv->i_sreg); 833 834 if (p_rcb->in_use && !(p_rcb->s_hdl > e_hdl || 835 p_rcb->e_hdl < s_hdl)) { 836 reason = gatt_build_find_info_rsp(p_rcb, p_msg, &buf_len, 837 s_hdl, e_hdl); 838 if (reason == GATT_NO_RESOURCES) { 839 reason = GATT_SUCCESS; 840 break; 841 } 842 } 843 p_srv = p_srv->p_next; 844 } 845 *p = (UINT8)p_msg->offset; 846 847 p_msg->offset = L2CAP_MIN_OFFSET; 848 } 849 850 if (reason != GATT_SUCCESS) 851 { 852 osi_free(p_msg); 853 gatt_send_error_rsp (p_tcb, reason, op_code, s_hdl, FALSE); 854 } 855 else 856 attp_send_sr_msg(p_tcb, p_msg); 857 858 } 859 860 /******************************************************************************* 861 ** 862 ** Function gatts_process_mtu_req 863 ** 864 ** Description This function is called to process excahnge MTU request. 865 ** Only used on LE. 866 ** 867 ** Returns void 868 ** 869 *******************************************************************************/ 870 static void gatts_process_mtu_req (tGATT_TCB *p_tcb, UINT16 len, UINT8 *p_data) 871 { 872 UINT16 mtu = 0; 873 UINT8 *p = p_data, i; 874 BT_HDR *p_buf; 875 UINT16 conn_id; 876 877 /* BR/EDR conenction, send error response */ 878 if (p_tcb->att_lcid != L2CAP_ATT_CID) 879 { 880 gatt_send_error_rsp (p_tcb, GATT_REQ_NOT_SUPPORTED, GATT_REQ_MTU, 0, FALSE); 881 } 882 else if (len < GATT_MTU_REQ_MIN_LEN) 883 { 884 GATT_TRACE_ERROR("invalid MTU request PDU received."); 885 gatt_send_error_rsp (p_tcb, GATT_INVALID_PDU, GATT_REQ_MTU, 0, FALSE); 886 } 887 else 888 { 889 STREAM_TO_UINT16 (mtu, p); 890 /* mtu must be greater than default MTU which is 23/48 */ 891 if (mtu < GATT_DEF_BLE_MTU_SIZE) 892 p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE; 893 else if (mtu > GATT_MAX_MTU_SIZE) 894 p_tcb->payload_size = GATT_MAX_MTU_SIZE; 895 else 896 p_tcb->payload_size = mtu; 897 898 GATT_TRACE_ERROR("MTU request PDU with MTU size %d", p_tcb->payload_size); 899 900 l2cble_set_fixed_channel_tx_data_length(p_tcb->peer_bda, L2CAP_ATT_CID, p_tcb->payload_size); 901 902 if ((p_buf = attp_build_sr_msg(p_tcb, GATT_RSP_MTU, (tGATT_SR_MSG *) &p_tcb->payload_size)) != NULL) 903 { 904 attp_send_sr_msg (p_tcb, p_buf); 905 906 /* Notify all registered applicaiton with new MTU size. Us a transaction ID */ 907 /* of 0, as no response is allowed from applcations */ 908 909 for (i = 0; i < GATT_MAX_APPS; i ++) 910 { 911 if (gatt_cb.cl_rcb[i].in_use ) 912 { 913 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_cb.cl_rcb[i].gatt_if); 914 gatt_sr_send_req_callback(conn_id, 0, GATTS_REQ_TYPE_MTU, 915 (tGATTS_DATA *)&p_tcb->payload_size); 916 } 917 } 918 919 } 920 } 921 } 922 923 /******************************************************************************* 924 ** 925 ** Function gatts_process_read_by_type_req 926 ** 927 ** Description process Read By type request. 928 ** This PDU can be used to perform: 929 ** - read characteristic value 930 ** - read characteristic descriptor value 931 ** - discover characteristic 932 ** - discover characteristic by UUID 933 ** - relationship discovery 934 ** 935 ** Returns void 936 ** 937 *******************************************************************************/ 938 void gatts_process_read_by_type_req(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data) 939 { 940 tBT_UUID uuid; 941 tGATT_SR_REG *p_rcb; 942 size_t msg_len = sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET; 943 UINT16 buf_len, s_hdl, e_hdl, err_hdl = 0; 944 BT_HDR *p_msg = NULL; 945 tGATT_STATUS reason, ret; 946 UINT8 *p; 947 UINT8 sec_flag, key_size; 948 tGATT_SRV_LIST_INFO *p_list= &gatt_cb.srv_list_info; 949 tGATT_SRV_LIST_ELEM *p_srv=NULL; 950 951 reason = gatts_validate_packet_format(op_code, &len, &p_data, &uuid, &s_hdl, &e_hdl); 952 953 #if GATT_CONFORMANCE_TESTING == TRUE 954 if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code) 955 { 956 GATT_TRACE_DEBUG("Conformance tst: forced err rsp for ReadByType: error status=%d", gatt_cb.err_status); 957 958 gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, s_hdl, FALSE); 959 960 return; 961 } 962 #endif 963 964 if (reason == GATT_SUCCESS) 965 { 966 p_msg = (BT_HDR *)osi_calloc(msg_len); 967 p = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET; 968 969 *p ++ = op_code + 1; 970 /* reserve length byte */ 971 p_msg->len = 2; 972 buf_len = p_tcb->payload_size - 2; 973 974 reason = GATT_NOT_FOUND; 975 976 p_srv = p_list->p_first; 977 978 while (p_srv) { 979 p_rcb = GATT_GET_SR_REG_PTR(p_srv->i_sreg); 980 981 if (p_rcb->in_use && !(p_rcb->s_hdl > e_hdl || 982 p_rcb->e_hdl < s_hdl)) { 983 gatt_sr_get_sec_info(p_tcb->peer_bda, p_tcb->transport, 984 &sec_flag, &key_size); 985 986 ret = gatts_db_read_attr_value_by_type(p_tcb, 987 p_rcb->p_db, 988 op_code, 989 p_msg, 990 s_hdl, 991 e_hdl, 992 uuid, 993 &buf_len, 994 sec_flag, 995 key_size, 996 0, 997 &err_hdl); 998 if (ret != GATT_NOT_FOUND) { 999 reason = ret; 1000 1001 if (ret == GATT_NO_RESOURCES) 1002 reason = GATT_SUCCESS; 1003 } 1004 if (ret != GATT_SUCCESS && ret != GATT_NOT_FOUND) { 1005 s_hdl = err_hdl; 1006 break; 1007 } 1008 } 1009 p_srv = p_srv->p_next; 1010 } 1011 *p = (UINT8)p_msg->offset; 1012 p_msg->offset = L2CAP_MIN_OFFSET; 1013 } 1014 if (reason != GATT_SUCCESS) 1015 { 1016 osi_free(p_msg); 1017 1018 /* in theroy BUSY is not possible(should already been checked), protected check */ 1019 if (reason != GATT_PENDING && reason != GATT_BUSY) 1020 gatt_send_error_rsp (p_tcb, reason, op_code, s_hdl, FALSE); 1021 } 1022 else 1023 attp_send_sr_msg(p_tcb, p_msg); 1024 1025 } 1026 1027 /******************************************************************************* 1028 ** 1029 ** Function gatts_process_write_req 1030 ** 1031 ** Description This function is called to process the write request 1032 ** from client. 1033 ** 1034 ** Returns void 1035 ** 1036 *******************************************************************************/ 1037 void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle, 1038 UINT8 op_code, UINT16 len, UINT8 *p_data) 1039 { 1040 tGATTS_DATA sr_data; 1041 UINT32 trans_id; 1042 tGATT_STATUS status; 1043 UINT8 sec_flag, key_size, *p = p_data; 1044 tGATT_SR_REG *p_sreg; 1045 UINT16 conn_id; 1046 1047 memset(&sr_data, 0, sizeof(tGATTS_DATA)); 1048 1049 switch (op_code) 1050 { 1051 case GATT_REQ_PREPARE_WRITE: 1052 if (len < 2) { 1053 GATT_TRACE_ERROR("%s: Prepare write request was invalid - missing offset, sending error response", __func__); 1054 gatt_send_error_rsp(p_tcb, GATT_INVALID_PDU, op_code, handle, FALSE); 1055 return; 1056 } 1057 sr_data.write_req.is_prep = TRUE; 1058 STREAM_TO_UINT16(sr_data.write_req.offset, p); 1059 len -= 2; 1060 /* fall through */ 1061 case GATT_SIGN_CMD_WRITE: 1062 if (op_code == GATT_SIGN_CMD_WRITE) 1063 { 1064 GATT_TRACE_DEBUG("Write CMD with data sigining" ); 1065 len -= GATT_AUTH_SIGN_LEN; 1066 } 1067 /* fall through */ 1068 case GATT_CMD_WRITE: 1069 case GATT_REQ_WRITE: 1070 if (op_code == GATT_REQ_WRITE || op_code == GATT_REQ_PREPARE_WRITE) 1071 sr_data.write_req.need_rsp = TRUE; 1072 sr_data.write_req.handle = handle; 1073 sr_data.write_req.len = len; 1074 if (len != 0 && p != NULL) 1075 { 1076 memcpy (sr_data.write_req.value, p, len); 1077 } 1078 break; 1079 } 1080 1081 gatt_sr_get_sec_info(p_tcb->peer_bda, 1082 p_tcb->transport, 1083 &sec_flag, 1084 &key_size); 1085 1086 status = gatts_write_attr_perm_check (gatt_cb.sr_reg[i_rcb].p_db, 1087 op_code, 1088 handle, 1089 sr_data.write_req.offset, 1090 p, 1091 len, 1092 sec_flag, 1093 key_size); 1094 1095 if (status == GATT_SUCCESS) 1096 { 1097 if ((trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, handle)) != 0) 1098 { 1099 p_sreg = &gatt_cb.sr_reg[i_rcb]; 1100 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_sreg->gatt_if); 1101 gatt_sr_send_req_callback(conn_id, 1102 trans_id, 1103 GATTS_REQ_TYPE_WRITE, 1104 &sr_data); 1105 1106 status = GATT_PENDING; 1107 } 1108 else 1109 { 1110 GATT_TRACE_ERROR("max pending command, send error"); 1111 status = GATT_BUSY; /* max pending command, application error */ 1112 } 1113 } 1114 1115 /* in theroy BUSY is not possible(should already been checked), protected check */ 1116 if (status != GATT_PENDING && status != GATT_BUSY && 1117 (op_code == GATT_REQ_PREPARE_WRITE || op_code == GATT_REQ_WRITE)) 1118 { 1119 gatt_send_error_rsp (p_tcb, status, op_code, handle, FALSE); 1120 } 1121 return; 1122 } 1123 1124 /******************************************************************************* 1125 ** 1126 ** Function gatts_process_read_req 1127 ** 1128 ** Description This function is called to process the read request 1129 ** from client. 1130 ** 1131 ** Returns void 1132 ** 1133 *******************************************************************************/ 1134 static void gatts_process_read_req(tGATT_TCB *p_tcb, tGATT_SR_REG *p_rcb, UINT8 op_code, 1135 UINT16 handle, UINT16 len, UINT8 *p_data) 1136 { 1137 size_t buf_len = sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET; 1138 tGATT_STATUS reason; 1139 UINT8 sec_flag, key_size, *p; 1140 UINT16 offset = 0, value_len = 0; 1141 BT_HDR *p_msg = (BT_HDR *)osi_calloc(buf_len); 1142 1143 UNUSED(len); 1144 1145 if (op_code == GATT_REQ_READ_BLOB) 1146 STREAM_TO_UINT16(offset, p_data); 1147 1148 p = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET; 1149 *p ++ = op_code + 1; 1150 p_msg->len = 1; 1151 buf_len = p_tcb->payload_size - 1; 1152 1153 gatt_sr_get_sec_info(p_tcb->peer_bda, p_tcb->transport, &sec_flag, 1154 &key_size); 1155 1156 reason = gatts_read_attr_value_by_handle(p_tcb, 1157 p_rcb->p_db, 1158 op_code, 1159 handle, 1160 offset, 1161 p, 1162 &value_len, 1163 (uint16_t)buf_len, 1164 sec_flag, 1165 key_size, 1166 0); 1167 1168 p_msg->len += value_len; 1169 1170 if (reason != GATT_SUCCESS) 1171 { 1172 osi_free(p_msg); 1173 1174 /* in theroy BUSY is not possible(should already been checked), protected check */ 1175 if (reason != GATT_PENDING && reason != GATT_BUSY) 1176 gatt_send_error_rsp (p_tcb, reason, op_code, handle, FALSE); 1177 } 1178 else 1179 attp_send_sr_msg(p_tcb, p_msg); 1180 1181 } 1182 1183 /******************************************************************************* 1184 ** 1185 ** Function gatts_process_attribute_req 1186 ** 1187 ** Description This function is called to process the per attribute handle request 1188 ** from client. 1189 ** 1190 ** Returns void 1191 ** 1192 *******************************************************************************/ 1193 void gatts_process_attribute_req (tGATT_TCB *p_tcb, UINT8 op_code, 1194 UINT16 len, UINT8 *p_data) 1195 { 1196 UINT16 handle = 0; 1197 UINT8 *p = p_data, i; 1198 tGATT_SR_REG *p_rcb = gatt_cb.sr_reg; 1199 tGATT_STATUS status = GATT_INVALID_HANDLE; 1200 tGATT_ATTR16 *p_attr; 1201 1202 if (len < 2) 1203 { 1204 GATT_TRACE_ERROR("Illegal PDU length, discard request"); 1205 status = GATT_INVALID_PDU; 1206 } 1207 else 1208 { 1209 STREAM_TO_UINT16(handle, p); 1210 len -= 2; 1211 } 1212 1213 #if GATT_CONFORMANCE_TESTING == TRUE 1214 gatt_cb.handle = handle; 1215 if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code) 1216 { 1217 GATT_TRACE_DEBUG("Conformance tst: forced err rsp: error status=%d", gatt_cb.err_status); 1218 1219 gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, handle, FALSE); 1220 1221 return; 1222 } 1223 #endif 1224 1225 if (GATT_HANDLE_IS_VALID(handle)) 1226 { 1227 for (i = 0; i < GATT_MAX_SR_PROFILES; i ++, p_rcb ++) 1228 { 1229 if (p_rcb->in_use && p_rcb->s_hdl <= handle && p_rcb->e_hdl >= handle) 1230 { 1231 p_attr = (tGATT_ATTR16 *)p_rcb->p_db->p_attr_list; 1232 1233 while (p_attr) 1234 { 1235 if (p_attr->handle == handle) 1236 { 1237 switch (op_code) 1238 { 1239 case GATT_REQ_READ: /* read char/char descriptor value */ 1240 case GATT_REQ_READ_BLOB: 1241 gatts_process_read_req(p_tcb, p_rcb, op_code, handle, len, p); 1242 break; 1243 1244 case GATT_REQ_WRITE: /* write char/char descriptor value */ 1245 case GATT_CMD_WRITE: 1246 case GATT_SIGN_CMD_WRITE: 1247 case GATT_REQ_PREPARE_WRITE: 1248 gatts_process_write_req(p_tcb, i, handle, op_code, len, p); 1249 break; 1250 default: 1251 break; 1252 } 1253 status = GATT_SUCCESS; 1254 break; 1255 } 1256 p_attr = (tGATT_ATTR16 *)p_attr->p_next; 1257 } 1258 break; 1259 } 1260 } 1261 } 1262 1263 if (status != GATT_SUCCESS && op_code != GATT_CMD_WRITE && op_code != GATT_SIGN_CMD_WRITE) 1264 gatt_send_error_rsp (p_tcb, status, op_code, handle, FALSE); 1265 } 1266 1267 /******************************************************************************* 1268 ** 1269 ** Function gatts_proc_srv_chg_ind_ack 1270 ** 1271 ** Description This function process the service changed indicaiton ACK 1272 ** 1273 ** Returns void 1274 ** 1275 *******************************************************************************/ 1276 static void gatts_proc_srv_chg_ind_ack(tGATT_TCB *p_tcb ) 1277 { 1278 tGATTS_SRV_CHG_REQ req; 1279 tGATTS_SRV_CHG *p_buf = NULL; 1280 1281 GATT_TRACE_DEBUG("gatts_proc_srv_chg_ind_ack"); 1282 1283 if ((p_buf = gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda)) != NULL) 1284 { 1285 GATT_TRACE_DEBUG("NV update set srv chg = FALSE"); 1286 p_buf->srv_changed = FALSE; 1287 memcpy(&req.srv_chg, p_buf, sizeof(tGATTS_SRV_CHG)); 1288 if (gatt_cb.cb_info.p_srv_chg_callback) 1289 (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_UPDATE_CLIENT,&req, NULL); 1290 } 1291 } 1292 1293 /******************************************************************************* 1294 ** 1295 ** Function gatts_chk_pending_ind 1296 ** 1297 ** Description This function check any pending indication needs to be sent if 1298 ** there is a pending indication then sent the indication 1299 ** 1300 ** Returns void 1301 ** 1302 *******************************************************************************/ 1303 static void gatts_chk_pending_ind(tGATT_TCB *p_tcb ) 1304 { 1305 GATT_TRACE_DEBUG("%s", __func__); 1306 1307 tGATT_VALUE *p_buf = (tGATT_VALUE *)fixed_queue_try_peek_first(p_tcb->pending_ind_q); 1308 if (p_buf != NULL) 1309 { 1310 GATTS_HandleValueIndication(p_buf->conn_id, 1311 p_buf->handle, 1312 p_buf->len, 1313 p_buf->value); 1314 osi_free(fixed_queue_try_remove_from_queue(p_tcb->pending_ind_q, 1315 p_buf)); 1316 } 1317 } 1318 1319 /******************************************************************************* 1320 ** 1321 ** Function gatts_proc_ind_ack 1322 ** 1323 ** Description This function process the Indication ack 1324 ** 1325 ** Returns TRUE continue to process the indication ack by the aaplication 1326 ** if the ACk is not a Service Changed Indication Ack 1327 ** 1328 *******************************************************************************/ 1329 static BOOLEAN gatts_proc_ind_ack(tGATT_TCB *p_tcb, UINT16 ack_handle) 1330 { 1331 BOOLEAN continue_processing = TRUE; 1332 1333 GATT_TRACE_DEBUG ("gatts_proc_ind_ack ack handle=%d", ack_handle); 1334 1335 if (ack_handle == gatt_cb.handle_of_h_r) 1336 { 1337 gatts_proc_srv_chg_ind_ack(p_tcb); 1338 /* there is no need to inform the application since srv chg is handled internally by GATT */ 1339 continue_processing = FALSE; 1340 } 1341 1342 gatts_chk_pending_ind(p_tcb); 1343 return continue_processing; 1344 } 1345 1346 /******************************************************************************* 1347 ** 1348 ** Function gatts_process_value_conf 1349 ** 1350 ** Description This function is called to process the handle value confirmation. 1351 ** 1352 ** Returns void 1353 ** 1354 *******************************************************************************/ 1355 void gatts_process_value_conf(tGATT_TCB *p_tcb, UINT8 op_code) 1356 { 1357 UINT16 handle = p_tcb->indicate_handle; 1358 UINT32 trans_id; 1359 UINT8 i; 1360 tGATT_SR_REG *p_rcb = gatt_cb.sr_reg; 1361 BOOLEAN continue_processing; 1362 UINT16 conn_id; 1363 1364 alarm_cancel(p_tcb->conf_timer); 1365 if (GATT_HANDLE_IS_VALID(handle)) 1366 { 1367 p_tcb->indicate_handle = 0; 1368 continue_processing = gatts_proc_ind_ack(p_tcb, handle); 1369 1370 if (continue_processing) 1371 { 1372 for (i = 0; i < GATT_MAX_SR_PROFILES; i ++, p_rcb ++) 1373 { 1374 if (p_rcb->in_use && p_rcb->s_hdl <= handle && p_rcb->e_hdl >= handle) 1375 { 1376 trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, handle); 1377 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_rcb->gatt_if); 1378 gatt_sr_send_req_callback(conn_id, 1379 trans_id, GATTS_REQ_TYPE_CONF, (tGATTS_DATA *)&handle); 1380 } 1381 } 1382 } 1383 } 1384 else 1385 { 1386 GATT_TRACE_ERROR("unexpected handle value confirmation"); 1387 } 1388 } 1389 1390 /******************************************************************************* 1391 ** 1392 ** Function gatt_server_handle_client_req 1393 ** 1394 ** Description This function is called to handle the client requests to 1395 ** server. 1396 ** 1397 ** 1398 ** Returns void 1399 ** 1400 *******************************************************************************/ 1401 void gatt_server_handle_client_req (tGATT_TCB *p_tcb, UINT8 op_code, 1402 UINT16 len, UINT8 *p_data) 1403 { 1404 /* there is pending command, discard this one */ 1405 if (!gatt_sr_cmd_empty(p_tcb) && op_code != GATT_HANDLE_VALUE_CONF) 1406 return; 1407 1408 /* the size of the message may not be bigger than the local max PDU size*/ 1409 /* The message has to be smaller than the agreed MTU, len does not include op code */ 1410 if (len >= p_tcb->payload_size) 1411 { 1412 GATT_TRACE_ERROR("server receive invalid PDU size:%d pdu size:%d", len + 1, p_tcb->payload_size ); 1413 /* for invalid request expecting response, send it now */ 1414 if (op_code != GATT_CMD_WRITE && 1415 op_code != GATT_SIGN_CMD_WRITE && 1416 op_code != GATT_HANDLE_VALUE_CONF) 1417 { 1418 gatt_send_error_rsp (p_tcb, GATT_INVALID_PDU, op_code, 0, FALSE); 1419 } 1420 /* otherwise, ignore the pkt */ 1421 } 1422 else 1423 { 1424 switch (op_code) 1425 { 1426 case GATT_REQ_READ_BY_GRP_TYPE: /* discover primary services */ 1427 case GATT_REQ_FIND_TYPE_VALUE: /* discover service by UUID */ 1428 gatts_process_primary_service_req (p_tcb, op_code, len, p_data); 1429 break; 1430 1431 case GATT_REQ_FIND_INFO:/* discover char descrptor */ 1432 gatts_process_find_info(p_tcb, op_code, len, p_data); 1433 break; 1434 1435 case GATT_REQ_READ_BY_TYPE: /* read characteristic value, char descriptor value */ 1436 /* discover characteristic, discover char by UUID */ 1437 gatts_process_read_by_type_req(p_tcb, op_code, len, p_data); 1438 break; 1439 1440 1441 case GATT_REQ_READ: /* read char/char descriptor value */ 1442 case GATT_REQ_READ_BLOB: 1443 case GATT_REQ_WRITE: /* write char/char descriptor value */ 1444 case GATT_CMD_WRITE: 1445 case GATT_SIGN_CMD_WRITE: 1446 case GATT_REQ_PREPARE_WRITE: 1447 gatts_process_attribute_req (p_tcb, op_code, len, p_data); 1448 break; 1449 1450 case GATT_HANDLE_VALUE_CONF: 1451 gatts_process_value_conf (p_tcb, op_code); 1452 break; 1453 1454 case GATT_REQ_MTU: 1455 gatts_process_mtu_req (p_tcb, len, p_data); 1456 break; 1457 1458 case GATT_REQ_EXEC_WRITE: 1459 gatt_process_exec_write_req (p_tcb, op_code, len, p_data); 1460 break; 1461 1462 case GATT_REQ_READ_MULTI: 1463 gatt_process_read_multi_req (p_tcb, op_code, len, p_data); 1464 break; 1465 1466 default: 1467 break; 1468 } 1469 } 1470 } 1471 1472 #endif /* BLE_INCLUDED */ 1473