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