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 500 while (length) 501 { 502 BE_STREAM_TO_UINT8 (param_type, p); 503 length--; 504 505 switch (param_type) 506 { 507 case LLCP_MIUX_TYPE: 508 BE_STREAM_TO_UINT8 (param_len, p); 509 BE_STREAM_TO_UINT16 (p_params->miu, p); 510 p_params->miu &= LLCP_MIUX_MASK; 511 p_params->miu += LLCP_DEFAULT_MIU; 512 513 LLCP_TRACE_DEBUG1 ("llcp_util_parse_connect (): LLCP_MIUX_TYPE:%d", p_params->miu); 514 break; 515 516 case LLCP_RW_TYPE: 517 BE_STREAM_TO_UINT8 (param_len, p); 518 BE_STREAM_TO_UINT8 (p_params->rw, p); 519 p_params->rw &= 0x0F; 520 521 LLCP_TRACE_DEBUG1 ("llcp_util_parse_connect (): LLCP_RW_TYPE:%d", p_params->rw); 522 break; 523 524 case LLCP_SN_TYPE: 525 BE_STREAM_TO_UINT8 (param_len, p); 526 527 if (param_len <= LLCP_MAX_SN_LEN) 528 { 529 memcpy (p_params->sn, p, param_len); 530 p_params->sn[param_len] = 0; 531 } 532 else 533 { 534 memcpy (p_params->sn, p, LLCP_MAX_SN_LEN); 535 p_params->sn[LLCP_MAX_SN_LEN] = 0; 536 } 537 p += param_len; 538 539 LLCP_TRACE_DEBUG1 ("llcp_util_parse_connect (): LLCP_SN_TYPE:<%s>", p_params->sn); 540 break; 541 542 default: 543 LLCP_TRACE_ERROR1 ("llcp_util_parse_connect (): Unexpected type 0x%x", param_type); 544 BE_STREAM_TO_UINT8 (param_len, p); 545 p += param_len; 546 break; 547 } 548 549 /* check remaining lengh */ 550 if (length >= param_len + 1) 551 { 552 length -= param_len + 1; 553 } 554 else 555 { 556 LLCP_TRACE_ERROR0 ("llcp_util_parse_connect (): Bad LTV's"); 557 return LLCP_STATUS_FAIL; 558 } 559 } 560 return LLCP_STATUS_SUCCESS; 561 } 562 563 /******************************************************************************* 564 ** 565 ** Function llcp_util_send_cc 566 ** 567 ** Description Send CC PDU 568 ** 569 ** Returns tLLCP_STATUS 570 ** 571 ******************************************************************************/ 572 tLLCP_STATUS llcp_util_send_cc (tLLCP_DLCB *p_dlcb, tLLCP_CONNECTION_PARAMS *p_params) 573 { 574 BT_HDR *p_msg; 575 UINT8 *p; 576 UINT16 miu_len = 0, rw_len = 0; 577 578 if (p_params->miu != LLCP_DEFAULT_MIU) 579 { 580 miu_len = 4; 581 } 582 if (p_params->rw != LLCP_DEFAULT_RW) 583 { 584 rw_len = 3; 585 p_params->rw &= 0x0F; 586 } 587 588 p_msg = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID); 589 590 if (p_msg) 591 { 592 p_msg->len = LLCP_PDU_HEADER_SIZE + miu_len + rw_len; 593 p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 594 595 p = (UINT8 *) (p_msg + 1) + p_msg->offset; 596 597 UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (p_dlcb->remote_sap, LLCP_PDU_CC_TYPE, p_dlcb->local_sap)); 598 599 if (miu_len) 600 { 601 UINT8_TO_BE_STREAM (p, LLCP_MIUX_TYPE); 602 UINT8_TO_BE_STREAM (p, LLCP_MIUX_LEN); 603 UINT16_TO_BE_STREAM (p, p_params->miu - LLCP_DEFAULT_MIU); 604 } 605 606 if (rw_len) 607 { 608 UINT8_TO_BE_STREAM (p, LLCP_RW_TYPE); 609 UINT8_TO_BE_STREAM (p, LLCP_RW_LEN); 610 UINT8_TO_BE_STREAM (p, p_params->rw); 611 } 612 613 GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, p_msg); 614 llcp_link_check_send_data (); 615 616 return LLCP_STATUS_SUCCESS; 617 } 618 619 return LLCP_STATUS_FAIL; 620 } 621 622 /******************************************************************************* 623 ** 624 ** Function llcp_util_parse_cc 625 ** 626 ** Description Parse CC PDU 627 ** 628 ** Returns tLLCP_STATUS 629 ** 630 *******************************************************************************/ 631 tLLCP_STATUS llcp_util_parse_cc (UINT8 *p_bytes, UINT16 length, UINT16 *p_miu, UINT8 *p_rw) 632 { 633 UINT8 param_type, param_len, *p = p_bytes; 634 635 *p_miu = LLCP_DEFAULT_MIU; 636 *p_rw = LLCP_DEFAULT_RW; 637 638 while (length) 639 { 640 BE_STREAM_TO_UINT8 (param_type, p); 641 length--; 642 643 switch (param_type) 644 { 645 case LLCP_MIUX_TYPE: 646 BE_STREAM_TO_UINT8 (param_len, p); 647 BE_STREAM_TO_UINT16 ((*p_miu), p); 648 (*p_miu) &= LLCP_MIUX_MASK; 649 (*p_miu) += LLCP_DEFAULT_MIU; 650 651 LLCP_TRACE_DEBUG1 ("llcp_util_parse_cc (): LLCP_MIUX_TYPE:%d", *p_miu); 652 break; 653 654 case LLCP_RW_TYPE: 655 BE_STREAM_TO_UINT8 (param_len, p); 656 BE_STREAM_TO_UINT8 ((*p_rw), p); 657 (*p_rw) &= 0x0F; 658 659 LLCP_TRACE_DEBUG1 ("llcp_util_parse_cc (): LLCP_RW_TYPE:%d", *p_rw); 660 break; 661 662 default: 663 LLCP_TRACE_ERROR1 ("llcp_util_parse_cc (): Unexpected type 0x%x", param_type); 664 BE_STREAM_TO_UINT8 (param_len, p); 665 p += param_len; 666 break; 667 } 668 669 if (length >= param_len + 1) 670 length -= param_len + 1; 671 else 672 { 673 LLCP_TRACE_ERROR0 ("llcp_util_parse_cc (): Bad LTV's"); 674 return LLCP_STATUS_FAIL; 675 } 676 } 677 return LLCP_STATUS_SUCCESS; 678 } 679 680 /******************************************************************************* 681 ** 682 ** Function llcp_util_send_dm 683 ** 684 ** Description Send DM PDU 685 ** 686 ** Returns void 687 ** 688 *******************************************************************************/ 689 void llcp_util_send_dm (UINT8 dsap, UINT8 ssap, UINT8 reason) 690 { 691 BT_HDR *p_msg; 692 UINT8 *p; 693 694 p_msg = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID); 695 696 if (p_msg) 697 { 698 p_msg->len = LLCP_PDU_DM_SIZE; 699 p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 700 701 p = (UINT8 *) (p_msg + 1) + p_msg->offset; 702 UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (dsap, LLCP_PDU_DM_TYPE, ssap)); 703 UINT8_TO_BE_STREAM (p, reason); 704 705 GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, p_msg); 706 llcp_link_check_send_data (); 707 } 708 } 709 710 /******************************************************************************* 711 ** 712 ** Function llcp_util_build_info_pdu 713 ** 714 ** Description Add DSAP, PTYPE, SSAP and sequence numbers and update local ack 715 ** sequence 716 ** 717 ** Returns void 718 ** 719 *******************************************************************************/ 720 void llcp_util_build_info_pdu (tLLCP_DLCB *p_dlcb, BT_HDR *p_msg) 721 { 722 UINT8 *p; 723 UINT8 rcv_seq; 724 725 p_msg->offset -= LLCP_PDU_HEADER_SIZE + LLCP_SEQUENCE_SIZE; 726 p_msg->len += LLCP_PDU_HEADER_SIZE + LLCP_SEQUENCE_SIZE; 727 p = (UINT8 *) (p_msg + 1) + p_msg->offset; 728 729 UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (p_dlcb->remote_sap, LLCP_PDU_I_TYPE, p_dlcb->local_sap)); 730 731 /* if local_busy or rx congested then do not update receive sequence number to flow off */ 732 if ( (p_dlcb->local_busy) 733 ||(p_dlcb->is_rx_congested) 734 ||(llcp_cb.overall_rx_congested) ) 735 { 736 rcv_seq = p_dlcb->sent_ack_seq; 737 } 738 else 739 { 740 p_dlcb->sent_ack_seq = p_dlcb->next_rx_seq; 741 rcv_seq = p_dlcb->sent_ack_seq; 742 } 743 UINT8_TO_BE_STREAM (p, LLCP_GET_SEQUENCE (p_dlcb->next_tx_seq, rcv_seq)); 744 } 745 746 /******************************************************************************* 747 ** 748 ** Function llcp_util_send_frmr 749 ** 750 ** Description Send FRMR PDU 751 ** 752 ** Returns tLLCP_STATUS 753 ** 754 *******************************************************************************/ 755 tLLCP_STATUS llcp_util_send_frmr (tLLCP_DLCB *p_dlcb, UINT8 flags, UINT8 ptype, UINT8 sequence) 756 { 757 BT_HDR *p_msg; 758 UINT8 *p; 759 760 p_msg = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID); 761 762 if (p_msg) 763 { 764 p_msg->len = LLCP_PDU_FRMR_SIZE; 765 p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 766 767 p = (UINT8 *) (p_msg + 1) + p_msg->offset; 768 769 UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (p_dlcb->remote_sap, LLCP_PDU_FRMR_TYPE, p_dlcb->local_sap)); 770 UINT8_TO_BE_STREAM (p, (flags << 4) | ptype); 771 UINT8_TO_BE_STREAM (p, sequence); 772 UINT8_TO_BE_STREAM (p, (p_dlcb->next_tx_seq << 4) | p_dlcb->next_rx_seq); 773 UINT8_TO_BE_STREAM (p, (p_dlcb->rcvd_ack_seq << 4) | p_dlcb->sent_ack_seq); 774 775 GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, p_msg); 776 llcp_link_check_send_data (); 777 778 return LLCP_STATUS_SUCCESS; 779 } 780 else 781 { 782 LLCP_TRACE_ERROR0 ("llcp_util_send_frmr (): Out of resource"); 783 return LLCP_STATUS_FAIL; 784 } 785 } 786 787 /******************************************************************************* 788 ** 789 ** Function llcp_util_send_rr_rnr 790 ** 791 ** Description Send RR or RNR PDU 792 ** 793 ** Returns void 794 ** 795 *******************************************************************************/ 796 void llcp_util_send_rr_rnr (tLLCP_DLCB *p_dlcb) 797 { 798 BT_HDR *p_msg; 799 UINT8 *p; 800 UINT8 pdu_type; 801 UINT8 pdu_size; 802 UINT8 rcv_seq; 803 804 /* if no indication of change in local busy or rx congestion */ 805 if ((p_dlcb->flags & LLCP_DATA_LINK_FLAG_PENDING_RR_RNR) == 0) 806 { 807 /* if all ack is sent */ 808 if (p_dlcb->sent_ack_seq == p_dlcb->next_rx_seq) 809 { 810 /* we don't need to send RR/RNR */ 811 return; 812 } 813 else 814 { 815 /* if rx flow off because of local busy or congestion */ 816 if ( (p_dlcb->local_busy) 817 ||(p_dlcb->is_rx_congested) 818 ||(llcp_cb.overall_rx_congested) ) 819 { 820 /* don't send RR/RNR */ 821 return; 822 } 823 } 824 } 825 826 if ( (p_dlcb->local_busy) 827 ||(p_dlcb->is_rx_congested) 828 ||(llcp_cb.overall_rx_congested) ) 829 { 830 LLCP_TRACE_DEBUG3 ("llcp_util_send_rr_rnr (): local_busy=%d,is_rx_congested=%d,overall_rx_congested=%d", 831 p_dlcb->local_busy, p_dlcb->is_rx_congested, llcp_cb.overall_rx_congested); 832 833 /* if local_busy or rx congested then do not update receive sequence number to flow off */ 834 pdu_type = LLCP_PDU_RNR_TYPE; 835 pdu_size = LLCP_PDU_RNR_SIZE; 836 rcv_seq = p_dlcb->sent_ack_seq; 837 } 838 else 839 { 840 pdu_type = LLCP_PDU_RR_TYPE; 841 pdu_size = LLCP_PDU_RR_SIZE; 842 843 p_dlcb->sent_ack_seq = p_dlcb->next_rx_seq; 844 rcv_seq = p_dlcb->sent_ack_seq; 845 } 846 847 p_msg = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID); 848 849 if (p_msg) 850 { 851 p_dlcb->flags &= ~LLCP_DATA_LINK_FLAG_PENDING_RR_RNR; 852 853 p_msg->len = pdu_size; 854 p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 855 856 p = (UINT8 *) (p_msg + 1) + p_msg->offset; 857 858 UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (p_dlcb->remote_sap, pdu_type, p_dlcb->local_sap)); 859 860 UINT8_TO_BE_STREAM (p, rcv_seq); 861 862 #if (BT_TRACE_VERBOSE == TRUE) 863 LLCP_TRACE_DEBUG5 ("LLCP TX - N(S,R):(NA,%d) V(S,SA,R,RA):(%d,%d,%d,%d)", 864 p_dlcb->next_rx_seq, 865 p_dlcb->next_tx_seq, p_dlcb->rcvd_ack_seq, 866 p_dlcb->next_rx_seq, p_dlcb->sent_ack_seq); 867 #endif 868 GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, p_msg); 869 llcp_link_check_send_data (); 870 } 871 else 872 { 873 LLCP_TRACE_ERROR0 ("llcp_util_send_rr_rnr (): Out of resource"); 874 } 875 } 876 877 /******************************************************************************* 878 ** 879 ** Function llcp_util_get_app_cb 880 ** 881 ** Description get pointer of application registered control block by SAP 882 ** 883 ** Returns tLLCP_APP_CB * 884 ** 885 *******************************************************************************/ 886 tLLCP_APP_CB *llcp_util_get_app_cb (UINT8 local_sap) 887 { 888 tLLCP_APP_CB *p_app_cb = NULL; 889 890 if (local_sap <= LLCP_UPPER_BOUND_WK_SAP) 891 { 892 if ((local_sap != LLCP_SAP_LM) && (local_sap < LLCP_MAX_WKS)) 893 { 894 p_app_cb = &llcp_cb.wks_cb[local_sap]; 895 } 896 } 897 else if (local_sap <= LLCP_UPPER_BOUND_SDP_SAP) 898 { 899 if (local_sap - LLCP_LOWER_BOUND_SDP_SAP < LLCP_MAX_SERVER) 900 { 901 p_app_cb = &llcp_cb.server_cb[local_sap - LLCP_LOWER_BOUND_SDP_SAP]; 902 } 903 } 904 else if (local_sap <= LLCP_UPPER_BOUND_LOCAL_SAP) 905 { 906 if (local_sap - LLCP_LOWER_BOUND_LOCAL_SAP < LLCP_MAX_CLIENT) 907 { 908 p_app_cb = &llcp_cb.client_cb[local_sap - LLCP_LOWER_BOUND_LOCAL_SAP]; 909 } 910 } 911 912 return (p_app_cb); 913 } 914