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