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