1 /****************************************************************************** 2 * 3 * Copyright (C) 2010-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 the LLCP utilities 22 * 23 ******************************************************************************/ 24 25 #include <string.h> 26 27 #include <android-base/stringprintf.h> 28 #include <base/logging.h> 29 30 #include "bt_types.h" 31 #include "gki.h" 32 #include "llcp_defs.h" 33 #include "llcp_int.h" 34 #include "nfc_int.h" 35 36 using android::base::StringPrintf; 37 38 extern bool nfc_debug_enabled; 39 40 /******************************************************************************* 41 ** 42 ** Function llcp_util_parse_link_params 43 ** 44 ** Description Parse LLCP Link parameters 45 ** 46 ** Returns TRUE if success 47 ** 48 *******************************************************************************/ 49 bool llcp_util_parse_link_params(uint16_t length, uint8_t* p_bytes) { 50 uint8_t param_type, param_len, *p = p_bytes; 51 52 while (length) { 53 BE_STREAM_TO_UINT8(param_type, p); 54 length--; 55 56 switch (param_type) { 57 case LLCP_VERSION_TYPE: 58 BE_STREAM_TO_UINT8(param_len, p); 59 BE_STREAM_TO_UINT8(llcp_cb.lcb.peer_version, p); 60 DLOG_IF(INFO, nfc_debug_enabled) 61 << StringPrintf("Peer Version - 0x%02X", llcp_cb.lcb.peer_version); 62 break; 63 64 case LLCP_MIUX_TYPE: 65 BE_STREAM_TO_UINT8(param_len, p); 66 BE_STREAM_TO_UINT16(llcp_cb.lcb.peer_miu, p); 67 llcp_cb.lcb.peer_miu &= LLCP_MIUX_MASK; 68 llcp_cb.lcb.peer_miu += LLCP_DEFAULT_MIU; 69 DLOG_IF(INFO, nfc_debug_enabled) 70 << StringPrintf("Peer MIU - %d bytes", llcp_cb.lcb.peer_miu); 71 break; 72 73 case LLCP_WKS_TYPE: 74 BE_STREAM_TO_UINT8(param_len, p); 75 BE_STREAM_TO_UINT16(llcp_cb.lcb.peer_wks, p); 76 DLOG_IF(INFO, nfc_debug_enabled) 77 << StringPrintf("Peer WKS - 0x%04X", llcp_cb.lcb.peer_wks); 78 break; 79 80 case LLCP_LTO_TYPE: 81 BE_STREAM_TO_UINT8(param_len, p); 82 BE_STREAM_TO_UINT8(llcp_cb.lcb.peer_lto, p); 83 llcp_cb.lcb.peer_lto *= LLCP_LTO_UNIT; /* 10ms unit */ 84 DLOG_IF(INFO, nfc_debug_enabled) 85 << StringPrintf("Peer LTO - %d ms", llcp_cb.lcb.peer_lto); 86 break; 87 88 case LLCP_OPT_TYPE: 89 BE_STREAM_TO_UINT8(param_len, p); 90 BE_STREAM_TO_UINT8(llcp_cb.lcb.peer_opt, p); 91 DLOG_IF(INFO, nfc_debug_enabled) 92 << StringPrintf("Peer OPT - 0x%02X", llcp_cb.lcb.peer_opt); 93 break; 94 95 default: 96 LOG(ERROR) << StringPrintf("Unexpected type 0x%x", param_type); 97 BE_STREAM_TO_UINT8(param_len, p); 98 p += param_len; 99 break; 100 } 101 102 if (length >= param_len + 1) 103 length -= param_len + 1; 104 else { 105 LOG(ERROR) << StringPrintf("Bad LTV's"); 106 return false; 107 } 108 } 109 return true; 110 } 111 112 /******************************************************************************* 113 ** 114 ** Function llcp_util_adjust_ll_congestion 115 ** 116 ** Description adjust tx/rx congestion thresholds on logical link 117 ** 118 ** Returns void 119 ** 120 *******************************************************************************/ 121 void llcp_util_adjust_ll_congestion(void) { 122 /* buffer quota is allocated equally for each logical data link */ 123 if (llcp_cb.num_logical_data_link) { 124 llcp_cb.ll_tx_congest_start = 125 llcp_cb.max_num_ll_tx_buff / llcp_cb.num_logical_data_link; 126 llcp_cb.ll_rx_congest_start = 127 llcp_cb.max_num_ll_rx_buff / llcp_cb.num_logical_data_link; 128 } else { 129 llcp_cb.ll_tx_congest_start = llcp_cb.max_num_ll_tx_buff; 130 llcp_cb.ll_rx_congest_start = llcp_cb.max_num_ll_rx_buff; 131 } 132 133 /* at least one for each logical data link */ 134 if (llcp_cb.ll_tx_congest_start == 0) { 135 llcp_cb.ll_tx_congest_start = 1; 136 } 137 if (llcp_cb.ll_rx_congest_start == 0) { 138 llcp_cb.ll_rx_congest_start = 1; 139 } 140 141 if (llcp_cb.ll_tx_congest_start > 1) { 142 llcp_cb.ll_tx_congest_end = 1; 143 } else { 144 llcp_cb.ll_tx_congest_end = 0; 145 } 146 147 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 148 "num_logical_data_link=%d, ll_tx_congest_start=%d, ll_tx_congest_end=%d, " 149 "ll_rx_congest_start=%d", 150 llcp_cb.num_logical_data_link, llcp_cb.ll_tx_congest_start, 151 llcp_cb.ll_tx_congest_end, llcp_cb.ll_rx_congest_start); 152 } 153 154 /******************************************************************************* 155 ** 156 ** Function llcp_util_adjust_dl_rx_congestion 157 ** 158 ** Description adjust rx congestion thresholds on data link 159 ** 160 ** Returns void 161 ** 162 *******************************************************************************/ 163 void llcp_util_adjust_dl_rx_congestion(void) { 164 uint8_t idx, rx_congest_start; 165 166 if (llcp_cb.num_data_link_connection) { 167 rx_congest_start = llcp_cb.num_rx_buff / llcp_cb.num_data_link_connection; 168 169 for (idx = 0; idx < LLCP_MAX_DATA_LINK; idx++) { 170 if (llcp_cb.dlcb[idx].state == LLCP_DLC_STATE_CONNECTED) { 171 if (rx_congest_start > llcp_cb.dlcb[idx].local_rw) { 172 /* 173 ** set rx congestion threshold LLCP_DL_MIN_RX_CONGEST at 174 ** least so, we don't need to flow off too often. 175 */ 176 if (llcp_cb.dlcb[idx].local_rw + 1 > LLCP_DL_MIN_RX_CONGEST) 177 llcp_cb.dlcb[idx].rx_congest_threshold = 178 llcp_cb.dlcb[idx].local_rw + 1; 179 else 180 llcp_cb.dlcb[idx].rx_congest_threshold = LLCP_DL_MIN_RX_CONGEST; 181 } else { 182 llcp_cb.dlcb[idx].rx_congest_threshold = LLCP_DL_MIN_RX_CONGEST; 183 } 184 185 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 186 "DLC[%d], local_rw=%d, rx_congest_threshold=%d", idx, 187 llcp_cb.dlcb[idx].local_rw, llcp_cb.dlcb[idx].rx_congest_threshold); 188 } 189 } 190 } 191 } 192 193 /******************************************************************************* 194 ** 195 ** Function llcp_util_check_rx_congested_status 196 ** 197 ** Description Update rx congested status 198 ** 199 ** Returns void 200 ** 201 *******************************************************************************/ 202 void llcp_util_check_rx_congested_status(void) { 203 uint8_t idx; 204 205 if (llcp_cb.overall_rx_congested) { 206 /* check if rx congestion clear */ 207 if (llcp_cb.total_rx_ui_pdu + llcp_cb.total_rx_i_pdu <= 208 llcp_cb.overall_rx_congest_end) { 209 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 210 "rx link is uncongested, " 211 "%d+%d <= %d", 212 llcp_cb.total_rx_ui_pdu, llcp_cb.total_rx_i_pdu, 213 llcp_cb.overall_rx_congest_end); 214 215 llcp_cb.overall_rx_congested = false; 216 217 for (idx = 0; idx < LLCP_MAX_DATA_LINK; idx++) { 218 /* set flag to clear local busy status on data link connections */ 219 if ((llcp_cb.dlcb[idx].state == LLCP_DLC_STATE_CONNECTED) && 220 (llcp_cb.dlcb[idx].is_rx_congested == false)) { 221 llcp_cb.dlcb[idx].flags |= LLCP_DATA_LINK_FLAG_PENDING_RR_RNR; 222 } 223 } 224 } 225 } else { 226 /* check if rx link is congested */ 227 if (llcp_cb.total_rx_ui_pdu + llcp_cb.total_rx_i_pdu >= 228 llcp_cb.overall_rx_congest_start) { 229 LOG(WARNING) << StringPrintf( 230 "rx link is congested, %d+%d " 231 ">= %d", 232 llcp_cb.total_rx_ui_pdu, llcp_cb.total_rx_i_pdu, 233 llcp_cb.overall_rx_congest_start); 234 235 llcp_cb.overall_rx_congested = true; 236 237 /* rx link congestion is started, send RNR to remote end point */ 238 for (idx = 0; idx < LLCP_MAX_DATA_LINK; idx++) { 239 if ((llcp_cb.dlcb[idx].state == LLCP_DLC_STATE_CONNECTED) && 240 (llcp_cb.dlcb[idx].is_rx_congested == false)) { 241 llcp_cb.dlcb[idx].flags |= LLCP_DATA_LINK_FLAG_PENDING_RR_RNR; 242 } 243 } 244 } 245 } 246 } 247 248 /******************************************************************************* 249 ** 250 ** Function llcp_util_send_ui 251 ** 252 ** Description Send UI PDU 253 ** 254 ** Returns tLLCP_STATUS 255 ** 256 *******************************************************************************/ 257 tLLCP_STATUS llcp_util_send_ui(uint8_t ssap, uint8_t dsap, 258 tLLCP_APP_CB* p_app_cb, NFC_HDR* p_msg) { 259 uint8_t* p; 260 tLLCP_STATUS status = LLCP_STATUS_SUCCESS; 261 262 p_msg->offset -= LLCP_PDU_HEADER_SIZE; 263 p_msg->len += LLCP_PDU_HEADER_SIZE; 264 265 p = (uint8_t*)(p_msg + 1) + p_msg->offset; 266 UINT16_TO_BE_STREAM(p, LLCP_GET_PDU_HEADER(dsap, LLCP_PDU_UI_TYPE, ssap)); 267 268 GKI_enqueue(&p_app_cb->ui_xmit_q, p_msg); 269 llcp_cb.total_tx_ui_pdu++; 270 271 llcp_link_check_send_data(); 272 273 if ((p_app_cb->is_ui_tx_congested) || 274 (p_app_cb->ui_xmit_q.count >= llcp_cb.ll_tx_congest_start) || 275 (llcp_cb.overall_tx_congested) || 276 (llcp_cb.total_tx_ui_pdu >= llcp_cb.max_num_ll_tx_buff)) { 277 /* set congested here so overall congestion check routine will not report 278 * event again, */ 279 /* or notify uncongestion later */ 280 p_app_cb->is_ui_tx_congested = true; 281 282 LOG(WARNING) << StringPrintf( 283 "Logical link (SAP=0x%X) congested: ui_xmit_q.count=%d", ssap, 284 p_app_cb->ui_xmit_q.count); 285 286 status = LLCP_STATUS_CONGESTED; 287 } 288 289 return status; 290 } 291 292 /******************************************************************************* 293 ** 294 ** Function llcp_util_send_disc 295 ** 296 ** Description Send DISC PDU 297 ** 298 ** Returns void 299 ** 300 *******************************************************************************/ 301 void llcp_util_send_disc(uint8_t dsap, uint8_t ssap) { 302 NFC_HDR* p_msg; 303 uint8_t* p; 304 305 p_msg = (NFC_HDR*)GKI_getpoolbuf(LLCP_POOL_ID); 306 307 if (p_msg) { 308 p_msg->len = LLCP_PDU_DISC_SIZE; 309 p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 310 311 p = (uint8_t*)(p_msg + 1) + p_msg->offset; 312 UINT16_TO_BE_STREAM(p, LLCP_GET_PDU_HEADER(dsap, LLCP_PDU_DISC_TYPE, ssap)); 313 314 GKI_enqueue(&llcp_cb.lcb.sig_xmit_q, p_msg); 315 llcp_link_check_send_data(); 316 } 317 } 318 319 /******************************************************************************* 320 ** 321 ** Function llcp_util_allocate_data_link 322 ** 323 ** Description Allocate tLLCP_DLCB for data link connection 324 ** 325 ** Returns tLLCP_DLCB * 326 ** 327 ******************************************************************************/ 328 tLLCP_DLCB* llcp_util_allocate_data_link(uint8_t reg_sap, uint8_t remote_sap) { 329 tLLCP_DLCB* p_dlcb = NULL; 330 int idx; 331 332 DLOG_IF(INFO, nfc_debug_enabled) 333 << StringPrintf("reg_sap = 0x%x, remote_sap = 0x%x", reg_sap, remote_sap); 334 335 for (idx = 0; idx < LLCP_MAX_DATA_LINK; idx++) { 336 if (llcp_cb.dlcb[idx].state == LLCP_DLC_STATE_IDLE) { 337 p_dlcb = &(llcp_cb.dlcb[idx]); 338 339 memset(p_dlcb, 0, sizeof(tLLCP_DLCB)); 340 break; 341 } 342 } 343 344 if (!p_dlcb) { 345 LOG(ERROR) << StringPrintf("Out of DLCB"); 346 } else { 347 p_dlcb->p_app_cb = llcp_util_get_app_cb(reg_sap); 348 p_dlcb->local_sap = reg_sap; 349 p_dlcb->remote_sap = remote_sap; 350 p_dlcb->timer.param = (uintptr_t)p_dlcb; 351 352 /* this is for inactivity timer and congestion control. */ 353 llcp_cb.num_data_link_connection++; 354 355 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 356 "local_sap = 0x%x, remote_sap = 0x%x, " 357 "num_data_link_connection = %d", 358 p_dlcb->local_sap, p_dlcb->remote_sap, 359 llcp_cb.num_data_link_connection); 360 } 361 return p_dlcb; 362 } 363 364 /******************************************************************************* 365 ** 366 ** Function llcp_util_deallocate_data_link 367 ** 368 ** Description Deallocate tLLCP_DLCB 369 ** 370 ** Returns void 371 ** 372 ******************************************************************************/ 373 void llcp_util_deallocate_data_link(tLLCP_DLCB* p_dlcb) { 374 if (p_dlcb) { 375 DLOG_IF(INFO, nfc_debug_enabled) 376 << StringPrintf("local_sap = 0x%x", p_dlcb->local_sap); 377 378 if (p_dlcb->state != LLCP_DLC_STATE_IDLE) { 379 nfc_stop_quick_timer(&p_dlcb->timer); 380 llcp_dlc_flush_q(p_dlcb); 381 382 p_dlcb->state = LLCP_DLC_STATE_IDLE; 383 384 if (llcp_cb.num_data_link_connection > 0) { 385 llcp_cb.num_data_link_connection--; 386 } 387 388 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 389 "num_data_link_connection = %d", llcp_cb.num_data_link_connection); 390 } 391 } 392 } 393 394 /******************************************************************************* 395 ** 396 ** Function llcp_util_send_connect 397 ** 398 ** Description Send CONNECT PDU 399 ** 400 ** Returns tLLCP_STATUS 401 ** 402 ******************************************************************************/ 403 tLLCP_STATUS llcp_util_send_connect(tLLCP_DLCB* p_dlcb, 404 tLLCP_CONNECTION_PARAMS* p_params) { 405 NFC_HDR* p_msg; 406 uint8_t* p; 407 uint16_t miu_len = 0, rw_len = 0, sn_len = 0; 408 409 if (p_params->miu != LLCP_DEFAULT_MIU) { 410 miu_len = 4; /* TYPE, LEN, 2 bytes MIU */ 411 } 412 if (p_params->rw != LLCP_DEFAULT_RW) { 413 rw_len = 3; /* TYPE, LEN, 1 byte RW */ 414 p_params->rw &= 0x0F; /* only 4 bits */ 415 } 416 if ((strlen(p_params->sn)) && (p_dlcb->remote_sap == LLCP_SAP_SDP)) { 417 sn_len = (uint16_t)(2 + strlen(p_params->sn)); /* TYPE, LEN, SN */ 418 } 419 420 p_msg = (NFC_HDR*)GKI_getpoolbuf(LLCP_POOL_ID); 421 422 if (p_msg) { 423 p_msg->len = LLCP_PDU_HEADER_SIZE + miu_len + rw_len + sn_len; 424 p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 425 426 p = (uint8_t*)(p_msg + 1) + p_msg->offset; 427 428 UINT16_TO_BE_STREAM( 429 p, LLCP_GET_PDU_HEADER(p_dlcb->remote_sap, LLCP_PDU_CONNECT_TYPE, 430 p_dlcb->local_sap)); 431 432 if (miu_len) { 433 UINT8_TO_BE_STREAM(p, LLCP_MIUX_TYPE); 434 UINT8_TO_BE_STREAM(p, LLCP_MIUX_LEN); 435 UINT16_TO_BE_STREAM(p, p_params->miu - LLCP_DEFAULT_MIU); 436 } 437 438 if (rw_len) { 439 UINT8_TO_BE_STREAM(p, LLCP_RW_TYPE); 440 UINT8_TO_BE_STREAM(p, LLCP_RW_LEN); 441 UINT8_TO_BE_STREAM(p, p_params->rw); 442 } 443 444 if (sn_len) { 445 UINT8_TO_BE_STREAM(p, LLCP_SN_TYPE); 446 UINT8_TO_BE_STREAM(p, sn_len - 2); 447 memcpy(p, p_params->sn, sn_len - 2); 448 } 449 450 GKI_enqueue(&llcp_cb.lcb.sig_xmit_q, p_msg); 451 llcp_link_check_send_data(); 452 453 return LLCP_STATUS_SUCCESS; 454 } 455 456 return LLCP_STATUS_FAIL; 457 } 458 459 /******************************************************************************* 460 ** 461 ** Function llcp_util_parse_connect 462 ** 463 ** Description Parse CONNECT PDU 464 ** 465 ** Returns tLLCP_STATUS 466 ** 467 *******************************************************************************/ 468 tLLCP_STATUS llcp_util_parse_connect(uint8_t* p_bytes, uint16_t length, 469 tLLCP_CONNECTION_PARAMS* p_params) { 470 uint8_t param_type, param_len, *p = p_bytes; 471 472 p_params->miu = LLCP_DEFAULT_MIU; 473 p_params->rw = LLCP_DEFAULT_RW; 474 p_params->sn[0] = 0; 475 p_params->sn[1] = 0; 476 477 while (length) { 478 BE_STREAM_TO_UINT8(param_type, p); 479 length--; 480 481 switch (param_type) { 482 case LLCP_MIUX_TYPE: 483 BE_STREAM_TO_UINT8(param_len, p); 484 BE_STREAM_TO_UINT16(p_params->miu, p); 485 p_params->miu &= LLCP_MIUX_MASK; 486 p_params->miu += LLCP_DEFAULT_MIU; 487 488 DLOG_IF(INFO, nfc_debug_enabled) 489 << StringPrintf("LLCP_MIUX_TYPE:%d", p_params->miu); 490 break; 491 492 case LLCP_RW_TYPE: 493 BE_STREAM_TO_UINT8(param_len, p); 494 BE_STREAM_TO_UINT8(p_params->rw, p); 495 p_params->rw &= 0x0F; 496 497 DLOG_IF(INFO, nfc_debug_enabled) 498 << StringPrintf("LLCP_RW_TYPE:%d", p_params->rw); 499 break; 500 501 case LLCP_SN_TYPE: 502 BE_STREAM_TO_UINT8(param_len, p); 503 504 if (param_len == 0) { 505 /* indicate that SN type is included without SN */ 506 p_params->sn[1] = LLCP_SN_TYPE; 507 } else if (param_len <= LLCP_MAX_SN_LEN) { 508 memcpy(p_params->sn, p, param_len); 509 p_params->sn[param_len] = 0; 510 } else { 511 memcpy(p_params->sn, p, LLCP_MAX_SN_LEN); 512 p_params->sn[LLCP_MAX_SN_LEN] = 0; 513 } 514 p += param_len; 515 516 DLOG_IF(INFO, nfc_debug_enabled) 517 << StringPrintf("LLCP_SN_TYPE:<%s>", p_params->sn); 518 break; 519 520 default: 521 LOG(ERROR) << StringPrintf("Unexpected type 0x%x", param_type); 522 BE_STREAM_TO_UINT8(param_len, p); 523 p += param_len; 524 break; 525 } 526 527 /* check remaining lengh */ 528 if (length >= param_len + 1) { 529 length -= param_len + 1; 530 } else { 531 LOG(ERROR) << StringPrintf("Bad LTV's"); 532 return LLCP_STATUS_FAIL; 533 } 534 } 535 return LLCP_STATUS_SUCCESS; 536 } 537 538 /******************************************************************************* 539 ** 540 ** Function llcp_util_send_cc 541 ** 542 ** Description Send CC PDU 543 ** 544 ** Returns tLLCP_STATUS 545 ** 546 ******************************************************************************/ 547 tLLCP_STATUS llcp_util_send_cc(tLLCP_DLCB* p_dlcb, 548 tLLCP_CONNECTION_PARAMS* p_params) { 549 NFC_HDR* p_msg; 550 uint8_t* p; 551 uint16_t miu_len = 0, rw_len = 0; 552 553 if (p_params->miu != LLCP_DEFAULT_MIU) { 554 miu_len = 4; 555 } 556 if (p_params->rw != LLCP_DEFAULT_RW) { 557 rw_len = 3; 558 p_params->rw &= 0x0F; 559 } 560 561 p_msg = (NFC_HDR*)GKI_getpoolbuf(LLCP_POOL_ID); 562 563 if (p_msg) { 564 p_msg->len = LLCP_PDU_HEADER_SIZE + miu_len + rw_len; 565 p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 566 567 p = (uint8_t*)(p_msg + 1) + p_msg->offset; 568 569 UINT16_TO_BE_STREAM( 570 p, LLCP_GET_PDU_HEADER(p_dlcb->remote_sap, LLCP_PDU_CC_TYPE, 571 p_dlcb->local_sap)); 572 573 if (miu_len) { 574 UINT8_TO_BE_STREAM(p, LLCP_MIUX_TYPE); 575 UINT8_TO_BE_STREAM(p, LLCP_MIUX_LEN); 576 UINT16_TO_BE_STREAM(p, p_params->miu - LLCP_DEFAULT_MIU); 577 } 578 579 if (rw_len) { 580 UINT8_TO_BE_STREAM(p, LLCP_RW_TYPE); 581 UINT8_TO_BE_STREAM(p, LLCP_RW_LEN); 582 UINT8_TO_BE_STREAM(p, p_params->rw); 583 } 584 585 GKI_enqueue(&llcp_cb.lcb.sig_xmit_q, p_msg); 586 llcp_link_check_send_data(); 587 588 return LLCP_STATUS_SUCCESS; 589 } 590 591 return LLCP_STATUS_FAIL; 592 } 593 594 /******************************************************************************* 595 ** 596 ** Function llcp_util_parse_cc 597 ** 598 ** Description Parse CC PDU 599 ** 600 ** Returns tLLCP_STATUS 601 ** 602 *******************************************************************************/ 603 tLLCP_STATUS llcp_util_parse_cc(uint8_t* p_bytes, uint16_t length, 604 uint16_t* p_miu, uint8_t* p_rw) { 605 uint8_t param_type, param_len, *p = p_bytes; 606 607 *p_miu = LLCP_DEFAULT_MIU; 608 *p_rw = LLCP_DEFAULT_RW; 609 610 while (length) { 611 BE_STREAM_TO_UINT8(param_type, p); 612 length--; 613 614 switch (param_type) { 615 case LLCP_MIUX_TYPE: 616 BE_STREAM_TO_UINT8(param_len, p); 617 BE_STREAM_TO_UINT16((*p_miu), p); 618 (*p_miu) &= LLCP_MIUX_MASK; 619 (*p_miu) += LLCP_DEFAULT_MIU; 620 621 DLOG_IF(INFO, nfc_debug_enabled) 622 << StringPrintf("LLCP_MIUX_TYPE:%d", *p_miu); 623 break; 624 625 case LLCP_RW_TYPE: 626 BE_STREAM_TO_UINT8(param_len, p); 627 BE_STREAM_TO_UINT8((*p_rw), p); 628 (*p_rw) &= 0x0F; 629 630 DLOG_IF(INFO, nfc_debug_enabled) 631 << StringPrintf("LLCP_RW_TYPE:%d", *p_rw); 632 break; 633 634 default: 635 LOG(ERROR) << StringPrintf("Unexpected type 0x%x", param_type); 636 BE_STREAM_TO_UINT8(param_len, p); 637 p += param_len; 638 break; 639 } 640 641 if (length >= param_len + 1) 642 length -= param_len + 1; 643 else { 644 LOG(ERROR) << StringPrintf("Bad LTV's"); 645 return LLCP_STATUS_FAIL; 646 } 647 } 648 return LLCP_STATUS_SUCCESS; 649 } 650 651 /******************************************************************************* 652 ** 653 ** Function llcp_util_send_dm 654 ** 655 ** Description Send DM PDU 656 ** 657 ** Returns void 658 ** 659 *******************************************************************************/ 660 void llcp_util_send_dm(uint8_t dsap, uint8_t ssap, uint8_t reason) { 661 NFC_HDR* p_msg; 662 uint8_t* p; 663 664 p_msg = (NFC_HDR*)GKI_getpoolbuf(LLCP_POOL_ID); 665 666 if (p_msg) { 667 p_msg->len = LLCP_PDU_DM_SIZE; 668 p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 669 670 p = (uint8_t*)(p_msg + 1) + p_msg->offset; 671 UINT16_TO_BE_STREAM(p, LLCP_GET_PDU_HEADER(dsap, LLCP_PDU_DM_TYPE, ssap)); 672 UINT8_TO_BE_STREAM(p, reason); 673 674 GKI_enqueue(&llcp_cb.lcb.sig_xmit_q, p_msg); 675 llcp_link_check_send_data(); 676 } 677 } 678 679 /******************************************************************************* 680 ** 681 ** Function llcp_util_build_info_pdu 682 ** 683 ** Description Add DSAP, PTYPE, SSAP and sequence numbers and update local 684 ** ack sequence 685 ** 686 ** Returns void 687 ** 688 *******************************************************************************/ 689 void llcp_util_build_info_pdu(tLLCP_DLCB* p_dlcb, NFC_HDR* p_msg) { 690 uint8_t* p; 691 uint8_t rcv_seq; 692 693 p_msg->offset -= LLCP_PDU_HEADER_SIZE + LLCP_SEQUENCE_SIZE; 694 p_msg->len += LLCP_PDU_HEADER_SIZE + LLCP_SEQUENCE_SIZE; 695 p = (uint8_t*)(p_msg + 1) + p_msg->offset; 696 697 UINT16_TO_BE_STREAM(p, 698 LLCP_GET_PDU_HEADER(p_dlcb->remote_sap, LLCP_PDU_I_TYPE, 699 p_dlcb->local_sap)); 700 701 /* if local_busy or rx congested then do not update receive sequence number to 702 * flow off */ 703 if ((p_dlcb->local_busy) || (p_dlcb->is_rx_congested) || 704 (llcp_cb.overall_rx_congested)) { 705 rcv_seq = p_dlcb->sent_ack_seq; 706 } else { 707 p_dlcb->sent_ack_seq = p_dlcb->next_rx_seq; 708 rcv_seq = p_dlcb->sent_ack_seq; 709 } 710 UINT8_TO_BE_STREAM(p, LLCP_GET_SEQUENCE(p_dlcb->next_tx_seq, rcv_seq)); 711 } 712 713 /******************************************************************************* 714 ** 715 ** Function llcp_util_send_frmr 716 ** 717 ** Description Send FRMR PDU 718 ** 719 ** Returns tLLCP_STATUS 720 ** 721 *******************************************************************************/ 722 tLLCP_STATUS llcp_util_send_frmr(tLLCP_DLCB* p_dlcb, uint8_t flags, 723 uint8_t ptype, uint8_t sequence) { 724 NFC_HDR* p_msg; 725 uint8_t* p; 726 727 p_msg = (NFC_HDR*)GKI_getpoolbuf(LLCP_POOL_ID); 728 729 if (p_msg) { 730 p_msg->len = LLCP_PDU_FRMR_SIZE; 731 p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 732 733 p = (uint8_t*)(p_msg + 1) + p_msg->offset; 734 735 UINT16_TO_BE_STREAM( 736 p, LLCP_GET_PDU_HEADER(p_dlcb->remote_sap, LLCP_PDU_FRMR_TYPE, 737 p_dlcb->local_sap)); 738 UINT8_TO_BE_STREAM(p, (flags << 4) | ptype); 739 UINT8_TO_BE_STREAM(p, sequence); 740 UINT8_TO_BE_STREAM(p, (p_dlcb->next_tx_seq << 4) | p_dlcb->next_rx_seq); 741 UINT8_TO_BE_STREAM(p, (p_dlcb->rcvd_ack_seq << 4) | p_dlcb->sent_ack_seq); 742 743 GKI_enqueue(&llcp_cb.lcb.sig_xmit_q, p_msg); 744 llcp_link_check_send_data(); 745 746 return LLCP_STATUS_SUCCESS; 747 } else { 748 LOG(ERROR) << StringPrintf("Out of resource"); 749 return LLCP_STATUS_FAIL; 750 } 751 } 752 753 /******************************************************************************* 754 ** 755 ** Function llcp_util_send_rr_rnr 756 ** 757 ** Description Send RR or RNR PDU 758 ** 759 ** Returns void 760 ** 761 *******************************************************************************/ 762 void llcp_util_send_rr_rnr(tLLCP_DLCB* p_dlcb) { 763 NFC_HDR* p_msg; 764 uint8_t* p; 765 uint8_t pdu_type; 766 uint8_t pdu_size; 767 uint8_t rcv_seq; 768 769 /* if no indication of change in local busy or rx congestion */ 770 if ((p_dlcb->flags & LLCP_DATA_LINK_FLAG_PENDING_RR_RNR) == 0) { 771 /* if all ack is sent */ 772 if (p_dlcb->sent_ack_seq == p_dlcb->next_rx_seq) { 773 /* we don't need to send RR/RNR */ 774 return; 775 } else { 776 /* if rx flow off because of local busy or congestion */ 777 if ((p_dlcb->local_busy) || (p_dlcb->is_rx_congested) || 778 (llcp_cb.overall_rx_congested)) { 779 /* don't send RR/RNR */ 780 return; 781 } 782 } 783 } 784 785 if ((p_dlcb->local_busy) || (p_dlcb->is_rx_congested) || 786 (llcp_cb.overall_rx_congested)) { 787 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 788 "" 789 "local_busy=%d,is_rx_congested=%d,overall_rx_congested=%d", 790 p_dlcb->local_busy, p_dlcb->is_rx_congested, 791 llcp_cb.overall_rx_congested); 792 793 /* if local_busy or rx congested then do not update receive sequence number 794 * to flow off */ 795 pdu_type = LLCP_PDU_RNR_TYPE; 796 pdu_size = LLCP_PDU_RNR_SIZE; 797 rcv_seq = p_dlcb->sent_ack_seq; 798 } else { 799 pdu_type = LLCP_PDU_RR_TYPE; 800 pdu_size = LLCP_PDU_RR_SIZE; 801 802 p_dlcb->sent_ack_seq = p_dlcb->next_rx_seq; 803 rcv_seq = p_dlcb->sent_ack_seq; 804 } 805 806 p_msg = (NFC_HDR*)GKI_getpoolbuf(LLCP_POOL_ID); 807 808 if (p_msg) { 809 p_dlcb->flags &= ~LLCP_DATA_LINK_FLAG_PENDING_RR_RNR; 810 811 p_msg->len = pdu_size; 812 p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 813 814 p = (uint8_t*)(p_msg + 1) + p_msg->offset; 815 816 UINT16_TO_BE_STREAM(p, LLCP_GET_PDU_HEADER(p_dlcb->remote_sap, pdu_type, 817 p_dlcb->local_sap)); 818 819 UINT8_TO_BE_STREAM(p, rcv_seq); 820 821 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 822 "LLCP TX - N(S,R):(NA,%d) V(S,SA,R,RA):(%d,%d,%d,%d)", 823 p_dlcb->next_rx_seq, p_dlcb->next_tx_seq, p_dlcb->rcvd_ack_seq, 824 p_dlcb->next_rx_seq, p_dlcb->sent_ack_seq); 825 GKI_enqueue(&llcp_cb.lcb.sig_xmit_q, p_msg); 826 llcp_link_check_send_data(); 827 } else { 828 LOG(ERROR) << StringPrintf("Out of resource"); 829 } 830 } 831 832 /******************************************************************************* 833 ** 834 ** Function llcp_util_get_app_cb 835 ** 836 ** Description get pointer of application registered control block by SAP 837 ** 838 ** Returns tLLCP_APP_CB * 839 ** 840 *******************************************************************************/ 841 tLLCP_APP_CB* llcp_util_get_app_cb(uint8_t local_sap) { 842 tLLCP_APP_CB* p_app_cb = NULL; 843 844 if (local_sap <= LLCP_UPPER_BOUND_WK_SAP) { 845 if ((local_sap != LLCP_SAP_LM) && (local_sap < LLCP_MAX_WKS)) { 846 p_app_cb = &llcp_cb.wks_cb[local_sap]; 847 } 848 } else if (local_sap <= LLCP_UPPER_BOUND_SDP_SAP) { 849 if (local_sap - LLCP_LOWER_BOUND_SDP_SAP < LLCP_MAX_SERVER) { 850 p_app_cb = &llcp_cb.server_cb[local_sap - LLCP_LOWER_BOUND_SDP_SAP]; 851 } 852 } else if (local_sap <= LLCP_UPPER_BOUND_LOCAL_SAP) { 853 if (local_sap - LLCP_LOWER_BOUND_LOCAL_SAP < LLCP_MAX_CLIENT) { 854 p_app_cb = &llcp_cb.client_cb[local_sap - LLCP_LOWER_BOUND_LOCAL_SAP]; 855 } 856 } 857 858 return (p_app_cb); 859 } 860