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