• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 utilities
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 
34 /*******************************************************************************
35 **
36 ** Function         llcp_util_parse_link_params
37 **
38 ** Description      Parse LLCP Link parameters
39 **
40 ** Returns          TRUE if success
41 **
42 *******************************************************************************/
llcp_util_parse_link_params(UINT16 length,UINT8 * p_bytes)43 BOOLEAN llcp_util_parse_link_params (UINT16 length, UINT8 *p_bytes)
44 {
45     UINT8 param_type, param_len, *p = p_bytes;
46 
47     while (length)
48     {
49         BE_STREAM_TO_UINT8 (param_type, p);
50         length--;
51 
52         switch (param_type)
53         {
54         case LLCP_VERSION_TYPE:
55             BE_STREAM_TO_UINT8 (param_len, p);
56             BE_STREAM_TO_UINT8 (llcp_cb.lcb.peer_version, p);
57             LLCP_TRACE_DEBUG1 ("Peer Version - 0x%02X", llcp_cb.lcb.peer_version);
58             break;
59 
60         case LLCP_MIUX_TYPE:
61             BE_STREAM_TO_UINT8 (param_len, p);
62             BE_STREAM_TO_UINT16 (llcp_cb.lcb.peer_miu, p);
63             llcp_cb.lcb.peer_miu &= LLCP_MIUX_MASK;
64             llcp_cb.lcb.peer_miu += LLCP_DEFAULT_MIU;
65             LLCP_TRACE_DEBUG1 ("Peer MIU - %d bytes", llcp_cb.lcb.peer_miu);
66             break;
67 
68         case LLCP_WKS_TYPE:
69             BE_STREAM_TO_UINT8 (param_len, p);
70             BE_STREAM_TO_UINT16 (llcp_cb.lcb.peer_wks, p);
71             LLCP_TRACE_DEBUG1 ("Peer WKS - 0x%04X", llcp_cb.lcb.peer_wks);
72             break;
73 
74         case LLCP_LTO_TYPE:
75             BE_STREAM_TO_UINT8 (param_len, p);
76             BE_STREAM_TO_UINT8 (llcp_cb.lcb.peer_lto, p);
77             llcp_cb.lcb.peer_lto *= LLCP_LTO_UNIT;  /* 10ms unit */
78             LLCP_TRACE_DEBUG1 ("Peer LTO - %d ms", llcp_cb.lcb.peer_lto);
79             break;
80 
81         case LLCP_OPT_TYPE:
82             BE_STREAM_TO_UINT8 (param_len, p);
83             BE_STREAM_TO_UINT8 (llcp_cb.lcb.peer_opt, p);
84             LLCP_TRACE_DEBUG1 ("Peer OPT - 0x%02X", llcp_cb.lcb.peer_opt);
85             break;
86 
87         default:
88             LLCP_TRACE_ERROR1 ("llcp_util_parse_link_params (): Unexpected type 0x%x", param_type);
89             BE_STREAM_TO_UINT8 (param_len, p);
90             p += param_len;
91             break;
92         }
93 
94         if (length >= param_len + 1)
95             length -= param_len + 1;
96         else
97         {
98             LLCP_TRACE_ERROR0 ("llcp_util_parse_link_params (): Bad LTV's");
99             return (FALSE);
100         }
101     }
102     return (TRUE);
103 }
104 
105 /*******************************************************************************
106 **
107 ** Function         llcp_util_adjust_ll_congestion
108 **
109 ** Description      adjust tx/rx congestion thresholds on logical link
110 **
111 ** Returns          void
112 **
113 *******************************************************************************/
llcp_util_adjust_ll_congestion(void)114 void llcp_util_adjust_ll_congestion (void)
115 {
116     /* buffer quota is allocated equally for each logical data link */
117     if (llcp_cb.num_logical_data_link)
118     {
119         llcp_cb.ll_tx_congest_start = llcp_cb.max_num_ll_tx_buff / llcp_cb.num_logical_data_link;
120         llcp_cb.ll_rx_congest_start = llcp_cb.max_num_ll_rx_buff / llcp_cb.num_logical_data_link;
121     }
122     else
123     {
124         llcp_cb.ll_tx_congest_start = llcp_cb.max_num_ll_tx_buff;
125         llcp_cb.ll_rx_congest_start = llcp_cb.max_num_ll_rx_buff;
126     }
127 
128     /* at least one for each logical data link */
129     if (llcp_cb.ll_tx_congest_start == 0)
130     {
131         llcp_cb.ll_tx_congest_start = 1;
132     }
133     if (llcp_cb.ll_rx_congest_start == 0)
134     {
135         llcp_cb.ll_rx_congest_start = 1;
136     }
137 
138     if (llcp_cb.ll_tx_congest_start > 1)
139     {
140         llcp_cb.ll_tx_congest_end = 1;
141     }
142     else
143     {
144         llcp_cb.ll_tx_congest_end = 0;
145     }
146 
147     LLCP_TRACE_DEBUG4 ("num_logical_data_link=%d, ll_tx_congest_start=%d, ll_tx_congest_end=%d, ll_rx_congest_start=%d",
148                        llcp_cb.num_logical_data_link,
149                        llcp_cb.ll_tx_congest_start,
150                        llcp_cb.ll_tx_congest_end,
151                        llcp_cb.ll_rx_congest_start);
152 }
153 
154 /*******************************************************************************
155 **
156 ** Function         llcp_util_adjust_dl_rx_congestion
157 **
158 ** Description      adjust rx congestion thresholds on data link
159 **
160 ** Returns          void
161 **
162 *******************************************************************************/
llcp_util_adjust_dl_rx_congestion(void)163 void llcp_util_adjust_dl_rx_congestion (void)
164 {
165     UINT8 idx, rx_congest_start;
166 
167     if (llcp_cb.num_data_link_connection)
168     {
169         rx_congest_start = llcp_cb.num_rx_buff / llcp_cb.num_data_link_connection;
170 
171         for (idx = 0; idx < LLCP_MAX_DATA_LINK; idx++)
172         {
173             if (llcp_cb.dlcb[idx].state == LLCP_DLC_STATE_CONNECTED)
174             {
175                 if (rx_congest_start > llcp_cb.dlcb[idx].local_rw)
176                 {
177                     /*
178                     ** set rx congestion threshold LLCP_DL_MIN_RX_CONGEST at least
179                     ** so, we don't need to flow off too often.
180                     */
181                     if (llcp_cb.dlcb[idx].local_rw + 1 > LLCP_DL_MIN_RX_CONGEST)
182                         llcp_cb.dlcb[idx].rx_congest_threshold = llcp_cb.dlcb[idx].local_rw + 1;
183                     else
184                         llcp_cb.dlcb[idx].rx_congest_threshold = LLCP_DL_MIN_RX_CONGEST;
185                 }
186                 else
187                 {
188                     llcp_cb.dlcb[idx].rx_congest_threshold = LLCP_DL_MIN_RX_CONGEST;
189                 }
190 
191                 LLCP_TRACE_DEBUG3 ("DLC[%d], local_rw=%d, rx_congest_threshold=%d",
192                                    idx,
193                                    llcp_cb.dlcb[idx].local_rw,
194                                    llcp_cb.dlcb[idx].rx_congest_threshold);
195             }
196         }
197     }
198 
199 }
200 
201 /*******************************************************************************
202 **
203 ** Function         llcp_util_check_rx_congested_status
204 **
205 ** Description      Update rx congested status
206 **
207 ** Returns          void
208 **
209 *******************************************************************************/
llcp_util_check_rx_congested_status(void)210 void llcp_util_check_rx_congested_status (void)
211 {
212     UINT8 idx;
213 
214     if (llcp_cb.overall_rx_congested)
215     {
216         /* check if rx congestion clear */
217         if (llcp_cb.total_rx_ui_pdu + llcp_cb.total_rx_i_pdu <= llcp_cb.overall_rx_congest_end)
218         {
219             LLCP_TRACE_DEBUG3 ("llcp_util_check_rx_congested_status (): rx link is uncongested, %d+%d <= %d",
220                                 llcp_cb.total_rx_ui_pdu, llcp_cb.total_rx_i_pdu,
221                                 llcp_cb.overall_rx_congest_end);
222 
223             llcp_cb.overall_rx_congested = FALSE;
224 
225             for (idx = 0; idx < LLCP_MAX_DATA_LINK; idx++)
226             {
227                 /* set flag to clear local busy status on data link connections */
228                 if (  (llcp_cb.dlcb[idx].state == LLCP_DLC_STATE_CONNECTED)
229                     &&(llcp_cb.dlcb[idx].is_rx_congested == FALSE)  )
230                 {
231                     llcp_cb.dlcb[idx].flags |= LLCP_DATA_LINK_FLAG_PENDING_RR_RNR;
232                 }
233             }
234         }
235     }
236     else
237     {
238         /* check if rx link is congested */
239         if (llcp_cb.total_rx_ui_pdu + llcp_cb.total_rx_i_pdu >= llcp_cb.overall_rx_congest_start)
240         {
241             LLCP_TRACE_WARNING3 ("llcp_util_check_rx_congested_status (): rx link is congested, %d+%d >= %d",
242                                   llcp_cb.total_rx_ui_pdu, llcp_cb.total_rx_i_pdu,
243                                   llcp_cb.overall_rx_congest_start);
244 
245             llcp_cb.overall_rx_congested = TRUE;
246 
247             /* rx link congestion is started, send RNR to remote end point */
248             for (idx = 0; idx < LLCP_MAX_DATA_LINK; idx++)
249             {
250                 if (  (llcp_cb.dlcb[idx].state == LLCP_DLC_STATE_CONNECTED)
251                     &&(llcp_cb.dlcb[idx].is_rx_congested == FALSE)  )
252                 {
253                     llcp_cb.dlcb[idx].flags |= LLCP_DATA_LINK_FLAG_PENDING_RR_RNR;
254                 }
255             }
256         }
257     }
258 }
259 
260 /*******************************************************************************
261 **
262 ** Function         llcp_util_send_ui
263 **
264 ** Description      Send UI PDU
265 **
266 ** Returns          tLLCP_STATUS
267 **
268 *******************************************************************************/
llcp_util_send_ui(UINT8 ssap,UINT8 dsap,tLLCP_APP_CB * p_app_cb,BT_HDR * p_msg)269 tLLCP_STATUS llcp_util_send_ui (UINT8 ssap, UINT8 dsap, tLLCP_APP_CB *p_app_cb, BT_HDR *p_msg)
270 {
271     UINT8        *p;
272     tLLCP_STATUS status = LLCP_STATUS_SUCCESS;
273 
274     p_msg->offset -= LLCP_PDU_HEADER_SIZE;
275     p_msg->len    += LLCP_PDU_HEADER_SIZE;
276 
277     p = (UINT8 *) (p_msg + 1) + p_msg->offset;
278     UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (dsap, LLCP_PDU_UI_TYPE, ssap));
279 
280     GKI_enqueue (&p_app_cb->ui_xmit_q, p_msg);
281     llcp_cb.total_tx_ui_pdu++;
282 
283     llcp_link_check_send_data ();
284 
285     if (  (p_app_cb->is_ui_tx_congested)
286         ||(p_app_cb->ui_xmit_q.count >= llcp_cb.ll_tx_congest_start)
287         ||(llcp_cb.overall_tx_congested)
288         ||(llcp_cb.total_tx_ui_pdu >= llcp_cb.max_num_ll_tx_buff)  )
289     {
290         /* set congested here so overall congestion check routine will not report event again, */
291         /* or notify uncongestion later                                                        */
292         p_app_cb->is_ui_tx_congested = TRUE;
293 
294         LLCP_TRACE_WARNING2 ("Logical link (SAP=0x%X) congested: ui_xmit_q.count=%d",
295                               ssap, p_app_cb->ui_xmit_q.count);
296 
297         status = LLCP_STATUS_CONGESTED;
298     }
299 
300     return status;
301 }
302 
303 /*******************************************************************************
304 **
305 ** Function         llcp_util_send_disc
306 **
307 ** Description      Send DISC PDU
308 **
309 ** Returns          void
310 **
311 *******************************************************************************/
llcp_util_send_disc(UINT8 dsap,UINT8 ssap)312 void llcp_util_send_disc (UINT8 dsap, UINT8 ssap)
313 {
314     BT_HDR *p_msg;
315     UINT8  *p;
316 
317     p_msg = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID);
318 
319     if (p_msg)
320     {
321         p_msg->len      = LLCP_PDU_DISC_SIZE;
322         p_msg->offset   = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
323 
324         p = (UINT8 *) (p_msg + 1) + p_msg->offset;
325         UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (dsap, LLCP_PDU_DISC_TYPE, ssap));
326 
327         GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, p_msg);
328         llcp_link_check_send_data ();
329     }
330 }
331 
332 /*******************************************************************************
333 **
334 ** Function         llcp_util_allocate_data_link
335 **
336 ** Description      Allocate tLLCP_DLCB for data link connection
337 **
338 ** Returns          tLLCP_DLCB *
339 **
340 ******************************************************************************/
llcp_util_allocate_data_link(UINT8 reg_sap,UINT8 remote_sap)341 tLLCP_DLCB *llcp_util_allocate_data_link (UINT8 reg_sap, UINT8 remote_sap)
342 {
343     tLLCP_DLCB *p_dlcb = NULL;
344     int         idx;
345 
346     LLCP_TRACE_DEBUG2 ("llcp_util_allocate_data_link (): reg_sap = 0x%x, remote_sap = 0x%x",
347                         reg_sap, remote_sap);
348 
349     for (idx = 0; idx < LLCP_MAX_DATA_LINK; idx++)
350     {
351         if (llcp_cb.dlcb[idx].state == LLCP_DLC_STATE_IDLE)
352         {
353             p_dlcb = &(llcp_cb.dlcb[idx]);
354 
355             memset (p_dlcb, 0, sizeof (tLLCP_DLCB));
356             break;
357         }
358     }
359 
360     if (!p_dlcb)
361     {
362         LLCP_TRACE_ERROR0 ("llcp_util_allocate_data_link (): Out of DLCB");
363     }
364     else
365     {
366         p_dlcb->p_app_cb    = llcp_util_get_app_cb (reg_sap);
367         p_dlcb->local_sap   = reg_sap;
368         p_dlcb->remote_sap  = remote_sap;
369         p_dlcb->timer.param = (TIMER_PARAM_TYPE) p_dlcb;
370 
371         /* this is for inactivity timer and congestion control. */
372         llcp_cb.num_data_link_connection++;
373 
374         LLCP_TRACE_DEBUG3 ("llcp_util_allocate_data_link (): local_sap = 0x%x, remote_sap = 0x%x, num_data_link_connection = %d",
375                             p_dlcb->local_sap, p_dlcb->remote_sap, llcp_cb.num_data_link_connection);
376     }
377     return p_dlcb;
378 }
379 
380 /*******************************************************************************
381 **
382 ** Function         llcp_util_deallocate_data_link
383 **
384 ** Description      Deallocate tLLCP_DLCB
385 **
386 ** Returns          void
387 **
388 ******************************************************************************/
llcp_util_deallocate_data_link(tLLCP_DLCB * p_dlcb)389 void llcp_util_deallocate_data_link (tLLCP_DLCB *p_dlcb)
390 {
391     if (p_dlcb)
392     {
393         LLCP_TRACE_DEBUG1 ("llcp_util_deallocate_data_link (): local_sap = 0x%x", p_dlcb->local_sap);
394 
395         if (p_dlcb->state != LLCP_DLC_STATE_IDLE)
396         {
397             nfc_stop_quick_timer (&p_dlcb->timer);
398             llcp_dlc_flush_q (p_dlcb);
399 
400             p_dlcb->state = LLCP_DLC_STATE_IDLE;
401 
402             if (llcp_cb.num_data_link_connection > 0)
403             {
404                 llcp_cb.num_data_link_connection--;
405             }
406 
407             LLCP_TRACE_DEBUG1 ("llcp_util_deallocate_data_link (): num_data_link_connection = %d", llcp_cb.num_data_link_connection);
408         }
409     }
410 }
411 
412 /*******************************************************************************
413 **
414 ** Function         llcp_util_send_connect
415 **
416 ** Description      Send CONNECT PDU
417 **
418 ** Returns          tLLCP_STATUS
419 **
420 ******************************************************************************/
llcp_util_send_connect(tLLCP_DLCB * p_dlcb,tLLCP_CONNECTION_PARAMS * p_params)421 tLLCP_STATUS llcp_util_send_connect (tLLCP_DLCB *p_dlcb, tLLCP_CONNECTION_PARAMS *p_params)
422 {
423     BT_HDR *p_msg;
424     UINT8  *p;
425     UINT16  miu_len = 0, rw_len = 0, sn_len = 0;
426 
427     if (p_params->miu != LLCP_DEFAULT_MIU)
428     {
429         miu_len = 4;    /* TYPE, LEN, 2 bytes MIU */
430     }
431     if (p_params->rw != LLCP_DEFAULT_RW)
432     {
433         rw_len = 3;     /* TYPE, LEN, 1 byte RW */
434         p_params->rw &= 0x0F;   /* only 4 bits  */
435     }
436     if ((strlen (p_params->sn)) && (p_dlcb->remote_sap == LLCP_SAP_SDP))
437     {
438         sn_len = (UINT16) (2 + strlen (p_params->sn));    /* TYPE, LEN, SN */
439     }
440 
441     p_msg = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID);
442 
443     if (p_msg)
444     {
445         p_msg->len    = LLCP_PDU_HEADER_SIZE + miu_len + rw_len + sn_len;
446         p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
447 
448         p = (UINT8 *) (p_msg + 1) + p_msg->offset;
449 
450         UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (p_dlcb->remote_sap, LLCP_PDU_CONNECT_TYPE, p_dlcb->local_sap));
451 
452         if (miu_len)
453         {
454             UINT8_TO_BE_STREAM (p, LLCP_MIUX_TYPE);
455             UINT8_TO_BE_STREAM (p, LLCP_MIUX_LEN);
456             UINT16_TO_BE_STREAM (p, p_params->miu - LLCP_DEFAULT_MIU);
457         }
458 
459         if (rw_len)
460         {
461             UINT8_TO_BE_STREAM (p, LLCP_RW_TYPE);
462             UINT8_TO_BE_STREAM (p, LLCP_RW_LEN);
463             UINT8_TO_BE_STREAM (p, p_params->rw);
464         }
465 
466         if (sn_len)
467         {
468             UINT8_TO_BE_STREAM (p, LLCP_SN_TYPE);
469             UINT8_TO_BE_STREAM (p, sn_len - 2);
470             memcpy (p, p_params->sn, sn_len - 2);
471         }
472 
473         GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, p_msg);
474         llcp_link_check_send_data ();
475 
476         return LLCP_STATUS_SUCCESS;
477     }
478 
479     return LLCP_STATUS_FAIL;
480 }
481 
482 /*******************************************************************************
483 **
484 ** Function         llcp_util_parse_connect
485 **
486 ** Description      Parse CONNECT PDU
487 **
488 ** Returns          tLLCP_STATUS
489 **
490 *******************************************************************************/
llcp_util_parse_connect(UINT8 * p_bytes,UINT16 length,tLLCP_CONNECTION_PARAMS * p_params)491 tLLCP_STATUS llcp_util_parse_connect (UINT8  *p_bytes, UINT16 length, tLLCP_CONNECTION_PARAMS *p_params)
492 {
493     UINT8 param_type, param_len, *p = p_bytes;
494 
495     p_params->miu = LLCP_DEFAULT_MIU;
496     p_params->rw  = LLCP_DEFAULT_RW;
497     p_params->sn[0] = 0;
498 
499     while (length)
500     {
501         BE_STREAM_TO_UINT8 (param_type, p);
502         length--;
503 
504         switch (param_type)
505         {
506         case LLCP_MIUX_TYPE:
507             BE_STREAM_TO_UINT8 (param_len, p);
508             BE_STREAM_TO_UINT16 (p_params->miu, p);
509             p_params->miu &= LLCP_MIUX_MASK;
510             p_params->miu += LLCP_DEFAULT_MIU;
511 
512             LLCP_TRACE_DEBUG1 ("llcp_util_parse_connect (): LLCP_MIUX_TYPE:%d", p_params->miu);
513             break;
514 
515         case LLCP_RW_TYPE:
516             BE_STREAM_TO_UINT8 (param_len, p);
517             BE_STREAM_TO_UINT8 (p_params->rw, p);
518             p_params->rw &= 0x0F;
519 
520             LLCP_TRACE_DEBUG1 ("llcp_util_parse_connect (): LLCP_RW_TYPE:%d", p_params->rw);
521             break;
522 
523         case LLCP_SN_TYPE:
524             BE_STREAM_TO_UINT8 (param_len, p);
525 
526             if (param_len <= LLCP_MAX_SN_LEN)
527             {
528                 memcpy (p_params->sn, p, param_len);
529                 p_params->sn[param_len] = 0;
530             }
531             else
532             {
533                 memcpy (p_params->sn, p, LLCP_MAX_SN_LEN);
534                 p_params->sn[LLCP_MAX_SN_LEN] = 0;
535             }
536             p += param_len;
537 
538             LLCP_TRACE_DEBUG1 ("llcp_util_parse_connect (): LLCP_SN_TYPE:<%s>", p_params->sn);
539             break;
540 
541         default:
542             LLCP_TRACE_ERROR1 ("llcp_util_parse_connect (): Unexpected type 0x%x", param_type);
543             BE_STREAM_TO_UINT8 (param_len, p);
544             p += param_len;
545             break;
546         }
547 
548         /* check remaining lengh */
549         if (length >= param_len + 1)
550         {
551             length -= param_len + 1;
552         }
553         else
554         {
555             LLCP_TRACE_ERROR0 ("llcp_util_parse_connect (): Bad LTV's");
556             return LLCP_STATUS_FAIL;
557         }
558     }
559     return LLCP_STATUS_SUCCESS;
560 }
561 
562 /*******************************************************************************
563 **
564 ** Function         llcp_util_send_cc
565 **
566 ** Description      Send CC PDU
567 **
568 ** Returns          tLLCP_STATUS
569 **
570 ******************************************************************************/
llcp_util_send_cc(tLLCP_DLCB * p_dlcb,tLLCP_CONNECTION_PARAMS * p_params)571 tLLCP_STATUS llcp_util_send_cc (tLLCP_DLCB *p_dlcb, tLLCP_CONNECTION_PARAMS *p_params)
572 {
573     BT_HDR *p_msg;
574     UINT8  *p;
575     UINT16  miu_len = 0, rw_len = 0;
576 
577     if (p_params->miu != LLCP_DEFAULT_MIU)
578     {
579         miu_len = 4;
580     }
581     if (p_params->rw != LLCP_DEFAULT_RW)
582     {
583         rw_len = 3;
584         p_params->rw &= 0x0F;
585     }
586 
587     p_msg = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID);
588 
589     if (p_msg)
590     {
591         p_msg->len      = LLCP_PDU_HEADER_SIZE + miu_len + rw_len;
592         p_msg->offset   = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
593 
594         p = (UINT8 *) (p_msg + 1) + p_msg->offset;
595 
596         UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (p_dlcb->remote_sap, LLCP_PDU_CC_TYPE, p_dlcb->local_sap));
597 
598         if (miu_len)
599         {
600             UINT8_TO_BE_STREAM (p, LLCP_MIUX_TYPE);
601             UINT8_TO_BE_STREAM (p, LLCP_MIUX_LEN);
602             UINT16_TO_BE_STREAM (p, p_params->miu - LLCP_DEFAULT_MIU);
603         }
604 
605         if (rw_len)
606         {
607             UINT8_TO_BE_STREAM (p, LLCP_RW_TYPE);
608             UINT8_TO_BE_STREAM (p, LLCP_RW_LEN);
609             UINT8_TO_BE_STREAM (p, p_params->rw);
610         }
611 
612         GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, p_msg);
613         llcp_link_check_send_data ();
614 
615         return LLCP_STATUS_SUCCESS;
616     }
617 
618     return LLCP_STATUS_FAIL;
619 }
620 
621 /*******************************************************************************
622 **
623 ** Function         llcp_util_parse_cc
624 **
625 ** Description      Parse CC PDU
626 **
627 ** Returns          tLLCP_STATUS
628 **
629 *******************************************************************************/
llcp_util_parse_cc(UINT8 * p_bytes,UINT16 length,UINT16 * p_miu,UINT8 * p_rw)630 tLLCP_STATUS llcp_util_parse_cc (UINT8 *p_bytes, UINT16 length, UINT16 *p_miu, UINT8 *p_rw)
631 {
632     UINT8 param_type, param_len, *p = p_bytes;
633 
634     *p_miu = LLCP_DEFAULT_MIU;
635     *p_rw  = LLCP_DEFAULT_RW;
636 
637     while (length)
638     {
639         BE_STREAM_TO_UINT8 (param_type, p);
640         length--;
641 
642         switch (param_type)
643         {
644         case LLCP_MIUX_TYPE:
645             BE_STREAM_TO_UINT8 (param_len, p);
646             BE_STREAM_TO_UINT16 ((*p_miu), p);
647             (*p_miu) &= LLCP_MIUX_MASK;
648             (*p_miu) += LLCP_DEFAULT_MIU;
649 
650             LLCP_TRACE_DEBUG1 ("llcp_util_parse_cc (): LLCP_MIUX_TYPE:%d", *p_miu);
651             break;
652 
653         case LLCP_RW_TYPE:
654             BE_STREAM_TO_UINT8 (param_len, p);
655             BE_STREAM_TO_UINT8 ((*p_rw), p);
656             (*p_rw) &= 0x0F;
657 
658             LLCP_TRACE_DEBUG1 ("llcp_util_parse_cc (): LLCP_RW_TYPE:%d", *p_rw);
659             break;
660 
661         default:
662             LLCP_TRACE_ERROR1 ("llcp_util_parse_cc (): Unexpected type 0x%x", param_type);
663             BE_STREAM_TO_UINT8 (param_len, p);
664             p += param_len;
665             break;
666         }
667 
668         if (length >= param_len + 1)
669             length -= param_len + 1;
670         else
671         {
672             LLCP_TRACE_ERROR0 ("llcp_util_parse_cc (): Bad LTV's");
673             return LLCP_STATUS_FAIL;
674         }
675     }
676     return LLCP_STATUS_SUCCESS;
677 }
678 
679 /*******************************************************************************
680 **
681 ** Function         llcp_util_send_dm
682 **
683 ** Description      Send DM PDU
684 **
685 ** Returns          void
686 **
687 *******************************************************************************/
llcp_util_send_dm(UINT8 dsap,UINT8 ssap,UINT8 reason)688 void llcp_util_send_dm (UINT8 dsap, UINT8 ssap, UINT8 reason)
689 {
690     BT_HDR *p_msg;
691     UINT8  *p;
692 
693     p_msg = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID);
694 
695     if (p_msg)
696     {
697         p_msg->len    = LLCP_PDU_DM_SIZE;
698         p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
699 
700         p = (UINT8 *) (p_msg + 1) + p_msg->offset;
701         UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (dsap, LLCP_PDU_DM_TYPE, ssap));
702         UINT8_TO_BE_STREAM  (p, reason);
703 
704         GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, p_msg);
705         llcp_link_check_send_data ();
706     }
707 }
708 
709 /*******************************************************************************
710 **
711 ** Function         llcp_util_build_info_pdu
712 **
713 ** Description      Add DSAP, PTYPE, SSAP and sequence numbers and update local ack
714 **                  sequence
715 **
716 ** Returns          void
717 **
718 *******************************************************************************/
llcp_util_build_info_pdu(tLLCP_DLCB * p_dlcb,BT_HDR * p_msg)719 void llcp_util_build_info_pdu (tLLCP_DLCB *p_dlcb, BT_HDR *p_msg)
720 {
721     UINT8  *p;
722     UINT8  rcv_seq;
723 
724     p_msg->offset -= LLCP_PDU_HEADER_SIZE + LLCP_SEQUENCE_SIZE;
725     p_msg->len    += LLCP_PDU_HEADER_SIZE + LLCP_SEQUENCE_SIZE;
726     p = (UINT8 *) (p_msg + 1) + p_msg->offset;
727 
728     UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (p_dlcb->remote_sap, LLCP_PDU_I_TYPE, p_dlcb->local_sap));
729 
730     /* if local_busy or rx congested then do not update receive sequence number to flow off */
731     if (  (p_dlcb->local_busy)
732         ||(p_dlcb->is_rx_congested)
733         ||(llcp_cb.overall_rx_congested)  )
734     {
735         rcv_seq = p_dlcb->sent_ack_seq;
736     }
737     else
738     {
739         p_dlcb->sent_ack_seq = p_dlcb->next_rx_seq;
740         rcv_seq = p_dlcb->sent_ack_seq;
741     }
742     UINT8_TO_BE_STREAM  (p, LLCP_GET_SEQUENCE (p_dlcb->next_tx_seq, rcv_seq));
743 }
744 
745 /*******************************************************************************
746 **
747 ** Function         llcp_util_send_frmr
748 **
749 ** Description      Send FRMR PDU
750 **
751 ** Returns          tLLCP_STATUS
752 **
753 *******************************************************************************/
llcp_util_send_frmr(tLLCP_DLCB * p_dlcb,UINT8 flags,UINT8 ptype,UINT8 sequence)754 tLLCP_STATUS llcp_util_send_frmr (tLLCP_DLCB *p_dlcb, UINT8 flags, UINT8 ptype, UINT8 sequence)
755 {
756     BT_HDR *p_msg;
757     UINT8  *p;
758 
759     p_msg = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID);
760 
761     if (p_msg)
762     {
763         p_msg->len      = LLCP_PDU_FRMR_SIZE;
764         p_msg->offset   = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
765 
766         p = (UINT8 *) (p_msg + 1) + p_msg->offset;
767 
768         UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (p_dlcb->remote_sap, LLCP_PDU_FRMR_TYPE, p_dlcb->local_sap));
769         UINT8_TO_BE_STREAM (p, (flags << 4) | ptype);
770         UINT8_TO_BE_STREAM (p, sequence);
771         UINT8_TO_BE_STREAM (p, (p_dlcb->next_tx_seq << 4) | p_dlcb->next_rx_seq);
772         UINT8_TO_BE_STREAM (p, (p_dlcb->rcvd_ack_seq << 4) | p_dlcb->sent_ack_seq);
773 
774         GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, p_msg);
775         llcp_link_check_send_data ();
776 
777         return LLCP_STATUS_SUCCESS;
778     }
779     else
780     {
781         LLCP_TRACE_ERROR0 ("llcp_util_send_frmr (): Out of resource");
782         return LLCP_STATUS_FAIL;
783     }
784 }
785 
786 /*******************************************************************************
787 **
788 ** Function         llcp_util_send_rr_rnr
789 **
790 ** Description      Send RR or RNR PDU
791 **
792 ** Returns          void
793 **
794 *******************************************************************************/
llcp_util_send_rr_rnr(tLLCP_DLCB * p_dlcb)795 void llcp_util_send_rr_rnr (tLLCP_DLCB *p_dlcb)
796 {
797     BT_HDR *p_msg;
798     UINT8  *p;
799     UINT8   pdu_type;
800     UINT8   pdu_size;
801     UINT8   rcv_seq;
802 
803     /* if no indication of change in local busy or rx congestion */
804     if ((p_dlcb->flags & LLCP_DATA_LINK_FLAG_PENDING_RR_RNR) == 0)
805     {
806         /* if all ack is sent */
807         if (p_dlcb->sent_ack_seq == p_dlcb->next_rx_seq)
808         {
809             /* we don't need to send RR/RNR */
810             return;
811         }
812         else
813         {
814             /* if rx flow off because of local busy or congestion */
815             if (  (p_dlcb->local_busy)
816                 ||(p_dlcb->is_rx_congested)
817                 ||(llcp_cb.overall_rx_congested)  )
818             {
819                 /* don't send RR/RNR */
820                 return;
821             }
822         }
823     }
824 
825     if (  (p_dlcb->local_busy)
826         ||(p_dlcb->is_rx_congested)
827         ||(llcp_cb.overall_rx_congested)  )
828     {
829         LLCP_TRACE_DEBUG3 ("llcp_util_send_rr_rnr (): local_busy=%d,is_rx_congested=%d,overall_rx_congested=%d",
830                             p_dlcb->local_busy, p_dlcb->is_rx_congested, llcp_cb.overall_rx_congested);
831 
832         /* if local_busy or rx congested then do not update receive sequence number to flow off */
833         pdu_type = LLCP_PDU_RNR_TYPE;
834         pdu_size = LLCP_PDU_RNR_SIZE;
835         rcv_seq = p_dlcb->sent_ack_seq;
836     }
837     else
838     {
839         pdu_type = LLCP_PDU_RR_TYPE;
840         pdu_size = LLCP_PDU_RR_SIZE;
841 
842         p_dlcb->sent_ack_seq = p_dlcb->next_rx_seq;
843         rcv_seq = p_dlcb->sent_ack_seq;
844     }
845 
846     p_msg = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID);
847 
848     if (p_msg)
849     {
850         p_dlcb->flags &= ~LLCP_DATA_LINK_FLAG_PENDING_RR_RNR;
851 
852         p_msg->len    = pdu_size;
853         p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
854 
855         p = (UINT8 *) (p_msg + 1) + p_msg->offset;
856 
857         UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (p_dlcb->remote_sap, pdu_type, p_dlcb->local_sap));
858 
859         UINT8_TO_BE_STREAM (p, rcv_seq);
860 
861 #if (BT_TRACE_VERBOSE == TRUE)
862         LLCP_TRACE_DEBUG5 ("LLCP TX - N(S,R):(NA,%d) V(S,SA,R,RA):(%d,%d,%d,%d)",
863                             p_dlcb->next_rx_seq,
864                             p_dlcb->next_tx_seq, p_dlcb->rcvd_ack_seq,
865                             p_dlcb->next_rx_seq, p_dlcb->sent_ack_seq);
866 #endif
867         GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, p_msg);
868         llcp_link_check_send_data ();
869     }
870     else
871     {
872         LLCP_TRACE_ERROR0 ("llcp_util_send_rr_rnr (): Out of resource");
873     }
874 }
875 
876 /*******************************************************************************
877 **
878 ** Function         llcp_util_get_app_cb
879 **
880 ** Description      get pointer of application registered control block by SAP
881 **
882 ** Returns          tLLCP_APP_CB *
883 **
884 *******************************************************************************/
llcp_util_get_app_cb(UINT8 local_sap)885 tLLCP_APP_CB *llcp_util_get_app_cb (UINT8 local_sap)
886 {
887     tLLCP_APP_CB *p_app_cb = NULL;
888 
889     if (local_sap <= LLCP_UPPER_BOUND_WK_SAP)
890     {
891         if ((local_sap != LLCP_SAP_LM) && (local_sap < LLCP_MAX_WKS))
892         {
893             p_app_cb = &llcp_cb.wks_cb[local_sap];
894         }
895     }
896     else if (local_sap <= LLCP_UPPER_BOUND_SDP_SAP)
897     {
898         if (local_sap - LLCP_LOWER_BOUND_SDP_SAP < LLCP_MAX_SERVER)
899         {
900             p_app_cb = &llcp_cb.server_cb[local_sap - LLCP_LOWER_BOUND_SDP_SAP];
901         }
902     }
903     else if (local_sap <= LLCP_UPPER_BOUND_LOCAL_SAP)
904     {
905         if (local_sap - LLCP_LOWER_BOUND_LOCAL_SAP < LLCP_MAX_CLIENT)
906         {
907             p_app_cb = &llcp_cb.client_cb[local_sap - LLCP_LOWER_BOUND_LOCAL_SAP];
908         }
909     }
910 
911     return (p_app_cb);
912 }
913