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 */
39tNFA_P2P_CB nfa_p2p_cb;
40
41/*****************************************************************************
42**  Static Functions
43*****************************************************************************/
44
45/* event handler function type */
46static bool nfa_p2p_evt_hdlr(NFC_HDR* p_msg);
47
48/* disable function type */
49static void nfa_p2p_sys_disable(void);
50static void nfa_p2p_update_active_listen(void);
51
52/* debug functions type */
53#if (BT_TRACE_VERBOSE == TRUE)
54static 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
63static 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 */
69typedef bool (*tNFA_P2P_ACTION)(tNFA_P2P_MSG* p_data);
70
71/* action function list */
72const 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*******************************************************************************/
99void 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*******************************************************************************/
167static 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*******************************************************************************/
184static 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    if (NFC_GetNCIVersion() == NCI_VERSION_2_0) {
210      nfa_p2p_cb.listen_tech_mask &= ~(NFA_TECHNOLOGY_MASK_ACTIVE);
211    } else {
212      nfa_p2p_cb.listen_tech_mask &=
213          ~(NFA_TECHNOLOGY_MASK_A_ACTIVE | NFA_TECHNOLOGY_MASK_F_ACTIVE);
214    }
215  }
216
217  if (nfa_p2p_cb.dm_disc_handle != NFA_HANDLE_INVALID) {
218    nfa_dm_delete_rf_discover(nfa_p2p_cb.dm_disc_handle);
219    nfa_p2p_cb.dm_disc_handle = NFA_HANDLE_INVALID;
220  }
221
222  /* collect listen technologies with NFC-DEP protocol */
223  if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_A)
224    p2p_listen_mask |= NFA_DM_DISC_MASK_LA_NFC_DEP;
225
226  if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_F)
227    p2p_listen_mask |= NFA_DM_DISC_MASK_LF_NFC_DEP;
228  if (NFC_GetNCIVersion() == NCI_VERSION_2_0) {
229    if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_ACTIVE)
230      p2p_listen_mask |= NFA_DM_DISC_MASK_LACM_NFC_DEP;
231  } else {
232    if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_A_ACTIVE)
233      p2p_listen_mask |= NFA_DM_DISC_MASK_LAA_NFC_DEP;
234    if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_F_ACTIVE)
235      p2p_listen_mask |= NFA_DM_DISC_MASK_LFA_NFC_DEP;
236  }
237
238  /* For P2P mode(Default DTA mode) open Raw channel to bypass LLCP layer. For
239   * LLCP DTA mode activate LLCP Bypassing LLCP is handled in
240   * nfa_dm_poll_disc_cback */
241
242  if (appl_dta_mode_flag == 1 &&
243      ((nfa_dm_cb.eDtaMode & 0x0F) == NFA_DTA_DEFAULT_MODE)) {
244    // Configure listen technologies and protocols and register callback to DTA
245
246    P2P_TRACE_DEBUG1(
247        "%s: DTA mode:Registering nfa_dm_poll_disc_cback to avoid LLCP in P2P",
248        __func__);
249    nfa_p2p_cb.dm_disc_handle =
250        nfa_dm_add_rf_discover(p2p_listen_mask, NFA_DM_DISC_HOST_ID_DH,
251                               nfa_dm_poll_disc_cback_dta_wrapper);
252  } else {
253    /* Configure listen technologies and protocols and register callback to NFA
254     * DM discovery */
255    nfa_p2p_cb.dm_disc_handle = nfa_dm_add_rf_discover(
256        p2p_listen_mask, NFA_DM_DISC_HOST_ID_DH, nfa_p2p_discovery_cback);
257  }
258
259  /* restart RF discovery to update RF technologies */
260  p_msg = (NFC_HDR*)GKI_getbuf(sizeof(NFC_HDR));
261  if (p_msg != NULL) {
262    p_msg->event = NFA_P2P_INT_RESTART_RF_DISC_EVT;
263    nfa_sys_sendmsg(p_msg);
264  }
265}
266
267/*******************************************************************************
268**
269** Function         nfa_p2p_llcp_link_cback
270**
271** Description      Processing event from LLCP link management callback
272**
273**
274** Returns          None
275**
276*******************************************************************************/
277void nfa_p2p_llcp_link_cback(uint8_t event, uint8_t reason) {
278  tNFA_LLCP_ACTIVATED llcp_activated;
279  tNFA_LLCP_DEACTIVATED llcp_deactivated;
280
281  P2P_TRACE_DEBUG2("nfa_p2p_llcp_link_cback () event:0x%x, reason:0x%x", event,
282                   reason);
283
284  if (event == LLCP_LINK_ACTIVATION_COMPLETE_EVT) {
285    LLCP_GetLinkMIU(&nfa_p2p_cb.local_link_miu, &nfa_p2p_cb.remote_link_miu);
286    nfa_p2p_cb.llcp_state = NFA_P2P_LLCP_STATE_ACTIVATED;
287
288    if (nfa_p2p_cb.is_initiator) {
289      /* notify NFA DM to send Activate Event to applicaiton with status  */
290      nfa_dm_notify_activation_status(NFA_STATUS_OK, NULL);
291    }
292
293    llcp_activated.is_initiator = nfa_p2p_cb.is_initiator;
294    llcp_activated.local_link_miu = nfa_p2p_cb.local_link_miu;
295    llcp_activated.remote_link_miu = nfa_p2p_cb.remote_link_miu;
296    llcp_activated.remote_lsc = LLCP_GetRemoteLSC();
297    llcp_activated.remote_wks = LLCP_GetRemoteWKS();
298    llcp_activated.remote_version = LLCP_GetRemoteVersion();
299
300    nfa_dm_act_conn_cback_notify(NFA_LLCP_ACTIVATED_EVT,
301                                 (tNFA_CONN_EVT_DATA*)&llcp_activated);
302
303  } else if (event == LLCP_LINK_ACTIVATION_FAILED_EVT) {
304    nfa_p2p_cb.llcp_state = NFA_P2P_LLCP_STATE_IDLE;
305
306    if (nfa_p2p_cb.is_initiator) {
307      /* notify NFA DM to send Activate Event to applicaiton with status  */
308      nfa_dm_notify_activation_status(NFA_STATUS_FAILED, NULL);
309    }
310
311    nfa_dm_rf_deactivate(NFA_DEACTIVATE_TYPE_DISCOVERY);
312  } else if (event == LLCP_LINK_FIRST_PACKET_RECEIVED_EVT) {
313    nfa_dm_act_conn_cback_notify(NFA_LLCP_FIRST_PACKET_RECEIVED_EVT, NULL);
314  } else /* LLCP_LINK_DEACTIVATED_EVT       */
315  {
316    nfa_p2p_cb.llcp_state = NFA_P2P_LLCP_STATE_IDLE;
317
318    /* if got RF link loss without any rx LLC PDU */
319    if (reason == LLCP_LINK_RF_LINK_LOSS_NO_RX_LLC) {
320      /* if it was active listen mode */
321      if ((nfa_p2p_cb.is_active_mode) && (!nfa_p2p_cb.is_initiator)) {
322        /* if it didn't retry without active listen mode and passive mode is
323         * available */
324        if ((nfa_p2p_cb.listen_tech_mask_to_restore == 0x00) &&
325            (nfa_p2p_cb.listen_tech_mask &
326             (NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_F))) {
327          P2P_TRACE_DEBUG0("Retry without active listen mode");
328
329          /* retry without active listen mode */
330          nfa_p2p_update_active_listen();
331        }
332      } else if (nfa_p2p_cb.listen_tech_mask_to_restore) {
333        nfa_sys_start_timer(&nfa_p2p_cb.active_listen_restore_timer, 0,
334                            NFA_P2P_RESTORE_ACTIVE_LISTEN_TIMEOUT);
335      }
336
337      reason = LLCP_LINK_RF_LINK_LOSS_ERR;
338    } else {
339      if (nfa_p2p_cb.listen_tech_mask_to_restore) {
340        /* restore active listen mode */
341        nfa_p2p_update_active_listen();
342      }
343    }
344
345    llcp_deactivated.reason = reason;
346    nfa_dm_act_conn_cback_notify(NFA_LLCP_DEACTIVATED_EVT,
347                                 (tNFA_CONN_EVT_DATA*)&llcp_deactivated);
348
349    if (reason != LLCP_LINK_RF_LINK_LOSS_ERR) /* if NFC link is still up */
350    {
351      if (nfa_p2p_cb.is_initiator) {
352        /*For LLCP DTA test, Deactivate to Sleep is needed to send DSL_REQ*/
353        if (appl_dta_mode_flag == 1 &&
354            ((nfa_dm_cb.eDtaMode & 0x0F) == NFA_DTA_LLCP_MODE)) {
355          nfa_dm_rf_deactivate(NFA_DEACTIVATE_TYPE_SLEEP);
356        } else {
357          nfa_dm_rf_deactivate(NFA_DEACTIVATE_TYPE_DISCOVERY);
358        }
359      } else if ((nfa_p2p_cb.is_active_mode) && (reason == LLCP_LINK_TIMEOUT)) {
360        /*
361        ** target needs to trun off RF in case of receiving invalid
362        ** frame from initiator
363        */
364        P2P_TRACE_DEBUG0("Got LLCP_LINK_TIMEOUT in active mode on target");
365        nfa_dm_rf_deactivate(NFA_DEACTIVATE_TYPE_DISCOVERY);
366      }
367    }
368  }
369}
370
371/*******************************************************************************
372**
373** Function         nfa_p2p_activate_llcp
374**
375** Description      Activate LLCP link
376**
377**
378** Returns          None
379**
380*******************************************************************************/
381void nfa_p2p_activate_llcp(tNFC_DISCOVER* p_data) {
382  tLLCP_ACTIVATE_CONFIG config;
383
384  P2P_TRACE_DEBUG0("nfa_p2p_activate_llcp ()");
385
386  if ((p_data->activate.rf_tech_param.mode == NFC_DISCOVERY_TYPE_POLL_A) ||
387      (p_data->activate.rf_tech_param.mode == NFC_DISCOVERY_TYPE_POLL_F)) {
388    config.is_initiator = true;
389  } else {
390    config.is_initiator = false;
391  }
392  if (NFC_GetNCIVersion() == NCI_VERSION_2_0) {
393    if (p_data->activate.rf_tech_param.mode == NFC_DISCOVERY_TYPE_POLL_ACTIVE) {
394      config.is_initiator = true;
395    }
396  } else {
397    if ((p_data->activate.rf_tech_param.mode ==
398         NFC_DISCOVERY_TYPE_POLL_A_ACTIVE) ||
399        (p_data->activate.rf_tech_param.mode ==
400         NFC_DISCOVERY_TYPE_POLL_F_ACTIVE)) {
401      config.is_initiator = true;
402    }
403  }
404  if (NFC_GetNCIVersion() == NCI_VERSION_2_0) {
405    if ((p_data->activate.rf_tech_param.mode ==
406         NFC_DISCOVERY_TYPE_POLL_ACTIVE) ||
407        (p_data->activate.rf_tech_param.mode ==
408         NFC_DISCOVERY_TYPE_LISTEN_ACTIVE)) {
409      nfa_p2p_cb.is_active_mode = true;
410    } else {
411      nfa_p2p_cb.is_active_mode = false;
412    }
413  } else {
414    if ((p_data->activate.rf_tech_param.mode ==
415         NFC_DISCOVERY_TYPE_POLL_A_ACTIVE) ||
416        (p_data->activate.rf_tech_param.mode ==
417         NFC_DISCOVERY_TYPE_POLL_F_ACTIVE) ||
418        (p_data->activate.rf_tech_param.mode ==
419         NFC_DISCOVERY_TYPE_LISTEN_A_ACTIVE) ||
420        (p_data->activate.rf_tech_param.mode ==
421         NFC_DISCOVERY_TYPE_LISTEN_F_ACTIVE)) {
422      nfa_p2p_cb.is_active_mode = true;
423    } else {
424      nfa_p2p_cb.is_active_mode = false;
425    }
426  }
427
428  nfa_p2p_cb.is_initiator = config.is_initiator;
429
430  config.max_payload_size =
431      p_data->activate.intf_param.intf_param.pa_nfc.max_payload_size;
432  config.waiting_time =
433      p_data->activate.intf_param.intf_param.pa_nfc.waiting_time;
434  config.p_gen_bytes = p_data->activate.intf_param.intf_param.pa_nfc.gen_bytes;
435  config.gen_bytes_len =
436      p_data->activate.intf_param.intf_param.pa_nfc.gen_bytes_len;
437
438  LLCP_ActivateLink(config, nfa_p2p_llcp_link_cback);
439}
440
441/*******************************************************************************
442**
443** Function         nfa_p2p_deactivate_llcp
444**
445** Description      Deactivate LLCP link
446**
447**
448** Returns          None
449**
450*******************************************************************************/
451void nfa_p2p_deactivate_llcp(void) {
452  P2P_TRACE_DEBUG0("nfa_p2p_deactivate_llcp ()");
453
454  LLCP_DeactivateLink();
455}
456
457/*******************************************************************************
458**
459** Function         nfa_p2p_init
460**
461** Description      Initialize NFA P2P
462**
463**
464** Returns          None
465**
466*******************************************************************************/
467void nfa_p2p_init(void) {
468  uint8_t xx;
469
470  P2P_TRACE_DEBUG0("nfa_p2p_init ()");
471
472  /* initialize control block */
473  memset(&nfa_p2p_cb, 0, sizeof(tNFA_P2P_CB));
474  nfa_p2p_cb.dm_disc_handle = NFA_HANDLE_INVALID;
475  nfa_p2p_cb.trace_level = APPL_INITIAL_TRACE_LEVEL;
476
477  for (xx = 0; xx < LLCP_MAX_SDP_TRANSAC; xx++) {
478    nfa_p2p_cb.sdp_cb[xx].local_sap = LLCP_INVALID_SAP;
479  }
480
481  /* register message handler on NFA SYS */
482  nfa_sys_register(NFA_ID_P2P, &nfa_p2p_sys_reg);
483}
484
485/*******************************************************************************
486**
487** Function         nfa_p2p_sys_disable
488**
489** Description      Deregister NFA P2P from NFA SYS/DM
490**
491**
492** Returns          None
493**
494*******************************************************************************/
495static void nfa_p2p_sys_disable(void) {
496  P2P_TRACE_DEBUG0("nfa_p2p_sys_disable()");
497
498  nfa_sys_stop_timer(&nfa_p2p_cb.active_listen_restore_timer);
499
500  /* deregister message handler on NFA SYS */
501  nfa_sys_deregister(NFA_ID_P2P);
502}
503
504/*******************************************************************************
505**
506** Function         nfa_p2p_set_config
507**
508** Description      Set General bytes and WT parameters for LLCP
509**
510**
511** Returns          void
512**
513*******************************************************************************/
514void nfa_p2p_set_config(tNFA_DM_DISC_TECH_PROTO_MASK disc_mask) {
515  uint8_t wt, gen_bytes_len = LLCP_MAX_GEN_BYTES;
516  uint8_t params[LLCP_MAX_GEN_BYTES + 5], *p, length;
517
518  P2P_TRACE_DEBUG0("nfa_p2p_set_config ()");
519
520  LLCP_GetDiscoveryConfig(&wt, params + 2, &gen_bytes_len);
521  if (nfa_dm_is_p2p_paused()) {
522    gen_bytes_len = 0;
523  }
524
525  if ((disc_mask &
526       (NFA_DM_DISC_MASK_PA_NFC_DEP | NFA_DM_DISC_MASK_PF_NFC_DEP)) ||
527      ((NFC_GetNCIVersion() == NCI_VERSION_2_0) &&
528       (disc_mask & NFA_DM_DISC_MASK_PACM_NFC_DEP)) ||
529      ((NFC_GetNCIVersion() != NCI_VERSION_2_0) &&
530       (disc_mask &
531        (NFA_DM_DISC_MASK_PAA_NFC_DEP | NFA_DM_DISC_MASK_PFA_NFC_DEP)))) {
532    p = params;
533
534    UINT8_TO_BE_STREAM(p, NFC_PMID_ATR_REQ_GEN_BYTES);
535    UINT8_TO_BE_STREAM(p, gen_bytes_len);
536
537    p += gen_bytes_len;
538    length = gen_bytes_len + 2;
539
540    nfa_dm_check_set_config(length, params, false);
541  }
542
543  if ((disc_mask &
544       (NFA_DM_DISC_MASK_LA_NFC_DEP | NFA_DM_DISC_MASK_LF_NFC_DEP)) ||
545      ((NFC_GetNCIVersion() == NCI_VERSION_2_0) &&
546       (disc_mask & NFA_DM_DISC_MASK_LACM_NFC_DEP)) ||
547      ((NFC_GetNCIVersion() != NCI_VERSION_2_0) &&
548       (disc_mask &
549        (NFA_DM_DISC_MASK_LFA_NFC_DEP | NFA_DM_DISC_MASK_LAA_NFC_DEP)))) {
550    p = params;
551
552    UINT8_TO_BE_STREAM(p, NFC_PMID_ATR_RES_GEN_BYTES);
553    UINT8_TO_BE_STREAM(p, gen_bytes_len);
554
555    p += gen_bytes_len;
556    length = gen_bytes_len + 2;
557
558    UINT8_TO_BE_STREAM(p, NFC_PMID_WT);
559    UINT8_TO_BE_STREAM(p, NCI_PARAM_LEN_WT);
560    UINT8_TO_BE_STREAM(p, wt);
561
562    length += 3;
563
564    nfa_dm_check_set_config(length, params, false);
565  }
566}
567
568/*******************************************************************************
569**
570** Function         nfa_p2p_enable_listening
571**
572** Description      Configure listen technologies and protocols for LLCP
573**                  If LLCP WKS is changed then LLCP Gen bytes will be updated.
574**
575** Returns          void
576**
577*******************************************************************************/
578void nfa_p2p_enable_listening(tNFA_SYS_ID sys_id, bool update_wks) {
579  tNFA_DM_DISC_TECH_PROTO_MASK p2p_listen_mask = 0;
580
581  P2P_TRACE_DEBUG2("nfa_p2p_enable_listening () sys_id = %d, update_wks = %d",
582                   sys_id, update_wks);
583
584  if (sys_id == NFA_ID_P2P)
585    nfa_p2p_cb.is_p2p_listening = true;
586  else if (sys_id == NFA_ID_SNEP)
587    nfa_p2p_cb.is_snep_listening = true;
588
589  if (nfa_p2p_cb.dm_disc_handle != NFA_HANDLE_INVALID) {
590    /* if need to update WKS in LLCP Gen bytes */
591    if (update_wks) {
592      /* update LLCP Gen Bytes */
593      nfa_p2p_set_config(NFA_DM_DISC_MASK_PA_NFC_DEP |
594                         NFA_DM_DISC_MASK_LA_NFC_DEP);
595    }
596    return;
597  }
598
599  /* collect listen technologies with NFC-DEP protocol */
600  if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_A)
601    p2p_listen_mask |= NFA_DM_DISC_MASK_LA_NFC_DEP;
602
603  if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_F)
604    p2p_listen_mask |= NFA_DM_DISC_MASK_LF_NFC_DEP;
605
606  if (NFC_GetNCIVersion() == NCI_VERSION_2_0) {
607    if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_ACTIVE)
608      p2p_listen_mask |= NFA_DM_DISC_MASK_LACM_NFC_DEP;
609  } else {
610    if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_A_ACTIVE)
611      p2p_listen_mask |= NFA_DM_DISC_MASK_LAA_NFC_DEP;
612
613    if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_F_ACTIVE)
614      p2p_listen_mask |= NFA_DM_DISC_MASK_LFA_NFC_DEP;
615  }
616
617  if (p2p_listen_mask) {
618    /* For P2P mode(Default DTA mode) open Raw channel to bypass LLCP layer.
619     * For LLCP DTA mode activate LLCP Bypassing LLCP is handled in
620     * nfa_dm_poll_disc_cback */
621    if (appl_dta_mode_flag == 1 &&
622        ((nfa_dm_cb.eDtaMode & 0x0F) == NFA_DTA_DEFAULT_MODE)) {
623      /* Configure listen technologies and protocols and register callback to
624       * NFA DM discovery */
625      P2P_TRACE_DEBUG1(
626          "%s: DTA mode:Registering nfa_dm_poll_disc_cback to avoid LLCP in "
627          "P2P",
628          __func__);
629      nfa_p2p_cb.dm_disc_handle =
630          nfa_dm_add_rf_discover(p2p_listen_mask, NFA_DM_DISC_HOST_ID_DH,
631                                 nfa_dm_poll_disc_cback_dta_wrapper);
632    } else {
633      /* Configure listen technologies and protocols and register callback to
634       * NFA DM discovery */
635      nfa_p2p_cb.dm_disc_handle = nfa_dm_add_rf_discover(
636          p2p_listen_mask, NFA_DM_DISC_HOST_ID_DH, nfa_p2p_discovery_cback);
637    }
638  }
639}
640
641/*******************************************************************************
642**
643** Function         nfa_p2p_disable_listening
644**
645** Description      Remove listen technologies and protocols for LLCP and
646**                  deregister callback from NFA DM discovery if all of
647**                  P2P/CHO/SNEP doesn't listen LLCP any more.
648**                  If LLCP WKS is changed then ATR_RES will be updated.
649**
650** Returns          void
651**
652*******************************************************************************/
653void nfa_p2p_disable_listening(tNFA_SYS_ID sys_id, bool update_wks) {
654  P2P_TRACE_DEBUG2("nfa_p2p_disable_listening ()  sys_id = %d, update_wks = %d",
655                   sys_id, update_wks);
656
657  if (sys_id == NFA_ID_P2P)
658    nfa_p2p_cb.is_p2p_listening = false;
659  else if (sys_id == NFA_ID_SNEP)
660    nfa_p2p_cb.is_snep_listening = false;
661
662  if (nfa_p2p_cb.dm_disc_handle != NFA_HANDLE_INVALID) {
663    if ((nfa_p2p_cb.is_p2p_listening == false) &&
664        (nfa_p2p_cb.is_snep_listening == false)) {
665      nfa_p2p_cb.llcp_state = NFA_P2P_LLCP_STATE_IDLE;
666      nfa_p2p_cb.rf_disc_state = NFA_DM_RFST_IDLE;
667
668      nfa_dm_delete_rf_discover(nfa_p2p_cb.dm_disc_handle);
669      nfa_p2p_cb.dm_disc_handle = NFA_HANDLE_INVALID;
670    } else if (update_wks) {
671      /* update LLCP Gen Bytes */
672      nfa_p2p_set_config(NFA_DM_DISC_MASK_PA_NFC_DEP |
673                         NFA_DM_DISC_MASK_LA_NFC_DEP);
674    }
675  }
676}
677
678/*******************************************************************************
679**
680** Function         nfa_p2p_update_listen_tech
681**
682** Description      Update P2P listen technologies. If there is change then
683**                  restart or stop P2P listen.
684**
685** Returns          void
686**
687*******************************************************************************/
688void nfa_p2p_update_listen_tech(tNFA_TECHNOLOGY_MASK tech_mask) {
689  P2P_TRACE_DEBUG1("nfa_p2p_update_listen_tech ()  tech_mask = 0x%x",
690                   tech_mask);
691
692  if (nfa_p2p_cb.listen_tech_mask_to_restore) {
693    nfa_p2p_cb.listen_tech_mask_to_restore = 0;
694    nfa_sys_stop_timer(&nfa_p2p_cb.active_listen_restore_timer);
695  }
696
697  if (nfa_p2p_cb.listen_tech_mask != tech_mask) {
698    nfa_p2p_cb.listen_tech_mask = tech_mask;
699
700    if (nfa_p2p_cb.dm_disc_handle != NFA_HANDLE_INVALID) {
701      nfa_p2p_cb.rf_disc_state = NFA_DM_RFST_IDLE;
702
703      nfa_dm_delete_rf_discover(nfa_p2p_cb.dm_disc_handle);
704      nfa_p2p_cb.dm_disc_handle = NFA_HANDLE_INVALID;
705    }
706
707    /* restart discovery without updating sub-module status */
708    if (nfa_p2p_cb.is_p2p_listening || appl_dta_mode_flag)
709      nfa_p2p_enable_listening(NFA_ID_P2P, false);
710    else if (nfa_p2p_cb.is_snep_listening)
711      nfa_p2p_enable_listening(NFA_ID_SNEP, false);
712  }
713}
714
715/*******************************************************************************
716**
717** Function         nfa_p2p_evt_hdlr
718**
719** Description      Processing event for NFA P2P
720**
721**
722** Returns          TRUE if p_msg needs to be deallocated
723**
724*******************************************************************************/
725static bool nfa_p2p_evt_hdlr(NFC_HDR* p_hdr) {
726  bool delete_msg = true;
727  uint16_t event;
728
729  tNFA_P2P_MSG* p_msg = (tNFA_P2P_MSG*)p_hdr;
730
731#if (BT_TRACE_VERBOSE == TRUE)
732  P2P_TRACE_DEBUG2("nfa_p2p_evt_hdlr (): LLCP State [%s], Event [%s]",
733                   nfa_p2p_llcp_state_code(nfa_p2p_cb.llcp_state),
734                   nfa_p2p_evt_code(p_msg->hdr.event));
735#else
736  P2P_TRACE_DEBUG2("nfa_p2p_evt_hdlr (): State 0x%02x, Event 0x%02x",
737                   nfa_p2p_cb.llcp_state, p_msg->hdr.event);
738#endif
739
740  event = p_msg->hdr.event & 0x00ff;
741
742  /* execute action functions */
743  if (event < NFA_P2P_NUM_ACTIONS) {
744    delete_msg = (*nfa_p2p_action[event])(p_msg);
745  } else {
746    P2P_TRACE_ERROR0("Unhandled event");
747  }
748
749  return delete_msg;
750}
751
752#if (BT_TRACE_VERBOSE == TRUE)
753/*******************************************************************************
754**
755** Function         nfa_p2p_llcp_state_code
756**
757** Description
758**
759** Returns          string of state
760**
761*******************************************************************************/
762static char* nfa_p2p_llcp_state_code(tNFA_P2P_LLCP_STATE state_code) {
763  switch (state_code) {
764    case NFA_P2P_LLCP_STATE_IDLE:
765      return "Link IDLE";
766    case NFA_P2P_LLCP_STATE_LISTENING:
767      return "Link LISTENING";
768    case NFA_P2P_LLCP_STATE_ACTIVATED:
769      return "Link ACTIVATED";
770    default:
771      return "Unknown state";
772  }
773}
774
775/*******************************************************************************
776**
777** Function         nfa_p2p_evt_code
778**
779** Description
780**
781** Returns          string of event
782**
783*******************************************************************************/
784char* nfa_p2p_evt_code(uint16_t evt_code) {
785  switch (evt_code) {
786    case NFA_P2P_API_REG_SERVER_EVT:
787      return "API_REG_SERVER";
788    case NFA_P2P_API_REG_CLIENT_EVT:
789      return "API_REG_CLIENT";
790    case NFA_P2P_API_DEREG_EVT:
791      return "API_DEREG";
792    case NFA_P2P_API_ACCEPT_CONN_EVT:
793      return "API_ACCEPT_CONN";
794    case NFA_P2P_API_REJECT_CONN_EVT:
795      return "API_REJECT_CONN";
796    case NFA_P2P_API_DISCONNECT_EVT:
797      return "API_DISCONNECT";
798    case NFA_P2P_API_CONNECT_EVT:
799      return "API_CONNECT";
800    case NFA_P2P_API_SEND_UI_EVT:
801      return "API_SEND_UI";
802    case NFA_P2P_API_SEND_DATA_EVT:
803      return "API_SEND_DATA";
804    case NFA_P2P_API_SET_LOCAL_BUSY_EVT:
805      return "API_SET_LOCAL_BUSY";
806    case NFA_P2P_API_GET_LINK_INFO_EVT:
807      return "API_GET_LINK_INFO";
808    case NFA_P2P_API_GET_REMOTE_SAP_EVT:
809      return "API_GET_REMOTE_SAP";
810    case NFA_P2P_API_SET_LLCP_CFG_EVT:
811      return "API_SET_LLCP_CFG_EVT";
812    case NFA_P2P_INT_RESTART_RF_DISC_EVT:
813      return "RESTART_RF_DISC_EVT";
814    default:
815      return "Unknown event";
816  }
817}
818#endif /* Debug Functions */
819