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