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