Home | History | Annotate | Download | only in p2p
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2010-2014 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 main implementation file for the NFA P2P.
     22  *
     23  ******************************************************************************/
     24 #include <string.h>
     25 #include "llcp_api.h"
     26 #include "llcp_defs.h"
     27 #include "nfa_dm_int.h"
     28 #include "nfa_p2p_api.h"
     29 #include "nfa_p2p_int.h"
     30 #include "nfa_sys.h"
     31 #include "nfa_sys_int.h"
     32 #include "nfc_api.h"
     33 
     34 /*****************************************************************************
     35 **  Global Variables
     36 *****************************************************************************/
     37 
     38 /* system manager control block definition */
     39 tNFA_P2P_CB nfa_p2p_cb;
     40 
     41 /*****************************************************************************
     42 **  Static Functions
     43 *****************************************************************************/
     44 
     45 /* event handler function type */
     46 static bool nfa_p2p_evt_hdlr(NFC_HDR* p_msg);
     47 
     48 /* disable function type */
     49 static void nfa_p2p_sys_disable(void);
     50 static void nfa_p2p_update_active_listen(void);
     51 
     52 /* debug functions type */
     53 #if (BT_TRACE_VERBOSE == TRUE)
     54 static char* nfa_p2p_llcp_state_code(tNFA_P2P_LLCP_STATE state_code);
     55 #endif
     56 
     57 /*****************************************************************************
     58 **  Constants
     59 *****************************************************************************/
     60 /* timeout to restore active listen mode if no RF activation on passive mode */
     61 #define NFA_P2P_RESTORE_ACTIVE_LISTEN_TIMEOUT 5000
     62 
     63 static const tNFA_SYS_REG nfa_p2p_sys_reg = {NULL, nfa_p2p_evt_hdlr,
     64                                              nfa_p2p_sys_disable, NULL};
     65 
     66 #define NFA_P2P_NUM_ACTIONS (NFA_P2P_LAST_EVT & 0x00ff)
     67 
     68 /* type for action functions */
     69 typedef bool (*tNFA_P2P_ACTION)(tNFA_P2P_MSG* p_data);
     70 
     71 /* action function list */
     72 const tNFA_P2P_ACTION nfa_p2p_action[] = {
     73     nfa_p2p_reg_server,                  /* NFA_P2P_API_REG_SERVER_EVT       */
     74     nfa_p2p_reg_client,                  /* NFA_P2P_API_REG_CLIENT_EVT       */
     75     nfa_p2p_dereg,                       /* NFA_P2P_API_DEREG_EVT            */
     76     nfa_p2p_accept_connection,           /* NFA_P2P_API_ACCEPT_CONN_EVT      */
     77     nfa_p2p_reject_connection,           /* NFA_P2P_API_REJECT_CONN_EVT      */
     78     nfa_p2p_disconnect,                  /* NFA_P2P_API_DISCONNECT_EVT       */
     79     nfa_p2p_create_data_link_connection, /* NFA_P2P_API_CONNECT_EVT          */
     80     nfa_p2p_send_ui,                     /* NFA_P2P_API_SEND_UI_EVT          */
     81     nfa_p2p_send_data,                   /* NFA_P2P_API_SEND_DATA_EVT        */
     82     nfa_p2p_set_local_busy,              /* NFA_P2P_API_SET_LOCAL_BUSY_EVT   */
     83     nfa_p2p_get_link_info,               /* NFA_P2P_API_GET_LINK_INFO_EVT    */
     84     nfa_p2p_get_remote_sap,              /* NFA_P2P_API_GET_REMOTE_SAP_EVT   */
     85     nfa_p2p_set_llcp_cfg,                /* NFA_P2P_API_SET_LLCP_CFG_EVT     */
     86     nfa_p2p_restart_rf_discovery         /* NFA_P2P_INT_RESTART_RF_DISC_EVT  */
     87 };
     88 
     89 /*******************************************************************************
     90 **
     91 ** Function         nfa_p2p_discovery_cback
     92 **
     93 ** Description      Processing event from discovery callback for listening
     94 **
     95 **
     96 ** Returns          None
     97 **
     98 *******************************************************************************/
     99 void nfa_p2p_discovery_cback(tNFA_DM_RF_DISC_EVT event, tNFC_DISCOVER* p_data) {
    100   tNFA_CONN_EVT_DATA evt_data;
    101 
    102   P2P_TRACE_DEBUG1("nfa_p2p_discovery_cback (): event:0x%02X", event);
    103 
    104   switch (event) {
    105     case NFA_DM_RF_DISC_START_EVT:
    106       if (p_data->status == NFC_STATUS_OK) {
    107         nfa_p2p_cb.llcp_state = NFA_P2P_LLCP_STATE_LISTENING;
    108         nfa_p2p_cb.rf_disc_state = NFA_DM_RFST_DISCOVERY;
    109       }
    110       break;
    111 
    112     case NFA_DM_RF_DISC_ACTIVATED_EVT:
    113 
    114       nfa_p2p_cb.rf_disc_state = NFA_DM_RFST_LISTEN_ACTIVE;
    115 
    116       /* notify NFC link activation */
    117       memcpy(&(evt_data.activated.activate_ntf), &(p_data->activate),
    118              sizeof(tNFC_ACTIVATE_DEVT));
    119       nfa_dm_conn_cback_event_notify(NFA_ACTIVATED_EVT, &evt_data);
    120 
    121       if ((p_data->activate.protocol == NFC_PROTOCOL_NFC_DEP) &&
    122           (p_data->activate.intf_param.type == NFC_INTERFACE_NFC_DEP)) {
    123         nfa_p2p_activate_llcp(p_data);
    124 
    125         /* stop timer not to deactivate LLCP link on passive mode */
    126         nfa_sys_stop_timer(&nfa_p2p_cb.active_listen_restore_timer);
    127       }
    128       break;
    129 
    130     case NFA_DM_RF_DISC_DEACTIVATED_EVT:
    131 
    132       if ((nfa_p2p_cb.rf_disc_state != NFA_DM_RFST_LISTEN_ACTIVE) &&
    133           (nfa_p2p_cb.rf_disc_state != NFA_DM_RFST_LISTEN_SLEEP)) {
    134         /* this is not for P2P listen
    135         ** DM broadcasts deactivaiton event in listen sleep state.
    136         */
    137         break;
    138       }
    139 
    140       /* notify deactivation */
    141       if ((p_data->deactivate.type == NFC_DEACTIVATE_TYPE_SLEEP) ||
    142           (p_data->deactivate.type == NFC_DEACTIVATE_TYPE_SLEEP_AF)) {
    143         nfa_p2p_cb.rf_disc_state = NFA_DM_RFST_LISTEN_SLEEP;
    144         evt_data.deactivated.type = NFA_DEACTIVATE_TYPE_SLEEP;
    145       } else {
    146         nfa_p2p_cb.rf_disc_state = NFA_DM_RFST_DISCOVERY;
    147         evt_data.deactivated.type = NFA_DEACTIVATE_TYPE_IDLE;
    148       }
    149       nfa_dm_conn_cback_event_notify(NFA_DEACTIVATED_EVT, &evt_data);
    150       break;
    151 
    152     default:
    153       P2P_TRACE_ERROR0("Unexpected event");
    154       break;
    155   }
    156 }
    157 
    158 /*******************************************************************************
    159 **
    160 ** Function         nfa_p2p_update_active_listen_timeout_cback
    161 **
    162 ** Description      Timeout while waiting for passive mode activation
    163 **
    164 ** Returns          void
    165 **
    166 *******************************************************************************/
    167 static void nfa_p2p_update_active_listen_timeout_cback(TIMER_LIST_ENT* p_tle) {
    168   NFA_TRACE_ERROR0("nfa_p2p_update_active_listen_timeout_cback()");
    169 
    170   /* restore active listen mode */
    171   nfa_p2p_update_active_listen();
    172 }
    173 
    174 /*******************************************************************************
    175 **
    176 ** Function         nfa_p2p_update_active_listen
    177 **
    178 ** Description      Remove active listen mode temporarily or restore it
    179 **
    180 **
    181 ** Returns          None
    182 **
    183 *******************************************************************************/
    184 static void nfa_p2p_update_active_listen(void) {
    185   tNFA_DM_DISC_TECH_PROTO_MASK p2p_listen_mask = 0;
    186   NFC_HDR* p_msg;
    187 
    188   P2P_TRACE_DEBUG1(
    189       "nfa_p2p_update_active_listen (): listen_tech_mask_to_restore:0x%x",
    190       nfa_p2p_cb.listen_tech_mask_to_restore);
    191 
    192   /* if active listen mode was removed temporarily */
    193   if (nfa_p2p_cb.listen_tech_mask_to_restore) {
    194     /* restore listen technologies */
    195     nfa_p2p_cb.listen_tech_mask = nfa_p2p_cb.listen_tech_mask_to_restore;
    196     nfa_p2p_cb.listen_tech_mask_to_restore = 0;
    197     nfa_sys_stop_timer(&nfa_p2p_cb.active_listen_restore_timer);
    198   } else {
    199     /* start timer in case of no passive activation */
    200     nfa_p2p_cb.active_listen_restore_timer.p_cback =
    201         (TIMER_CBACK*)nfa_p2p_update_active_listen_timeout_cback;
    202     nfa_sys_start_timer(&nfa_p2p_cb.active_listen_restore_timer, 0,
    203                         NFA_P2P_RESTORE_ACTIVE_LISTEN_TIMEOUT);
    204 
    205     /* save listen techonologies */
    206     nfa_p2p_cb.listen_tech_mask_to_restore = nfa_p2p_cb.listen_tech_mask;
    207 
    208     /* remove active listen mode */
    209     nfa_p2p_cb.listen_tech_mask &=
    210         ~(NFA_TECHNOLOGY_MASK_A_ACTIVE | NFA_TECHNOLOGY_MASK_F_ACTIVE);
    211   }
    212 
    213   if (nfa_p2p_cb.dm_disc_handle != NFA_HANDLE_INVALID) {
    214     nfa_dm_delete_rf_discover(nfa_p2p_cb.dm_disc_handle);
    215     nfa_p2p_cb.dm_disc_handle = NFA_HANDLE_INVALID;
    216   }
    217 
    218   /* collect listen technologies with NFC-DEP protocol */
    219   if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_A)
    220     p2p_listen_mask |= NFA_DM_DISC_MASK_LA_NFC_DEP;
    221 
    222   if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_F)
    223     p2p_listen_mask |= NFA_DM_DISC_MASK_LF_NFC_DEP;
    224 
    225   if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_A_ACTIVE)
    226     p2p_listen_mask |= NFA_DM_DISC_MASK_LAA_NFC_DEP;
    227 
    228   if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_F_ACTIVE)
    229     p2p_listen_mask |= NFA_DM_DISC_MASK_LFA_NFC_DEP;
    230 
    231   /* Configure listen technologies and protocols and register callback to NFA DM
    232    * discovery */
    233   nfa_p2p_cb.dm_disc_handle = nfa_dm_add_rf_discover(
    234       p2p_listen_mask, NFA_DM_DISC_HOST_ID_DH, nfa_p2p_discovery_cback);
    235 
    236   /* restart RF discovery to update RF technologies */
    237   p_msg = (NFC_HDR*)GKI_getbuf(sizeof(NFC_HDR));
    238   if (p_msg != NULL) {
    239     p_msg->event = NFA_P2P_INT_RESTART_RF_DISC_EVT;
    240     nfa_sys_sendmsg(p_msg);
    241   }
    242 }
    243 
    244 /*******************************************************************************
    245 **
    246 ** Function         nfa_p2p_llcp_link_cback
    247 **
    248 ** Description      Processing event from LLCP link management callback
    249 **
    250 **
    251 ** Returns          None
    252 **
    253 *******************************************************************************/
    254 void nfa_p2p_llcp_link_cback(uint8_t event, uint8_t reason) {
    255   tNFA_LLCP_ACTIVATED llcp_activated;
    256   tNFA_LLCP_DEACTIVATED llcp_deactivated;
    257 
    258   P2P_TRACE_DEBUG2("nfa_p2p_llcp_link_cback () event:0x%x, reason:0x%x", event,
    259                    reason);
    260 
    261   if (event == LLCP_LINK_ACTIVATION_COMPLETE_EVT) {
    262     LLCP_GetLinkMIU(&nfa_p2p_cb.local_link_miu, &nfa_p2p_cb.remote_link_miu);
    263     nfa_p2p_cb.llcp_state = NFA_P2P_LLCP_STATE_ACTIVATED;
    264 
    265     if (nfa_p2p_cb.is_initiator) {
    266       /* notify NFA DM to send Activate Event to applicaiton with status  */
    267       nfa_dm_notify_activation_status(NFA_STATUS_OK, NULL);
    268     }
    269 
    270     llcp_activated.is_initiator = nfa_p2p_cb.is_initiator;
    271     llcp_activated.local_link_miu = nfa_p2p_cb.local_link_miu;
    272     llcp_activated.remote_link_miu = nfa_p2p_cb.remote_link_miu;
    273     llcp_activated.remote_lsc = LLCP_GetRemoteLSC();
    274     llcp_activated.remote_wks = LLCP_GetRemoteWKS();
    275     llcp_activated.remote_version = LLCP_GetRemoteVersion();
    276 
    277     nfa_dm_act_conn_cback_notify(NFA_LLCP_ACTIVATED_EVT,
    278                                  (tNFA_CONN_EVT_DATA*)&llcp_activated);
    279 
    280   } else if (event == LLCP_LINK_ACTIVATION_FAILED_EVT) {
    281     nfa_p2p_cb.llcp_state = NFA_P2P_LLCP_STATE_IDLE;
    282 
    283     if (nfa_p2p_cb.is_initiator) {
    284       /* notify NFA DM to send Activate Event to applicaiton with status  */
    285       nfa_dm_notify_activation_status(NFA_STATUS_FAILED, NULL);
    286     }
    287 
    288     nfa_dm_rf_deactivate(NFA_DEACTIVATE_TYPE_DISCOVERY);
    289   } else if (event == LLCP_LINK_FIRST_PACKET_RECEIVED_EVT) {
    290     nfa_dm_act_conn_cback_notify(NFA_LLCP_FIRST_PACKET_RECEIVED_EVT, NULL);
    291   } else /* LLCP_LINK_DEACTIVATED_EVT       */
    292   {
    293     nfa_p2p_cb.llcp_state = NFA_P2P_LLCP_STATE_IDLE;
    294 
    295     /* if got RF link loss without any rx LLC PDU */
    296     if (reason == LLCP_LINK_RF_LINK_LOSS_NO_RX_LLC) {
    297       /* if it was active listen mode */
    298       if ((nfa_p2p_cb.is_active_mode) && (!nfa_p2p_cb.is_initiator)) {
    299         /* if it didn't retry without active listen mode and passive mode is
    300          * available */
    301         if ((nfa_p2p_cb.listen_tech_mask_to_restore == 0x00) &&
    302             (nfa_p2p_cb.listen_tech_mask &
    303              (NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_F))) {
    304           P2P_TRACE_DEBUG0("Retry without active listen mode");
    305 
    306           /* retry without active listen mode */
    307           nfa_p2p_update_active_listen();
    308         }
    309       } else if (nfa_p2p_cb.listen_tech_mask_to_restore) {
    310         nfa_sys_start_timer(&nfa_p2p_cb.active_listen_restore_timer, 0,
    311                             NFA_P2P_RESTORE_ACTIVE_LISTEN_TIMEOUT);
    312       }
    313 
    314       reason = LLCP_LINK_RF_LINK_LOSS_ERR;
    315     } else {
    316       if (nfa_p2p_cb.listen_tech_mask_to_restore) {
    317         /* restore active listen mode */
    318         nfa_p2p_update_active_listen();
    319       }
    320     }
    321 
    322     llcp_deactivated.reason = reason;
    323     nfa_dm_act_conn_cback_notify(NFA_LLCP_DEACTIVATED_EVT,
    324                                  (tNFA_CONN_EVT_DATA*)&llcp_deactivated);
    325 
    326     if (reason != LLCP_LINK_RF_LINK_LOSS_ERR) /* if NFC link is still up */
    327     {
    328       if (nfa_p2p_cb.is_initiator) {
    329         nfa_dm_rf_deactivate(NFA_DEACTIVATE_TYPE_DISCOVERY);
    330       } else if ((nfa_p2p_cb.is_active_mode) && (reason == LLCP_LINK_TIMEOUT)) {
    331         /*
    332         ** target needs to trun off RF in case of receiving invalid
    333         ** frame from initiator
    334         */
    335         P2P_TRACE_DEBUG0("Got LLCP_LINK_TIMEOUT in active mode on target");
    336         nfa_dm_rf_deactivate(NFA_DEACTIVATE_TYPE_DISCOVERY);
    337       }
    338     }
    339   }
    340 }
    341 
    342 /*******************************************************************************
    343 **
    344 ** Function         nfa_p2p_activate_llcp
    345 **
    346 ** Description      Activate LLCP link
    347 **
    348 **
    349 ** Returns          None
    350 **
    351 *******************************************************************************/
    352 void nfa_p2p_activate_llcp(tNFC_DISCOVER* p_data) {
    353   tLLCP_ACTIVATE_CONFIG config;
    354 
    355   P2P_TRACE_DEBUG0("nfa_p2p_activate_llcp ()");
    356 
    357   if ((p_data->activate.rf_tech_param.mode == NFC_DISCOVERY_TYPE_POLL_A) ||
    358       (p_data->activate.rf_tech_param.mode == NFC_DISCOVERY_TYPE_POLL_F) ||
    359       (p_data->activate.rf_tech_param.mode ==
    360        NFC_DISCOVERY_TYPE_POLL_A_ACTIVE) ||
    361       (p_data->activate.rf_tech_param.mode ==
    362        NFC_DISCOVERY_TYPE_POLL_F_ACTIVE)) {
    363     config.is_initiator = true;
    364   } else {
    365     config.is_initiator = false;
    366   }
    367 
    368   if ((p_data->activate.rf_tech_param.mode ==
    369        NFC_DISCOVERY_TYPE_POLL_A_ACTIVE) ||
    370       (p_data->activate.rf_tech_param.mode ==
    371        NFC_DISCOVERY_TYPE_POLL_F_ACTIVE) ||
    372       (p_data->activate.rf_tech_param.mode ==
    373        NFC_DISCOVERY_TYPE_LISTEN_A_ACTIVE) ||
    374       (p_data->activate.rf_tech_param.mode ==
    375        NFC_DISCOVERY_TYPE_LISTEN_F_ACTIVE)) {
    376     nfa_p2p_cb.is_active_mode = true;
    377   } else {
    378     nfa_p2p_cb.is_active_mode = false;
    379   }
    380 
    381   nfa_p2p_cb.is_initiator = config.is_initiator;
    382 
    383   config.max_payload_size =
    384       p_data->activate.intf_param.intf_param.pa_nfc.max_payload_size;
    385   config.waiting_time =
    386       p_data->activate.intf_param.intf_param.pa_nfc.waiting_time;
    387   config.p_gen_bytes = p_data->activate.intf_param.intf_param.pa_nfc.gen_bytes;
    388   config.gen_bytes_len =
    389       p_data->activate.intf_param.intf_param.pa_nfc.gen_bytes_len;
    390 
    391   LLCP_ActivateLink(config, nfa_p2p_llcp_link_cback);
    392 }
    393 
    394 /*******************************************************************************
    395 **
    396 ** Function         nfa_p2p_deactivate_llcp
    397 **
    398 ** Description      Deactivate LLCP link
    399 **
    400 **
    401 ** Returns          None
    402 **
    403 *******************************************************************************/
    404 void nfa_p2p_deactivate_llcp(void) {
    405   P2P_TRACE_DEBUG0("nfa_p2p_deactivate_llcp ()");
    406 
    407   LLCP_DeactivateLink();
    408 }
    409 
    410 /*******************************************************************************
    411 **
    412 ** Function         nfa_p2p_init
    413 **
    414 ** Description      Initialize NFA P2P
    415 **
    416 **
    417 ** Returns          None
    418 **
    419 *******************************************************************************/
    420 void nfa_p2p_init(void) {
    421   uint8_t xx;
    422 
    423   P2P_TRACE_DEBUG0("nfa_p2p_init ()");
    424 
    425   /* initialize control block */
    426   memset(&nfa_p2p_cb, 0, sizeof(tNFA_P2P_CB));
    427   nfa_p2p_cb.dm_disc_handle = NFA_HANDLE_INVALID;
    428   nfa_p2p_cb.trace_level = APPL_INITIAL_TRACE_LEVEL;
    429 
    430   for (xx = 0; xx < LLCP_MAX_SDP_TRANSAC; xx++) {
    431     nfa_p2p_cb.sdp_cb[xx].local_sap = LLCP_INVALID_SAP;
    432   }
    433 
    434   /* register message handler on NFA SYS */
    435   nfa_sys_register(NFA_ID_P2P, &nfa_p2p_sys_reg);
    436 }
    437 
    438 /*******************************************************************************
    439 **
    440 ** Function         nfa_p2p_sys_disable
    441 **
    442 ** Description      Deregister NFA P2P from NFA SYS/DM
    443 **
    444 **
    445 ** Returns          None
    446 **
    447 *******************************************************************************/
    448 static void nfa_p2p_sys_disable(void) {
    449   P2P_TRACE_DEBUG0("nfa_p2p_sys_disable()");
    450 
    451   nfa_sys_stop_timer(&nfa_p2p_cb.active_listen_restore_timer);
    452 
    453   /* deregister message handler on NFA SYS */
    454   nfa_sys_deregister(NFA_ID_P2P);
    455 }
    456 
    457 /*******************************************************************************
    458 **
    459 ** Function         nfa_p2p_set_config
    460 **
    461 ** Description      Set General bytes and WT parameters for LLCP
    462 **
    463 **
    464 ** Returns          void
    465 **
    466 *******************************************************************************/
    467 void nfa_p2p_set_config(tNFA_DM_DISC_TECH_PROTO_MASK disc_mask) {
    468   uint8_t wt, gen_bytes_len = LLCP_MAX_GEN_BYTES;
    469   uint8_t params[LLCP_MAX_GEN_BYTES + 5], *p, length;
    470 
    471   P2P_TRACE_DEBUG0("nfa_p2p_set_config ()");
    472 
    473   LLCP_GetDiscoveryConfig(&wt, params + 2, &gen_bytes_len);
    474   if (nfa_dm_is_p2p_paused()) {
    475     gen_bytes_len = 0;
    476   }
    477 
    478   if (disc_mask &
    479       (NFA_DM_DISC_MASK_PA_NFC_DEP | NFA_DM_DISC_MASK_PF_NFC_DEP |
    480        NFA_DM_DISC_MASK_PAA_NFC_DEP | NFA_DM_DISC_MASK_PFA_NFC_DEP)) {
    481     p = params;
    482 
    483     UINT8_TO_BE_STREAM(p, NFC_PMID_ATR_REQ_GEN_BYTES);
    484     UINT8_TO_BE_STREAM(p, gen_bytes_len);
    485 
    486     p += gen_bytes_len;
    487     length = gen_bytes_len + 2;
    488 
    489     nfa_dm_check_set_config(length, params, false);
    490   }
    491 
    492   if (disc_mask &
    493       (NFA_DM_DISC_MASK_LA_NFC_DEP | NFA_DM_DISC_MASK_LF_NFC_DEP |
    494        NFA_DM_DISC_MASK_LAA_NFC_DEP | NFA_DM_DISC_MASK_LFA_NFC_DEP)) {
    495     p = params;
    496 
    497     UINT8_TO_BE_STREAM(p, NFC_PMID_ATR_RES_GEN_BYTES);
    498     UINT8_TO_BE_STREAM(p, gen_bytes_len);
    499 
    500     p += gen_bytes_len;
    501     length = gen_bytes_len + 2;
    502 
    503     UINT8_TO_BE_STREAM(p, NFC_PMID_WT);
    504     UINT8_TO_BE_STREAM(p, NCI_PARAM_LEN_WT);
    505     UINT8_TO_BE_STREAM(p, wt);
    506 
    507     length += 3;
    508 
    509     nfa_dm_check_set_config(length, params, false);
    510   }
    511 }
    512 
    513 /*******************************************************************************
    514 **
    515 ** Function         nfa_p2p_enable_listening
    516 **
    517 ** Description      Configure listen technologies and protocols for LLCP
    518 **                  If LLCP WKS is changed then LLCP Gen bytes will be updated.
    519 **
    520 ** Returns          void
    521 **
    522 *******************************************************************************/
    523 void nfa_p2p_enable_listening(tNFA_SYS_ID sys_id, bool update_wks) {
    524   tNFA_DM_DISC_TECH_PROTO_MASK p2p_listen_mask = 0;
    525 
    526   P2P_TRACE_DEBUG2("nfa_p2p_enable_listening () sys_id = %d, update_wks = %d",
    527                    sys_id, update_wks);
    528 
    529   if (sys_id == NFA_ID_P2P)
    530     nfa_p2p_cb.is_p2p_listening = true;
    531   else if (sys_id == NFA_ID_SNEP)
    532     nfa_p2p_cb.is_snep_listening = true;
    533 
    534   if (nfa_p2p_cb.dm_disc_handle != NFA_HANDLE_INVALID) {
    535     /* if need to update WKS in LLCP Gen bytes */
    536     if (update_wks) {
    537       /* update LLCP Gen Bytes */
    538       nfa_p2p_set_config(NFA_DM_DISC_MASK_PA_NFC_DEP |
    539                          NFA_DM_DISC_MASK_LA_NFC_DEP);
    540     }
    541     return;
    542   }
    543 
    544   /* collect listen technologies with NFC-DEP protocol */
    545   if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_A)
    546     p2p_listen_mask |= NFA_DM_DISC_MASK_LA_NFC_DEP;
    547 
    548   if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_F)
    549     p2p_listen_mask |= NFA_DM_DISC_MASK_LF_NFC_DEP;
    550 
    551   if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_A_ACTIVE)
    552     p2p_listen_mask |= NFA_DM_DISC_MASK_LAA_NFC_DEP;
    553 
    554   if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_F_ACTIVE)
    555     p2p_listen_mask |= NFA_DM_DISC_MASK_LFA_NFC_DEP;
    556 
    557   if (p2p_listen_mask) {
    558     /* Configure listen technologies and protocols and register callback to NFA
    559      * DM discovery */
    560     nfa_p2p_cb.dm_disc_handle = nfa_dm_add_rf_discover(
    561         p2p_listen_mask, NFA_DM_DISC_HOST_ID_DH, nfa_p2p_discovery_cback);
    562   }
    563 }
    564 
    565 /*******************************************************************************
    566 **
    567 ** Function         nfa_p2p_disable_listening
    568 **
    569 ** Description      Remove listen technologies and protocols for LLCP and
    570 **                  deregister callback from NFA DM discovery if all of
    571 **                  P2P/CHO/SNEP doesn't listen LLCP any more.
    572 **                  If LLCP WKS is changed then ATR_RES will be updated.
    573 **
    574 ** Returns          void
    575 **
    576 *******************************************************************************/
    577 void nfa_p2p_disable_listening(tNFA_SYS_ID sys_id, bool update_wks) {
    578   P2P_TRACE_DEBUG2("nfa_p2p_disable_listening ()  sys_id = %d, update_wks = %d",
    579                    sys_id, update_wks);
    580 
    581   if (sys_id == NFA_ID_P2P)
    582     nfa_p2p_cb.is_p2p_listening = false;
    583   else if (sys_id == NFA_ID_SNEP)
    584     nfa_p2p_cb.is_snep_listening = false;
    585 
    586   if (nfa_p2p_cb.dm_disc_handle != NFA_HANDLE_INVALID) {
    587     if ((nfa_p2p_cb.is_p2p_listening == false) &&
    588         (nfa_p2p_cb.is_snep_listening == false)) {
    589       nfa_p2p_cb.llcp_state = NFA_P2P_LLCP_STATE_IDLE;
    590       nfa_p2p_cb.rf_disc_state = NFA_DM_RFST_IDLE;
    591 
    592       nfa_dm_delete_rf_discover(nfa_p2p_cb.dm_disc_handle);
    593       nfa_p2p_cb.dm_disc_handle = NFA_HANDLE_INVALID;
    594     } else if (update_wks) {
    595       /* update LLCP Gen Bytes */
    596       nfa_p2p_set_config(NFA_DM_DISC_MASK_PA_NFC_DEP |
    597                          NFA_DM_DISC_MASK_LA_NFC_DEP);
    598     }
    599   }
    600 }
    601 
    602 /*******************************************************************************
    603 **
    604 ** Function         nfa_p2p_update_listen_tech
    605 **
    606 ** Description      Update P2P listen technologies. If there is change then
    607 **                  restart or stop P2P listen.
    608 **
    609 ** Returns          void
    610 **
    611 *******************************************************************************/
    612 void nfa_p2p_update_listen_tech(tNFA_TECHNOLOGY_MASK tech_mask) {
    613   P2P_TRACE_DEBUG1("nfa_p2p_update_listen_tech ()  tech_mask = 0x%x",
    614                    tech_mask);
    615 
    616   if (nfa_p2p_cb.listen_tech_mask_to_restore) {
    617     nfa_p2p_cb.listen_tech_mask_to_restore = 0;
    618     nfa_sys_stop_timer(&nfa_p2p_cb.active_listen_restore_timer);
    619   }
    620 
    621   if (nfa_p2p_cb.listen_tech_mask != tech_mask) {
    622     nfa_p2p_cb.listen_tech_mask = tech_mask;
    623 
    624     if (nfa_p2p_cb.dm_disc_handle != NFA_HANDLE_INVALID) {
    625       nfa_p2p_cb.rf_disc_state = NFA_DM_RFST_IDLE;
    626 
    627       nfa_dm_delete_rf_discover(nfa_p2p_cb.dm_disc_handle);
    628       nfa_p2p_cb.dm_disc_handle = NFA_HANDLE_INVALID;
    629     }
    630 
    631     /* restart discovery without updating sub-module status */
    632     if (nfa_p2p_cb.is_p2p_listening)
    633       nfa_p2p_enable_listening(NFA_ID_P2P, false);
    634     else if (nfa_p2p_cb.is_snep_listening)
    635       nfa_p2p_enable_listening(NFA_ID_SNEP, false);
    636   }
    637 }
    638 
    639 /*******************************************************************************
    640 **
    641 ** Function         nfa_p2p_evt_hdlr
    642 **
    643 ** Description      Processing event for NFA P2P
    644 **
    645 **
    646 ** Returns          TRUE if p_msg needs to be deallocated
    647 **
    648 *******************************************************************************/
    649 static bool nfa_p2p_evt_hdlr(NFC_HDR* p_hdr) {
    650   bool delete_msg = true;
    651   uint16_t event;
    652 
    653   tNFA_P2P_MSG* p_msg = (tNFA_P2P_MSG*)p_hdr;
    654 
    655 #if (BT_TRACE_VERBOSE == TRUE)
    656   P2P_TRACE_DEBUG2("nfa_p2p_evt_hdlr (): LLCP State [%s], Event [%s]",
    657                    nfa_p2p_llcp_state_code(nfa_p2p_cb.llcp_state),
    658                    nfa_p2p_evt_code(p_msg->hdr.event));
    659 #else
    660   P2P_TRACE_DEBUG2("nfa_p2p_evt_hdlr (): State 0x%02x, Event 0x%02x",
    661                    nfa_p2p_cb.llcp_state, p_msg->hdr.event);
    662 #endif
    663 
    664   event = p_msg->hdr.event & 0x00ff;
    665 
    666   /* execute action functions */
    667   if (event < NFA_P2P_NUM_ACTIONS) {
    668     delete_msg = (*nfa_p2p_action[event])(p_msg);
    669   } else {
    670     P2P_TRACE_ERROR0("Unhandled event");
    671   }
    672 
    673   return delete_msg;
    674 }
    675 
    676 #if (BT_TRACE_VERBOSE == TRUE)
    677 /*******************************************************************************
    678 **
    679 ** Function         nfa_p2p_llcp_state_code
    680 **
    681 ** Description
    682 **
    683 ** Returns          string of state
    684 **
    685 *******************************************************************************/
    686 static char* nfa_p2p_llcp_state_code(tNFA_P2P_LLCP_STATE state_code) {
    687   switch (state_code) {
    688     case NFA_P2P_LLCP_STATE_IDLE:
    689       return "Link IDLE";
    690     case NFA_P2P_LLCP_STATE_LISTENING:
    691       return "Link LISTENING";
    692     case NFA_P2P_LLCP_STATE_ACTIVATED:
    693       return "Link ACTIVATED";
    694     default:
    695       return "Unknown state";
    696   }
    697 }
    698 
    699 /*******************************************************************************
    700 **
    701 ** Function         nfa_p2p_evt_code
    702 **
    703 ** Description
    704 **
    705 ** Returns          string of event
    706 **
    707 *******************************************************************************/
    708 char* nfa_p2p_evt_code(uint16_t evt_code) {
    709   switch (evt_code) {
    710     case NFA_P2P_API_REG_SERVER_EVT:
    711       return "API_REG_SERVER";
    712     case NFA_P2P_API_REG_CLIENT_EVT:
    713       return "API_REG_CLIENT";
    714     case NFA_P2P_API_DEREG_EVT:
    715       return "API_DEREG";
    716     case NFA_P2P_API_ACCEPT_CONN_EVT:
    717       return "API_ACCEPT_CONN";
    718     case NFA_P2P_API_REJECT_CONN_EVT:
    719       return "API_REJECT_CONN";
    720     case NFA_P2P_API_DISCONNECT_EVT:
    721       return "API_DISCONNECT";
    722     case NFA_P2P_API_CONNECT_EVT:
    723       return "API_CONNECT";
    724     case NFA_P2P_API_SEND_UI_EVT:
    725       return "API_SEND_UI";
    726     case NFA_P2P_API_SEND_DATA_EVT:
    727       return "API_SEND_DATA";
    728     case NFA_P2P_API_SET_LOCAL_BUSY_EVT:
    729       return "API_SET_LOCAL_BUSY";
    730     case NFA_P2P_API_GET_LINK_INFO_EVT:
    731       return "API_GET_LINK_INFO";
    732     case NFA_P2P_API_GET_REMOTE_SAP_EVT:
    733       return "API_GET_REMOTE_SAP";
    734     case NFA_P2P_API_SET_LLCP_CFG_EVT:
    735       return "API_SET_LLCP_CFG_EVT";
    736     case NFA_P2P_INT_RESTART_RF_DISC_EVT:
    737       return "RESTART_RF_DISC_EVT";
    738     default:
    739       return "Unknown event";
    740   }
    741 }
    742 #endif /* Debug Functions */
    743