1 /****************************************************************************** 2 * 3 * Copyright (C) 2008-2014 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 ATT protocol functions 22 * 23 ******************************************************************************/ 24 25 #include "bt_target.h" 26 27 #include "gatt_int.h" 28 #include "l2c_api.h" 29 30 #define GATT_HDR_FIND_TYPE_VALUE_LEN 21 31 #define GATT_OP_CODE_SIZE 1 32 #define GATT_START_END_HANDLE_SIZE 4 33 34 using base::StringPrintf; 35 /********************************************************************** 36 * ATT protocl message building utility * 37 **********************************************************************/ 38 /******************************************************************************* 39 * 40 * Function attp_build_mtu_exec_cmd 41 * 42 * Description Build a exchange MTU request 43 * 44 * Returns None. 45 * 46 ******************************************************************************/ 47 BT_HDR* attp_build_mtu_cmd(uint8_t op_code, uint16_t rx_mtu) { 48 uint8_t* p; 49 BT_HDR* p_buf = 50 (BT_HDR*)osi_malloc(sizeof(BT_HDR) + GATT_HDR_SIZE + L2CAP_MIN_OFFSET); 51 52 p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET; 53 UINT8_TO_STREAM(p, op_code); 54 UINT16_TO_STREAM(p, rx_mtu); 55 56 p_buf->offset = L2CAP_MIN_OFFSET; 57 p_buf->len = GATT_HDR_SIZE; /* opcode + 2 bytes mtu */ 58 59 return p_buf; 60 } 61 /******************************************************************************* 62 * 63 * Function attp_build_exec_write_cmd 64 * 65 * Description Build a execute write request or response. 66 * 67 * Returns None. 68 * 69 ******************************************************************************/ 70 BT_HDR* attp_build_exec_write_cmd(uint8_t op_code, uint8_t flag) { 71 BT_HDR* p_buf = (BT_HDR*)osi_malloc(GATT_DATA_BUF_SIZE); 72 uint8_t* p; 73 74 p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET; 75 76 p_buf->offset = L2CAP_MIN_OFFSET; 77 p_buf->len = GATT_OP_CODE_SIZE; 78 79 UINT8_TO_STREAM(p, op_code); 80 81 if (op_code == GATT_REQ_EXEC_WRITE) { 82 flag &= GATT_PREP_WRITE_EXEC; 83 UINT8_TO_STREAM(p, flag); 84 p_buf->len += 1; 85 } 86 87 return p_buf; 88 } 89 90 /******************************************************************************* 91 * 92 * Function attp_build_err_cmd 93 * 94 * Description Build a exchange MTU request 95 * 96 * Returns None. 97 * 98 ******************************************************************************/ 99 BT_HDR* attp_build_err_cmd(uint8_t cmd_code, uint16_t err_handle, 100 uint8_t reason) { 101 uint8_t* p; 102 BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + L2CAP_MIN_OFFSET + 5); 103 104 p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET; 105 UINT8_TO_STREAM(p, GATT_RSP_ERROR); 106 UINT8_TO_STREAM(p, cmd_code); 107 UINT16_TO_STREAM(p, err_handle); 108 UINT8_TO_STREAM(p, reason); 109 110 p_buf->offset = L2CAP_MIN_OFFSET; 111 /* GATT_HDR_SIZE (1B ERR_RSP op code+ 2B handle) + 1B cmd_op_code + 1B status 112 */ 113 p_buf->len = GATT_HDR_SIZE + 1 + 1; 114 115 return p_buf; 116 } 117 /******************************************************************************* 118 * 119 * Function attp_build_browse_cmd 120 * 121 * Description Build a read information request or read by type request 122 * 123 * Returns None. 124 * 125 ******************************************************************************/ 126 BT_HDR* attp_build_browse_cmd(uint8_t op_code, uint16_t s_hdl, uint16_t e_hdl, 127 tBT_UUID uuid) { 128 const size_t payload_size = 129 (GATT_OP_CODE_SIZE) + (GATT_START_END_HANDLE_SIZE) + (LEN_UUID_128); 130 BT_HDR* p_buf = 131 (BT_HDR*)osi_malloc(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET); 132 133 uint8_t* p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET; 134 /* Describe the built message location and size */ 135 p_buf->offset = L2CAP_MIN_OFFSET; 136 p_buf->len = GATT_OP_CODE_SIZE + 4; 137 138 UINT8_TO_STREAM(p, op_code); 139 UINT16_TO_STREAM(p, s_hdl); 140 UINT16_TO_STREAM(p, e_hdl); 141 p_buf->len += gatt_build_uuid_to_stream(&p, uuid); 142 143 return p_buf; 144 } 145 146 /******************************************************************************* 147 * 148 * Function attp_build_read_handles_cmd 149 * 150 * Description Build a read by type and value request. 151 * 152 * Returns pointer to the command buffer. 153 * 154 ******************************************************************************/ 155 BT_HDR* attp_build_read_by_type_value_cmd(uint16_t payload_size, 156 tGATT_FIND_TYPE_VALUE* p_value_type) { 157 uint8_t* p; 158 uint16_t len = p_value_type->value_len; 159 BT_HDR* p_buf = 160 (BT_HDR*)osi_malloc(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET); 161 162 p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET; 163 p_buf->offset = L2CAP_MIN_OFFSET; 164 p_buf->len = 5; /* opcode + s_handle + e_handle */ 165 166 UINT8_TO_STREAM(p, GATT_REQ_FIND_TYPE_VALUE); 167 UINT16_TO_STREAM(p, p_value_type->s_handle); 168 UINT16_TO_STREAM(p, p_value_type->e_handle); 169 170 p_buf->len += gatt_build_uuid_to_stream(&p, p_value_type->uuid); 171 172 if (p_value_type->value_len + p_buf->len > payload_size) 173 len = payload_size - p_buf->len; 174 175 memcpy(p, p_value_type->value, len); 176 p_buf->len += len; 177 178 return p_buf; 179 } 180 181 /******************************************************************************* 182 * 183 * Function attp_build_read_multi_cmd 184 * 185 * Description Build a read multiple request 186 * 187 * Returns None. 188 * 189 ******************************************************************************/ 190 BT_HDR* attp_build_read_multi_cmd(uint16_t payload_size, uint16_t num_handle, 191 uint16_t* p_handle) { 192 uint8_t *p, i = 0; 193 BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + num_handle * 2 + 1 + 194 L2CAP_MIN_OFFSET); 195 196 p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET; 197 p_buf->offset = L2CAP_MIN_OFFSET; 198 p_buf->len = 1; 199 200 UINT8_TO_STREAM(p, GATT_REQ_READ_MULTI); 201 202 for (i = 0; i < num_handle && p_buf->len + 2 <= payload_size; i++) { 203 UINT16_TO_STREAM(p, *(p_handle + i)); 204 p_buf->len += 2; 205 } 206 207 return p_buf; 208 } 209 /******************************************************************************* 210 * 211 * Function attp_build_handle_cmd 212 * 213 * Description Build a read /read blob request 214 * 215 * Returns None. 216 * 217 ******************************************************************************/ 218 BT_HDR* attp_build_handle_cmd(uint8_t op_code, uint16_t handle, 219 uint16_t offset) { 220 uint8_t* p; 221 BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + 5 + L2CAP_MIN_OFFSET); 222 223 p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET; 224 p_buf->offset = L2CAP_MIN_OFFSET; 225 226 UINT8_TO_STREAM(p, op_code); 227 p_buf->len = 1; 228 229 UINT16_TO_STREAM(p, handle); 230 p_buf->len += 2; 231 232 if (op_code == GATT_REQ_READ_BLOB) { 233 UINT16_TO_STREAM(p, offset); 234 p_buf->len += 2; 235 } 236 237 return p_buf; 238 } 239 240 /******************************************************************************* 241 * 242 * Function attp_build_opcode_cmd 243 * 244 * Description Build a request/response with opcode only. 245 * 246 * Returns None. 247 * 248 ******************************************************************************/ 249 BT_HDR* attp_build_opcode_cmd(uint8_t op_code) { 250 uint8_t* p; 251 BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + 1 + L2CAP_MIN_OFFSET); 252 253 p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET; 254 p_buf->offset = L2CAP_MIN_OFFSET; 255 256 UINT8_TO_STREAM(p, op_code); 257 p_buf->len = 1; 258 259 return p_buf; 260 } 261 262 /******************************************************************************* 263 * 264 * Function attp_build_value_cmd 265 * 266 * Description Build a attribute value request 267 * 268 * Returns None. 269 * 270 ******************************************************************************/ 271 BT_HDR* attp_build_value_cmd(uint16_t payload_size, uint8_t op_code, 272 uint16_t handle, uint16_t offset, uint16_t len, 273 uint8_t* p_data) { 274 uint8_t *p, *pp, pair_len, *p_pair_len; 275 BT_HDR* p_buf = 276 (BT_HDR*)osi_malloc(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET); 277 278 p = pp = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET; 279 UINT8_TO_STREAM(p, op_code); 280 p_buf->offset = L2CAP_MIN_OFFSET; 281 p_buf->len = 1; 282 283 if (op_code == GATT_RSP_READ_BY_TYPE) { 284 p_pair_len = p; 285 pair_len = len + 2; 286 UINT8_TO_STREAM(p, pair_len); 287 p_buf->len += 1; 288 } 289 if (op_code != GATT_RSP_READ_BLOB && op_code != GATT_RSP_READ) { 290 UINT16_TO_STREAM(p, handle); 291 p_buf->len += 2; 292 } 293 294 if (op_code == GATT_REQ_PREPARE_WRITE || op_code == GATT_RSP_PREPARE_WRITE) { 295 UINT16_TO_STREAM(p, offset); 296 p_buf->len += 2; 297 } 298 299 if (len > 0 && p_data != NULL) { 300 /* ensure data not exceed MTU size */ 301 if (payload_size - p_buf->len < len) { 302 len = payload_size - p_buf->len; 303 /* update handle value pair length */ 304 if (op_code == GATT_RSP_READ_BY_TYPE) *p_pair_len = (len + 2); 305 306 LOG(WARNING) << StringPrintf( 307 "attribute value too long, to be truncated to %d", len); 308 } 309 310 ARRAY_TO_STREAM(p, p_data, len); 311 p_buf->len += len; 312 } 313 314 return p_buf; 315 } 316 317 /******************************************************************************* 318 * 319 * Function attp_send_msg_to_l2cap 320 * 321 * Description Send message to L2CAP. 322 * 323 ******************************************************************************/ 324 tGATT_STATUS attp_send_msg_to_l2cap(tGATT_TCB& tcb, BT_HDR* p_toL2CAP) { 325 uint16_t l2cap_ret; 326 327 if (tcb.att_lcid == L2CAP_ATT_CID) 328 l2cap_ret = L2CA_SendFixedChnlData(L2CAP_ATT_CID, tcb.peer_bda, p_toL2CAP); 329 else 330 l2cap_ret = (uint16_t)L2CA_DataWrite(tcb.att_lcid, p_toL2CAP); 331 332 if (l2cap_ret == L2CAP_DW_FAILED) { 333 LOG(ERROR) << StringPrintf( 334 "ATT failed to pass msg:0x%0x to L2CAP", 335 *((uint8_t*)(p_toL2CAP + 1) + p_toL2CAP->offset)); 336 return GATT_INTERNAL_ERROR; 337 } else if (l2cap_ret == L2CAP_DW_CONGESTED) { 338 VLOG(1) << StringPrintf("ATT congested, message accepted"); 339 return GATT_CONGESTED; 340 } 341 return GATT_SUCCESS; 342 } 343 344 /** Build ATT Server PDUs */ 345 BT_HDR* attp_build_sr_msg(tGATT_TCB& tcb, uint8_t op_code, 346 tGATT_SR_MSG* p_msg) { 347 uint16_t offset = 0; 348 349 switch (op_code) { 350 case GATT_RSP_READ_BLOB: 351 case GATT_RSP_PREPARE_WRITE: 352 VLOG(1) << StringPrintf( 353 "ATT_RSP_READ_BLOB/GATT_RSP_PREPARE_WRITE: len = %d offset = %d", 354 p_msg->attr_value.len, p_msg->attr_value.offset); 355 offset = p_msg->attr_value.offset; 356 /* Coverity: [FALSE-POSITIVE error] intended fall through */ 357 /* Missing break statement between cases in switch statement */ 358 /* fall through */ 359 case GATT_RSP_READ_BY_TYPE: 360 case GATT_RSP_READ: 361 case GATT_HANDLE_VALUE_NOTIF: 362 case GATT_HANDLE_VALUE_IND: 363 return attp_build_value_cmd( 364 tcb.payload_size, op_code, p_msg->attr_value.handle, offset, 365 p_msg->attr_value.len, p_msg->attr_value.value); 366 367 case GATT_RSP_WRITE: 368 return attp_build_opcode_cmd(op_code); 369 370 case GATT_RSP_ERROR: 371 return attp_build_err_cmd(p_msg->error.cmd_code, p_msg->error.handle, 372 p_msg->error.reason); 373 374 case GATT_RSP_EXEC_WRITE: 375 return attp_build_exec_write_cmd(op_code, 0); 376 377 case GATT_RSP_MTU: 378 return attp_build_mtu_cmd(op_code, p_msg->mtu); 379 380 default: 381 LOG(FATAL) << "attp_build_sr_msg: unknown op code = " << +op_code; 382 return nullptr; 383 } 384 } 385 386 /******************************************************************************* 387 * 388 * Function attp_send_sr_msg 389 * 390 * Description This function sends the server response or indication 391 * message to client. 392 * 393 * Parameter p_tcb: pointer to the connecton control block. 394 * p_msg: pointer to message parameters structure. 395 * 396 * Returns GATT_SUCCESS if sucessfully sent; otherwise error code. 397 * 398 * 399 ******************************************************************************/ 400 tGATT_STATUS attp_send_sr_msg(tGATT_TCB& tcb, BT_HDR* p_msg) { 401 if (p_msg == NULL) return GATT_NO_RESOURCES; 402 403 p_msg->offset = L2CAP_MIN_OFFSET; 404 return attp_send_msg_to_l2cap(tcb, p_msg); 405 } 406 407 /******************************************************************************* 408 * 409 * Function attp_cl_send_cmd 410 * 411 * Description Send a ATT command or enqueue it. 412 * 413 * Returns GATT_SUCCESS if command sent 414 * GATT_CONGESTED if command sent but channel congested 415 * GATT_CMD_STARTED if command queue up in GATT 416 * GATT_ERROR if command sending failure 417 * 418 ******************************************************************************/ 419 tGATT_STATUS attp_cl_send_cmd(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, 420 uint8_t cmd_code, BT_HDR* p_cmd) { 421 cmd_code &= ~GATT_AUTH_SIGN_MASK; 422 423 if (!tcb.cl_cmd_q.empty() && cmd_code != GATT_HANDLE_VALUE_CONF) { 424 gatt_cmd_enq(tcb, p_clcb, true, cmd_code, p_cmd); 425 return GATT_CMD_STARTED; 426 } 427 428 /* no pending request or value confirmation */ 429 tGATT_STATUS att_ret = attp_send_msg_to_l2cap(tcb, p_cmd); 430 if (att_ret != GATT_CONGESTED && att_ret != GATT_SUCCESS) { 431 return GATT_INTERNAL_ERROR; 432 } 433 434 /* do not enq cmd if handle value confirmation or set request */ 435 if (cmd_code == GATT_HANDLE_VALUE_CONF || cmd_code == GATT_CMD_WRITE) { 436 return att_ret; 437 } 438 439 gatt_start_rsp_timer(p_clcb); 440 gatt_cmd_enq(tcb, p_clcb, false, cmd_code, NULL); 441 return att_ret; 442 } 443 444 /******************************************************************************* 445 * 446 * Function attp_send_cl_msg 447 * 448 * Description This function sends the client request or confirmation 449 * message to server. 450 * 451 * Parameter p_tcb: pointer to the connectino control block. 452 * p_clcb: clcb 453 * op_code: message op code. 454 * p_msg: pointer to message parameters structure. 455 * 456 * Returns GATT_SUCCESS if sucessfully sent; otherwise error code. 457 * 458 * 459 ******************************************************************************/ 460 tGATT_STATUS attp_send_cl_msg(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, 461 uint8_t op_code, tGATT_CL_MSG* p_msg) { 462 BT_HDR* p_cmd = NULL; 463 uint16_t offset = 0, handle; 464 switch (op_code) { 465 case GATT_REQ_MTU: 466 if (p_msg->mtu > GATT_MAX_MTU_SIZE) return GATT_ILLEGAL_PARAMETER; 467 468 tcb.payload_size = p_msg->mtu; 469 p_cmd = attp_build_mtu_cmd(GATT_REQ_MTU, p_msg->mtu); 470 break; 471 472 case GATT_REQ_FIND_INFO: 473 case GATT_REQ_READ_BY_TYPE: 474 case GATT_REQ_READ_BY_GRP_TYPE: 475 if (!GATT_HANDLE_IS_VALID(p_msg->browse.s_handle) || 476 !GATT_HANDLE_IS_VALID(p_msg->browse.e_handle) || 477 p_msg->browse.s_handle > p_msg->browse.e_handle) 478 return GATT_ILLEGAL_PARAMETER; 479 480 p_cmd = attp_build_browse_cmd(op_code, p_msg->browse.s_handle, 481 p_msg->browse.e_handle, p_msg->browse.uuid); 482 break; 483 484 case GATT_REQ_READ_BLOB: 485 offset = p_msg->read_blob.offset; 486 /* fall through */ 487 case GATT_REQ_READ: 488 handle = 489 (op_code == GATT_REQ_READ) ? p_msg->handle : p_msg->read_blob.handle; 490 /* handle checking */ 491 if (!GATT_HANDLE_IS_VALID(handle)) return GATT_ILLEGAL_PARAMETER; 492 493 p_cmd = attp_build_handle_cmd(op_code, handle, offset); 494 break; 495 496 case GATT_HANDLE_VALUE_CONF: 497 p_cmd = attp_build_opcode_cmd(op_code); 498 break; 499 500 case GATT_REQ_PREPARE_WRITE: 501 offset = p_msg->attr_value.offset; 502 /* fall through */ 503 case GATT_REQ_WRITE: 504 case GATT_CMD_WRITE: 505 case GATT_SIGN_CMD_WRITE: 506 if (!GATT_HANDLE_IS_VALID(p_msg->attr_value.handle)) 507 return GATT_ILLEGAL_PARAMETER; 508 509 p_cmd = attp_build_value_cmd( 510 tcb.payload_size, op_code, p_msg->attr_value.handle, offset, 511 p_msg->attr_value.len, p_msg->attr_value.value); 512 break; 513 514 case GATT_REQ_EXEC_WRITE: 515 p_cmd = attp_build_exec_write_cmd(op_code, p_msg->exec_write); 516 break; 517 518 case GATT_REQ_FIND_TYPE_VALUE: 519 p_cmd = attp_build_read_by_type_value_cmd(tcb.payload_size, 520 &p_msg->find_type_value); 521 break; 522 523 case GATT_REQ_READ_MULTI: 524 p_cmd = attp_build_read_multi_cmd(tcb.payload_size, 525 p_msg->read_multi.num_handles, 526 p_msg->read_multi.handles); 527 break; 528 529 default: 530 break; 531 } 532 533 if (p_cmd == NULL) return GATT_NO_RESOURCES; 534 535 return attp_cl_send_cmd(tcb, p_clcb, op_code, p_cmd); 536 } 537