| /****************************************************************************** |
| * |
| * 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. |
| * |
| ******************************************************************************/ |
| |
| /****************************************************************************** |
| * |
| * NFA interface for connection handover |
| * |
| ******************************************************************************/ |
| #include <string.h> |
| #include "nfc_api.h" |
| #include "nfa_sys.h" |
| #include "nfa_sys_int.h" |
| #include "nfa_p2p_api.h" |
| #include "nfa_cho_api.h" |
| #include "nfa_cho_int.h" |
| #include "nfa_mem_co.h" |
| |
| /***************************************************************************** |
| ** Constants |
| *****************************************************************************/ |
| |
| /******************************************************************************* |
| ** |
| ** Function NFA_ChoRegister |
| ** |
| ** Description This function is called to register callback function to receive |
| ** connection handover events. |
| ** |
| ** On this registration, "urn:nfc:sn:handover" server will be |
| ** registered on LLCP if enable_server is TRUE. |
| ** |
| ** The result of the registration is reported with NFA_CHO_REG_EVT. |
| ** |
| ** Note: If RF discovery is started, NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT |
| ** should happen before calling this function |
| ** |
| ** Returns NFA_STATUS_OK if successfully initiated |
| ** NFA_STATUS_FAILED otherwise |
| ** |
| *******************************************************************************/ |
| tNFA_STATUS NFA_ChoRegister (BOOLEAN enable_server, |
| tNFA_CHO_CBACK *p_cback) |
| { |
| tNFA_CHO_API_REG *p_msg; |
| |
| CHO_TRACE_API1 ("NFA_ChoRegister (): enable_server=%d", enable_server); |
| |
| if ( (nfa_cho_cb.state != NFA_CHO_ST_DISABLED) |
| ||(nfa_cho_cb.p_cback != NULL) ) |
| { |
| CHO_TRACE_ERROR0 ("NFA_ChoRegister (): Already registered or callback is not provided"); |
| return (NFA_STATUS_FAILED); |
| } |
| |
| if ((p_msg = (tNFA_CHO_API_REG *) GKI_getbuf (sizeof (tNFA_CHO_API_REG))) != NULL) |
| { |
| p_msg->hdr.event = NFA_CHO_API_REG_EVT; |
| |
| p_msg->enable_server = enable_server; |
| p_msg->p_cback = p_cback; |
| |
| nfa_sys_sendmsg (p_msg); |
| |
| return (NFA_STATUS_OK); |
| } |
| |
| return (NFA_STATUS_FAILED); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function NFA_ChoDeregister |
| ** |
| ** Description This function is called to deregister callback function from NFA |
| ** Connection Handover Application. |
| ** |
| ** If this is the valid deregistration, NFA Connection Handover |
| ** Application will close the service with "urn:nfc:sn:handover" |
| ** on LLCP and deregister NDEF type handler if any. |
| ** |
| ** Note: If RF discovery is started, NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT |
| ** should happen before calling this function |
| ** |
| ** Returns NFA_STATUS_OK if successfully initiated |
| ** NFA_STATUS_FAILED otherwise |
| ** |
| *******************************************************************************/ |
| tNFA_STATUS NFA_ChoDeregister (void) |
| { |
| tNFA_CHO_API_DEREG *p_msg; |
| |
| CHO_TRACE_API0 ("NFA_ChoDeregister ()"); |
| |
| if (nfa_cho_cb.state == NFA_CHO_ST_DISABLED) |
| { |
| CHO_TRACE_ERROR0 ("NFA_ChoDeregister (): Not registered"); |
| return (NFA_STATUS_FAILED); |
| } |
| |
| if ((p_msg = (tNFA_CHO_API_DEREG *) GKI_getbuf (sizeof (tNFA_CHO_API_DEREG))) != NULL) |
| { |
| p_msg->event = NFA_CHO_API_DEREG_EVT; |
| |
| nfa_sys_sendmsg (p_msg); |
| |
| return (NFA_STATUS_OK); |
| } |
| |
| return (NFA_STATUS_FAILED); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function NFA_ChoConnect |
| ** |
| ** Description This function is called to create data link connection to |
| ** Connection Handover server on peer device. |
| ** |
| ** It must be called after receiving NFA_CHO_ACTIVATED_EVT. |
| ** NFA_CHO_CONNECTED_EVT will be returned if successful. |
| ** Otherwise, NFA_CHO_DISCONNECTED_EVT will be returned. |
| ** |
| ** If NFA_CHO_ROLE_REQUESTER is returned in NFA_CHO_CONNECTED_EVT, |
| ** Handover Request Message can be sent. |
| ** If NFA_CHO_ROLE_SELECTOR is returned in NFA_CHO_CONNECTED_EVT |
| ** because of collision, application must wait for Handover |
| ** Request Message. |
| ** |
| ** Returns NFA_STATUS_OK if successfully initiated |
| ** NFA_STATUS_FAILED otherwise |
| ** |
| *******************************************************************************/ |
| tNFA_STATUS NFA_ChoConnect (void) |
| { |
| tNFA_CHO_API_CONNECT *p_msg; |
| |
| CHO_TRACE_API0 ("NFA_ChoConnect ()"); |
| |
| if (nfa_cho_cb.state == NFA_CHO_ST_DISABLED) |
| { |
| CHO_TRACE_ERROR0 ("NFA_ChoConnect (): Not registered"); |
| return (NFA_STATUS_FAILED); |
| } |
| else if (nfa_cho_cb.state == NFA_CHO_ST_CONNECTED) |
| { |
| CHO_TRACE_ERROR0 ("NFA_ChoConnect (): Already connected"); |
| return (NFA_STATUS_FAILED); |
| } |
| |
| if ((p_msg = (tNFA_CHO_API_CONNECT *) GKI_getbuf (sizeof (tNFA_CHO_API_CONNECT))) != NULL) |
| { |
| p_msg->event = NFA_CHO_API_CONNECT_EVT; |
| |
| nfa_sys_sendmsg (p_msg); |
| |
| return (NFA_STATUS_OK); |
| } |
| |
| return (NFA_STATUS_FAILED); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function NFA_ChoDisconnect |
| ** |
| ** Description This function is called to disconnect data link connection with |
| ** Connection Handover server on peer device. |
| ** |
| ** NFA_CHO_DISCONNECTED_EVT will be returned. |
| ** |
| ** Returns NFA_STATUS_OK if successfully initiated |
| ** NFA_STATUS_FAILED otherwise |
| ** |
| *******************************************************************************/ |
| tNFA_STATUS NFA_ChoDisconnect (void) |
| { |
| tNFA_CHO_API_DISCONNECT *p_msg; |
| |
| CHO_TRACE_API0 ("NFA_ChoDisconnect ()"); |
| |
| if (nfa_cho_cb.state == NFA_CHO_ST_DISABLED) |
| { |
| CHO_TRACE_ERROR0 ("NFA_ChoDisconnect (): Not registered"); |
| return (NFA_STATUS_FAILED); |
| } |
| |
| if ((p_msg = (tNFA_CHO_API_DISCONNECT *) GKI_getbuf (sizeof (tNFA_CHO_API_DISCONNECT))) != NULL) |
| { |
| p_msg->event = NFA_CHO_API_DISCONNECT_EVT; |
| |
| nfa_sys_sendmsg (p_msg); |
| |
| return (NFA_STATUS_OK); |
| } |
| |
| return (NFA_STATUS_FAILED); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function NFA_ChoSendHr |
| ** |
| ** Description This function is called to send Handover Request Message with |
| ** Handover Carrier records or Alternative Carrier records. |
| ** |
| ** It must be called after receiving NFA_CHO_CONNECTED_EVT. |
| ** |
| ** NDEF may include one or more Handover Carrier records or Alternative |
| ** Carrier records with auxiliary data. |
| ** The records in NDEF must be matched with tNFA_CHO_AC_INFO in order. |
| ** Payload ID must be unique and Payload ID length must be less than |
| ** or equal to NFA_CHO_MAX_REF_NAME_LEN. |
| ** |
| ** The alternative carrier information of Handover Select record |
| ** will be sent to application by NFA_CHO_SELECT_EVT. Application |
| ** may receive NFA_CHO_REQUEST_EVT because of handover collision. |
| ** |
| ** Returns NFA_STATUS_OK if successfully initiated |
| ** NFA_STATUS_FAILED otherwise |
| ** |
| *******************************************************************************/ |
| tNFA_STATUS NFA_ChoSendHr (UINT8 num_ac_info, |
| tNFA_CHO_AC_INFO *p_ac_info, |
| UINT8 *p_ndef, |
| UINT32 ndef_len) |
| { |
| tNFA_CHO_API_SEND_HR *p_msg; |
| UINT16 msg_size; |
| UINT8 *p_ndef_buf; |
| |
| CHO_TRACE_API2 ("NFA_ChoSendHr (): num_ac_info=%d, ndef_len=%d", num_ac_info, ndef_len); |
| |
| if (nfa_cho_cb.state != NFA_CHO_ST_CONNECTED) |
| { |
| CHO_TRACE_ERROR0 ("NFA_ChoSendHr (): Not connected"); |
| return (NFA_STATUS_FAILED); |
| } |
| |
| if (num_ac_info > NFA_CHO_MAX_AC_INFO) |
| { |
| CHO_TRACE_ERROR0 ("NFA_ChoSendHr (): Too many AC information"); |
| return (NFA_STATUS_FAILED); |
| } |
| |
| p_ndef_buf = (UINT8 *) GKI_getpoolbuf (LLCP_POOL_ID); |
| |
| if (!p_ndef_buf) |
| { |
| CHO_TRACE_ERROR0 ("NFA_ChoSendHr (): Failed to allocate buffer for NDEF"); |
| return NFA_STATUS_FAILED; |
| } |
| else if (ndef_len > LLCP_POOL_BUF_SIZE) |
| { |
| CHO_TRACE_ERROR1 ("NFA_ChoSendHr (): Failed to allocate buffer for %d bytes", ndef_len); |
| GKI_freebuf (p_ndef_buf); |
| return NFA_STATUS_FAILED; |
| } |
| |
| msg_size = sizeof (tNFA_CHO_API_SEND_HR) + num_ac_info * sizeof (tNFA_CHO_AC_INFO); |
| |
| if ((p_msg = (tNFA_CHO_API_SEND_HR *) GKI_getbuf (msg_size)) != NULL) |
| { |
| p_msg->hdr.event = NFA_CHO_API_SEND_HR_EVT; |
| |
| memcpy (p_ndef_buf, p_ndef, ndef_len); |
| p_msg->p_ndef = p_ndef_buf; |
| p_msg->max_ndef_size = LLCP_POOL_BUF_SIZE; |
| p_msg->cur_ndef_size = ndef_len; |
| |
| p_msg->num_ac_info = num_ac_info; |
| p_msg->p_ac_info = (tNFA_CHO_AC_INFO *) (p_msg + 1); |
| memcpy (p_msg->p_ac_info, p_ac_info, num_ac_info * sizeof (tNFA_CHO_AC_INFO)); |
| |
| nfa_sys_sendmsg (p_msg); |
| return (NFA_STATUS_OK); |
| } |
| else |
| { |
| GKI_freebuf (p_ndef_buf); |
| return (NFA_STATUS_FAILED); |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function NFA_ChoSendHs |
| ** |
| ** Description This function is called to send Handover Select message with |
| ** Alternative Carrier records as response to Handover Request |
| ** message. |
| ** |
| ** NDEF may include one or more Alternative Carrier records with |
| ** auxiliary data. |
| ** The records in NDEF must be matched with tNFA_CHO_AC_INFO in order. |
| ** Payload ID must be unique and Payload ID length must be less than |
| ** or equal to NFA_CHO_MAX_REF_NAME_LEN. |
| ** |
| ** Returns NFA_STATUS_OK if successfully initiated |
| ** NFA_STATUS_FAILED otherwise |
| ** |
| *******************************************************************************/ |
| tNFA_STATUS NFA_ChoSendHs (UINT8 num_ac_info, |
| tNFA_CHO_AC_INFO *p_ac_info, |
| UINT8 *p_ndef, |
| UINT32 ndef_len) |
| { |
| tNFA_CHO_API_SEND_HS *p_msg; |
| UINT16 msg_size; |
| UINT8 *p_ndef_buf; |
| |
| CHO_TRACE_API2 ("NFA_ChoSendHs(): num_ac_info=%d, ndef_len=%d", |
| num_ac_info, ndef_len); |
| |
| if (nfa_cho_cb.state != NFA_CHO_ST_CONNECTED) |
| { |
| CHO_TRACE_ERROR0 ("NFA_ChoSendHs (): Not connected"); |
| return (NFA_STATUS_FAILED); |
| } |
| |
| if (num_ac_info > NFA_CHO_MAX_AC_INFO) |
| { |
| CHO_TRACE_ERROR0 ("NFA_ChoSendHs (): Too many AC information"); |
| return (NFA_STATUS_FAILED); |
| } |
| |
| p_ndef_buf = (UINT8 *) GKI_getpoolbuf (LLCP_POOL_ID); |
| if (!p_ndef_buf) |
| { |
| CHO_TRACE_ERROR0 ("NFA_ChoSendHs (): Failed to allocate buffer for NDEF"); |
| return NFA_STATUS_FAILED; |
| } |
| else if (ndef_len > LLCP_POOL_BUF_SIZE) |
| { |
| CHO_TRACE_ERROR1 ("NFA_ChoSendHs (): Failed to allocate buffer for %d bytes", ndef_len); |
| GKI_freebuf (p_ndef_buf); |
| return NFA_STATUS_FAILED; |
| } |
| |
| msg_size = sizeof (tNFA_CHO_API_SEND_HS) + num_ac_info * sizeof (tNFA_CHO_AC_INFO); |
| |
| if ((p_msg = (tNFA_CHO_API_SEND_HS *) GKI_getbuf (msg_size)) != NULL) |
| { |
| p_msg->hdr.event = NFA_CHO_API_SEND_HS_EVT; |
| |
| memcpy (p_ndef_buf, p_ndef, ndef_len); |
| p_msg->p_ndef = p_ndef_buf; |
| p_msg->max_ndef_size = LLCP_POOL_BUF_SIZE; |
| p_msg->cur_ndef_size = ndef_len; |
| |
| p_msg->num_ac_info = num_ac_info; |
| p_msg->p_ac_info = (tNFA_CHO_AC_INFO *) (p_msg + 1); |
| memcpy (p_msg->p_ac_info, p_ac_info, num_ac_info * sizeof (tNFA_CHO_AC_INFO)); |
| |
| nfa_sys_sendmsg (p_msg); |
| return (NFA_STATUS_OK); |
| } |
| else |
| { |
| GKI_freebuf (p_ndef_buf); |
| return (NFA_STATUS_FAILED); |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function NFA_ChoSendSelectError |
| ** |
| ** Description This function is called to send Error record to indicate failure |
| ** to process the most recently received Handover Request message. |
| ** |
| ** error_reason : NFA_CHO_ERROR_TEMP_MEM |
| ** NFA_CHO_ERROR_PERM_MEM |
| ** NFA_CHO_ERROR_CARRIER |
| ** |
| ** Returns NFA_STATUS_OK if successfully initiated |
| ** NFA_STATUS_FAILED otherwise |
| ** |
| *******************************************************************************/ |
| tNFA_STATUS NFA_ChoSendSelectError (UINT8 error_reason, |
| UINT32 error_data) |
| { |
| tNFA_CHO_API_SEL_ERR *p_msg; |
| |
| CHO_TRACE_API2 ("NFA_ChoSendSelectError (): error_reason=0x%x, error_data=0x%x", |
| error_reason, error_data); |
| |
| if (nfa_cho_cb.state == NFA_CHO_ST_DISABLED) |
| { |
| CHO_TRACE_ERROR0 ("NFA_ChoSendSelectError (): Not registered"); |
| return (NFA_STATUS_FAILED); |
| } |
| |
| if ((p_msg = (tNFA_CHO_API_SEL_ERR *) GKI_getbuf (sizeof (tNFA_CHO_API_SEL_ERR))) != NULL) |
| { |
| p_msg->hdr.event = NFA_CHO_API_SEL_ERR_EVT; |
| |
| p_msg->error_reason = error_reason; |
| p_msg->error_data = error_data; |
| |
| nfa_sys_sendmsg (p_msg); |
| |
| return (NFA_STATUS_OK); |
| } |
| |
| return (NFA_STATUS_FAILED); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function NFA_ChoSetTraceLevel |
| ** |
| ** Description This function sets the trace level for CHO. If called with |
| ** a value of 0xFF, it simply returns the current trace level. |
| ** |
| ** Returns The new or current trace level |
| ** |
| *******************************************************************************/ |
| UINT8 NFA_ChoSetTraceLevel (UINT8 new_level) |
| { |
| if (new_level != 0xFF) |
| nfa_cho_cb.trace_level = new_level; |
| |
| return (nfa_cho_cb.trace_level); |
| } |
| |
| #if (defined (NFA_CHO_TEST_INCLUDED) && (NFA_CHO_TEST_INCLUDED == TRUE)) |
| /******************************************************************************* |
| ** |
| ** Function NFA_ChoSetTestParam |
| ** |
| ** Description This function is called to set test parameters. |
| ** |
| *******************************************************************************/ |
| void NFA_ChoSetTestParam (UINT8 test_enable, |
| UINT8 test_version, |
| UINT16 test_random_number) |
| { |
| nfa_cho_cb.test_enabled = test_enable; |
| nfa_cho_cb.test_version = test_version; |
| nfa_cho_cb.test_random_number = test_random_number; |
| } |
| #endif |