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 
    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