llcp_link.c revision e9df6ba5a8fcccf306a80b1670b423be8fe7746a
1/******************************************************************************
2 *
3 *  Copyright (C) 2010-2012 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 Link Management
22 *
23 ******************************************************************************/
24
25#include <string.h>
26#include "gki.h"
27#include "nfc_target.h"
28#include "bt_types.h"
29#include "trace_api.h"
30#include "llcp_int.h"
31#include "llcp_defs.h"
32#include "nfc_int.h"
33
34const UINT16 llcp_link_rwt[15] =  /* RWT = (302us)*2**WT; 302us = 256*16/fc; fc = 13.56MHz */
35{
36       1, /* WT=0,     302us */
37       1, /* WT=1,     604us */
38       2, /* WT=2,    1208us */
39       3, /* WT=3,     2.4ms */
40       5, /* WT=4,     4.8ms */
41      10, /* WT=5,     9.7ms */
42      20, /* WT=6,    19.3ms */
43      39, /* WT=7,    38.7ms */
44      78, /* WT=8,    77.3ms */
45     155, /* WT=9,   154.6ms */
46     310, /* WT=10,  309.2ms */
47     619, /* WT=11,  618.5ms */
48    1237, /* WT=12, 1237.0ms */
49    2474, /* WT=13, 2474.0ms */
50    4948, /* WT=14, 4948.0ms */
51};
52
53static BOOLEAN llcp_link_parse_gen_bytes (UINT8 gen_bytes_len, UINT8 *p_gen_bytes);
54static BOOLEAN llcp_link_version_agreement (void);
55
56static void    llcp_link_send_SYMM (void);
57static void    llcp_link_update_status (BOOLEAN is_activated);
58static void    llcp_link_check_congestion (void);
59static void    llcp_link_check_uncongested (void);
60static void    llcp_link_proc_ui_pdu (UINT8 local_sap, UINT8 remote_sap, UINT16 ui_pdu_length, UINT8 *p_ui_pdu, BT_HDR *p_msg);
61static void    llcp_link_proc_agf_pdu (BT_HDR *p_msg);
62static void    llcp_link_proc_rx_pdu (UINT8 dsap, UINT8 ptype, UINT8 ssap, BT_HDR *p_msg);
63static void    llcp_link_proc_rx_data (BT_HDR *p_msg);
64
65static BT_HDR *llcp_link_get_next_pdu (BOOLEAN length_only, UINT16 *p_next_pdu_length);
66static BT_HDR *llcp_link_build_next_pdu (BT_HDR *p_agf);
67static void    llcp_link_send_to_lower (BT_HDR *p_msg);
68
69#if (LLCP_TEST_INCLUDED == TRUE) /* this is for LLCP testing */
70extern tLLCP_TEST_PARAMS llcp_test_params;
71#endif
72
73/* debug functions type */
74#if (BT_TRACE_VERBOSE == TRUE)
75static char *llcp_pdu_type (UINT8 ptype);
76#endif
77
78/*******************************************************************************
79**
80** Function         llcp_link_start_inactivity_timer
81**
82** Description      This function start LLCP link inactivity timer.
83**
84** Returns          void
85**
86*******************************************************************************/
87static void llcp_link_start_inactivity_timer (void)
88{
89    if (  (llcp_cb.lcb.inact_timer.in_use == FALSE)
90        &&(llcp_cb.lcb.inact_timeout > 0)  )
91    {
92        LLCP_TRACE_DEBUG1 ("Start inactivity_timer: %d ms", llcp_cb.lcb.inact_timeout);
93
94        nfc_start_quick_timer (&llcp_cb.lcb.inact_timer, NFC_TTYPE_LLCP_LINK_INACT,
95                               ((UINT32) llcp_cb.lcb.inact_timeout) * QUICK_TIMER_TICKS_PER_SEC / 1000);
96    }
97}
98
99/*******************************************************************************
100**
101** Function         llcp_link_stop_inactivity_timer
102**
103** Description      This function stop LLCP link inactivity timer.
104**
105** Returns          void
106**
107*******************************************************************************/
108static void llcp_link_stop_inactivity_timer (void)
109{
110    if (llcp_cb.lcb.inact_timer.in_use)
111    {
112        LLCP_TRACE_DEBUG0 ("Stop inactivity_timer");
113
114        nfc_stop_quick_timer (&llcp_cb.lcb.inact_timer);
115    }
116}
117
118/*******************************************************************************
119**
120** Function         llcp_link_start_link_timer
121**
122** Description      This function starts LLCP link timer (LTO or delay response).
123**
124** Returns          void
125**
126*******************************************************************************/
127static void llcp_link_start_link_timer (void)
128{
129    if (llcp_cb.lcb.symm_state == LLCP_LINK_SYMM_LOCAL_XMIT_NEXT)
130    {
131        /* wait for application layer sending data */
132        nfc_start_quick_timer (&llcp_cb.lcb.timer, NFC_TTYPE_LLCP_LINK_MANAGER,
133                               (((UINT32) llcp_cb.lcb.symm_delay) * QUICK_TIMER_TICKS_PER_SEC) / 1000);
134    }
135    else
136    {
137        /* wait for data to receive from remote */
138        nfc_start_quick_timer (&llcp_cb.lcb.timer, NFC_TTYPE_LLCP_LINK_MANAGER,
139                               ((UINT32) llcp_cb.lcb.peer_lto) * QUICK_TIMER_TICKS_PER_SEC / 1000);
140    }
141}
142
143/*******************************************************************************
144**
145** Function         llcp_link_stop_link_timer
146**
147** Description      This function stop LLCP link timer (LTO or delay response).
148**
149** Returns          void
150**
151*******************************************************************************/
152static void llcp_link_stop_link_timer (void)
153{
154    nfc_stop_quick_timer (&llcp_cb.lcb.timer);
155}
156
157/*******************************************************************************
158**
159** Function         llcp_link_activate
160**
161** Description      Activate LLCP link
162**
163** Returns          tLLCP_STATUS
164**
165*******************************************************************************/
166tLLCP_STATUS llcp_link_activate (tLLCP_ACTIVATE_CONFIG *p_config)
167{
168    LLCP_TRACE_DEBUG0 ("llcp_link_activate ()");
169
170    /* At this point, MAC link activation procedure has been successfully completed */
171
172    /* The Length Reduction values LRi and LRt MUST be 11b. (254bytes) */
173    if (p_config->max_payload_size != LLCP_NCI_MAX_PAYL_SIZE)
174    {
175        LLCP_TRACE_WARNING2 ("llcp_link_activate (): max payload size (%d) must be %d bytes",
176                             p_config->max_payload_size, LLCP_NCI_MAX_PAYL_SIZE);
177    }
178
179    /* Processing the parametes that have been received with the MAC link activation */
180    if (llcp_link_parse_gen_bytes (p_config->gen_bytes_len,
181                                   p_config->p_gen_bytes ) == FALSE)
182    {
183        LLCP_TRACE_ERROR0 ("llcp_link_activate (): Failed to parse general bytes");
184        (*llcp_cb.lcb.p_link_cback) (LLCP_LINK_ACTIVATION_FAILED_EVT, LLCP_LINK_BAD_GEN_BYTES);
185        return LLCP_STATUS_FAIL;
186    }
187
188    /*
189    ** For the Target device, the scaled value of RWT MUST be less than or equal to the
190    ** scaled value of the LLC Link Timeout (LTO).
191    */
192    if ((p_config->is_initiator) && (llcp_link_rwt[p_config->waiting_time] > llcp_cb.lcb.peer_lto))
193    {
194        LLCP_TRACE_WARNING3 ("llcp_link_activate (): WT (%d, %dms) must be less than or equal to LTO (%dms)",
195                             p_config->waiting_time,
196                             llcp_link_rwt[p_config->waiting_time],
197                             llcp_cb.lcb.peer_lto);
198    }
199
200    /* extend LTO as much as internally required processing time and propagation delays */
201    llcp_cb.lcb.peer_lto += LLCP_INTERNAL_TX_DELAY + LLCP_INTERNAL_RX_DELAY;
202
203    /* LLCP version number agreement */
204    if (llcp_link_version_agreement () == FALSE)
205    {
206        LLCP_TRACE_ERROR0 ("llcp_link_activate (): Failed to agree version");
207        (*llcp_cb.lcb.p_link_cback) (LLCP_LINK_ACTIVATION_FAILED_EVT, LLCP_LINK_VERSION_FAILED);
208        return LLCP_STATUS_FAIL;
209    }
210
211    llcp_cb.lcb.is_initiator = p_config->is_initiator;
212
213    /* set tx MIU to MIN (MIU of local LLCP, MIU of peer LLCP) */
214
215    if (llcp_cb.lcb.local_link_miu >= llcp_cb.lcb.peer_miu)
216        llcp_cb.lcb.effective_miu = llcp_cb.lcb.peer_miu;
217    else
218        llcp_cb.lcb.effective_miu = llcp_cb.lcb.local_link_miu;
219
220    /*
221    ** When entering the normal operation phase, LLCP shall initialize the symmetry
222    ** procedure.
223    */
224    if (llcp_cb.lcb.is_initiator)
225    {
226        LLCP_TRACE_DEBUG0 ("llcp_link_activate (): Connected as Initiator");
227
228        llcp_cb.lcb.inact_timeout = llcp_cb.lcb.inact_timeout_init;
229        llcp_cb.lcb.symm_state    = LLCP_LINK_SYMM_LOCAL_XMIT_NEXT;
230
231        if (llcp_cb.lcb.delay_first_pdu_timeout > 0)
232        {
233            /* give a chance to upper layer to send PDU if need */
234            nfc_start_quick_timer (&llcp_cb.lcb.timer, NFC_TTYPE_LLCP_DELAY_FIRST_PDU,
235                                   (((UINT32) llcp_cb.lcb.delay_first_pdu_timeout) * QUICK_TIMER_TICKS_PER_SEC) / 1000);
236        }
237        else
238        {
239            llcp_link_send_SYMM ();
240        }
241    }
242    else
243    {
244        LLCP_TRACE_DEBUG0 ("llcp_link_activate (): Connected as Target");
245        llcp_cb.lcb.inact_timeout = llcp_cb.lcb.inact_timeout_target;
246        llcp_cb.lcb.symm_state    = LLCP_LINK_SYMM_REMOTE_XMIT_NEXT;
247
248        /* wait for data to receive from remote */
249        llcp_link_start_link_timer ();
250    }
251
252
253    /*
254    ** Set state to LLCP_LINK_STATE_ACTIVATED and notify activation before set data callback
255    ** because LLCP PDU could be in NCI queue.
256    */
257    llcp_cb.lcb.link_state = LLCP_LINK_STATE_ACTIVATED;
258
259    /* LLCP Link Activation completed */
260    (*llcp_cb.lcb.p_link_cback) (LLCP_LINK_ACTIVATION_COMPLETE_EVT, LLCP_LINK_SUCCESS);
261
262    /* Update link status to service layer */
263    llcp_link_update_status (TRUE);
264
265    NFC_SetStaticRfCback (llcp_link_connection_cback);
266
267    return (LLCP_STATUS_SUCCESS);
268}
269
270/*******************************************************************************
271**
272** Function         llcp_deactivate_cleanup
273**
274** Description      Clean up for link deactivation
275**
276** Returns          void
277**
278*******************************************************************************/
279static void llcp_deactivate_cleanup  (UINT8 reason)
280{
281    /* report SDP failure for any pending request */
282    llcp_sdp_proc_deactivation ();
283
284    /* Update link status to service layer */
285    llcp_link_update_status (FALSE);
286
287    /* We had sent out DISC */
288    llcp_cb.lcb.link_state = LLCP_LINK_STATE_DEACTIVATED;
289
290    llcp_link_stop_link_timer ();
291
292    /* stop inactivity timer */
293    llcp_link_stop_inactivity_timer ();
294
295    /* Let upper layer deactivate local link */
296    (*llcp_cb.lcb.p_link_cback) (LLCP_LINK_DEACTIVATED_EVT, reason);
297}
298
299/*******************************************************************************
300**
301** Function         llcp_link_process_link_timeout
302**
303** Description      Process timeout events for LTO, SYMM and deactivating
304**
305** Returns          void
306**
307*******************************************************************************/
308void llcp_link_process_link_timeout (void)
309{
310    if (llcp_cb.lcb.link_state == LLCP_LINK_STATE_ACTIVATED)
311    {
312        if ((llcp_cb.lcb.symm_delay > 0) && (llcp_cb.lcb.symm_state == LLCP_LINK_SYMM_LOCAL_XMIT_NEXT))
313        {
314            /* upper layer doesn't have anything to send */
315            LLCP_TRACE_DEBUG0 ("llcp_link_process_link_timeout (): LEVT_TIMEOUT in state of LLCP_LINK_SYMM_LOCAL_XMIT_NEXT");
316            llcp_link_send_SYMM ();
317
318            /* wait for data to receive from remote */
319            llcp_link_start_link_timer ();
320
321            /* start inactivity timer */
322            if (llcp_cb.num_data_link_connection == 0)
323            {
324                llcp_link_start_inactivity_timer ();
325            }
326        }
327        else
328        {
329            LLCP_TRACE_ERROR0 ("llcp_link_process_link_timeout (): LEVT_TIMEOUT in state of LLCP_LINK_SYMM_REMOTE_XMIT_NEXT");
330            llcp_link_deactivate (LLCP_LINK_TIMEOUT);
331        }
332    }
333    else if (llcp_cb.lcb.link_state == LLCP_LINK_STATE_DEACTIVATING)
334    {
335        llcp_deactivate_cleanup (llcp_cb.lcb.link_deact_reason);
336
337        NFC_SetStaticRfCback (NULL);
338    }
339}
340
341/*******************************************************************************
342**
343** Function         llcp_link_deactivate
344**
345** Description      Deactivate LLCP link
346**
347** Returns          void
348**
349*******************************************************************************/
350void llcp_link_deactivate (UINT8 reason)
351{
352    UINT8        local_sap, idx;
353    tLLCP_DLCB   *p_dlcb;
354    tLLCP_APP_CB *p_app_cb;
355
356    LLCP_TRACE_DEBUG1 ("llcp_link_deactivate () reason = 0x%x", reason);
357
358    /* Release any held buffers in signaling PDU queue */
359    while (llcp_cb.lcb.sig_xmit_q.p_first)
360        GKI_freebuf (GKI_dequeue (&llcp_cb.lcb.sig_xmit_q));
361
362    /* Release any held buffers in UI PDU queue */
363    for (local_sap = LLCP_SAP_SDP + 1; local_sap < LLCP_NUM_SAPS; local_sap++)
364    {
365        p_app_cb = llcp_util_get_app_cb (local_sap);
366
367        if (  (p_app_cb)
368            &&(p_app_cb->p_app_cback)  )
369        {
370            while (p_app_cb->ui_xmit_q.p_first)
371                GKI_freebuf (GKI_dequeue (&p_app_cb->ui_xmit_q));
372
373            p_app_cb->is_ui_tx_congested = FALSE;
374
375            while (p_app_cb->ui_rx_q.p_first)
376                GKI_freebuf (GKI_dequeue (&p_app_cb->ui_rx_q));
377        }
378    }
379
380    llcp_cb.total_tx_ui_pdu = 0;
381    llcp_cb.total_rx_ui_pdu = 0;
382
383    /* Notify all of data link */
384    for (idx = 0; idx < LLCP_MAX_DATA_LINK; idx++)
385    {
386        if (llcp_cb.dlcb[idx].state != LLCP_DLC_STATE_IDLE)
387        {
388            p_dlcb = &(llcp_cb.dlcb[idx]);
389
390            llcp_dlsm_execute (p_dlcb, LLCP_DLC_EVENT_LINK_ERROR, NULL);
391        }
392    }
393    llcp_cb.total_tx_i_pdu = 0;
394    llcp_cb.total_rx_i_pdu = 0;
395
396    llcp_cb.overall_tx_congested = FALSE;
397    llcp_cb.overall_rx_congested = FALSE;
398
399    if (  (reason == LLCP_LINK_FRAME_ERROR)
400        ||(reason == LLCP_LINK_LOCAL_INITIATED)  )
401    {
402        /* get rid of the data pending in NFC tx queue, so DISC PDU can be sent ASAP */
403        NFC_FlushData (NFC_RF_CONN_ID);
404
405        llcp_util_send_disc (LLCP_SAP_LM, LLCP_SAP_LM);
406
407        /* Wait until DISC is sent to peer */
408        LLCP_TRACE_DEBUG0 ("llcp_link_deactivate (): Wait until DISC is sent to peer");
409
410        llcp_cb.lcb.link_state = LLCP_LINK_STATE_DEACTIVATING;
411
412        if (llcp_cb.lcb.sig_xmit_q.count == 0)
413        {
414            /* if DISC is sent to NFCC, wait for short period for NFCC to send it to peer */
415            nfc_start_quick_timer (&llcp_cb.lcb.timer, NFC_TTYPE_LLCP_LINK_MANAGER,
416                                   ((UINT32) 50) * QUICK_TIMER_TICKS_PER_SEC / 1000);
417        }
418
419        llcp_cb.lcb.link_deact_reason = reason;
420        return;
421    }
422    else if (  (reason == LLCP_LINK_REMOTE_INITIATED)
423             &&(!llcp_cb.lcb.is_initiator)  )
424    {
425        /* if received DISC to deactivate LLCP link as target role, send SYMM PDU */
426        llcp_link_send_SYMM ();
427    }
428    else /*  for link timeout and interface error */
429    {
430        NFC_FlushData (NFC_RF_CONN_ID);
431    }
432
433    llcp_deactivate_cleanup (reason);
434}
435
436/*******************************************************************************
437**
438** Function         llcp_link_parse_gen_bytes
439**
440** Description      Check LLCP magic number and get parameters in general bytes
441**
442** Returns          TRUE if success
443**
444*******************************************************************************/
445static BOOLEAN llcp_link_parse_gen_bytes (UINT8 gen_bytes_len, UINT8 *p_gen_bytes)
446{
447    UINT8 *p = p_gen_bytes + LLCP_MAGIC_NUMBER_LEN;
448    UINT8 length = gen_bytes_len - LLCP_MAGIC_NUMBER_LEN;
449
450    if (  (gen_bytes_len >= LLCP_MAGIC_NUMBER_LEN)
451        &&(*(p_gen_bytes) == LLCP_MAGIC_NUMBER_BYTE0)
452        &&(*(p_gen_bytes + 1) == LLCP_MAGIC_NUMBER_BYTE1)
453        &&(*(p_gen_bytes + 2) == LLCP_MAGIC_NUMBER_BYTE2)  )
454    {
455        /* in case peer didn't include these */
456        llcp_cb.lcb.peer_miu = LLCP_DEFAULT_MIU;
457        llcp_cb.lcb.peer_lto = LLCP_DEFAULT_LTO_IN_MS;
458
459        return (llcp_util_parse_link_params (length, p));
460    }
461    else /* if this is not LLCP */
462    {
463        return (FALSE);
464    }
465
466    return (TRUE);
467}
468
469/*******************************************************************************
470**
471** Function         llcp_link_version_agreement
472**
473** Description      LLCP version number agreement
474**
475** Returns          TRUE if success
476**
477*******************************************************************************/
478static BOOLEAN llcp_link_version_agreement (void)
479{
480    UINT8 peer_major_version, peer_minor_version;
481
482    peer_major_version = LLCP_GET_MAJOR_VERSION (llcp_cb.lcb.peer_version);
483    peer_minor_version = LLCP_GET_MINOR_VERSION (llcp_cb.lcb.peer_version);
484
485    if (peer_major_version < LLCP_MIN_MAJOR_VERSION)
486    {
487        LLCP_TRACE_ERROR1("llcp_link_version_agreement(): unsupported peer version number. Peer Major Version:%d", peer_major_version);
488        return FALSE;
489    }
490    else
491    {
492        if (peer_major_version == LLCP_VERSION_MAJOR)
493        {
494            llcp_cb.lcb.agreed_major_version = LLCP_VERSION_MAJOR;
495            if (peer_minor_version >= LLCP_VERSION_MINOR)
496            {
497                llcp_cb.lcb.agreed_minor_version = LLCP_VERSION_MINOR;
498            }
499            else
500            {
501                llcp_cb.lcb.agreed_minor_version = peer_minor_version;
502            }
503        }
504        else if (peer_major_version < LLCP_VERSION_MAJOR)
505        {
506            /* so far we can support backward compatibility */
507            llcp_cb.lcb.agreed_major_version = peer_major_version;
508            llcp_cb.lcb.agreed_minor_version = peer_minor_version;
509        }
510        else
511        {
512            /* let peer (higher major version) decide it */
513            llcp_cb.lcb.agreed_major_version = LLCP_VERSION_MAJOR;
514            llcp_cb.lcb.agreed_minor_version = LLCP_VERSION_MINOR;
515        }
516
517        LLCP_TRACE_DEBUG6 ("local version:%d.%d, remote version:%d.%d, agreed version:%d.%d",
518                            LLCP_VERSION_MAJOR, LLCP_VERSION_MINOR,
519                            peer_major_version, peer_minor_version,
520                            llcp_cb.lcb.agreed_major_version, llcp_cb.lcb.agreed_minor_version);
521
522        return (TRUE);
523    }
524}
525
526/*******************************************************************************
527**
528** Function         llcp_link_update_status
529**
530** Description      Notify all of service layer client link status change
531**
532** Returns          void
533**
534*******************************************************************************/
535static void llcp_link_update_status (BOOLEAN is_activated)
536{
537    tLLCP_SAP_CBACK_DATA data;
538    tLLCP_APP_CB *p_app_cb;
539    UINT8 sap;
540
541    data.link_status.event        = LLCP_SAP_EVT_LINK_STATUS;
542    data.link_status.is_activated = is_activated;
543    data.link_status.is_initiator = llcp_cb.lcb.is_initiator;
544
545    /* notify all SAP so they can create connection while link is activated */
546    for (sap = LLCP_SAP_SDP + 1; sap < LLCP_NUM_SAPS; sap++)
547    {
548        p_app_cb = llcp_util_get_app_cb (sap);
549
550        if (  (p_app_cb)
551            &&(p_app_cb->p_app_cback)  )
552        {
553            data.link_status.local_sap = sap;
554            p_app_cb->p_app_cback (&data);
555        }
556    }
557}
558
559/*******************************************************************************
560**
561** Function         llcp_link_check_congestion
562**
563** Description      Check overall congestion status
564**                  Notify to all of upper layer if congested
565**
566** Returns          void
567**
568*******************************************************************************/
569static void llcp_link_check_congestion (void)
570{
571    tLLCP_SAP_CBACK_DATA data;
572    tLLCP_APP_CB *p_app_cb;
573    UINT8 sap, idx;
574
575    if (llcp_cb.overall_tx_congested)
576    {
577        /* already congested so no need to check again */
578        return;
579    }
580
581    if (llcp_cb.total_tx_ui_pdu + llcp_cb.total_tx_i_pdu >= llcp_cb.max_num_tx_buff)
582    {
583        /* overall buffer usage is high */
584        llcp_cb.overall_tx_congested = TRUE;
585
586        LLCP_TRACE_WARNING2 ("overall tx congestion start: total_tx_ui_pdu=%d, total_tx_i_pdu=%d",
587                              llcp_cb.total_tx_ui_pdu, llcp_cb.total_tx_i_pdu);
588
589        data.congest.event        = LLCP_SAP_EVT_CONGEST;
590        data.congest.is_congested = TRUE;
591
592        /* notify logical data link congestion status */
593        data.congest.remote_sap = LLCP_INVALID_SAP;
594        data.congest.link_type  = LLCP_LINK_TYPE_LOGICAL_DATA_LINK;
595
596        for (sap = LLCP_SAP_SDP + 1; sap < LLCP_NUM_SAPS; sap++)
597        {
598            p_app_cb = llcp_util_get_app_cb (sap);
599
600            if (  (p_app_cb)
601                &&(p_app_cb->p_app_cback)
602                &&(p_app_cb->link_type & LLCP_LINK_TYPE_LOGICAL_DATA_LINK)  )
603            {
604                /* if already congested then no need to notify again */
605                if (!p_app_cb->is_ui_tx_congested)
606                {
607                    p_app_cb->is_ui_tx_congested = TRUE;
608
609                    LLCP_TRACE_WARNING2 ("Logical link (SAP=0x%X) congestion start: count=%d",
610                                          sap, p_app_cb->ui_xmit_q.count);
611
612                    data.congest.local_sap = sap;
613                    p_app_cb->p_app_cback (&data);
614                }
615            }
616        }
617
618        /* notify data link connection congestion status */
619        data.congest.link_type  = LLCP_LINK_TYPE_DATA_LINK_CONNECTION;
620
621        for (idx = 0; idx < LLCP_MAX_DATA_LINK; idx++ )
622        {
623            if (  (llcp_cb.dlcb[idx].state == LLCP_DLC_STATE_CONNECTED)
624                &&(llcp_cb.dlcb[idx].remote_busy == FALSE)
625                &&(llcp_cb.dlcb[idx].is_tx_congested == FALSE)  )
626            {
627                llcp_cb.dlcb[idx].is_tx_congested = TRUE;
628
629                LLCP_TRACE_WARNING3 ("Data link (SSAP:DSAP=0x%X:0x%X) congestion start: count=%d",
630                                      llcp_cb.dlcb[idx].local_sap, llcp_cb.dlcb[idx].remote_sap,
631                                      llcp_cb.dlcb[idx].i_xmit_q.count);
632
633                data.congest.local_sap  = llcp_cb.dlcb[idx].local_sap;
634                data.congest.remote_sap = llcp_cb.dlcb[idx].remote_sap;
635
636                (*llcp_cb.dlcb[idx].p_app_cb->p_app_cback) (&data);
637            }
638        }
639    }
640}
641
642/*******************************************************************************
643**
644** Function         llcp_link_check_uncongested
645**
646** Description      Check overall congestion status, logical data link and
647**                  data link connection congestion status
648**                  Notify to each upper layer if uncongested
649**
650** Returns          void
651**
652*******************************************************************************/
653static void llcp_link_check_uncongested (void)
654{
655    tLLCP_SAP_CBACK_DATA data;
656    tLLCP_APP_CB *p_app_cb;
657    UINT8 xx, sap, idx;
658
659    if (llcp_cb.overall_tx_congested)
660    {
661        if (llcp_cb.total_tx_ui_pdu + llcp_cb.total_tx_i_pdu <= llcp_cb.max_num_tx_buff / 2)
662        {
663            /* overall congestion is cleared */
664            llcp_cb.overall_tx_congested = FALSE;
665
666            LLCP_TRACE_WARNING2 ("overall tx congestion end: total_tx_ui_pdu=%d, total_tx_i_pdu=%d",
667                                  llcp_cb.total_tx_ui_pdu, llcp_cb.total_tx_i_pdu);
668        }
669        else
670        {
671            /* wait until more data packets are sent out */
672            return;
673        }
674    }
675
676    data.congest.event        = LLCP_SAP_EVT_CONGEST;
677    data.congest.is_congested = FALSE;
678
679    /* if total number of UI PDU is below threshold */
680    if (llcp_cb.total_tx_ui_pdu < llcp_cb.max_num_ll_tx_buff)
681    {
682        /* check and notify logical data link congestion status */
683        data.congest.remote_sap = LLCP_INVALID_SAP;
684        data.congest.link_type  = LLCP_LINK_TYPE_LOGICAL_DATA_LINK;
685
686        /*
687        ** start point of uncongested status notification is in round robin
688        ** so each logical data link has equal chance of transmitting.
689        */
690        sap = llcp_cb.ll_tx_uncongest_ntf_start_sap;
691
692        for (xx = LLCP_SAP_SDP + 1; xx < LLCP_NUM_SAPS; xx++)
693        {
694            /* no logical data link on LM and SDP */
695            if (sap > LLCP_SAP_SDP)
696            {
697                p_app_cb = llcp_util_get_app_cb (sap);
698
699                if (  (p_app_cb)
700                    &&(p_app_cb->p_app_cback)
701                    &&(p_app_cb->link_type & LLCP_LINK_TYPE_LOGICAL_DATA_LINK)
702                    &&(p_app_cb->is_ui_tx_congested)
703                    &&(p_app_cb->ui_xmit_q.count <= llcp_cb.ll_tx_congest_end)  )
704                {
705                    /* if it was congested but now tx queue count is below threshold */
706                    p_app_cb->is_ui_tx_congested = FALSE;
707
708                    LLCP_TRACE_DEBUG2 ("Logical link (SAP=0x%X) congestion end: count=%d",
709                                        sap, p_app_cb->ui_xmit_q.count);
710
711                    data.congest.local_sap = sap;
712                    p_app_cb->p_app_cback (&data);
713                }
714            }
715
716            sap = (sap + 1) % LLCP_NUM_SAPS;
717        }
718
719        /* move start point for next logical data link */
720        for (xx = 0; xx < LLCP_NUM_SAPS; xx++)
721        {
722            sap = (llcp_cb.ll_tx_uncongest_ntf_start_sap + 1) % LLCP_NUM_SAPS;
723
724            if (sap > LLCP_SAP_SDP)
725            {
726                p_app_cb = llcp_util_get_app_cb (sap);
727
728                if (  (p_app_cb)
729                    &&(p_app_cb->p_app_cback)
730                    &&(p_app_cb->link_type & LLCP_LINK_TYPE_LOGICAL_DATA_LINK)  )
731                {
732                    llcp_cb.ll_tx_uncongest_ntf_start_sap = sap;
733                    break;
734                }
735            }
736        }
737    }
738
739    /* notify data link connection congestion status */
740    data.congest.link_type  = LLCP_LINK_TYPE_DATA_LINK_CONNECTION;
741
742    /*
743    ** start point of uncongested status notification is in round robin
744    ** so each data link connection has equal chance of transmitting.
745    */
746    idx = llcp_cb.dl_tx_uncongest_ntf_start_idx;
747
748    for (xx = 0; xx < LLCP_MAX_DATA_LINK; xx++ )
749    {
750        /* if it was congested but now tx queue is below threshold (receiving window) */
751        if (  (llcp_cb.dlcb[idx].state == LLCP_DLC_STATE_CONNECTED)
752            &&(llcp_cb.dlcb[idx].is_tx_congested)
753            &&(llcp_cb.dlcb[idx].i_xmit_q.count <= llcp_cb.dlcb[idx].remote_rw / 2)  )
754        {
755            llcp_cb.dlcb[idx].is_tx_congested = FALSE;
756
757            if (llcp_cb.dlcb[idx].remote_busy == FALSE)
758            {
759                LLCP_TRACE_DEBUG3 ("Data link (SSAP:DSAP=0x%X:0x%X) congestion end: count=%d",
760                                    llcp_cb.dlcb[idx].local_sap, llcp_cb.dlcb[idx].remote_sap,
761                                    llcp_cb.dlcb[idx].i_xmit_q.count);
762
763                data.congest.local_sap  = llcp_cb.dlcb[idx].local_sap;
764                data.congest.remote_sap = llcp_cb.dlcb[idx].remote_sap;
765
766                (*llcp_cb.dlcb[idx].p_app_cb->p_app_cback) (&data);
767            }
768        }
769        idx = (idx + 1) % LLCP_MAX_DATA_LINK;
770    }
771
772    /* move start point for next data link connection */
773    for (xx = 0; xx < LLCP_MAX_DATA_LINK; xx++ )
774    {
775        idx = (llcp_cb.dl_tx_uncongest_ntf_start_idx + 1) % LLCP_MAX_DATA_LINK;
776        if (llcp_cb.dlcb[idx].state == LLCP_DLC_STATE_CONNECTED)
777        {
778            llcp_cb.dl_tx_uncongest_ntf_start_idx = idx;
779            break;
780        }
781    }
782}
783
784/*******************************************************************************
785**
786** Function         llcp_link_send_SYMM
787**
788** Description      Send SYMM PDU
789**
790** Returns          void
791**
792*******************************************************************************/
793static void llcp_link_send_SYMM (void)
794{
795    BT_HDR *p_msg;
796    UINT8  *p;
797
798    p_msg = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID);
799
800    if (p_msg)
801    {
802        p_msg->len    = LLCP_PDU_SYMM_SIZE;
803        p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
804
805        p = (UINT8 *) (p_msg + 1) + p_msg->offset;
806        UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (LLCP_SAP_LM, LLCP_PDU_SYMM_TYPE, LLCP_SAP_LM ));
807
808        llcp_link_send_to_lower (p_msg);
809    }
810}
811
812/*******************************************************************************
813**
814** Function         llcp_link_check_send_data
815**
816** Description      Send PDU to peer
817**
818** Returns          void
819**
820*******************************************************************************/
821void llcp_link_check_send_data (void)
822{
823    BT_HDR *p_pdu;
824
825    /* don't re-enter while processing to prevent out of sequence */
826    if (llcp_cb.lcb.is_sending_data)
827        return;
828    else
829        llcp_cb.lcb.is_sending_data = TRUE;
830
831    /*
832    ** check overall congestion due to high usage of buffer pool
833    ** if congested then notify all of upper layers not to send any more data
834    */
835    llcp_link_check_congestion ();
836
837    if (llcp_cb.lcb.symm_state == LLCP_LINK_SYMM_LOCAL_XMIT_NEXT)
838    {
839        LLCP_TRACE_DEBUG0 ("llcp_link_check_send_data () in state of LLCP_LINK_SYMM_LOCAL_XMIT_NEXT");
840
841        p_pdu = llcp_link_build_next_pdu (NULL);
842
843        /*
844        ** For data link connection,
845        ** V(RA) was updated and N(R) was set to V(RA), if I PDU was added in this transmission.
846        ** If there was no I PDU to carry V(RA) and V(RA) is not V(R) and it's not congested,
847        ** then RR PDU will be sent.
848        ** If there was no I PDU to carry V(RA) and V(RA) is not V(R) and it's congested,
849        ** then RNR PDU will be sent.
850        ** If local busy state has been changed then RR or RNR PDU may be sent.
851        */
852        llcp_dlc_check_to_send_rr_rnr ();
853
854        /* add RR/RNR PDU to be sent if any */
855        p_pdu = llcp_link_build_next_pdu (p_pdu);
856
857        if (p_pdu != NULL)
858        {
859            llcp_link_send_to_lower (p_pdu);
860
861            /* stop inactivity timer */
862            llcp_link_stop_inactivity_timer ();
863
864            /* check congestion status after sending out some data */
865            llcp_link_check_uncongested ();
866        }
867        else
868        {
869            /* There is no data to send, so send SYMM */
870            if (llcp_cb.lcb.link_state == LLCP_LINK_STATE_ACTIVATED)
871            {
872                if (llcp_cb.lcb.symm_delay > 0)
873                {
874                    /* wait for application layer sending data */
875                    llcp_link_start_link_timer ();
876                    llcp_cb.lcb.is_sending_data = FALSE;
877                    return;
878                }
879                else
880                {
881                    llcp_link_send_SYMM ();
882
883                    /* start inactivity timer */
884                    if (llcp_cb.num_data_link_connection == 0)
885                    {
886                        llcp_link_start_inactivity_timer ();
887                    }
888                }
889            }
890            else
891            {
892                llcp_cb.lcb.is_sending_data = FALSE;
893                return;
894            }
895        }
896
897        if (llcp_cb.lcb.link_state == LLCP_LINK_STATE_DEACTIVATING)
898        {
899            /* wait for short period for NFCC to send DISC */
900            nfc_start_quick_timer (&llcp_cb.lcb.timer, NFC_TTYPE_LLCP_LINK_MANAGER,
901                                   ((UINT32) 50) * QUICK_TIMER_TICKS_PER_SEC / 1000);
902        }
903        else
904        {
905            /* wait for data to receive from remote */
906            llcp_link_start_link_timer ();
907        }
908    }
909
910    llcp_cb.lcb.is_sending_data = FALSE;
911}
912
913/*******************************************************************************
914**
915** Function         llcp_link_proc_ui_pdu
916**
917** Description      Process UI PDU from peer device
918**
919** Returns          None
920**
921*******************************************************************************/
922static void llcp_link_proc_ui_pdu (UINT8  local_sap,
923                                   UINT8  remote_sap,
924                                   UINT16 ui_pdu_length,
925                                   UINT8  *p_ui_pdu,
926                                   BT_HDR *p_msg)
927{
928    BOOLEAN      appended;
929    BT_HDR       *p_last_buf;
930    UINT16       available_bytes;
931    UINT8        *p_dst;
932    tLLCP_APP_CB *p_app_cb;
933    tLLCP_SAP_CBACK_DATA data;
934    tLLCP_DLCB   *p_dlcb;
935
936    p_app_cb = llcp_util_get_app_cb (local_sap);
937        /*if UI PDU sent to SAP with data link connection*/
938    if ((p_dlcb = llcp_dlc_find_dlcb_by_sap (local_sap, remote_sap)))
939    {
940        llcp_util_send_frmr (p_dlcb, LLCP_FRMR_W_ERROR_FLAG, LLCP_PDU_UI_TYPE, 0);
941        llcp_dlsm_execute (p_dlcb, LLCP_DLC_EVENT_FRAME_ERROR, NULL);
942        if (p_msg)
943        {
944            GKI_freebuf (p_msg);
945        }
946        return;
947    }
948
949    /* if application is registered and expecting UI PDU on logical data link */
950    if (  (p_app_cb)
951        &&(p_app_cb->p_app_cback)
952        &&(p_app_cb->link_type & LLCP_LINK_TYPE_LOGICAL_DATA_LINK)  )
953    {
954        LLCP_TRACE_DEBUG2 ("llcp_link_proc_ui_pdu () Local SAP:0x%x, Remote SAP:0x%x", local_sap, remote_sap);
955
956        /* if this is not from AGF PDU */
957        if (p_msg)
958        {
959            ui_pdu_length = p_msg->len; /* including LLCP header */
960            p_ui_pdu      = (UINT8*) (p_msg + 1) + p_msg->offset;
961        }
962
963        appended = FALSE;
964
965        /* get last buffer in rx queue */
966        p_last_buf = (BT_HDR *) GKI_getlast (&p_app_cb->ui_rx_q);
967
968        if (p_last_buf)
969        {
970            /* get max length to append at the end of buffer */
971            available_bytes = GKI_get_buf_size (p_last_buf) - BT_HDR_SIZE - p_last_buf->offset - p_last_buf->len;
972
973            /* if new UI PDU with length can be attached at the end of buffer */
974            if (available_bytes >= LLCP_PDU_AGF_LEN_SIZE + ui_pdu_length)
975            {
976                p_dst = (UINT8*) (p_last_buf + 1) + p_last_buf->offset + p_last_buf->len;
977
978                /* add length of UI PDU */
979                UINT16_TO_BE_STREAM (p_dst, ui_pdu_length);
980
981                /* copy UI PDU with LLCP header */
982                memcpy (p_dst, p_ui_pdu, ui_pdu_length);
983
984                p_last_buf->len += LLCP_PDU_AGF_LEN_SIZE + ui_pdu_length;
985
986                if (p_msg)
987                    GKI_freebuf (p_msg);
988
989                appended = TRUE;
990            }
991        }
992
993        /* if it is not available to append */
994        if (!appended)
995        {
996            /* if it's not from AGF PDU */
997            if (p_msg)
998            {
999                /* add length of PDU in front of UI PDU (reuse room for NCI header) */
1000                p_ui_pdu -= LLCP_PDU_AGF_LEN_SIZE;
1001                UINT16_TO_BE_STREAM (p_ui_pdu, ui_pdu_length);
1002
1003                p_msg->offset -= LLCP_PDU_AGF_LEN_SIZE;
1004                p_msg->len    += LLCP_PDU_AGF_LEN_SIZE;
1005                p_msg->layer_specific = 0;
1006            }
1007            else
1008            {
1009                p_msg = (BT_HDR *) GKI_getpoolbuf (LLCP_POOL_ID);
1010
1011                if (p_msg)
1012                {
1013                    p_dst = (UINT8*) (p_msg + 1);
1014
1015                    /* add length of PDU in front of UI PDU */
1016                    UINT16_TO_BE_STREAM (p_dst, ui_pdu_length);
1017
1018                    memcpy (p_dst, p_ui_pdu, ui_pdu_length);
1019
1020                    p_msg->offset = 0;
1021                    p_msg->len    = LLCP_PDU_AGF_LEN_SIZE + ui_pdu_length;
1022                    p_msg->layer_specific = 0;
1023                }
1024                else
1025                {
1026                    LLCP_TRACE_ERROR0 ("llcp_link_proc_ui_pdu (): out of buffer");
1027                }
1028            }
1029
1030            /* insert UI PDU in rx queue */
1031            if (p_msg)
1032            {
1033                GKI_enqueue (&p_app_cb->ui_rx_q, p_msg);
1034                llcp_cb.total_rx_ui_pdu++;
1035            }
1036        }
1037
1038        if (p_app_cb->ui_rx_q.count > llcp_cb.ll_rx_congest_start)
1039        {
1040            LLCP_TRACE_WARNING2 ("llcp_link_proc_ui_pdu (): SAP:0x%x, rx link is congested (%d), discard oldest UI PDU",
1041                                 local_sap, p_app_cb->ui_rx_q.count);
1042
1043            GKI_freebuf (GKI_dequeue (&p_app_cb->ui_rx_q));
1044            llcp_cb.total_rx_ui_pdu--;
1045        }
1046
1047        if ((p_app_cb->ui_rx_q.count == 1) && (appended == FALSE))
1048        {
1049            data.data_ind.event         = LLCP_SAP_EVT_DATA_IND;
1050            data.data_ind.local_sap     = local_sap;
1051            data.data_ind.remote_sap    = remote_sap;
1052            data.data_ind.link_type     = LLCP_LINK_TYPE_LOGICAL_DATA_LINK;
1053            (*p_app_cb->p_app_cback) (&data);
1054        }
1055    }
1056    else
1057    {
1058        LLCP_TRACE_ERROR1 ("llcp_link_proc_ui_pdu (): Unregistered SAP:0x%x", local_sap);
1059
1060        if (p_msg)
1061        {
1062            GKI_freebuf (p_msg);
1063        }
1064    }
1065}
1066
1067/*******************************************************************************
1068**
1069** Function         llcp_link_proc_agf_pdu
1070**
1071** Description      Process AGF PDU from peer device
1072**
1073** Returns          void
1074**
1075*******************************************************************************/
1076static void llcp_link_proc_agf_pdu (BT_HDR *p_agf)
1077{
1078    UINT16 agf_length;
1079    UINT8 *p, *p_info, *p_pdu_length;
1080    UINT16 pdu_hdr, pdu_length;
1081    UINT8  dsap, ptype, ssap;
1082
1083    p_agf->len    -= LLCP_PDU_HEADER_SIZE;
1084    p_agf->offset += LLCP_PDU_HEADER_SIZE;
1085
1086    /*
1087    ** check integrity of AGF PDU and get number of PDUs in AGF PDU
1088    */
1089    agf_length = p_agf->len;
1090    p = (UINT8 *) (p_agf + 1) + p_agf->offset;
1091
1092    while (agf_length > 0)
1093    {
1094        if (agf_length > LLCP_PDU_AGF_LEN_SIZE)
1095        {
1096            BE_STREAM_TO_UINT16 (pdu_length, p);
1097            agf_length -= LLCP_PDU_AGF_LEN_SIZE;
1098        }
1099        else
1100        {
1101            break;
1102        }
1103
1104        if (pdu_length <= agf_length)
1105        {
1106            p += pdu_length;
1107            agf_length -= pdu_length;
1108        }
1109        else
1110        {
1111            break;
1112        }
1113    }
1114
1115    if (agf_length != 0)
1116    {
1117        LLCP_TRACE_ERROR0 ("llcp_link_proc_agf_pdu (): Received invalid AGF PDU");
1118        GKI_freebuf (p_agf);
1119        return;
1120    }
1121
1122    /*
1123    ** Process PDUs in AGF
1124    */
1125    agf_length = p_agf->len;
1126    p = (UINT8 *) (p_agf + 1) + p_agf->offset;
1127
1128    while (agf_length > 0)
1129    {
1130        /* get length of PDU */
1131        p_pdu_length = p;
1132        BE_STREAM_TO_UINT16 (pdu_length, p);
1133        agf_length -= LLCP_PDU_AGF_LEN_SIZE;
1134
1135        /* get DSAP/PTYPE/SSAP */
1136        p_info = p;
1137        BE_STREAM_TO_UINT16 (pdu_hdr, p_info );
1138
1139        dsap  = LLCP_GET_DSAP (pdu_hdr);
1140        ptype = (UINT8) (LLCP_GET_PTYPE (pdu_hdr));
1141        ssap  = LLCP_GET_SSAP (pdu_hdr);
1142
1143#if (BT_TRACE_VERBOSE == TRUE)
1144        LLCP_TRACE_DEBUG4 ("llcp_link_proc_agf_pdu (): Rx DSAP:0x%x, PTYPE:%s (0x%x), SSAP:0x%x in AGF",
1145                           dsap, llcp_pdu_type (ptype), ptype, ssap);
1146#endif
1147
1148        if (  (ptype == LLCP_PDU_DISC_TYPE)
1149            &&(dsap == LLCP_SAP_LM)
1150            &&(ssap == LLCP_SAP_LM)  )
1151        {
1152            GKI_freebuf (p_agf);
1153            llcp_link_deactivate (LLCP_LINK_REMOTE_INITIATED);
1154            return;
1155        }
1156        else if (ptype == LLCP_PDU_SYMM_TYPE)
1157        {
1158            LLCP_TRACE_ERROR0 ("llcp_link_proc_agf_pdu (): SYMM PDU exchange shall not be in AGF");
1159        }
1160        else if (ptype == LLCP_PDU_PAX_TYPE)
1161        {
1162            LLCP_TRACE_ERROR0 ("llcp_link_proc_agf_pdu (): PAX PDU exchange shall not be used");
1163        }
1164        else if (ptype == LLCP_PDU_SNL_TYPE)
1165        {
1166            llcp_sdp_proc_snl ((UINT16) (pdu_length - LLCP_PDU_HEADER_SIZE), p_info);
1167        }
1168        else if ((ptype == LLCP_PDU_UI_TYPE) && (pdu_length > LLCP_PDU_HEADER_SIZE))
1169        {
1170            llcp_link_proc_ui_pdu (dsap, ssap, pdu_length, p, NULL);
1171        }
1172        else if (ptype == LLCP_PDU_I_TYPE)
1173        {
1174            llcp_dlc_proc_i_pdu (dsap, ssap, pdu_length, p, NULL);
1175        }
1176        else /* let data link connection handle PDU */
1177        {
1178            llcp_dlc_proc_rx_pdu (dsap, ptype, ssap, (UINT16) (pdu_length - LLCP_PDU_HEADER_SIZE), p_info);
1179        }
1180
1181        p += pdu_length;
1182        agf_length -= pdu_length;
1183    }
1184
1185    GKI_freebuf (p_agf);
1186}
1187
1188/*******************************************************************************
1189**
1190** Function         llcp_link_proc_rx_pdu
1191**
1192** Description      Process received PDU from peer device
1193**
1194** Returns          void
1195**
1196*******************************************************************************/
1197static void llcp_link_proc_rx_pdu (UINT8 dsap, UINT8 ptype, UINT8 ssap, BT_HDR *p_msg)
1198{
1199    BOOLEAN free_buffer = TRUE;
1200    UINT8   *p_data;
1201
1202    switch (ptype)
1203    {
1204    case LLCP_PDU_PAX_TYPE:
1205        LLCP_TRACE_ERROR0 ("llcp_link_proc_rx_pdu (); PAX PDU exchange shall not be used");
1206        break;
1207
1208    case LLCP_PDU_DISC_TYPE:
1209        if ((dsap == LLCP_SAP_LM) && (ssap == LLCP_SAP_LM))
1210        {
1211            llcp_link_deactivate (LLCP_LINK_REMOTE_INITIATED);
1212        }
1213        else
1214        {
1215            p_data = (UINT8 *) (p_msg + 1) + p_msg->offset + LLCP_PDU_HEADER_SIZE;
1216            llcp_dlc_proc_rx_pdu (dsap, ptype, ssap, (UINT16) (p_msg->len - LLCP_PDU_HEADER_SIZE), p_data);
1217        }
1218        break;
1219
1220    case LLCP_PDU_SNL_TYPE:
1221        p_data = (UINT8 *) (p_msg + 1) + p_msg->offset + LLCP_PDU_HEADER_SIZE;
1222        llcp_sdp_proc_snl ((UINT16) (p_msg->len - LLCP_PDU_HEADER_SIZE), p_data);
1223        break;
1224
1225    case LLCP_PDU_AGF_TYPE:
1226        llcp_link_proc_agf_pdu (p_msg);
1227        free_buffer = FALSE;
1228        break;
1229
1230    case LLCP_PDU_UI_TYPE:
1231        llcp_link_proc_ui_pdu (dsap, ssap, 0, NULL, p_msg);
1232        free_buffer = FALSE;
1233        break;
1234
1235    case LLCP_PDU_I_TYPE:
1236        llcp_dlc_proc_i_pdu (dsap, ssap, 0, NULL, p_msg);
1237        free_buffer = FALSE;
1238        break;
1239
1240    default:
1241        p_data = (UINT8 *) (p_msg + 1) + p_msg->offset + LLCP_PDU_HEADER_SIZE;
1242        llcp_dlc_proc_rx_pdu (dsap, ptype, ssap, (UINT16) (p_msg->len - LLCP_PDU_HEADER_SIZE), p_data);
1243        break;
1244    }
1245
1246    if (free_buffer)
1247        GKI_freebuf (p_msg);
1248}
1249
1250/*******************************************************************************
1251**
1252** Function         llcp_link_proc_rx_data
1253**
1254** Description      Process received data from NFCC and maintain symmetry state
1255**
1256** Returns          void
1257**
1258*******************************************************************************/
1259static void llcp_link_proc_rx_data (BT_HDR *p_msg)
1260{
1261    UINT8  *p;
1262    UINT16  pdu_hdr, info_length = 0;
1263    UINT8   dsap, ptype, ssap;
1264    BOOLEAN free_buffer = TRUE;
1265    BOOLEAN frame_error = FALSE;
1266
1267    if (llcp_cb.lcb.symm_state == LLCP_LINK_SYMM_REMOTE_XMIT_NEXT)
1268    {
1269        llcp_link_stop_link_timer ();
1270
1271        if (  (llcp_cb.lcb.link_state == LLCP_LINK_STATE_DEACTIVATING)
1272            &&(llcp_cb.lcb.sig_xmit_q.count == 0)  )
1273        {
1274            /* this indicates that DISC PDU had been sent out to peer */
1275            /* initiator may wait for SYMM PDU */
1276            llcp_link_process_link_timeout ();
1277        }
1278        else
1279        {
1280            if (p_msg->len < LLCP_PDU_HEADER_SIZE)
1281            {
1282                LLCP_TRACE_ERROR1 ("Received too small PDU: got %d bytes", p_msg->len);
1283                frame_error = TRUE;
1284            }
1285            else
1286            {
1287                p = (UINT8 *) (p_msg + 1) + p_msg->offset;
1288                BE_STREAM_TO_UINT16 (pdu_hdr, p );
1289
1290                dsap  = LLCP_GET_DSAP (pdu_hdr);
1291                ptype = (UINT8) (LLCP_GET_PTYPE (pdu_hdr));
1292                ssap  = LLCP_GET_SSAP (pdu_hdr);
1293
1294                /* get length of information per PDU type */
1295                if (  (ptype == LLCP_PDU_I_TYPE)
1296                    ||(ptype == LLCP_PDU_RR_TYPE)
1297                    ||(ptype == LLCP_PDU_RNR_TYPE)  )
1298                {
1299                    if (p_msg->len >= LLCP_PDU_HEADER_SIZE + LLCP_SEQUENCE_SIZE)
1300                    {
1301                        info_length = p_msg->len - LLCP_PDU_HEADER_SIZE - LLCP_SEQUENCE_SIZE;
1302                    }
1303                    else
1304                    {
1305                        LLCP_TRACE_ERROR0 ("Received I/RR/RNR PDU without sequence");
1306                        frame_error = TRUE;
1307                    }
1308                }
1309                else
1310                {
1311                    info_length = p_msg->len - LLCP_PDU_HEADER_SIZE;
1312                }
1313
1314                /* check if length of information is bigger than link MIU */
1315                if ((!frame_error) && (info_length > llcp_cb.lcb.local_link_miu))
1316                {
1317                    LLCP_TRACE_ERROR2 ("Received exceeding MIU (%d): got %d bytes SDU",
1318                                       llcp_cb.lcb.local_link_miu, info_length);
1319
1320                    frame_error = TRUE;
1321                }
1322                else
1323                {
1324#if (BT_TRACE_VERBOSE == TRUE)
1325                    LLCP_TRACE_DEBUG4 ("llcp_link_proc_rx_data (): DSAP:0x%x, PTYPE:%s (0x%x), SSAP:0x%x",
1326                                       dsap, llcp_pdu_type (ptype), ptype, ssap);
1327#endif
1328
1329                    if (ptype == LLCP_PDU_SYMM_TYPE)
1330                    {
1331                        if (info_length > 0)
1332                        {
1333                            LLCP_TRACE_ERROR1 ("Received extra data (%d bytes) in SYMM PDU", info_length);
1334                            frame_error = TRUE;
1335                        }
1336                    }
1337                    else
1338                    {
1339                        /* received other than SYMM */
1340                        llcp_link_stop_inactivity_timer ();
1341
1342                        llcp_link_proc_rx_pdu (dsap, ptype, ssap, p_msg);
1343                        free_buffer = FALSE;
1344                    }
1345                }
1346            }
1347
1348            llcp_cb.lcb.symm_state = LLCP_LINK_SYMM_LOCAL_XMIT_NEXT;
1349
1350            /* check if any pending packet */
1351            llcp_link_check_send_data ();
1352        }
1353    }
1354    else
1355    {
1356        LLCP_TRACE_ERROR0 ("Received PDU in state of SYMM_MUST_XMIT_NEXT");
1357    }
1358
1359    if (free_buffer)
1360        GKI_freebuf (p_msg);
1361}
1362
1363/*******************************************************************************
1364**
1365** Function         llcp_link_get_next_pdu
1366**
1367** Description      Get next PDU from link manager or data links w/wo dequeue
1368**
1369** Returns          pointer of a PDU to send if length_only is FALSE
1370**                  NULL otherwise
1371**
1372*******************************************************************************/
1373static BT_HDR *llcp_link_get_next_pdu (BOOLEAN length_only, UINT16 *p_next_pdu_length)
1374{
1375    BT_HDR *p_msg;
1376    int     count, xx;
1377    tLLCP_APP_CB *p_app_cb;
1378
1379    /* processing signalling PDU first */
1380    if (llcp_cb.lcb.sig_xmit_q.p_first)
1381    {
1382        if (length_only)
1383        {
1384            p_msg = (BT_HDR*) llcp_cb.lcb.sig_xmit_q.p_first;
1385            *p_next_pdu_length = p_msg->len;
1386            return NULL;
1387        }
1388        else
1389            p_msg = (BT_HDR*) GKI_dequeue (&llcp_cb.lcb.sig_xmit_q);
1390
1391        return p_msg;
1392    }
1393    else
1394    {
1395        /* transmitting logical data link and data link connection equaly */
1396        for (xx = 0; xx < 2; xx++)
1397        {
1398            if (!llcp_cb.lcb.ll_served)
1399            {
1400                /* Get one from logical link connection */
1401                for (count = 0; count < LLCP_NUM_SAPS; count++)
1402                {
1403                    /* round robin schedule without priority  */
1404                    p_app_cb = llcp_util_get_app_cb (llcp_cb.lcb.ll_idx);
1405
1406                    if (  (p_app_cb)
1407                        &&(p_app_cb->p_app_cback)
1408                        &&(p_app_cb->ui_xmit_q.count)  )
1409                    {
1410                        if (length_only)
1411                        {
1412                            /* don't alternate next data link to return the same length of PDU */
1413                            p_msg = (BT_HDR *) p_app_cb->ui_xmit_q.p_first;
1414                            *p_next_pdu_length = p_msg->len;
1415                            return NULL;
1416                        }
1417                        else
1418                        {
1419                            /* check data link connection first in next time */
1420                            llcp_cb.lcb.ll_served = !llcp_cb.lcb.ll_served;
1421
1422                            p_msg = (BT_HDR*) GKI_dequeue (&p_app_cb->ui_xmit_q);
1423                            llcp_cb.total_tx_ui_pdu--;
1424
1425                            /* this logical link has been served, so start from next logical link next time */
1426                            llcp_cb.lcb.ll_idx = (llcp_cb.lcb.ll_idx + 1) % LLCP_NUM_SAPS;
1427
1428                            return p_msg;
1429                        }
1430                    }
1431                    else
1432                    {
1433                        /* check next logical link connection */
1434                        llcp_cb.lcb.ll_idx = (llcp_cb.lcb.ll_idx + 1) % LLCP_NUM_SAPS;
1435                    }
1436                }
1437
1438                /* no data, so check data link connection if not checked yet */
1439                llcp_cb.lcb.ll_served = !llcp_cb.lcb.ll_served;
1440            }
1441            else
1442            {
1443                /* Get one from data link connection */
1444                for (count = 0; count < LLCP_MAX_DATA_LINK; count++)
1445                {
1446                    /* round robin schedule without priority  */
1447                    if (llcp_cb.dlcb[llcp_cb.lcb.dl_idx].state != LLCP_DLC_STATE_IDLE)
1448                    {
1449                        if (length_only)
1450                        {
1451                            *p_next_pdu_length = llcp_dlc_get_next_pdu_length (&llcp_cb.dlcb[llcp_cb.lcb.dl_idx]);
1452
1453                            if (*p_next_pdu_length > 0 )
1454                            {
1455                                /* don't change data link connection to return the same length of PDU */
1456                                return NULL;
1457                            }
1458                            else
1459                            {
1460                                /* no data, so check next data link connection */
1461                                llcp_cb.lcb.dl_idx = (llcp_cb.lcb.dl_idx + 1) % LLCP_MAX_DATA_LINK;
1462                            }
1463                        }
1464                        else
1465                        {
1466                            p_msg = llcp_dlc_get_next_pdu (&llcp_cb.dlcb[llcp_cb.lcb.dl_idx]);
1467
1468                            /* this data link has been served, so start from next data link next time */
1469                            llcp_cb.lcb.dl_idx = (llcp_cb.lcb.dl_idx + 1) % LLCP_MAX_DATA_LINK;
1470
1471                            if (p_msg)
1472                            {
1473                                /* serve logical data link next time */
1474                                llcp_cb.lcb.ll_served = !llcp_cb.lcb.ll_served;
1475                                return p_msg;
1476                            }
1477                        }
1478                    }
1479                    else
1480                    {
1481                        /* check next data link connection */
1482                        llcp_cb.lcb.dl_idx = (llcp_cb.lcb.dl_idx + 1) % LLCP_MAX_DATA_LINK;
1483                    }
1484                }
1485
1486                /* if all of data link connection doesn't have data to send */
1487                if (count >= LLCP_MAX_DATA_LINK)
1488                {
1489                    llcp_cb.lcb.ll_served = !llcp_cb.lcb.ll_served;
1490                }
1491            }
1492        }
1493    }
1494
1495    /* nothing to send */
1496    *p_next_pdu_length = 0;
1497    return NULL;
1498}
1499
1500/*******************************************************************************
1501**
1502** Function         llcp_link_build_next_pdu
1503**
1504** Description      Build a PDU from Link Manager and Data Link
1505**                  Perform aggregation procedure if necessary
1506**
1507** Returns          BT_HDR* if sent any PDU
1508**
1509*******************************************************************************/
1510static BT_HDR *llcp_link_build_next_pdu (BT_HDR *p_pdu)
1511{
1512    BT_HDR *p_agf = NULL, *p_msg = NULL, *p_next_pdu;
1513    UINT8  *p, ptype;
1514    UINT16  next_pdu_length, pdu_hdr;
1515
1516    LLCP_TRACE_DEBUG0 ("llcp_link_build_next_pdu ()");
1517
1518    /* add any pending SNL PDU into sig_xmit_q for transmitting */
1519    llcp_sdp_check_send_snl ();
1520
1521    if (p_pdu)
1522    {
1523        /* get PDU type */
1524        p = (UINT8 *) (p_pdu + 1) + p_pdu->offset;
1525        BE_STREAM_TO_UINT16 (pdu_hdr, p);
1526
1527        ptype = (UINT8) (LLCP_GET_PTYPE (pdu_hdr));
1528
1529        if (ptype == LLCP_PDU_AGF_TYPE)
1530        {
1531            /* add more PDU into this AGF PDU */
1532            p_agf = p_pdu;
1533        }
1534        else
1535        {
1536            p_msg = p_pdu;
1537        }
1538    }
1539    else
1540    {
1541        /* Get a PDU from link manager or data links */
1542        p_msg = llcp_link_get_next_pdu (FALSE, &next_pdu_length);
1543
1544        if (!p_msg)
1545        {
1546            return NULL;
1547        }
1548    }
1549
1550    /* Get length of next PDU from link manager or data links without dequeue */
1551    llcp_link_get_next_pdu (TRUE, &next_pdu_length);
1552    while (next_pdu_length > 0)
1553    {
1554        /* if it's first visit */
1555        if (!p_agf)
1556        {
1557            /* if next PDU fits into MIU, allocate AGF PDU and copy the first PDU */
1558            if (2 + p_msg->len + 2 + next_pdu_length <= llcp_cb.lcb.effective_miu)
1559            {
1560                p_agf = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID);
1561                if (p_agf)
1562                {
1563                    p_agf->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
1564
1565                    p = (UINT8 *) (p_agf + 1) + p_agf->offset;
1566
1567                    UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (LLCP_SAP_LM, LLCP_PDU_AGF_TYPE, LLCP_SAP_LM ));
1568                    UINT16_TO_BE_STREAM (p, p_msg->len);
1569                    memcpy(p, (UINT8 *) (p_msg + 1) + p_msg->offset, p_msg->len);
1570
1571                    p_agf->len      = LLCP_PDU_HEADER_SIZE + 2 + p_msg->len;
1572
1573                    GKI_freebuf (p_msg);
1574                    p_msg = p_agf;
1575                }
1576                else
1577                {
1578                    LLCP_TRACE_ERROR0 ("llcp_link_build_next_pdu (): Out of buffer");
1579                    return p_msg;
1580                }
1581            }
1582            else
1583            {
1584                break;
1585            }
1586        }
1587
1588        /* if next PDU fits into MIU, copy the next PDU into AGF */
1589        if (p_agf->len - LLCP_PDU_HEADER_SIZE + 2 + next_pdu_length <= llcp_cb.lcb.effective_miu)
1590        {
1591            /* Get a next PDU from link manager or data links */
1592            p_next_pdu = llcp_link_get_next_pdu (FALSE, &next_pdu_length);
1593
1594            p = (UINT8 *) (p_agf + 1) + p_agf->offset + p_agf->len;
1595
1596            UINT16_TO_BE_STREAM (p, p_next_pdu->len);
1597            memcpy (p, (UINT8 *) (p_next_pdu + 1) + p_next_pdu->offset, p_next_pdu->len);
1598
1599            p_agf->len += 2 + p_next_pdu->len;
1600
1601            GKI_freebuf (p_next_pdu);
1602
1603            /* Get next PDU length from link manager or data links without dequeue */
1604            llcp_link_get_next_pdu (TRUE, &next_pdu_length);
1605        }
1606        else
1607        {
1608            break;
1609        }
1610    }
1611
1612    if (p_agf)
1613        return p_agf;
1614    else
1615        return p_msg;
1616}
1617
1618/*******************************************************************************
1619**
1620** Function         llcp_link_send_to_lower
1621**
1622** Description      Send PDU to lower layer
1623**
1624** Returns          void
1625**
1626*******************************************************************************/
1627static void llcp_link_send_to_lower (BT_HDR *p_pdu)
1628{
1629#if (BT_TRACE_PROTOCOL == TRUE)
1630    DispLLCP (p_pdu, FALSE);
1631#endif
1632
1633    llcp_cb.lcb.symm_state = LLCP_LINK_SYMM_REMOTE_XMIT_NEXT;
1634
1635    NFC_SendData (NFC_RF_CONN_ID, p_pdu);
1636}
1637
1638/*******************************************************************************
1639**
1640** Function         llcp_link_connection_cback
1641**
1642** Description      processing incoming data
1643**
1644** Returns          void
1645**
1646*******************************************************************************/
1647void llcp_link_connection_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data)
1648{
1649    if (event == NFC_DATA_CEVT)
1650    {
1651#if (BT_TRACE_PROTOCOL == TRUE)
1652        DispLLCP ((BT_HDR *)p_data->data.p_data, TRUE);
1653#endif
1654        if (llcp_cb.lcb.link_state == LLCP_LINK_STATE_DEACTIVATED)
1655        {
1656            /* respoding SYMM while LLCP is deactivated but RF link is not deactivated yet */
1657            llcp_link_send_SYMM ();
1658            GKI_freebuf ((BT_HDR *) p_data->data.p_data);
1659        }
1660        else
1661        {
1662            llcp_link_proc_rx_data ((BT_HDR *) p_data->data.p_data);
1663        }
1664    }
1665    else if (event == NFC_ERROR_CEVT)
1666    {
1667        /* RF interface specific status code */
1668        llcp_link_deactivate (*(UINT8*) p_data);
1669    }
1670    else if (event == NFC_DEACTIVATE_CEVT)
1671    {
1672        if (  (llcp_cb.lcb.link_state == LLCP_LINK_STATE_DEACTIVATING)
1673            &&(!llcp_cb.lcb.is_initiator)  )
1674        {
1675            /* peer initiates NFC link deactivation before timeout */
1676            llcp_link_stop_link_timer ();
1677            llcp_link_process_link_timeout ();
1678        }
1679        else if (llcp_cb.lcb.link_state != LLCP_LINK_STATE_DEACTIVATED)
1680        {
1681            llcp_link_deactivate (LLCP_LINK_RF_LINK_LOSS_ERR);
1682        }
1683        NFC_SetStaticRfCback (NULL);
1684    }
1685
1686    /* LLCP ignores the following events
1687
1688        NFC_CONN_CREATE_CEVT
1689        NFC_CONN_CLOSE_CEVT
1690    */
1691}
1692
1693#if (BT_TRACE_VERBOSE == TRUE)
1694/*******************************************************************************
1695**
1696** Function         llcp_pdu_type
1697**
1698** Description
1699**
1700** Returns          string of PDU type
1701**
1702*******************************************************************************/
1703static char *llcp_pdu_type (UINT8 ptype)
1704{
1705    switch(ptype)
1706    {
1707    case LLCP_PDU_SYMM_TYPE:
1708        return "SYMM";
1709    case LLCP_PDU_PAX_TYPE:
1710        return "PAX";
1711    case LLCP_PDU_AGF_TYPE:
1712        return "AGF";
1713    case LLCP_PDU_UI_TYPE:
1714        return "UI";
1715    case LLCP_PDU_CONNECT_TYPE:
1716        return "CONNECT";
1717    case LLCP_PDU_DISC_TYPE:
1718        return "DISC";
1719    case LLCP_PDU_CC_TYPE:
1720        return "CC";
1721    case LLCP_PDU_DM_TYPE:
1722        return "DM";
1723    case LLCP_PDU_FRMR_TYPE:
1724        return "FRMR";
1725    case LLCP_PDU_SNL_TYPE:
1726        return "SNL";
1727    case LLCP_PDU_I_TYPE:
1728        return "I";
1729    case LLCP_PDU_RR_TYPE:
1730        return "RR";
1731    case LLCP_PDU_RNR_TYPE:
1732        return "RNR";
1733
1734    default:
1735        return "RESERVED";
1736    }
1737}
1738
1739#endif
1740
1741