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