C++程序  |  1976行  |  66.45 KB

/******************************************************************************
 *
 *  Copyright (C) 2010-2012 Broadcom Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at:
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 ******************************************************************************/

/******************************************************************************
 *
 *  This is the generic SNEP implementation file for the NFA SNEP.
 *
 ******************************************************************************/
#include <string.h>
#include "nfa_api.h"
#include "nfa_sys.h"
#include "nfa_sys_int.h"
#include "llcp_defs.h"
#include "nfa_p2p_int.h"
#include "nfa_snep_int.h"
#include "nfa_mem_co.h"
#include "trace_api.h"

/*****************************************************************************
**  Global Variables
*****************************************************************************/

/*****************************************************************************
**  Static Functions
*****************************************************************************/

/* debug functions type */
#if (BT_TRACE_VERBOSE == TRUE)
static char *nfa_snep_opcode (UINT8 opcode);
#endif

/*****************************************************************************
**  Constants
*****************************************************************************/

/*******************************************************************************
**
** Function         nfa_snep_sap_to_index
**
** Description      find a connection control block with SAP
**
**
** Returns          index of connection control block if success
**                  NFA_SNEP_MAX_CONN, otherwise
**
*******************************************************************************/
UINT8 nfa_snep_sap_to_index (UINT8 local_sap, UINT8 remote_sap, UINT8 flags)
{
    UINT8 xx;

    for (xx = 0; xx < NFA_SNEP_MAX_CONN; xx++)
    {
        if (  (nfa_snep_cb.conn[xx].p_cback)
            &&(nfa_snep_cb.conn[xx].local_sap == local_sap)
            &&((remote_sap == NFA_SNEP_ANY_SAP) || (nfa_snep_cb.conn[xx].remote_sap == remote_sap))
            &&((nfa_snep_cb.conn[xx].flags & flags) == flags)  )
        {
            return xx;
        }
    }
    return NFA_SNEP_MAX_CONN;
}

/*******************************************************************************
**
** Function         nfa_snep_allocate_cb
**
** Description      Allocate a connection control block
**
**
** Returns          index of connection control block if success
**                  NFA_SNEP_MAX_CONN, otherwise
**
*******************************************************************************/
UINT8 nfa_snep_allocate_cb (void)
{
    UINT8 xx;

    for (xx = 0; xx < NFA_SNEP_MAX_CONN; xx++)
    {
        if (nfa_snep_cb.conn[xx].p_cback == NULL)
        {
            memset (&nfa_snep_cb.conn[xx], 0x00, sizeof (tNFA_SNEP_CONN));
            return xx;
        }
    }
    return NFA_SNEP_MAX_CONN;
}

/*******************************************************************************
**
** Function         nfa_snep_deallocate_cb
**
** Description      Deallocate a connection control block
**
**
** Returns          void
**
*******************************************************************************/
void nfa_snep_deallocate_cb (UINT8 xx)
{
    nfa_snep_cb.conn[xx].p_cback = NULL;
}

/*******************************************************************************
**
** Function         nfa_snep_timer_cback
**
** Description      Process timeout event when timer expires
**
**
** Returns          None
**
*******************************************************************************/
static void nfa_snep_timer_cback (void *p_tle)
{
    UINT8 dlink = (UINT8) ((TIMER_LIST_ENT*)p_tle)->event;

    SNEP_TRACE_DEBUG1 ("nfa_snep_timer_cback () dlink = %d", dlink);

    /* application will free buffer when receiving NFA_SNEP_DISC_EVT */
    nfa_snep_cb.conn[dlink].p_ndef_buff = NULL;

    LLCP_DisconnectReq (nfa_snep_cb.conn[dlink].local_sap,
                        nfa_snep_cb.conn[dlink].remote_sap, TRUE);
}

/*******************************************************************************
**
** Function         nfa_snep_get_efficent_miu
**
** Description      Calculate best MIU to send data for throughput
**
**
** Returns          most efficent MIU for throughput
**
*******************************************************************************/
static UINT16 nfa_snep_get_efficent_miu (UINT16 remote_miu, UINT8 remote_rw)
{
    UINT16 local_link_miu, remote_link_miu;
    UINT16 max_num_pdu_in_agf;
    UINT16 efficent_miu;

    SNEP_TRACE_DEBUG2 ("nfa_snep_get_efficent_miu () remote_miu = %d, remote_rw = %d",
                        remote_miu, remote_rw);

    LLCP_GetLinkMIU (&local_link_miu, &remote_link_miu);

    /* local buffer size is small than max receiving size of peer */
    if (local_link_miu < remote_link_miu)
    {
        remote_link_miu = local_link_miu;
    }

    /*
    ** 9 bytes overhead if AGF is used
    **  - 2 byts AGF header
    **  - at least two of 2 bytes length field for I-PDU
    **  - 3 bytes header for I-PDU
    */
    if (remote_link_miu - remote_miu > 9)
    {
        /*
        ** 5 bytes overhead for each I-PDU in AGF
        **  - 2 bytes length field
        **  - 3 bytes header for I-PDU
        */
        max_num_pdu_in_agf = remote_link_miu / (remote_miu + 5);

        if (remote_link_miu % (remote_miu + 5))
        {
            max_num_pdu_in_agf += 1;
        }

        /* if local devie can put all I-PDU in one AGF */
        if (max_num_pdu_in_agf <= remote_rw)
        {
            efficent_miu = (remote_link_miu - max_num_pdu_in_agf*5)/max_num_pdu_in_agf;
        }
        else
        {
            efficent_miu = remote_miu;
        }
    }
    else
    {
        efficent_miu = remote_miu;
    }

    SNEP_TRACE_DEBUG2 ("nfa_snep_get_efficent_miu () remote_link_miu = %d, efficent_miu = %d",
                        remote_link_miu, efficent_miu);

    return efficent_miu;
}

/*******************************************************************************
**
** Function         nfa_snep_check_version
**
** Description      Check version of SNEP
**
**
** Returns          TRUE if supported
**
*******************************************************************************/
BOOLEAN nfa_snep_check_version (UINT8 version)
{
    /* if major version is matched */
    if ((version & 0xF0) == (NFA_SNEP_VERSION & 0xF0))
        return TRUE;
    else
        return FALSE;
}

/*******************************************************************************
**
** Function         nfa_snep_send_msg
**
** Description      Send complete or the first fragment of SNEP message with or
**                  without information.
**
** Returns          void
**
*******************************************************************************/
void nfa_snep_send_msg (UINT8 opcode, UINT8 dlink)
{
    BT_HDR *p_msg;
    UINT32 length;
    UINT8  *p;
    tLLCP_STATUS status = LLCP_STATUS_FAIL;

#if (BT_TRACE_VERBOSE == TRUE)
    SNEP_TRACE_DEBUG4 ("nfa_snep_send_msg () [0x%x, 0x%x]: %s (0x%02x)",
                       nfa_snep_cb.conn[dlink].local_sap,
                       nfa_snep_cb.conn[dlink].remote_sap,
                       nfa_snep_opcode (opcode), opcode);
#else
    SNEP_TRACE_DEBUG3 ("nfa_snep_send_msg () [0x%x, 0x%x]: opcode 0x%02x",
                       nfa_snep_cb.conn[dlink].local_sap,
                       nfa_snep_cb.conn[dlink].remote_sap,
                       opcode);
#endif

    /* if there is pending SNEP message and opcode can have information */
    if (  (nfa_snep_cb.conn[dlink].p_ndef_buff)
        &&((opcode == NFA_SNEP_REQ_CODE_GET) || (opcode == NFA_SNEP_REQ_CODE_PUT) || (opcode == NFA_SNEP_RESP_CODE_SUCCESS))  )
    {
        length = NFA_SNEP_HEADER_SIZE + nfa_snep_cb.conn[dlink].ndef_length;

        if (opcode == NFA_SNEP_REQ_CODE_GET)
        {
            length += NFA_SNEP_ACCEPT_LEN_SIZE; /* add acceptable length field */
        }

        /* if message is bigger than peer's MIU, send the first fragment */
        if (length > nfa_snep_cb.conn[dlink].tx_miu)
        {
            length = nfa_snep_cb.conn[dlink].tx_miu;
        }

        if ((p_msg = (BT_HDR *) GKI_getpoolbuf (LLCP_POOL_ID)) != NULL)
        {
            p_msg->len    = (UINT16) length;
            p_msg->offset = LLCP_MIN_OFFSET;

            p = (UINT8*) (p_msg + 1) + p_msg->offset;

            /* add SNEP header */
            UINT8_TO_BE_STREAM (p, NFA_SNEP_VERSION);
            UINT8_TO_BE_STREAM (p, opcode);

            if (opcode == NFA_SNEP_REQ_CODE_GET)
            {
                /* add acceptable length field in information field*/
                UINT32_TO_BE_STREAM (p, nfa_snep_cb.conn[dlink].ndef_length + NFA_SNEP_ACCEPT_LEN_SIZE);
                UINT32_TO_BE_STREAM (p, nfa_snep_cb.conn[dlink].acceptable_length);
                length -= NFA_SNEP_ACCEPT_LEN_SIZE;
            }
            else
            {
                UINT32_TO_BE_STREAM (p, nfa_snep_cb.conn[dlink].ndef_length);
            }

            length -= NFA_SNEP_HEADER_SIZE;


            /* add the first fragment or complete of NDEF message */
            memcpy (p, nfa_snep_cb.conn[dlink].p_ndef_buff, length);

#if (BT_TRACE_PROTOCOL == TRUE)
            DispSNEP (nfa_snep_cb.conn[dlink].local_sap,
                      nfa_snep_cb.conn[dlink].remote_sap,
                     (UINT8*)(p_msg + 1) + p_msg->offset,
                      NFA_SNEP_HEADER_SIZE,
                      FALSE);
#endif
            status = LLCP_SendData (nfa_snep_cb.conn[dlink].local_sap,
                                    nfa_snep_cb.conn[dlink].remote_sap, p_msg);

            if (status != LLCP_STATUS_FAIL)
            {
                SNEP_TRACE_DEBUG2 ("nfa_snep_send_msg (): sending %d out of %d",
                                   length, nfa_snep_cb.conn[dlink].ndef_length);

                /* if sent complete SNEP message */
                if (length == nfa_snep_cb.conn[dlink].ndef_length)
                {
                    nfa_snep_cb.conn[dlink].cur_length = 0;

                    if (  (opcode == NFA_SNEP_RESP_CODE_SUCCESS)
                        &&(nfa_snep_cb.conn[dlink].rx_code == NFA_SNEP_REQ_CODE_GET)  )
                    {
                        /* Set LLCP to send LLCP_SAP_EVT_TX_COMPLETE */
                        LLCP_SetTxCompleteNtf (nfa_snep_cb.conn[dlink].local_sap,
                                               nfa_snep_cb.conn[dlink].remote_sap);
                    }
                }
                else
                {
                    /* update sent length */
                    nfa_snep_cb.conn[dlink].cur_length = length;

                    if ((opcode == NFA_SNEP_REQ_CODE_GET) || (opcode == NFA_SNEP_REQ_CODE_PUT))
                    {
                        nfa_snep_cb.conn[dlink].flags |= NFA_SNEP_FLAG_W4_RESP_CONTINUE;
                    }
                    else /* (opcode == NFA_SNEP_RESP_CODE_SUCCESS) */
                    {
                        nfa_snep_cb.conn[dlink].flags |= NFA_SNEP_FLAG_W4_REQ_CONTINUE;
                    }
                }
            }
        }
    }
    else /* opcode without information */
    {
        if ((p_msg = (BT_HDR *) GKI_getpoolbuf (LLCP_POOL_ID)) != NULL)
        {
            p_msg->len    = NFA_SNEP_HEADER_SIZE;
            p_msg->offset = LLCP_MIN_OFFSET;

            p = (UINT8*) (p_msg + 1) + p_msg->offset;

            /* add SNEP header without information */
            UINT8_TO_BE_STREAM (p, NFA_SNEP_VERSION);
            UINT8_TO_BE_STREAM (p, opcode);
            UINT32_TO_BE_STREAM (p, 0);

#if (BT_TRACE_PROTOCOL == TRUE)
            DispSNEP(nfa_snep_cb.conn[dlink].local_sap,
                     nfa_snep_cb.conn[dlink].remote_sap,
                     (UINT8*)(p_msg + 1) + p_msg->offset,
                     NFA_SNEP_HEADER_SIZE,
                     FALSE);
#endif
            status = LLCP_SendData (nfa_snep_cb.conn[dlink].local_sap,
                                    nfa_snep_cb.conn[dlink].remote_sap, p_msg);
        }
    }

    if (status == LLCP_STATUS_FAIL)
    {
        SNEP_TRACE_ERROR0 ("Cannot allocate buffer or failed to send data");

        /* upper layer will free buffer when NFA_SNEP_DISC_EVT is received */
        nfa_snep_cb.conn[dlink].p_ndef_buff = 0;

        LLCP_DisconnectReq (nfa_snep_cb.conn[dlink].local_sap,
                            nfa_snep_cb.conn[dlink].remote_sap, TRUE);
    }
    else if (status == LLCP_STATUS_CONGESTED)
    {
        nfa_snep_cb.conn[dlink].congest = TRUE;
    }
}

/*******************************************************************************
**
** Function         nfa_snep_send_remaining
**
** Description      Send remaining fragments of SNEP message
**
**
** Returns          void
**
*******************************************************************************/
void nfa_snep_send_remaining (UINT8 dlink)
{
    BT_HDR *p_msg;
    UINT8  *p_src, *p_dst;
    UINT32 length;
    tLLCP_STATUS status;

    SNEP_TRACE_DEBUG1 ("nfa_snep_send_remaining (): dlink:0x%02X", dlink);

    /* while data link connection is not congested */
    while (  (nfa_snep_cb.conn[dlink].congest == FALSE)
           &&(nfa_snep_cb.conn[dlink].cur_length > 0)   /* if any fragment was sent */
           &&(nfa_snep_cb.conn[dlink].cur_length < nfa_snep_cb.conn[dlink].ndef_length)  )
    {
        /* start of remaining fragments */
        p_src = nfa_snep_cb.conn[dlink].p_ndef_buff + nfa_snep_cb.conn[dlink].cur_length;

        length = nfa_snep_cb.conn[dlink].ndef_length - nfa_snep_cb.conn[dlink].cur_length;

        /* sending up to peer's MIU */
        if (length > nfa_snep_cb.conn[dlink].tx_miu)
        {
            length = nfa_snep_cb.conn[dlink].tx_miu;
        }

        status = LLCP_STATUS_FAIL;

        if ((p_msg = (BT_HDR *) GKI_getpoolbuf (LLCP_POOL_ID)) != NULL)
        {
            p_msg->len    = (UINT16) length;
            p_msg->offset = LLCP_MIN_OFFSET;

            p_dst = (UINT8*) (p_msg + 1) + p_msg->offset;

            memcpy (p_dst, p_src, length);

            status = LLCP_SendData (nfa_snep_cb.conn[dlink].local_sap,
                                    nfa_snep_cb.conn[dlink].remote_sap, p_msg);

            if (status != LLCP_STATUS_FAIL)
            {
                /* update sent length */
                nfa_snep_cb.conn[dlink].cur_length += length;

                SNEP_TRACE_DEBUG2 ("nfa_snep_send_remaining (): sending %d out of %d",
                                   nfa_snep_cb.conn[dlink].cur_length,
                                   nfa_snep_cb.conn[dlink].ndef_length);

                /* if sent the last fragment */
                if (nfa_snep_cb.conn[dlink].cur_length == nfa_snep_cb.conn[dlink].ndef_length)
                {
                    nfa_snep_cb.conn[dlink].cur_length = 0;

                    if (  (nfa_snep_cb.conn[dlink].tx_code == NFA_SNEP_RESP_CODE_SUCCESS)
                        &&(nfa_snep_cb.conn[dlink].rx_code == NFA_SNEP_REQ_CODE_CONTINUE)  )
                    {
                        /* Set LLCP to send LLCP_SAP_EVT_TX_COMPLETE */
                        LLCP_SetTxCompleteNtf (nfa_snep_cb.conn[dlink].local_sap,
                                               nfa_snep_cb.conn[dlink].remote_sap);
                    }
                }
            }
        }

        if (status == LLCP_STATUS_CONGESTED)
        {
            nfa_snep_cb.conn[dlink].congest = TRUE;

            /* wait for uncongested event from LLCP */
            break;
        }
        else if (status == LLCP_STATUS_FAIL)
        {
            SNEP_TRACE_ERROR0 ("Cannot allocate buffer or failed to send data");

            /* upper layer will free buffer when NFA_SNEP_DISC_EVT is received */
            nfa_snep_cb.conn[dlink].p_ndef_buff = 0;

            LLCP_DisconnectReq (nfa_snep_cb.conn[dlink].local_sap,
                                nfa_snep_cb.conn[dlink].remote_sap, TRUE);
            return;
        }
    }
}

/*******************************************************************************
**
** Function         nfa_snep_llcp_cback
**
** Description      Processing event from LLCP
**
**
** Returns          None
**
*******************************************************************************/
void nfa_snep_llcp_cback (tLLCP_SAP_CBACK_DATA *p_data)
{
    SNEP_TRACE_DEBUG2 ("nfa_snep_llcp_cback (): event:0x%02X, local_sap:0x%02X", p_data->hdr.event, p_data->hdr.local_sap);

    switch (p_data->hdr.event)
    {
    case LLCP_SAP_EVT_DATA_IND:
        nfa_snep_proc_llcp_data_ind (p_data);
        break;

    case LLCP_SAP_EVT_CONNECT_IND:
        nfa_snep_proc_llcp_connect_ind (p_data);
        break;

    case LLCP_SAP_EVT_CONNECT_RESP:
        nfa_snep_proc_llcp_connect_resp (p_data);
        break;

    case LLCP_SAP_EVT_DISCONNECT_IND:
        nfa_snep_proc_llcp_disconnect_ind (p_data);
        break;

    case LLCP_SAP_EVT_DISCONNECT_RESP:
        nfa_snep_proc_llcp_disconnect_resp (p_data);
        break;

    case LLCP_SAP_EVT_CONGEST:
        /* congestion start/end */
        nfa_snep_proc_llcp_congest (p_data);
        break;

    case LLCP_SAP_EVT_LINK_STATUS:
        nfa_snep_proc_llcp_link_status (p_data);
        break;

    case LLCP_SAP_EVT_TX_COMPLETE:
        nfa_snep_proc_llcp_tx_complete (p_data);
        break;

    default:
        SNEP_TRACE_ERROR1 ("Unknown event:0x%02X", p_data->hdr.event);
        return;
    }
}

/*******************************************************************************
**
** Function         nfa_snep_validate_rx_msg
**
** Description      Validate version, opcode, length in received message
**
**
** Returns          TRUE if message is valid
**
*******************************************************************************/
BOOLEAN nfa_snep_validate_rx_msg (UINT8 dlink)
{
    UINT32  length;
    UINT8   buffer[NFA_SNEP_HEADER_SIZE], *p;
    BOOLEAN more;
    UINT8   version, opcode;
    UINT32  info_len;

    SNEP_TRACE_DEBUG0 ("nfa_snep_validate_rx_msg ()");

    more = LLCP_ReadDataLinkData (nfa_snep_cb.conn[dlink].local_sap,
                                  nfa_snep_cb.conn[dlink].remote_sap,
                                  NFA_SNEP_HEADER_SIZE,
                                  &length, buffer);

#if (BT_TRACE_PROTOCOL == TRUE)
    DispSNEP(nfa_snep_cb.conn[dlink].local_sap,
             nfa_snep_cb.conn[dlink].remote_sap,
             buffer,
             (UINT16)length,
             TRUE);
#endif

    /* check if it has minimum header,
    ** the first fragment shall include at least the entier SNEP header
    */
    if (length < NFA_SNEP_HEADER_SIZE)
    {
        SNEP_TRACE_ERROR0 ("The first fragment shall include at least the entire SNEP header");

        /* application will free buffer when receiving NFA_SNEP_DISC_EVT */
        nfa_snep_cb.conn[dlink].p_ndef_buff = NULL;

        LLCP_DisconnectReq (nfa_snep_cb.conn[dlink].local_sap,
                            nfa_snep_cb.conn[dlink].remote_sap, TRUE);
        return FALSE;
    }

    p = buffer;

    /* parse SNEP header */
    BE_STREAM_TO_UINT8 (version, p);
    BE_STREAM_TO_UINT8 (opcode,  p);
    BE_STREAM_TO_UINT32 (info_len, p);

    /* check version of SNEP */
    if (!nfa_snep_check_version (version))
    {
        nfa_snep_send_msg (NFA_SNEP_RESP_CODE_UNSUPP_VER, dlink);
        return FALSE;
    }

    /* check valid opcode for server */
    if (nfa_snep_cb.conn[dlink].flags & NFA_SNEP_FLAG_SERVER)
    {
        /* if this is response message */
        if (opcode & NFA_SNEP_RESP_CODE_CONTINUE)
        {
            SNEP_TRACE_ERROR0 ("Invalid opcode for server");

            /* application will free buffer when receiving NFA_SNEP_DISC_EVT */
            nfa_snep_cb.conn[dlink].p_ndef_buff = NULL;

            LLCP_DisconnectReq (nfa_snep_cb.conn[dlink].local_sap,
                                nfa_snep_cb.conn[dlink].remote_sap, TRUE);
            return FALSE;
        }
        else if (  (opcode != NFA_SNEP_REQ_CODE_CONTINUE)
                 &&(opcode != NFA_SNEP_REQ_CODE_GET)
                 &&(opcode != NFA_SNEP_REQ_CODE_PUT)
                 &&(opcode != NFA_SNEP_REQ_CODE_REJECT)  )
        {
            SNEP_TRACE_ERROR0 ("Not supported opcode for server");
            nfa_snep_send_msg (NFA_SNEP_RESP_CODE_NOT_IMPLM, dlink);
            return FALSE;
        }
    }
    /* check valid opcode for client */
    else
    {
        if (  (opcode != NFA_SNEP_RESP_CODE_CONTINUE)
            &&(opcode != NFA_SNEP_RESP_CODE_SUCCESS)
            &&(opcode != NFA_SNEP_RESP_CODE_NOT_FOUND)
            &&(opcode != NFA_SNEP_RESP_CODE_EXCESS_DATA)
            &&(opcode != NFA_SNEP_RESP_CODE_BAD_REQ)
            &&(opcode != NFA_SNEP_RESP_CODE_NOT_IMPLM)
            &&(opcode != NFA_SNEP_RESP_CODE_UNSUPP_VER)
            &&(opcode != NFA_SNEP_RESP_CODE_REJECT)  )
        {
            SNEP_TRACE_ERROR0 ("Invalid opcode for client");
            /* client cannot send error code so disconnect */
            /* application will free buffer when receiving NFA_SNEP_DISC_EVT */
            nfa_snep_cb.conn[dlink].p_ndef_buff = NULL;

            LLCP_DisconnectReq (nfa_snep_cb.conn[dlink].local_sap,
                                nfa_snep_cb.conn[dlink].remote_sap, TRUE);
            return FALSE;
        }
    }

    if (opcode == NFA_SNEP_REQ_CODE_GET)
    {
        more = LLCP_ReadDataLinkData (nfa_snep_cb.conn[dlink].local_sap,
                                      nfa_snep_cb.conn[dlink].remote_sap,
                                      NFA_SNEP_ACCEPT_LEN_SIZE,
                                      &length, buffer);

        if (length < NFA_SNEP_ACCEPT_LEN_SIZE)
        {
            /*
            ** Including acceptable length in the first segment is not mandated in spec
            ** but MIU is always big enough to include acceptable length field.
            */
            nfa_snep_send_msg (NFA_SNEP_RESP_CODE_BAD_REQ, dlink);
            return FALSE;
        }

        p = buffer;
        BE_STREAM_TO_UINT32 (nfa_snep_cb.conn[dlink].acceptable_length, p);

        /* store expected NDEF message length */
        nfa_snep_cb.conn[dlink].ndef_length = info_len - NFA_SNEP_ACCEPT_LEN_SIZE;
    }
    else if (  (opcode == NFA_SNEP_REQ_CODE_PUT)
             ||((opcode == NFA_SNEP_RESP_CODE_SUCCESS) && (nfa_snep_cb.conn[dlink].tx_code == NFA_SNEP_REQ_CODE_GET)))
    {
        /* store expected NDEF message length */
        nfa_snep_cb.conn[dlink].ndef_length = info_len;
    }
    else
    {
        if (more)
        {
            SNEP_TRACE_ERROR0 ("The information field shall not be transmitted with this request or response");

            if (nfa_snep_cb.conn[dlink].flags & NFA_SNEP_FLAG_SERVER)
            {
                nfa_snep_send_msg (NFA_SNEP_RESP_CODE_BAD_REQ, dlink);
            }
            /* client cannot send error code so disconnect */
            /* application will free buffer when receiving NFA_SNEP_DISC_EVT */
            nfa_snep_cb.conn[dlink].p_ndef_buff = NULL;

            LLCP_DisconnectReq (nfa_snep_cb.conn[dlink].local_sap,
                                nfa_snep_cb.conn[dlink].remote_sap, TRUE);
            return FALSE;
        }
    }

    /* store received opcode */
    nfa_snep_cb.conn[dlink].rx_code = opcode;

    return TRUE;
}

/*******************************************************************************
**
** Function         nfa_snep_store_first_rx_msg
**
** Description      Allocate buffer and store the first fragment
**
**
** Returns          TRUE if the received fragment is successfully stored
**
*******************************************************************************/
BOOLEAN nfa_snep_store_first_rx_msg (UINT8 dlink)
{
    tNFA_SNEP_EVT_DATA evt_data;
    BOOLEAN            more;
    UINT32             length;

    /* send event to upper layer of this data link connection to allocate buffer */
    evt_data.alloc.conn_handle = (NFA_HANDLE_GROUP_SNEP | dlink);
    evt_data.alloc.req_code    = nfa_snep_cb.conn[dlink].rx_code;
    evt_data.alloc.ndef_length = nfa_snep_cb.conn[dlink].ndef_length;
    evt_data.alloc.p_buff      = NULL;

    nfa_snep_cb.conn[dlink].p_cback (NFA_SNEP_ALLOC_BUFF_EVT, &evt_data);
    nfa_snep_cb.conn[dlink].p_ndef_buff = evt_data.alloc.p_buff;

    /* store information into application buffer */
    if (nfa_snep_cb.conn[dlink].p_ndef_buff)
    {
        /* store buffer size */
        nfa_snep_cb.conn[dlink].buff_length = evt_data.alloc.ndef_length;

        more = LLCP_ReadDataLinkData (nfa_snep_cb.conn[dlink].local_sap,
                                      nfa_snep_cb.conn[dlink].remote_sap,
                                      nfa_snep_cb.conn[dlink].buff_length,
                                      &length,
                                      nfa_snep_cb.conn[dlink].p_ndef_buff);

        /* store received message length */
        nfa_snep_cb.conn[dlink].cur_length  = (UINT32) length;

        SNEP_TRACE_DEBUG2 ("Received NDEF on SNEP, %d ouf of %d",
                           nfa_snep_cb.conn[dlink].cur_length,
                           nfa_snep_cb.conn[dlink].ndef_length);

        /* if fragmented */
        if (nfa_snep_cb.conn[dlink].ndef_length > nfa_snep_cb.conn[dlink].cur_length)
        {
            nfa_snep_cb.conn[dlink].rx_fragments = TRUE;
        }
        else if (more)
        {
            /* ignore extra bytes in the message */
            length = LLCP_FlushDataLinkRxData (nfa_snep_cb.conn[dlink].local_sap,
                                               nfa_snep_cb.conn[dlink].remote_sap);

            SNEP_TRACE_WARNING1 ("Received extra %d bytes on SNEP", length);
        }

        return TRUE;
    }
    else
    {
        SNEP_TRACE_ERROR1 ("Upper layer cannot allocate buffer for %d bytes",
                           nfa_snep_cb.conn[dlink].ndef_length);

        /* clear data in data link connection */
        length = LLCP_FlushDataLinkRxData (nfa_snep_cb.conn[dlink].local_sap,
                                           nfa_snep_cb.conn[dlink].remote_sap);

        /* if fragmented */
        if (nfa_snep_cb.conn[dlink].ndef_length > nfa_snep_cb.conn[dlink].cur_length)
        {
            /* notify peer not to send any more fragment */
            if (evt_data.alloc.resp_code != NFA_SNEP_RESP_CODE_NOT_IMPLM)
            {
                /* Set proper code */
                evt_data.alloc.resp_code = NFA_SNEP_REQ_CODE_REJECT;
            }
        }
        else
        {
            if (evt_data.alloc.resp_code != NFA_SNEP_RESP_CODE_NOT_IMPLM)
            {
                /* Set proper code */
                evt_data.alloc.resp_code = NFA_SNEP_RESP_CODE_NOT_FOUND;
            }
        }

        nfa_snep_send_msg (evt_data.alloc.resp_code, dlink);

        return FALSE;
    }
}

/*******************************************************************************
**
** Function         nfa_snep_proc_first_rx_msg
**
** Description      Process the first part of received message
**
**
** Returns          TRUE if it is not fragmented message
**                  FALSE if it is fragmented or found error
**
*******************************************************************************/
BOOLEAN nfa_snep_proc_first_rx_msg (UINT8 dlink)
{
    UINT32             length;
    tNFA_SNEP_EVT_DATA evt_data;
    BOOLEAN            more;

    SNEP_TRACE_DEBUG0 ("nfa_snep_proc_first_rx_msg ()");

    /* if version, opcode or length is not valid in received message */
    if (!nfa_snep_validate_rx_msg (dlink))
    {
        /* clear data in data link connection */
        LLCP_FlushDataLinkRxData (nfa_snep_cb.conn[dlink].local_sap,
                                  nfa_snep_cb.conn[dlink].remote_sap);
        return FALSE;
    }

    if (nfa_snep_cb.conn[dlink].rx_code == NFA_SNEP_REQ_CODE_GET)
    {
        /* if failed to allocate buffer */
        if (!nfa_snep_store_first_rx_msg (dlink))
        {
            return FALSE;
        }
        else
        {
            if (nfa_snep_cb.conn[dlink].rx_fragments == TRUE)
            {
                /* let peer send remaining fragments */
                nfa_snep_send_msg (NFA_SNEP_RESP_CODE_CONTINUE, dlink);

                return FALSE;
            }
        }
    }
    else if (nfa_snep_cb.conn[dlink].rx_code == NFA_SNEP_REQ_CODE_PUT)
    {
        /* if failed to allocate buffer */
        if (!nfa_snep_store_first_rx_msg (dlink))
        {
            return FALSE;
        }
        else
        {
            if (nfa_snep_cb.conn[dlink].rx_fragments == TRUE)
            {
                /* let peer send remaining fragments */
                nfa_snep_send_msg (NFA_SNEP_RESP_CODE_CONTINUE, dlink);
                return FALSE;
            }
        }
    }
    /* if we got response of GET request from server */
    else if (  (nfa_snep_cb.conn[dlink].rx_code == NFA_SNEP_RESP_CODE_SUCCESS)
             &&(nfa_snep_cb.conn[dlink].tx_code == NFA_SNEP_REQ_CODE_GET)  )
    {
        /* if server is sending more than acceptable length */
        if (nfa_snep_cb.conn[dlink].ndef_length > nfa_snep_cb.conn[dlink].acceptable_length)
        {
            SNEP_TRACE_ERROR0 ("Server is sending more than acceptable length");

            length = LLCP_FlushDataLinkRxData (nfa_snep_cb.conn[dlink].local_sap,
                                               nfa_snep_cb.conn[dlink].remote_sap);

            /* if fragmented */
            if (nfa_snep_cb.conn[dlink].ndef_length > length)
            {
                nfa_snep_send_msg (NFA_SNEP_REQ_CODE_REJECT, dlink);
                nfa_snep_cb.conn[dlink].rx_fragments = FALSE;
            }

            /* return error to client so buffer can be freed */
            evt_data.get_resp.conn_handle = (NFA_HANDLE_GROUP_SNEP | dlink);
            evt_data.get_resp.resp_code   = NFA_SNEP_RESP_CODE_EXCESS_DATA;
            evt_data.get_resp.ndef_length = 0;
            evt_data.get_resp.p_ndef      = nfa_snep_cb.conn[dlink].p_ndef_buff;

            nfa_snep_cb.conn[dlink].p_cback (NFA_SNEP_GET_RESP_EVT, &evt_data);
            nfa_snep_cb.conn[dlink].p_ndef_buff = NULL;

            return FALSE;
        }

        more = LLCP_ReadDataLinkData (nfa_snep_cb.conn[dlink].local_sap,
                                      nfa_snep_cb.conn[dlink].remote_sap,
                                      nfa_snep_cb.conn[dlink].buff_length,
                                      &length,
                                      nfa_snep_cb.conn[dlink].p_ndef_buff);

        /* store received message length */
        nfa_snep_cb.conn[dlink].cur_length = length;

        SNEP_TRACE_DEBUG2 ("Received NDEF on SNEP, %d ouf of %d",
                           nfa_snep_cb.conn[dlink].cur_length,
                           nfa_snep_cb.conn[dlink].ndef_length);

        if (nfa_snep_cb.conn[dlink].ndef_length > nfa_snep_cb.conn[dlink].cur_length)
        {
            nfa_snep_cb.conn[dlink].rx_fragments = TRUE;
        }
        else if (more)
        {
            /* ignore extra bytes in the message */
            length = LLCP_FlushDataLinkRxData (nfa_snep_cb.conn[dlink].local_sap,
                                               nfa_snep_cb.conn[dlink].remote_sap);

            SNEP_TRACE_WARNING1 ("Received extra %d bytes on SNEP", length);
        }

        if (nfa_snep_cb.conn[dlink].rx_fragments == TRUE)
        {
            /* let peer send remaining fragments */
            nfa_snep_send_msg (NFA_SNEP_REQ_CODE_CONTINUE, dlink);

            /* start timer for next fragment */
            nfa_sys_start_timer (&nfa_snep_cb.conn[dlink].timer, dlink, NFA_SNEP_CLIENT_TIMEOUT);

            return FALSE;
        }
    }

    /* other than above cases, there is no inforamtion field */

    return TRUE;
}

/*******************************************************************************
**
** Function         nfa_snep_assemble_fragments
**
** Description      Assemble fragments of SNEP message
**
**
** Returns          TRUE if it is not fragmented message
**                  FALSE if it is fragmented or found error
**
*******************************************************************************/
BOOLEAN nfa_snep_assemble_fragments (UINT8 dlink)
{
    BOOLEAN more;
    UINT32  length;

    more = LLCP_ReadDataLinkData (nfa_snep_cb.conn[dlink].local_sap,
                                  nfa_snep_cb.conn[dlink].remote_sap,
                                  nfa_snep_cb.conn[dlink].buff_length - nfa_snep_cb.conn[dlink].cur_length,
                                  &length,
                                  nfa_snep_cb.conn[dlink].p_ndef_buff + nfa_snep_cb.conn[dlink].cur_length);

    nfa_snep_cb.conn[dlink].cur_length += length;

    SNEP_TRACE_DEBUG2 ("Received NDEF on SNEP, %d ouf of %d",
                       nfa_snep_cb.conn[dlink].cur_length,
                       nfa_snep_cb.conn[dlink].ndef_length);

    /* if received the last fragment */
    if (nfa_snep_cb.conn[dlink].ndef_length == nfa_snep_cb.conn[dlink].cur_length)
    {
        nfa_snep_cb.conn[dlink].rx_fragments = FALSE;

        if (more)
        {
            length = LLCP_FlushDataLinkRxData (nfa_snep_cb.conn[dlink].local_sap,
                                               nfa_snep_cb.conn[dlink].remote_sap);

            SNEP_TRACE_ERROR2 ("Received extra %d bytes more than NDEF length (%d)",
                               length,
                               nfa_snep_cb.conn[dlink].ndef_length);

            /* application will free buffer when receiving NFA_SNEP_DISC_EVT */
            nfa_snep_cb.conn[dlink].p_ndef_buff = NULL;

            LLCP_DisconnectReq (nfa_snep_cb.conn[dlink].local_sap,
                                nfa_snep_cb.conn[dlink].remote_sap, TRUE);

            return FALSE;
        }
    }
    else
    {
        if (nfa_snep_cb.conn[dlink].flags & NFA_SNEP_FLAG_CLIENT)
        {
            /* wait for more fragments */
            nfa_sys_start_timer (&nfa_snep_cb.conn[dlink].timer, dlink, NFA_SNEP_CLIENT_TIMEOUT);
        }

        return FALSE;
    }

    return TRUE;
}

/*******************************************************************************
**
** Function         nfa_snep_proc_llcp_data_ind
**
** Description      Processing incoming data from LLCP
**
**
** Returns          None
**
*******************************************************************************/
void nfa_snep_proc_llcp_data_ind (tLLCP_SAP_CBACK_DATA  *p_data)
{
    UINT8              dlink;
    tNFA_SNEP_EVT_DATA evt_data;

    SNEP_TRACE_DEBUG0 ("nfa_snep_proc_llcp_data_ind ()");

    /* find connection control block with SAP */
    dlink = nfa_snep_sap_to_index (p_data->data_ind.local_sap,
                                   p_data->data_ind.remote_sap,
                                   NFA_SNEP_FLAG_ANY);

    /* if found */
    if (  (dlink < NFA_SNEP_MAX_CONN)
        &&(nfa_snep_cb.conn[dlink].flags & NFA_SNEP_FLAG_CONNECTED)  )
    {
        if (nfa_snep_cb.conn[dlink].flags & NFA_SNEP_FLAG_CLIENT)
        {
            /* stop timer for response from server */
            nfa_sys_stop_timer (&nfa_snep_cb.conn[dlink].timer);
        }

        /* if received the first fragment or complete SNEP message */
        if (nfa_snep_cb.conn[dlink].rx_fragments == FALSE)
        {
            if (!nfa_snep_proc_first_rx_msg (dlink))
            {
                /* need more data or found error */
                return;
            }
        }
        /* if received other than the first fragment */
        else
        {
            if (!nfa_snep_assemble_fragments (dlink))
            {
                /* need more data or found error */
                return;
            }
        }

        /* processing complete SNEP message */
        switch (nfa_snep_cb.conn[dlink].rx_code)
        {
        case NFA_SNEP_REQ_CODE_CONTINUE:
            if (nfa_snep_cb.conn[dlink].flags & NFA_SNEP_FLAG_W4_REQ_CONTINUE)
            {
                nfa_snep_cb.conn[dlink].flags &= ~NFA_SNEP_FLAG_W4_REQ_CONTINUE;

                /* send remaining fragments of GET response */
                nfa_snep_send_remaining (dlink);
            }
            else
            {
                SNEP_TRACE_ERROR0 ("Received invalid NFA_SNEP_REQ_CODE_CONTINUE");

                /* application will free buffer when receiving NFA_SNEP_DISC_EVT */
                nfa_snep_cb.conn[dlink].p_ndef_buff = NULL;

                LLCP_DisconnectReq (nfa_snep_cb.conn[dlink].local_sap,
                                    nfa_snep_cb.conn[dlink].remote_sap, TRUE);
            }
            break;

        case NFA_SNEP_REQ_CODE_GET:
            evt_data.get_req.conn_handle       = (NFA_HANDLE_GROUP_SNEP | dlink);
            evt_data.get_req.acceptable_length = nfa_snep_cb.conn[dlink].acceptable_length;

            /* NDEF message */
            evt_data.get_req.ndef_length = nfa_snep_cb.conn[dlink].ndef_length;
            evt_data.get_req.p_ndef      = nfa_snep_cb.conn[dlink].p_ndef_buff;

            nfa_snep_cb.conn[dlink].p_ndef_buff = NULL;

            /* send event to server of this data link connection */
            nfa_snep_cb.conn[dlink].p_cback (NFA_SNEP_GET_REQ_EVT, &evt_data);
            break;

        case NFA_SNEP_REQ_CODE_PUT:
            evt_data.put_req.conn_handle = (NFA_HANDLE_GROUP_SNEP | dlink);

            /* NDEF message */
            evt_data.put_req.ndef_length = nfa_snep_cb.conn[dlink].ndef_length;
            evt_data.put_req.p_ndef      = nfa_snep_cb.conn[dlink].p_ndef_buff;

            nfa_snep_cb.conn[dlink].p_ndef_buff = NULL;

            /* send event to server of this data link connection */
            nfa_snep_cb.conn[dlink].p_cback (NFA_SNEP_PUT_REQ_EVT, &evt_data);
            break;

        case NFA_SNEP_RESP_CODE_CONTINUE:
            if (nfa_snep_cb.conn[dlink].flags & NFA_SNEP_FLAG_W4_RESP_CONTINUE)
            {
                nfa_snep_cb.conn[dlink].flags &= ~NFA_SNEP_FLAG_W4_RESP_CONTINUE;
                /* send remaining fragments GET/PUT request */
                nfa_snep_send_remaining (dlink);
            }
            else
            {
                SNEP_TRACE_ERROR0 ("Received invalid NFA_SNEP_RESP_CODE_CONTINUE");

                /* application will free buffer when receiving NFA_SNEP_DISC_EVT */
                nfa_snep_cb.conn[dlink].p_ndef_buff = NULL;

                LLCP_DisconnectReq (nfa_snep_cb.conn[dlink].local_sap,
                                    nfa_snep_cb.conn[dlink].remote_sap, TRUE);
            }
            break;

        case NFA_SNEP_RESP_CODE_SUCCESS:
            if (nfa_snep_cb.conn[dlink].tx_code == NFA_SNEP_REQ_CODE_GET)
            {
                evt_data.get_resp.conn_handle = (NFA_HANDLE_GROUP_SNEP | dlink);
                evt_data.get_resp.resp_code   = NFA_SNEP_RESP_CODE_SUCCESS;
                evt_data.get_resp.ndef_length = nfa_snep_cb.conn[dlink].ndef_length;
                evt_data.get_resp.p_ndef      = nfa_snep_cb.conn[dlink].p_ndef_buff;

                nfa_snep_cb.conn[dlink].p_ndef_buff = NULL;

                /* send event to client of this data link connection */
                nfa_snep_cb.conn[dlink].p_cback (NFA_SNEP_GET_RESP_EVT, &evt_data);
            }
            else
            {
                evt_data.put_resp.conn_handle = (NFA_HANDLE_GROUP_SNEP | dlink);
                evt_data.put_resp.resp_code   = NFA_SNEP_RESP_CODE_SUCCESS;

                /* send event to client of this data link connection */
                nfa_snep_cb.conn[dlink].p_cback (NFA_SNEP_PUT_RESP_EVT, &evt_data);
            }
            break;

        case NFA_SNEP_RESP_CODE_NOT_FOUND:
        case NFA_SNEP_RESP_CODE_EXCESS_DATA:
        case NFA_SNEP_RESP_CODE_BAD_REQ:
        case NFA_SNEP_RESP_CODE_NOT_IMPLM:
        case NFA_SNEP_RESP_CODE_UNSUPP_VER:
        case NFA_SNEP_RESP_CODE_REJECT:
            /* if client sent GET request */
            if (nfa_snep_cb.conn[dlink].tx_code == NFA_SNEP_REQ_CODE_GET)
            {
                evt_data.get_resp.conn_handle = (NFA_HANDLE_GROUP_SNEP | dlink);
                evt_data.get_resp.resp_code   = nfa_snep_cb.conn[dlink].rx_code;
                evt_data.get_resp.ndef_length = 0;
                evt_data.get_resp.p_ndef      = nfa_snep_cb.conn[dlink].p_ndef_buff;

                /* send event to client of this data link connection */
                nfa_snep_cb.conn[dlink].p_cback (NFA_SNEP_GET_RESP_EVT, &evt_data);
            }
            /* if client sent PUT request */
            else if (nfa_snep_cb.conn[dlink].tx_code == NFA_SNEP_REQ_CODE_PUT)
            {
                evt_data.put_resp.conn_handle = (NFA_HANDLE_GROUP_SNEP | dlink);
                evt_data.put_resp.resp_code   = nfa_snep_cb.conn[dlink].rx_code;

                /* send event to client of this data link connection */
                nfa_snep_cb.conn[dlink].p_cback (NFA_SNEP_PUT_RESP_EVT, &evt_data);
            }

            /* if there is remaining SNEP message */
            if (nfa_snep_cb.conn[dlink].p_ndef_buff)
            {
                nfa_snep_cb.conn[dlink].p_ndef_buff = NULL;
            }
            break;
        }
    }
}

/*******************************************************************************
**
** Function         nfa_snep_proc_llcp_connect_ind
**
** Description      Processing connection request from peer
**
**
** Returns          None
**
*******************************************************************************/
void nfa_snep_proc_llcp_connect_ind (tLLCP_SAP_CBACK_DATA  *p_data)
{
    UINT8 server, dlink;
    tLLCP_CONNECTION_PARAMS params;
    tNFA_SNEP_EVT_DATA      evt_data;

    SNEP_TRACE_DEBUG0 ("nfa_snep_proc_llcp_connect_ind ()");

    server = nfa_snep_sap_to_index (p_data->connect_ind.server_sap,
                                    NFA_SNEP_ANY_SAP,
                                    NFA_SNEP_FLAG_SERVER);

    /* if found valid server */
    if (server < NFA_SNEP_MAX_CONN)
    {
        /* allocate connection control block for data link connection */
        dlink = nfa_snep_allocate_cb ();

        if (dlink < NFA_SNEP_MAX_CONN)
        {
            /* set data link connection's callback to server's callback */
            /* request will be sent to this server */
            nfa_snep_cb.conn[dlink].local_sap  = p_data->connect_ind.local_sap;
            nfa_snep_cb.conn[dlink].remote_sap = p_data->connect_ind.remote_sap;
            nfa_snep_cb.conn[dlink].p_cback    = nfa_snep_cb.conn[server].p_cback;
            nfa_snep_cb.conn[dlink].flags      = NFA_SNEP_FLAG_SERVER|NFA_SNEP_FLAG_CONNECTED;

            nfa_snep_cb.conn[dlink].tx_miu = nfa_snep_get_efficent_miu (p_data->connect_ind.miu,
                                                                        p_data->connect_ind.rw);

            /* accept connection request */
            params.miu = NFA_SNEP_MIU;
            params.rw  = NFA_SNEP_RW;
            params.sn[0] = 0;

            LLCP_ConnectCfm (p_data->connect_ind.local_sap,
                             p_data->connect_ind.remote_sap, &params);

            evt_data.connect.reg_handle  = (NFA_HANDLE_GROUP_SNEP | server);
            evt_data.connect.conn_handle = (NFA_HANDLE_GROUP_SNEP | dlink);
            nfa_snep_cb.conn[dlink].p_cback (NFA_SNEP_CONNECTED_EVT, &evt_data);
        }
        else
        {
            SNEP_TRACE_ERROR0 ("Cannot allocate connection control block");
            LLCP_ConnectReject (p_data->connect_ind.local_sap,
                                p_data->connect_ind.remote_sap,
                                LLCP_SAP_DM_REASON_TEMP_REJECT_THIS);
        }
    }
    else
    {
        SNEP_TRACE_ERROR0 ("Cannot find SNEP server");
        LLCP_ConnectReject (p_data->connect_ind.local_sap,
                            p_data->connect_ind.remote_sap,
                            LLCP_SAP_DM_REASON_NO_SERVICE);
    }
}

/*******************************************************************************
**
** Function         nfa_snep_proc_llcp_connect_resp
**
** Description      Processing connection response from peer
**
**
** Returns          None
**
*******************************************************************************/
void nfa_snep_proc_llcp_connect_resp (tLLCP_SAP_CBACK_DATA  *p_data)
{
    UINT8 dlink;
    tNFA_SNEP_EVT_DATA evt_data;

    SNEP_TRACE_DEBUG0 ("nfa_snep_proc_llcp_connect_resp ()");

    /* find client by SAP */
    dlink = nfa_snep_sap_to_index (p_data->connect_resp.local_sap,
                                   NFA_SNEP_ANY_SAP,
                                   NFA_SNEP_FLAG_CLIENT|NFA_SNEP_FLAG_CONNECTING);

    /* if found client */
    if (dlink < NFA_SNEP_MAX_CONN)
    {
        nfa_snep_cb.conn[dlink].remote_sap = p_data->connect_resp.remote_sap;
        nfa_snep_cb.conn[dlink].flags      = NFA_SNEP_FLAG_CLIENT|NFA_SNEP_FLAG_CONNECTED;

        nfa_snep_cb.conn[dlink].tx_miu = nfa_snep_get_efficent_miu (p_data->connect_resp.miu,
                                                                    p_data->connect_resp.rw);

        evt_data.connect.reg_handle  = (NFA_HANDLE_GROUP_SNEP | dlink);
        evt_data.connect.conn_handle = (NFA_HANDLE_GROUP_SNEP | dlink);
        nfa_snep_cb.conn[dlink].p_cback (NFA_SNEP_CONNECTED_EVT, &evt_data);
    }
    else
    {
        SNEP_TRACE_ERROR0 ("Cannot find SNEP client");
        LLCP_DisconnectReq (p_data->connect_resp.local_sap,
                            p_data->connect_resp.remote_sap, TRUE);
    }
}

/*******************************************************************************
**
** Function         nfa_snep_proc_llcp_disconnect_ind
**
** Description      Processing disconnection request from peer
**
**
** Returns          None
**
*******************************************************************************/
void nfa_snep_proc_llcp_disconnect_ind (tLLCP_SAP_CBACK_DATA  *p_data)
{
    UINT8              dlink;
    tNFA_SNEP_EVT_DATA evt_data;

    SNEP_TRACE_DEBUG0 ("nfa_snep_proc_llcp_disconnect_ind ()");

    /* find connection control block by SAP */
    dlink = nfa_snep_sap_to_index (p_data->disconnect_ind.local_sap,
                                   p_data->disconnect_ind.remote_sap,
                                   NFA_SNEP_FLAG_ANY);

    /* if found */
    if (dlink < NFA_SNEP_MAX_CONN)
    {
        evt_data.disc.conn_handle = (NFA_HANDLE_GROUP_SNEP | dlink);

        nfa_snep_cb.conn[dlink].p_cback (NFA_SNEP_DISC_EVT, &evt_data);

        if (nfa_snep_cb.conn[dlink].flags & NFA_SNEP_FLAG_CLIENT)
        {
            /* clear other flags */
            nfa_snep_cb.conn[dlink].flags      = NFA_SNEP_FLAG_CLIENT;
            nfa_snep_cb.conn[dlink].remote_sap = LLCP_INVALID_SAP;
        }
        else
        {
            nfa_snep_deallocate_cb (dlink);
        }
    }
    else
    {
        SNEP_TRACE_ERROR0 ("Cannot find SNEP connection");
    }
}

/*******************************************************************************
**
** Function         nfa_snep_proc_llcp_disconnect_resp
**
** Description      Processing rejected connection from peer
**
**
** Returns          None
**
*******************************************************************************/
void nfa_snep_proc_llcp_disconnect_resp (tLLCP_SAP_CBACK_DATA  *p_data)
{
    UINT8              dlink, flags;
    UINT8              remote_sap;
    tNFA_SNEP_EVT_DATA evt_data;

    SNEP_TRACE_DEBUG0 ("nfa_snep_proc_llcp_disconnect_resp ()");

    /* if remote sent response to disconnection requested by local */
    if (p_data->disconnect_resp.reason == LLCP_SAP_DM_REASON_RESP_DISC)
    {
        remote_sap = p_data->disconnect_resp.remote_sap;
        flags      = NFA_SNEP_FLAG_CLIENT|NFA_SNEP_FLAG_CONNECTED;
    }
    else /* connection failed so we don't have remote SAP */
    {
        remote_sap = NFA_SNEP_ANY_SAP;
        flags      = NFA_SNEP_FLAG_CLIENT|NFA_SNEP_FLAG_CONNECTING;
    }

    /* find connection control block by SAP */
    dlink = nfa_snep_sap_to_index (p_data->disconnect_resp.local_sap,
                                   remote_sap,
                                   flags);

    /* if found client */
    if (dlink < NFA_SNEP_MAX_CONN)
    {
        evt_data.disc.conn_handle = (NFA_HANDLE_GROUP_SNEP | dlink);

        nfa_snep_cb.conn[dlink].p_cback (NFA_SNEP_DISC_EVT, &evt_data);

        /* clear other flags */
        nfa_snep_cb.conn[dlink].flags      = NFA_SNEP_FLAG_CLIENT;
        nfa_snep_cb.conn[dlink].remote_sap = LLCP_INVALID_SAP;
    }
    else
    {
        /* find server connection control block by SAP */
        dlink = nfa_snep_sap_to_index (p_data->disconnect_resp.local_sap,
                                       remote_sap,
                                       NFA_SNEP_FLAG_SERVER|NFA_SNEP_FLAG_CONNECTED);

        /* if found server connection */
        if (dlink < NFA_SNEP_MAX_CONN)
        {
            evt_data.disc.conn_handle = (NFA_HANDLE_GROUP_SNEP | dlink);

            nfa_snep_cb.conn[dlink].p_cback (NFA_SNEP_DISC_EVT, &evt_data);

            nfa_snep_deallocate_cb (dlink);
        }
        else
        {
            SNEP_TRACE_ERROR0 ("Cannot find SNEP connection");
        }
    }
}

/*******************************************************************************
**
** Function         nfa_snep_proc_llcp_congest
**
** Description      Processing LLCP congestion event
**
**
** Returns          None
**
*******************************************************************************/
void nfa_snep_proc_llcp_congest (tLLCP_SAP_CBACK_DATA  *p_data)
{
    UINT8 dlink;

    SNEP_TRACE_DEBUG3 ("nfa_snep_proc_llcp_congest () local_sap=0x%x, remote_sap=0x%x, is_congested=%d",
                       p_data->congest.local_sap,
                       p_data->congest.remote_sap,
                       p_data->congest.is_congested);

    /* if data link connection is congested */
    if (p_data->congest.link_type == LLCP_LINK_TYPE_DATA_LINK_CONNECTION)
    {
        dlink = nfa_snep_sap_to_index (p_data->congest.local_sap,
                                       p_data->congest.remote_sap,
                                       NFA_SNEP_FLAG_ANY);

        if (  (dlink < NFA_SNEP_MAX_CONN)
            &&(nfa_snep_cb.conn[dlink].flags & NFA_SNEP_FLAG_CONNECTED)  )
        {
            nfa_snep_cb.conn[dlink].congest = p_data->congest.is_congested;

            if (!nfa_snep_cb.conn[dlink].congest)
            {
                /* if received CONTINUE then continue to send remaining fragments */
                if (  (nfa_snep_cb.conn[dlink].rx_code == NFA_SNEP_REQ_CODE_CONTINUE)
                    ||(nfa_snep_cb.conn[dlink].rx_code == NFA_SNEP_RESP_CODE_CONTINUE)  )
                {
                    nfa_snep_send_remaining (dlink);
                }
            }
        }
    }
}

/*******************************************************************************
**
** Function         nfa_snep_proc_llcp_link_status
**
** Description      Processing LLCP link status
**
**
** Returns          none
**
*******************************************************************************/
void nfa_snep_proc_llcp_link_status (tLLCP_SAP_CBACK_DATA  *p_data)
{
    UINT8              xx;
    tNFA_SNEP_EVT_DATA evt_data;

    SNEP_TRACE_DEBUG1 ("nfa_snep_proc_llcp_link_status () is_activated:%d",
                       p_data->link_status.is_activated);

    xx = nfa_snep_sap_to_index (p_data->link_status.local_sap,
                                NFA_SNEP_ANY_SAP,
                                NFA_SNEP_FLAG_CLIENT);

    if (xx < NFA_SNEP_MAX_CONN)
    {
        evt_data.activated.client_handle = (NFA_HANDLE_GROUP_SNEP | xx);

        /* if LLCP link is activated */
        if (p_data->link_status.is_activated == TRUE)
        {
            /* notify only client which may want to connect */
            nfa_snep_cb.conn[xx].p_cback (NFA_SNEP_ACTIVATED_EVT, &evt_data);
        }
        else
        {
            /* LLCP link is deactivated */
            nfa_snep_cb.conn[xx].p_cback (NFA_SNEP_DEACTIVATED_EVT, &evt_data);
        }
    }
}

/*******************************************************************************
**
** Function         nfa_snep_proc_llcp_tx_complete
**
** Description      Processing LLCP tx complete event
**
**
** Returns          none
**
*******************************************************************************/
void nfa_snep_proc_llcp_tx_complete (tLLCP_SAP_CBACK_DATA  *p_data)
{
    UINT8              dlink;
    tNFA_SNEP_EVT_DATA evt_data;

    SNEP_TRACE_DEBUG0 ("nfa_snep_proc_llcp_tx_complete ()");

    dlink = nfa_snep_sap_to_index (p_data->tx_complete.local_sap,
                                   p_data->tx_complete.remote_sap,
                                   NFA_SNEP_FLAG_SERVER|NFA_SNEP_FLAG_CONNECTED);

    if (dlink < NFA_SNEP_MAX_CONN)
    {
        /* notify upper layer that transmission is complete */
        evt_data.get_resp_cmpl.conn_handle = (NFA_HANDLE_GROUP_SNEP | dlink);
        evt_data.get_resp_cmpl.p_buff      = nfa_snep_cb.conn[dlink].p_ndef_buff;

        nfa_snep_cb.conn[dlink].p_cback (NFA_SNEP_GET_RESP_CMPL_EVT, &evt_data);
        nfa_snep_cb.conn[dlink].p_ndef_buff = NULL;
    }
}

/*******************************************************************************
**
** Function         nfa_snep_reg_server
**
** Description      Allocate a connection control block as server and register to LLCP
**
**
** Returns          TRUE to deallocate message
**
*******************************************************************************/
BOOLEAN nfa_snep_reg_server (tNFA_SNEP_MSG *p_msg)
{
    tNFA_SNEP_EVT_DATA  evt_data;
    UINT8               xx, local_sap = LLCP_INVALID_SAP;

    SNEP_TRACE_DEBUG0 ("nfa_snep_reg_server ()");

    xx = nfa_snep_allocate_cb ();

    if (xx < NFA_SNEP_MAX_CONN)
    {
        local_sap = LLCP_RegisterServer (p_msg->api_reg_server.server_sap,
                                         LLCP_LINK_TYPE_DATA_LINK_CONNECTION,
                                         p_msg->api_reg_server.service_name,
                                         nfa_snep_llcp_cback);
    }

    BCM_STRNCPY_S (evt_data.reg.service_name, sizeof (evt_data.reg.service_name),
                   p_msg->api_reg_server.service_name, LLCP_MAX_SN_LEN);
    evt_data.reg.service_name[LLCP_MAX_SN_LEN] = 0x00;

    if ((xx == NFA_SNEP_MAX_CONN) || (local_sap == LLCP_INVALID_SAP))
    {
        SNEP_TRACE_ERROR0 ("Cannot allocate or register SNEP server");

        evt_data.reg.status = NFA_STATUS_FAILED;
        p_msg->api_reg_server.p_cback (NFA_SNEP_REG_EVT, &evt_data);
        return TRUE;
    }

    if (!nfa_snep_cb.is_dta_mode)
    {
        /* if need to update WKS in LLCP Gen bytes */
        if (local_sap <= LLCP_UPPER_BOUND_WK_SAP)
        {
            nfa_p2p_enable_listening (NFA_ID_SNEP, TRUE);
            nfa_snep_cb.listen_enabled = TRUE;
        }
        else if (!nfa_snep_cb.listen_enabled)
        {
            nfa_p2p_enable_listening (NFA_ID_SNEP, FALSE);
            nfa_snep_cb.listen_enabled = TRUE;
        }
    }

    nfa_snep_cb.conn[xx].local_sap  = local_sap;
    nfa_snep_cb.conn[xx].remote_sap = LLCP_INVALID_SAP;
    nfa_snep_cb.conn[xx].p_cback    = p_msg->api_reg_server.p_cback;
    nfa_snep_cb.conn[xx].flags      = NFA_SNEP_FLAG_SERVER;

    evt_data.reg.status     = NFA_STATUS_OK;
    evt_data.reg.reg_handle = (NFA_HANDLE_GROUP_SNEP | xx);

    /* notify NFA_SNEP_REG_EVT to application */
    nfa_snep_cb.conn[xx].p_cback (NFA_SNEP_REG_EVT, &evt_data);

    return TRUE;
}

/*******************************************************************************
**
** Function         nfa_snep_reg_client
**
** Description      Allocate a connection control block as client and register to LLCP
**
**
** Returns          TRUE to deallocate message
**
*******************************************************************************/
BOOLEAN nfa_snep_reg_client (tNFA_SNEP_MSG *p_msg)
{
    tNFA_SNEP_EVT_DATA  evt_data;
    UINT8               xx, local_sap = LLCP_INVALID_SAP;

    SNEP_TRACE_DEBUG0 ("nfa_snep_reg_client ()");

    xx = nfa_snep_allocate_cb ();

    if (xx < NFA_SNEP_MAX_CONN)
    {
        local_sap = LLCP_RegisterClient (LLCP_LINK_TYPE_DATA_LINK_CONNECTION,
                                         nfa_snep_llcp_cback);
    }

    evt_data.reg.service_name[0] = 0x00;

    if ((xx == NFA_SNEP_MAX_CONN) || (local_sap == LLCP_INVALID_SAP))
    {
        SNEP_TRACE_ERROR0 ("Cannot allocate or register SNEP client");

        evt_data.reg.status = NFA_STATUS_FAILED;
        p_msg->api_reg_client.p_cback (NFA_SNEP_REG_EVT, &evt_data);
        return TRUE;
    }

    nfa_snep_cb.conn[xx].local_sap  = local_sap;
    nfa_snep_cb.conn[xx].remote_sap = LLCP_INVALID_SAP;
    nfa_snep_cb.conn[xx].p_cback    = p_msg->api_reg_client.p_cback;
    nfa_snep_cb.conn[xx].flags      = NFA_SNEP_FLAG_CLIENT;

    /* initialize timer callback */
    nfa_snep_cb.conn[xx].timer.p_cback = nfa_snep_timer_cback;

    evt_data.reg.status     = NFA_STATUS_OK;
    evt_data.reg.reg_handle = (NFA_HANDLE_GROUP_SNEP | xx);

    /* notify NFA_SNEP_REG_EVT to application */
    nfa_snep_cb.conn[xx].p_cback (NFA_SNEP_REG_EVT, &evt_data);

    return TRUE;
}

/*******************************************************************************
**
** Function         nfa_snep_dereg
**
** Description      Deallocate a connection control block and deregister to LLCP
**                  LLCP will deallocate any data link connection created for this
**
** Returns          TRUE to deallocate message
**
*******************************************************************************/
BOOLEAN nfa_snep_dereg (tNFA_SNEP_MSG *p_msg)
{
    UINT8 xx;
    UINT8 local_sap;

    SNEP_TRACE_DEBUG0 ("nfa_snep_dereg ()");

    xx = (UINT8) (p_msg->api_dereg.reg_handle & NFA_HANDLE_MASK);

    if (  (xx < NFA_SNEP_MAX_CONN)
        &&(nfa_snep_cb.conn[xx].p_cback)
        &&(nfa_snep_cb.conn[xx].flags & (NFA_SNEP_FLAG_SERVER|NFA_SNEP_FLAG_CLIENT))  )
    {
        local_sap = nfa_snep_cb.conn[xx].local_sap;
        LLCP_Deregister (local_sap);
        nfa_snep_deallocate_cb (xx);
    }
    else
    {
        SNEP_TRACE_ERROR0 ("Cannot find SNEP server/client");
        return TRUE;
    }

    if (!nfa_snep_cb.is_dta_mode)
    {
        if (nfa_snep_cb.listen_enabled)
        {
            for (xx = 0; xx < NFA_SNEP_MAX_CONN; xx++)
            {
                if (  (nfa_snep_cb.conn[xx].p_cback)
                    &&(nfa_snep_cb.conn[xx].flags & NFA_SNEP_FLAG_SERVER)  )
                {
                    break;
                }
            }

            if (xx >= NFA_SNEP_MAX_CONN)
            {
                /* if need to update WKS in LLCP Gen bytes */
                if (local_sap <= LLCP_UPPER_BOUND_WK_SAP)
                    nfa_p2p_disable_listening (NFA_ID_SNEP, TRUE);
                else
                    nfa_p2p_disable_listening (NFA_ID_SNEP, FALSE);

                nfa_snep_cb.listen_enabled = FALSE;
            }
            /* if need to update WKS in LLCP Gen bytes */
            else if (local_sap <= LLCP_UPPER_BOUND_WK_SAP)
            {
                nfa_p2p_enable_listening (NFA_ID_SNEP, TRUE);
            }
        }
    }
    return TRUE;
}

/*******************************************************************************
**
** Function         nfa_snep_connect
**
** Description      Create data link connection for client
**
** Returns          TRUE to deallocate message
**
*******************************************************************************/
BOOLEAN nfa_snep_connect (tNFA_SNEP_MSG *p_msg)
{
    tLLCP_CONNECTION_PARAMS conn_params;
    UINT8 xx;

    SNEP_TRACE_DEBUG0 ("nfa_snep_connect ()");

    xx = (UINT8) (p_msg->api_connect.client_handle & NFA_HANDLE_MASK);

    if (xx < NFA_SNEP_MAX_CONN)
    {
        nfa_snep_cb.conn[xx].congest = FALSE;

        /* Set remote_sap to SDP to find callback in case that link is deactivted before connected */
        nfa_snep_cb.conn[xx].remote_sap = LLCP_SAP_SDP;

        /* in order to send NFA_SNEP_DISC_EVT in case of connection failure */
        nfa_snep_cb.conn[xx].flags = NFA_SNEP_FLAG_CLIENT|NFA_SNEP_FLAG_CONNECTING;

        /* create data link connection with server name */
        conn_params.miu = NFA_SNEP_MIU;
        conn_params.rw  = NFA_SNEP_RW;
        BCM_STRNCPY_S (conn_params.sn, sizeof (conn_params.sn),
                       p_msg->api_connect.service_name, LLCP_MAX_SN_LEN);
        conn_params.sn[LLCP_MAX_SN_LEN] = 0;

        LLCP_ConnectReq (nfa_snep_cb.conn[xx].local_sap, LLCP_SAP_SDP, &conn_params);
    }
    return TRUE;
}

/*******************************************************************************
**
** Function         nfa_snep_get_req
**
** Description      Send SNEP GET request on data link connection
**
** Returns          TRUE to deallocate message
**
*******************************************************************************/
BOOLEAN nfa_snep_get_req (tNFA_SNEP_MSG *p_msg)
{
    UINT8 dlink;

    SNEP_TRACE_DEBUG0 ("nfa_snep_get_req ()");

    dlink = (UINT8) (p_msg->api_get_req.conn_handle & NFA_HANDLE_MASK);

    if (  (dlink < NFA_SNEP_MAX_CONN)
        &&(nfa_snep_cb.conn[dlink].flags & NFA_SNEP_FLAG_CONNECTED)  )
    {
        nfa_snep_cb.conn[dlink].tx_code           = NFA_SNEP_REQ_CODE_GET;
        nfa_snep_cb.conn[dlink].buff_length       = p_msg->api_get_req.buff_length;
        nfa_snep_cb.conn[dlink].ndef_length       = p_msg->api_get_req.ndef_length;
        nfa_snep_cb.conn[dlink].p_ndef_buff       = p_msg->api_get_req.p_ndef_buff;
        nfa_snep_cb.conn[dlink].acceptable_length = p_msg->api_get_req.buff_length;

        nfa_snep_send_msg (NFA_SNEP_REQ_CODE_GET, dlink);

        /* start timer for response from server */
        nfa_sys_start_timer (&nfa_snep_cb.conn[dlink].timer, dlink, NFA_SNEP_CLIENT_TIMEOUT);
    }
    else
    {
        SNEP_TRACE_ERROR0 ("Data link connection is not established");
    }
    return TRUE;
}

/*******************************************************************************
**
** Function         nfa_snep_put_req
**
** Description      Send SNEP PUT request on data link connection
**
** Returns          TRUE to deallocate message
**
*******************************************************************************/
BOOLEAN nfa_snep_put_req (tNFA_SNEP_MSG *p_msg)
{
    UINT8 dlink;

    SNEP_TRACE_DEBUG0 ("nfa_snep_put_req ()");

    dlink = (UINT8) (p_msg->api_put_req.conn_handle & NFA_HANDLE_MASK);

    if (  (dlink < NFA_SNEP_MAX_CONN)
        &&(nfa_snep_cb.conn[dlink].flags & NFA_SNEP_FLAG_CONNECTED)  )
    {
        nfa_snep_cb.conn[dlink].tx_code     = NFA_SNEP_REQ_CODE_PUT;
        nfa_snep_cb.conn[dlink].buff_length = p_msg->api_put_req.ndef_length;
        nfa_snep_cb.conn[dlink].ndef_length = p_msg->api_put_req.ndef_length;
        nfa_snep_cb.conn[dlink].p_ndef_buff = p_msg->api_put_req.p_ndef_buff;

        nfa_snep_send_msg (NFA_SNEP_REQ_CODE_PUT, dlink);

        /* start timer for response from server */
        nfa_sys_start_timer (&nfa_snep_cb.conn[dlink].timer, dlink, NFA_SNEP_CLIENT_TIMEOUT);
    }
    else
    {
        SNEP_TRACE_ERROR0 ("Data link connection is not established");
    }
    return TRUE;
}

/*******************************************************************************
**
** Function         nfa_snep_get_resp
**
** Description      Server responds to GET request
**
**
** Returns          TRUE to deallocate message
**
*******************************************************************************/
BOOLEAN nfa_snep_get_resp (tNFA_SNEP_MSG *p_msg)
{
    UINT8 dlink;

    SNEP_TRACE_DEBUG0 ("nfa_snep_get_resp ()");

    dlink = (UINT8) (p_msg->api_get_resp.conn_handle & NFA_HANDLE_MASK);

    if (  (dlink < NFA_SNEP_MAX_CONN)
        &&(nfa_snep_cb.conn[dlink].flags & NFA_SNEP_FLAG_CONNECTED)  )
    {
        nfa_snep_cb.conn[dlink].buff_length = p_msg->api_get_resp.ndef_length;
        nfa_snep_cb.conn[dlink].ndef_length = p_msg->api_get_resp.ndef_length;
        nfa_snep_cb.conn[dlink].p_ndef_buff = p_msg->api_get_resp.p_ndef_buff;

        nfa_snep_cb.conn[dlink].tx_code     = p_msg->api_get_resp.resp_code;

        nfa_snep_send_msg (p_msg->api_get_resp.resp_code, dlink);
    }
    else
    {
        SNEP_TRACE_ERROR0 ("Data link connection is not established");
    }
    return TRUE;
}

/*******************************************************************************
**
** Function         nfa_snep_put_resp
**
** Description      Server responds to PUT request
**
**
** Returns          TRUE to deallocate message
**
*******************************************************************************/
BOOLEAN nfa_snep_put_resp (tNFA_SNEP_MSG *p_msg)
{
    UINT8 dlink;

    SNEP_TRACE_DEBUG0 ("nfa_snep_put_resp ()");

    dlink = (UINT8) (p_msg->api_put_resp.conn_handle & NFA_HANDLE_MASK);

    if (  (dlink < NFA_SNEP_MAX_CONN)
        &&(nfa_snep_cb.conn[dlink].flags & NFA_SNEP_FLAG_CONNECTED)  )
    {
        nfa_snep_cb.conn[dlink].tx_code = p_msg->api_put_resp.resp_code;

        nfa_snep_send_msg (p_msg->api_put_resp.resp_code, dlink);
    }
    else
    {
        SNEP_TRACE_ERROR0 ("Data link connection is not established");
    }
    return TRUE;
}

/*******************************************************************************
**
** Function         nfa_snep_disconnect
**
** Description      Disconnect data link connection
**
**
** Returns          TRUE to deallocate message
**
*******************************************************************************/
BOOLEAN nfa_snep_disconnect (tNFA_SNEP_MSG *p_msg)
{
    UINT8 dlink;

    SNEP_TRACE_DEBUG0 ("nfa_snep_disconnect ()");

    dlink = (UINT8) (p_msg->api_disc.conn_handle & NFA_HANDLE_MASK);

    if (  (dlink < NFA_SNEP_MAX_CONN)
        &&(nfa_snep_cb.conn[dlink].flags & NFA_SNEP_FLAG_CONNECTED)  )
    {
        LLCP_DisconnectReq (nfa_snep_cb.conn[dlink].local_sap,
                            nfa_snep_cb.conn[dlink].remote_sap,
                            p_msg->api_disc.flush);
    }
    else
    {
        SNEP_TRACE_ERROR0 ("Data link connection is not established");
    }
    return TRUE;
}

#if (BT_TRACE_VERBOSE == TRUE)
/*******************************************************************************
**
** Function         nfa_snep_opcode
**
** Description
**
** Returns          string of event
**
*******************************************************************************/
static char *nfa_snep_opcode (UINT8 opcode)
{
    switch (opcode)
    {
    case NFA_SNEP_REQ_CODE_CONTINUE:
        return "REQ_CONTINUE";
    case NFA_SNEP_REQ_CODE_GET:
        return "REQ_GET";
    case NFA_SNEP_REQ_CODE_PUT:
        return "REQ_PUT";
    case NFA_SNEP_REQ_CODE_REJECT:
        return "REQ_REJECT";

    case NFA_SNEP_RESP_CODE_CONTINUE:
        return "RESP_CONTINUE";
    case NFA_SNEP_RESP_CODE_SUCCESS:
        return "RESP_SUCCESS";
    case NFA_SNEP_RESP_CODE_NOT_FOUND:
        return "RESP_NOT_FOUND";
    case NFA_SNEP_RESP_CODE_EXCESS_DATA:
        return "RESP_EXCESS_DATA";
    case NFA_SNEP_RESP_CODE_BAD_REQ:
        return "RESP_BAD_REQ";
    case NFA_SNEP_RESP_CODE_NOT_IMPLM:
        return "RESP_NOT_IMPLM";
    case NFA_SNEP_RESP_CODE_UNSUPP_VER:
        return "RESP_UNSUPP_VER";
    case NFA_SNEP_RESP_CODE_REJECT:
        return "RESP_REJECT";

    default:
        return "Reserved opcode";
    }
}

#endif  /* Debug Functions */