• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2010-2014 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 
20 /******************************************************************************
21  *
22  *  This file contains the LLCP 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     p_params->sn[1] = 0;
500 
501     while (length)
502     {
503         BE_STREAM_TO_UINT8 (param_type, p);
504         length--;
505 
506         switch (param_type)
507         {
508         case LLCP_MIUX_TYPE:
509             BE_STREAM_TO_UINT8 (param_len, p);
510             BE_STREAM_TO_UINT16 (p_params->miu, p);
511             p_params->miu &= LLCP_MIUX_MASK;
512             p_params->miu += LLCP_DEFAULT_MIU;
513 
514             LLCP_TRACE_DEBUG1 ("llcp_util_parse_connect (): LLCP_MIUX_TYPE:%d", p_params->miu);
515             break;
516 
517         case LLCP_RW_TYPE:
518             BE_STREAM_TO_UINT8 (param_len, p);
519             BE_STREAM_TO_UINT8 (p_params->rw, p);
520             p_params->rw &= 0x0F;
521 
522             LLCP_TRACE_DEBUG1 ("llcp_util_parse_connect (): LLCP_RW_TYPE:%d", p_params->rw);
523             break;
524 
525         case LLCP_SN_TYPE:
526             BE_STREAM_TO_UINT8 (param_len, p);
527 
528             if (param_len == 0)
529             {
530                 /* indicate that SN type is included without SN */
531                 p_params->sn[1] = LLCP_SN_TYPE;
532             }
533             else if (param_len <= LLCP_MAX_SN_LEN)
534             {
535                 memcpy (p_params->sn, p, param_len);
536                 p_params->sn[param_len] = 0;
537             }
538             else
539             {
540                 memcpy (p_params->sn, p, LLCP_MAX_SN_LEN);
541                 p_params->sn[LLCP_MAX_SN_LEN] = 0;
542             }
543             p += param_len;
544 
545             LLCP_TRACE_DEBUG1 ("llcp_util_parse_connect (): LLCP_SN_TYPE:<%s>", p_params->sn);
546             break;
547 
548         default:
549             LLCP_TRACE_ERROR1 ("llcp_util_parse_connect (): Unexpected type 0x%x", param_type);
550             BE_STREAM_TO_UINT8 (param_len, p);
551             p += param_len;
552             break;
553         }
554 
555         /* check remaining lengh */
556         if (length >= param_len + 1)
557         {
558             length -= param_len + 1;
559         }
560         else
561         {
562             LLCP_TRACE_ERROR0 ("llcp_util_parse_connect (): Bad LTV's");
563             return LLCP_STATUS_FAIL;
564         }
565     }
566     return LLCP_STATUS_SUCCESS;
567 }
568 
569 /*******************************************************************************
570 **
571 ** Function         llcp_util_send_cc
572 **
573 ** Description      Send CC PDU
574 **
575 ** Returns          tLLCP_STATUS
576 **
577 ******************************************************************************/
llcp_util_send_cc(tLLCP_DLCB * p_dlcb,tLLCP_CONNECTION_PARAMS * p_params)578 tLLCP_STATUS llcp_util_send_cc (tLLCP_DLCB *p_dlcb, tLLCP_CONNECTION_PARAMS *p_params)
579 {
580     BT_HDR *p_msg;
581     UINT8  *p;
582     UINT16  miu_len = 0, rw_len = 0;
583 
584     if (p_params->miu != LLCP_DEFAULT_MIU)
585     {
586         miu_len = 4;
587     }
588     if (p_params->rw != LLCP_DEFAULT_RW)
589     {
590         rw_len = 3;
591         p_params->rw &= 0x0F;
592     }
593 
594     p_msg = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID);
595 
596     if (p_msg)
597     {
598         p_msg->len      = LLCP_PDU_HEADER_SIZE + miu_len + rw_len;
599         p_msg->offset   = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
600 
601         p = (UINT8 *) (p_msg + 1) + p_msg->offset;
602 
603         UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (p_dlcb->remote_sap, LLCP_PDU_CC_TYPE, p_dlcb->local_sap));
604 
605         if (miu_len)
606         {
607             UINT8_TO_BE_STREAM (p, LLCP_MIUX_TYPE);
608             UINT8_TO_BE_STREAM (p, LLCP_MIUX_LEN);
609             UINT16_TO_BE_STREAM (p, p_params->miu - LLCP_DEFAULT_MIU);
610         }
611 
612         if (rw_len)
613         {
614             UINT8_TO_BE_STREAM (p, LLCP_RW_TYPE);
615             UINT8_TO_BE_STREAM (p, LLCP_RW_LEN);
616             UINT8_TO_BE_STREAM (p, p_params->rw);
617         }
618 
619         GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, p_msg);
620         llcp_link_check_send_data ();
621 
622         return LLCP_STATUS_SUCCESS;
623     }
624 
625     return LLCP_STATUS_FAIL;
626 }
627 
628 /*******************************************************************************
629 **
630 ** Function         llcp_util_parse_cc
631 **
632 ** Description      Parse CC PDU
633 **
634 ** Returns          tLLCP_STATUS
635 **
636 *******************************************************************************/
llcp_util_parse_cc(UINT8 * p_bytes,UINT16 length,UINT16 * p_miu,UINT8 * p_rw)637 tLLCP_STATUS llcp_util_parse_cc (UINT8 *p_bytes, UINT16 length, UINT16 *p_miu, UINT8 *p_rw)
638 {
639     UINT8 param_type, param_len, *p = p_bytes;
640 
641     *p_miu = LLCP_DEFAULT_MIU;
642     *p_rw  = LLCP_DEFAULT_RW;
643 
644     while (length)
645     {
646         BE_STREAM_TO_UINT8 (param_type, p);
647         length--;
648 
649         switch (param_type)
650         {
651         case LLCP_MIUX_TYPE:
652             BE_STREAM_TO_UINT8 (param_len, p);
653             BE_STREAM_TO_UINT16 ((*p_miu), p);
654             (*p_miu) &= LLCP_MIUX_MASK;
655             (*p_miu) += LLCP_DEFAULT_MIU;
656 
657             LLCP_TRACE_DEBUG1 ("llcp_util_parse_cc (): LLCP_MIUX_TYPE:%d", *p_miu);
658             break;
659 
660         case LLCP_RW_TYPE:
661             BE_STREAM_TO_UINT8 (param_len, p);
662             BE_STREAM_TO_UINT8 ((*p_rw), p);
663             (*p_rw) &= 0x0F;
664 
665             LLCP_TRACE_DEBUG1 ("llcp_util_parse_cc (): LLCP_RW_TYPE:%d", *p_rw);
666             break;
667 
668         default:
669             LLCP_TRACE_ERROR1 ("llcp_util_parse_cc (): Unexpected type 0x%x", param_type);
670             BE_STREAM_TO_UINT8 (param_len, p);
671             p += param_len;
672             break;
673         }
674 
675         if (length >= param_len + 1)
676             length -= param_len + 1;
677         else
678         {
679             LLCP_TRACE_ERROR0 ("llcp_util_parse_cc (): Bad LTV's");
680             return LLCP_STATUS_FAIL;
681         }
682     }
683     return LLCP_STATUS_SUCCESS;
684 }
685 
686 /*******************************************************************************
687 **
688 ** Function         llcp_util_send_dm
689 **
690 ** Description      Send DM PDU
691 **
692 ** Returns          void
693 **
694 *******************************************************************************/
llcp_util_send_dm(UINT8 dsap,UINT8 ssap,UINT8 reason)695 void llcp_util_send_dm (UINT8 dsap, UINT8 ssap, UINT8 reason)
696 {
697     BT_HDR *p_msg;
698     UINT8  *p;
699 
700     p_msg = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID);
701 
702     if (p_msg)
703     {
704         p_msg->len    = LLCP_PDU_DM_SIZE;
705         p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
706 
707         p = (UINT8 *) (p_msg + 1) + p_msg->offset;
708         UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (dsap, LLCP_PDU_DM_TYPE, ssap));
709         UINT8_TO_BE_STREAM  (p, reason);
710 
711         GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, p_msg);
712         llcp_link_check_send_data ();
713     }
714 }
715 
716 /*******************************************************************************
717 **
718 ** Function         llcp_util_build_info_pdu
719 **
720 ** Description      Add DSAP, PTYPE, SSAP and sequence numbers and update local ack
721 **                  sequence
722 **
723 ** Returns          void
724 **
725 *******************************************************************************/
llcp_util_build_info_pdu(tLLCP_DLCB * p_dlcb,BT_HDR * p_msg)726 void llcp_util_build_info_pdu (tLLCP_DLCB *p_dlcb, BT_HDR *p_msg)
727 {
728     UINT8  *p;
729     UINT8  rcv_seq;
730 
731     p_msg->offset -= LLCP_PDU_HEADER_SIZE + LLCP_SEQUENCE_SIZE;
732     p_msg->len    += LLCP_PDU_HEADER_SIZE + LLCP_SEQUENCE_SIZE;
733     p = (UINT8 *) (p_msg + 1) + p_msg->offset;
734 
735     UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (p_dlcb->remote_sap, LLCP_PDU_I_TYPE, p_dlcb->local_sap));
736 
737     /* if local_busy or rx congested then do not update receive sequence number to flow off */
738     if (  (p_dlcb->local_busy)
739         ||(p_dlcb->is_rx_congested)
740         ||(llcp_cb.overall_rx_congested)  )
741     {
742         rcv_seq = p_dlcb->sent_ack_seq;
743     }
744     else
745     {
746         p_dlcb->sent_ack_seq = p_dlcb->next_rx_seq;
747         rcv_seq = p_dlcb->sent_ack_seq;
748     }
749     UINT8_TO_BE_STREAM  (p, LLCP_GET_SEQUENCE (p_dlcb->next_tx_seq, rcv_seq));
750 }
751 
752 /*******************************************************************************
753 **
754 ** Function         llcp_util_send_frmr
755 **
756 ** Description      Send FRMR PDU
757 **
758 ** Returns          tLLCP_STATUS
759 **
760 *******************************************************************************/
llcp_util_send_frmr(tLLCP_DLCB * p_dlcb,UINT8 flags,UINT8 ptype,UINT8 sequence)761 tLLCP_STATUS llcp_util_send_frmr (tLLCP_DLCB *p_dlcb, UINT8 flags, UINT8 ptype, UINT8 sequence)
762 {
763     BT_HDR *p_msg;
764     UINT8  *p;
765 
766     p_msg = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID);
767 
768     if (p_msg)
769     {
770         p_msg->len      = LLCP_PDU_FRMR_SIZE;
771         p_msg->offset   = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
772 
773         p = (UINT8 *) (p_msg + 1) + p_msg->offset;
774 
775         UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (p_dlcb->remote_sap, LLCP_PDU_FRMR_TYPE, p_dlcb->local_sap));
776         UINT8_TO_BE_STREAM (p, (flags << 4) | ptype);
777         UINT8_TO_BE_STREAM (p, sequence);
778         UINT8_TO_BE_STREAM (p, (p_dlcb->next_tx_seq << 4) | p_dlcb->next_rx_seq);
779         UINT8_TO_BE_STREAM (p, (p_dlcb->rcvd_ack_seq << 4) | p_dlcb->sent_ack_seq);
780 
781         GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, p_msg);
782         llcp_link_check_send_data ();
783 
784         return LLCP_STATUS_SUCCESS;
785     }
786     else
787     {
788         LLCP_TRACE_ERROR0 ("llcp_util_send_frmr (): Out of resource");
789         return LLCP_STATUS_FAIL;
790     }
791 }
792 
793 /*******************************************************************************
794 **
795 ** Function         llcp_util_send_rr_rnr
796 **
797 ** Description      Send RR or RNR PDU
798 **
799 ** Returns          void
800 **
801 *******************************************************************************/
llcp_util_send_rr_rnr(tLLCP_DLCB * p_dlcb)802 void llcp_util_send_rr_rnr (tLLCP_DLCB *p_dlcb)
803 {
804     BT_HDR *p_msg;
805     UINT8  *p;
806     UINT8   pdu_type;
807     UINT8   pdu_size;
808     UINT8   rcv_seq;
809 
810     /* if no indication of change in local busy or rx congestion */
811     if ((p_dlcb->flags & LLCP_DATA_LINK_FLAG_PENDING_RR_RNR) == 0)
812     {
813         /* if all ack is sent */
814         if (p_dlcb->sent_ack_seq == p_dlcb->next_rx_seq)
815         {
816             /* we don't need to send RR/RNR */
817             return;
818         }
819         else
820         {
821             /* if rx flow off because of local busy or congestion */
822             if (  (p_dlcb->local_busy)
823                 ||(p_dlcb->is_rx_congested)
824                 ||(llcp_cb.overall_rx_congested)  )
825             {
826                 /* don't send RR/RNR */
827                 return;
828             }
829         }
830     }
831 
832     if (  (p_dlcb->local_busy)
833         ||(p_dlcb->is_rx_congested)
834         ||(llcp_cb.overall_rx_congested)  )
835     {
836         LLCP_TRACE_DEBUG3 ("llcp_util_send_rr_rnr (): local_busy=%d,is_rx_congested=%d,overall_rx_congested=%d",
837                             p_dlcb->local_busy, p_dlcb->is_rx_congested, llcp_cb.overall_rx_congested);
838 
839         /* if local_busy or rx congested then do not update receive sequence number to flow off */
840         pdu_type = LLCP_PDU_RNR_TYPE;
841         pdu_size = LLCP_PDU_RNR_SIZE;
842         rcv_seq = p_dlcb->sent_ack_seq;
843     }
844     else
845     {
846         pdu_type = LLCP_PDU_RR_TYPE;
847         pdu_size = LLCP_PDU_RR_SIZE;
848 
849         p_dlcb->sent_ack_seq = p_dlcb->next_rx_seq;
850         rcv_seq = p_dlcb->sent_ack_seq;
851     }
852 
853     p_msg = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID);
854 
855     if (p_msg)
856     {
857         p_dlcb->flags &= ~LLCP_DATA_LINK_FLAG_PENDING_RR_RNR;
858 
859         p_msg->len    = pdu_size;
860         p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
861 
862         p = (UINT8 *) (p_msg + 1) + p_msg->offset;
863 
864         UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (p_dlcb->remote_sap, pdu_type, p_dlcb->local_sap));
865 
866         UINT8_TO_BE_STREAM (p, rcv_seq);
867 
868 #if (BT_TRACE_VERBOSE == TRUE)
869         LLCP_TRACE_DEBUG5 ("LLCP TX - N(S,R):(NA,%d) V(S,SA,R,RA):(%d,%d,%d,%d)",
870                             p_dlcb->next_rx_seq,
871                             p_dlcb->next_tx_seq, p_dlcb->rcvd_ack_seq,
872                             p_dlcb->next_rx_seq, p_dlcb->sent_ack_seq);
873 #endif
874         GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, p_msg);
875         llcp_link_check_send_data ();
876     }
877     else
878     {
879         LLCP_TRACE_ERROR0 ("llcp_util_send_rr_rnr (): Out of resource");
880     }
881 }
882 
883 /*******************************************************************************
884 **
885 ** Function         llcp_util_get_app_cb
886 **
887 ** Description      get pointer of application registered control block by SAP
888 **
889 ** Returns          tLLCP_APP_CB *
890 **
891 *******************************************************************************/
llcp_util_get_app_cb(UINT8 local_sap)892 tLLCP_APP_CB *llcp_util_get_app_cb (UINT8 local_sap)
893 {
894     tLLCP_APP_CB *p_app_cb = NULL;
895 
896     if (local_sap <= LLCP_UPPER_BOUND_WK_SAP)
897     {
898         if ((local_sap != LLCP_SAP_LM) && (local_sap < LLCP_MAX_WKS))
899         {
900             p_app_cb = &llcp_cb.wks_cb[local_sap];
901         }
902     }
903     else if (local_sap <= LLCP_UPPER_BOUND_SDP_SAP)
904     {
905         if (local_sap - LLCP_LOWER_BOUND_SDP_SAP < LLCP_MAX_SERVER)
906         {
907             p_app_cb = &llcp_cb.server_cb[local_sap - LLCP_LOWER_BOUND_SDP_SAP];
908         }
909     }
910     else if (local_sap <= LLCP_UPPER_BOUND_LOCAL_SAP)
911     {
912         if (local_sap - LLCP_LOWER_BOUND_LOCAL_SAP < LLCP_MAX_CLIENT)
913         {
914             p_app_cb = &llcp_cb.client_cb[local_sap - LLCP_LOWER_BOUND_LOCAL_SAP];
915         }
916     }
917 
918     return (p_app_cb);
919 }
920