1 /****************************************************************************** 2 * 3 * Copyright (C) 1999-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 main GATT client functions 22 * 23 ******************************************************************************/ 24 25 #include "bt_target.h" 26 27 #if BLE_INCLUDED == TRUE 28 29 #include <string.h> 30 #include "gki.h" 31 #include "gatt_int.h" 32 33 #define GATT_WRITE_LONG_HDR_SIZE 5 /* 1 opcode + 2 handle + 2 offset */ 34 #define GATT_READ_CHAR_VALUE_HDL (GATT_READ_CHAR_VALUE | 0x80) 35 #define GATT_READ_INC_SRV_UUID128 (GATT_DISC_INC_SRVC | 0x90) 36 37 #define GATT_PREP_WRITE_RSP_MIN_LEN 4 38 #define GATT_NOTIFICATION_MIN_LEN 2 39 #define GATT_WRITE_RSP_MIN_LEN 2 40 #define GATT_INFO_RSP_MIN_LEN 1 41 #define GATT_MTU_RSP_MIN_LEN 2 42 #define GATT_READ_BY_TYPE_RSP_MIN_LEN 1 43 44 /******************************************************************************** 45 ** G L O B A L G A T T D A T A * 46 *********************************************************************************/ 47 void gatt_send_prepare_write(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb); 48 49 UINT8 disc_type_to_att_opcode[GATT_DISC_MAX] = 50 { 51 0, 52 GATT_REQ_READ_BY_GRP_TYPE, /* GATT_DISC_SRVC_ALL = 1, */ 53 GATT_REQ_FIND_TYPE_VALUE, /* GATT_DISC_SRVC_BY_UUID, */ 54 GATT_REQ_READ_BY_TYPE, /* GATT_DISC_INC_SRVC, */ 55 GATT_REQ_READ_BY_TYPE, /* GATT_DISC_CHAR, */ 56 GATT_REQ_FIND_INFO /* GATT_DISC_CHAR_DSCPT, */ 57 }; 58 59 UINT16 disc_type_to_uuid[GATT_DISC_MAX] = 60 { 61 0, /* reserved */ 62 GATT_UUID_PRI_SERVICE, /* <service> DISC_SRVC_ALL */ 63 GATT_UUID_PRI_SERVICE, /* <service> for DISC_SERVC_BY_UUID */ 64 GATT_UUID_INCLUDE_SERVICE, /* <include_service> for DISC_INC_SRVC */ 65 GATT_UUID_CHAR_DECLARE, /* <characteristic> for DISC_CHAR */ 66 0 /* no type filtering for DISC_CHAR_DSCPT */ 67 }; 68 69 70 /******************************************************************************* 71 ** 72 ** Function gatt_act_discovery 73 ** 74 ** Description GATT discovery operation. 75 ** 76 ** Returns void. 77 ** 78 *******************************************************************************/ 79 void gatt_act_discovery(tGATT_CLCB *p_clcb) 80 { 81 UINT8 op_code = disc_type_to_att_opcode[p_clcb->op_subtype]; 82 tGATT_CL_MSG cl_req; 83 tGATT_STATUS st; 84 85 if (p_clcb->s_handle <= p_clcb->e_handle && p_clcb->s_handle != 0) 86 { 87 memset(&cl_req, 0, sizeof(tGATT_CL_MSG)); 88 89 cl_req.browse.s_handle = p_clcb->s_handle; 90 cl_req.browse.e_handle = p_clcb->e_handle; 91 92 if (disc_type_to_uuid[p_clcb->op_subtype] != 0) 93 { 94 cl_req.browse.uuid.len = 2; 95 cl_req.browse.uuid.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype]; 96 } 97 98 if (p_clcb->op_subtype == GATT_DISC_SRVC_BY_UUID) /* fill in the FindByTypeValue request info*/ 99 { 100 cl_req.find_type_value.uuid.len = 2; 101 cl_req.find_type_value.uuid.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype]; 102 cl_req.find_type_value.s_handle = p_clcb->s_handle; 103 cl_req.find_type_value.e_handle = p_clcb->e_handle; 104 cl_req.find_type_value.value_len = p_clcb->uuid.len; 105 memcpy (cl_req.find_type_value.value, &p_clcb->uuid.uu, p_clcb->uuid.len); 106 } 107 108 st = attp_send_cl_msg(p_clcb->p_tcb, p_clcb->clcb_idx, op_code, &cl_req); 109 110 if (st != GATT_SUCCESS && st != GATT_CMD_STARTED) 111 { 112 gatt_end_operation(p_clcb, GATT_ERROR, NULL); 113 } 114 } 115 else /* end of handle range */ 116 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL); 117 } 118 119 /******************************************************************************* 120 ** 121 ** Function gatt_act_read 122 ** 123 ** Description GATT read operation. 124 ** 125 ** Returns void. 126 ** 127 *******************************************************************************/ 128 void gatt_act_read (tGATT_CLCB *p_clcb, UINT16 offset) 129 { 130 tGATT_TCB *p_tcb = p_clcb->p_tcb; 131 UINT8 rt = GATT_INTERNAL_ERROR; 132 tGATT_CL_MSG msg; 133 UINT8 op_code = 0; 134 135 memset (&msg, 0, sizeof(tGATT_CL_MSG)); 136 137 switch (p_clcb->op_subtype) 138 { 139 case GATT_READ_CHAR_VALUE: 140 case GATT_READ_BY_TYPE: 141 op_code = GATT_REQ_READ_BY_TYPE; 142 msg.browse.s_handle = p_clcb->s_handle; 143 msg.browse.e_handle = p_clcb->e_handle; 144 if (p_clcb->op_subtype == GATT_READ_BY_TYPE) 145 memcpy(&msg.browse.uuid, &p_clcb->uuid, sizeof(tBT_UUID)); 146 else 147 { 148 msg.browse.uuid.len = LEN_UUID_16; 149 msg.browse.uuid.uu.uuid16 = GATT_UUID_CHAR_DECLARE; 150 } 151 break; 152 153 case GATT_READ_CHAR_VALUE_HDL: 154 case GATT_READ_BY_HANDLE: 155 if (!p_clcb->counter) 156 { 157 op_code = GATT_REQ_READ; 158 msg.handle = p_clcb->s_handle; 159 } 160 else 161 { 162 if (!p_clcb->first_read_blob_after_read) 163 p_clcb->first_read_blob_after_read = TRUE; 164 else 165 p_clcb->first_read_blob_after_read = FALSE; 166 167 GATT_TRACE_DEBUG1("gatt_act_read first_read_blob_after_read=%d", 168 p_clcb->first_read_blob_after_read); 169 op_code = GATT_REQ_READ_BLOB; 170 msg.read_blob.offset = offset; 171 msg.read_blob.handle = p_clcb->s_handle; 172 } 173 p_clcb->op_subtype &= ~ 0x80; 174 break; 175 176 case GATT_READ_PARTIAL: 177 op_code = GATT_REQ_READ_BLOB; 178 msg.read_blob.handle = p_clcb->s_handle; 179 msg.read_blob.offset = offset; 180 break; 181 182 case GATT_READ_MULTIPLE: 183 op_code = GATT_REQ_READ_MULTI; 184 memcpy (&msg.read_multi, p_clcb->p_attr_buf, sizeof(tGATT_READ_MULTI)); 185 break; 186 187 case GATT_READ_INC_SRV_UUID128: 188 op_code = GATT_REQ_READ; 189 msg.handle = p_clcb->s_handle; 190 p_clcb->op_subtype &= ~ 0x90; 191 break; 192 193 default: 194 GATT_TRACE_ERROR1("Unknown read type: %d", p_clcb->op_subtype); 195 break; 196 } 197 198 if (op_code != 0) 199 rt = attp_send_cl_msg(p_tcb, p_clcb->clcb_idx, op_code, &msg); 200 201 if ( op_code == 0 || (rt != GATT_SUCCESS && rt != GATT_CMD_STARTED)) 202 { 203 gatt_end_operation(p_clcb, rt, NULL); 204 } 205 } 206 207 /******************************************************************************* 208 ** 209 ** Function gatt_act_write 210 ** 211 ** Description GATT write operation. 212 ** 213 ** Returns void. 214 ** 215 *******************************************************************************/ 216 void gatt_act_write (tGATT_CLCB *p_clcb, UINT8 sec_act) 217 { 218 tGATT_TCB *p_tcb = p_clcb->p_tcb; 219 UINT8 rt = GATT_SUCCESS, op_code = 0; 220 tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf; 221 222 if (p_attr) 223 { 224 switch (p_clcb->op_subtype) 225 { 226 case GATT_WRITE_NO_RSP: 227 p_clcb->s_handle = p_attr->handle; 228 op_code = (sec_act == GATT_SEC_SIGN_DATA) ? GATT_SIGN_CMD_WRITE : GATT_CMD_WRITE; 229 rt = gatt_send_write_msg(p_tcb, 230 p_clcb->clcb_idx, 231 op_code, 232 p_attr->handle, 233 p_attr->len, 234 0, 235 p_attr->value); 236 break; 237 238 case GATT_WRITE: 239 if (p_attr->len <= (p_tcb->payload_size - GATT_HDR_SIZE)) 240 { 241 p_clcb->s_handle = p_attr->handle; 242 243 rt = gatt_send_write_msg(p_tcb, 244 p_clcb->clcb_idx, 245 GATT_REQ_WRITE, 246 p_attr->handle, 247 p_attr->len, 248 0, 249 p_attr->value); 250 } 251 else /* prepare write for long attribute */ 252 { 253 gatt_send_prepare_write(p_tcb, p_clcb); 254 } 255 break; 256 257 case GATT_WRITE_PREPARE: 258 gatt_send_prepare_write(p_tcb, p_clcb); 259 break; 260 261 default: 262 rt = GATT_INTERNAL_ERROR; 263 GATT_TRACE_ERROR1("Unknown write type: %d", p_clcb->op_subtype); 264 break; 265 } 266 } 267 else 268 rt = GATT_INTERNAL_ERROR; 269 270 if ((rt != GATT_SUCCESS && rt != GATT_CMD_STARTED) 271 || (rt != GATT_CMD_STARTED && p_clcb->op_subtype == GATT_WRITE_NO_RSP)) 272 { 273 if (rt != GATT_SUCCESS) 274 { 275 GATT_TRACE_ERROR1("gatt_act_write() failed op_code=0x%x", op_code); 276 } 277 gatt_end_operation(p_clcb, rt, NULL); 278 } 279 } 280 /******************************************************************************* 281 ** 282 ** Function gatt_send_queue_write_cancel 283 ** 284 ** Description send queue write cancel 285 ** 286 ** Returns void. 287 ** 288 *******************************************************************************/ 289 void gatt_send_queue_write_cancel (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, tGATT_EXEC_FLAG flag) 290 { 291 UINT8 rt ; 292 293 GATT_TRACE_DEBUG0("gatt_send_queue_write_cancel "); 294 295 rt = attp_send_cl_msg(p_tcb, p_clcb->clcb_idx, GATT_REQ_EXEC_WRITE, (tGATT_CL_MSG *)&flag); 296 297 if (rt != GATT_SUCCESS) 298 { 299 gatt_end_operation(p_clcb, rt, NULL); 300 } 301 } 302 /******************************************************************************* 303 ** 304 ** Function gatt_check_write_long_terminate 305 ** 306 ** Description To terminate write long or not. 307 ** 308 ** Returns TRUE: write long is terminated; FALSE keep sending. 309 ** 310 *******************************************************************************/ 311 BOOLEAN gatt_check_write_long_terminate(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, tGATT_VALUE *p_rsp_value) 312 { 313 tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf; 314 BOOLEAN exec = FALSE; 315 tGATT_EXEC_FLAG flag = GATT_PREP_WRITE_EXEC; 316 317 GATT_TRACE_DEBUG0("gatt_check_write_long_terminate "); 318 /* check the first write response status */ 319 if (p_rsp_value != NULL) 320 { 321 if (p_rsp_value->handle != p_attr->handle || 322 p_rsp_value->len != p_clcb->counter || 323 memcmp(p_rsp_value->value, p_attr->value + p_attr->offset, p_rsp_value->len)) 324 { 325 /* data does not match */ 326 p_clcb->status = GATT_ERROR; 327 flag = GATT_PREP_WRITE_CANCEL; 328 exec = TRUE; 329 } 330 else /* response checking is good */ 331 { 332 p_clcb->status = GATT_SUCCESS; 333 /* update write offset and check if end of attribute value */ 334 if ((p_attr->offset += p_rsp_value->len) >= p_attr->len) 335 exec = TRUE; 336 } 337 } 338 if (exec) 339 { 340 gatt_send_queue_write_cancel (p_tcb, p_clcb, flag); 341 return TRUE; 342 } 343 return FALSE; 344 } 345 /******************************************************************************* 346 ** 347 ** Function gatt_send_prepare_write 348 ** 349 ** Description Send prepare write. 350 ** 351 ** Returns void. 352 ** 353 *******************************************************************************/ 354 void gatt_send_prepare_write(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb) 355 { 356 tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf; 357 UINT16 to_send, offset; 358 UINT8 rt = GATT_SUCCESS; 359 UINT8 type = p_clcb->op_subtype; 360 361 GATT_TRACE_DEBUG1("gatt_send_prepare_write type=0x%x", type ); 362 to_send = p_attr->len - p_attr->offset; 363 364 if (to_send > (p_tcb->payload_size - GATT_WRITE_LONG_HDR_SIZE)) /* 2 = UINT16 offset bytes */ 365 to_send = p_tcb->payload_size - GATT_WRITE_LONG_HDR_SIZE; 366 367 p_clcb->s_handle = p_attr->handle; 368 369 offset = p_attr->offset; 370 if (type == GATT_WRITE_PREPARE) 371 { 372 offset += p_clcb->start_offset; 373 } 374 375 GATT_TRACE_DEBUG2("offset =0x%x len=%d", offset, to_send ); 376 377 rt = gatt_send_write_msg(p_tcb, 378 p_clcb->clcb_idx, 379 GATT_REQ_PREPARE_WRITE, 380 p_attr->handle, 381 to_send, /* length */ 382 offset, /* used as offset */ 383 p_attr->value + p_attr->offset); /* data */ 384 385 /* remember the write long attribute length */ 386 p_clcb->counter = to_send; 387 388 if (rt != GATT_SUCCESS && rt != GATT_CMD_STARTED) 389 { 390 gatt_end_operation(p_clcb, rt, NULL); 391 } 392 } 393 394 395 /******************************************************************************* 396 ** 397 ** Function gatt_process_find_type_value_rsp 398 ** 399 ** Description This function is called to handle find by type value response. 400 ** 401 ** 402 ** Returns void 403 ** 404 *******************************************************************************/ 405 void gatt_process_find_type_value_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data) 406 { 407 tGATT_DISC_RES result; 408 UINT8 *p = p_data; 409 410 GATT_TRACE_DEBUG0("gatt_process_find_type_value_rsp "); 411 /* unexpected response */ 412 if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_SRVC_BY_UUID) 413 return; 414 415 memset (&result, 0, sizeof(tGATT_DISC_RES)); 416 result.type.len = 2; 417 result.type.uu.uuid16 = GATT_UUID_PRI_SERVICE; 418 419 /* returns a series of handle ranges */ 420 while (len >= 4) 421 { 422 STREAM_TO_UINT16 (result.handle, p); 423 STREAM_TO_UINT16 (result.value.group_value.e_handle, p); 424 memcpy (&result.value.group_value.service_type, &p_clcb->uuid, sizeof(tBT_UUID)); 425 426 len -= 4; 427 428 if (p_clcb->p_reg->app_cb.p_disc_res_cb) 429 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result); 430 } 431 432 /* last handle + 1 */ 433 p_clcb->s_handle = (result.value.group_value.e_handle == 0) ? 0 : (result.value.group_value.e_handle + 1); 434 /* initiate another request */ 435 gatt_act_discovery(p_clcb) ; 436 } 437 /******************************************************************************* 438 ** 439 ** Function gatt_process_read_info_rsp 440 ** 441 ** Description This function is called to handle the read information 442 ** response. 443 ** 444 ** 445 ** Returns void 446 ** 447 *******************************************************************************/ 448 void gatt_process_read_info_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, 449 UINT16 len, UINT8 *p_data) 450 { 451 tGATT_DISC_RES result; 452 UINT8 *p = p_data, uuid_len = 0, type; 453 454 if (len < GATT_INFO_RSP_MIN_LEN) 455 { 456 GATT_TRACE_ERROR0("invalid Info Response PDU received, discard."); 457 gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL); 458 return; 459 } 460 /* unexpected response */ 461 if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_CHAR_DSCPT) 462 return; 463 464 STREAM_TO_UINT8(type, p); 465 len -= 1; 466 467 if (type == GATT_INFO_TYPE_PAIR_16) 468 uuid_len = LEN_UUID_16; 469 else if (type == GATT_INFO_TYPE_PAIR_128) 470 uuid_len = LEN_UUID_128; 471 472 while (len >= uuid_len + 2) 473 { 474 STREAM_TO_UINT16 (result.handle, p); 475 476 if (uuid_len > 0) 477 { 478 if (!gatt_parse_uuid_from_cmd(&result.type, uuid_len, &p)) 479 break; 480 } 481 else 482 memcpy (&result.type, &p_clcb->uuid, sizeof(tBT_UUID)); 483 484 len -= (uuid_len + 2); 485 486 if (p_clcb->p_reg->app_cb.p_disc_res_cb) 487 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result); 488 } 489 490 p_clcb->s_handle = (result.handle == 0) ? 0 :(result.handle + 1); 491 /* initiate another request */ 492 gatt_act_discovery(p_clcb) ; 493 } 494 /******************************************************************************* 495 ** 496 ** Function gatt_proc_disc_error_rsp 497 ** 498 ** Description This function process the read by type response and send another 499 ** request if needed. 500 ** 501 ** Returns void. 502 ** 503 *******************************************************************************/ 504 void gatt_proc_disc_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 opcode, 505 UINT16 handle, UINT8 reason) 506 { 507 tGATT_STATUS status = (tGATT_STATUS) reason; 508 509 GATT_TRACE_DEBUG2("gatt_proc_disc_error_rsp reason: %02x cmd_code %04x", reason, opcode); 510 511 switch (opcode) 512 { 513 case GATT_REQ_READ_BY_GRP_TYPE: 514 case GATT_REQ_FIND_TYPE_VALUE: 515 case GATT_REQ_READ_BY_TYPE: 516 case GATT_REQ_FIND_INFO: 517 if (reason == GATT_NOT_FOUND) 518 { 519 status = GATT_SUCCESS; 520 GATT_TRACE_DEBUG0("Discovery completed"); 521 } 522 break; 523 default: 524 GATT_TRACE_ERROR1("Incorrect discovery opcode %04x", opcode); 525 break; 526 } 527 528 gatt_end_operation(p_clcb, status, NULL); 529 } 530 531 /******************************************************************************* 532 ** 533 ** Function gatt_process_error_rsp 534 ** 535 ** Description This function is called to handle the error response 536 ** 537 ** 538 ** Returns void 539 ** 540 *******************************************************************************/ 541 void gatt_process_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, 542 UINT16 len, UINT8 *p_data) 543 { 544 UINT8 opcode, reason, * p= p_data; 545 UINT16 handle; 546 tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf; 547 548 GATT_TRACE_DEBUG0("gatt_process_error_rsp "); 549 STREAM_TO_UINT8(opcode, p); 550 STREAM_TO_UINT16(handle, p); 551 STREAM_TO_UINT8(reason, p); 552 553 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY) 554 { 555 gatt_proc_disc_error_rsp(p_tcb, p_clcb, opcode, handle, reason); 556 } 557 else 558 { 559 if ( (p_clcb->operation == GATTC_OPTYPE_WRITE) && 560 (p_clcb->op_subtype == GATT_WRITE) && 561 (opcode == GATT_REQ_PREPARE_WRITE) && 562 (p_attr) && 563 (handle == p_attr->handle) ) 564 { 565 p_clcb->status = reason; 566 gatt_send_queue_write_cancel(p_tcb, p_clcb, GATT_PREP_WRITE_CANCEL); 567 } 568 else if ((p_clcb->operation == GATTC_OPTYPE_READ) && 569 ((p_clcb->op_subtype == GATT_READ_CHAR_VALUE_HDL) || 570 (p_clcb->op_subtype == GATT_READ_BY_HANDLE)) && 571 (opcode == GATT_REQ_READ_BLOB) && 572 p_clcb->first_read_blob_after_read && 573 (reason == GATT_NOT_LONG)) 574 { 575 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf); 576 } 577 else 578 gatt_end_operation(p_clcb, reason, NULL); 579 } 580 } 581 /******************************************************************************* 582 ** 583 ** Function gatt_process_prep_write_rsp 584 ** 585 ** Description This function is called to handle the read response 586 ** 587 ** 588 ** Returns void 589 ** 590 *******************************************************************************/ 591 void gatt_process_prep_write_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, 592 UINT16 len, UINT8 *p_data) 593 { 594 tGATT_VALUE value = {0}; 595 UINT8 *p= p_data; 596 597 GATT_TRACE_ERROR2("value resp op_code = %s len = %d", gatt_dbg_op_name(op_code), len); 598 599 if (len < GATT_PREP_WRITE_RSP_MIN_LEN) 600 { 601 GATT_TRACE_ERROR0("illegal prepare write response length, discard"); 602 gatt_end_operation(p_clcb, GATT_INVALID_PDU, &value); 603 return; 604 } 605 606 STREAM_TO_UINT16 (value.handle, p); 607 STREAM_TO_UINT16 (value.offset, p); 608 609 value.len = len - 4; 610 611 memcpy (value.value, p, value.len); 612 613 if (p_clcb->op_subtype == GATT_WRITE_PREPARE) 614 { 615 p_clcb->status = GATT_SUCCESS; 616 /* application should verify handle offset 617 and value are matched or not */ 618 619 gatt_end_operation(p_clcb, p_clcb->status, &value); 620 } 621 else if (p_clcb->op_subtype == GATT_WRITE ) 622 { 623 if (!gatt_check_write_long_terminate(p_tcb, p_clcb, &value)) 624 gatt_send_prepare_write(p_tcb, p_clcb); 625 } 626 627 } 628 /******************************************************************************* 629 ** 630 ** Function gatt_process_notification 631 ** 632 ** Description This function is called to handle the handle value indication 633 ** or handle value notification. 634 ** 635 ** 636 ** Returns void 637 ** 638 *******************************************************************************/ 639 void gatt_process_notification(tGATT_TCB *p_tcb, UINT8 op_code, 640 UINT16 len, UINT8 *p_data) 641 { 642 tGATT_VALUE value = {0}; 643 tGATT_REG *p_reg; 644 UINT16 conn_id; 645 tGATT_STATUS encrypt_status; 646 UINT8 *p= p_data, i, 647 event = (op_code == GATT_HANDLE_VALUE_NOTIF) ? GATTC_OPTYPE_NOTIFICATION : GATTC_OPTYPE_INDICATION; 648 649 GATT_TRACE_DEBUG0("gatt_process_notification "); 650 651 if (len < GATT_NOTIFICATION_MIN_LEN) 652 { 653 GATT_TRACE_ERROR0("illegal notification PDU length, discard"); 654 return; 655 } 656 657 STREAM_TO_UINT16 (value.handle, p); 658 value.len = len - 2; 659 memcpy (value.value, p, value.len); 660 661 if (!GATT_HANDLE_IS_VALID(value.handle)) 662 { 663 /* illegal handle, send ack now */ 664 if (op_code == GATT_HANDLE_VALUE_IND) 665 attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL); 666 return; 667 } 668 669 if (event == GATTC_OPTYPE_INDICATION) 670 { 671 if (p_tcb->ind_count) 672 { 673 /* this is an error case that receiving an indication but we 674 still has an indication not being acked yet. 675 For now, just log the error reset the counter. 676 Later we need to disconnect the link unconditionally. 677 */ 678 GATT_TRACE_ERROR1("gatt_process_notification rcv Ind. but ind_count=%d (will reset ind_count)", p_tcb->ind_count); 679 } 680 p_tcb->ind_count = 0; 681 } 682 683 /* should notify all registered client with the handle value notificaion/indication 684 Note: need to do the indication count and start timer first then do callback 685 */ 686 687 for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) 688 { 689 if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb && (event == GATTC_OPTYPE_INDICATION)) 690 p_tcb->ind_count++; 691 } 692 693 if (event == GATTC_OPTYPE_INDICATION) 694 { 695 /* start a timer for app confirmation */ 696 if (p_tcb->ind_count > 0) 697 gatt_start_ind_ack_timer(p_tcb); 698 else /* no app to indicate, or invalid handle */ 699 attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL); 700 } 701 702 encrypt_status = gatt_get_link_encrypt_status(p_tcb); 703 for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) 704 { 705 if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb) 706 { 707 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if); 708 (*p_reg->app_cb.p_cmpl_cb) (conn_id, event, encrypt_status, (tGATT_CL_COMPLETE *)&value); 709 } 710 } 711 712 } 713 714 /******************************************************************************* 715 ** 716 ** Function gatt_process_read_by_type_rsp 717 ** 718 ** Description This function is called to handle the read by type response. 719 ** read by type can be used for discovery, or read by type or 720 ** read characteristic value. 721 ** 722 ** Returns void 723 ** 724 *******************************************************************************/ 725 void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, 726 UINT16 len, UINT8 *p_data) 727 { 728 tGATT_DISC_RES result; 729 tGATT_DISC_VALUE record_value; 730 UINT8 *p = p_data, value_len, handle_len = 2; 731 UINT16 handle = 0; 732 733 /* discovery procedure and no callback function registered */ 734 if (((!p_clcb->p_reg) || (!p_clcb->p_reg->app_cb.p_disc_res_cb)) && (p_clcb->operation == GATTC_OPTYPE_DISCOVERY)) 735 return; 736 737 if (len < GATT_READ_BY_TYPE_RSP_MIN_LEN) 738 { 739 GATT_TRACE_ERROR0("Illegal ReadByType/ReadByGroupType Response length, discard"); 740 gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL); 741 return; 742 } 743 744 STREAM_TO_UINT8(value_len, p); 745 746 if ((value_len > (p_tcb->payload_size - 2)) || (value_len > (len-1)) ) 747 { 748 /* this is an error case that server's response containing a value length which is larger than MTU-2 749 or value_len > message total length -1 */ 750 GATT_TRACE_ERROR4("gatt_process_read_by_type_rsp: Discard response op_code=%d vale_len=%d > (MTU-2=%d or msg_len-1=%d)", 751 op_code, value_len, (p_tcb->payload_size - 2), (len-1)); 752 gatt_end_operation(p_clcb, GATT_ERROR, NULL); 753 return; 754 } 755 756 if (op_code == GATT_RSP_READ_BY_GRP_TYPE) 757 handle_len = 4; 758 759 value_len -= handle_len; /* substract the handle pairs bytes */ 760 len -= 1; 761 762 while (len >= (handle_len + value_len)) 763 { 764 STREAM_TO_UINT16(handle, p); 765 766 if (!GATT_HANDLE_IS_VALID(handle)) 767 { 768 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL); 769 return; 770 } 771 772 memset(&result, 0, sizeof(tGATT_DISC_RES)); 773 memset(&record_value, 0, sizeof(tGATT_DISC_VALUE)); 774 775 result.handle = handle; 776 result.type.len = 2; 777 result.type.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype]; 778 779 /* discover all services */ 780 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && 781 p_clcb->op_subtype == GATT_DISC_SRVC_ALL && 782 op_code == GATT_RSP_READ_BY_GRP_TYPE) 783 { 784 STREAM_TO_UINT16(handle, p); 785 786 if (!GATT_HANDLE_IS_VALID(handle)) 787 { 788 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL); 789 return; 790 } 791 else 792 { 793 record_value.group_value.e_handle = handle; 794 if (!gatt_parse_uuid_from_cmd(&record_value.group_value.service_type, value_len, &p)) 795 { 796 GATT_TRACE_ERROR0("discover all service response parsing failure"); 797 break; 798 } 799 } 800 } 801 /* discover included service */ 802 else if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->op_subtype == GATT_DISC_INC_SRVC) 803 { 804 STREAM_TO_UINT16(record_value.incl_service.s_handle, p); 805 STREAM_TO_UINT16(record_value.incl_service.e_handle, p); 806 807 if (!GATT_HANDLE_IS_VALID(record_value.incl_service.s_handle) || 808 !GATT_HANDLE_IS_VALID(record_value.incl_service.e_handle)) 809 { 810 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL); 811 return; 812 } 813 814 if(value_len == 6) 815 { 816 STREAM_TO_UINT16(record_value.incl_service.service_type.uu.uuid16, p); 817 record_value.incl_service.service_type.len = LEN_UUID_16; 818 } 819 else if (value_len == 4) 820 { 821 p_clcb->s_handle = record_value.incl_service.s_handle; 822 p_clcb->read_uuid128.wait_for_read_rsp = TRUE; 823 p_clcb->read_uuid128.next_disc_start_hdl = handle + 1; 824 memcpy(&p_clcb->read_uuid128.result, &result, sizeof(result)); 825 memcpy(&p_clcb->read_uuid128.result.value, &record_value, sizeof (result.value)); 826 p_clcb->op_subtype |= 0x90; 827 gatt_act_read(p_clcb, 0); 828 return; 829 } 830 else 831 { 832 GATT_TRACE_ERROR1("gatt_process_read_by_type_rsp INCL_SRVC failed with invalid data value_len=%d", value_len); 833 gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p); 834 return; 835 } 836 } 837 /* read by type */ 838 else if (p_clcb->operation == GATTC_OPTYPE_READ && p_clcb->op_subtype == GATT_READ_BY_TYPE) 839 { 840 p_clcb->counter = len - 2; 841 p_clcb->s_handle = handle; 842 if ( p_clcb->counter == (p_clcb->p_tcb->payload_size -4)) 843 { 844 p_clcb->op_subtype = GATT_READ_BY_HANDLE; 845 if (!p_clcb->p_attr_buf) 846 p_clcb->p_attr_buf = (UINT8 *)GKI_getbuf(GATT_MAX_ATTR_LEN); 847 if (p_clcb->p_attr_buf && p_clcb->counter <= GATT_MAX_ATTR_LEN) 848 { 849 memcpy(p_clcb->p_attr_buf, p, p_clcb->counter); 850 gatt_act_read(p_clcb, p_clcb->counter); 851 } 852 else 853 gatt_end_operation(p_clcb, GATT_INTERNAL_ERROR, (void *)p); 854 } 855 else 856 { 857 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p); 858 } 859 return; 860 } 861 else /* discover characterisitic */ 862 { 863 STREAM_TO_UINT8 (record_value.dclr_value.char_prop, p); 864 STREAM_TO_UINT16(record_value.dclr_value.val_handle, p); 865 if (!GATT_HANDLE_IS_VALID(record_value.dclr_value.val_handle)) 866 { 867 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL); 868 return; 869 } 870 if (!gatt_parse_uuid_from_cmd(&record_value.dclr_value.char_uuid, (UINT16)(value_len - 3), &p)) 871 { 872 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL); 873 /* invalid format, and skip the result */ 874 return; 875 } 876 877 /* UUID not matching */ 878 if (!gatt_uuid_compare(record_value.dclr_value.char_uuid, p_clcb->uuid)) 879 { 880 len -= (value_len + 2); 881 continue; /* skip the result, and look for next one */ 882 } 883 else if (p_clcb->operation == GATTC_OPTYPE_READ) 884 /* UUID match for read characteristic value */ 885 { 886 /* only read the first matching UUID characteristic value, and 887 discard the rest results */ 888 p_clcb->s_handle = record_value.dclr_value.val_handle; 889 p_clcb->op_subtype |= 0x80; 890 gatt_act_read(p_clcb, 0); 891 return; 892 } 893 } 894 len -= (value_len + handle_len); 895 896 /* result is (handle, 16bits UUID) pairs */ 897 memcpy (&result.value, &record_value, sizeof (result.value)); 898 899 /* send callback if is discover procedure */ 900 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->p_reg->app_cb.p_disc_res_cb) 901 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result); 902 } 903 904 p_clcb->s_handle = (handle == 0) ? 0 : (handle + 1); 905 906 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY) 907 { 908 /* initiate another request */ 909 gatt_act_discovery(p_clcb) ; 910 } 911 else /* read characteristic value */ 912 { 913 gatt_act_read(p_clcb, 0); 914 } 915 } 916 917 /******************************************************************************* 918 ** 919 ** Function gatt_process_read_rsp 920 ** 921 ** Description This function is called to handle the read BLOB response 922 ** 923 ** 924 ** Returns void 925 ** 926 *******************************************************************************/ 927 void gatt_process_read_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, 928 UINT16 len, UINT8 *p_data) 929 { 930 UINT16 offset = p_clcb->counter; 931 UINT8 * p= p_data; 932 933 if (p_clcb->operation == GATTC_OPTYPE_READ) 934 { 935 if (p_clcb->op_subtype != GATT_READ_BY_HANDLE) 936 { 937 p_clcb->counter = len; 938 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p); 939 } 940 else 941 { 942 943 /* allocate GKI buffer holding up long attribute value */ 944 if (!p_clcb->p_attr_buf) 945 p_clcb->p_attr_buf = (UINT8 *)GKI_getbuf(GATT_MAX_ATTR_LEN); 946 947 /* copy attrobute value into cb buffer */ 948 if (p_clcb->p_attr_buf && offset < GATT_MAX_ATTR_LEN) 949 { 950 if ((len + offset) > GATT_MAX_ATTR_LEN) 951 len = GATT_MAX_ATTR_LEN - offset; 952 953 p_clcb->counter += len; 954 955 memcpy(p_clcb->p_attr_buf + offset, p, len); 956 957 /* send next request if needed */ 958 959 if (len == (p_tcb->payload_size - 1) && /* full packet for read or read blob rsp */ 960 len + offset < GATT_MAX_ATTR_LEN) 961 { 962 GATT_TRACE_DEBUG3("full pkt issue read blob for remianing bytes old offset=%d len=%d new offset=%d", 963 offset, len, p_clcb->counter); 964 gatt_act_read(p_clcb, p_clcb->counter); 965 } 966 else /* end of request, send callback */ 967 { 968 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf); 969 } 970 } 971 else /* exception, should not happen */ 972 { 973 GATT_TRACE_ERROR2("attr offset = %d p_attr_buf = %d ", offset, p_clcb->p_attr_buf); 974 gatt_end_operation(p_clcb, GATT_NO_RESOURCES, (void *)p_clcb->p_attr_buf); 975 } 976 } 977 } 978 else 979 { 980 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && 981 p_clcb->op_subtype == GATT_DISC_INC_SRVC && 982 p_clcb->read_uuid128.wait_for_read_rsp ) 983 { 984 p_clcb->s_handle = p_clcb->read_uuid128.next_disc_start_hdl; 985 p_clcb->read_uuid128.wait_for_read_rsp = FALSE; 986 if (len == LEN_UUID_128) 987 { 988 989 memcpy(p_clcb->read_uuid128.result.value.incl_service.service_type.uu.uuid128, p, len); 990 p_clcb->read_uuid128.result.value.incl_service.service_type.len = LEN_UUID_128; 991 if ( p_clcb->p_reg->app_cb.p_disc_res_cb) 992 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &p_clcb->read_uuid128.result); 993 gatt_act_discovery(p_clcb) ; 994 } 995 else 996 { 997 gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p); 998 } 999 } 1000 } 1001 1002 } 1003 1004 1005 /******************************************************************************* 1006 ** 1007 ** Function gatt_process_handle_rsp 1008 ** 1009 ** Description This function is called to handle the write response 1010 ** 1011 ** 1012 ** Returns void 1013 ** 1014 *******************************************************************************/ 1015 void gatt_process_handle_rsp(tGATT_CLCB *p_clcb) 1016 { 1017 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL); 1018 } 1019 /******************************************************************************* 1020 ** 1021 ** Function gatt_process_mtu_rsp 1022 ** 1023 ** Description This function is called to process the configure MTU response. 1024 ** 1025 ** 1026 ** Returns void 1027 ** 1028 *******************************************************************************/ 1029 void gatt_process_mtu_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data) 1030 { 1031 UINT16 mtu; 1032 tGATT_STATUS status = GATT_SUCCESS; 1033 1034 if (len < GATT_MTU_RSP_MIN_LEN) 1035 { 1036 GATT_TRACE_ERROR0("invalid MTU response PDU received, discard."); 1037 status = GATT_INVALID_PDU; 1038 } 1039 else 1040 { 1041 STREAM_TO_UINT16(mtu, p_data); 1042 1043 if (mtu < p_tcb->payload_size && mtu >= GATT_DEF_BLE_MTU_SIZE) 1044 p_tcb->payload_size = mtu; 1045 } 1046 1047 gatt_end_operation(p_clcb, status, NULL); 1048 } 1049 /******************************************************************************* 1050 ** 1051 ** Function gatt_cmd_to_rsp_code 1052 ** 1053 ** Description The function convert a ATT command op code into the corresponding 1054 ** response code assume no error occurs. 1055 ** 1056 ** Returns response code. 1057 ** 1058 *******************************************************************************/ 1059 UINT8 gatt_cmd_to_rsp_code (UINT8 cmd_code) 1060 { 1061 UINT8 rsp_code = 0; 1062 1063 if (cmd_code > 1 && cmd_code != GATT_CMD_WRITE) 1064 { 1065 rsp_code = cmd_code + 1; 1066 } 1067 return rsp_code; 1068 } 1069 /******************************************************************************* 1070 ** 1071 ** Function gatt_cl_send_next_cmd_inq 1072 ** 1073 ** Description Find next command in queue and sent to server 1074 ** 1075 ** Returns TRUE if command sent, otherwise FALSE. 1076 ** 1077 *******************************************************************************/ 1078 BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb) 1079 { 1080 tGATT_CMD_Q *p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req]; 1081 BOOLEAN sent = FALSE; 1082 UINT8 rsp_code; 1083 tGATT_CLCB *p_clcb = NULL; 1084 1085 while (!sent && 1086 p_tcb->pending_cl_req != p_tcb->next_slot_inq && 1087 p_cmd->to_send && p_cmd->p_cmd != NULL) 1088 { 1089 sent = attp_send_msg_to_L2CAP(p_tcb, p_cmd->p_cmd); 1090 1091 if (sent) 1092 { 1093 p_cmd->to_send = FALSE; 1094 p_cmd->p_cmd = NULL; 1095 1096 /* dequeue the request if is write command or sign write */ 1097 if (p_cmd->op_code != GATT_CMD_WRITE && p_cmd->op_code != GATT_SIGN_CMD_WRITE) 1098 { 1099 gatt_start_rsp_timer (p_tcb); 1100 } 1101 else 1102 { 1103 p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code); 1104 1105 /* if no ack needed, keep sending */ 1106 sent = FALSE; 1107 p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req]; 1108 /* send command complete callback here */ 1109 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL); 1110 } 1111 } 1112 else 1113 { 1114 GATT_TRACE_ERROR0("gatt_cl_send_next_cmd_inq: L2CAP sent error"); 1115 1116 memset(p_cmd, 0, sizeof(tGATT_CMD_Q)); 1117 p_tcb->pending_cl_req ++; 1118 p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req]; 1119 } 1120 1121 } 1122 return sent; 1123 } 1124 1125 /******************************************************************************* 1126 ** 1127 ** Function gatt_client_handle_server_rsp 1128 ** 1129 ** Description This function is called to handle the server response to 1130 ** client. 1131 ** 1132 ** 1133 ** Returns void 1134 ** 1135 *******************************************************************************/ 1136 void gatt_client_handle_server_rsp (tGATT_TCB *p_tcb, UINT8 op_code, 1137 UINT16 len, UINT8 *p_data) 1138 { 1139 tGATT_CLCB *p_clcb = NULL; 1140 UINT8 rsp_code; 1141 1142 if (op_code != GATT_HANDLE_VALUE_IND && op_code != GATT_HANDLE_VALUE_NOTIF) 1143 { 1144 p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code); 1145 1146 rsp_code = gatt_cmd_to_rsp_code(rsp_code); 1147 1148 if (p_clcb == NULL || (rsp_code != op_code && op_code != GATT_RSP_ERROR)) 1149 { 1150 GATT_TRACE_WARNING2 ("ATT - Ignore wrong response. Receives (%02x) \ 1151 Request(%02x) Ignored", op_code, rsp_code); 1152 1153 return; 1154 } 1155 else 1156 btu_stop_timer (&p_tcb->rsp_timer_ent); 1157 } 1158 /* the size of the message may not be bigger than the local max PDU size*/ 1159 /* The message has to be smaller than the agreed MTU, len does not count op_code */ 1160 if (len >= p_tcb->payload_size) 1161 { 1162 GATT_TRACE_ERROR2("invalid response/indicate pkt size: %d, PDU size: %d", len + 1, p_tcb->payload_size); 1163 if (op_code != GATT_HANDLE_VALUE_NOTIF && 1164 op_code != GATT_HANDLE_VALUE_IND) 1165 gatt_end_operation(p_clcb, GATT_ERROR, NULL); 1166 } 1167 else 1168 { 1169 switch (op_code) 1170 { 1171 case GATT_RSP_ERROR: 1172 gatt_process_error_rsp(p_tcb, p_clcb, op_code, len, p_data); 1173 break; 1174 1175 case GATT_RSP_MTU: /* 2 bytes mtu */ 1176 gatt_process_mtu_rsp(p_tcb, p_clcb, len ,p_data); 1177 break; 1178 1179 case GATT_RSP_FIND_INFO: 1180 gatt_process_read_info_rsp(p_tcb, p_clcb, op_code, len, p_data); 1181 break; 1182 1183 case GATT_RSP_READ_BY_TYPE: 1184 case GATT_RSP_READ_BY_GRP_TYPE: 1185 gatt_process_read_by_type_rsp(p_tcb, p_clcb, op_code, len, p_data); 1186 break; 1187 1188 case GATT_RSP_READ: 1189 case GATT_RSP_READ_BLOB: 1190 case GATT_RSP_READ_MULTI: 1191 gatt_process_read_rsp(p_tcb, p_clcb, op_code, len, p_data); 1192 break; 1193 1194 case GATT_RSP_FIND_TYPE_VALUE: /* disc service with UUID */ 1195 gatt_process_find_type_value_rsp(p_tcb, p_clcb, len, p_data); 1196 break; 1197 1198 case GATT_RSP_WRITE: 1199 gatt_process_handle_rsp(p_clcb); 1200 break; 1201 1202 case GATT_RSP_PREPARE_WRITE: 1203 gatt_process_prep_write_rsp(p_tcb, p_clcb, op_code, len, p_data); 1204 break; 1205 1206 case GATT_RSP_EXEC_WRITE: 1207 gatt_end_operation(p_clcb, p_clcb->status, NULL); 1208 break; 1209 1210 case GATT_HANDLE_VALUE_NOTIF: 1211 case GATT_HANDLE_VALUE_IND: 1212 gatt_process_notification(p_tcb, op_code, len, p_data); 1213 break; 1214 1215 default: 1216 GATT_TRACE_ERROR1("Unknown opcode = %d", op_code); 1217 break; 1218 } 1219 } 1220 1221 if (op_code != GATT_HANDLE_VALUE_IND && op_code != GATT_HANDLE_VALUE_NOTIF) 1222 { 1223 gatt_cl_send_next_cmd_inq(p_tcb); 1224 } 1225 1226 return; 1227 } 1228 1229 #endif /* BLE_INCLUDED */ 1230