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