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 state implementation file for the NFA Connection Handover.
22 *
23 ******************************************************************************/
24 #include <string.h>
25 #include "nfc_api.h"
26 #include "llcp_api.h"
27 #include "llcp_defs.h"
28 #include "nfa_sys.h"
29 #include "nfa_sys_int.h"
30 #include "nfa_cho_api.h"
31 #include "nfa_cho_int.h"
32 #include "nfa_mem_co.h"
33
34 /*****************************************************************************
35 ** Global Variables
36 *****************************************************************************/
37
38 /*****************************************************************************
39 ** Static Functions
40 *****************************************************************************/
41 static void nfa_cho_sm_disabled (tNFA_CHO_INT_EVT event, tNFA_CHO_INT_EVENT_DATA *p_data);
42 static void nfa_cho_sm_idle (tNFA_CHO_INT_EVT event, tNFA_CHO_INT_EVENT_DATA *p_data);
43 static void nfa_cho_sm_w4_cc (tNFA_CHO_INT_EVT event, tNFA_CHO_INT_EVENT_DATA *p_data);
44 static void nfa_cho_sm_connected (tNFA_CHO_INT_EVT event, tNFA_CHO_INT_EVENT_DATA *p_data);
45 static void nfa_cho_proc_rx_handover_msg (void);
46
47 /* debug functions type */
48 #if (BT_TRACE_VERBOSE == TRUE)
49 static char *nfa_cho_state_code (tNFA_CHO_STATE state_code);
50 static char *nfa_cho_evt_code (tNFA_CHO_INT_EVT evt_code);
51 #endif
52
53 /*****************************************************************************
54 ** Constants
55 *****************************************************************************/
56
57 /*******************************************************************************
58 **
59 ** Function nfa_cho_sm_llcp_cback
60 **
61 ** Description Processing event from LLCP
62 **
63 **
64 ** Returns None
65 **
66 *******************************************************************************/
nfa_cho_sm_llcp_cback(tLLCP_SAP_CBACK_DATA * p_data)67 void nfa_cho_sm_llcp_cback (tLLCP_SAP_CBACK_DATA *p_data)
68 {
69 tNFA_CHO_RX_NDEF_STATUS rx_status;
70
71 CHO_TRACE_DEBUG2 ("nfa_cho_sm_llcp_cback (): event:0x%02X, local_sap:0x%02X",
72 p_data->hdr.event, p_data->hdr.local_sap);
73
74 switch (p_data->hdr.event)
75 {
76 case LLCP_SAP_EVT_DATA_IND:
77 /* check if we received complete Handover Message */
78 rx_status = nfa_cho_reassemble_ho_msg (p_data->data_ind.local_sap,
79 p_data->data_ind.remote_sap);
80
81 if (rx_status == NFA_CHO_RX_NDEF_COMPLETE)
82 {
83 nfa_cho_sm_execute (NFA_CHO_RX_HANDOVER_MSG_EVT, NULL);
84 }
85 break;
86
87 case LLCP_SAP_EVT_CONNECT_IND:
88 nfa_cho_sm_execute (NFA_CHO_LLCP_CONNECT_IND_EVT, (tNFA_CHO_INT_EVENT_DATA *) p_data);
89 break;
90
91 case LLCP_SAP_EVT_CONNECT_RESP:
92 nfa_cho_sm_execute (NFA_CHO_LLCP_CONNECT_RESP_EVT, (tNFA_CHO_INT_EVENT_DATA *) p_data);
93 break;
94
95 case LLCP_SAP_EVT_DISCONNECT_IND:
96 nfa_cho_sm_execute (NFA_CHO_LLCP_DISCONNECT_IND_EVT, (tNFA_CHO_INT_EVENT_DATA *) p_data);
97 break;
98
99 case LLCP_SAP_EVT_DISCONNECT_RESP:
100 nfa_cho_sm_execute (NFA_CHO_LLCP_DISCONNECT_RESP_EVT, (tNFA_CHO_INT_EVENT_DATA *) p_data);
101 break;
102
103 case LLCP_SAP_EVT_CONGEST:
104 nfa_cho_sm_execute (NFA_CHO_LLCP_CONGEST_EVT, (tNFA_CHO_INT_EVENT_DATA *) p_data);
105 break;
106
107 case LLCP_SAP_EVT_LINK_STATUS:
108 nfa_cho_sm_execute (NFA_CHO_LLCP_LINK_STATUS_EVT, (tNFA_CHO_INT_EVENT_DATA *) p_data);
109 break;
110
111 default:
112 CHO_TRACE_ERROR1 ("Unknown event:0x%02X", p_data->hdr.event);
113 return;
114 }
115 }
116
117 /*******************************************************************************
118 **
119 ** Function nfa_cho_sm_disabled
120 **
121 ** Description Process event in disabled state
122 **
123 ** Returns None
124 **
125 *******************************************************************************/
nfa_cho_sm_disabled(tNFA_CHO_INT_EVT event,tNFA_CHO_INT_EVENT_DATA * p_data)126 static void nfa_cho_sm_disabled (tNFA_CHO_INT_EVT event, tNFA_CHO_INT_EVENT_DATA *p_data)
127 {
128 tNFA_CHO_EVT_DATA evt_data;
129 UINT16 remote_link_miu;
130
131 switch (event)
132 {
133 case NFA_CHO_API_REG_EVT:
134
135 evt_data.status = nfa_cho_proc_api_reg (p_data);
136
137 if (evt_data.status == NFA_STATUS_OK)
138 {
139 nfa_cho_cb.state = NFA_CHO_ST_IDLE;
140 }
141 p_data->api_reg.p_cback (NFA_CHO_REG_EVT, &evt_data);
142
143 if (evt_data.status == NFA_STATUS_OK)
144 {
145 /* check if LLCP is already activated */
146 LLCP_GetLinkMIU (&nfa_cho_cb.local_link_miu, &remote_link_miu);
147
148 if (nfa_cho_cb.local_link_miu > 0)
149 {
150 nfa_cho_cb.flags |= NFA_CHO_FLAGS_LLCP_ACTIVATED;
151
152 /* Notify application LLCP link activated */
153 evt_data.activated.is_initiator = FALSE;
154 nfa_cho_cb.p_cback (NFA_CHO_ACTIVATED_EVT, &evt_data);
155 }
156 }
157 break;
158
159 default:
160 CHO_TRACE_ERROR0 ("Unknown event");
161 break;
162 }
163 }
164
165 /*******************************************************************************
166 **
167 ** Function nfa_cho_sm_idle
168 **
169 ** Description Process event in idle state
170 **
171 ** Returns None
172 **
173 *******************************************************************************/
nfa_cho_sm_idle(tNFA_CHO_INT_EVT event,tNFA_CHO_INT_EVENT_DATA * p_data)174 static void nfa_cho_sm_idle (tNFA_CHO_INT_EVT event, tNFA_CHO_INT_EVENT_DATA *p_data)
175 {
176 UINT16 remote_link_miu;
177 tNFA_CHO_EVT_DATA evt_data;
178 tLLCP_CONNECTION_PARAMS params;
179
180 switch (event)
181 {
182 case NFA_CHO_API_REG_EVT:
183 evt_data.status = NFA_STATUS_FAILED;
184 p_data->api_reg.p_cback (NFA_CHO_REG_EVT, &evt_data);
185 break;
186
187 case NFA_CHO_API_DEREG_EVT:
188 nfa_cho_proc_api_dereg ();
189 nfa_cho_cb.state = NFA_CHO_ST_DISABLED;
190 break;
191
192 case NFA_CHO_API_CONNECT_EVT:
193 /* if LLCP activated then create data link connection */
194 if (nfa_cho_cb.flags & NFA_CHO_FLAGS_LLCP_ACTIVATED)
195 {
196 if (nfa_cho_create_connection () == NFA_STATUS_OK)
197 {
198 /* waiting for connection confirm */
199 nfa_cho_cb.state = NFA_CHO_ST_W4_CC;
200 }
201 else
202 {
203 evt_data.disconnected.reason = NFA_CHO_DISC_REASON_CONNECTION_FAIL;
204 nfa_cho_cb.p_cback (NFA_CHO_DISCONNECTED_EVT, &evt_data);
205 }
206 }
207 else
208 {
209 evt_data.disconnected.reason = NFA_CHO_DISC_REASON_LINK_DEACTIVATED;
210 nfa_cho_cb.p_cback (NFA_CHO_DISCONNECTED_EVT, &evt_data);
211 }
212 break;
213
214 case NFA_CHO_API_DISCONNECT_EVT:
215 /* Nothing to disconnect */
216 nfa_cho_process_disconnection (NFA_CHO_DISC_REASON_API_REQUEST);
217 break;
218
219 case NFA_CHO_LLCP_CONNECT_IND_EVT:
220
221 /* accept connection request */
222 params.miu = (UINT16) (nfa_cho_cb.local_link_miu >= NFA_CHO_MIU ? NFA_CHO_MIU : nfa_cho_cb.local_link_miu);
223 params.rw = NFA_CHO_RW;
224 params.sn[0] = 0;
225
226 LLCP_ConnectCfm (p_data->llcp_cback_data.connect_ind.local_sap,
227 p_data->llcp_cback_data.connect_ind.remote_sap,
228 ¶ms);
229
230 nfa_cho_cb.remote_miu = p_data->llcp_cback_data.connect_ind.miu;
231 nfa_cho_cb.remote_sap = p_data->llcp_cback_data.connect_ind.remote_sap;
232 nfa_cho_cb.local_sap = p_data->llcp_cback_data.connect_ind.local_sap;
233
234 nfa_cho_cb.substate = NFA_CHO_SUBSTATE_W4_REMOTE_HR;
235 nfa_cho_cb.state = NFA_CHO_ST_CONNECTED;
236 nfa_cho_cb.congested = FALSE;
237
238 evt_data.connected.initial_role = NFA_CHO_ROLE_SELECTOR;
239 nfa_cho_cb.p_cback (NFA_CHO_CONNECTED_EVT, &evt_data);
240 break;
241
242 case NFA_CHO_LLCP_LINK_STATUS_EVT:
243 /*
244 ** LLCP sends NFA_CHO_LLCP_DISCONNECT_IND_EVT for all data link connection
245 ** before sending NFA_CHO_LLCP_LINK_STATUS_EVT for deactivation.
246 ** This event can be received only in this state.
247 */
248
249 if (p_data->llcp_cback_data.link_status.is_activated == TRUE)
250 {
251 nfa_cho_cb.flags |= NFA_CHO_FLAGS_LLCP_ACTIVATED;
252
253 /* store local link MIU to decide MIU of data link connection later */
254 LLCP_GetLinkMIU (&nfa_cho_cb.local_link_miu, &remote_link_miu);
255
256 /* Notify application LLCP link activated */
257 evt_data.activated.is_initiator = p_data->llcp_cback_data.link_status.is_initiator;
258 nfa_cho_cb.p_cback (NFA_CHO_ACTIVATED_EVT, &evt_data);
259 }
260 else
261 {
262 /* the other flags had been cleared by NFA_CHO_LLCP_DISCONNECT_IND_EVT */
263 nfa_cho_cb.flags &= ~NFA_CHO_FLAGS_LLCP_ACTIVATED;
264
265 /* Notify application LLCP link deactivated */
266 evt_data.status = NFA_STATUS_OK;
267 nfa_cho_cb.p_cback (NFA_CHO_DEACTIVATED_EVT, &evt_data);
268 }
269 break;
270
271 case NFA_CHO_API_SEND_HR_EVT:
272 GKI_freebuf (p_data->api_send_hr.p_ndef);
273 break;
274
275 case NFA_CHO_API_SEND_HS_EVT:
276 GKI_freebuf (p_data->api_send_hs.p_ndef);
277 break;
278
279 case NFA_CHO_NDEF_TYPE_HANDLER_EVT:
280 nfa_cho_proc_ndef_type_handler_evt (p_data);
281 break;
282
283 default:
284 CHO_TRACE_ERROR0 ("Unknown event");
285 break;
286 }
287 }
288
289 /*******************************************************************************
290 **
291 ** Function nfa_cho_sm_w4_cc
292 **
293 ** Description Process event in waiting for connection confirm state
294 **
295 ** Returns None
296 **
297 *******************************************************************************/
nfa_cho_sm_w4_cc(tNFA_CHO_INT_EVT event,tNFA_CHO_INT_EVENT_DATA * p_data)298 static void nfa_cho_sm_w4_cc (tNFA_CHO_INT_EVT event, tNFA_CHO_INT_EVENT_DATA *p_data)
299 {
300 tNFA_CHO_EVT_DATA evt_data;
301 tLLCP_CONNECTION_PARAMS params;
302
303 switch (event)
304 {
305 case NFA_CHO_API_REG_EVT:
306 evt_data.status = NFA_STATUS_FAILED;
307 p_data->api_reg.p_cback (NFA_CHO_REG_EVT, &evt_data);
308 break;
309
310 case NFA_CHO_API_DEREG_EVT:
311 nfa_cho_proc_api_dereg ();
312 nfa_cho_cb.state = NFA_CHO_ST_DISABLED;
313 break;
314
315 case NFA_CHO_API_CONNECT_EVT:
316 evt_data.disconnected.reason = NFA_CHO_DISC_REASON_ALEADY_CONNECTED;
317 nfa_cho_cb.p_cback (NFA_CHO_DISCONNECTED_EVT, &evt_data);
318 break;
319
320 case NFA_CHO_API_DISCONNECT_EVT:
321 /* disconnect collision connection accepted by local device */
322 if (nfa_cho_cb.flags & NFA_CHO_FLAGS_CONN_COLLISION)
323 {
324 LLCP_DisconnectReq (nfa_cho_cb.collision_local_sap,
325 nfa_cho_cb.collision_remote_sap,
326 FALSE);
327
328 /* clear collision flag */
329 nfa_cho_cb.flags &= ~NFA_CHO_FLAGS_CONN_COLLISION;
330 }
331
332 nfa_cho_cb.state = NFA_CHO_ST_IDLE;
333
334 /* we cannot send DISC because we don't know remote SAP */
335 nfa_cho_process_disconnection (NFA_CHO_DISC_REASON_API_REQUEST);
336 break;
337
338 case NFA_CHO_LLCP_CONNECT_RESP_EVT:
339 /* peer accepted connection request */
340 nfa_cho_cb.state = NFA_CHO_ST_CONNECTED;
341 nfa_cho_cb.substate = NFA_CHO_SUBSTATE_W4_LOCAL_HR;
342 nfa_cho_cb.congested = FALSE;
343
344 /* store data link connection parameters */
345 nfa_cho_cb.remote_miu = p_data->llcp_cback_data.connect_resp.miu;
346 nfa_cho_cb.remote_sap = p_data->llcp_cback_data.connect_resp.remote_sap;
347 nfa_cho_cb.local_sap = nfa_cho_cb.client_sap;
348
349 evt_data.connected.initial_role = NFA_CHO_ROLE_REQUESTER;
350 nfa_cho_cb.p_cback (NFA_CHO_CONNECTED_EVT, &evt_data);
351 break;
352
353 case NFA_CHO_LLCP_CONNECT_IND_EVT:
354 /* if already collision of connection */
355 if (nfa_cho_cb.flags & NFA_CHO_FLAGS_CONN_COLLISION)
356 {
357 LLCP_ConnectReject (p_data->llcp_cback_data.connect_ind.local_sap,
358 p_data->llcp_cback_data.connect_ind.remote_sap,
359 LLCP_SAP_DM_REASON_TEMP_REJECT_THIS);
360 }
361 else
362 {
363 /*
364 ** accept connection request and set collision flag
365 ** wait for accepting connection request from peer or Hr message
366 */
367 params.miu = (UINT16) (nfa_cho_cb.local_link_miu >= NFA_CHO_MIU ? NFA_CHO_MIU : nfa_cho_cb.local_link_miu);
368 params.rw = NFA_CHO_RW;
369 params.sn[0] = 0;
370
371 LLCP_ConnectCfm (p_data->llcp_cback_data.connect_ind.local_sap,
372 p_data->llcp_cback_data.connect_ind.remote_sap,
373 ¶ms);
374
375 nfa_cho_cb.flags |= NFA_CHO_FLAGS_CONN_COLLISION;
376
377 nfa_cho_cb.collision_remote_miu = p_data->llcp_cback_data.connect_ind.miu;
378 nfa_cho_cb.collision_remote_sap = p_data->llcp_cback_data.connect_ind.remote_sap;
379 nfa_cho_cb.collision_local_sap = p_data->llcp_cback_data.connect_ind.local_sap;
380 nfa_cho_cb.collision_congested = FALSE;
381 }
382 break;
383
384 case NFA_CHO_RX_HANDOVER_MSG_EVT:
385 /* peer device sent handover message before accepting connection */
386 /* clear collision flag */
387 nfa_cho_cb.flags &= ~NFA_CHO_FLAGS_CONN_COLLISION;
388
389 nfa_cho_cb.remote_miu = nfa_cho_cb.collision_remote_miu;
390 nfa_cho_cb.remote_sap = nfa_cho_cb.collision_remote_sap;
391 nfa_cho_cb.local_sap = nfa_cho_cb.collision_local_sap;
392 nfa_cho_cb.congested = nfa_cho_cb.collision_congested;
393
394 nfa_cho_cb.substate = NFA_CHO_SUBSTATE_W4_REMOTE_HR;
395 nfa_cho_cb.state = NFA_CHO_ST_CONNECTED;
396
397 evt_data.connected.initial_role = NFA_CHO_ROLE_SELECTOR;
398 nfa_cho_cb.p_cback (NFA_CHO_CONNECTED_EVT, &evt_data);
399
400 /* process handover message in nfa_cho_cb.p_rx_ndef_msg */
401 nfa_cho_proc_rx_handover_msg ();
402 break;
403
404 case NFA_CHO_LLCP_DISCONNECT_RESP_EVT:
405 /*
406 ** if peer rejected our connection request or there is no handover service in peer
407 ** but we already accepted connection from peer
408 */
409 if (nfa_cho_cb.flags & NFA_CHO_FLAGS_CONN_COLLISION)
410 {
411 /* clear collision flag */
412 nfa_cho_cb.flags &= ~NFA_CHO_FLAGS_CONN_COLLISION;
413
414 nfa_cho_cb.remote_miu = nfa_cho_cb.collision_remote_miu;
415 nfa_cho_cb.remote_sap = nfa_cho_cb.collision_remote_sap;
416 nfa_cho_cb.local_sap = nfa_cho_cb.collision_local_sap;
417 nfa_cho_cb.congested = nfa_cho_cb.collision_congested;
418
419 nfa_cho_cb.substate = NFA_CHO_SUBSTATE_W4_REMOTE_HR;
420 nfa_cho_cb.state = NFA_CHO_ST_CONNECTED;
421
422 evt_data.connected.initial_role = NFA_CHO_ROLE_SELECTOR;
423 nfa_cho_cb.p_cback (NFA_CHO_CONNECTED_EVT, &evt_data);
424 }
425 else
426 {
427 nfa_cho_cb.state = NFA_CHO_ST_IDLE;
428 nfa_cho_process_disconnection (NFA_CHO_DISC_REASON_CONNECTION_FAIL);
429 }
430 break;
431
432 case NFA_CHO_LLCP_DISCONNECT_IND_EVT:
433 /* if peer disconnects collision connection */
434 if ( (nfa_cho_cb.flags & NFA_CHO_FLAGS_CONN_COLLISION)
435 &&(p_data->llcp_cback_data.disconnect_ind.local_sap == nfa_cho_cb.collision_local_sap)
436 &&(p_data->llcp_cback_data.disconnect_ind.remote_sap == nfa_cho_cb.collision_remote_sap) )
437 {
438 /* clear collision flag */
439 nfa_cho_cb.flags &= ~NFA_CHO_FLAGS_CONN_COLLISION;
440 }
441 else /* Link failure before peer accepts or rejects connection request */
442 {
443 nfa_cho_cb.state = NFA_CHO_ST_IDLE;
444 nfa_cho_process_disconnection (NFA_CHO_DISC_REASON_CONNECTION_FAIL);
445 }
446 break;
447
448 case NFA_CHO_LLCP_CONGEST_EVT:
449 /* if collision connection is congested */
450 if ( (p_data->llcp_cback_data.congest.link_type == LLCP_LINK_TYPE_DATA_LINK_CONNECTION)
451 &&(nfa_cho_cb.flags & NFA_CHO_FLAGS_CONN_COLLISION))
452 {
453 nfa_cho_cb.collision_congested = p_data->llcp_cback_data.congest.is_congested;
454 }
455 break;
456
457 case NFA_CHO_API_SEND_HR_EVT:
458 GKI_freebuf (p_data->api_send_hr.p_ndef);
459 break;
460
461 case NFA_CHO_API_SEND_HS_EVT:
462 GKI_freebuf (p_data->api_send_hs.p_ndef);
463 break;
464
465 case NFA_CHO_NDEF_TYPE_HANDLER_EVT:
466 nfa_cho_proc_ndef_type_handler_evt (p_data);
467 break;
468
469 default:
470 CHO_TRACE_ERROR0 ("Unknown event");
471 break;
472 }
473 }
474
475 /*******************************************************************************
476 **
477 ** Function nfa_cho_sm_connected
478 **
479 ** Description Process event in connected state
480 **
481 ** Returns None
482 **
483 *******************************************************************************/
nfa_cho_sm_connected(tNFA_CHO_INT_EVT event,tNFA_CHO_INT_EVENT_DATA * p_data)484 static void nfa_cho_sm_connected (tNFA_CHO_INT_EVT event, tNFA_CHO_INT_EVENT_DATA *p_data)
485 {
486 tNFA_CHO_EVT_DATA evt_data;
487 tNFA_STATUS status;
488
489 switch (event)
490 {
491 case NFA_CHO_API_REG_EVT:
492 evt_data.status = NFA_STATUS_FAILED;
493 p_data->api_reg.p_cback (NFA_CHO_REG_EVT, &evt_data);
494 break;
495
496 case NFA_CHO_API_DEREG_EVT:
497 nfa_cho_proc_api_dereg ();
498 nfa_cho_cb.state = NFA_CHO_ST_DISABLED;
499 break;
500
501 case NFA_CHO_API_CONNECT_EVT:
502 /* it could be race condition, let app know outgoing connection failed */
503 evt_data.disconnected.reason = NFA_CHO_DISC_REASON_ALEADY_CONNECTED;
504 nfa_cho_cb.p_cback (NFA_CHO_DISCONNECTED_EVT, &evt_data);
505 break;
506
507 case NFA_CHO_API_DISCONNECT_EVT:
508 /* disconnect collision connection accepted by local device */
509 if (nfa_cho_cb.flags & NFA_CHO_FLAGS_CONN_COLLISION)
510 {
511 LLCP_DisconnectReq (nfa_cho_cb.collision_local_sap,
512 nfa_cho_cb.collision_remote_sap,
513 FALSE);
514
515 /* clear collision flag */
516 nfa_cho_cb.flags &= ~NFA_CHO_FLAGS_CONN_COLLISION;
517 }
518
519 LLCP_DisconnectReq (nfa_cho_cb.local_sap,
520 nfa_cho_cb.remote_sap,
521 FALSE);
522
523 /* store disconnect reason */
524 nfa_cho_cb.disc_reason = NFA_CHO_DISC_REASON_API_REQUEST;
525 break;
526
527 case NFA_CHO_API_SEND_HR_EVT:
528 if (nfa_cho_cb.substate == NFA_CHO_SUBSTATE_W4_LOCAL_HR)
529 {
530 /* Send Handover Request Message */
531 status = nfa_cho_send_hr (&p_data->api_send_hr);
532
533 if (status == NFA_STATUS_OK)
534 {
535 nfa_cho_cb.substate = NFA_CHO_SUBSTATE_W4_REMOTE_HS;
536 /* start timer for Handover Select Message */
537 nfa_sys_start_timer (&nfa_cho_cb.timer, 0, NFA_CHO_TIMEOUT_FOR_HS);
538 }
539 else
540 {
541 CHO_TRACE_ERROR0 ("NFA CHO failed to send Hr");
542 nfa_cho_notify_tx_fail_evt (status);
543 }
544 }
545 else
546 {
547 CHO_TRACE_ERROR0 ("NFA CHO got unexpected NFA_CHO_API_SEND_HR_EVT");
548 nfa_cho_notify_tx_fail_evt (NFA_STATUS_SEMANTIC_ERROR);
549 }
550 GKI_freebuf (p_data->api_send_hr.p_ndef);
551 break;
552
553 case NFA_CHO_API_SEND_HS_EVT:
554 if (nfa_cho_cb.substate == NFA_CHO_SUBSTATE_W4_LOCAL_HS)
555 {
556 /* send Handover Select Message */
557 status = nfa_cho_send_hs (&p_data->api_send_hs);
558 if (status == NFA_STATUS_OK)
559 {
560 nfa_cho_cb.substate = NFA_CHO_SUBSTATE_W4_REMOTE_HR;
561 }
562 else
563 {
564 CHO_TRACE_ERROR0 ("NFA CHO failed to send Hs");
565 nfa_cho_notify_tx_fail_evt (status);
566 }
567 }
568 else
569 {
570 CHO_TRACE_ERROR0 ("NFA CHO got unexpected NFA_CHO_API_SEND_HS_EVT");
571 nfa_cho_notify_tx_fail_evt (NFA_STATUS_SEMANTIC_ERROR);
572 }
573 GKI_freebuf (p_data->api_send_hs.p_ndef);
574 break;
575
576 case NFA_CHO_API_SEL_ERR_EVT:
577 /* application detected error */
578 if (nfa_cho_cb.substate == NFA_CHO_SUBSTATE_W4_LOCAL_HS)
579 {
580 /* Send Handover Select Error record */
581 status = nfa_cho_send_hs_error (p_data->api_sel_err.error_reason,
582 p_data->api_sel_err.error_data);
583 if (status == NFA_STATUS_OK)
584 {
585 nfa_cho_cb.substate = NFA_CHO_SUBSTATE_W4_REMOTE_HR;
586 }
587 else
588 {
589 CHO_TRACE_ERROR0 ("Failed to send Hs Error record");
590 nfa_cho_notify_tx_fail_evt (status);
591 }
592 }
593 else
594 {
595 CHO_TRACE_ERROR0 ("NFA CHO got unexpected NFA_CHO_API_SEL_ERR_EVT");
596 nfa_cho_notify_tx_fail_evt (NFA_STATUS_SEMANTIC_ERROR);
597 }
598 break;
599
600 case NFA_CHO_LLCP_CONNECT_RESP_EVT:
601 /* peer accepted connection after we accepted and received Hr */
602 /* disconnect data link connection created by local device */
603 LLCP_DisconnectReq (p_data->llcp_cback_data.connect_resp.local_sap,
604 p_data->llcp_cback_data.connect_resp.remote_sap,
605 FALSE);
606 break;
607
608 case NFA_CHO_LLCP_CONNECT_IND_EVT:
609 LLCP_ConnectReject (p_data->llcp_cback_data.connect_ind.local_sap,
610 p_data->llcp_cback_data.connect_ind.remote_sap,
611 LLCP_SAP_DM_REASON_TEMP_REJECT_THIS);
612 break;
613
614 case NFA_CHO_RX_HANDOVER_MSG_EVT:
615 /* process handover message in nfa_cho_cb.p_rx_ndef_msg */
616 nfa_cho_proc_rx_handover_msg ();
617 break;
618
619 case NFA_CHO_LLCP_DISCONNECT_IND_EVT:
620 if ( (p_data->llcp_cback_data.disconnect_ind.local_sap == nfa_cho_cb.local_sap)
621 &&(p_data->llcp_cback_data.disconnect_ind.remote_sap == nfa_cho_cb.remote_sap) )
622 {
623 nfa_cho_cb.state = NFA_CHO_ST_IDLE;
624 nfa_cho_process_disconnection (NFA_CHO_DISC_REASON_PEER_REQUEST);
625 }
626 else /* if disconnection of collision conneciton */
627 {
628 nfa_cho_cb.flags &= ~NFA_CHO_FLAGS_CONN_COLLISION;
629 }
630 break;
631
632 case NFA_CHO_LLCP_DISCONNECT_RESP_EVT:
633 if ( (p_data->llcp_cback_data.disconnect_ind.local_sap == nfa_cho_cb.local_sap)
634 &&(p_data->llcp_cback_data.disconnect_ind.remote_sap == nfa_cho_cb.remote_sap) )
635 {
636 nfa_cho_cb.state = NFA_CHO_ST_IDLE;
637 nfa_cho_process_disconnection (nfa_cho_cb.disc_reason);
638 }
639 else /* if disconnection of collision conneciton */
640 {
641 nfa_cho_cb.flags &= ~NFA_CHO_FLAGS_CONN_COLLISION;
642 }
643 break;
644
645 case NFA_CHO_LLCP_CONGEST_EVT:
646 /* if data link connection is congested */
647 if ( (p_data->llcp_cback_data.congest.link_type == LLCP_LINK_TYPE_DATA_LINK_CONNECTION)
648 &&(p_data->llcp_cback_data.congest.local_sap == nfa_cho_cb.local_sap)
649 &&(p_data->llcp_cback_data.congest.remote_sap == nfa_cho_cb.remote_sap) )
650 {
651 nfa_cho_cb.congested = p_data->llcp_cback_data.congest.is_congested;
652
653 if (!nfa_cho_cb.congested)
654 {
655 /* send remaining message if any */
656 if ( (nfa_cho_cb.p_tx_ndef_msg)
657 &&(nfa_cho_cb.tx_ndef_sent_size < nfa_cho_cb.tx_ndef_cur_size) )
658 {
659 nfa_cho_send_handover_msg ();
660 }
661 }
662 }
663 break;
664
665 case NFA_CHO_TIMEOUT_EVT:
666 if (nfa_cho_cb.substate == NFA_CHO_SUBSTATE_W4_REMOTE_HS)
667 {
668 CHO_TRACE_ERROR0 ("Failed to receive Hs message");
669 }
670 else if (nfa_cho_cb.substate == NFA_CHO_SUBSTATE_W4_REMOTE_HR)
671 {
672 /* we didn't get complete Hr, don't need to notify application */
673 CHO_TRACE_ERROR0 ("Failed to receive Hr message");
674 }
675
676 /* store disconnect reason and disconnect */
677 nfa_cho_cb.disc_reason = NFA_CHO_DISC_REASON_TIMEOUT;
678 LLCP_DisconnectReq (nfa_cho_cb.local_sap,
679 nfa_cho_cb.remote_sap,
680 FALSE);
681 break;
682
683 case NFA_CHO_NDEF_TYPE_HANDLER_EVT:
684 nfa_cho_proc_ndef_type_handler_evt (p_data);
685 break;
686
687 default:
688 CHO_TRACE_ERROR0 ("Unknown event");
689 break;
690 }
691 }
692 /*******************************************************************************
693 **
694 ** Function nfa_cho_sm_execute
695 **
696 ** Description Process event in state machine
697 **
698 ** Returns None
699 **
700 *******************************************************************************/
nfa_cho_sm_execute(tNFA_CHO_INT_EVT event,tNFA_CHO_INT_EVENT_DATA * p_data)701 void nfa_cho_sm_execute (tNFA_CHO_INT_EVT event, tNFA_CHO_INT_EVENT_DATA *p_data)
702 {
703 #if (BT_TRACE_VERBOSE == TRUE)
704 CHO_TRACE_DEBUG2 ("nfa_cho_sm_execute (): State[%s], Event[%s]",
705 nfa_cho_state_code (nfa_cho_cb.state),
706 nfa_cho_evt_code (event));
707 #else
708 CHO_TRACE_DEBUG2 ("nfa_cho_sm_execute (): State[%d], Event[%d]",
709 nfa_cho_cb.state, event);
710 #endif
711
712
713 switch (nfa_cho_cb.state)
714 {
715 case NFA_CHO_ST_DISABLED:
716 nfa_cho_sm_disabled (event, p_data);
717 break;
718
719 case NFA_CHO_ST_IDLE:
720 nfa_cho_sm_idle (event, p_data);
721 break;
722
723 case NFA_CHO_ST_W4_CC:
724 nfa_cho_sm_w4_cc (event, p_data);
725 break;
726
727 case NFA_CHO_ST_CONNECTED:
728 nfa_cho_sm_connected (event, p_data);
729 break;
730
731 default:
732 CHO_TRACE_ERROR0 ("Unknown state");
733 break;
734 }
735 }
736
737 /*******************************************************************************
738 **
739 ** Function nfa_cho_resolve_collision
740 **
741 ** Description Resolve collision by random number in Hr
742 **
743 ** Returns None
744 **
745 *******************************************************************************/
nfa_cho_resolve_collision(BOOLEAN * p_free_hr)746 void nfa_cho_resolve_collision (BOOLEAN *p_free_hr)
747 {
748 tNFA_CHO_ROLE_TYPE role;
749 tNFA_STATUS status;
750
751 /* resolve collistion by random number */
752 role = nfa_cho_get_local_device_role (nfa_cho_cb.rx_ndef_cur_size,
753 nfa_cho_cb.p_rx_ndef_msg);
754
755 /* if local device becomes selector */
756 if (role == NFA_CHO_ROLE_SELECTOR)
757 {
758 /* peer device is winner so clean up any collision */
759 if (nfa_cho_cb.flags & NFA_CHO_FLAGS_CONN_COLLISION)
760 {
761 /* disconnect data link connection created by local device */
762 LLCP_DisconnectReq (nfa_cho_cb.local_sap,
763 nfa_cho_cb.remote_sap,
764 FALSE);
765
766 nfa_cho_cb.remote_miu = nfa_cho_cb.collision_remote_miu;
767 nfa_cho_cb.remote_sap = nfa_cho_cb.collision_remote_sap;
768 nfa_cho_cb.local_sap = nfa_cho_cb.collision_local_sap;
769 nfa_cho_cb.congested = nfa_cho_cb.collision_congested;
770 }
771
772 nfa_cho_cb.substate = NFA_CHO_SUBSTATE_W4_LOCAL_HS;
773
774 nfa_cho_proc_hr (nfa_cho_cb.rx_ndef_cur_size,
775 nfa_cho_cb.p_rx_ndef_msg);
776
777 *p_free_hr = TRUE;
778 }
779 /* if both random numbers are equal */
780 else if (role == NFA_CHO_ROLE_UNDECIDED)
781 {
782 /* send Hr with new random number */
783 if (nfa_cho_cb.p_tx_ndef_msg)
784 {
785 status = nfa_cho_update_random_number (nfa_cho_cb.p_tx_ndef_msg);
786
787 if (status == NFA_STATUS_OK)
788 {
789 nfa_cho_cb.tx_ndef_sent_size = 0;
790 status = nfa_cho_send_handover_msg ();
791 }
792 }
793 else
794 {
795 status = NFA_STATUS_FAILED;
796 }
797
798 if (status == NFA_STATUS_FAILED)
799 {
800 CHO_TRACE_ERROR0 ("Failed to send Hr record with new random number");
801
802 nfa_cho_cb.disc_reason = NFA_CHO_DISC_REASON_INTERNAL_ERROR;
803
804 /* disconnect and notify application */
805 LLCP_DisconnectReq (nfa_cho_cb.local_sap,
806 nfa_cho_cb.remote_sap,
807 FALSE);
808 }
809 else
810 {
811 /* restart timer */
812 nfa_sys_start_timer (&nfa_cho_cb.timer, 0, NFA_CHO_TIMEOUT_FOR_HS);
813
814 /* Don't free previous tx NDEF message because we are reusing it */
815 *p_free_hr = FALSE;
816 }
817 }
818 else /* if (role == NFA_CHO_ROLE_REQUESTER) */
819 {
820 /* wait for "Hs" record */
821 *p_free_hr = TRUE;
822 }
823 }
824
825 /*******************************************************************************
826 **
827 ** Function nfa_cho_check_disconnect_collision
828 **
829 ** Description Disconnect any collision connection
830 **
831 ** Returns None
832 **
833 *******************************************************************************/
nfa_cho_check_disconnect_collision(void)834 void nfa_cho_check_disconnect_collision (void)
835 {
836 if (nfa_cho_cb.flags & NFA_CHO_FLAGS_CONN_COLLISION)
837 {
838 /* disconnect collision connection */
839 LLCP_DisconnectReq (nfa_cho_cb.collision_local_sap,
840 nfa_cho_cb.collision_remote_sap,
841 FALSE);
842 }
843 }
844
845 /*******************************************************************************
846 **
847 ** Function nfa_cho_proc_rx_handover_msg
848 **
849 ** Description Process received Handover Message
850 **
851 ** Returns None
852 **
853 *******************************************************************************/
nfa_cho_proc_rx_handover_msg(void)854 void nfa_cho_proc_rx_handover_msg (void)
855 {
856 tNFA_CHO_MSG_TYPE msg_type;
857 BOOLEAN free_tx_ndef_msg = TRUE;
858
859 /* get message type before processing to check collision */
860 msg_type = nfa_cho_get_msg_type (nfa_cho_cb.rx_ndef_cur_size,
861 nfa_cho_cb.p_rx_ndef_msg);
862
863 if (nfa_cho_cb.substate == NFA_CHO_SUBSTATE_W4_REMOTE_HS)
864 {
865 /* if we sent "Hr" but received "Hr", collision */
866 if (msg_type == NFA_CHO_MSG_HR)
867 {
868 nfa_cho_resolve_collision (&free_tx_ndef_msg);
869 }
870 else if (msg_type == NFA_CHO_MSG_HS)
871 {
872 /* parse and report application */
873 nfa_cho_proc_hs (nfa_cho_cb.rx_ndef_cur_size,
874 nfa_cho_cb.p_rx_ndef_msg);
875
876 nfa_cho_cb.substate = NFA_CHO_SUBSTATE_W4_LOCAL_HR;
877 }
878 else
879 {
880 CHO_TRACE_ERROR0 ("nfa_cho_proc_rx_handover_msg (): Unknown Message Type");
881
882 nfa_cho_check_disconnect_collision ();
883
884 nfa_cho_cb.disc_reason = NFA_CHO_DISC_REASON_UNKNOWN_MSG;
885
886 LLCP_DisconnectReq (nfa_cho_cb.local_sap,
887 nfa_cho_cb.remote_sap,
888 FALSE);
889 }
890 }
891 else if (nfa_cho_cb.substate == NFA_CHO_SUBSTATE_W4_REMOTE_HR)
892 {
893 if (msg_type == NFA_CHO_MSG_HR)
894 {
895 /* parse and notify NFA_CHO_REQ_EVT to application */
896 nfa_cho_proc_hr (nfa_cho_cb.rx_ndef_cur_size,
897 nfa_cho_cb.p_rx_ndef_msg);
898
899 /* In case of parsing error, let peer got timeout (1 sec) */
900
901 /* wait for application selection */
902 nfa_cho_cb.substate = NFA_CHO_SUBSTATE_W4_LOCAL_HS;
903 }
904 else
905 {
906 CHO_TRACE_ERROR0 ("nfa_cho_proc_rx_handover_msg (): Expecting Handover Request");
907
908 nfa_cho_check_disconnect_collision ();
909
910 nfa_cho_cb.disc_reason = NFA_CHO_DISC_REASON_SEMANTIC_ERROR;
911
912 LLCP_DisconnectReq (nfa_cho_cb.local_sap,
913 nfa_cho_cb.remote_sap,
914 FALSE);
915 }
916 }
917 else
918 {
919 CHO_TRACE_ERROR1 ("nfa_cho_proc_rx_handover_msg (): Unexpected data in substate (0x%x)", nfa_cho_cb.substate);
920
921 nfa_cho_check_disconnect_collision ();
922
923 nfa_cho_cb.disc_reason = NFA_CHO_DISC_REASON_SEMANTIC_ERROR;
924
925 LLCP_DisconnectReq (nfa_cho_cb.local_sap,
926 nfa_cho_cb.remote_sap,
927 FALSE);
928 }
929
930 if ((free_tx_ndef_msg) && (nfa_cho_cb.p_tx_ndef_msg))
931 {
932 GKI_freebuf (nfa_cho_cb.p_tx_ndef_msg);
933 nfa_cho_cb.p_tx_ndef_msg = NULL;
934 }
935
936 /* processing rx message is done, free buffer for rx handover message */
937 if (nfa_cho_cb.p_rx_ndef_msg)
938 {
939 GKI_freebuf (nfa_cho_cb.p_rx_ndef_msg);
940 nfa_cho_cb.p_rx_ndef_msg = NULL;
941 }
942 }
943
944 #if (BT_TRACE_VERBOSE == TRUE)
945 /*******************************************************************************
946 **
947 ** Function nfa_cho_state_code
948 **
949 ** Description
950 **
951 ** Returns string of state
952 **
953 *******************************************************************************/
nfa_cho_state_code(tNFA_CHO_STATE state_code)954 static char *nfa_cho_state_code (tNFA_CHO_STATE state_code)
955 {
956 switch (state_code)
957 {
958 case NFA_CHO_ST_DISABLED:
959 return "DISABLED";
960 case NFA_CHO_ST_IDLE:
961 return "IDLE";
962 case NFA_CHO_ST_CONNECTED:
963 return "CONNECTED";
964 default:
965 return "unknown state";
966 }
967 }
968
969 /*******************************************************************************
970 **
971 ** Function nfa_cho_evt_code
972 **
973 ** Description
974 **
975 ** Returns string of event
976 **
977 *******************************************************************************/
nfa_cho_evt_code(tNFA_CHO_INT_EVT evt_code)978 char *nfa_cho_evt_code (tNFA_CHO_INT_EVT evt_code)
979 {
980 switch (evt_code)
981 {
982 case NFA_CHO_API_REG_EVT:
983 return "API_REG";
984 case NFA_CHO_API_DEREG_EVT:
985 return "API_DEREG";
986 case NFA_CHO_API_CONNECT_EVT:
987 return "API_CONNECT";
988 case NFA_CHO_API_DISCONNECT_EVT:
989 return "API_DISCONNECT";
990 case NFA_CHO_API_SEND_HR_EVT:
991 return "API_SEND_HR";
992 case NFA_CHO_API_SEND_HS_EVT:
993 return "API_SEND_HS";
994 case NFA_CHO_API_SEL_ERR_EVT:
995 return "API_SEL_ERR";
996
997 case NFA_CHO_RX_HANDOVER_MSG_EVT:
998 return "RX_HANDOVER_MSG";
999
1000 case NFA_CHO_LLCP_CONNECT_IND_EVT:
1001 return "LLCP_CONNECT_IND";
1002 case NFA_CHO_LLCP_CONNECT_RESP_EVT:
1003 return "LLCP_CONNECT_RESP";
1004 case NFA_CHO_LLCP_DISCONNECT_IND_EVT:
1005 return "LLCP_DISCONNECT_IND";
1006 case NFA_CHO_LLCP_DISCONNECT_RESP_EVT:
1007 return "LLCP_DISCONNECT_RESP";
1008 case NFA_CHO_LLCP_CONGEST_EVT:
1009 return "LLCP_CONGEST";
1010 case NFA_CHO_LLCP_LINK_STATUS_EVT:
1011 return "LLCP_LINK_STATUS";
1012
1013 case NFA_CHO_NDEF_TYPE_HANDLER_EVT:
1014 return "NDEF_TYPE_HANDLER";
1015 case NFA_CHO_TIMEOUT_EVT:
1016 return "TIMEOUT";
1017
1018 default:
1019 return "unknown event";
1020 }
1021 }
1022 #endif /* Debug Functions */
1023