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