• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *******************************************************************************/
nfa_cho_ndef_cback(tNFA_NDEF_EVT event,tNFA_NDEF_EVT_DATA * p_data)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 *******************************************************************************/
nfa_cho_proc_ndef_type_handler_evt(tNFA_CHO_INT_EVENT_DATA * p_evt_data)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 *******************************************************************************/
nfa_cho_proc_api_reg(tNFA_CHO_INT_EVENT_DATA * p_evt_data)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 *******************************************************************************/
nfa_cho_proc_api_dereg(void)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 *******************************************************************************/
nfa_cho_create_connection(void)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 *******************************************************************************/
nfa_cho_process_disconnection(tNFA_CHO_DISC_REASON disc_reason)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 *******************************************************************************/
nfa_cho_notify_tx_fail_evt(tNFA_STATUS status)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 *******************************************************************************/
nfa_cho_reassemble_ho_msg(UINT8 local_sap,UINT8 remote_sap)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 *******************************************************************************/
nfa_cho_send_handover_msg(void)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 *******************************************************************************/
nfa_cho_read_ndef_msg(UINT8 local_sap,UINT8 remote_sap)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 *******************************************************************************/
nfa_cho_add_cr_record(UINT8 * p_msg,UINT32 max_size,UINT32 * p_cur_size)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 *******************************************************************************/
nfa_cho_add_ac_record(UINT8 * p_msg,UINT32 max_size,UINT32 * p_cur_size,UINT8 num_ac_info,tNFA_CHO_AC_INFO * p_ac_info,UINT8 * p_ndef,UINT32 max_ndef_size,UINT32 * p_cur_ndef_size)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 *******************************************************************************/
nfa_cho_send_hr(tNFA_CHO_API_SEND_HR * p_api_send_hr)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 *******************************************************************************/
nfa_cho_send_hs(tNFA_CHO_API_SEND_HS * p_api_select)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 *******************************************************************************/
nfa_cho_send_hs_error(UINT8 error_reason,UINT32 error_data)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 *******************************************************************************/
nfa_cho_get_random_number(UINT8 * p_ndef_msg)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 *******************************************************************************/
nfa_cho_parse_ac_records(UINT8 * p_ndef_msg,UINT8 * p_num_ac_rec,tNFA_CHO_AC_REC * p_ac_rec)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 *******************************************************************************/
nfa_cho_parse_hr_record(UINT8 * p_ndef_msg,UINT8 * p_version,UINT16 * p_random_number,UINT8 * p_num_ac_rec,tNFA_CHO_AC_REC * p_ac_rec)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 *******************************************************************************/
nfa_cho_parse_carrier_config(UINT8 * p_ndef_msg,UINT8 num_ac_rec,tNFA_CHO_AC_REC * p_ac_rec)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 *******************************************************************************/
nfa_cho_proc_hr(UINT32 length,UINT8 * p_ndef_msg)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 *******************************************************************************/
nfa_cho_get_error(UINT8 * p_ndef_msg,UINT8 * p_error_reason,UINT32 * p_error_data)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 *******************************************************************************/
nfa_cho_parse_hs_record(UINT8 * p_ndef_msg,UINT8 * p_version,UINT8 * p_num_ac_rec,tNFA_CHO_AC_REC * p_ac_rec,UINT8 * p_error_reason,UINT32 * p_error_data)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 *******************************************************************************/
nfa_cho_proc_hs(UINT32 length,UINT8 * p_ndef_msg)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 *******************************************************************************/
nfa_cho_proc_simplified_format(UINT32 length,UINT8 * p_ndef_msg)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 *******************************************************************************/
nfa_cho_get_msg_type(UINT32 length,UINT8 * p_ndef_msg)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 *******************************************************************************/
nfa_cho_get_local_device_role(UINT32 length,UINT8 * p_ndef_msg)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 *******************************************************************************/
nfa_cho_update_random_number(UINT8 * p_ndef_msg)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