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