Home | History | Annotate | Download | only in cho
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2010-2012 Broadcom Corporation
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19 /******************************************************************************
     20  *
     21  *  This is the utilities implementation file for the NFA Connection
     22  *  Handover.
     23  *
     24  ******************************************************************************/
     25 
     26 #include "string.h"
     27 #include "nfa_sys.h"
     28 #include "llcp_api.h"
     29 #include "llcp_defs.h"
     30 #include "nfa_p2p_int.h"
     31 #include "nfa_cho_api.h"
     32 #include "nfa_cho_int.h"
     33 #include "trace_api.h"
     34 #include "nfa_mem_co.h"
     35 
     36 /*****************************************************************************
     37 **  Constants
     38 *****************************************************************************/
     39 /* Handover server name on LLCP */
     40 static char *p_cho_service_name = "urn:nfc:sn:handover";
     41 
     42 /* Handover Request Record Type */
     43 static UINT8 hr_rec_type[HR_REC_TYPE_LEN] = { 0x48, 0x72 }; /* "Hr" */
     44 
     45 /* Handover Select Record Type */
     46 static UINT8 hs_rec_type[HS_REC_TYPE_LEN] = { 0x48, 0x73 }; /* "Hs" */
     47 
     48 /* Handover Carrier recrod Type */
     49 /* static UINT8 hc_rec_type[HC_REC_TYPE_LEN] = { 0x48, 0x63 }; "Hc" */
     50 
     51 /* Collision Resolution Record Type */
     52 static UINT8 cr_rec_type[CR_REC_TYPE_LEN] = { 0x63, 0x72 }; /* "cr" */
     53 
     54 /* Alternative Carrier Record Type */
     55 static UINT8 ac_rec_type[AC_REC_TYPE_LEN] = { 0x61, 0x63 }; /* "ac" */
     56 
     57 /* Error Record Type */
     58 static UINT8 err_rec_type[ERR_REC_TYPE_LEN] = { 0x65, 0x72, 0x72 }; /* "err" */
     59 
     60 /* Bluetooth OOB Data Type */
     61 static UINT8 *p_bt_oob_rec_type = (UINT8 *) "application/vnd.bluetooth.ep.oob";
     62 
     63 /* WiFi Data Type */
     64 static UINT8 *p_wifi_rec_type = (UINT8 *) "application/vnd.wfa.wsc";
     65 
     66 /*****************************************************************************
     67 **  Global Variables
     68 *****************************************************************************/
     69 
     70 /*****************************************************************************
     71 **  Static Functions
     72 *****************************************************************************/
     73 static void nfa_cho_ndef_cback (tNFA_NDEF_EVT event, tNFA_NDEF_EVT_DATA *p_data);
     74 
     75 /*******************************************************************************
     76 **
     77 ** Function         nfa_cho_ndef_cback
     78 **
     79 ** Description      callback function from NDEF handler
     80 **                  Post NDEF handler callback event to NFA Connection Handover module
     81 **
     82 ** Returns          None
     83 **
     84 *******************************************************************************/
     85 static void nfa_cho_ndef_cback (tNFA_NDEF_EVT event, tNFA_NDEF_EVT_DATA *p_data)
     86 {
     87     tNFA_CHO_NDEF_TYPE_HDLR_EVT *p_msg;
     88     tNFA_CHO_MSG_TYPE           msg_type;
     89 
     90     CHO_TRACE_DEBUG1 ("nfa_cho_ndef_cback () event=%d", event);
     91 
     92     if ((p_msg = (tNFA_CHO_NDEF_TYPE_HDLR_EVT *) GKI_getbuf (sizeof (tNFA_CHO_NDEF_TYPE_HDLR_EVT))) != NULL)
     93     {
     94         p_msg->hdr.event = NFA_CHO_NDEF_TYPE_HANDLER_EVT;
     95 
     96         /* copy NDEF handler callback event and data */
     97         p_msg->event = event;
     98         memcpy (&(p_msg->data), p_data, sizeof (tNFA_NDEF_EVT_DATA));
     99 
    100         /* if it has NDEF message */
    101         if (event == NFA_NDEF_DATA_EVT)
    102         {
    103             if (p_data->ndef_data.ndef_type_handle == nfa_cho_cb.bt_ndef_type_handle )
    104             {
    105                 msg_type = nfa_cho_get_msg_type (p_data->ndef_data.len,
    106                                                  p_data->ndef_data.p_data);
    107                 if (msg_type != NFA_CHO_MSG_BT_OOB)
    108                 {
    109                     /* This is not simplified BT OOB Message. It contains BT OOB Message. */
    110                     GKI_freebuf (p_msg);
    111                     return;
    112                 }
    113             }
    114             else if (p_data->ndef_data.ndef_type_handle == nfa_cho_cb.wifi_ndef_type_handle )
    115             {
    116                 msg_type = nfa_cho_get_msg_type (p_data->ndef_data.len,
    117                                                  p_data->ndef_data.p_data);
    118                 if (msg_type != NFA_CHO_MSG_WIFI)
    119                 {
    120                     /* This is not simplified WiFi Message. It contains WiFi Message. */
    121                     GKI_freebuf (p_msg);
    122                     return;
    123                 }
    124             }
    125 
    126             /*
    127             ** NDEF message could be bigger than max GKI buffer
    128             ** so allocate memory from platform.
    129             */
    130             p_msg->data.ndef_data.p_data = (UINT8 *) nfa_mem_co_alloc (p_msg->data.ndef_data.len);
    131 
    132             if (p_msg->data.ndef_data.p_data)
    133             {
    134                 memcpy (p_msg->data.ndef_data.p_data,
    135                         p_data->ndef_data.p_data,
    136                         p_msg->data.ndef_data.len);
    137             }
    138             else
    139             {
    140                 CHO_TRACE_ERROR1 ("Failed nfa_mem_co_alloc () for %d bytes", p_msg->data.ndef_data.len);
    141                 GKI_freebuf (p_msg);
    142                 return;
    143             }
    144         }
    145 
    146         nfa_sys_sendmsg (p_msg);
    147     }
    148 }
    149 
    150 /*******************************************************************************
    151 **
    152 ** Function         nfa_cho_proc_ndef_type_handler_evt
    153 **
    154 ** Description      Process events (registration and NDEF data) from NFA NDEF
    155 **                  Type Handler
    156 **
    157 ** Returns          tNFA_STATUS
    158 **
    159 *******************************************************************************/
    160 void nfa_cho_proc_ndef_type_handler_evt (tNFA_CHO_INT_EVENT_DATA *p_evt_data)
    161 {
    162     tNFA_CHO_MSG_TYPE msg_type;
    163 
    164     if (p_evt_data->ndef_type_hdlr.event == NFA_NDEF_REGISTER_EVT)
    165     {
    166         if (p_evt_data->ndef_type_hdlr.data.ndef_reg.status == NFA_STATUS_OK)
    167         {
    168             /* store handle for deregistration */
    169             if (nfa_cho_cb.hs_ndef_type_handle == NFA_HANDLE_INVALID)
    170             {
    171                 nfa_cho_cb.hs_ndef_type_handle = p_evt_data->ndef_type_hdlr.data.ndef_reg.ndef_type_handle;
    172             }
    173             else if (nfa_cho_cb.bt_ndef_type_handle == NFA_HANDLE_INVALID)
    174             {
    175                 nfa_cho_cb.bt_ndef_type_handle = p_evt_data->ndef_type_hdlr.data.ndef_reg.ndef_type_handle;
    176             }
    177             else if (nfa_cho_cb.wifi_ndef_type_handle == NFA_HANDLE_INVALID)
    178             {
    179                 nfa_cho_cb.wifi_ndef_type_handle = p_evt_data->ndef_type_hdlr.data.ndef_reg.ndef_type_handle;
    180             }
    181         }
    182     }
    183     else if (p_evt_data->ndef_type_hdlr.event == NFA_NDEF_DATA_EVT)
    184     {
    185         /* if negotiated handover is on going, then ignore static handover */
    186         if (nfa_cho_cb.state != NFA_CHO_ST_CONNECTED)
    187         {
    188 #if (BT_TRACE_PROTOCOL == TRUE)
    189             DispNDEFMsg (p_evt_data->ndef_type_hdlr.data.ndef_data.p_data,
    190                          p_evt_data->ndef_type_hdlr.data.ndef_data.len, TRUE);
    191 #endif
    192             msg_type = nfa_cho_get_msg_type (p_evt_data->ndef_type_hdlr.data.ndef_data.len,
    193                                              p_evt_data->ndef_type_hdlr.data.ndef_data.p_data);
    194 
    195             if (msg_type == NFA_CHO_MSG_HS)
    196             {
    197                 nfa_cho_proc_hs (p_evt_data->ndef_type_hdlr.data.ndef_data.len,
    198                                  p_evt_data->ndef_type_hdlr.data.ndef_data.p_data);
    199             }
    200             else if (  (msg_type == NFA_CHO_MSG_BT_OOB)
    201                      ||(msg_type == NFA_CHO_MSG_WIFI)  )
    202             {
    203                 /* simplified BT OOB/Wifi Message */
    204                 nfa_cho_proc_simplified_format (p_evt_data->ndef_type_hdlr.data.ndef_data.len,
    205                                                 p_evt_data->ndef_type_hdlr.data.ndef_data.p_data);
    206             }
    207             else
    208             {
    209                 CHO_TRACE_ERROR0 ("Unexpected CHO Message Type");
    210             }
    211         }
    212 
    213         nfa_mem_co_free (p_evt_data->ndef_type_hdlr.data.ndef_data.p_data);
    214     }
    215 }
    216 
    217 /*******************************************************************************
    218 **
    219 ** Function         nfa_cho_proc_api_reg
    220 **
    221 ** Description      Process registeration request from application
    222 **                  Register Handover server on LLCP for negotiated handover
    223 **                  Register handover select records on NDEF handler for static handover
    224 **
    225 ** Returns          tNFA_STATUS
    226 **
    227 *******************************************************************************/
    228 tNFA_STATUS nfa_cho_proc_api_reg (tNFA_CHO_INT_EVENT_DATA *p_evt_data)
    229 {
    230     CHO_TRACE_DEBUG1 ("nfa_cho_proc_api_reg (): enable_server=%d",
    231                       p_evt_data->api_reg.enable_server);
    232 
    233     if (p_evt_data->api_reg.enable_server == TRUE)
    234     {
    235         /* Register Handover server on LLCP for negotiated handover */
    236         nfa_cho_cb.server_sap = LLCP_RegisterServer (LLCP_INVALID_SAP,
    237                                                      LLCP_LINK_TYPE_DATA_LINK_CONNECTION,
    238                                                      p_cho_service_name,
    239                                                      nfa_cho_sm_llcp_cback);
    240         if (nfa_cho_cb.server_sap == LLCP_INVALID_SAP)
    241         {
    242             CHO_TRACE_ERROR0 ("Cannot register CHO server");
    243             return NFA_STATUS_FAILED;
    244         }
    245         else
    246         {
    247             nfa_p2p_enable_listening (NFA_ID_CHO, FALSE);
    248         }
    249     }
    250     else
    251     {
    252         /*
    253         ** Register Handover client on LLCP for negotiated handover
    254         ** LLCP will notify link status through callback
    255         */
    256         nfa_cho_cb.client_sap = LLCP_RegisterClient (LLCP_LINK_TYPE_DATA_LINK_CONNECTION,
    257                                                      nfa_cho_sm_llcp_cback);
    258 
    259         if (nfa_cho_cb.client_sap == LLCP_INVALID_SAP)
    260         {
    261             CHO_TRACE_ERROR0 ("Cannot register CHO client");
    262             return NFA_STATUS_FAILED;
    263         }
    264 
    265         /* set flag not to deregister client when disconnected */
    266         nfa_cho_cb.flags |= NFA_CHO_FLAGS_CLIENT_ONLY;
    267     }
    268 
    269     /* Register handover select record on NDEF handler for static handover */
    270     if (nfa_cho_cb.hs_ndef_type_handle == NFA_HANDLE_INVALID)
    271     {
    272         NFA_RegisterNDefTypeHandler (TRUE, NFA_TNF_WKT, hs_rec_type, HS_REC_TYPE_LEN,
    273                                      nfa_cho_ndef_cback);
    274     }
    275     if (nfa_cho_cb.bt_ndef_type_handle == NFA_HANDLE_INVALID)
    276     {
    277         NFA_RegisterNDefTypeHandler (TRUE, NFA_TNF_RFC2046_MEDIA,
    278                                      p_bt_oob_rec_type, (UINT8) strlen ((char *) p_bt_oob_rec_type),
    279                                      nfa_cho_ndef_cback);
    280     }
    281     if (nfa_cho_cb.wifi_ndef_type_handle == NFA_HANDLE_INVALID)
    282     {
    283         NFA_RegisterNDefTypeHandler (TRUE, NFA_TNF_RFC2046_MEDIA,
    284                                      p_wifi_rec_type, (UINT8) strlen ((char *) p_wifi_rec_type),
    285                                      nfa_cho_ndef_cback);
    286     }
    287 
    288     nfa_cho_cb.p_cback = p_evt_data->api_reg.p_cback;
    289 
    290     return NFA_STATUS_OK;
    291 }
    292 
    293 /*******************************************************************************
    294 **
    295 ** Function         nfa_cho_proc_api_dereg
    296 **
    297 ** Description      Process deregisteration request from application
    298 **                  Disconnect LLCP connection if any
    299 **                  Deregister callback from NDEF handler and NFA P2P
    300 **
    301 ** Returns          None
    302 **
    303 *******************************************************************************/
    304 void nfa_cho_proc_api_dereg (void)
    305 {
    306     CHO_TRACE_DEBUG0 ("nfa_cho_proc_api_dereg ()");
    307 
    308     /* Deregister outgoing connection, data link will be disconnected if any */
    309     if (nfa_cho_cb.client_sap != LLCP_INVALID_SAP)
    310     {
    311         LLCP_Deregister (nfa_cho_cb.client_sap);
    312         nfa_cho_cb.client_sap = LLCP_INVALID_SAP;
    313     }
    314 
    315     /* Close Connection Handover server in LLCP, data link will be disconnected if any */
    316     if (nfa_cho_cb.server_sap != LLCP_INVALID_SAP)
    317     {
    318         LLCP_Deregister (nfa_cho_cb.server_sap);
    319         nfa_cho_cb.server_sap = LLCP_INVALID_SAP;
    320     }
    321 
    322     /* Deregister type handler if any */
    323     if (nfa_cho_cb.hs_ndef_type_handle != NFA_HANDLE_INVALID)
    324     {
    325         NFA_DeregisterNDefTypeHandler (nfa_cho_cb.hs_ndef_type_handle);
    326         nfa_cho_cb.hs_ndef_type_handle = NFA_HANDLE_INVALID;
    327     }
    328 
    329     if (nfa_cho_cb.bt_ndef_type_handle != NFA_HANDLE_INVALID)
    330     {
    331         NFA_DeregisterNDefTypeHandler (nfa_cho_cb.bt_ndef_type_handle);
    332         nfa_cho_cb.bt_ndef_type_handle = NFA_HANDLE_INVALID;
    333     }
    334 
    335     if (nfa_cho_cb.wifi_ndef_type_handle != NFA_HANDLE_INVALID)
    336     {
    337         NFA_DeregisterNDefTypeHandler (nfa_cho_cb.wifi_ndef_type_handle);
    338         nfa_cho_cb.wifi_ndef_type_handle = NFA_HANDLE_INVALID;
    339     }
    340 
    341     nfa_sys_stop_timer (&nfa_cho_cb.timer);
    342     nfa_cho_cb.p_cback = NULL;
    343     nfa_cho_cb.flags   = 0;
    344 
    345     nfa_p2p_disable_listening (NFA_ID_CHO, FALSE);
    346 }
    347 
    348 /*******************************************************************************
    349 **
    350 ** Function         nfa_cho_create_connection
    351 **
    352 ** Description      Create data link connection with handover server in remote
    353 **
    354 **
    355 ** Returns          None
    356 **
    357 *******************************************************************************/
    358 tNFA_STATUS nfa_cho_create_connection (void)
    359 {
    360     tLLCP_CONNECTION_PARAMS conn_params;
    361     tNFA_STATUS             status = NFA_STATUS_FAILED;
    362 
    363     CHO_TRACE_DEBUG0 ("nfa_cho_create_connection ()");
    364 
    365     if (nfa_cho_cb.client_sap == LLCP_INVALID_SAP)
    366     {
    367         nfa_cho_cb.client_sap = LLCP_RegisterClient (LLCP_LINK_TYPE_DATA_LINK_CONNECTION,
    368                                                      nfa_cho_sm_llcp_cback);
    369     }
    370 
    371     if (nfa_cho_cb.client_sap == LLCP_INVALID_SAP)
    372     {
    373         CHO_TRACE_ERROR0 ("Cannot register CHO client");
    374     }
    375     else
    376     {
    377         /* create data link connection with server name */
    378         conn_params.miu = (UINT16) (nfa_cho_cb.local_link_miu >= NFA_CHO_MIU ? NFA_CHO_MIU : nfa_cho_cb.local_link_miu);
    379         conn_params.rw  = NFA_CHO_RW;
    380         BCM_STRNCPY_S (conn_params.sn, sizeof (conn_params.sn),
    381                        p_cho_service_name, LLCP_MAX_SN_LEN);
    382         conn_params.sn[LLCP_MAX_SN_LEN] = 0;
    383 
    384         if (LLCP_ConnectReq (nfa_cho_cb.client_sap, LLCP_SAP_SDP, &conn_params) == LLCP_STATUS_SUCCESS)
    385             status = NFA_STATUS_OK;
    386     }
    387 
    388     return status;
    389 }
    390 
    391 /*******************************************************************************
    392 **
    393 ** Function         nfa_cho_process_disconnection
    394 **
    395 ** Description      Clean up buffers and notify disconnection to application
    396 **
    397 **
    398 ** Returns          None
    399 **
    400 *******************************************************************************/
    401 void nfa_cho_process_disconnection (tNFA_CHO_DISC_REASON disc_reason)
    402 {
    403     tNFA_CHO_EVT_DATA evt_data;
    404 
    405     nfa_sys_stop_timer (&nfa_cho_cb.timer);
    406 
    407     /* free buffer for Tx/Rx NDEF message */
    408     if (nfa_cho_cb.p_tx_ndef_msg)
    409     {
    410         GKI_freebuf (nfa_cho_cb.p_tx_ndef_msg);
    411         nfa_cho_cb.p_tx_ndef_msg = NULL;
    412     }
    413     if (nfa_cho_cb.p_rx_ndef_msg)
    414     {
    415         GKI_freebuf (nfa_cho_cb.p_rx_ndef_msg);
    416         nfa_cho_cb.p_rx_ndef_msg = NULL;
    417     }
    418 
    419     /* if no server is registered on LLCP, do not deregister client to get link statue from LLCP */
    420     if (!(nfa_cho_cb.flags & NFA_CHO_FLAGS_CLIENT_ONLY))
    421     {
    422         if (nfa_cho_cb.client_sap != LLCP_INVALID_SAP)
    423         {
    424             LLCP_Deregister (nfa_cho_cb.client_sap);
    425             nfa_cho_cb.client_sap = LLCP_INVALID_SAP;
    426         }
    427     }
    428 
    429     nfa_cho_cb.flags &= ~NFA_CHO_FLAGS_CONN_COLLISION;
    430 
    431     evt_data.disconnected.reason = disc_reason;
    432     nfa_cho_cb.p_cback (NFA_CHO_DISCONNECTED_EVT, &evt_data);
    433 }
    434 
    435 /*******************************************************************************
    436 **
    437 ** Function         nfa_cho_notify_tx_fail_evt
    438 **
    439 ** Description      Notify application of NFA_CHO_TX_FAIL_EVT
    440 **
    441 **
    442 ** Returns          None
    443 **
    444 *******************************************************************************/
    445 void nfa_cho_notify_tx_fail_evt (tNFA_STATUS status)
    446 {
    447     tNFA_CHO_EVT_DATA evt_data;
    448 
    449     CHO_TRACE_DEBUG0 ("nfa_cho_notify_tx_fail_evt ()");
    450 
    451     evt_data.status = status;
    452 
    453     if (nfa_cho_cb.p_cback)
    454         nfa_cho_cb.p_cback (NFA_CHO_TX_FAIL_EVT, &evt_data);
    455 }
    456 
    457 /*******************************************************************************
    458 **
    459 ** Function         nfa_cho_reassemble_ho_msg
    460 **
    461 ** Description      Reassemble received data for handover message
    462 **
    463 **
    464 ** Returns          tNFA_CHO_RX_NDEF_STATUS
    465 **
    466 *******************************************************************************/
    467 tNFA_CHO_RX_NDEF_STATUS nfa_cho_reassemble_ho_msg (UINT8 local_sap, UINT8 remote_sap)
    468 {
    469     tNFA_CHO_RX_NDEF_STATUS rx_status;
    470 
    471     nfa_sys_stop_timer (&nfa_cho_cb.timer);
    472 
    473     /*
    474     ** allocate memory for NDEF message for the first segment
    475     ** validate NDEF message to check if received complete message
    476     */
    477     rx_status = nfa_cho_read_ndef_msg (local_sap, remote_sap);
    478 
    479     /* if Temporary Memory Constraint */
    480     if (rx_status == NFA_CHO_RX_NDEF_TEMP_MEM)
    481     {
    482         CHO_TRACE_ERROR0 ("Failed due to Temporary Memory Constraint");
    483 
    484         /* if we are expecting Hr then send Hs Error record */
    485         if (nfa_cho_cb.substate == NFA_CHO_SUBSTATE_W4_REMOTE_HR)
    486         {
    487             /* ask retry later, handover request will disconnect */
    488             nfa_cho_send_hs_error (NFA_CHO_ERROR_TEMP_MEM, NFA_CHO_TIMEOUT_FOR_RETRY);
    489         }
    490         else
    491         {
    492             /* we cannot send error record, so disconnect */
    493             nfa_cho_cb.disc_reason = NFA_CHO_DISC_REASON_INTERNAL_ERROR;
    494             LLCP_DisconnectReq (nfa_cho_cb.local_sap, nfa_cho_cb.remote_sap, FALSE);
    495         }
    496     }
    497     /* Permanent Memory Constraint */
    498     else if (rx_status == NFA_CHO_RX_NDEF_PERM_MEM)
    499     {
    500         CHO_TRACE_ERROR0 ("Failed due to Permanent Memory Constraint");
    501 
    502         /* if we are expecting Hr then send Hs Error record */
    503         if (nfa_cho_cb.substate == NFA_CHO_SUBSTATE_W4_REMOTE_HR)
    504         {
    505             /*
    506             ** notify our buffer size and ask retry with modified message later
    507             ** handover request will disconnect
    508             */
    509             nfa_cho_send_hs_error (NFA_CHO_ERROR_PERM_MEM, nfa_cho_cb.rx_ndef_buf_size);
    510         }
    511         else
    512         {
    513             /* we cannot send error record, so disconnect */
    514             nfa_cho_cb.disc_reason = NFA_CHO_DISC_REASON_INTERNAL_ERROR;
    515             LLCP_DisconnectReq (nfa_cho_cb.local_sap, nfa_cho_cb.remote_sap, FALSE);
    516         }
    517     }
    518     /* Invalid NDEF message */
    519     else if (rx_status == NFA_CHO_RX_NDEF_INVALID)
    520     {
    521         CHO_TRACE_ERROR0 ("Failed due to invalid NDEF message");
    522 
    523         if (nfa_cho_cb.substate == NFA_CHO_SUBSTATE_W4_REMOTE_HR)
    524         {
    525             /* let Handover Requester got timeout */
    526         }
    527         else
    528         {
    529             /* we cannot send error record, so disconnect */
    530             nfa_cho_cb.disc_reason = NFA_CHO_DISC_REASON_INVALID_MSG;
    531             LLCP_DisconnectReq (nfa_cho_cb.local_sap, nfa_cho_cb.remote_sap, FALSE);
    532         }
    533     }
    534     /* need more segment */
    535     else if (rx_status == NFA_CHO_RX_NDEF_INCOMPLTE)
    536     {
    537         /* wait for next segment */
    538         if (nfa_cho_cb.substate == NFA_CHO_SUBSTATE_W4_REMOTE_HR)
    539         {
    540             nfa_sys_start_timer (&nfa_cho_cb.timer, 0, NFA_CHO_TIMEOUT_SEGMENTED_HR);
    541         }
    542         /* don't update running timer if we are waiting Hs */
    543     }
    544     else /* NFA_CHO_RX_NDEF_COMPLETE */
    545     {
    546         /* Received complete NDEF message */
    547     }
    548 
    549     return rx_status;
    550 }
    551 
    552 /*******************************************************************************
    553 **
    554 ** Function         nfa_cho_send_handover_msg
    555 **
    556 ** Description      Send segmented or whole Handover Message on LLCP
    557 **                  if congested then wait for uncongested event from LLCP
    558 **
    559 ** Returns          tNFA_STATUS
    560 **
    561 *******************************************************************************/
    562 tNFA_STATUS nfa_cho_send_handover_msg (void)
    563 {
    564     tNFA_STATUS  status = NFA_STATUS_FAILED;
    565     tLLCP_STATUS llcp_status;
    566     UINT16       tx_size;
    567     BT_HDR       *p_msg;
    568     UINT8        *p_src, *p_dst;
    569 
    570     CHO_TRACE_DEBUG2 ("nfa_cho_send_handover_msg () size=%d, sent=%d",
    571                       nfa_cho_cb.tx_ndef_cur_size, nfa_cho_cb.tx_ndef_sent_size);
    572 
    573     /* while data link connection is not congested */
    574     while ((!nfa_cho_cb.congested) && (nfa_cho_cb.tx_ndef_sent_size < nfa_cho_cb.tx_ndef_cur_size))
    575     {
    576         /* select segment size as min (MIU of remote, remaining NDEF size) */
    577         if (nfa_cho_cb.tx_ndef_cur_size - nfa_cho_cb.tx_ndef_sent_size > nfa_cho_cb.remote_miu)
    578         {
    579             tx_size = nfa_cho_cb.remote_miu;
    580         }
    581         else
    582         {
    583             tx_size = (UINT16) (nfa_cho_cb.tx_ndef_cur_size - nfa_cho_cb.tx_ndef_sent_size);
    584         }
    585 
    586         /* transmit a segment on LLCP */
    587         if ((p_msg = (BT_HDR *) GKI_getpoolbuf (LLCP_POOL_ID)) != NULL)
    588         {
    589             p_msg->len    = (UINT16) tx_size;
    590             p_msg->offset = LLCP_MIN_OFFSET;
    591 
    592             p_dst = (UINT8*) (p_msg + 1) + p_msg->offset;
    593             p_src = nfa_cho_cb.p_tx_ndef_msg + nfa_cho_cb.tx_ndef_sent_size;
    594 
    595             memcpy (p_dst, p_src, tx_size);
    596 
    597             llcp_status = LLCP_SendData (nfa_cho_cb.local_sap, nfa_cho_cb.remote_sap, p_msg);
    598 
    599             nfa_cho_cb.tx_ndef_sent_size += tx_size;
    600         }
    601         else
    602         {
    603             llcp_status = LLCP_STATUS_FAIL;
    604         }
    605 
    606         if (llcp_status == LLCP_STATUS_SUCCESS)
    607         {
    608             status = NFA_STATUS_OK;
    609         }
    610         else if (llcp_status == LLCP_STATUS_CONGESTED)
    611         {
    612             status = NFA_STATUS_CONGESTED;
    613             CHO_TRACE_DEBUG0 ("Data link connection is congested");
    614             /* wait for uncongested event */
    615             nfa_cho_cb.congested = TRUE;
    616             break;
    617         }
    618         else
    619         {
    620             status = NFA_STATUS_FAILED;
    621             GKI_freebuf (nfa_cho_cb.p_tx_ndef_msg);
    622             nfa_cho_cb.p_tx_ndef_msg = NULL;
    623             break;
    624         }
    625     }
    626 
    627     /*
    628     ** free buffer when receiving response or disconnected because we may need to send
    629     ** Hr message again due to collision
    630     */
    631 
    632     return status;
    633 }
    634 
    635 /*******************************************************************************
    636 **
    637 ** Function         nfa_cho_read_ndef_msg
    638 **
    639 ** Description      allocate memory for NDEF message for the first segment
    640 **                  validate NDEF message to check if received complete message
    641 **
    642 ** Returns          None
    643 **
    644 *******************************************************************************/
    645 tNFA_CHO_RX_NDEF_STATUS nfa_cho_read_ndef_msg (UINT8 local_sap, UINT8 remote_sap)
    646 {
    647     tNDEF_STATUS            ndef_status;
    648     tNFA_CHO_RX_NDEF_STATUS rx_status;
    649     BOOLEAN                 more;
    650     UINT32                  length;
    651 
    652     CHO_TRACE_DEBUG2 ("nfa_cho_read_ndef_msg () local_sap=0x%x, remote_sap=0x%x",
    653                       local_sap, remote_sap);
    654 
    655     /* if this is the first segment */
    656     if (!nfa_cho_cb.p_rx_ndef_msg)
    657     {
    658         nfa_cho_cb.p_rx_ndef_msg = (UINT8 *) GKI_getpoolbuf (LLCP_POOL_ID);
    659 
    660         if (!nfa_cho_cb.p_rx_ndef_msg)
    661         {
    662             CHO_TRACE_ERROR0 ("Failed to allocate buffer");
    663             return NFA_CHO_RX_NDEF_TEMP_MEM;
    664         }
    665 
    666         nfa_cho_cb.rx_ndef_buf_size = LLCP_POOL_BUF_SIZE;
    667         nfa_cho_cb.rx_ndef_cur_size = 0;
    668     }
    669 
    670     more = TRUE;
    671     while (more)
    672     {
    673         more = LLCP_ReadDataLinkData (local_sap,
    674                                       remote_sap,
    675                                       (UINT16)(nfa_cho_cb.rx_ndef_buf_size - nfa_cho_cb.rx_ndef_cur_size),
    676                                       &length,
    677                                       nfa_cho_cb.p_rx_ndef_msg + nfa_cho_cb.rx_ndef_cur_size);
    678 
    679         nfa_cho_cb.rx_ndef_cur_size += length;
    680 
    681         /* if it doesn't fit into allocated memory */
    682         if ((nfa_cho_cb.rx_ndef_cur_size >= nfa_cho_cb.rx_ndef_buf_size)
    683           &&(more))
    684         {
    685             CHO_TRACE_ERROR0 ("Failed to store too much data");
    686 
    687             LLCP_FlushDataLinkRxData (local_sap, remote_sap);
    688 
    689             GKI_freebuf (nfa_cho_cb.p_rx_ndef_msg);
    690             nfa_cho_cb.p_rx_ndef_msg = NULL;
    691 
    692             return NFA_CHO_RX_NDEF_PERM_MEM;
    693         }
    694     }
    695 
    696     /* check NDEF message */
    697     ndef_status = NDEF_MsgValidate (nfa_cho_cb.p_rx_ndef_msg, nfa_cho_cb.rx_ndef_cur_size, FALSE);
    698 
    699     switch (ndef_status)
    700     {
    701     case NDEF_OK:
    702         rx_status = NFA_CHO_RX_NDEF_COMPLETE;
    703         break;
    704 
    705     case NDEF_MSG_TOO_SHORT:
    706     case NDEF_MSG_NO_MSG_END:
    707     case NDEF_MSG_LENGTH_MISMATCH:
    708         rx_status = NFA_CHO_RX_NDEF_INCOMPLTE;
    709         break;
    710 
    711     default:
    712         rx_status = NFA_CHO_RX_NDEF_INVALID;
    713         break;
    714     }
    715 
    716     if (rx_status == NFA_CHO_RX_NDEF_COMPLETE)
    717     {
    718 #if (BT_TRACE_PROTOCOL == TRUE)
    719         DispCHO (nfa_cho_cb.p_rx_ndef_msg, nfa_cho_cb.rx_ndef_cur_size, TRUE);
    720 #endif
    721     }
    722     else if (rx_status == NFA_CHO_RX_NDEF_INCOMPLTE)
    723     {
    724         CHO_TRACE_DEBUG0 ("Need more data to complete NDEF message");
    725     }
    726     else /* if (rx_status == NFA_CHO_RX_NDEF_INVALID) */
    727     {
    728         CHO_TRACE_ERROR1 ("Failed to validate NDEF message error=0x%x", ndef_status);
    729         GKI_freebuf (nfa_cho_cb.p_rx_ndef_msg);
    730         nfa_cho_cb.p_rx_ndef_msg = NULL;
    731     }
    732 
    733     return rx_status;
    734 }
    735 
    736 /*******************************************************************************
    737 **
    738 ** Function         nfa_cho_add_cr_record
    739 **
    740 ** Description      Adding Collision Resolution record
    741 **
    742 **
    743 ** Returns          NDEF_OK if success
    744 **
    745 *******************************************************************************/
    746 tNDEF_STATUS nfa_cho_add_cr_record (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size)
    747 {
    748     tNDEF_STATUS status;
    749     UINT32       temp32;
    750 
    751     CHO_TRACE_DEBUG1 ("nfa_cho_add_cr_record () cur_size = %d", *p_cur_size);
    752 
    753     /* Get random number from timer */
    754     temp32 = GKI_get_tick_count ();
    755     nfa_cho_cb.tx_random_number = (UINT16) ((temp32 >> 16) ^ (temp32));
    756 
    757 #if (defined (NFA_CHO_TEST_INCLUDED) && (NFA_CHO_TEST_INCLUDED == TRUE))
    758     if (nfa_cho_cb.test_enabled & NFA_CHO_TEST_RANDOM)
    759     {
    760         nfa_cho_cb.tx_random_number = nfa_cho_cb.test_random_number;
    761     }
    762 #endif
    763 
    764     CHO_TRACE_DEBUG1 ("tx_random_number = 0x%04x", nfa_cho_cb.tx_random_number);
    765 
    766     /* Add Well-Known Type:Collistion Resolution Record */
    767     status = NDEF_MsgAddWktCr (p_msg, max_size, p_cur_size,
    768                                nfa_cho_cb.tx_random_number);
    769 
    770     return status;
    771 }
    772 
    773 /*******************************************************************************
    774 **
    775 ** Function         nfa_cho_add_ac_record
    776 **
    777 ** Description      Adding Alternative Carrier record
    778 **
    779 **
    780 ** Returns          NDEF_OK if success
    781 **
    782 *******************************************************************************/
    783 tNDEF_STATUS nfa_cho_add_ac_record (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size,
    784                                     UINT8 num_ac_info, tNFA_CHO_AC_INFO *p_ac_info,
    785                                     UINT8 *p_ndef, UINT32 max_ndef_size, UINT32 *p_cur_ndef_size)
    786 {
    787     tNDEF_STATUS status = NDEF_OK;
    788     UINT8        xx, yy;
    789     UINT8       *p_rec, *p_id, id_len;
    790     char         carrier_data_ref_str[NFA_CHO_MAX_REF_NAME_LEN];
    791     char        *aux_data_ref[NFA_CHO_MAX_AUX_DATA_COUNT];
    792     char         aux_data_ref_str[NFA_CHO_MAX_AUX_DATA_COUNT][NFA_CHO_MAX_REF_NAME_LEN];
    793 
    794     CHO_TRACE_DEBUG1 ("nfa_cho_add_ac_record (): num_ac_info = %d", num_ac_info);
    795 
    796     /* initialize auxilary data reference */
    797     for (xx = 0; xx < NFA_CHO_MAX_AUX_DATA_COUNT; xx++)
    798     {
    799         aux_data_ref[xx] = aux_data_ref_str[xx];
    800     }
    801 
    802     p_rec = p_ndef;
    803 
    804     /* Alternative Carrier Records */
    805     for (xx = 0; (xx < num_ac_info) && (status == NDEF_OK); xx++)
    806     {
    807         if (!p_rec)
    808         {
    809             status = NDEF_REC_NOT_FOUND;
    810             break;
    811         }
    812 
    813         p_id = NDEF_RecGetId (p_rec, &id_len);
    814 
    815         if ((p_id) && (id_len > 0) && (id_len <= NFA_CHO_MAX_REF_NAME_LEN))
    816         {
    817             memcpy (carrier_data_ref_str, p_id, id_len);
    818             carrier_data_ref_str[id_len] = 0x00;
    819         }
    820         else
    821         {
    822             CHO_TRACE_ERROR1 ("nfa_cho_add_ac_record ():id_len=%d", id_len);
    823             status = NDEF_REC_NOT_FOUND;
    824             break;
    825         }
    826 
    827         p_rec = NDEF_MsgGetNextRec (p_rec);
    828 
    829         /* auxilary data reference */
    830         for (yy = 0; yy < p_ac_info[xx].num_aux_data; yy++)
    831         {
    832             if (!p_rec)
    833             {
    834                 status = NDEF_REC_NOT_FOUND;
    835                 break;
    836             }
    837 
    838             p_id = NDEF_RecGetId (p_rec, &id_len);
    839 
    840             if ((p_id) && (id_len > 0) && (id_len <= NFA_CHO_MAX_REF_NAME_LEN))
    841             {
    842                 memcpy (aux_data_ref_str[yy], p_id, id_len);
    843                 aux_data_ref_str[yy][id_len] = 0x00;
    844             }
    845             else
    846             {
    847                 CHO_TRACE_ERROR1 ("nfa_cho_add_ac_record ():id_len=%d", id_len);
    848                 status = NDEF_REC_NOT_FOUND;
    849                 break;
    850             }
    851 
    852             p_rec = NDEF_MsgGetNextRec (p_rec);
    853         }
    854 
    855         if (status == NDEF_OK)
    856         {
    857             /* Add Well-Known Type:Alternative Carrier Record */
    858             status = NDEF_MsgAddWktAc (p_msg, max_size, p_cur_size,
    859                                        p_ac_info[xx].cps, carrier_data_ref_str,
    860                                        p_ac_info[xx].num_aux_data, aux_data_ref);
    861         }
    862 
    863         if (status != NDEF_OK)
    864         {
    865             break;
    866         }
    867     }
    868 
    869     return status;
    870 }
    871 
    872 /*******************************************************************************
    873 **
    874 ** Function         nfa_cho_send_hr
    875 **
    876 ** Description      Sending Handover Request Message
    877 **                  It may send one from AC list to select a specific AC.
    878 **
    879 ** Returns          NFA_STATUS_OK if success
    880 **
    881 *******************************************************************************/
    882 tNFA_STATUS nfa_cho_send_hr (tNFA_CHO_API_SEND_HR *p_api_send_hr)
    883 {
    884     tNDEF_STATUS    status;
    885     UINT8          *p_msg_cr_ac;
    886     UINT32          cur_size_cr_ac, max_size;
    887     UINT8           version;
    888 
    889     CHO_TRACE_DEBUG0 ("nfa_cho_send_hr ()");
    890 
    891     /* Collistion Resolution Record and Alternative Carrier Records */
    892 
    893     p_msg_cr_ac = (UINT8 *) GKI_getpoolbuf (LLCP_POOL_ID);
    894     if (!p_msg_cr_ac)
    895     {
    896         CHO_TRACE_ERROR0 ("Failed to allocate buffer");
    897         return NFA_STATUS_NO_BUFFERS;
    898     }
    899 
    900     max_size = LLCP_POOL_BUF_SIZE;
    901     NDEF_MsgInit (p_msg_cr_ac, max_size, &cur_size_cr_ac);
    902 
    903     /* Collistion Resolution Record */
    904     if (NDEF_OK != nfa_cho_add_cr_record (p_msg_cr_ac, max_size, &cur_size_cr_ac))
    905     {
    906         CHO_TRACE_ERROR0 ("Failed to add cr record");
    907         GKI_freebuf (p_msg_cr_ac);
    908         return NFA_STATUS_FAILED;
    909     }
    910 
    911     /* Alternative Carrier Records */
    912     if (NDEF_OK != nfa_cho_add_ac_record (p_msg_cr_ac, max_size, &cur_size_cr_ac,
    913                                           p_api_send_hr->num_ac_info, p_api_send_hr->p_ac_info,
    914                                           p_api_send_hr->p_ndef, p_api_send_hr->max_ndef_size,
    915                                           &(p_api_send_hr->cur_ndef_size)))
    916     {
    917         CHO_TRACE_ERROR0 ("Failed to add ac record");
    918         GKI_freebuf (p_msg_cr_ac);
    919         return NFA_STATUS_FAILED;
    920     }
    921 
    922     /* Handover Request Message */
    923 
    924     nfa_cho_cb.p_tx_ndef_msg = (UINT8 *) GKI_getpoolbuf (LLCP_POOL_ID);
    925     if (!nfa_cho_cb.p_tx_ndef_msg)
    926     {
    927         CHO_TRACE_ERROR0 ("Failed to allocate buffer");
    928         GKI_freebuf (p_msg_cr_ac);
    929         return NFA_STATUS_FAILED;
    930     }
    931 
    932     max_size = LLCP_POOL_BUF_SIZE;
    933 
    934     /* Handover Request Record */
    935     version = NFA_CHO_VERSION;
    936 
    937 #if (defined (NFA_CHO_TEST_INCLUDED) && (NFA_CHO_TEST_INCLUDED == TRUE))
    938     if (nfa_cho_cb.test_enabled & NFA_CHO_TEST_VERSION)
    939     {
    940         version = nfa_cho_cb.test_version;
    941     }
    942 #endif
    943 
    944     status = NDEF_MsgCreateWktHr (nfa_cho_cb.p_tx_ndef_msg, max_size, &nfa_cho_cb.tx_ndef_cur_size,
    945                                   version);
    946     if (status != NDEF_OK)
    947     {
    948         CHO_TRACE_ERROR0 ("Failed to create Hr");
    949         GKI_freebuf (nfa_cho_cb.p_tx_ndef_msg);
    950         nfa_cho_cb.p_tx_ndef_msg = NULL;
    951         GKI_freebuf (p_msg_cr_ac);
    952         return NFA_STATUS_FAILED;
    953     }
    954 
    955     /* Append Collistion Resolution Record and Alternative Carrier Records */
    956     status = NDEF_MsgAppendPayload (nfa_cho_cb.p_tx_ndef_msg, max_size, &nfa_cho_cb.tx_ndef_cur_size,
    957                                     nfa_cho_cb.p_tx_ndef_msg, p_msg_cr_ac, cur_size_cr_ac);
    958 
    959     GKI_freebuf (p_msg_cr_ac);
    960 
    961     if (status != NDEF_OK)
    962     {
    963         CHO_TRACE_ERROR0 ("Failed to add cr/ac record");
    964         GKI_freebuf (nfa_cho_cb.p_tx_ndef_msg);
    965         nfa_cho_cb.p_tx_ndef_msg = NULL;
    966         return NFA_STATUS_FAILED;
    967     }
    968 
    969 
    970     /* Append Alternative Carrier Reference Data or Handover Carrier Record */
    971     status = NDEF_MsgAppendRec (nfa_cho_cb.p_tx_ndef_msg, max_size, &nfa_cho_cb.tx_ndef_cur_size,
    972                                 p_api_send_hr->p_ndef, p_api_send_hr->cur_ndef_size);
    973 
    974     if (status != NDEF_OK)
    975     {
    976         CHO_TRACE_ERROR0 ("Failed to add ac reference data or Hc record");
    977         GKI_freebuf (nfa_cho_cb.p_tx_ndef_msg);
    978         nfa_cho_cb.p_tx_ndef_msg = NULL;
    979         return NFA_STATUS_FAILED;
    980     }
    981 
    982 #if (BT_TRACE_PROTOCOL == TRUE)
    983     DispCHO (nfa_cho_cb.p_tx_ndef_msg, nfa_cho_cb.tx_ndef_cur_size, FALSE);
    984 #endif
    985 
    986     /* Send it to peer */
    987     nfa_cho_cb.tx_ndef_sent_size = 0;
    988 
    989     status = nfa_cho_send_handover_msg ();
    990 
    991     if (status == NFA_STATUS_CONGESTED)
    992     {
    993         status = NFA_STATUS_OK;
    994     }
    995 
    996     return status;
    997 }
    998 
    999 /*******************************************************************************
   1000 **
   1001 ** Function         nfa_cho_send_hs
   1002 **
   1003 ** Description      Send Handover Select Message
   1004 **
   1005 **
   1006 ** Returns          NFA_STATUS_OK if success
   1007 **
   1008 *******************************************************************************/
   1009 tNFA_STATUS nfa_cho_send_hs (tNFA_CHO_API_SEND_HS *p_api_select)
   1010 {
   1011     tNDEF_STATUS    status;
   1012     UINT8          *p_msg_ac;
   1013     UINT32          cur_size_ac = 0, max_size;
   1014     UINT8           version;
   1015 
   1016     CHO_TRACE_DEBUG1 ("nfa_cho_send_hs () num_ac_info=%d", p_api_select->num_ac_info);
   1017 
   1018     if (p_api_select->num_ac_info > 0)
   1019     {
   1020         /* Alternative Carrier Records */
   1021 
   1022         p_msg_ac = (UINT8 *) GKI_getpoolbuf (LLCP_POOL_ID);
   1023 
   1024         if (!p_msg_ac)
   1025         {
   1026             CHO_TRACE_ERROR0 ("Failed to allocate buffer");
   1027             return NFA_STATUS_FAILED;
   1028         }
   1029 
   1030         max_size = LLCP_POOL_BUF_SIZE;
   1031         NDEF_MsgInit (p_msg_ac, max_size, &cur_size_ac);
   1032 
   1033         if (NDEF_OK != nfa_cho_add_ac_record (p_msg_ac, max_size, &cur_size_ac,
   1034                                               p_api_select->num_ac_info, p_api_select->p_ac_info,
   1035                                               p_api_select->p_ndef, p_api_select->max_ndef_size,
   1036                                               &(p_api_select->cur_ndef_size)))
   1037         {
   1038             CHO_TRACE_ERROR0 ("Failed to add ac record");
   1039             GKI_freebuf (p_msg_ac);
   1040             return NFA_STATUS_FAILED;
   1041         }
   1042     }
   1043     else
   1044     {
   1045         p_msg_ac = NULL;
   1046     }
   1047 
   1048     /* Handover Select Message */
   1049     nfa_cho_cb.p_tx_ndef_msg = (UINT8 *) GKI_getpoolbuf (LLCP_POOL_ID);
   1050 
   1051     if (!nfa_cho_cb.p_tx_ndef_msg)
   1052     {
   1053         CHO_TRACE_ERROR0 ("Failed to allocate buffer");
   1054 
   1055         if (p_msg_ac)
   1056             GKI_freebuf (p_msg_ac);
   1057 
   1058         return NFA_STATUS_FAILED;
   1059     }
   1060     max_size = LLCP_POOL_BUF_SIZE;
   1061 
   1062     /* Handover Select Record */
   1063     version = NFA_CHO_VERSION;
   1064 
   1065 #if (defined (NFA_CHO_TEST_INCLUDED) && (NFA_CHO_TEST_INCLUDED == TRUE))
   1066     if (nfa_cho_cb.test_enabled & NFA_CHO_TEST_VERSION)
   1067     {
   1068         version = nfa_cho_cb.test_version;
   1069     }
   1070 #endif
   1071     status = NDEF_MsgCreateWktHs (nfa_cho_cb.p_tx_ndef_msg, max_size, &nfa_cho_cb.tx_ndef_cur_size,
   1072                                   version);
   1073 
   1074     if (status != NDEF_OK)
   1075     {
   1076         CHO_TRACE_ERROR0 ("Failed to create Hs");
   1077 
   1078         GKI_freebuf (nfa_cho_cb.p_tx_ndef_msg);
   1079         nfa_cho_cb.p_tx_ndef_msg = NULL;
   1080 
   1081         if (p_msg_ac)
   1082             GKI_freebuf (p_msg_ac);
   1083 
   1084         return NFA_STATUS_FAILED;
   1085     }
   1086 
   1087     if (p_api_select->num_ac_info > 0)
   1088     {
   1089         /* Append Alternative Carrier Records */
   1090         status = NDEF_MsgAppendPayload (nfa_cho_cb.p_tx_ndef_msg, max_size, &nfa_cho_cb.tx_ndef_cur_size,
   1091                                         nfa_cho_cb.p_tx_ndef_msg, p_msg_ac, cur_size_ac);
   1092 
   1093         if (p_msg_ac)
   1094             GKI_freebuf (p_msg_ac);
   1095 
   1096         if (status != NDEF_OK)
   1097         {
   1098             CHO_TRACE_ERROR0 ("Failed to add cr record");
   1099             GKI_freebuf (nfa_cho_cb.p_tx_ndef_msg);
   1100             nfa_cho_cb.p_tx_ndef_msg = NULL;
   1101             return NFA_STATUS_FAILED;
   1102         }
   1103 
   1104         /* Append Alternative Carrier Reference Data */
   1105         status = NDEF_MsgAppendRec (nfa_cho_cb.p_tx_ndef_msg, max_size, &nfa_cho_cb.tx_ndef_cur_size,
   1106                                     p_api_select->p_ndef, p_api_select->cur_ndef_size);
   1107 
   1108         if (status != NDEF_OK)
   1109         {
   1110             CHO_TRACE_ERROR0 ("Failed to add ac reference data record");
   1111             GKI_freebuf (nfa_cho_cb.p_tx_ndef_msg);
   1112             nfa_cho_cb.p_tx_ndef_msg = NULL;
   1113             return NFA_STATUS_FAILED;
   1114         }
   1115     }
   1116 
   1117 #if (BT_TRACE_PROTOCOL == TRUE)
   1118     DispCHO (nfa_cho_cb.p_tx_ndef_msg, nfa_cho_cb.tx_ndef_cur_size, FALSE);
   1119 #endif
   1120 
   1121     /* Send it to peer */
   1122     nfa_cho_cb.tx_ndef_sent_size = 0;
   1123 
   1124     status = nfa_cho_send_handover_msg ();
   1125 
   1126     if (status == NFA_STATUS_CONGESTED)
   1127     {
   1128         status = NFA_STATUS_OK;
   1129     }
   1130     return status;
   1131 }
   1132 
   1133 /*******************************************************************************
   1134 **
   1135 ** Function         nfa_cho_send_hs_error
   1136 **
   1137 ** Description      Sending Handover Select Message with error record
   1138 **
   1139 **
   1140 ** Returns          NFA_STATUS_OK if success
   1141 **
   1142 *******************************************************************************/
   1143 tNFA_STATUS nfa_cho_send_hs_error (UINT8 error_reason, UINT32 error_data)
   1144 {
   1145     tNDEF_STATUS    status;
   1146     UINT8           version;
   1147     UINT32          max_size;
   1148 
   1149     CHO_TRACE_DEBUG2 ("nfa_cho_send_hs_error () error_reason=0x%x, error_data=0x%x",
   1150                        error_reason, error_data);
   1151 
   1152     /* Handover Select Message */
   1153     nfa_cho_cb.p_tx_ndef_msg = (UINT8 *) GKI_getpoolbuf (LLCP_POOL_ID);
   1154 
   1155     if (!nfa_cho_cb.p_tx_ndef_msg)
   1156     {
   1157         CHO_TRACE_ERROR0 ("Failed to allocate buffer");
   1158         return NFA_STATUS_FAILED;
   1159     }
   1160 
   1161     max_size = LLCP_POOL_BUF_SIZE;
   1162 
   1163     /* Handover Select Record with Version */
   1164     version = NFA_CHO_VERSION;
   1165 
   1166 #if (defined (NFA_CHO_TEST_INCLUDED) && (NFA_CHO_TEST_INCLUDED == TRUE))
   1167     if (nfa_cho_cb.test_enabled & NFA_CHO_TEST_VERSION)
   1168     {
   1169         version = nfa_cho_cb.test_version;
   1170     }
   1171 #endif
   1172     status = NDEF_MsgCreateWktHs (nfa_cho_cb.p_tx_ndef_msg, max_size, &nfa_cho_cb.tx_ndef_cur_size,
   1173                                   version);
   1174 
   1175     if (status != NDEF_OK)
   1176     {
   1177         CHO_TRACE_ERROR0 ("Failed to create Hs");
   1178 
   1179         GKI_freebuf (nfa_cho_cb.p_tx_ndef_msg);
   1180         nfa_cho_cb.p_tx_ndef_msg = NULL;
   1181 
   1182         return NFA_STATUS_FAILED;
   1183     }
   1184 
   1185     /* Add Error Records */
   1186     status = NDEF_MsgAddWktErr (nfa_cho_cb.p_tx_ndef_msg, max_size, &nfa_cho_cb.tx_ndef_cur_size,
   1187                                 error_reason, error_data);
   1188 
   1189     if (status != NDEF_OK)
   1190     {
   1191         CHO_TRACE_ERROR0 ("Failed to add err record");
   1192 
   1193         GKI_freebuf (nfa_cho_cb.p_tx_ndef_msg);
   1194         nfa_cho_cb.p_tx_ndef_msg = NULL;
   1195 
   1196         return NFA_STATUS_FAILED;
   1197     }
   1198 
   1199 #if (BT_TRACE_PROTOCOL == TRUE)
   1200     DispCHO (nfa_cho_cb.p_tx_ndef_msg, nfa_cho_cb.tx_ndef_cur_size, FALSE);
   1201 #endif
   1202 
   1203     /* Send it to peer */
   1204     nfa_cho_cb.tx_ndef_sent_size = 0;
   1205 
   1206     status = nfa_cho_send_handover_msg ();
   1207 
   1208     if (status == NFA_STATUS_CONGESTED)
   1209     {
   1210         status = NFA_STATUS_OK;
   1211     }
   1212     return status;
   1213 }
   1214 
   1215 /*******************************************************************************
   1216 **
   1217 ** Function         nfa_cho_get_random_number
   1218 **
   1219 ** Description      Return random number in Handover Request message
   1220 **
   1221 **
   1222 ** Returns          random number in "cr" record
   1223 **
   1224 *******************************************************************************/
   1225 UINT16 nfa_cho_get_random_number (UINT8 *p_ndef_msg)
   1226 {
   1227     UINT16 random_number;
   1228     UINT8 *p_cr_record, *p_cr_payload;
   1229     UINT32 cr_payload_len;
   1230 
   1231     CHO_TRACE_DEBUG0 ("nfa_cho_get_random_number ()");
   1232 
   1233     /* find Collision Resolution record */
   1234     p_cr_record = NDEF_MsgGetFirstRecByType (p_ndef_msg, NDEF_TNF_WKT, cr_rec_type, CR_REC_TYPE_LEN);
   1235 
   1236     if (!p_cr_record)
   1237     {
   1238         CHO_TRACE_ERROR0 ("Failed to find cr record");
   1239         return 0;
   1240     }
   1241 
   1242     /* get start of payload in Collision Resolution record */
   1243     p_cr_payload = NDEF_RecGetPayload (p_cr_record, &cr_payload_len);
   1244 
   1245     if ((!p_cr_payload) || (cr_payload_len != 2))
   1246     {
   1247         CHO_TRACE_ERROR0 ("Failed to get cr payload (random number)");
   1248         return 0;
   1249     }
   1250 
   1251     /* get random number from payload */
   1252     BE_STREAM_TO_UINT16 (random_number, p_cr_payload);
   1253 
   1254     return random_number;
   1255 }
   1256 
   1257 /*******************************************************************************
   1258 **
   1259 ** Function         nfa_cho_parse_ac_records
   1260 **
   1261 ** Description      Parsing NDEF message to retrieve Alternative Carrier records
   1262 **                  and store into tNFA_CHO_AC_REC
   1263 **
   1264 ** Returns          tNFA_STATUS
   1265 **
   1266 *******************************************************************************/
   1267 tNFA_STATUS nfa_cho_parse_ac_records (UINT8 *p_ndef_msg, UINT8 *p_num_ac_rec, tNFA_CHO_AC_REC *p_ac_rec)
   1268 {
   1269     UINT8 *p_ac_record, *p_ac_payload;
   1270     UINT32 ac_payload_len;
   1271 
   1272     UINT8  xx, yy;
   1273 
   1274     CHO_TRACE_DEBUG0 ("nfa_cho_parse_ac_records ()");
   1275 
   1276     /* get Alternative Carrier record */
   1277     p_ac_record = NDEF_MsgGetFirstRecByType (p_ndef_msg, NDEF_TNF_WKT, ac_rec_type, AC_REC_TYPE_LEN);
   1278 
   1279     xx = 0;
   1280 
   1281     while ((p_ac_record) && (xx < NFA_CHO_MAX_AC_INFO))
   1282     {
   1283         /* get payload */
   1284         p_ac_payload = NDEF_RecGetPayload (p_ac_record, &ac_payload_len);
   1285 
   1286         if ((!p_ac_payload) || (ac_payload_len < 3))
   1287         {
   1288             CHO_TRACE_ERROR0 ("Failed to get ac payload");
   1289             return NFA_STATUS_FAILED;
   1290         }
   1291 
   1292         /* Carrier Power State */
   1293         BE_STREAM_TO_UINT8 (p_ac_rec->cps, p_ac_payload);
   1294 
   1295         /* Carrier Data Reference Length and Characters */
   1296         BE_STREAM_TO_UINT8 (p_ac_rec->carrier_data_ref.ref_len, p_ac_payload);
   1297 
   1298         ac_payload_len -= 2;
   1299 
   1300         /* remaining must have carrier data ref and Auxiliary Data Reference Count at least */
   1301         if (ac_payload_len > p_ac_rec->carrier_data_ref.ref_len)
   1302         {
   1303             if (p_ac_rec->carrier_data_ref.ref_len > NFA_CHO_MAX_REF_NAME_LEN)
   1304             {
   1305                 CHO_TRACE_ERROR1 ("Too many bytes for carrier_data_ref, ref_len = %d",
   1306                                    p_ac_rec->carrier_data_ref.ref_len);
   1307                 return NFA_STATUS_FAILED;
   1308             }
   1309 
   1310             BE_STREAM_TO_ARRAY (p_ac_payload,
   1311                                 p_ac_rec->carrier_data_ref.ref_name,
   1312                                 p_ac_rec->carrier_data_ref.ref_len);
   1313             ac_payload_len -= p_ac_rec->carrier_data_ref.ref_len;
   1314         }
   1315         else
   1316         {
   1317             CHO_TRACE_ERROR0 ("Failed to parse carrier_data_ref.ref_len");
   1318             return NFA_STATUS_FAILED;
   1319         }
   1320 
   1321         /* Auxiliary Data Reference Count */
   1322         BE_STREAM_TO_UINT8 (p_ac_rec->aux_data_ref_count, p_ac_payload);
   1323         ac_payload_len--;
   1324 
   1325         /* Auxiliary Data Reference Length and Characters */
   1326         for (yy = 0; (yy < p_ac_rec->aux_data_ref_count) && (yy < NFA_CHO_MAX_AUX_DATA_COUNT); yy++)
   1327         {
   1328             if (ac_payload_len > 0)
   1329             {
   1330                 BE_STREAM_TO_UINT8 (p_ac_rec->aux_data_ref[yy].ref_len, p_ac_payload);
   1331                 ac_payload_len--;
   1332 
   1333                 if (ac_payload_len >= p_ac_rec->aux_data_ref[yy].ref_len)
   1334                 {
   1335                     if (p_ac_rec->aux_data_ref[yy].ref_len > NFA_CHO_MAX_REF_NAME_LEN)
   1336                     {
   1337                         CHO_TRACE_ERROR2 ("Too many bytes for aux_data_ref[%d], ref_len=%d",
   1338                                            yy, p_ac_rec->aux_data_ref[yy].ref_len);
   1339                         return NFA_STATUS_FAILED;
   1340                     }
   1341 
   1342                     BE_STREAM_TO_ARRAY (p_ac_payload,
   1343                                         p_ac_rec->aux_data_ref[yy].ref_name,
   1344                                         p_ac_rec->aux_data_ref[yy].ref_len);
   1345                     ac_payload_len -= p_ac_rec->aux_data_ref[yy].ref_len;
   1346                 }
   1347                 else
   1348                 {
   1349                     CHO_TRACE_ERROR1 ("Failed to parse ref_name for aux_data_ref[%d]", yy);
   1350                     return NFA_STATUS_FAILED;
   1351                 }
   1352             }
   1353             else
   1354             {
   1355                 CHO_TRACE_ERROR1 ("Failed to parse ref_len for aux_data_ref[%d]", yy);
   1356                 return NFA_STATUS_FAILED;
   1357             }
   1358         }
   1359 
   1360         if (ac_payload_len != 0)
   1361         {
   1362             CHO_TRACE_WARNING1 ("Found extra data in AC record[%d]", xx);
   1363         }
   1364 
   1365         xx++;
   1366         p_ac_rec++;
   1367 
   1368         /* get next Alternative Carrier record */
   1369         p_ac_record = NDEF_MsgGetNextRecByType (p_ac_record, NDEF_TNF_WKT, ac_rec_type, AC_REC_TYPE_LEN);
   1370     }
   1371 
   1372     *p_num_ac_rec = xx;
   1373 
   1374     return NFA_STATUS_OK;
   1375 }
   1376 
   1377 /*******************************************************************************
   1378 **
   1379 ** Function         nfa_cho_parse_hr_record
   1380 **
   1381 ** Description      Parsing Handover Request message to retrieve version, random number,
   1382 **                  Alternative Carrier records and store into tNFA_CHO_AC_REC
   1383 **
   1384 **
   1385 ** Returns          tNFA_STATUS
   1386 **
   1387 *******************************************************************************/
   1388 tNFA_STATUS nfa_cho_parse_hr_record (UINT8  *p_ndef_msg,
   1389                                      UINT8  *p_version,
   1390                                      UINT16 *p_random_number,
   1391                                      UINT8  *p_num_ac_rec,
   1392                                      tNFA_CHO_AC_REC *p_ac_rec)
   1393 {
   1394     UINT8 *p_hr_record, *p_hr_payload;
   1395     UINT32 hr_payload_len;
   1396 
   1397     CHO_TRACE_DEBUG0 ("nfa_cho_parse_hr_record ()");
   1398 
   1399     /* get Handover Request record */
   1400     p_hr_record = NDEF_MsgGetFirstRecByType (p_ndef_msg, NDEF_TNF_WKT, hr_rec_type, HR_REC_TYPE_LEN);
   1401 
   1402     if (!p_hr_record)
   1403     {
   1404         CHO_TRACE_ERROR0 ("Failed to find Hr record");
   1405         return NFA_STATUS_FAILED;
   1406     }
   1407 
   1408     p_hr_payload = NDEF_RecGetPayload (p_hr_record, &hr_payload_len);
   1409 
   1410     if ((!p_hr_payload) || (hr_payload_len < 7))
   1411     {
   1412         CHO_TRACE_ERROR0 ("Failed to get Hr payload (version, cr/ac record)");
   1413         return NFA_STATUS_FAILED;
   1414     }
   1415 
   1416     /* Version */
   1417     STREAM_TO_UINT8 ((*p_version), p_hr_payload);
   1418     hr_payload_len--;
   1419 
   1420     /* NDEF message for Collision Resolution record and Alternative Carrier records */
   1421 
   1422     if (NDEF_OK != NDEF_MsgValidate (p_hr_payload, hr_payload_len, FALSE))
   1423     {
   1424         CHO_TRACE_ERROR0 ("Failed to validate NDEF message for cr/ac records");
   1425         return NFA_STATUS_FAILED;
   1426     }
   1427 
   1428     /* Collision Resolution record */
   1429     if (p_random_number)
   1430     {
   1431         *p_random_number = nfa_cho_get_random_number (p_hr_payload);
   1432     }
   1433 
   1434     /* Alternative Carrier records */
   1435     if (p_ac_rec)
   1436     {
   1437         return (nfa_cho_parse_ac_records (p_hr_payload, p_num_ac_rec, p_ac_rec));
   1438     }
   1439 
   1440     return NFA_STATUS_OK;
   1441 }
   1442 
   1443 /*******************************************************************************
   1444 **
   1445 ** Function         nfa_cho_parse_carrier_config
   1446 **
   1447 ** Description      Parse Alternative Carrier Configuration and Aux Data
   1448 **
   1449 **
   1450 ** Returns          tNFA_STATUS
   1451 **
   1452 *******************************************************************************/
   1453 tNFA_STATUS nfa_cho_parse_carrier_config (UINT8 *p_ndef_msg, UINT8 num_ac_rec, tNFA_CHO_AC_REC *p_ac_rec)
   1454 {
   1455     UINT8  *p_record;
   1456     UINT8   xx, yy;
   1457 
   1458     CHO_TRACE_DEBUG1 ("nfa_cho_parse_carrier_config () num_ac_rec = %d", num_ac_rec);
   1459 
   1460     /* Parse Alternative Carrier Configuration and Aux Data */
   1461     for (xx = 0; xx < num_ac_rec; xx++)
   1462     {
   1463         p_record = NDEF_MsgGetFirstRecById (p_ndef_msg,
   1464                                             p_ac_rec->carrier_data_ref.ref_name,
   1465                                             p_ac_rec->carrier_data_ref.ref_len);
   1466 
   1467         if (!p_record)
   1468         {
   1469             CHO_TRACE_ERROR2 ("Failed to find Payload ID: len=%d, [0x%x ...]",
   1470                               p_ac_rec->carrier_data_ref.ref_len,
   1471                               p_ac_rec->carrier_data_ref.ref_name[0]);
   1472             return NFA_STATUS_FAILED;
   1473         }
   1474 
   1475         for (yy = 0; yy < p_ac_rec->aux_data_ref_count; yy++)
   1476         {
   1477             /* Get aux data record by Payload ID */
   1478             p_record = NDEF_MsgGetFirstRecById (p_ndef_msg,
   1479                                                 p_ac_rec->aux_data_ref[yy].ref_name,
   1480                                                 p_ac_rec->aux_data_ref[yy].ref_len);
   1481 
   1482             if (!p_record)
   1483             {
   1484                 CHO_TRACE_ERROR2 ("Failed to find Payload ID for Aux: len=%d, [0x%x ...]",
   1485                                   p_ac_rec->aux_data_ref[yy].ref_len,
   1486                                   p_ac_rec->aux_data_ref[yy].ref_name[0]);
   1487                 return NFA_STATUS_FAILED;
   1488             }
   1489         }
   1490 
   1491         p_ac_rec++;
   1492     }
   1493 
   1494     return NFA_STATUS_OK;
   1495 }
   1496 
   1497 /*******************************************************************************
   1498 **
   1499 ** Function         nfa_cho_proc_hr
   1500 **
   1501 ** Description      Parse Handover Request Message
   1502 **                  In case of parsing error, let peer got timeout (1 sec).
   1503 **
   1504 **
   1505 ** Returns          None
   1506 **
   1507 *******************************************************************************/
   1508 void nfa_cho_proc_hr (UINT32 length, UINT8 *p_ndef_msg)
   1509 {
   1510     tNFA_CHO_EVT_DATA    evt_data;
   1511     tNFA_CHO_API_SEND_HS select;
   1512     UINT8  version;
   1513     UINT16 random_number;
   1514 
   1515     CHO_TRACE_DEBUG1 ("nfa_cho_proc_hr () length=%d", length);
   1516 
   1517     /* Parse Handover Request record */
   1518     if (NDEF_OK != nfa_cho_parse_hr_record (p_ndef_msg, &version, &random_number,
   1519                                             &evt_data.request.num_ac_rec,
   1520                                             &evt_data.request.ac_rec[0]))
   1521     {
   1522         CHO_TRACE_ERROR0 ("Failed to parse hr record");
   1523         return;
   1524     }
   1525 
   1526     if (version != NFA_CHO_VERSION)
   1527     {
   1528         CHO_TRACE_DEBUG1 ("Version (0x%02x) not matched", version);
   1529         /* For the future, */
   1530         /* if we have higher major then support peer's version */
   1531         /* if we have lower major then send empty handover select message */
   1532         if (NFA_CHO_GET_MAJOR_VERSION (version) > NFA_CHO_GET_MAJOR_VERSION (NFA_CHO_VERSION))
   1533         {
   1534             select.num_ac_info = 0;
   1535             nfa_cho_send_hs (&select);
   1536             return;
   1537         }
   1538     }
   1539 
   1540     if (NFA_STATUS_OK != nfa_cho_parse_carrier_config (p_ndef_msg,
   1541                                                        evt_data.request.num_ac_rec,
   1542                                                        &evt_data.request.ac_rec[0]))
   1543     {
   1544         CHO_TRACE_ERROR0 ("Failed to parse carrier configuration");
   1545 
   1546         evt_data.request.status       = NFA_STATUS_FAILED;
   1547         evt_data.request.num_ac_rec   = 0;
   1548         evt_data.request.p_ref_ndef   = NULL;
   1549         evt_data.request.ref_ndef_len = 0;
   1550 
   1551         nfa_cho_cb.p_cback (NFA_CHO_REQUEST_EVT, &evt_data);
   1552         return;
   1553     }
   1554 
   1555     if (evt_data.request.num_ac_rec)
   1556     {
   1557         /* passing alternative carrier references */
   1558         evt_data.request.p_ref_ndef   = NDEF_MsgGetNextRec (p_ndef_msg);
   1559         *evt_data.request.p_ref_ndef |= NDEF_MB_MASK;
   1560         evt_data.request.ref_ndef_len = (UINT32)(length - (evt_data.request.p_ref_ndef - p_ndef_msg));
   1561     }
   1562     else
   1563     {
   1564         evt_data.request.p_ref_ndef   = NULL;
   1565         evt_data.request.ref_ndef_len = 0;
   1566     }
   1567 
   1568     evt_data.request.status = NFA_STATUS_OK;
   1569 
   1570     nfa_cho_cb.p_cback (NFA_CHO_REQUEST_EVT, &evt_data);
   1571 }
   1572 
   1573 /*******************************************************************************
   1574 **
   1575 ** Function         nfa_cho_get_error
   1576 **
   1577 ** Description      Search Error record and parse it
   1578 **
   1579 **
   1580 ** Returns          tNFA_STATUS
   1581 **
   1582 *******************************************************************************/
   1583 tNFA_STATUS nfa_cho_get_error (UINT8 *p_ndef_msg, UINT8 *p_error_reason, UINT32 *p_error_data)
   1584 {
   1585     UINT8 *p_err_record, *p_err_payload, u8;
   1586     UINT32 err_payload_len;
   1587 
   1588     CHO_TRACE_DEBUG0 ("nfa_cho_get_error ()");
   1589 
   1590     p_err_record = NDEF_MsgGetFirstRecByType (p_ndef_msg, NDEF_TNF_WKT, err_rec_type, ERR_REC_TYPE_LEN);
   1591 
   1592     if (!p_err_record)
   1593     {
   1594         CHO_TRACE_DEBUG0 ("Found no err record");
   1595         return NFA_STATUS_FAILED;
   1596     }
   1597 
   1598     p_err_payload = NDEF_RecGetPayload (p_err_record, &err_payload_len);
   1599 
   1600     if (!p_err_payload)
   1601     {
   1602         CHO_TRACE_ERROR0 ("Failed to get err payload");
   1603         return NFA_STATUS_SYNTAX_ERROR;
   1604     }
   1605 
   1606     BE_STREAM_TO_UINT8 (*p_error_reason, p_err_payload);
   1607 
   1608     if (  (err_payload_len == 2)
   1609         &&(  (*p_error_reason == NFA_CHO_ERROR_TEMP_MEM)
   1610            ||(*p_error_reason == NFA_CHO_ERROR_CARRIER)  )  )
   1611     {
   1612         BE_STREAM_TO_UINT8 (u8, p_err_payload);
   1613         *p_error_data = (UINT32)u8;
   1614     }
   1615     else if (  (err_payload_len == 5)
   1616              &&(*p_error_reason == NFA_CHO_ERROR_PERM_MEM)  )
   1617     {
   1618         BE_STREAM_TO_UINT32 (*p_error_data, p_err_payload);
   1619     }
   1620     else
   1621     {
   1622         CHO_TRACE_ERROR2 ("Unknown error reason = %d, err_payload_len = %d",
   1623                           *p_error_reason, err_payload_len);
   1624         return NFA_STATUS_SYNTAX_ERROR;
   1625     }
   1626 
   1627     CHO_TRACE_DEBUG2 ("error_reason=0x%x, error_data=0x%x", *p_error_reason, *p_error_data);
   1628 
   1629     return NFA_STATUS_OK;
   1630 }
   1631 
   1632 /*******************************************************************************
   1633 **
   1634 ** Function         nfa_cho_parse_hs_record
   1635 **
   1636 ** Description      Parse Handover Select record
   1637 **
   1638 **
   1639 ** Returns          tNFA_STATUS
   1640 **
   1641 *******************************************************************************/
   1642 tNFA_STATUS nfa_cho_parse_hs_record (UINT8  *p_ndef_msg,
   1643                                      UINT8  *p_version,
   1644                                      UINT8  *p_num_ac_rec,
   1645                                      tNFA_CHO_AC_REC *p_ac_rec,
   1646                                      UINT8  *p_error_reason,
   1647                                      UINT32 *p_error_data)
   1648 {
   1649     tNFA_STATUS status;
   1650     UINT8 *p_hs_record, *p_hs_payload;
   1651     UINT32 hs_payload_len;
   1652 
   1653     CHO_TRACE_DEBUG0 ("nfa_cho_parse_hs_record ()");
   1654 
   1655     /* get Handover Select record */
   1656     p_hs_record = NDEF_MsgGetFirstRecByType (p_ndef_msg, NDEF_TNF_WKT, hs_rec_type, HS_REC_TYPE_LEN);
   1657 
   1658     if (!p_hs_record)
   1659     {
   1660         CHO_TRACE_ERROR0 ("Failed to find Hs record");
   1661         return NFA_STATUS_FAILED;
   1662     }
   1663 
   1664     p_hs_payload = NDEF_RecGetPayload (p_hs_record, &hs_payload_len);
   1665 
   1666     if ((!p_hs_payload) || (hs_payload_len < 1))  /* at least version */
   1667     {
   1668         CHO_TRACE_ERROR0 ("Failed to get Hs payload (version, ac record)");
   1669         return NFA_STATUS_FAILED;
   1670     }
   1671 
   1672     STREAM_TO_UINT8 ((*p_version), p_hs_payload);
   1673     hs_payload_len--;
   1674 
   1675     /* Check if error record is sent */
   1676     status = nfa_cho_get_error (p_ndef_msg, p_error_reason, p_error_data);
   1677 
   1678     if (status == NFA_STATUS_SYNTAX_ERROR)
   1679     {
   1680         return NFA_STATUS_FAILED;
   1681     }
   1682     else if (status == NFA_STATUS_OK)
   1683     {
   1684         return NFA_STATUS_OK;
   1685     }
   1686 
   1687     if (hs_payload_len >= 3 )
   1688     {
   1689         /* NDEF message for Alternative Carrier records */
   1690         if (NDEF_OK != NDEF_MsgValidate (p_hs_payload, hs_payload_len, FALSE))
   1691         {
   1692             CHO_TRACE_ERROR0 ("Failed to validate NDEF message for ac records");
   1693             return NFA_STATUS_FAILED;
   1694         }
   1695 
   1696         /* Alternative Carrier records */
   1697         if (p_ac_rec)
   1698         {
   1699             if (NFA_STATUS_OK != nfa_cho_parse_ac_records (p_hs_payload, p_num_ac_rec, p_ac_rec))
   1700             {
   1701                 return NFA_STATUS_FAILED;
   1702             }
   1703 
   1704             CHO_TRACE_DEBUG1 ("Found %d ac record", *p_num_ac_rec);
   1705         }
   1706     }
   1707     else
   1708     {
   1709         CHO_TRACE_DEBUG0 ("Empty Handover Select Message");
   1710         *p_num_ac_rec = 0;
   1711     }
   1712 
   1713     return NFA_STATUS_OK;
   1714 }
   1715 
   1716 /*******************************************************************************
   1717 **
   1718 ** Function         nfa_cho_proc_hs
   1719 **
   1720 ** Description      Parse Handover Select Message
   1721 **
   1722 **
   1723 ** Returns          FALSE if we need to select one from inactive ACs
   1724 **
   1725 *******************************************************************************/
   1726 void nfa_cho_proc_hs (UINT32 length, UINT8 *p_ndef_msg)
   1727 {
   1728     tNFA_CHO_EVT_DATA evt_data;
   1729     UINT8  version, error_reason = 0;
   1730     UINT32 error_data;
   1731 
   1732     CHO_TRACE_DEBUG0 ("nfa_cho_proc_hs ()");
   1733 
   1734     evt_data.select.status = NFA_STATUS_OK;
   1735 
   1736     /* Parse Handover Select record */
   1737     if (NFA_STATUS_OK != nfa_cho_parse_hs_record (p_ndef_msg, &version,
   1738                                                   &evt_data.select.num_ac_rec,
   1739                                                   &evt_data.select.ac_rec[0],
   1740                                                   &error_reason, &error_data))
   1741     {
   1742         CHO_TRACE_ERROR0 ("Failed to parse hs record");
   1743 
   1744         evt_data.select.status = NFA_STATUS_FAILED;
   1745     }
   1746 
   1747     if (  (evt_data.select.status == NFA_STATUS_OK)
   1748         &&(error_reason != 0)  )
   1749     {
   1750         /* We got error records */
   1751         evt_data.sel_err.error_reason = error_reason;
   1752         evt_data.sel_err.error_data   = error_data;
   1753 
   1754         nfa_cho_cb.p_cback (NFA_CHO_SEL_ERR_EVT, &evt_data);
   1755         return;
   1756     }
   1757 
   1758     if (  (evt_data.select.status == NFA_STATUS_OK)
   1759         &&(version != NFA_CHO_VERSION)  )
   1760     {
   1761         CHO_TRACE_ERROR1 ("Version (0x%02x) not matched", version);
   1762 
   1763         evt_data.select.status = NFA_STATUS_FAILED;
   1764     }
   1765 
   1766     /* parse Alternative Carrier information */
   1767 
   1768     if (  (evt_data.select.status == NFA_STATUS_OK)
   1769         &&(NFA_STATUS_OK != nfa_cho_parse_carrier_config (p_ndef_msg,
   1770                                                           evt_data.select.num_ac_rec,
   1771                                                           &evt_data.select.ac_rec[0]))  )
   1772     {
   1773         CHO_TRACE_ERROR0 ("Failed to parse carrier configuration");
   1774 
   1775         evt_data.select.status = NFA_STATUS_FAILED;
   1776     }
   1777 
   1778     if (evt_data.select.status == NFA_STATUS_OK)
   1779     {
   1780         if (evt_data.select.num_ac_rec)
   1781         {
   1782             /* passing alternative carrier references */
   1783             evt_data.select.p_ref_ndef   = NDEF_MsgGetNextRec (p_ndef_msg);
   1784             *evt_data.select.p_ref_ndef |= NDEF_MB_MASK;
   1785             evt_data.select.ref_ndef_len = (UINT32)(length - (evt_data.select.p_ref_ndef - p_ndef_msg));
   1786         }
   1787         else
   1788         {
   1789             evt_data.select.p_ref_ndef   = NULL;
   1790             evt_data.select.ref_ndef_len = 0;
   1791         }
   1792     }
   1793     else
   1794     {
   1795         evt_data.select.num_ac_rec   = 0;
   1796         evt_data.select.p_ref_ndef   = NULL;
   1797         evt_data.select.ref_ndef_len = 0;
   1798     }
   1799 
   1800     nfa_cho_cb.p_cback (NFA_CHO_SELECT_EVT, &evt_data);
   1801 }
   1802 
   1803 /*******************************************************************************
   1804 **
   1805 ** Function         nfa_cho_proc_simplified_format
   1806 **
   1807 ** Description      Parse simplified BT OOB/Wifi Message
   1808 **
   1809 **
   1810 ** Returns          void
   1811 **
   1812 *******************************************************************************/
   1813 void nfa_cho_proc_simplified_format (UINT32 length, UINT8 *p_ndef_msg)
   1814 {
   1815     tNFA_CHO_EVT_DATA evt_data;
   1816 
   1817     CHO_TRACE_DEBUG0 ("nfa_cho_proc_simplified_format ()");
   1818 
   1819     evt_data.select.status = NFA_STATUS_OK;
   1820 
   1821     evt_data.select.num_ac_rec = 1;
   1822 
   1823     evt_data.select.ac_rec[0].cps = NFA_CHO_CPS_UNKNOWN;
   1824     evt_data.select.ac_rec[0].carrier_data_ref.ref_len = 0;
   1825     evt_data.select.ac_rec[0].aux_data_ref_count       = 0;
   1826 
   1827     evt_data.select.p_ref_ndef   = p_ndef_msg;
   1828     evt_data.select.ref_ndef_len = length;
   1829 
   1830     nfa_cho_cb.p_cback (NFA_CHO_SELECT_EVT, &evt_data);
   1831 }
   1832 
   1833 /*******************************************************************************
   1834 **
   1835 ** Function         nfa_cho_get_msg_type
   1836 **
   1837 ** Description      Get handover message type to check collision
   1838 **
   1839 **
   1840 ** Returns          NFA_CHO_MSG_HR if it has Handover Request record
   1841 **                  NFA_CHO_MSG_HS if it has Handover Select record
   1842 **                  NFA_CHO_MSG_BT_OOB if it has simplified BT OOB record
   1843 **                  NFA_CHO_MSG_WIFI if it has simplified WiFi record
   1844 **                  NFA_CHO_MSG_UNKNOWN, otherwise
   1845 **
   1846 *******************************************************************************/
   1847 tNFA_CHO_MSG_TYPE nfa_cho_get_msg_type (UINT32 length, UINT8 *p_ndef_msg)
   1848 {
   1849     UINT8 *p_record;
   1850 
   1851     CHO_TRACE_DEBUG1 ("nfa_cho_get_msg_type () length=%d", length);
   1852 
   1853     p_record = NDEF_MsgGetFirstRecByType (p_ndef_msg, NDEF_TNF_WKT, hr_rec_type, HR_REC_TYPE_LEN);
   1854 
   1855     if (p_record)
   1856     {
   1857         CHO_TRACE_DEBUG0 ("Found Hr record");
   1858         return NFA_CHO_MSG_HR;
   1859     }
   1860 
   1861     p_record = NDEF_MsgGetFirstRecByType (p_ndef_msg, NDEF_TNF_WKT, hs_rec_type, HS_REC_TYPE_LEN);
   1862 
   1863     if (p_record)
   1864     {
   1865         CHO_TRACE_DEBUG0 ("Found Hs record");
   1866         return NFA_CHO_MSG_HS;
   1867     }
   1868 
   1869     p_record = NDEF_MsgGetFirstRecByType (p_ndef_msg, NDEF_TNF_MEDIA,
   1870                                           p_bt_oob_rec_type, BT_OOB_REC_TYPE_LEN);
   1871 
   1872     if (p_record)
   1873     {
   1874         CHO_TRACE_DEBUG0 ("Found simplified BT OOB record");
   1875         return NFA_CHO_MSG_BT_OOB;
   1876     }
   1877 
   1878     p_record = NDEF_MsgGetFirstRecByType (p_ndef_msg, NDEF_TNF_MEDIA,
   1879                                           p_wifi_rec_type, (UINT8) strlen ((char *) p_wifi_rec_type));
   1880 
   1881     if (p_record)
   1882     {
   1883         CHO_TRACE_DEBUG0 ("Found simplified WiFi record");
   1884         return NFA_CHO_MSG_WIFI;
   1885     }
   1886 
   1887     CHO_TRACE_ERROR0 ("Failed to find Hr/Hs record");
   1888 
   1889     return NFA_CHO_MSG_UNKNOWN;
   1890 }
   1891 
   1892 /*******************************************************************************
   1893 **
   1894 ** Function         nfa_cho_get_local_device_role
   1895 **
   1896 ** Description      Resolve collision and get role of local device
   1897 **
   1898 **
   1899 ** Returns          tNFA_CHO_ROLE_TYPE
   1900 **
   1901 *******************************************************************************/
   1902 tNFA_CHO_ROLE_TYPE nfa_cho_get_local_device_role (UINT32 length, UINT8 *p_ndef_msg)
   1903 {
   1904     UINT16 rx_random_number;
   1905     UINT8  version;
   1906 
   1907     CHO_TRACE_DEBUG1 ("nfa_cho_get_local_device_role () length=%d", length);
   1908 
   1909     /* Get random number in Handover Request record */
   1910     if (NDEF_OK != nfa_cho_parse_hr_record (p_ndef_msg, &version, &rx_random_number, NULL, NULL))
   1911     {
   1912         CHO_TRACE_ERROR0 ("Failed to parse hr record");
   1913         return NFA_CHO_ROLE_UNDECIDED;
   1914     }
   1915 
   1916     CHO_TRACE_DEBUG2 ("tx_random_number=0x%x, rx_random_number=0x%x",
   1917                        nfa_cho_cb.tx_random_number, rx_random_number);
   1918 
   1919     if (nfa_cho_cb.tx_random_number == rx_random_number)
   1920     {
   1921         return NFA_CHO_ROLE_UNDECIDED;
   1922     }
   1923     /* if the least significant bits are same */
   1924     else if (((nfa_cho_cb.tx_random_number ^ rx_random_number) & 0x0001) == 0)
   1925     {
   1926         if (nfa_cho_cb.tx_random_number > rx_random_number)
   1927             return NFA_CHO_ROLE_SELECTOR;
   1928         else
   1929             return NFA_CHO_ROLE_REQUESTER;
   1930     }
   1931     else
   1932     {
   1933         if (nfa_cho_cb.tx_random_number > rx_random_number)
   1934             return NFA_CHO_ROLE_REQUESTER;
   1935         else
   1936             return NFA_CHO_ROLE_SELECTOR;
   1937     }
   1938 }
   1939 
   1940 /*******************************************************************************
   1941 **
   1942 ** Function         nfa_cho_update_random_number
   1943 **
   1944 ** Description      Replace random number
   1945 **
   1946 **
   1947 ** Returns          tNFA_STATUS
   1948 **
   1949 *******************************************************************************/
   1950 tNFA_STATUS nfa_cho_update_random_number (UINT8 *p_ndef_msg)
   1951 {
   1952     UINT8 *p_hr_record, *p_hr_payload;
   1953     UINT8 *p_cr_record, *p_cr_payload;
   1954     UINT32 hr_payload_len, cr_payload_len;
   1955     UINT32 temp32;
   1956 
   1957     CHO_TRACE_DEBUG0 ("nfa_cho_update_random_number ()");
   1958 
   1959     /* get Handover Request record */
   1960     p_hr_record = NDEF_MsgGetFirstRecByType (p_ndef_msg, NDEF_TNF_WKT, hr_rec_type, HR_REC_TYPE_LEN);
   1961 
   1962     if (!p_hr_record)
   1963     {
   1964         CHO_TRACE_ERROR0 ("Failed to find Hr record");
   1965         return NFA_STATUS_FAILED;
   1966     }
   1967 
   1968     p_hr_payload = NDEF_RecGetPayload (p_hr_record, &hr_payload_len);
   1969 
   1970     /* Skip Version */
   1971     p_hr_payload++;
   1972     hr_payload_len--;
   1973 
   1974     /* NDEF message for Collision Resolution record and Alternative Carrier records */
   1975 
   1976     /* find Collision Resolution record */
   1977     p_cr_record = NDEF_MsgGetFirstRecByType (p_hr_payload, NDEF_TNF_WKT, cr_rec_type, CR_REC_TYPE_LEN);
   1978 
   1979     if (!p_cr_record)
   1980     {
   1981         CHO_TRACE_ERROR0 ("Failed to find cr record");
   1982         return NFA_STATUS_FAILED;
   1983     }
   1984 
   1985     /* get start of payload in Collision Resolution record */
   1986     p_cr_payload = NDEF_RecGetPayload (p_cr_record, &cr_payload_len);
   1987 
   1988     /* Get random number from timer */
   1989     temp32 = GKI_get_tick_count ();
   1990     nfa_cho_cb.tx_random_number = (UINT16) ((temp32 >> 16) ^ (temp32));
   1991 
   1992 #if (defined (NFA_CHO_TEST_INCLUDED) && (NFA_CHO_TEST_INCLUDED == TRUE))
   1993     if (nfa_cho_cb.test_enabled & NFA_CHO_TEST_RANDOM)
   1994     {
   1995         nfa_cho_cb.tx_random_number = nfa_cho_cb.test_random_number;
   1996     }
   1997 #endif
   1998 
   1999     CHO_TRACE_DEBUG1 ("tx_random_number = 0x%04x", nfa_cho_cb.tx_random_number);
   2000 
   2001     /* update random number in payload */
   2002     UINT16_TO_BE_STREAM (p_cr_payload, nfa_cho_cb.tx_random_number);
   2003 
   2004     return NFA_STATUS_OK;
   2005 }
   2006