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