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