Home | History | Annotate | Download | only in llcp
      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