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 */
40static char *p_cho_service_name = "urn:nfc:sn:handover";
41
42/* Handover Request Record Type */
43static UINT8 hr_rec_type[HR_REC_TYPE_LEN] = { 0x48, 0x72 }; /* "Hr" */
44
45/* Handover Select Record Type */
46static 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 */
52static UINT8 cr_rec_type[CR_REC_TYPE_LEN] = { 0x63, 0x72 }; /* "cr" */
53
54/* Alternative Carrier Record Type */
55static UINT8 ac_rec_type[AC_REC_TYPE_LEN] = { 0x61, 0x63 }; /* "ac" */
56
57/* Error Record Type */
58static UINT8 err_rec_type[ERR_REC_TYPE_LEN] = { 0x65, 0x72, 0x72 }; /* "err" */
59
60/* Bluetooth OOB Data Type */
61static UINT8 *p_bt_oob_rec_type = (UINT8 *) "application/vnd.bluetooth.ep.oob";
62
63/* WiFi Data Type */
64static UINT8 *p_wifi_rec_type = (UINT8 *) "application/vnd.wfa.wsc";
65
66/*****************************************************************************
67**  Global Variables
68*****************************************************************************/
69
70/*****************************************************************************
71**  Static Functions
72*****************************************************************************/
73static 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*******************************************************************************/
85static 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*******************************************************************************/
160void 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*******************************************************************************/
228tNFA_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*******************************************************************************/
304void 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*******************************************************************************/
358tNFA_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*******************************************************************************/
401void 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*******************************************************************************/
445void 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*******************************************************************************/
467tNFA_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*******************************************************************************/
562tNFA_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*******************************************************************************/
645tNFA_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*******************************************************************************/
746tNDEF_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*******************************************************************************/
783tNDEF_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*******************************************************************************/
882tNFA_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*******************************************************************************/
1009tNFA_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*******************************************************************************/
1143tNFA_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*******************************************************************************/
1225UINT16 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*******************************************************************************/
1267tNFA_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*******************************************************************************/
1388tNFA_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*******************************************************************************/
1453tNFA_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*******************************************************************************/
1508void 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*******************************************************************************/
1583tNFA_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*******************************************************************************/
1642tNFA_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*******************************************************************************/
1726void 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*******************************************************************************/
1813void 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*******************************************************************************/
1847tNFA_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*******************************************************************************/
1902tNFA_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*******************************************************************************/
1950tNFA_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