Home | History | Annotate | Download | only in cho
      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                          &params);
    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                              &params);
    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