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