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 implementation file for the NFA P2P.
22 *
23 ******************************************************************************/
24
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#include "string.h"
34
35/*****************************************************************************
36**  Global Variables
37*****************************************************************************/
38
39/*****************************************************************************
40**  Static Functions
41*****************************************************************************/
42
43/*****************************************************************************
44**  Constants
45*****************************************************************************/
46
47/*******************************************************************************
48**
49** Function         nfa_p2p_allocate_conn_cb
50**
51** Description      Allocate data link connection control block
52**
53**
54** Returns          uint8_t
55**
56*******************************************************************************/
57static uint8_t nfa_p2p_allocate_conn_cb(uint8_t local_sap) {
58  uint8_t xx;
59
60  for (xx = 0; xx < LLCP_MAX_DATA_LINK; xx++) {
61    if (nfa_p2p_cb.conn_cb[xx].flags == 0) {
62      nfa_p2p_cb.conn_cb[xx].flags |= NFA_P2P_CONN_FLAG_IN_USE;
63      nfa_p2p_cb.conn_cb[xx].local_sap = local_sap;
64
65      return (xx);
66    }
67  }
68
69  P2P_TRACE_ERROR0("nfa_p2p_allocate_conn_cb (): No resource");
70
71  return LLCP_MAX_DATA_LINK;
72}
73
74/*******************************************************************************
75**
76** Function         nfa_p2p_deallocate_conn_cb
77**
78** Description      Deallocate data link connection control block
79**
80**
81** Returns          void
82**
83*******************************************************************************/
84static void nfa_p2p_deallocate_conn_cb(uint8_t xx) {
85  if (xx < LLCP_MAX_DATA_LINK) {
86    nfa_p2p_cb.conn_cb[xx].flags = 0;
87  } else {
88    P2P_TRACE_ERROR1("nfa_p2p_deallocate_conn_cb (): Invalid index (%d)", xx);
89  }
90}
91
92/*******************************************************************************
93**
94** Function         nfa_p2p_find_conn_cb
95**
96** Description      Find data link connection control block by local/remote SAP
97**
98**
99** Returns          uint8_t
100**
101*******************************************************************************/
102static uint8_t nfa_p2p_find_conn_cb(uint8_t local_sap, uint8_t remote_sap) {
103  uint8_t xx;
104
105  for (xx = 0; xx < LLCP_MAX_DATA_LINK; xx++) {
106    if ((nfa_p2p_cb.conn_cb[xx].flags & NFA_P2P_CONN_FLAG_IN_USE) &&
107        (nfa_p2p_cb.conn_cb[xx].local_sap == local_sap) &&
108        (nfa_p2p_cb.conn_cb[xx].remote_sap == remote_sap)) {
109      return (xx);
110    }
111  }
112
113  return (LLCP_MAX_DATA_LINK);
114}
115
116/*******************************************************************************
117**
118** Function         nfa_p2p_llcp_cback
119**
120** Description      Processing SAP callback events from LLCP
121**
122**
123** Returns          None
124**
125*******************************************************************************/
126static void nfa_p2p_llcp_cback(tLLCP_SAP_CBACK_DATA* p_data) {
127  P2P_TRACE_DEBUG2("nfa_p2p_llcp_cback (): event:0x%02X, local_sap:0x%02X",
128                   p_data->hdr.event, p_data->hdr.local_sap);
129
130  switch (p_data->hdr.event) {
131    case LLCP_SAP_EVT_DATA_IND:
132      nfa_p2p_proc_llcp_data_ind(p_data);
133      break;
134
135    case LLCP_SAP_EVT_CONNECT_IND:
136      nfa_p2p_proc_llcp_connect_ind(p_data);
137      break;
138
139    case LLCP_SAP_EVT_CONNECT_RESP:
140      nfa_p2p_proc_llcp_connect_resp(p_data);
141      break;
142
143    case LLCP_SAP_EVT_DISCONNECT_IND:
144      nfa_p2p_proc_llcp_disconnect_ind(p_data);
145      break;
146
147    case LLCP_SAP_EVT_DISCONNECT_RESP:
148      nfa_p2p_proc_llcp_disconnect_resp(p_data);
149      break;
150
151    case LLCP_SAP_EVT_CONGEST:
152      nfa_p2p_proc_llcp_congestion(p_data);
153      break;
154
155    case LLCP_SAP_EVT_LINK_STATUS:
156      nfa_p2p_proc_llcp_link_status(p_data);
157      break;
158
159    default:
160      P2P_TRACE_ERROR1("nfa_p2p_llcp_cback (): Unknown event:0x%02X",
161                       p_data->hdr.event);
162      return;
163  }
164}
165
166/*******************************************************************************
167**
168** Function         nfa_p2p_sdp_cback
169**
170** Description      Process SDP callback event from LLCP
171**
172**
173** Returns          None
174**
175*******************************************************************************/
176void nfa_p2p_sdp_cback(uint8_t tid, uint8_t remote_sap) {
177  uint8_t local_sap;
178  uint8_t xx;
179  tNFA_P2P_EVT_DATA evt_data;
180
181  P2P_TRACE_DEBUG2("nfa_p2p_sdp_cback (): tid:0x%02X, remote_sap:0x%02X", tid,
182                   remote_sap);
183
184  /* search for callback function to process */
185  for (xx = 0; xx < LLCP_MAX_SDP_TRANSAC; xx++) {
186    if ((nfa_p2p_cb.sdp_cb[xx].local_sap != LLCP_INVALID_SAP) &&
187        (nfa_p2p_cb.sdp_cb[xx].tid == tid)) {
188      local_sap = nfa_p2p_cb.sdp_cb[xx].local_sap;
189
190      evt_data.sdp.handle = (NFA_HANDLE_GROUP_P2P | local_sap);
191      evt_data.sdp.remote_sap = remote_sap;
192      nfa_p2p_cb.sap_cb[local_sap].p_cback(NFA_P2P_SDP_EVT, &evt_data);
193
194      nfa_p2p_cb.sdp_cb[xx].local_sap = LLCP_INVALID_SAP;
195      break;
196    }
197  }
198}
199
200/*******************************************************************************
201**
202** Function         nfa_p2p_start_sdp
203**
204** Description      Initiate SDP
205**
206**
207** Returns          TRUE if success
208**
209*******************************************************************************/
210bool nfa_p2p_start_sdp(char* p_service_name, uint8_t local_sap) {
211  int xx;
212
213  P2P_TRACE_DEBUG1("nfa_p2p_start_sdp (): SN:<%s>", p_service_name);
214
215  /* search for empty slot */
216  for (xx = 0; xx < LLCP_MAX_SDP_TRANSAC; xx++) {
217    if (nfa_p2p_cb.sdp_cb[xx].local_sap == LLCP_INVALID_SAP) {
218      if (LLCP_DiscoverService(p_service_name, nfa_p2p_sdp_cback,
219                               &(nfa_p2p_cb.sdp_cb[xx].tid)) ==
220          LLCP_STATUS_SUCCESS) {
221        nfa_p2p_cb.sdp_cb[xx].local_sap = local_sap;
222        return true;
223      } else {
224        /* failure of SDP */
225        return false;
226      }
227    }
228  }
229  return false;
230}
231
232/*******************************************************************************
233**
234** Function         nfa_p2p_proc_llcp_data_ind
235**
236** Description      Processing incoming data event from LLCP
237**
238**
239** Returns          None
240**
241*******************************************************************************/
242void nfa_p2p_proc_llcp_data_ind(tLLCP_SAP_CBACK_DATA* p_data) {
243  uint8_t local_sap, xx;
244  tNFA_P2P_EVT_DATA evt_data;
245
246  P2P_TRACE_DEBUG0("nfa_p2p_proc_llcp_data_ind ()");
247
248  local_sap = p_data->data_ind.local_sap;
249
250  if (nfa_p2p_cb.sap_cb[local_sap].p_cback) {
251    evt_data.data.handle = 0;
252    /* if connectionless */
253    if (p_data->data_ind.link_type == NFA_P2P_LLINK_TYPE) {
254      evt_data.data.handle = (NFA_HANDLE_GROUP_P2P | local_sap);
255    } else {
256      xx = nfa_p2p_find_conn_cb(p_data->data_ind.local_sap,
257                                p_data->data_ind.remote_sap);
258
259      if (xx != LLCP_MAX_DATA_LINK) {
260        evt_data.data.handle =
261            (NFA_HANDLE_GROUP_P2P | NFA_P2P_HANDLE_FLAG_CONN | xx);
262      }
263    }
264
265    evt_data.data.remote_sap = p_data->data_ind.remote_sap;
266    evt_data.data.link_type = p_data->data_ind.link_type;
267
268    /* notify upper layer that there are data at LLCP */
269    nfa_p2p_cb.sap_cb[local_sap].p_cback(NFA_P2P_DATA_EVT, &evt_data);
270  }
271}
272
273/*******************************************************************************
274**
275** Function         nfa_p2p_proc_llcp_connect_ind
276**
277** Description      Processing connection request from peer
278**
279**
280** Returns          None
281**
282*******************************************************************************/
283void nfa_p2p_proc_llcp_connect_ind(tLLCP_SAP_CBACK_DATA* p_data) {
284  uint8_t server_sap, local_sap;
285  tNFA_P2P_EVT_DATA evt_data;
286  uint8_t xx;
287
288  P2P_TRACE_DEBUG1("nfa_p2p_proc_llcp_connect_ind () server_sap:0x%x",
289                   p_data->connect_ind.server_sap);
290
291  server_sap = p_data->connect_ind.server_sap;
292  local_sap = p_data->connect_ind.local_sap;
293
294  if (nfa_p2p_cb.sap_cb[server_sap].p_cback) {
295    xx = nfa_p2p_allocate_conn_cb(server_sap);
296
297    if (xx != LLCP_MAX_DATA_LINK) {
298      nfa_p2p_cb.conn_cb[xx].remote_sap = p_data->connect_ind.remote_sap;
299      nfa_p2p_cb.conn_cb[xx].remote_miu = p_data->connect_ind.miu;
300
301      /* peer will not receive any data */
302      if (p_data->connect_ind.rw == 0)
303        nfa_p2p_cb.conn_cb[xx].flags |= NFA_P2P_CONN_FLAG_REMOTE_RW_ZERO;
304
305      evt_data.conn_req.server_handle = (NFA_HANDLE_GROUP_P2P | server_sap);
306      evt_data.conn_req.conn_handle =
307          (NFA_HANDLE_GROUP_P2P | NFA_P2P_HANDLE_FLAG_CONN | xx);
308      evt_data.conn_req.remote_sap = p_data->connect_ind.remote_sap;
309      evt_data.conn_req.remote_miu = p_data->connect_ind.miu;
310      evt_data.conn_req.remote_rw = p_data->connect_ind.rw;
311
312      nfa_p2p_cb.sap_cb[server_sap].p_cback(NFA_P2P_CONN_REQ_EVT, &evt_data);
313    }
314  } else {
315    P2P_TRACE_ERROR0("nfa_p2p_proc_llcp_connect_ind (): Not registered");
316  }
317}
318
319/*******************************************************************************
320**
321** Function         nfa_p2p_proc_llcp_connect_resp
322**
323** Description      Processing connection response from peer
324**
325**
326** Returns          None
327**
328*******************************************************************************/
329void nfa_p2p_proc_llcp_connect_resp(tLLCP_SAP_CBACK_DATA* p_data) {
330  uint8_t local_sap, xx;
331  tNFA_P2P_EVT_DATA evt_data;
332
333  P2P_TRACE_DEBUG0("nfa_p2p_proc_llcp_connect_resp ()");
334
335  local_sap = p_data->connect_resp.local_sap;
336
337  if (nfa_p2p_cb.sap_cb[local_sap].p_cback) {
338    xx = nfa_p2p_allocate_conn_cb(local_sap);
339
340    if (xx != LLCP_MAX_DATA_LINK) {
341      nfa_p2p_cb.conn_cb[xx].remote_sap = p_data->connect_resp.remote_sap;
342      nfa_p2p_cb.conn_cb[xx].remote_miu = p_data->connect_resp.miu;
343
344      /* peer will not receive any data */
345      if (p_data->connect_resp.rw == 0)
346        nfa_p2p_cb.conn_cb[xx].flags |= NFA_P2P_CONN_FLAG_REMOTE_RW_ZERO;
347
348      evt_data.connected.client_handle = (NFA_HANDLE_GROUP_P2P | local_sap);
349      evt_data.connected.conn_handle =
350          (NFA_HANDLE_GROUP_P2P | NFA_P2P_HANDLE_FLAG_CONN | xx);
351      evt_data.connected.remote_sap = p_data->connect_resp.remote_sap;
352      evt_data.connected.remote_miu = p_data->connect_resp.miu;
353      evt_data.connected.remote_rw = p_data->connect_resp.rw;
354
355      nfa_p2p_cb.sap_cb[local_sap].p_cback(NFA_P2P_CONNECTED_EVT, &evt_data);
356    }
357  }
358}
359
360/*******************************************************************************
361**
362** Function         nfa_p2p_proc_llcp_disconnect_ind
363**
364** Description      Processing disconnection request from peer
365**
366**
367** Returns          None
368**
369*******************************************************************************/
370void nfa_p2p_proc_llcp_disconnect_ind(tLLCP_SAP_CBACK_DATA* p_data) {
371  uint8_t local_sap, xx;
372  tNFA_P2P_EVT_DATA evt_data;
373
374  P2P_TRACE_DEBUG0("nfa_p2p_proc_llcp_disconnect_ind ()");
375
376  local_sap = p_data->disconnect_ind.local_sap;
377
378  if (nfa_p2p_cb.sap_cb[local_sap].p_cback) {
379    xx = nfa_p2p_find_conn_cb(p_data->disconnect_ind.local_sap,
380                              p_data->disconnect_ind.remote_sap);
381
382    if (xx != LLCP_MAX_DATA_LINK) {
383      evt_data.disc.handle =
384          (NFA_HANDLE_GROUP_P2P | NFA_P2P_HANDLE_FLAG_CONN | xx);
385      evt_data.disc.reason = NFA_P2P_DISC_REASON_REMOTE_INITIATE;
386
387      nfa_p2p_deallocate_conn_cb(xx);
388
389      nfa_p2p_cb.sap_cb[local_sap].p_cback(NFA_P2P_DISC_EVT, &evt_data);
390    } else {
391      /*
392      ** LLCP link has been deactivated before receiving CC or DM.
393      ** Return NFA_P2P_DISC_EVT to indicate failure of creating
394      ** connection
395      */
396
397      evt_data.disc.handle = (NFA_HANDLE_GROUP_P2P | local_sap);
398      evt_data.disc.reason = NFA_P2P_DISC_REASON_LLCP_DEACTIVATED;
399
400      nfa_p2p_cb.sap_cb[local_sap].p_cback(NFA_P2P_DISC_EVT, &evt_data);
401
402      P2P_TRACE_ERROR0("nfa_p2p_proc_llcp_disconnect_ind (): Link deactivated");
403    }
404  }
405}
406
407/*******************************************************************************
408**
409** Function         nfa_p2p_proc_llcp_disconnect_resp
410**
411** Description      Processing rejected connection from peer
412**
413**
414** Returns          None
415**
416*******************************************************************************/
417void nfa_p2p_proc_llcp_disconnect_resp(tLLCP_SAP_CBACK_DATA* p_data) {
418  uint8_t local_sap, xx;
419  tNFA_P2P_EVT_DATA evt_data;
420
421  P2P_TRACE_DEBUG0("nfa_p2p_proc_llcp_disconnect_resp ()");
422
423  local_sap = p_data->disconnect_resp.local_sap;
424
425  if (nfa_p2p_cb.sap_cb[local_sap].p_cback) {
426    if (p_data->disconnect_resp.reason == LLCP_SAP_DM_REASON_RESP_DISC) {
427      evt_data.disc.reason = NFA_P2P_DISC_REASON_LOCAL_INITITATE;
428    } else if ((p_data->disconnect_resp.reason ==
429                LLCP_SAP_DM_REASON_APP_REJECTED) ||
430               (p_data->disconnect_resp.reason ==
431                LLCP_SAP_DM_REASON_PERM_REJECT_THIS) ||
432               (p_data->disconnect_resp.reason ==
433                LLCP_SAP_DM_REASON_PERM_REJECT_ANY) ||
434               (p_data->disconnect_resp.reason ==
435                LLCP_SAP_DM_REASON_TEMP_REJECT_THIS) ||
436               (p_data->disconnect_resp.reason ==
437                LLCP_SAP_DM_REASON_TEMP_REJECT_ANY)) {
438      evt_data.disc.reason = NFA_P2P_DISC_REASON_REMOTE_REJECT;
439    } else if (p_data->disconnect_resp.reason ==
440               LLCP_SAP_DM_REASON_NO_SERVICE) {
441      evt_data.disc.reason = NFA_P2P_DISC_REASON_NO_SERVICE;
442    } else if (p_data->disconnect_resp.reason ==
443               LLCP_SAP_DM_REASON_NO_ACTIVE_CONNECTION) {
444      evt_data.disc.reason = NFA_P2P_DISC_REASON_LLCP_DEACTIVATED;
445    } else {
446      evt_data.disc.reason = NFA_P2P_DISC_REASON_NO_INFORMATION;
447    }
448
449    if (evt_data.disc.reason == NFA_P2P_DISC_REASON_LOCAL_INITITATE) {
450      xx = nfa_p2p_find_conn_cb(p_data->disconnect_resp.local_sap,
451                                p_data->disconnect_resp.remote_sap);
452
453      if (xx != LLCP_MAX_DATA_LINK) {
454        evt_data.disc.handle =
455            (NFA_HANDLE_GROUP_P2P | NFA_P2P_HANDLE_FLAG_CONN | xx);
456
457        nfa_p2p_deallocate_conn_cb(xx);
458
459        nfa_p2p_cb.sap_cb[local_sap].p_cback(NFA_P2P_DISC_EVT, &evt_data);
460      } else {
461        P2P_TRACE_ERROR0(
462            "nfa_p2p_proc_llcp_disconnect_resp (): No connection found");
463      }
464    } else {
465      evt_data.disc.handle = (NFA_HANDLE_GROUP_P2P | local_sap);
466      nfa_p2p_cb.sap_cb[local_sap].p_cback(NFA_P2P_DISC_EVT, &evt_data);
467    }
468  }
469}
470
471/*******************************************************************************
472**
473** Function         nfa_p2p_proc_llcp_congest
474**
475** Description      Processing LLCP congestion event
476**
477**
478** Returns          None
479**
480*******************************************************************************/
481void nfa_p2p_proc_llcp_congestion(tLLCP_SAP_CBACK_DATA* p_data) {
482  uint8_t local_sap, remote_sap, xx;
483  tNFA_P2P_EVT_DATA evt_data;
484
485  local_sap = p_data->congest.local_sap;
486  remote_sap = p_data->congest.remote_sap;
487
488  evt_data.congest.link_type = p_data->congest.link_type;
489  evt_data.congest.is_congested = p_data->congest.is_congested;
490
491  if (p_data->congest.is_congested) {
492    P2P_TRACE_DEBUG2("nfa_p2p_proc_llcp_congestion () START SAP=(0x%x,0x%x)",
493                     local_sap, remote_sap);
494
495  } else {
496    P2P_TRACE_DEBUG2("nfa_p2p_proc_llcp_congestion () END SAP=(0x%x,0x%x)",
497                     local_sap, remote_sap);
498  }
499
500  if (nfa_p2p_cb.sap_cb[local_sap].p_cback) {
501    if (evt_data.congest.link_type == NFA_P2P_LLINK_TYPE) {
502      evt_data.congest.handle = (NFA_HANDLE_GROUP_P2P | local_sap);
503
504      if ((evt_data.congest.is_congested == false) &&
505          (nfa_p2p_cb.sap_cb[local_sap].flags &
506           NFA_P2P_SAP_FLAG_LLINK_CONGESTED)) {
507        nfa_p2p_cb.sap_cb[local_sap].flags &= ~NFA_P2P_SAP_FLAG_LLINK_CONGESTED;
508        nfa_p2p_cb.sap_cb[local_sap].p_cback(NFA_P2P_CONGEST_EVT, &evt_data);
509      } else if ((evt_data.congest.is_congested == true) &&
510                 (!(nfa_p2p_cb.sap_cb[local_sap].flags &
511                    NFA_P2P_SAP_FLAG_LLINK_CONGESTED))) {
512        /* this is overall congestion due to high usage of buffer pool */
513        nfa_p2p_cb.sap_cb[local_sap].flags |= NFA_P2P_SAP_FLAG_LLINK_CONGESTED;
514        nfa_p2p_cb.sap_cb[local_sap].p_cback(NFA_P2P_CONGEST_EVT, &evt_data);
515      }
516    } else {
517      xx = nfa_p2p_find_conn_cb(local_sap, remote_sap);
518
519      if (xx != LLCP_MAX_DATA_LINK) {
520        evt_data.congest.handle =
521            (NFA_HANDLE_GROUP_P2P | NFA_P2P_HANDLE_FLAG_CONN | xx);
522
523        if ((evt_data.congest.is_congested == false) &&
524            (nfa_p2p_cb.conn_cb[xx].flags & NFA_P2P_CONN_FLAG_CONGESTED)) {
525          nfa_p2p_cb.conn_cb[xx].flags &= ~NFA_P2P_CONN_FLAG_CONGESTED;
526          nfa_p2p_cb.sap_cb[local_sap].p_cback(NFA_P2P_CONGEST_EVT, &evt_data);
527        } else if ((evt_data.congest.is_congested == true) &&
528                   (!(nfa_p2p_cb.conn_cb[xx].flags &
529                      NFA_P2P_CONN_FLAG_CONGESTED))) {
530          /* this is overall congestion due to high usage of buffer pool */
531          nfa_p2p_cb.conn_cb[xx].flags |= NFA_P2P_CONN_FLAG_CONGESTED;
532          nfa_p2p_cb.sap_cb[local_sap].p_cback(NFA_P2P_CONGEST_EVT, &evt_data);
533        }
534      } else {
535        P2P_TRACE_ERROR0(
536            "nfa_p2p_proc_llcp_congestion (): No connection found");
537      }
538    }
539  }
540}
541
542/*******************************************************************************
543**
544** Function         nfa_p2p_proc_llcp_link_status
545**
546** Description      Processing LLCP link status
547**
548**
549** Returns          next state after processing this event
550**
551*******************************************************************************/
552void nfa_p2p_proc_llcp_link_status(tLLCP_SAP_CBACK_DATA* p_data) {
553  uint8_t local_sap, xx;
554  tNFA_P2P_EVT_DATA evt_data;
555
556  P2P_TRACE_DEBUG1("nfa_p2p_proc_llcp_link_status () is_activated:%d",
557                   p_data->link_status.is_activated);
558
559  local_sap = p_data->link_status.local_sap;
560
561  if (nfa_p2p_cb.sap_cb[local_sap].p_cback) {
562    if (p_data->link_status.is_activated) {
563      /* only for server */
564      evt_data.activated.handle = (NFA_HANDLE_GROUP_P2P | local_sap);
565      evt_data.activated.local_link_miu = nfa_p2p_cb.local_link_miu;
566      evt_data.activated.remote_link_miu = nfa_p2p_cb.remote_link_miu;
567
568      nfa_p2p_cb.sap_cb[local_sap].p_cback(NFA_P2P_ACTIVATED_EVT, &evt_data);
569    } else /* if LLCP link is deactivated */
570    {
571      for (xx = 0; xx < LLCP_MAX_DATA_LINK; xx++) {
572        if ((nfa_p2p_cb.conn_cb[xx].flags & NFA_P2P_CONN_FLAG_IN_USE) &&
573            (nfa_p2p_cb.conn_cb[xx].local_sap == local_sap)) {
574          evt_data.disc.handle =
575              (NFA_HANDLE_GROUP_P2P | NFA_P2P_HANDLE_FLAG_CONN | xx);
576          evt_data.disc.reason = NFA_P2P_DISC_REASON_LLCP_DEACTIVATED;
577
578          nfa_p2p_deallocate_conn_cb(xx);
579          nfa_p2p_cb.sap_cb[local_sap].p_cback(NFA_P2P_DISC_EVT, &evt_data);
580        }
581      }
582
583      /* notify deactivation and clear flags */
584      if (nfa_p2p_cb.sap_cb[local_sap].flags & NFA_P2P_SAP_FLAG_SERVER) {
585        evt_data.deactivated.handle = (NFA_HANDLE_GROUP_P2P | local_sap);
586        nfa_p2p_cb.sap_cb[local_sap].p_cback(NFA_P2P_DEACTIVATED_EVT,
587                                             &evt_data);
588
589        nfa_p2p_cb.sap_cb[local_sap].flags = NFA_P2P_SAP_FLAG_SERVER;
590      } else if (nfa_p2p_cb.sap_cb[local_sap].flags & NFA_P2P_SAP_FLAG_CLIENT) {
591        evt_data.deactivated.handle = (NFA_HANDLE_GROUP_P2P | local_sap);
592        nfa_p2p_cb.sap_cb[local_sap].p_cback(NFA_P2P_DEACTIVATED_EVT,
593                                             &evt_data);
594
595        nfa_p2p_cb.sap_cb[local_sap].flags = NFA_P2P_SAP_FLAG_CLIENT;
596      } else /* if this is not registered service */
597      {
598        nfa_p2p_cb.sap_cb[local_sap].p_cback = NULL;
599      }
600    }
601  }
602}
603
604/*******************************************************************************
605**
606** Function         nfa_p2p_reg_server
607**
608** Description      Allocate a service as server and register to LLCP
609**
610**
611** Returns          FALSE if need to keep buffer
612**
613*******************************************************************************/
614bool nfa_p2p_reg_server(tNFA_P2P_MSG* p_msg) {
615  tNFA_P2P_EVT_DATA evt_data;
616  uint8_t server_sap;
617
618  P2P_TRACE_DEBUG0("nfa_p2p_reg_server ()");
619
620  server_sap = LLCP_RegisterServer(
621      p_msg->api_reg_server.server_sap, p_msg->api_reg_server.link_type,
622      p_msg->api_reg_server.service_name, nfa_p2p_llcp_cback);
623
624  if (server_sap == LLCP_INVALID_SAP) {
625    evt_data.reg_server.server_handle = NFA_HANDLE_INVALID;
626    evt_data.reg_server.server_sap = NFA_P2P_INVALID_SAP;
627    strncpy(evt_data.reg_server.service_name,
628            p_msg->api_reg_server.service_name, LLCP_MAX_SN_LEN);
629    evt_data.reg_server.service_name[LLCP_MAX_SN_LEN] = 0;
630
631    p_msg->api_reg_server.p_cback(NFA_P2P_REG_SERVER_EVT, &evt_data);
632
633    return true;
634  }
635
636  /* if need to update WKS in LLCP Gen bytes */
637  if (server_sap <= LLCP_UPPER_BOUND_WK_SAP) {
638    nfa_p2p_enable_listening(NFA_ID_P2P, true);
639  } else if (!nfa_p2p_cb.is_p2p_listening) {
640    nfa_p2p_enable_listening(NFA_ID_P2P, false);
641  }
642
643  nfa_p2p_cb.sap_cb[server_sap].p_cback = p_msg->api_reg_server.p_cback;
644  nfa_p2p_cb.sap_cb[server_sap].flags = NFA_P2P_SAP_FLAG_SERVER;
645
646  evt_data.reg_server.server_handle = (NFA_HANDLE_GROUP_P2P | server_sap);
647  evt_data.reg_server.server_sap = server_sap;
648  strncpy(evt_data.reg_server.service_name, p_msg->api_reg_server.service_name,
649          LLCP_MAX_SN_LEN);
650  evt_data.reg_server.service_name[LLCP_MAX_SN_LEN] = 0;
651
652  /* notify NFA_P2P_REG_SERVER_EVT to server */
653  nfa_p2p_cb.sap_cb[server_sap].p_cback(NFA_P2P_REG_SERVER_EVT, &evt_data);
654
655  /* if LLCP is already activated */
656  if (nfa_p2p_cb.llcp_state == NFA_P2P_LLCP_STATE_ACTIVATED) {
657    evt_data.activated.handle = (NFA_HANDLE_GROUP_P2P | server_sap);
658    evt_data.activated.local_link_miu = nfa_p2p_cb.local_link_miu;
659    evt_data.activated.remote_link_miu = nfa_p2p_cb.remote_link_miu;
660
661    /* notify NFA_P2P_ACTIVATED_EVT to server */
662    nfa_p2p_cb.sap_cb[server_sap].p_cback(NFA_P2P_ACTIVATED_EVT, &evt_data);
663  }
664
665  return true;
666}
667
668/*******************************************************************************
669**
670** Function         nfa_p2p_reg_client
671**
672** Description      Allocate a service as client and register to LLCP
673**
674**
675** Returns          TRUE to deallocate buffer
676**
677*******************************************************************************/
678bool nfa_p2p_reg_client(tNFA_P2P_MSG* p_msg) {
679  tNFA_P2P_EVT_DATA evt_data;
680  uint8_t local_sap;
681
682  P2P_TRACE_DEBUG0("nfa_p2p_reg_client ()");
683
684  local_sap =
685      LLCP_RegisterClient(p_msg->api_reg_client.link_type, nfa_p2p_llcp_cback);
686
687  if (local_sap == LLCP_INVALID_SAP) {
688    evt_data.reg_client.client_handle = NFA_HANDLE_INVALID;
689    p_msg->api_reg_client.p_cback(NFA_P2P_REG_CLIENT_EVT, &evt_data);
690    return true;
691  }
692
693  nfa_p2p_cb.sap_cb[local_sap].p_cback = p_msg->api_reg_client.p_cback;
694  nfa_p2p_cb.sap_cb[local_sap].flags = NFA_P2P_SAP_FLAG_CLIENT;
695
696  evt_data.reg_client.client_handle = (NFA_HANDLE_GROUP_P2P | local_sap);
697  nfa_p2p_cb.sap_cb[local_sap].p_cback(NFA_P2P_REG_CLIENT_EVT, &evt_data);
698
699  /* if LLCP is already activated */
700  if (nfa_p2p_cb.llcp_state == NFA_P2P_LLCP_STATE_ACTIVATED) {
701    evt_data.activated.handle = (NFA_HANDLE_GROUP_P2P | local_sap);
702    evt_data.activated.local_link_miu = nfa_p2p_cb.local_link_miu;
703    evt_data.activated.remote_link_miu = nfa_p2p_cb.remote_link_miu;
704
705    /* notify NFA_P2P_ACTIVATED_EVT to client */
706    nfa_p2p_cb.sap_cb[local_sap].p_cback(NFA_P2P_ACTIVATED_EVT, &evt_data);
707  }
708
709  return true;
710}
711
712/*******************************************************************************
713**
714** Function         nfa_p2p_dereg
715**
716** Description      Deallocate a service as server or client and deregister to
717**                  LLCP. LLCP will deallocate data link connection created by
718**                  this server
719**
720** Returns          TRUE to deallocate buffer
721**
722*******************************************************************************/
723bool nfa_p2p_dereg(tNFA_P2P_MSG* p_msg) {
724  uint8_t local_sap, xx;
725
726  P2P_TRACE_DEBUG0("nfa_p2p_dereg ()");
727
728  local_sap = (uint8_t)(p_msg->api_dereg.handle & NFA_HANDLE_MASK);
729
730  if (nfa_p2p_cb.sap_cb[local_sap].p_cback) {
731    for (xx = 0; xx < LLCP_MAX_DATA_LINK; xx++) {
732      if ((nfa_p2p_cb.conn_cb[xx].flags & NFA_P2P_CONN_FLAG_IN_USE) &&
733          (nfa_p2p_cb.conn_cb[xx].local_sap == local_sap)) {
734        nfa_p2p_deallocate_conn_cb(xx);
735      }
736    }
737  }
738
739  LLCP_Deregister(local_sap);
740  nfa_p2p_cb.sap_cb[local_sap].p_cback = NULL;
741
742  if (nfa_p2p_cb.is_p2p_listening) {
743    /* check if this is the last server on NFA P2P */
744    for (xx = 0; xx < NFA_P2P_NUM_SAP; xx++) {
745      if ((nfa_p2p_cb.sap_cb[xx].p_cback) &&
746          (nfa_p2p_cb.sap_cb[xx].flags & NFA_P2P_SAP_FLAG_SERVER)) {
747        break;
748      }
749    }
750
751    if (xx >= NFA_P2P_NUM_SAP) {
752      /* if need to update WKS in LLCP Gen bytes */
753      if (local_sap <= LLCP_UPPER_BOUND_WK_SAP)
754        nfa_p2p_disable_listening(NFA_ID_P2P, true);
755      else
756        nfa_p2p_disable_listening(NFA_ID_P2P, false);
757    }
758    /* if need to update WKS in LLCP Gen bytes */
759    else if (local_sap <= LLCP_UPPER_BOUND_WK_SAP) {
760      nfa_p2p_enable_listening(NFA_ID_P2P, true);
761    }
762  }
763
764  return true;
765}
766
767/*******************************************************************************
768**
769** Function         nfa_p2p_accept_connection
770**
771** Description      Connection Confirm from local application
772**
773**
774** Returns          TRUE to deallocate buffer
775**
776*******************************************************************************/
777bool nfa_p2p_accept_connection(tNFA_P2P_MSG* p_msg) {
778  uint8_t xx;
779  tLLCP_CONNECTION_PARAMS params;
780
781  P2P_TRACE_DEBUG0("nfa_p2p_accept_connection ()");
782
783  xx = (uint8_t)(p_msg->api_accept.conn_handle & NFA_HANDLE_MASK);
784  xx &= ~NFA_P2P_HANDLE_FLAG_CONN;
785
786  params.miu = p_msg->api_accept.miu;
787  params.rw = p_msg->api_accept.rw;
788  params.sn[0] = 0;
789
790  LLCP_ConnectCfm(nfa_p2p_cb.conn_cb[xx].local_sap,
791                  nfa_p2p_cb.conn_cb[xx].remote_sap, &params);
792
793  return true;
794}
795
796/*******************************************************************************
797**
798** Function         nfa_p2p_reject_connection
799**
800** Description      Reject connection by local application
801**
802**
803** Returns          TRUE to deallocate buffer
804**
805*******************************************************************************/
806bool nfa_p2p_reject_connection(tNFA_P2P_MSG* p_msg) {
807  uint8_t xx;
808
809  P2P_TRACE_DEBUG0("nfa_p2p_reject_connection ()");
810
811  xx = (uint8_t)(p_msg->api_reject.conn_handle & NFA_HANDLE_MASK);
812  xx &= ~NFA_P2P_HANDLE_FLAG_CONN;
813
814  LLCP_ConnectReject(nfa_p2p_cb.conn_cb[xx].local_sap,
815                     nfa_p2p_cb.conn_cb[xx].remote_sap,
816                     LLCP_SAP_DM_REASON_APP_REJECTED);
817
818  /* no need to deregister service on LLCP */
819  nfa_p2p_deallocate_conn_cb(xx);
820
821  return true;
822}
823
824/*******************************************************************************
825**
826** Function         nfa_p2p_disconnect
827**
828** Description      Disconnect data link connection by local application
829**
830**
831** Returns          TRUE to deallocate buffer
832**
833*******************************************************************************/
834bool nfa_p2p_disconnect(tNFA_P2P_MSG* p_msg) {
835  uint8_t local_sap, xx;
836  tLLCP_STATUS status;
837  tNFA_P2P_EVT_DATA evt_data;
838
839  P2P_TRACE_DEBUG0("nfa_p2p_disconnect ()");
840
841  xx = (uint8_t)(p_msg->api_disconnect.conn_handle & NFA_HANDLE_MASK);
842
843  /* if this is for data link connection */
844  if (xx & NFA_P2P_HANDLE_FLAG_CONN) {
845    xx &= ~NFA_P2P_HANDLE_FLAG_CONN;
846
847    status = LLCP_DisconnectReq(nfa_p2p_cb.conn_cb[xx].local_sap,
848                                nfa_p2p_cb.conn_cb[xx].remote_sap,
849                                p_msg->api_disconnect.flush);
850
851    if (status == LLCP_STATUS_SUCCESS) {
852      /* wait for disconnect response if successful */
853      return true;
854    } else {
855      /*
856      ** while we are waiting for connect confirm,
857      ** we cannot sent DISC because we don't know DSAP yet
858      */
859      local_sap = nfa_p2p_cb.conn_cb[xx].local_sap;
860
861      if (nfa_p2p_cb.sap_cb[local_sap].p_cback) {
862        evt_data.disc.handle =
863            (NFA_HANDLE_GROUP_P2P | NFA_P2P_HANDLE_FLAG_CONN | xx);
864        evt_data.disc.reason = NFA_P2P_DISC_REASON_LOCAL_INITITATE;
865
866        nfa_p2p_deallocate_conn_cb(xx);
867        nfa_p2p_cb.sap_cb[local_sap].p_cback(NFA_P2P_DISC_EVT, &evt_data);
868      }
869    }
870  } else {
871    P2P_TRACE_ERROR0("Handle is not for Data link connection");
872  }
873
874  return true;
875}
876
877/*******************************************************************************
878**
879** Function         nfa_p2p_create_data_link_connection
880**
881** Description      Create data link connection
882**
883**
884** Returns          TRUE to deallocate buffer
885**
886*******************************************************************************/
887bool nfa_p2p_create_data_link_connection(tNFA_P2P_MSG* p_msg) {
888  uint8_t local_sap;
889  tNFA_P2P_EVT_DATA evt_data;
890  tLLCP_CONNECTION_PARAMS conn_params;
891  tLLCP_STATUS status;
892
893  P2P_TRACE_DEBUG0("nfa_p2p_create_data_link_connection ()");
894
895  local_sap = (uint8_t)(p_msg->api_connect.client_handle & NFA_HANDLE_MASK);
896
897  conn_params.miu = p_msg->api_connect.miu;
898  conn_params.rw = p_msg->api_connect.rw;
899
900  /* NFA_P2pConnectBySap () */
901  if (p_msg->api_connect.dsap != LLCP_INVALID_SAP) {
902    conn_params.sn[0] = 0;
903    status = LLCP_ConnectReq(local_sap, p_msg->api_connect.dsap, &conn_params);
904  }
905  /* NFA_P2pConnectByName () */
906  else {
907    strncpy(conn_params.sn, p_msg->api_connect.service_name, LLCP_MAX_SN_LEN);
908    conn_params.sn[LLCP_MAX_SN_LEN] = 0;
909
910    status = LLCP_ConnectReq(local_sap, LLCP_SAP_SDP, &conn_params);
911  }
912
913  if (status != LLCP_STATUS_SUCCESS) {
914    evt_data.disc.handle = (NFA_HANDLE_GROUP_P2P | local_sap);
915    evt_data.disc.reason = NFA_P2P_DISC_REASON_NO_INFORMATION;
916
917    nfa_p2p_cb.sap_cb[local_sap].p_cback(NFA_P2P_DISC_EVT, &evt_data);
918  }
919
920  return true;
921}
922
923/*******************************************************************************
924**
925** Function         nfa_p2p_send_ui
926**
927** Description      Send UI PDU
928**
929**
930** Returns          TRUE to deallocate buffer
931**
932*******************************************************************************/
933bool nfa_p2p_send_ui(tNFA_P2P_MSG* p_msg) {
934  uint8_t local_sap;
935  tLLCP_STATUS status;
936  tNFA_P2P_EVT_DATA evt_data;
937
938  P2P_TRACE_DEBUG0("nfa_p2p_send_ui ()");
939
940  local_sap = (uint8_t)(p_msg->api_send_ui.handle & NFA_HANDLE_MASK);
941
942  /* decrease number of tx UI PDU which is not processed by NFA for congestion
943   * control */
944  if (nfa_p2p_cb.sap_cb[local_sap].num_pending_ui_pdu)
945    nfa_p2p_cb.sap_cb[local_sap].num_pending_ui_pdu--;
946
947  if (nfa_p2p_cb.total_pending_ui_pdu) nfa_p2p_cb.total_pending_ui_pdu--;
948
949  status =
950      LLCP_SendUI(local_sap, p_msg->api_send_ui.dsap, p_msg->api_send_ui.p_msg);
951
952  if (status == LLCP_STATUS_CONGESTED) {
953    if (!(nfa_p2p_cb.sap_cb[local_sap].flags &
954          NFA_P2P_SAP_FLAG_LLINK_CONGESTED)) {
955      nfa_p2p_cb.sap_cb[local_sap].flags |= NFA_P2P_SAP_FLAG_LLINK_CONGESTED;
956
957      /* notify that this logical link is congested */
958      evt_data.congest.link_type = NFA_P2P_LLINK_TYPE;
959      evt_data.congest.handle = (NFA_HANDLE_GROUP_P2P | local_sap);
960      evt_data.congest.is_congested = true;
961
962      nfa_p2p_cb.sap_cb[local_sap].p_cback(NFA_P2P_CONGEST_EVT, &evt_data);
963    }
964  }
965
966  return true;
967}
968
969/*******************************************************************************
970**
971** Function         nfa_p2p_send_data
972**
973** Description      Send I PDU
974**
975**
976** Returns          TRUE to deallocate buffer
977**
978*******************************************************************************/
979bool nfa_p2p_send_data(tNFA_P2P_MSG* p_msg) {
980  tNFA_P2P_EVT_DATA evt_data;
981  tLLCP_STATUS status;
982  uint8_t xx;
983
984  P2P_TRACE_DEBUG0("nfa_p2p_send_data ()");
985
986  xx = (uint8_t)(p_msg->api_send_data.conn_handle & NFA_HANDLE_MASK);
987  xx &= ~NFA_P2P_HANDLE_FLAG_CONN;
988
989  /* decrease number of tx I PDU which is not processed by NFA for congestion
990   * control */
991  if (nfa_p2p_cb.conn_cb[xx].num_pending_i_pdu)
992    nfa_p2p_cb.conn_cb[xx].num_pending_i_pdu--;
993
994  if (nfa_p2p_cb.total_pending_i_pdu) nfa_p2p_cb.total_pending_i_pdu--;
995
996  status = LLCP_SendData(nfa_p2p_cb.conn_cb[xx].local_sap,
997                         nfa_p2p_cb.conn_cb[xx].remote_sap,
998                         p_msg->api_send_data.p_msg);
999
1000  if (status == LLCP_STATUS_CONGESTED) {
1001    if (!(nfa_p2p_cb.conn_cb[xx].flags & NFA_P2P_CONN_FLAG_CONGESTED)) {
1002      nfa_p2p_cb.conn_cb[xx].flags |= NFA_P2P_CONN_FLAG_CONGESTED;
1003
1004      /* notify that this data link is congested */
1005      evt_data.congest.link_type = NFA_P2P_DLINK_TYPE;
1006      evt_data.congest.handle =
1007          (NFA_HANDLE_GROUP_P2P | NFA_P2P_HANDLE_FLAG_CONN | xx);
1008      evt_data.congest.is_congested = true;
1009
1010      nfa_p2p_cb.sap_cb[nfa_p2p_cb.conn_cb[xx].local_sap].p_cback(
1011          NFA_P2P_CONGEST_EVT, &evt_data);
1012    }
1013  }
1014
1015  return true;
1016}
1017
1018/*******************************************************************************
1019**
1020** Function         nfa_p2p_set_local_busy
1021**
1022** Description      Set or reset local busy
1023**
1024**
1025** Returns          TRUE to deallocate buffer
1026**
1027*******************************************************************************/
1028bool nfa_p2p_set_local_busy(tNFA_P2P_MSG* p_msg) {
1029  uint8_t xx;
1030
1031  P2P_TRACE_DEBUG0("nfa_p2p_set_local_busy ()");
1032
1033  xx = (uint8_t)(p_msg->api_local_busy.conn_handle & NFA_HANDLE_MASK);
1034  xx &= ~NFA_P2P_HANDLE_FLAG_CONN;
1035
1036  LLCP_SetLocalBusyStatus(nfa_p2p_cb.conn_cb[xx].local_sap,
1037                          nfa_p2p_cb.conn_cb[xx].remote_sap,
1038                          p_msg->api_local_busy.is_busy);
1039
1040  return true;
1041}
1042
1043/*******************************************************************************
1044**
1045** Function         nfa_p2p_get_link_info
1046**
1047** Description      Get WKS of remote and link MIU
1048**
1049**
1050** Returns          TRUE to deallocate buffer
1051**
1052*******************************************************************************/
1053bool nfa_p2p_get_link_info(tNFA_P2P_MSG* p_msg) {
1054  tNFA_P2P_EVT_DATA evt_data;
1055  uint8_t local_sap;
1056
1057  P2P_TRACE_DEBUG0("nfa_p2p_get_link_info ()");
1058
1059  evt_data.link_info.handle = p_msg->api_link_info.handle;
1060  evt_data.link_info.wks = LLCP_GetRemoteWKS();
1061  evt_data.link_info.local_link_miu = nfa_p2p_cb.local_link_miu;
1062  evt_data.link_info.remote_link_miu = nfa_p2p_cb.remote_link_miu;
1063
1064  local_sap = (uint8_t)(p_msg->api_link_info.handle & NFA_HANDLE_MASK);
1065  nfa_p2p_cb.sap_cb[local_sap].p_cback(NFA_P2P_LINK_INFO_EVT, &evt_data);
1066
1067  return true;
1068}
1069
1070/*******************************************************************************
1071**
1072** Function         nfa_p2p_get_remote_sap
1073**
1074** Description      Get remote SAP
1075**
1076**
1077** Returns          TRUE to deallocate buffer
1078**
1079*******************************************************************************/
1080bool nfa_p2p_get_remote_sap(tNFA_P2P_MSG* p_msg) {
1081  tNFA_P2P_EVT_DATA evt_data;
1082  uint8_t local_sap;
1083
1084  P2P_TRACE_DEBUG0("nfa_p2p_get_remote_sap ()");
1085
1086  local_sap = (uint8_t)(p_msg->api_remote_sap.handle & NFA_HANDLE_MASK);
1087
1088  if (!nfa_p2p_start_sdp(p_msg->api_remote_sap.service_name, local_sap)) {
1089    evt_data.sdp.handle = p_msg->api_remote_sap.handle;
1090    evt_data.sdp.remote_sap = 0x00;
1091    nfa_p2p_cb.sap_cb[local_sap].p_cback(NFA_P2P_SDP_EVT, &evt_data);
1092  }
1093
1094  return true;
1095}
1096
1097/*******************************************************************************
1098**
1099** Function         nfa_p2p_set_llcp_cfg
1100**
1101** Description      Set LLCP configuration
1102**
1103**
1104** Returns          TRUE to deallocate buffer
1105**
1106*******************************************************************************/
1107bool nfa_p2p_set_llcp_cfg(tNFA_P2P_MSG* p_msg) {
1108  LLCP_SetConfig(p_msg->api_set_llcp_cfg.link_miu, p_msg->api_set_llcp_cfg.opt,
1109                 p_msg->api_set_llcp_cfg.wt,
1110                 p_msg->api_set_llcp_cfg.link_timeout,
1111                 p_msg->api_set_llcp_cfg.inact_timeout_init,
1112                 p_msg->api_set_llcp_cfg.inact_timeout_target,
1113                 p_msg->api_set_llcp_cfg.symm_delay,
1114                 p_msg->api_set_llcp_cfg.data_link_timeout,
1115                 p_msg->api_set_llcp_cfg.delay_first_pdu_timeout);
1116
1117  return true;
1118}
1119
1120/*******************************************************************************
1121**
1122** Function         nfa_p2p_restart_rf_discovery
1123**
1124** Description      Restart RF discovery by deactivating to IDLE
1125**
1126**
1127** Returns          TRUE to deallocate buffer
1128**
1129*******************************************************************************/
1130bool nfa_p2p_restart_rf_discovery(tNFA_P2P_MSG* p_msg) {
1131  P2P_TRACE_DEBUG0("nfa_p2p_restart_rf_discovery ()");
1132
1133  nfa_dm_rf_deactivate(NFA_DEACTIVATE_TYPE_IDLE);
1134
1135  return true;
1136}
1137