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