gatt_cl.c revision b83a823466bf93f7d484f7c8d23513e0e7c1a5a8
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*********************************************************************************/ 47void gatt_send_prepare_write(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb); 48 49UINT8 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 59UINT16 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*******************************************************************************/ 79void 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*******************************************************************************/ 128void 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*******************************************************************************/ 216void 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*******************************************************************************/ 289void 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*******************************************************************************/ 311BOOLEAN 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*******************************************************************************/ 354void 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*******************************************************************************/ 405static void gatt_process_find_type_value_rsp (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*******************************************************************************/ 448static void gatt_process_read_info_rsp(tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data) 449{ 450 tGATT_DISC_RES result; 451 UINT8 *p = p_data, uuid_len = 0, type; 452 453 if (len < GATT_INFO_RSP_MIN_LEN) 454 { 455 GATT_TRACE_ERROR0("invalid Info Response PDU received, discard."); 456 gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL); 457 return; 458 } 459 /* unexpected response */ 460 if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_CHAR_DSCPT) 461 return; 462 463 STREAM_TO_UINT8(type, p); 464 len -= 1; 465 466 if (type == GATT_INFO_TYPE_PAIR_16) 467 uuid_len = LEN_UUID_16; 468 else if (type == GATT_INFO_TYPE_PAIR_128) 469 uuid_len = LEN_UUID_128; 470 471 while (len >= uuid_len + 2) 472 { 473 STREAM_TO_UINT16 (result.handle, p); 474 475 if (uuid_len > 0) 476 { 477 if (!gatt_parse_uuid_from_cmd(&result.type, uuid_len, &p)) 478 break; 479 } 480 else 481 memcpy (&result.type, &p_clcb->uuid, sizeof(tBT_UUID)); 482 483 len -= (uuid_len + 2); 484 485 if (p_clcb->p_reg->app_cb.p_disc_res_cb) 486 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result); 487 } 488 489 p_clcb->s_handle = (result.handle == 0) ? 0 :(result.handle + 1); 490 /* initiate another request */ 491 gatt_act_discovery(p_clcb) ; 492} 493/******************************************************************************* 494** 495** Function gatt_proc_disc_error_rsp 496** 497** Description This function process the read by type response and send another 498** request if needed. 499** 500** Returns void. 501** 502*******************************************************************************/ 503static void gatt_proc_disc_error_rsp(tGATT_CLCB *p_clcb, UINT8 opcode, UINT8 reason) 504{ 505 tGATT_STATUS status = (tGATT_STATUS) reason; 506 507 GATT_TRACE_DEBUG2("gatt_proc_disc_error_rsp reason: %02x cmd_code %04x", reason, opcode); 508 509 switch (opcode) 510 { 511 case GATT_REQ_READ_BY_GRP_TYPE: 512 case GATT_REQ_FIND_TYPE_VALUE: 513 case GATT_REQ_READ_BY_TYPE: 514 case GATT_REQ_FIND_INFO: 515 if (reason == GATT_NOT_FOUND) 516 { 517 status = GATT_SUCCESS; 518 GATT_TRACE_DEBUG0("Discovery completed"); 519 } 520 break; 521 default: 522 GATT_TRACE_ERROR1("Incorrect discovery opcode %04x", opcode); 523 break; 524 } 525 526 gatt_end_operation(p_clcb, status, NULL); 527} 528 529/******************************************************************************* 530** 531** Function gatt_process_error_rsp 532** 533** Description This function is called to handle the error response 534** 535** 536** Returns void 537** 538*******************************************************************************/ 539static void gatt_process_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 *p_data) 540{ 541 UINT8 opcode, reason, * p= p_data; 542 UINT16 handle; 543 tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf; 544 545 GATT_TRACE_DEBUG0("gatt_process_error_rsp "); 546 STREAM_TO_UINT8(opcode, p); 547 STREAM_TO_UINT16(handle, p); 548 STREAM_TO_UINT8(reason, p); 549 550 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY) 551 { 552 gatt_proc_disc_error_rsp(p_clcb, opcode, reason); 553 } 554 else 555 { 556 if ( (p_clcb->operation == GATTC_OPTYPE_WRITE) && 557 (p_clcb->op_subtype == GATT_WRITE) && 558 (opcode == GATT_REQ_PREPARE_WRITE) && 559 (p_attr) && 560 (handle == p_attr->handle) ) 561 { 562 p_clcb->status = reason; 563 gatt_send_queue_write_cancel(p_tcb, p_clcb, GATT_PREP_WRITE_CANCEL); 564 } 565 else if ((p_clcb->operation == GATTC_OPTYPE_READ) && 566 ((p_clcb->op_subtype == GATT_READ_CHAR_VALUE_HDL) || 567 (p_clcb->op_subtype == GATT_READ_BY_HANDLE)) && 568 (opcode == GATT_REQ_READ_BLOB) && 569 p_clcb->first_read_blob_after_read && 570 (reason == GATT_NOT_LONG)) 571 { 572 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf); 573 } 574 else 575 gatt_end_operation(p_clcb, reason, NULL); 576 } 577} 578/******************************************************************************* 579** 580** Function gatt_process_prep_write_rsp 581** 582** Description This function is called to handle the read response 583** 584** 585** Returns void 586** 587*******************************************************************************/ 588void gatt_process_prep_write_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, 589 UINT16 len, UINT8 *p_data) 590{ 591 tGATT_VALUE value = {0}; 592 UINT8 *p= p_data; 593 594 GATT_TRACE_ERROR2("value resp op_code = %s len = %d", gatt_dbg_op_name(op_code), len); 595 596 if (len < GATT_PREP_WRITE_RSP_MIN_LEN) 597 { 598 GATT_TRACE_ERROR0("illegal prepare write response length, discard"); 599 gatt_end_operation(p_clcb, GATT_INVALID_PDU, &value); 600 return; 601 } 602 603 STREAM_TO_UINT16 (value.handle, p); 604 STREAM_TO_UINT16 (value.offset, p); 605 606 value.len = len - 4; 607 608 memcpy (value.value, p, value.len); 609 610 if (p_clcb->op_subtype == GATT_WRITE_PREPARE) 611 { 612 p_clcb->status = GATT_SUCCESS; 613 /* application should verify handle offset 614 and value are matched or not */ 615 616 gatt_end_operation(p_clcb, p_clcb->status, &value); 617 } 618 else if (p_clcb->op_subtype == GATT_WRITE ) 619 { 620 if (!gatt_check_write_long_terminate(p_tcb, p_clcb, &value)) 621 gatt_send_prepare_write(p_tcb, p_clcb); 622 } 623 624} 625/******************************************************************************* 626** 627** Function gatt_process_notification 628** 629** Description This function is called to handle the handle value indication 630** or handle value notification. 631** 632** 633** Returns void 634** 635*******************************************************************************/ 636void gatt_process_notification(tGATT_TCB *p_tcb, UINT8 op_code, 637 UINT16 len, UINT8 *p_data) 638{ 639 tGATT_VALUE value = {0}; 640 tGATT_REG *p_reg; 641 UINT16 conn_id; 642 tGATT_STATUS encrypt_status; 643 UINT8 *p= p_data, i, 644 event = (op_code == GATT_HANDLE_VALUE_NOTIF) ? GATTC_OPTYPE_NOTIFICATION : GATTC_OPTYPE_INDICATION; 645 646 GATT_TRACE_DEBUG0("gatt_process_notification "); 647 648 if (len < GATT_NOTIFICATION_MIN_LEN) 649 { 650 GATT_TRACE_ERROR0("illegal notification PDU length, discard"); 651 return; 652 } 653 654 STREAM_TO_UINT16 (value.handle, p); 655 value.len = len - 2; 656 memcpy (value.value, p, value.len); 657 658 if (!GATT_HANDLE_IS_VALID(value.handle)) 659 { 660 /* illegal handle, send ack now */ 661 if (op_code == GATT_HANDLE_VALUE_IND) 662 attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL); 663 return; 664 } 665 666 if (event == GATTC_OPTYPE_INDICATION) 667 { 668 if (p_tcb->ind_count) 669 { 670 /* this is an error case that receiving an indication but we 671 still has an indication not being acked yet. 672 For now, just log the error reset the counter. 673 Later we need to disconnect the link unconditionally. 674 */ 675 GATT_TRACE_ERROR1("gatt_process_notification rcv Ind. but ind_count=%d (will reset ind_count)", p_tcb->ind_count); 676 } 677 p_tcb->ind_count = 0; 678 } 679 680 /* should notify all registered client with the handle value notificaion/indication 681 Note: need to do the indication count and start timer first then do callback 682 */ 683 684 for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) 685 { 686 if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb && (event == GATTC_OPTYPE_INDICATION)) 687 p_tcb->ind_count++; 688 } 689 690 if (event == GATTC_OPTYPE_INDICATION) 691 { 692 /* start a timer for app confirmation */ 693 if (p_tcb->ind_count > 0) 694 gatt_start_ind_ack_timer(p_tcb); 695 else /* no app to indicate, or invalid handle */ 696 attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL); 697 } 698 699 encrypt_status = gatt_get_link_encrypt_status(p_tcb); 700 for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) 701 { 702 if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb) 703 { 704 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if); 705 (*p_reg->app_cb.p_cmpl_cb) (conn_id, event, encrypt_status, (tGATT_CL_COMPLETE *)&value); 706 } 707 } 708 709} 710 711/******************************************************************************* 712** 713** Function gatt_process_read_by_type_rsp 714** 715** Description This function is called to handle the read by type response. 716** read by type can be used for discovery, or read by type or 717** read characteristic value. 718** 719** Returns void 720** 721*******************************************************************************/ 722void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, 723 UINT16 len, UINT8 *p_data) 724{ 725 tGATT_DISC_RES result; 726 tGATT_DISC_VALUE record_value; 727 UINT8 *p = p_data, value_len, handle_len = 2; 728 UINT16 handle = 0; 729 730 /* discovery procedure and no callback function registered */ 731 if (((!p_clcb->p_reg) || (!p_clcb->p_reg->app_cb.p_disc_res_cb)) && (p_clcb->operation == GATTC_OPTYPE_DISCOVERY)) 732 return; 733 734 if (len < GATT_READ_BY_TYPE_RSP_MIN_LEN) 735 { 736 GATT_TRACE_ERROR0("Illegal ReadByType/ReadByGroupType Response length, discard"); 737 gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL); 738 return; 739 } 740 741 STREAM_TO_UINT8(value_len, p); 742 743 if ((value_len > (p_tcb->payload_size - 2)) || (value_len > (len-1)) ) 744 { 745 /* this is an error case that server's response containing a value length which is larger than MTU-2 746 or value_len > message total length -1 */ 747 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)", 748 op_code, value_len, (p_tcb->payload_size - 2), (len-1)); 749 gatt_end_operation(p_clcb, GATT_ERROR, NULL); 750 return; 751 } 752 753 if (op_code == GATT_RSP_READ_BY_GRP_TYPE) 754 handle_len = 4; 755 756 value_len -= handle_len; /* substract the handle pairs bytes */ 757 len -= 1; 758 759 while (len >= (handle_len + value_len)) 760 { 761 STREAM_TO_UINT16(handle, p); 762 763 if (!GATT_HANDLE_IS_VALID(handle)) 764 { 765 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL); 766 return; 767 } 768 769 memset(&result, 0, sizeof(tGATT_DISC_RES)); 770 memset(&record_value, 0, sizeof(tGATT_DISC_VALUE)); 771 772 result.handle = handle; 773 result.type.len = 2; 774 result.type.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype]; 775 776 /* discover all services */ 777 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && 778 p_clcb->op_subtype == GATT_DISC_SRVC_ALL && 779 op_code == GATT_RSP_READ_BY_GRP_TYPE) 780 { 781 STREAM_TO_UINT16(handle, p); 782 783 if (!GATT_HANDLE_IS_VALID(handle)) 784 { 785 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL); 786 return; 787 } 788 else 789 { 790 record_value.group_value.e_handle = handle; 791 if (!gatt_parse_uuid_from_cmd(&record_value.group_value.service_type, value_len, &p)) 792 { 793 GATT_TRACE_ERROR0("discover all service response parsing failure"); 794 break; 795 } 796 } 797 } 798 /* discover included service */ 799 else if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->op_subtype == GATT_DISC_INC_SRVC) 800 { 801 STREAM_TO_UINT16(record_value.incl_service.s_handle, p); 802 STREAM_TO_UINT16(record_value.incl_service.e_handle, p); 803 804 if (!GATT_HANDLE_IS_VALID(record_value.incl_service.s_handle) || 805 !GATT_HANDLE_IS_VALID(record_value.incl_service.e_handle)) 806 { 807 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL); 808 return; 809 } 810 811 if(value_len == 6) 812 { 813 STREAM_TO_UINT16(record_value.incl_service.service_type.uu.uuid16, p); 814 record_value.incl_service.service_type.len = LEN_UUID_16; 815 } 816 else if (value_len == 4) 817 { 818 p_clcb->s_handle = record_value.incl_service.s_handle; 819 p_clcb->read_uuid128.wait_for_read_rsp = TRUE; 820 p_clcb->read_uuid128.next_disc_start_hdl = handle + 1; 821 memcpy(&p_clcb->read_uuid128.result, &result, sizeof(result)); 822 memcpy(&p_clcb->read_uuid128.result.value, &record_value, sizeof (result.value)); 823 p_clcb->op_subtype |= 0x90; 824 gatt_act_read(p_clcb, 0); 825 return; 826 } 827 else 828 { 829 GATT_TRACE_ERROR1("gatt_process_read_by_type_rsp INCL_SRVC failed with invalid data value_len=%d", value_len); 830 gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p); 831 return; 832 } 833 } 834 /* read by type */ 835 else if (p_clcb->operation == GATTC_OPTYPE_READ && p_clcb->op_subtype == GATT_READ_BY_TYPE) 836 { 837 p_clcb->counter = len - 2; 838 p_clcb->s_handle = handle; 839 if ( p_clcb->counter == (p_clcb->p_tcb->payload_size -4)) 840 { 841 p_clcb->op_subtype = GATT_READ_BY_HANDLE; 842 if (!p_clcb->p_attr_buf) 843 p_clcb->p_attr_buf = (UINT8 *)GKI_getbuf(GATT_MAX_ATTR_LEN); 844 if (p_clcb->p_attr_buf && p_clcb->counter <= GATT_MAX_ATTR_LEN) 845 { 846 memcpy(p_clcb->p_attr_buf, p, p_clcb->counter); 847 gatt_act_read(p_clcb, p_clcb->counter); 848 } 849 else 850 gatt_end_operation(p_clcb, GATT_INTERNAL_ERROR, (void *)p); 851 } 852 else 853 { 854 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p); 855 } 856 return; 857 } 858 else /* discover characterisitic */ 859 { 860 STREAM_TO_UINT8 (record_value.dclr_value.char_prop, p); 861 STREAM_TO_UINT16(record_value.dclr_value.val_handle, p); 862 if (!GATT_HANDLE_IS_VALID(record_value.dclr_value.val_handle)) 863 { 864 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL); 865 return; 866 } 867 if (!gatt_parse_uuid_from_cmd(&record_value.dclr_value.char_uuid, (UINT16)(value_len - 3), &p)) 868 { 869 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL); 870 /* invalid format, and skip the result */ 871 return; 872 } 873 874 /* UUID not matching */ 875 if (!gatt_uuid_compare(record_value.dclr_value.char_uuid, p_clcb->uuid)) 876 { 877 len -= (value_len + 2); 878 continue; /* skip the result, and look for next one */ 879 } 880 else if (p_clcb->operation == GATTC_OPTYPE_READ) 881 /* UUID match for read characteristic value */ 882 { 883 /* only read the first matching UUID characteristic value, and 884 discard the rest results */ 885 p_clcb->s_handle = record_value.dclr_value.val_handle; 886 p_clcb->op_subtype |= 0x80; 887 gatt_act_read(p_clcb, 0); 888 return; 889 } 890 } 891 len -= (value_len + handle_len); 892 893 /* result is (handle, 16bits UUID) pairs */ 894 memcpy (&result.value, &record_value, sizeof (result.value)); 895 896 /* send callback if is discover procedure */ 897 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->p_reg->app_cb.p_disc_res_cb) 898 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result); 899 } 900 901 p_clcb->s_handle = (handle == 0) ? 0 : (handle + 1); 902 903 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY) 904 { 905 /* initiate another request */ 906 gatt_act_discovery(p_clcb) ; 907 } 908 else /* read characteristic value */ 909 { 910 gatt_act_read(p_clcb, 0); 911 } 912} 913 914/******************************************************************************* 915** 916** Function gatt_process_read_rsp 917** 918** Description This function is called to handle the read BLOB response 919** 920** 921** Returns void 922** 923*******************************************************************************/ 924static void gatt_process_read_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, 925 UINT16 len, UINT8 *p_data) 926{ 927 UINT16 offset = p_clcb->counter; 928 UINT8 * p= p_data; 929 930 if (p_clcb->operation == GATTC_OPTYPE_READ) 931 { 932 if (p_clcb->op_subtype != GATT_READ_BY_HANDLE) 933 { 934 p_clcb->counter = len; 935 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p); 936 } 937 else 938 { 939 940 /* allocate GKI buffer holding up long attribute value */ 941 if (!p_clcb->p_attr_buf) 942 p_clcb->p_attr_buf = (UINT8 *)GKI_getbuf(GATT_MAX_ATTR_LEN); 943 944 /* copy attrobute value into cb buffer */ 945 if (p_clcb->p_attr_buf && offset < GATT_MAX_ATTR_LEN) 946 { 947 if ((len + offset) > GATT_MAX_ATTR_LEN) 948 len = GATT_MAX_ATTR_LEN - offset; 949 950 p_clcb->counter += len; 951 952 memcpy(p_clcb->p_attr_buf + offset, p, len); 953 954 /* send next request if needed */ 955 956 if (len == (p_tcb->payload_size - 1) && /* full packet for read or read blob rsp */ 957 len + offset < GATT_MAX_ATTR_LEN) 958 { 959 GATT_TRACE_DEBUG3("full pkt issue read blob for remianing bytes old offset=%d len=%d new offset=%d", 960 offset, len, p_clcb->counter); 961 gatt_act_read(p_clcb, p_clcb->counter); 962 } 963 else /* end of request, send callback */ 964 { 965 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf); 966 } 967 } 968 else /* exception, should not happen */ 969 { 970 GATT_TRACE_ERROR2("attr offset = %d p_attr_buf = %d ", offset, p_clcb->p_attr_buf); 971 gatt_end_operation(p_clcb, GATT_NO_RESOURCES, (void *)p_clcb->p_attr_buf); 972 } 973 } 974 } 975 else 976 { 977 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && 978 p_clcb->op_subtype == GATT_DISC_INC_SRVC && 979 p_clcb->read_uuid128.wait_for_read_rsp ) 980 { 981 p_clcb->s_handle = p_clcb->read_uuid128.next_disc_start_hdl; 982 p_clcb->read_uuid128.wait_for_read_rsp = FALSE; 983 if (len == LEN_UUID_128) 984 { 985 986 memcpy(p_clcb->read_uuid128.result.value.incl_service.service_type.uu.uuid128, p, len); 987 p_clcb->read_uuid128.result.value.incl_service.service_type.len = LEN_UUID_128; 988 if ( p_clcb->p_reg->app_cb.p_disc_res_cb) 989 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &p_clcb->read_uuid128.result); 990 gatt_act_discovery(p_clcb) ; 991 } 992 else 993 { 994 gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p); 995 } 996 } 997 } 998 999} 1000 1001 1002/******************************************************************************* 1003** 1004** Function gatt_process_handle_rsp 1005** 1006** Description This function is called to handle the write response 1007** 1008** 1009** Returns void 1010** 1011*******************************************************************************/ 1012void gatt_process_handle_rsp(tGATT_CLCB *p_clcb) 1013{ 1014 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL); 1015} 1016/******************************************************************************* 1017** 1018** Function gatt_process_mtu_rsp 1019** 1020** Description This function is called to process the configure MTU response. 1021** 1022** 1023** Returns void 1024** 1025*******************************************************************************/ 1026void gatt_process_mtu_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data) 1027{ 1028 UINT16 mtu; 1029 tGATT_STATUS status = GATT_SUCCESS; 1030 1031 if (len < GATT_MTU_RSP_MIN_LEN) 1032 { 1033 GATT_TRACE_ERROR0("invalid MTU response PDU received, discard."); 1034 status = GATT_INVALID_PDU; 1035 } 1036 else 1037 { 1038 STREAM_TO_UINT16(mtu, p_data); 1039 1040 if (mtu < p_tcb->payload_size && mtu >= GATT_DEF_BLE_MTU_SIZE) 1041 p_tcb->payload_size = mtu; 1042 } 1043 1044 gatt_end_operation(p_clcb, status, NULL); 1045} 1046/******************************************************************************* 1047** 1048** Function gatt_cmd_to_rsp_code 1049** 1050** Description The function convert a ATT command op code into the corresponding 1051** response code assume no error occurs. 1052** 1053** Returns response code. 1054** 1055*******************************************************************************/ 1056UINT8 gatt_cmd_to_rsp_code (UINT8 cmd_code) 1057{ 1058 UINT8 rsp_code = 0; 1059 1060 if (cmd_code > 1 && cmd_code != GATT_CMD_WRITE) 1061 { 1062 rsp_code = cmd_code + 1; 1063 } 1064 return rsp_code; 1065} 1066/******************************************************************************* 1067** 1068** Function gatt_cl_send_next_cmd_inq 1069** 1070** Description Find next command in queue and sent to server 1071** 1072** Returns TRUE if command sent, otherwise FALSE. 1073** 1074*******************************************************************************/ 1075BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb) 1076{ 1077 tGATT_CMD_Q *p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req]; 1078 BOOLEAN sent = FALSE; 1079 UINT8 rsp_code; 1080 tGATT_CLCB *p_clcb = NULL; 1081 1082 while (!sent && 1083 p_tcb->pending_cl_req != p_tcb->next_slot_inq && 1084 p_cmd->to_send && p_cmd->p_cmd != NULL) 1085 { 1086 sent = attp_send_msg_to_L2CAP(p_tcb, p_cmd->p_cmd); 1087 1088 if (sent) 1089 { 1090 p_cmd->to_send = FALSE; 1091 p_cmd->p_cmd = NULL; 1092 1093 /* dequeue the request if is write command or sign write */ 1094 if (p_cmd->op_code != GATT_CMD_WRITE && p_cmd->op_code != GATT_SIGN_CMD_WRITE) 1095 { 1096 gatt_start_rsp_timer (p_cmd->clcb_idx); 1097 } 1098 else 1099 { 1100 p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code); 1101 1102 /* if no ack needed, keep sending */ 1103 sent = FALSE; 1104 p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req]; 1105 /* send command complete callback here */ 1106 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL); 1107 } 1108 } 1109 else 1110 { 1111 GATT_TRACE_ERROR0("gatt_cl_send_next_cmd_inq: L2CAP sent error"); 1112 1113 memset(p_cmd, 0, sizeof(tGATT_CMD_Q)); 1114 p_tcb->pending_cl_req ++; 1115 p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req]; 1116 } 1117 1118 } 1119 return sent; 1120} 1121 1122/******************************************************************************* 1123** 1124** Function gatt_client_handle_server_rsp 1125** 1126** Description This function is called to handle the server response to 1127** client. 1128** 1129** 1130** Returns void 1131** 1132*******************************************************************************/ 1133void gatt_client_handle_server_rsp (tGATT_TCB *p_tcb, UINT8 op_code, 1134 UINT16 len, UINT8 *p_data) 1135{ 1136 tGATT_CLCB *p_clcb = NULL; 1137 UINT8 rsp_code; 1138 1139 if (op_code != GATT_HANDLE_VALUE_IND && op_code != GATT_HANDLE_VALUE_NOTIF) 1140 { 1141 p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code); 1142 1143 rsp_code = gatt_cmd_to_rsp_code(rsp_code); 1144 1145 if (p_clcb == NULL || (rsp_code != op_code && op_code != GATT_RSP_ERROR)) 1146 { 1147 GATT_TRACE_WARNING2 ("ATT - Ignore wrong response. Receives (%02x) \ 1148 Request(%02x) Ignored", op_code, rsp_code); 1149 1150 return; 1151 } 1152 else 1153 { 1154 btu_stop_timer (&p_clcb->rsp_timer_ent); 1155 p_clcb->retry_count = 0; 1156 } 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, 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_clcb, 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, 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_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