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