| /****************************************************************************** |
| * |
| * 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, ¶ms); |
| |
| 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 */ |
| |