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