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 * 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*******************************************************************************/ 44BOOLEAN 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*******************************************************************************/ 115void 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*******************************************************************************/ 164void 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*******************************************************************************/ 211void 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*******************************************************************************/ 270tLLCP_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*******************************************************************************/ 313void 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******************************************************************************/ 342tLLCP_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******************************************************************************/ 390void 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******************************************************************************/ 422tLLCP_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*******************************************************************************/ 492tLLCP_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******************************************************************************/ 578tLLCP_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*******************************************************************************/ 637tLLCP_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*******************************************************************************/ 695void 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*******************************************************************************/ 726void 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*******************************************************************************/ 761tLLCP_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*******************************************************************************/ 802void 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*******************************************************************************/ 892tLLCP_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