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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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