llcp_api.cc revision 7dab0e579144a72612d29a4b1548e4d60a7d0ebd
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 file contains the LLCP API code
22 *
23 ******************************************************************************/
24
25#include "llcp_api.h"
26#include <string.h>
27#include <string>
28#include "bt_types.h"
29#include "gki.h"
30#include "llcp_defs.h"
31#include "llcp_int.h"
32#include "nfc_target.h"
33
34#if (LLCP_TEST_INCLUDED == TRUE) /* this is for LLCP testing */
35
36tLLCP_TEST_PARAMS llcp_test_params = {
37    LLCP_VERSION_VALUE, 0, /* not override */
38};
39
40/*******************************************************************************
41**
42** Function         LLCP_SetTestParams
43**
44** Description      Set test parameters for LLCP
45**
46**
47** Returns          void
48**
49*******************************************************************************/
50void LLCP_SetTestParams(uint8_t version, uint16_t wks) {
51  LLCP_TRACE_API2("LLCP_SetTestParams () version:0x%02X, wks:0x%04X", version,
52                  wks);
53
54  if (version != 0xFF) llcp_test_params.version = version;
55
56  if (wks != 0xFFFF) llcp_test_params.wks = wks;
57}
58#endif
59
60/*******************************************************************************
61**
62** Function         LLCP_RegisterDtaCback
63**
64** Description      Register callback function for LLCP DTA testing
65**
66**
67** Returns          void
68**
69*******************************************************************************/
70void LLCP_RegisterDtaCback(tLLCP_DTA_CBACK* p_dta_cback) {
71  LLCP_TRACE_API1("%s", __func__);
72
73  llcp_cb.p_dta_cback = p_dta_cback;
74}
75
76/*******************************************************************************
77**
78** Function         LLCP_SetConfig
79**
80** Description      Set configuration parameters for LLCP
81**                  - Local Link MIU
82**                  - Option parameter
83**                  - Response Waiting Time Index
84**                  - Local Link Timeout
85**                  - Inactivity Timeout as initiator role
86**                  - Inactivity Timeout as target role
87**                  - Delay SYMM response
88**                  - Data link connection timeout
89**                  - Delay timeout to send first PDU as initiator
90**
91** Returns          void
92**
93*******************************************************************************/
94void LLCP_SetConfig(uint16_t link_miu, uint8_t opt, uint8_t wt,
95                    uint16_t link_timeout, uint16_t inact_timeout_init,
96                    uint16_t inact_timeout_target, uint16_t symm_delay,
97                    uint16_t data_link_timeout,
98                    uint16_t delay_first_pdu_timeout) {
99  LLCP_TRACE_API4(
100      "LLCP_SetConfig () link_miu:%d, opt:0x%02X, wt:%d, link_timeout:%d",
101      link_miu, opt, wt, link_timeout);
102  LLCP_TRACE_API4(
103      "                 inact_timeout (init:%d,target:%d), symm_delay:%d, "
104      "data_link_timeout:%d",
105      inact_timeout_init, inact_timeout_target, symm_delay, data_link_timeout);
106  LLCP_TRACE_API1("                 delay_first_pdu_timeout:%d",
107                  delay_first_pdu_timeout);
108
109  if (link_miu < LLCP_DEFAULT_MIU) {
110    LLCP_TRACE_ERROR1(
111        "LLCP_SetConfig (): link_miu shall not be smaller than "
112        "LLCP_DEFAULT_MIU (%d)",
113        LLCP_DEFAULT_MIU);
114    link_miu = LLCP_DEFAULT_MIU;
115  } else if (link_miu > LLCP_MAX_MIU) {
116    LLCP_TRACE_ERROR1(
117        "LLCP_SetConfig (): link_miu shall not be bigger than LLCP_MAX_MIU "
118        "(%d)",
119        LLCP_MAX_MIU);
120    link_miu = LLCP_MAX_MIU;
121  }
122
123  /* if Link MIU is bigger than GKI buffer */
124  if (link_miu > LLCP_MIU) {
125    LLCP_TRACE_ERROR1(
126        "LLCP_SetConfig (): link_miu shall not be bigger than LLCP_MIU (%d)",
127        LLCP_MIU);
128    llcp_cb.lcb.local_link_miu = LLCP_MIU;
129  } else
130    llcp_cb.lcb.local_link_miu = link_miu;
131
132  llcp_cb.lcb.local_opt = opt;
133  llcp_cb.lcb.local_wt = wt;
134
135  if (link_timeout < LLCP_LTO_UNIT) {
136    LLCP_TRACE_ERROR1(
137        "LLCP_SetConfig (): link_timeout shall not be smaller than "
138        "LLCP_LTO_UNIT (%d ms)",
139        LLCP_LTO_UNIT);
140    llcp_cb.lcb.local_lto = LLCP_DEFAULT_LTO_IN_MS;
141  } else if (link_timeout > LLCP_MAX_LTO_IN_MS) {
142    LLCP_TRACE_ERROR1(
143        "LLCP_SetConfig (): link_timeout shall not be bigger than "
144        "LLCP_MAX_LTO_IN_MS (%d ms)",
145        LLCP_MAX_LTO_IN_MS);
146    llcp_cb.lcb.local_lto = LLCP_MAX_LTO_IN_MS;
147  } else
148    llcp_cb.lcb.local_lto = link_timeout;
149
150  llcp_cb.lcb.inact_timeout_init = inact_timeout_init;
151  llcp_cb.lcb.inact_timeout_target = inact_timeout_target;
152  llcp_cb.lcb.symm_delay = symm_delay;
153  llcp_cb.lcb.data_link_timeout = data_link_timeout;
154  llcp_cb.lcb.delay_first_pdu_timeout = delay_first_pdu_timeout;
155}
156
157/*******************************************************************************
158**
159** Function         LLCP_GetConfig
160**
161** Description      Get configuration parameters for LLCP
162**                  - Local Link MIU
163**                  - Option parameter
164**                  - Response Waiting Time Index
165**                  - Local Link Timeout
166**                  - Inactivity Timeout as initiator role
167**                  - Inactivity Timeout as target role
168**                  - Delay SYMM response
169**                  - Data link connection timeout
170**                  - Delay timeout to send first PDU as initiator
171**
172** Returns          void
173**
174*******************************************************************************/
175void LLCP_GetConfig(uint16_t* p_link_miu, uint8_t* p_opt, uint8_t* p_wt,
176                    uint16_t* p_link_timeout, uint16_t* p_inact_timeout_init,
177                    uint16_t* p_inact_timeout_target, uint16_t* p_symm_delay,
178                    uint16_t* p_data_link_timeout,
179                    uint16_t* p_delay_first_pdu_timeout) {
180  *p_link_miu = llcp_cb.lcb.local_link_miu;
181  *p_opt = llcp_cb.lcb.local_opt;
182  *p_wt = llcp_cb.lcb.local_wt;
183  *p_link_timeout = llcp_cb.lcb.local_lto;
184  *p_inact_timeout_init = llcp_cb.lcb.inact_timeout_init;
185  *p_inact_timeout_target = llcp_cb.lcb.inact_timeout_target;
186  *p_symm_delay = llcp_cb.lcb.symm_delay;
187  *p_data_link_timeout = llcp_cb.lcb.data_link_timeout;
188  *p_delay_first_pdu_timeout = llcp_cb.lcb.delay_first_pdu_timeout;
189
190  LLCP_TRACE_API4(
191      "LLCP_GetConfig () link_miu:%d, opt:0x%02X, wt:%d, link_timeout:%d",
192      *p_link_miu, *p_opt, *p_wt, *p_link_timeout);
193  LLCP_TRACE_API4(
194      "                 inact_timeout (init:%d, target:%d), symm_delay:%d, "
195      "data_link_timeout:%d",
196      *p_inact_timeout_init, *p_inact_timeout_target, *p_symm_delay,
197      *p_data_link_timeout);
198  LLCP_TRACE_API1("                 delay_first_pdu_timeout:%d",
199                  *p_delay_first_pdu_timeout);
200}
201
202/*******************************************************************************
203**
204** Function         LLCP_GetDiscoveryConfig
205**
206** Description      Returns discovery config for ISO 18092 MAC link activation
207**                  This function is called to get general bytes for
208**                  NFC_PMID_ATR_REQ_GEN_BYTES or NFC_PMID_ATR_RES_GEN_BYTES
209**                  before starting discovery.
210**
211**                  wt:Waiting time 0 - 8, only for listen
212**                  p_gen_bytes: pointer to store LLCP magic number and
213**                               paramters
214**                  p_gen_bytes_len: length of buffer for gen bytes as input
215**                                   (NOTE:it must be bigger than
216**                                   LLCP_MIN_GEN_BYTES) actual gen bytes size
217**                                   as output
218**
219**                  Restrictions on the use of ISO 18092
220**                  1. The DID features shall not be used.
221**                  2. the NAD features shall not be used.
222**                  3. Frame waiting time extentions (WTX) shall not be used.
223**
224** Returns          None
225**
226*******************************************************************************/
227void LLCP_GetDiscoveryConfig(uint8_t* p_wt, uint8_t* p_gen_bytes,
228                             uint8_t* p_gen_bytes_len) {
229  uint8_t* p = p_gen_bytes;
230
231  LLCP_TRACE_API0("LLCP_GetDiscoveryConfig ()");
232
233  if (*p_gen_bytes_len < LLCP_MIN_GEN_BYTES) {
234    LLCP_TRACE_ERROR1(
235        "LLCP_GetDiscoveryConfig (): GenBytes length shall not be smaller than "
236        "LLCP_MIN_GEN_BYTES (%d)",
237        LLCP_MIN_GEN_BYTES);
238    *p_gen_bytes_len = 0;
239    return;
240  }
241
242  *p_wt = llcp_cb.lcb.local_wt;
243
244  UINT8_TO_BE_STREAM(p, LLCP_MAGIC_NUMBER_BYTE0);
245  UINT8_TO_BE_STREAM(p, LLCP_MAGIC_NUMBER_BYTE1);
246  UINT8_TO_BE_STREAM(p, LLCP_MAGIC_NUMBER_BYTE2);
247
248#if (LLCP_TEST_INCLUDED == TRUE) /* this is for LLCP testing */
249  UINT8_TO_BE_STREAM(p, LLCP_VERSION_TYPE);
250  UINT8_TO_BE_STREAM(p, LLCP_VERSION_LEN);
251  UINT8_TO_BE_STREAM(p, llcp_test_params.version);
252
253  UINT8_TO_BE_STREAM(p, LLCP_MIUX_TYPE);
254  UINT8_TO_BE_STREAM(p, LLCP_MIUX_LEN);
255  UINT16_TO_BE_STREAM(p, (llcp_cb.lcb.local_link_miu - LLCP_DEFAULT_MIU));
256
257  UINT8_TO_BE_STREAM(p, LLCP_WKS_TYPE);
258  UINT8_TO_BE_STREAM(p, LLCP_WKS_LEN);
259  if (llcp_test_params.wks == 0) /* not override */
260  {
261    UINT16_TO_BE_STREAM(p, llcp_cb.lcb.wks);
262  } else {
263    UINT16_TO_BE_STREAM(p, llcp_test_params.wks);
264  }
265#else
266  UINT8_TO_BE_STREAM(p, LLCP_VERSION_TYPE);
267  UINT8_TO_BE_STREAM(p, LLCP_VERSION_LEN);
268  UINT8_TO_BE_STREAM(p, LLCP_VERSION_VALUE);
269
270  UINT8_TO_BE_STREAM(p, LLCP_MIUX_TYPE);
271  UINT8_TO_BE_STREAM(p, LLCP_MIUX_LEN);
272  UINT16_TO_BE_STREAM(p, (llcp_cb.lcb.local_link_miu - LLCP_DEFAULT_MIU));
273
274  UINT8_TO_BE_STREAM(p, LLCP_WKS_TYPE);
275  UINT8_TO_BE_STREAM(p, LLCP_WKS_LEN);
276  UINT16_TO_BE_STREAM(p, llcp_cb.lcb.wks);
277#endif
278
279  UINT8_TO_BE_STREAM(p, LLCP_LTO_TYPE);
280  UINT8_TO_BE_STREAM(p, LLCP_LTO_LEN);
281  UINT8_TO_BE_STREAM(p, (llcp_cb.lcb.local_lto / LLCP_LTO_UNIT));
282
283  UINT8_TO_BE_STREAM(p, LLCP_OPT_TYPE);
284  UINT8_TO_BE_STREAM(p, LLCP_OPT_LEN);
285  UINT8_TO_BE_STREAM(p, llcp_cb.lcb.local_opt);
286
287  *p_gen_bytes_len = (uint8_t)(p - p_gen_bytes);
288}
289
290/*******************************************************************************
291**
292** Function         LLCP_ActivateLink
293**
294** Description      This function will activate LLCP link with LR, WT and Gen
295**                  Bytes in activation NTF from NFCC.
296**
297**                  LLCP_LINK_ACTIVATION_COMPLETE_EVT will be returned through
298**                  callback function if successful.
299**                  Otherwise, LLCP_LINK_ACTIVATION_FAILED_EVT will be returned.
300**
301** Returns          LLCP_STATUS_SUCCESS if success
302**
303*******************************************************************************/
304tLLCP_STATUS LLCP_ActivateLink(tLLCP_ACTIVATE_CONFIG config,
305                               tLLCP_LINK_CBACK* p_link_cback) {
306  LLCP_TRACE_API1("LLCP_ActivateLink () link_state = %d",
307                  llcp_cb.lcb.link_state);
308
309  if ((llcp_cb.lcb.link_state == LLCP_LINK_STATE_DEACTIVATED) &&
310      (p_link_cback)) {
311    llcp_cb.lcb.p_link_cback = p_link_cback;
312    return (llcp_link_activate(&config));
313  } else
314    return LLCP_STATUS_FAIL;
315}
316
317/*******************************************************************************
318**
319** Function         LLCP_DeactivateLink
320**
321** Description      Deactivate LLCP link
322**
323**                  LLCP_LINK_DEACTIVATED_EVT will be returned through callback
324**                  when LLCP link is deactivated. Then NFC link may be
325**                  deactivated.
326**
327** Returns          LLCP_STATUS_SUCCESS if success
328**
329*******************************************************************************/
330tLLCP_STATUS LLCP_DeactivateLink(void) {
331  LLCP_TRACE_API1("LLCP_DeactivateLink () link_state = %d",
332                  llcp_cb.lcb.link_state);
333
334  if (llcp_cb.lcb.link_state != LLCP_LINK_STATE_DEACTIVATED) {
335    llcp_link_deactivate(LLCP_LINK_LOCAL_INITIATED);
336    return LLCP_STATUS_SUCCESS;
337  } else
338    return LLCP_STATUS_FAIL;
339}
340
341/*******************************************************************************
342**
343** Function         LLCP_RegisterServer
344**
345** Description      Register server and callback function
346**
347**                  reg_sap : Well-Known SAP except LM and SDP (0x02 - 0x0F)
348**                            Advertized by SDP (0x10 - 0x1F)
349**                            LLCP_INVALID_SAP, LLCP will allocate between 0x10
350**                            and 0x1F
351**                  link_type : LLCP_LINK_TYPE_LOGICAL_DATA_LINK
352**                              and/or LLCP_LINK_TYPE_DATA_LINK_CONNECTION
353**                  p_service_name : Null-terminated string up to
354**                                   LLCP_MAX_SN_LEN
355**
356** Returns          SAP between 0x02 and 0x1F, if success
357**                  LLCP_INVALID_SAP, otherwise
358**
359*******************************************************************************/
360uint8_t LLCP_RegisterServer(uint8_t reg_sap, uint8_t link_type,
361                            std::string p_service_name,
362                            tLLCP_APP_CBACK* p_app_cback) {
363  uint8_t sap;
364  uint16_t length;
365  tLLCP_APP_CB* p_app_cb = {
366      0,
367  };
368
369  LLCP_TRACE_API3(
370      "LLCP_RegisterServer (): SAP:0x%x, link_type:0x%x, ServiceName:<%s>",
371      reg_sap, link_type,
372      ((p_service_name.empty()) ? "" : p_service_name.c_str()));
373
374  if (!p_app_cback) {
375    LLCP_TRACE_ERROR0("LLCP_RegisterServer (): Callback must be provided");
376    return LLCP_INVALID_SAP;
377  } else if (((link_type & LLCP_LINK_TYPE_LOGICAL_DATA_LINK) == 0x00) &&
378             ((link_type & LLCP_LINK_TYPE_DATA_LINK_CONNECTION) == 0x00)) {
379    LLCP_TRACE_ERROR1(
380        "LLCP_RegisterServer (): link type (0x%x) must be specified",
381        link_type);
382    return LLCP_INVALID_SAP;
383  }
384
385  if (reg_sap == LLCP_INVALID_SAP) {
386    /* allocate a SAP between 0x10 and 0x1F */
387    for (sap = 0; sap < LLCP_MAX_SERVER; sap++) {
388      if (llcp_cb.server_cb[sap].p_app_cback == NULL) {
389        p_app_cb = &llcp_cb.server_cb[sap];
390        reg_sap = LLCP_LOWER_BOUND_SDP_SAP + sap;
391        break;
392      }
393    }
394
395    if (reg_sap == LLCP_INVALID_SAP) {
396      LLCP_TRACE_ERROR0("LLCP_RegisterServer (): out of resource");
397      return LLCP_INVALID_SAP;
398    }
399  } else if (reg_sap == LLCP_SAP_LM) {
400    LLCP_TRACE_ERROR1("LLCP_RegisterServer (): SAP (0x%x) is for link manager",
401                      reg_sap);
402    return LLCP_INVALID_SAP;
403  } else if (reg_sap <= LLCP_UPPER_BOUND_WK_SAP) {
404    if (reg_sap >= LLCP_MAX_WKS) {
405      LLCP_TRACE_ERROR1(
406          "LLCP_RegisterServer (): out of resource for SAP (0x%x)", reg_sap);
407      return LLCP_INVALID_SAP;
408    } else if (llcp_cb.wks_cb[reg_sap].p_app_cback) {
409      LLCP_TRACE_ERROR1(
410          "LLCP_RegisterServer (): SAP (0x%x) is already registered", reg_sap);
411      return LLCP_INVALID_SAP;
412    } else {
413      p_app_cb = &llcp_cb.wks_cb[reg_sap];
414    }
415  } else if (reg_sap <= LLCP_UPPER_BOUND_SDP_SAP) {
416    if (reg_sap - LLCP_LOWER_BOUND_SDP_SAP >= LLCP_MAX_SERVER) {
417      LLCP_TRACE_ERROR1(
418          "LLCP_RegisterServer (): out of resource for SAP (0x%x)", reg_sap);
419      return LLCP_INVALID_SAP;
420    } else if (llcp_cb.server_cb[reg_sap - LLCP_LOWER_BOUND_SDP_SAP]
421                   .p_app_cback) {
422      LLCP_TRACE_ERROR1(
423          "LLCP_RegisterServer (): SAP (0x%x) is already registered", reg_sap);
424      return LLCP_INVALID_SAP;
425    } else {
426      p_app_cb = &llcp_cb.server_cb[reg_sap - LLCP_LOWER_BOUND_SDP_SAP];
427    }
428  } else if (reg_sap >= LLCP_LOWER_BOUND_LOCAL_SAP) {
429    LLCP_TRACE_ERROR2(
430        "LLCP_RegisterServer (): SAP (0x%x) must be less than 0x%x", reg_sap,
431        LLCP_LOWER_BOUND_LOCAL_SAP);
432    return LLCP_INVALID_SAP;
433  }
434
435  memset(p_app_cb, 0x00, sizeof(tLLCP_APP_CB));
436
437  if (!p_service_name.empty()) {
438    length = p_service_name.length();
439    if (length > LLCP_MAX_SN_LEN) {
440      LLCP_TRACE_ERROR1(
441          "LLCP_RegisterServer (): Service Name (%d bytes) is too long",
442          length);
443      return LLCP_INVALID_SAP;
444    }
445
446    p_app_cb->p_service_name = (char*)GKI_getbuf((uint16_t)(length + 1));
447    if (p_app_cb->p_service_name == NULL) {
448      LLCP_TRACE_ERROR0("LLCP_RegisterServer (): Out of resource");
449      return LLCP_INVALID_SAP;
450    }
451
452    strncpy(p_app_cb->p_service_name, p_service_name.c_str(), length + 1);
453    p_app_cb->p_service_name[length] = 0;
454  } else
455    p_app_cb->p_service_name = NULL;
456
457  p_app_cb->p_app_cback = p_app_cback;
458  p_app_cb->link_type = link_type;
459
460  if (reg_sap <= LLCP_UPPER_BOUND_WK_SAP) {
461    llcp_cb.lcb.wks |= (1 << reg_sap);
462  }
463
464  LLCP_TRACE_DEBUG1("LLCP_RegisterServer (): Registered SAP = 0x%02X", reg_sap);
465
466  if (link_type & LLCP_LINK_TYPE_LOGICAL_DATA_LINK) {
467    llcp_cb.num_logical_data_link++;
468    llcp_util_adjust_ll_congestion();
469  }
470
471  return reg_sap;
472}
473
474/*******************************************************************************
475**
476** Function         LLCP_RegisterClient
477**
478** Description      Register client and callback function
479**
480**                  link_type : LLCP_LINK_TYPE_LOGICAL_DATA_LINK
481**                              and/or LLCP_LINK_TYPE_DATA_LINK_CONNECTION
482**
483** Returns          SAP between 0x20 and 0x3F, if success
484**                  LLCP_INVALID_SAP, otherwise
485**
486*******************************************************************************/
487uint8_t LLCP_RegisterClient(uint8_t link_type, tLLCP_APP_CBACK* p_app_cback) {
488  uint8_t reg_sap = LLCP_INVALID_SAP;
489  uint8_t sap;
490  tLLCP_APP_CB* p_app_cb;
491
492  LLCP_TRACE_API1("LLCP_RegisterClient (): link_type = 0x%x", link_type);
493
494  if (!p_app_cback) {
495    LLCP_TRACE_ERROR0("LLCP_RegisterClient (): Callback must be provided");
496    return LLCP_INVALID_SAP;
497  } else if (((link_type & LLCP_LINK_TYPE_LOGICAL_DATA_LINK) == 0x00) &&
498             ((link_type & LLCP_LINK_TYPE_DATA_LINK_CONNECTION) == 0x00)) {
499    LLCP_TRACE_ERROR1(
500        "LLCP_RegisterClient (): link type (0x%x) must be specified",
501        link_type);
502    return LLCP_INVALID_SAP;
503  }
504
505  /* allocate a SAP between 0x20 and 0x3F */
506  for (sap = 0; sap < LLCP_MAX_CLIENT; sap++) {
507    if (llcp_cb.client_cb[sap].p_app_cback == NULL) {
508      p_app_cb = &llcp_cb.client_cb[sap];
509      memset(p_app_cb, 0x00, sizeof(tLLCP_APP_CB));
510      reg_sap = LLCP_LOWER_BOUND_LOCAL_SAP + sap;
511      break;
512    }
513  }
514
515  if (reg_sap == LLCP_INVALID_SAP) {
516    LLCP_TRACE_ERROR0("LLCP_RegisterClient (): out of resource");
517    return LLCP_INVALID_SAP;
518  }
519
520  p_app_cb->p_app_cback = p_app_cback;
521  p_app_cb->p_service_name = NULL;
522  p_app_cb->link_type = link_type;
523
524  LLCP_TRACE_DEBUG1("LLCP_RegisterClient (): Registered SAP = 0x%02X", reg_sap);
525
526  if (link_type & LLCP_LINK_TYPE_LOGICAL_DATA_LINK) {
527    llcp_cb.num_logical_data_link++;
528    llcp_util_adjust_ll_congestion();
529  }
530
531  return reg_sap;
532}
533
534/*******************************************************************************
535**
536** Function         LLCP_Deregister
537**
538** Description      Deregister server or client
539**
540**
541** Returns          LLCP_STATUS_SUCCESS if success
542**
543*******************************************************************************/
544tLLCP_STATUS LLCP_Deregister(uint8_t local_sap) {
545  uint8_t idx;
546  tLLCP_APP_CB* p_app_cb;
547
548  LLCP_TRACE_API1("LLCP_Deregister () SAP:0x%x", local_sap);
549
550  p_app_cb = llcp_util_get_app_cb(local_sap);
551
552  if ((!p_app_cb) || (p_app_cb->p_app_cback == NULL)) {
553    LLCP_TRACE_ERROR1("LLCP_Deregister (): SAP (0x%x) is not registered",
554                      local_sap);
555    return LLCP_STATUS_FAIL;
556  }
557
558  if (p_app_cb->p_service_name) GKI_freebuf(p_app_cb->p_service_name);
559
560  /* update WKS bit map */
561  if (local_sap <= LLCP_UPPER_BOUND_WK_SAP) {
562    llcp_cb.lcb.wks &= ~(1 << local_sap);
563  }
564
565  /* discard any received UI PDU on this SAP */
566  LLCP_FlushLogicalLinkRxData(local_sap);
567  llcp_cb.total_rx_ui_pdu = 0;
568
569  /* deallocate any data link connection on this SAP */
570  for (idx = 0; idx < LLCP_MAX_DATA_LINK; idx++) {
571    if ((llcp_cb.dlcb[idx].state != LLCP_DLC_STATE_IDLE) &&
572        (llcp_cb.dlcb[idx].local_sap == local_sap)) {
573      llcp_util_deallocate_data_link(&llcp_cb.dlcb[idx]);
574    }
575  }
576
577  p_app_cb->p_app_cback = NULL;
578
579  /* discard any pending tx UI PDU from this SAP */
580  while (p_app_cb->ui_xmit_q.p_first) {
581    GKI_freebuf(GKI_dequeue(&p_app_cb->ui_xmit_q));
582    llcp_cb.total_tx_ui_pdu--;
583  }
584
585  if (p_app_cb->link_type & LLCP_LINK_TYPE_LOGICAL_DATA_LINK) {
586    llcp_cb.num_logical_data_link--;
587    llcp_util_adjust_ll_congestion();
588  }
589
590  /* check rx congestion status */
591  llcp_util_check_rx_congested_status();
592
593  return LLCP_STATUS_SUCCESS;
594}
595
596/*******************************************************************************
597**
598** Function         LLCP_IsLogicalLinkCongested
599**
600** Description      Check if logical link is congested
601**
602**
603** Returns          TRUE if congested
604**
605*******************************************************************************/
606bool LLCP_IsLogicalLinkCongested(uint8_t local_sap, uint8_t num_pending_ui_pdu,
607                                 uint8_t total_pending_ui_pdu,
608                                 uint8_t total_pending_i_pdu) {
609  tLLCP_APP_CB* p_app_cb;
610
611  LLCP_TRACE_API4(
612      "LLCP_IsLogicalLinkCongested () Local SAP:0x%x, pending = (%d, %d, %d)",
613      local_sap, num_pending_ui_pdu, total_pending_ui_pdu, total_pending_i_pdu);
614
615  p_app_cb = llcp_util_get_app_cb(local_sap);
616
617  if ((llcp_cb.lcb.link_state != LLCP_LINK_STATE_ACTIVATED) ||
618      (p_app_cb == NULL) || (p_app_cb->p_app_cback == NULL) ||
619      ((p_app_cb->link_type & LLCP_LINK_TYPE_LOGICAL_DATA_LINK) == 0) ||
620      (p_app_cb->is_ui_tx_congested)) {
621    return true;
622  } else if ((num_pending_ui_pdu + p_app_cb->ui_xmit_q.count >=
623              llcp_cb.ll_tx_congest_start) ||
624             (total_pending_ui_pdu + llcp_cb.total_tx_ui_pdu >=
625              llcp_cb.max_num_ll_tx_buff) ||
626             (total_pending_ui_pdu + total_pending_i_pdu +
627                  llcp_cb.total_tx_ui_pdu + llcp_cb.total_tx_i_pdu >=
628              llcp_cb.max_num_tx_buff)) {
629    /* set flag so LLCP can notify uncongested status later */
630    p_app_cb->is_ui_tx_congested = true;
631
632    return true;
633  }
634  return false;
635}
636
637/*******************************************************************************
638**
639** Function         LLCP_SendUI
640**
641** Description      Send connnectionless data to DSAP
642**
643**
644** Returns          LLCP_STATUS_SUCCESS if success
645**                  LLCP_STATUS_CONGESTED if logical link is congested
646**                  LLCP_STATUS_FAIL, otherwise
647**
648*******************************************************************************/
649tLLCP_STATUS LLCP_SendUI(uint8_t ssap, uint8_t dsap, NFC_HDR* p_buf) {
650  tLLCP_STATUS status = LLCP_STATUS_FAIL;
651  tLLCP_APP_CB* p_app_cb;
652
653  LLCP_TRACE_API2("LLCP_SendUI () SSAP=0x%x, DSAP=0x%x", ssap, dsap);
654
655  p_app_cb = llcp_util_get_app_cb(ssap);
656
657  if ((p_app_cb == NULL) || (p_app_cb->p_app_cback == NULL)) {
658    LLCP_TRACE_ERROR1("LLCP_SendUI (): SSAP (0x%x) is not registered", ssap);
659  } else if ((p_app_cb->link_type & LLCP_LINK_TYPE_LOGICAL_DATA_LINK) == 0) {
660    LLCP_TRACE_ERROR1(
661        "LLCP_SendUI (): Logical link on SSAP (0x%x) is not enabled", ssap);
662  } else if (llcp_cb.lcb.link_state != LLCP_LINK_STATE_ACTIVATED) {
663    LLCP_TRACE_ERROR0("LLCP_SendUI (): LLCP link is not activated");
664  } else if ((llcp_cb.lcb.peer_opt == LLCP_LSC_UNKNOWN) ||
665             (llcp_cb.lcb.peer_opt & LLCP_LSC_1)) {
666    if (p_buf->len <= llcp_cb.lcb.peer_miu) {
667      if (p_buf->offset >= LLCP_MIN_OFFSET) {
668        status = llcp_util_send_ui(ssap, dsap, p_app_cb, p_buf);
669      } else {
670        LLCP_TRACE_ERROR2("LLCP_SendUI (): offset (%d) must be %d at least",
671                          p_buf->offset, LLCP_MIN_OFFSET);
672      }
673    } else {
674      LLCP_TRACE_ERROR0(
675          "LLCP_SendUI (): Data length shall not be bigger than peer's link "
676          "MIU");
677    }
678  } else {
679    LLCP_TRACE_ERROR0(
680        "LLCP_SendUI (): Peer doesn't support connectionless link");
681  }
682
683  if (status == LLCP_STATUS_FAIL) {
684    GKI_freebuf(p_buf);
685  }
686
687  return status;
688}
689
690/*******************************************************************************
691**
692** Function         LLCP_ReadLogicalLinkData
693**
694** Description      Read information of UI PDU for local SAP
695**
696**                  - Remote SAP who sent UI PDU is returned.
697**                  - Information of UI PDU up to max_data_len is copied into
698**                    p_data.
699**                  - Information of next UI PDU is not concatenated.
700**                  - Recommended max_data_len is link MIU of local device
701**
702** Returns          TRUE if more information of UI PDU or more UI PDU in queue
703**
704*******************************************************************************/
705bool LLCP_ReadLogicalLinkData(uint8_t local_sap, uint32_t max_data_len,
706                              uint8_t* p_remote_sap, uint32_t* p_data_len,
707                              uint8_t* p_data) {
708  tLLCP_APP_CB* p_app_cb;
709  NFC_HDR* p_buf;
710  uint8_t* p_ui_pdu;
711  uint16_t pdu_hdr, ui_pdu_length;
712
713  LLCP_TRACE_API1("LLCP_ReadLogicalLinkData () Local SAP:0x%x", local_sap);
714
715  *p_data_len = 0;
716
717  p_app_cb = llcp_util_get_app_cb(local_sap);
718
719  /* if application is registered */
720  if ((p_app_cb) && (p_app_cb->p_app_cback)) {
721    /* if any UI PDU in rx queue */
722    if (p_app_cb->ui_rx_q.p_first) {
723      p_buf = (NFC_HDR*)p_app_cb->ui_rx_q.p_first;
724      p_ui_pdu = (uint8_t*)(p_buf + 1) + p_buf->offset;
725
726      /* get length of UI PDU */
727      BE_STREAM_TO_UINT16(ui_pdu_length, p_ui_pdu);
728
729      /* get remote SAP from LLCP header */
730      BE_STREAM_TO_UINT16(pdu_hdr, p_ui_pdu);
731      *p_remote_sap = LLCP_GET_SSAP(pdu_hdr);
732
733      /* layer_specific has the offset to read within UI PDU */
734      p_ui_pdu += p_buf->layer_specific;
735
736      /* copy data up to max_data_len */
737      if (max_data_len >= (uint32_t)(ui_pdu_length - LLCP_PDU_HEADER_SIZE -
738                                     p_buf->layer_specific)) {
739        /* copy information without LLCP header */
740        *p_data_len = (uint32_t)(ui_pdu_length - LLCP_PDU_HEADER_SIZE -
741                                 p_buf->layer_specific);
742
743        /* move to next UI PDU if any */
744        p_buf->layer_specific =
745            0; /* reset offset to read from the first byte of next UI PDU */
746        p_buf->offset += LLCP_PDU_AGF_LEN_SIZE + ui_pdu_length;
747        p_buf->len -= LLCP_PDU_AGF_LEN_SIZE + ui_pdu_length;
748      } else {
749        *p_data_len = max_data_len;
750
751        /* update offset to read from remaining UI PDU next time */
752        p_buf->layer_specific += max_data_len;
753      }
754
755      memcpy(p_data, p_ui_pdu, *p_data_len);
756
757      /* if read all of UI PDU */
758      if (p_buf->len == 0) {
759        GKI_dequeue(&p_app_cb->ui_rx_q);
760        GKI_freebuf(p_buf);
761
762        /* decrease number of received UI PDU in in all of ui_rx_q and check rx
763         * congestion status */
764        llcp_cb.total_rx_ui_pdu--;
765        llcp_util_check_rx_congested_status();
766      }
767    }
768
769    /* if there is more UI PDU in rx queue */
770    if (p_app_cb->ui_rx_q.p_first) {
771      return true;
772    } else {
773      return false;
774    }
775  } else {
776    LLCP_TRACE_ERROR1("LLCP_ReadLogicalLinkData (): Unregistered SAP:0x%x",
777                      local_sap);
778
779    return false;
780  }
781}
782
783/*******************************************************************************
784**
785** Function         LLCP_FlushLogicalLinkRxData
786**
787** Description      Discard received data in logical data link of local SAP
788**
789**
790** Returns          length of data flushed
791**
792*******************************************************************************/
793uint32_t LLCP_FlushLogicalLinkRxData(uint8_t local_sap) {
794  NFC_HDR* p_buf;
795  uint32_t flushed_length = 0;
796  tLLCP_APP_CB* p_app_cb;
797  uint8_t* p_ui_pdu;
798  uint16_t ui_pdu_length;
799
800  LLCP_TRACE_API1("LLCP_FlushLogicalLinkRxData () Local SAP:0x%x", local_sap);
801
802  p_app_cb = llcp_util_get_app_cb(local_sap);
803
804  /* if application is registered */
805  if ((p_app_cb) && (p_app_cb->p_app_cback)) {
806    /* if any UI PDU in rx queue */
807    while (p_app_cb->ui_rx_q.p_first) {
808      p_buf = (NFC_HDR*)p_app_cb->ui_rx_q.p_first;
809      p_ui_pdu = (uint8_t*)(p_buf + 1) + p_buf->offset;
810
811      /* get length of UI PDU */
812      BE_STREAM_TO_UINT16(ui_pdu_length, p_ui_pdu);
813
814      flushed_length += (uint32_t)(ui_pdu_length - LLCP_PDU_HEADER_SIZE -
815                                   p_buf->layer_specific);
816
817      /* move to next UI PDU if any */
818      p_buf->layer_specific = 0; /* offset */
819      p_buf->offset += LLCP_PDU_AGF_LEN_SIZE + ui_pdu_length;
820      p_buf->len -= LLCP_PDU_AGF_LEN_SIZE + ui_pdu_length;
821
822      /* if read all of UI PDU */
823      if (p_buf->len == 0) {
824        GKI_dequeue(&p_app_cb->ui_rx_q);
825        GKI_freebuf(p_buf);
826        llcp_cb.total_rx_ui_pdu--;
827      }
828    }
829
830    /* number of received UI PDU is decreased so check rx congestion status */
831    llcp_util_check_rx_congested_status();
832  } else {
833    LLCP_TRACE_ERROR1("LLCP_FlushLogicalLinkRxData (): Unregistered SAP:0x%x",
834                      local_sap);
835  }
836
837  return (flushed_length);
838}
839
840/*******************************************************************************
841**
842** Function         LLCP_ConnectReq
843**
844** Description      Create data link connection between registered SAP and DSAP
845**                  in peer LLCP,
846**
847**
848** Returns          LLCP_STATUS_SUCCESS if success
849**                  LLCP_STATUS_FAIL, otherwise
850**
851*******************************************************************************/
852tLLCP_STATUS LLCP_ConnectReq(uint8_t reg_sap, uint8_t dsap,
853                             tLLCP_CONNECTION_PARAMS* p_params) {
854  tLLCP_DLCB* p_dlcb;
855  tLLCP_STATUS status;
856  tLLCP_APP_CB* p_app_cb;
857  tLLCP_CONNECTION_PARAMS params;
858
859  LLCP_TRACE_API2("LLCP_ConnectReq () reg_sap=0x%x, DSAP=0x%x", reg_sap, dsap);
860
861  if ((llcp_cb.lcb.peer_opt != LLCP_LSC_UNKNOWN) &&
862      ((llcp_cb.lcb.peer_opt & LLCP_LSC_2) == 0)) {
863    LLCP_TRACE_ERROR0(
864        "LLCP_ConnectReq (): Peer doesn't support connection-oriented link");
865    return LLCP_STATUS_FAIL;
866  }
867
868  if (!p_params) {
869    params.miu = LLCP_DEFAULT_MIU;
870    params.rw = LLCP_DEFAULT_RW;
871    params.sn[0] = 0;
872    p_params = &params;
873  }
874
875  p_app_cb = llcp_util_get_app_cb(reg_sap);
876
877  /* if application is registered */
878  if ((p_app_cb == NULL) || (p_app_cb->p_app_cback == NULL)) {
879    LLCP_TRACE_ERROR1("LLCP_ConnectReq (): SSAP (0x%x) is not registered",
880                      reg_sap);
881    return LLCP_STATUS_FAIL;
882  }
883
884  if (dsap == LLCP_SAP_LM) {
885    LLCP_TRACE_ERROR1(
886        "LLCP_ConnectReq (): DSAP (0x%x) must not be link manager SAP", dsap);
887    return LLCP_STATUS_FAIL;
888  }
889
890  if (dsap == LLCP_SAP_SDP) {
891    if (strlen(p_params->sn) > LLCP_MAX_SN_LEN) {
892      LLCP_TRACE_ERROR1(
893          "LLCP_ConnectReq (): Service Name (%d bytes) is too long",
894          strlen(p_params->sn));
895      return LLCP_STATUS_FAIL;
896    }
897  }
898
899  if ((p_params) && (p_params->miu > llcp_cb.lcb.local_link_miu)) {
900    LLCP_TRACE_ERROR0(
901        "LLCP_ConnectReq (): Data link MIU shall not be bigger than local link "
902        "MIU");
903    return LLCP_STATUS_FAIL;
904  }
905
906  /* check if any pending connection request on this reg_sap */
907  p_dlcb = llcp_dlc_find_dlcb_by_sap(reg_sap, LLCP_INVALID_SAP);
908  if (p_dlcb) {
909    /*
910    ** Accepting LLCP may change SAP in CC, so we cannot find right data
911    ** link connection if there is multiple pending connection request on
912    ** the same local SAP.
913    */
914    LLCP_TRACE_ERROR0(
915        "LLCP_ConnectReq (): There is pending connect request on this reg_sap");
916    return LLCP_STATUS_FAIL;
917  }
918
919  p_dlcb = llcp_util_allocate_data_link(reg_sap, dsap);
920
921  if (p_dlcb) {
922    status =
923        llcp_dlsm_execute(p_dlcb, LLCP_DLC_EVENT_API_CONNECT_REQ, p_params);
924    if (status != LLCP_STATUS_SUCCESS) {
925      LLCP_TRACE_ERROR0("LLCP_ConnectReq (): Error in state machine");
926      llcp_util_deallocate_data_link(p_dlcb);
927      return LLCP_STATUS_FAIL;
928    }
929  } else {
930    return LLCP_STATUS_FAIL;
931  }
932
933  return LLCP_STATUS_SUCCESS;
934}
935
936/*******************************************************************************
937**
938** Function         LLCP_ConnectCfm
939**
940** Description      Accept connection request from peer LLCP
941**
942**
943** Returns          LLCP_STATUS_SUCCESS if success
944**                  LLCP_STATUS_FAIL, otherwise
945**
946*******************************************************************************/
947tLLCP_STATUS LLCP_ConnectCfm(uint8_t local_sap, uint8_t remote_sap,
948                             tLLCP_CONNECTION_PARAMS* p_params) {
949  tLLCP_STATUS status;
950  tLLCP_DLCB* p_dlcb;
951  tLLCP_CONNECTION_PARAMS params;
952
953  LLCP_TRACE_API2("LLCP_ConnectCfm () Local SAP:0x%x, Remote SAP:0x%x)",
954                  local_sap, remote_sap);
955
956  if (!p_params) {
957    params.miu = LLCP_DEFAULT_MIU;
958    params.rw = LLCP_DEFAULT_RW;
959    params.sn[0] = 0;
960    p_params = &params;
961  }
962  if (p_params->miu > llcp_cb.lcb.local_link_miu) {
963    LLCP_TRACE_ERROR0(
964        "LLCP_ConnectCfm (): Data link MIU shall not be bigger than local link "
965        "MIU");
966    return LLCP_STATUS_FAIL;
967  }
968
969  p_dlcb = llcp_dlc_find_dlcb_by_sap(local_sap, remote_sap);
970
971  if (p_dlcb) {
972    status =
973        llcp_dlsm_execute(p_dlcb, LLCP_DLC_EVENT_API_CONNECT_CFM, p_params);
974  } else {
975    LLCP_TRACE_ERROR0("LLCP_ConnectCfm (): No data link");
976    status = LLCP_STATUS_FAIL;
977  }
978
979  return status;
980}
981
982/*******************************************************************************
983**
984** Function         LLCP_ConnectReject
985**
986** Description      Reject connection request from peer LLCP
987**
988**                  reason : LLCP_SAP_DM_REASON_APP_REJECTED
989**                           LLCP_SAP_DM_REASON_PERM_REJECT_THIS
990**                           LLCP_SAP_DM_REASON_PERM_REJECT_ANY
991**                           LLCP_SAP_DM_REASON_TEMP_REJECT_THIS
992**                           LLCP_SAP_DM_REASON_TEMP_REJECT_ANY
993**
994** Returns          LLCP_STATUS_SUCCESS if success
995**                  LLCP_STATUS_FAIL, otherwise
996**
997*******************************************************************************/
998tLLCP_STATUS LLCP_ConnectReject(uint8_t local_sap, uint8_t remote_sap,
999                                uint8_t reason) {
1000  tLLCP_STATUS status;
1001  tLLCP_DLCB* p_dlcb;
1002
1003  LLCP_TRACE_API3(
1004      "LLCP_ConnectReject () Local SAP:0x%x, Remote SAP:0x%x, reason:0x%x",
1005      local_sap, remote_sap, reason);
1006
1007  p_dlcb = llcp_dlc_find_dlcb_by_sap(local_sap, remote_sap);
1008
1009  if (p_dlcb) {
1010    status =
1011        llcp_dlsm_execute(p_dlcb, LLCP_DLC_EVENT_API_CONNECT_REJECT, &reason);
1012    llcp_util_deallocate_data_link(p_dlcb);
1013  } else {
1014    LLCP_TRACE_ERROR0("LLCP_ConnectReject (): No data link");
1015    status = LLCP_STATUS_FAIL;
1016  }
1017
1018  return status;
1019}
1020
1021/*******************************************************************************
1022**
1023** Function         LLCP_IsDataLinkCongested
1024**
1025** Description      Check if data link connection is congested
1026**
1027**
1028** Returns          TRUE if congested
1029**
1030*******************************************************************************/
1031bool LLCP_IsDataLinkCongested(uint8_t local_sap, uint8_t remote_sap,
1032                              uint8_t num_pending_i_pdu,
1033                              uint8_t total_pending_ui_pdu,
1034                              uint8_t total_pending_i_pdu) {
1035  tLLCP_DLCB* p_dlcb;
1036
1037  LLCP_TRACE_API5(
1038      "LLCP_IsDataLinkCongested () Local SAP:0x%x, Remote SAP:0x%x, pending = "
1039      "(%d, %d, %d)",
1040      local_sap, remote_sap, num_pending_i_pdu, total_pending_ui_pdu,
1041      total_pending_i_pdu);
1042
1043  p_dlcb = llcp_dlc_find_dlcb_by_sap(local_sap, remote_sap);
1044
1045  if (p_dlcb) {
1046    if ((p_dlcb->is_tx_congested) || (p_dlcb->remote_busy)) {
1047      return true;
1048    } else if ((num_pending_i_pdu + p_dlcb->i_xmit_q.count >=
1049                p_dlcb->remote_rw) ||
1050               (total_pending_ui_pdu + total_pending_i_pdu +
1051                    llcp_cb.total_tx_ui_pdu + llcp_cb.total_tx_i_pdu >=
1052                llcp_cb.max_num_tx_buff)) {
1053      /* set flag so LLCP can notify uncongested status later */
1054      p_dlcb->is_tx_congested = true;
1055      return true;
1056    }
1057    return false;
1058  }
1059  return true;
1060}
1061
1062/*******************************************************************************
1063**
1064** Function         LLCP_SendData
1065**
1066** Description      Send connection-oriented data
1067**
1068**
1069** Returns          LLCP_STATUS_SUCCESS if success
1070**                  LLCP_STATUS_CONGESTED if data link is congested
1071**
1072*******************************************************************************/
1073tLLCP_STATUS LLCP_SendData(uint8_t local_sap, uint8_t remote_sap,
1074                           NFC_HDR* p_buf) {
1075  tLLCP_STATUS status = LLCP_STATUS_FAIL;
1076  tLLCP_DLCB* p_dlcb;
1077
1078  LLCP_TRACE_API2("LLCP_SendData () Local SAP:0x%x, Remote SAP:0x%x", local_sap,
1079                  remote_sap);
1080
1081  p_dlcb = llcp_dlc_find_dlcb_by_sap(local_sap, remote_sap);
1082
1083  if (p_dlcb) {
1084    if (p_dlcb->remote_miu >= p_buf->len) {
1085      if (p_buf->offset >= LLCP_MIN_OFFSET) {
1086        status = llcp_dlsm_execute(p_dlcb, LLCP_DLC_EVENT_API_DATA_REQ, p_buf);
1087      } else {
1088        LLCP_TRACE_ERROR2("LLCP_SendData (): offset (%d) must be %d at least",
1089                          p_buf->offset, LLCP_MIN_OFFSET);
1090      }
1091    } else {
1092      LLCP_TRACE_ERROR2(
1093          "LLCP_SendData (): Information (%d bytes) cannot be more than peer "
1094          "MIU (%d bytes)",
1095          p_buf->len, p_dlcb->remote_miu);
1096    }
1097  } else {
1098    LLCP_TRACE_ERROR0("LLCP_SendData (): No data link");
1099  }
1100
1101  if (status == LLCP_STATUS_FAIL) {
1102    GKI_freebuf(p_buf);
1103  }
1104
1105  return status;
1106}
1107
1108/*******************************************************************************
1109**
1110** Function         LLCP_ReadDataLinkData
1111**
1112** Description      Read information of I PDU for data link connection
1113**
1114**                  - Information of I PDU up to max_data_len is copied into
1115**                    p_data.
1116**                  - Information of next I PDU is not concatenated.
1117**                  - Recommended max_data_len is data link connection MIU of
1118**                    local end point
1119**
1120** Returns          TRUE if more data in queue
1121**
1122*******************************************************************************/
1123bool LLCP_ReadDataLinkData(uint8_t local_sap, uint8_t remote_sap,
1124                           uint32_t max_data_len, uint32_t* p_data_len,
1125                           uint8_t* p_data) {
1126  tLLCP_DLCB* p_dlcb;
1127  NFC_HDR* p_buf;
1128  uint8_t* p_i_pdu;
1129  uint16_t i_pdu_length;
1130
1131  LLCP_TRACE_API2("LLCP_ReadDataLinkData () Local SAP:0x%x, Remote SAP:0x%x",
1132                  local_sap, remote_sap);
1133
1134  p_dlcb = llcp_dlc_find_dlcb_by_sap(local_sap, remote_sap);
1135
1136  *p_data_len = 0;
1137  if (p_dlcb) {
1138    /* if any I PDU in rx queue */
1139    if (p_dlcb->i_rx_q.p_first) {
1140      p_buf = (NFC_HDR*)p_dlcb->i_rx_q.p_first;
1141      p_i_pdu = (uint8_t*)(p_buf + 1) + p_buf->offset;
1142
1143      /* get length of I PDU */
1144      BE_STREAM_TO_UINT16(i_pdu_length, p_i_pdu);
1145
1146      /* layer_specific has the offset to read within I PDU */
1147      p_i_pdu += p_buf->layer_specific;
1148
1149      /* copy data up to max_data_len */
1150      if (max_data_len >= (uint32_t)(i_pdu_length - p_buf->layer_specific)) {
1151        /* copy information */
1152        *p_data_len = (uint32_t)(i_pdu_length - p_buf->layer_specific);
1153
1154        /* move to next I PDU if any */
1155        p_buf->layer_specific =
1156            0; /* reset offset to read from the first byte of next I PDU */
1157        p_buf->offset += LLCP_PDU_AGF_LEN_SIZE + i_pdu_length;
1158        p_buf->len -= LLCP_PDU_AGF_LEN_SIZE + i_pdu_length;
1159      } else {
1160        *p_data_len = max_data_len;
1161
1162        /* update offset to read from remaining I PDU next time */
1163        p_buf->layer_specific += max_data_len;
1164      }
1165
1166      memcpy(p_data, p_i_pdu, *p_data_len);
1167
1168      if (p_buf->layer_specific == 0) {
1169        p_dlcb->num_rx_i_pdu--;
1170      }
1171
1172      /* if read all of I PDU */
1173      if (p_buf->len == 0) {
1174        GKI_dequeue(&p_dlcb->i_rx_q);
1175        GKI_freebuf(p_buf);
1176
1177        /* decrease number of received I PDU in in all of ui_rx_q and check rx
1178         * congestion status */
1179        llcp_cb.total_rx_i_pdu--;
1180        llcp_util_check_rx_congested_status();
1181      }
1182    }
1183
1184    /* if getting out of rx congestion */
1185    if ((!p_dlcb->local_busy) && (p_dlcb->is_rx_congested) &&
1186        (p_dlcb->num_rx_i_pdu <= p_dlcb->rx_congest_threshold / 2)) {
1187      /* send RR */
1188      p_dlcb->is_rx_congested = false;
1189      p_dlcb->flags |= LLCP_DATA_LINK_FLAG_PENDING_RR_RNR;
1190    }
1191
1192    /* if there is more I PDU in rx queue */
1193    if (p_dlcb->i_rx_q.p_first) {
1194      return true;
1195    } else {
1196      return false;
1197    }
1198  } else {
1199    LLCP_TRACE_ERROR0("LLCP_ReadDataLinkData (): No data link connection");
1200
1201    return false;
1202  }
1203}
1204
1205/*******************************************************************************
1206**
1207** Function         LLCP_FlushDataLinkRxData
1208**
1209** Description      Discard received data in data link connection
1210**
1211**
1212** Returns          length of rx data flushed
1213**
1214*******************************************************************************/
1215uint32_t LLCP_FlushDataLinkRxData(uint8_t local_sap, uint8_t remote_sap) {
1216  tLLCP_DLCB* p_dlcb;
1217  NFC_HDR* p_buf;
1218  uint32_t flushed_length = 0;
1219  uint8_t* p_i_pdu;
1220  uint16_t i_pdu_length;
1221
1222  LLCP_TRACE_API2("LLCP_FlushDataLinkRxData () Local SAP:0x%x, Remote SAP:0x%x",
1223                  local_sap, remote_sap);
1224
1225  p_dlcb = llcp_dlc_find_dlcb_by_sap(local_sap, remote_sap);
1226
1227  if (p_dlcb) {
1228    /* if any I PDU in rx queue */
1229    while (p_dlcb->i_rx_q.p_first) {
1230      p_buf = (NFC_HDR*)p_dlcb->i_rx_q.p_first;
1231      p_i_pdu = (uint8_t*)(p_buf + 1) + p_buf->offset;
1232
1233      /* get length of I PDU */
1234      BE_STREAM_TO_UINT16(i_pdu_length, p_i_pdu);
1235
1236      flushed_length += (uint32_t)(i_pdu_length - p_buf->layer_specific);
1237
1238      /* move to next I PDU if any */
1239      p_buf->layer_specific = 0; /* offset */
1240      p_buf->offset += LLCP_PDU_AGF_LEN_SIZE + i_pdu_length;
1241      p_buf->len -= LLCP_PDU_AGF_LEN_SIZE + i_pdu_length;
1242
1243      /* if read all of I PDU */
1244      if (p_buf->len == 0) {
1245        GKI_dequeue(&p_dlcb->i_rx_q);
1246        GKI_freebuf(p_buf);
1247        llcp_cb.total_rx_i_pdu--;
1248      }
1249    }
1250
1251    p_dlcb->num_rx_i_pdu = 0;
1252
1253    /* if getting out of rx congestion */
1254    if ((!p_dlcb->local_busy) && (p_dlcb->is_rx_congested)) {
1255      /* send RR */
1256      p_dlcb->is_rx_congested = false;
1257      p_dlcb->flags |= LLCP_DATA_LINK_FLAG_PENDING_RR_RNR;
1258    }
1259
1260    /* number of received I PDU is decreased so check rx congestion status */
1261    llcp_util_check_rx_congested_status();
1262  } else {
1263    LLCP_TRACE_ERROR0("LLCP_FlushDataLinkRxData (): No data link connection");
1264  }
1265
1266  return (flushed_length);
1267}
1268
1269/*******************************************************************************
1270**
1271** Function         LLCP_DisconnectReq
1272**
1273** Description      Disconnect data link
1274**                  discard any pending data if flush is set to TRUE
1275**
1276** Returns          LLCP_STATUS_SUCCESS if success
1277**
1278*******************************************************************************/
1279tLLCP_STATUS LLCP_DisconnectReq(uint8_t local_sap, uint8_t remote_sap,
1280                                bool flush) {
1281  tLLCP_STATUS status;
1282  tLLCP_DLCB* p_dlcb;
1283
1284  LLCP_TRACE_API3(
1285      "LLCP_DisconnectReq () Local SAP:0x%x, Remote SAP:0x%x, flush=%d",
1286      local_sap, remote_sap, flush);
1287
1288  p_dlcb = llcp_dlc_find_dlcb_by_sap(local_sap, remote_sap);
1289
1290  if (p_dlcb) {
1291    status =
1292        llcp_dlsm_execute(p_dlcb, LLCP_DLC_EVENT_API_DISCONNECT_REQ, &flush);
1293  } else {
1294    LLCP_TRACE_ERROR0("LLCP_DisconnectReq (): No data link");
1295    status = LLCP_STATUS_FAIL;
1296  }
1297
1298  return status;
1299}
1300
1301/*******************************************************************************
1302**
1303** Function         LLCP_SetTxCompleteNtf
1304**
1305** Description      This function is called to get LLCP_SERVICE_TX_COMPLETE
1306**                  when Tx queue is empty and all PDU is acked.
1307**                  This is one time event, so upper layer shall call this
1308**                  function again to get next LLCP_SERVICE_TX_COMPLETE.
1309**
1310** Returns          LLCP_STATUS_SUCCESS if success
1311**
1312*******************************************************************************/
1313tLLCP_STATUS LLCP_SetTxCompleteNtf(uint8_t local_sap, uint8_t remote_sap) {
1314  tLLCP_STATUS status;
1315  tLLCP_DLCB* p_dlcb;
1316
1317  LLCP_TRACE_API2("LLCP_SetTxCompleteNtf () Local SAP:0x%x, Remote SAP:0x%x",
1318                  local_sap, remote_sap);
1319
1320  p_dlcb = llcp_dlc_find_dlcb_by_sap(local_sap, remote_sap);
1321
1322  if (p_dlcb) {
1323    /* set flag to notify upper later when tx complete */
1324    p_dlcb->flags |= LLCP_DATA_LINK_FLAG_NOTIFY_TX_DONE;
1325    status = LLCP_STATUS_SUCCESS;
1326  } else {
1327    LLCP_TRACE_ERROR0("LLCP_SetTxCompleteNtf (): No data link");
1328    status = LLCP_STATUS_FAIL;
1329  }
1330
1331  return status;
1332}
1333
1334/*******************************************************************************
1335**
1336** Function         LLCP_SetLocalBusyStatus
1337**
1338** Description      Set local busy status
1339**
1340**
1341** Returns          LLCP_STATUS_SUCCESS if success
1342**
1343*******************************************************************************/
1344tLLCP_STATUS LLCP_SetLocalBusyStatus(uint8_t local_sap, uint8_t remote_sap,
1345                                     bool is_busy) {
1346  tLLCP_STATUS status;
1347  tLLCP_DLCB* p_dlcb;
1348
1349  LLCP_TRACE_API2("LLCP_SetLocalBusyStatus () Local SAP:0x%x, is_busy=%d",
1350                  local_sap, is_busy);
1351
1352  p_dlcb = llcp_dlc_find_dlcb_by_sap(local_sap, remote_sap);
1353
1354  if (p_dlcb) {
1355    if (p_dlcb->local_busy != is_busy) {
1356      p_dlcb->local_busy = is_busy;
1357
1358      /* send RR or RNR with valid sequence */
1359      p_dlcb->flags |= LLCP_DATA_LINK_FLAG_PENDING_RR_RNR;
1360
1361      if (is_busy == false) {
1362        if (p_dlcb->i_rx_q.count) {
1363          llcp_dlsm_execute(p_dlcb, LLCP_DLC_EVENT_PEER_DATA_IND, NULL);
1364        }
1365      }
1366    }
1367    status = LLCP_STATUS_SUCCESS;
1368  } else {
1369    LLCP_TRACE_ERROR0("LLCP_SetLocalBusyStatus (): No data link");
1370    status = LLCP_STATUS_FAIL;
1371  }
1372
1373  return status;
1374}
1375
1376/*******************************************************************************
1377**
1378** Function         LLCP_GetRemoteWKS
1379**
1380** Description      Return well-known service bitmap of connected device
1381**
1382**
1383** Returns          WKS bitmap if success
1384**
1385*******************************************************************************/
1386uint16_t LLCP_GetRemoteWKS(void) {
1387  LLCP_TRACE_API1("LLCP_GetRemoteWKS () WKS:0x%04x",
1388                  (llcp_cb.lcb.link_state == LLCP_LINK_STATE_ACTIVATED)
1389                      ? llcp_cb.lcb.peer_wks
1390                      : 0);
1391
1392  if (llcp_cb.lcb.link_state == LLCP_LINK_STATE_ACTIVATED)
1393    return (llcp_cb.lcb.peer_wks);
1394  else
1395    return (0);
1396}
1397
1398/*******************************************************************************
1399**
1400** Function         LLCP_GetRemoteLSC
1401**
1402** Description      Return link service class of connected device
1403**
1404**
1405** Returns          link service class
1406**
1407*******************************************************************************/
1408uint8_t LLCP_GetRemoteLSC(void) {
1409  LLCP_TRACE_API1("LLCP_GetRemoteLSC () LSC:0x%x",
1410                  (llcp_cb.lcb.link_state == LLCP_LINK_STATE_ACTIVATED)
1411                      ? llcp_cb.lcb.peer_opt & (LLCP_LSC_1 | LLCP_LSC_2)
1412                      : 0);
1413
1414  if (llcp_cb.lcb.link_state == LLCP_LINK_STATE_ACTIVATED)
1415    return (llcp_cb.lcb.peer_opt & (LLCP_LSC_1 | LLCP_LSC_2));
1416  else
1417    return (LLCP_LSC_UNKNOWN);
1418}
1419
1420/*******************************************************************************
1421**
1422** Function         LLCP_GetRemoteVersion
1423**
1424** Description      Return LLCP version of connected device
1425**
1426**
1427** Returns          LLCP version
1428**
1429*******************************************************************************/
1430uint8_t LLCP_GetRemoteVersion(void) {
1431  LLCP_TRACE_API1("LLCP_GetRemoteVersion () Version: 0x%x",
1432                  (llcp_cb.lcb.link_state == LLCP_LINK_STATE_ACTIVATED)
1433                      ? llcp_cb.lcb.peer_version
1434                      : 0);
1435
1436  if (llcp_cb.lcb.link_state == LLCP_LINK_STATE_ACTIVATED)
1437    return (llcp_cb.lcb.peer_version);
1438  else
1439    return 0;
1440}
1441
1442/*******************************************************************************
1443**
1444** Function         LLCP_GetLinkMIU
1445**
1446** Description      Return local and remote link MIU
1447**
1448**
1449** Returns          None
1450**
1451*******************************************************************************/
1452void LLCP_GetLinkMIU(uint16_t* p_local_link_miu, uint16_t* p_remote_link_miu) {
1453  LLCP_TRACE_API0("LLCP_GetLinkMIU ()");
1454
1455  if (llcp_cb.lcb.link_state == LLCP_LINK_STATE_ACTIVATED) {
1456    *p_local_link_miu = llcp_cb.lcb.local_link_miu;
1457    *p_remote_link_miu = llcp_cb.lcb.effective_miu;
1458  } else {
1459    *p_local_link_miu = 0;
1460    *p_remote_link_miu = 0;
1461  }
1462
1463  LLCP_TRACE_DEBUG2(
1464      "LLCP_GetLinkMIU (): local_link_miu = %d, remote_link_miu = %d",
1465      *p_local_link_miu, *p_remote_link_miu);
1466}
1467
1468/*******************************************************************************
1469**
1470** Function         LLCP_DiscoverService
1471**
1472** Description      Return SAP of service name in connected device through
1473**                  callback
1474**
1475**
1476** Returns          LLCP_STATUS_SUCCESS if success
1477**
1478*******************************************************************************/
1479tLLCP_STATUS LLCP_DiscoverService(char* p_name, tLLCP_SDP_CBACK* p_cback,
1480                                  uint8_t* p_tid) {
1481  tLLCP_STATUS status;
1482  uint8_t i;
1483
1484  LLCP_TRACE_API1("LLCP_DiscoverService () Service Name:%s", p_name);
1485
1486  if (llcp_cb.lcb.link_state != LLCP_LINK_STATE_ACTIVATED) {
1487    LLCP_TRACE_ERROR0("LLCP_DiscoverService (): Link is not activated");
1488    return LLCP_STATUS_FAIL;
1489  }
1490
1491  if (!p_cback) {
1492    LLCP_TRACE_ERROR0("LLCP_DiscoverService (): Callback must be provided.");
1493    return LLCP_STATUS_FAIL;
1494  }
1495
1496  /* if peer version is less than V1.1 then SNL is not supported */
1497  if ((llcp_cb.lcb.agreed_major_version == 0x01) &&
1498      (llcp_cb.lcb.agreed_minor_version < 0x01)) {
1499    LLCP_TRACE_ERROR0("LLCP_DiscoverService (): Peer doesn't support SNL");
1500    return LLCP_STATUS_FAIL;
1501  }
1502
1503  for (i = 0; i < LLCP_MAX_SDP_TRANSAC; i++) {
1504    if (!llcp_cb.sdp_cb.transac[i].p_cback) {
1505      llcp_cb.sdp_cb.transac[i].tid = llcp_cb.sdp_cb.next_tid;
1506      llcp_cb.sdp_cb.next_tid++;
1507      llcp_cb.sdp_cb.transac[i].p_cback = p_cback;
1508
1509      status = llcp_sdp_send_sdreq(llcp_cb.sdp_cb.transac[i].tid, p_name);
1510
1511      if (status == LLCP_STATUS_FAIL) {
1512        llcp_cb.sdp_cb.transac[i].p_cback = NULL;
1513      }
1514
1515      *p_tid = llcp_cb.sdp_cb.transac[i].tid;
1516      return (status);
1517    }
1518  }
1519
1520  LLCP_TRACE_ERROR0("LLCP_DiscoverService (): Out of resource");
1521
1522  return LLCP_STATUS_FAIL;
1523}
1524