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