blob: 973a1b9c78c2d38ff3c79804e6862e0b4b8bd490 [file] [log] [blame]
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08001/******************************************************************************
2 *
Evan Chue9629ba2014-01-31 11:18:47 -05003 * Copyright (C) 2010-2014 Broadcom Corporation
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -08004 *
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
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080019/******************************************************************************
20 *
21 * This file contains the LLCP utilities
22 *
23 ******************************************************************************/
24
25#include <string.h>
Andre Eisenbach8a4edf62017-11-20 14:51:11 -080026
27#include <android-base/stringprintf.h>
28#include <base/logging.h>
Ruchi Kandoi8f404a42018-09-14 15:42:46 -070029#include <log/log.h>
Andre Eisenbach8a4edf62017-11-20 14:51:11 -080030
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080031#include "bt_types.h"
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080032#include "gki.h"
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080033#include "llcp_defs.h"
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080034#include "llcp_int.h"
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080035#include "nfc_int.h"
36
Andre Eisenbach8a4edf62017-11-20 14:51:11 -080037using android::base::StringPrintf;
38
39extern bool nfc_debug_enabled;
40
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080041/*******************************************************************************
42**
43** Function llcp_util_parse_link_params
44**
45** Description Parse LLCP Link parameters
46**
47** Returns TRUE if success
48**
49*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080050bool llcp_util_parse_link_params(uint16_t length, uint8_t* p_bytes) {
51 uint8_t param_type, param_len, *p = p_bytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080052
Ruchi Kandoi8f404a42018-09-14 15:42:46 -070053 while (length >= 2) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080054 BE_STREAM_TO_UINT8(param_type, p);
Ruchi Kandoi8f404a42018-09-14 15:42:46 -070055 BE_STREAM_TO_UINT8(param_len, p);
56 if (length < param_len + 2) {
57 android_errorWriteLog(0x534e4554, "114238578");
58 LOG(ERROR) << StringPrintf("Bad LTV's");
59 return false;
60 }
61 length -= param_len + 2;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080062
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080063 switch (param_type) {
64 case LLCP_VERSION_TYPE:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080065 BE_STREAM_TO_UINT8(llcp_cb.lcb.peer_version, p);
Ruchi Kandoi6767aec2017-09-26 09:46:26 -070066 DLOG_IF(INFO, nfc_debug_enabled)
67 << StringPrintf("Peer Version - 0x%02X", llcp_cb.lcb.peer_version);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080068 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080069
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080070 case LLCP_MIUX_TYPE:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080071 BE_STREAM_TO_UINT16(llcp_cb.lcb.peer_miu, p);
72 llcp_cb.lcb.peer_miu &= LLCP_MIUX_MASK;
73 llcp_cb.lcb.peer_miu += LLCP_DEFAULT_MIU;
Ruchi Kandoi6767aec2017-09-26 09:46:26 -070074 DLOG_IF(INFO, nfc_debug_enabled)
75 << StringPrintf("Peer MIU - %d bytes", llcp_cb.lcb.peer_miu);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080076 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080077
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080078 case LLCP_WKS_TYPE:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080079 BE_STREAM_TO_UINT16(llcp_cb.lcb.peer_wks, p);
Ruchi Kandoi6767aec2017-09-26 09:46:26 -070080 DLOG_IF(INFO, nfc_debug_enabled)
81 << StringPrintf("Peer WKS - 0x%04X", llcp_cb.lcb.peer_wks);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080082 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080083
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080084 case LLCP_LTO_TYPE:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080085 BE_STREAM_TO_UINT8(llcp_cb.lcb.peer_lto, p);
86 llcp_cb.lcb.peer_lto *= LLCP_LTO_UNIT; /* 10ms unit */
Ruchi Kandoi6767aec2017-09-26 09:46:26 -070087 DLOG_IF(INFO, nfc_debug_enabled)
88 << StringPrintf("Peer LTO - %d ms", llcp_cb.lcb.peer_lto);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080089 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080090
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080091 case LLCP_OPT_TYPE:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080092 BE_STREAM_TO_UINT8(llcp_cb.lcb.peer_opt, p);
Ruchi Kandoi6767aec2017-09-26 09:46:26 -070093 DLOG_IF(INFO, nfc_debug_enabled)
94 << StringPrintf("Peer OPT - 0x%02X", llcp_cb.lcb.peer_opt);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080095 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -080096
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080097 default:
Ruchi Kandoi6767aec2017-09-26 09:46:26 -070098 LOG(ERROR) << StringPrintf("Unexpected type 0x%x", param_type);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -080099 p += param_len;
100 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800101 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800102 }
103 return true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800104}
105
106/*******************************************************************************
107**
108** Function llcp_util_adjust_ll_congestion
109**
110** Description adjust tx/rx congestion thresholds on logical link
111**
112** Returns void
113**
114*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800115void llcp_util_adjust_ll_congestion(void) {
116 /* buffer quota is allocated equally for each logical data link */
117 if (llcp_cb.num_logical_data_link) {
118 llcp_cb.ll_tx_congest_start =
119 llcp_cb.max_num_ll_tx_buff / llcp_cb.num_logical_data_link;
120 llcp_cb.ll_rx_congest_start =
121 llcp_cb.max_num_ll_rx_buff / llcp_cb.num_logical_data_link;
122 } else {
123 llcp_cb.ll_tx_congest_start = llcp_cb.max_num_ll_tx_buff;
124 llcp_cb.ll_rx_congest_start = llcp_cb.max_num_ll_rx_buff;
125 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800126
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800127 /* at least one for each logical data link */
128 if (llcp_cb.ll_tx_congest_start == 0) {
129 llcp_cb.ll_tx_congest_start = 1;
130 }
131 if (llcp_cb.ll_rx_congest_start == 0) {
132 llcp_cb.ll_rx_congest_start = 1;
133 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800134
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800135 if (llcp_cb.ll_tx_congest_start > 1) {
136 llcp_cb.ll_tx_congest_end = 1;
137 } else {
138 llcp_cb.ll_tx_congest_end = 0;
139 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800140
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700141 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800142 "num_logical_data_link=%d, ll_tx_congest_start=%d, ll_tx_congest_end=%d, "
143 "ll_rx_congest_start=%d",
144 llcp_cb.num_logical_data_link, llcp_cb.ll_tx_congest_start,
145 llcp_cb.ll_tx_congest_end, llcp_cb.ll_rx_congest_start);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800146}
147
148/*******************************************************************************
149**
150** Function llcp_util_adjust_dl_rx_congestion
151**
152** Description adjust rx congestion thresholds on data link
153**
154** Returns void
155**
156*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800157void llcp_util_adjust_dl_rx_congestion(void) {
158 uint8_t idx, rx_congest_start;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800159
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800160 if (llcp_cb.num_data_link_connection) {
161 rx_congest_start = llcp_cb.num_rx_buff / llcp_cb.num_data_link_connection;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800162
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800163 for (idx = 0; idx < LLCP_MAX_DATA_LINK; idx++) {
164 if (llcp_cb.dlcb[idx].state == LLCP_DLC_STATE_CONNECTED) {
165 if (rx_congest_start > llcp_cb.dlcb[idx].local_rw) {
166 /*
167 ** set rx congestion threshold LLCP_DL_MIN_RX_CONGEST at
168 ** least so, we don't need to flow off too often.
169 */
170 if (llcp_cb.dlcb[idx].local_rw + 1 > LLCP_DL_MIN_RX_CONGEST)
171 llcp_cb.dlcb[idx].rx_congest_threshold =
172 llcp_cb.dlcb[idx].local_rw + 1;
173 else
174 llcp_cb.dlcb[idx].rx_congest_threshold = LLCP_DL_MIN_RX_CONGEST;
175 } else {
176 llcp_cb.dlcb[idx].rx_congest_threshold = LLCP_DL_MIN_RX_CONGEST;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800177 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800178
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700179 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
180 "DLC[%d], local_rw=%d, rx_congest_threshold=%d", idx,
181 llcp_cb.dlcb[idx].local_rw, llcp_cb.dlcb[idx].rx_congest_threshold);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800182 }
183 }
184 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800185}
186
187/*******************************************************************************
188**
189** Function llcp_util_check_rx_congested_status
190**
191** Description Update rx congested status
192**
193** Returns void
194**
195*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800196void llcp_util_check_rx_congested_status(void) {
197 uint8_t idx;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800198
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800199 if (llcp_cb.overall_rx_congested) {
200 /* check if rx congestion clear */
201 if (llcp_cb.total_rx_ui_pdu + llcp_cb.total_rx_i_pdu <=
202 llcp_cb.overall_rx_congest_end) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700203 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
204 "rx link is uncongested, "
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800205 "%d+%d <= %d",
206 llcp_cb.total_rx_ui_pdu, llcp_cb.total_rx_i_pdu,
207 llcp_cb.overall_rx_congest_end);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800208
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800209 llcp_cb.overall_rx_congested = false;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800210
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800211 for (idx = 0; idx < LLCP_MAX_DATA_LINK; idx++) {
212 /* set flag to clear local busy status on data link connections */
213 if ((llcp_cb.dlcb[idx].state == LLCP_DLC_STATE_CONNECTED) &&
214 (llcp_cb.dlcb[idx].is_rx_congested == false)) {
215 llcp_cb.dlcb[idx].flags |= LLCP_DATA_LINK_FLAG_PENDING_RR_RNR;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800216 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800217 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800218 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800219 } else {
220 /* check if rx link is congested */
221 if (llcp_cb.total_rx_ui_pdu + llcp_cb.total_rx_i_pdu >=
222 llcp_cb.overall_rx_congest_start) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700223 LOG(WARNING) << StringPrintf(
224 "rx link is congested, %d+%d "
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800225 ">= %d",
226 llcp_cb.total_rx_ui_pdu, llcp_cb.total_rx_i_pdu,
227 llcp_cb.overall_rx_congest_start);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800228
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800229 llcp_cb.overall_rx_congested = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800230
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800231 /* rx link congestion is started, send RNR to remote end point */
232 for (idx = 0; idx < LLCP_MAX_DATA_LINK; idx++) {
233 if ((llcp_cb.dlcb[idx].state == LLCP_DLC_STATE_CONNECTED) &&
234 (llcp_cb.dlcb[idx].is_rx_congested == false)) {
235 llcp_cb.dlcb[idx].flags |= LLCP_DATA_LINK_FLAG_PENDING_RR_RNR;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800236 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800237 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800238 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800239 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800240}
241
242/*******************************************************************************
243**
244** Function llcp_util_send_ui
245**
246** Description Send UI PDU
247**
248** Returns tLLCP_STATUS
249**
250*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800251tLLCP_STATUS llcp_util_send_ui(uint8_t ssap, uint8_t dsap,
252 tLLCP_APP_CB* p_app_cb, NFC_HDR* p_msg) {
253 uint8_t* p;
254 tLLCP_STATUS status = LLCP_STATUS_SUCCESS;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800255
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800256 p_msg->offset -= LLCP_PDU_HEADER_SIZE;
257 p_msg->len += LLCP_PDU_HEADER_SIZE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800258
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800259 p = (uint8_t*)(p_msg + 1) + p_msg->offset;
260 UINT16_TO_BE_STREAM(p, LLCP_GET_PDU_HEADER(dsap, LLCP_PDU_UI_TYPE, ssap));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800261
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800262 GKI_enqueue(&p_app_cb->ui_xmit_q, p_msg);
263 llcp_cb.total_tx_ui_pdu++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800264
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800265 llcp_link_check_send_data();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800266
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800267 if ((p_app_cb->is_ui_tx_congested) ||
268 (p_app_cb->ui_xmit_q.count >= llcp_cb.ll_tx_congest_start) ||
269 (llcp_cb.overall_tx_congested) ||
270 (llcp_cb.total_tx_ui_pdu >= llcp_cb.max_num_ll_tx_buff)) {
271 /* set congested here so overall congestion check routine will not report
272 * event again, */
273 /* or notify uncongestion later */
274 p_app_cb->is_ui_tx_congested = true;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800275
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700276 LOG(WARNING) << StringPrintf(
277 "Logical link (SAP=0x%X) congested: ui_xmit_q.count=%d", ssap,
278 p_app_cb->ui_xmit_q.count);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800279
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800280 status = LLCP_STATUS_CONGESTED;
281 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800282
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800283 return status;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800284}
285
286/*******************************************************************************
287**
288** Function llcp_util_send_disc
289**
290** Description Send DISC PDU
291**
292** Returns void
293**
294*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800295void llcp_util_send_disc(uint8_t dsap, uint8_t ssap) {
296 NFC_HDR* p_msg;
297 uint8_t* p;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800298
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800299 p_msg = (NFC_HDR*)GKI_getpoolbuf(LLCP_POOL_ID);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800300
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800301 if (p_msg) {
302 p_msg->len = LLCP_PDU_DISC_SIZE;
303 p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800304
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800305 p = (uint8_t*)(p_msg + 1) + p_msg->offset;
306 UINT16_TO_BE_STREAM(p, LLCP_GET_PDU_HEADER(dsap, LLCP_PDU_DISC_TYPE, ssap));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800307
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800308 GKI_enqueue(&llcp_cb.lcb.sig_xmit_q, p_msg);
309 llcp_link_check_send_data();
310 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800311}
312
313/*******************************************************************************
314**
315** Function llcp_util_allocate_data_link
316**
317** Description Allocate tLLCP_DLCB for data link connection
318**
319** Returns tLLCP_DLCB *
320**
321******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800322tLLCP_DLCB* llcp_util_allocate_data_link(uint8_t reg_sap, uint8_t remote_sap) {
323 tLLCP_DLCB* p_dlcb = NULL;
324 int idx;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800325
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700326 DLOG_IF(INFO, nfc_debug_enabled)
327 << StringPrintf("reg_sap = 0x%x, remote_sap = 0x%x", reg_sap, remote_sap);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800328
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800329 for (idx = 0; idx < LLCP_MAX_DATA_LINK; idx++) {
330 if (llcp_cb.dlcb[idx].state == LLCP_DLC_STATE_IDLE) {
331 p_dlcb = &(llcp_cb.dlcb[idx]);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800332
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800333 memset(p_dlcb, 0, sizeof(tLLCP_DLCB));
334 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800335 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800336 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800337
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800338 if (!p_dlcb) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700339 LOG(ERROR) << StringPrintf("Out of DLCB");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800340 } else {
341 p_dlcb->p_app_cb = llcp_util_get_app_cb(reg_sap);
342 p_dlcb->local_sap = reg_sap;
343 p_dlcb->remote_sap = remote_sap;
344 p_dlcb->timer.param = (uintptr_t)p_dlcb;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800345
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800346 /* this is for inactivity timer and congestion control. */
347 llcp_cb.num_data_link_connection++;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800348
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700349 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
350 "local_sap = 0x%x, remote_sap = 0x%x, "
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800351 "num_data_link_connection = %d",
352 p_dlcb->local_sap, p_dlcb->remote_sap,
353 llcp_cb.num_data_link_connection);
354 }
355 return p_dlcb;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800356}
357
358/*******************************************************************************
359**
360** Function llcp_util_deallocate_data_link
361**
362** Description Deallocate tLLCP_DLCB
363**
364** Returns void
365**
366******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800367void llcp_util_deallocate_data_link(tLLCP_DLCB* p_dlcb) {
368 if (p_dlcb) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700369 DLOG_IF(INFO, nfc_debug_enabled)
370 << StringPrintf("local_sap = 0x%x", p_dlcb->local_sap);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800371
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800372 if (p_dlcb->state != LLCP_DLC_STATE_IDLE) {
373 nfc_stop_quick_timer(&p_dlcb->timer);
374 llcp_dlc_flush_q(p_dlcb);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800375
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800376 p_dlcb->state = LLCP_DLC_STATE_IDLE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800377
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800378 if (llcp_cb.num_data_link_connection > 0) {
379 llcp_cb.num_data_link_connection--;
380 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800381
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700382 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
383 "num_data_link_connection = %d", llcp_cb.num_data_link_connection);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800384 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800385 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800386}
387
388/*******************************************************************************
389**
390** Function llcp_util_send_connect
391**
392** Description Send CONNECT PDU
393**
394** Returns tLLCP_STATUS
395**
396******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800397tLLCP_STATUS llcp_util_send_connect(tLLCP_DLCB* p_dlcb,
398 tLLCP_CONNECTION_PARAMS* p_params) {
399 NFC_HDR* p_msg;
400 uint8_t* p;
401 uint16_t miu_len = 0, rw_len = 0, sn_len = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800402
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800403 if (p_params->miu != LLCP_DEFAULT_MIU) {
404 miu_len = 4; /* TYPE, LEN, 2 bytes MIU */
405 }
406 if (p_params->rw != LLCP_DEFAULT_RW) {
407 rw_len = 3; /* TYPE, LEN, 1 byte RW */
408 p_params->rw &= 0x0F; /* only 4 bits */
409 }
410 if ((strlen(p_params->sn)) && (p_dlcb->remote_sap == LLCP_SAP_SDP)) {
411 sn_len = (uint16_t)(2 + strlen(p_params->sn)); /* TYPE, LEN, SN */
412 }
413
414 p_msg = (NFC_HDR*)GKI_getpoolbuf(LLCP_POOL_ID);
415
416 if (p_msg) {
417 p_msg->len = LLCP_PDU_HEADER_SIZE + miu_len + rw_len + sn_len;
418 p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
419
420 p = (uint8_t*)(p_msg + 1) + p_msg->offset;
421
422 UINT16_TO_BE_STREAM(
423 p, LLCP_GET_PDU_HEADER(p_dlcb->remote_sap, LLCP_PDU_CONNECT_TYPE,
424 p_dlcb->local_sap));
425
426 if (miu_len) {
427 UINT8_TO_BE_STREAM(p, LLCP_MIUX_TYPE);
428 UINT8_TO_BE_STREAM(p, LLCP_MIUX_LEN);
429 UINT16_TO_BE_STREAM(p, p_params->miu - LLCP_DEFAULT_MIU);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800430 }
431
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800432 if (rw_len) {
433 UINT8_TO_BE_STREAM(p, LLCP_RW_TYPE);
434 UINT8_TO_BE_STREAM(p, LLCP_RW_LEN);
435 UINT8_TO_BE_STREAM(p, p_params->rw);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800436 }
437
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800438 if (sn_len) {
439 UINT8_TO_BE_STREAM(p, LLCP_SN_TYPE);
440 UINT8_TO_BE_STREAM(p, sn_len - 2);
441 memcpy(p, p_params->sn, sn_len - 2);
442 }
443
444 GKI_enqueue(&llcp_cb.lcb.sig_xmit_q, p_msg);
445 llcp_link_check_send_data();
446
447 return LLCP_STATUS_SUCCESS;
448 }
449
450 return LLCP_STATUS_FAIL;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800451}
452
453/*******************************************************************************
454**
455** Function llcp_util_parse_connect
456**
457** Description Parse CONNECT PDU
458**
459** Returns tLLCP_STATUS
460**
461*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800462tLLCP_STATUS llcp_util_parse_connect(uint8_t* p_bytes, uint16_t length,
463 tLLCP_CONNECTION_PARAMS* p_params) {
464 uint8_t param_type, param_len, *p = p_bytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800465
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800466 p_params->miu = LLCP_DEFAULT_MIU;
467 p_params->rw = LLCP_DEFAULT_RW;
468 p_params->sn[0] = 0;
469 p_params->sn[1] = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800470
Ruchi Kandoi8f404a42018-09-14 15:42:46 -0700471 while (length >= 2) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800472 BE_STREAM_TO_UINT8(param_type, p);
Ruchi Kandoi8f404a42018-09-14 15:42:46 -0700473 BE_STREAM_TO_UINT8(param_len, p);
474 /* check remaining lengh */
475 if (length < param_len + 2) {
476 android_errorWriteLog(0x534e4554, "111660010");
477 LOG(ERROR) << StringPrintf("Bad LTV's");
478 return LLCP_STATUS_FAIL;
479 }
480 length -= param_len + 2;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800481
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800482 switch (param_type) {
483 case LLCP_MIUX_TYPE:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800484 BE_STREAM_TO_UINT16(p_params->miu, p);
485 p_params->miu &= LLCP_MIUX_MASK;
486 p_params->miu += LLCP_DEFAULT_MIU;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800487
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700488 DLOG_IF(INFO, nfc_debug_enabled)
489 << StringPrintf("LLCP_MIUX_TYPE:%d", p_params->miu);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800490 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800491
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800492 case LLCP_RW_TYPE:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800493 BE_STREAM_TO_UINT8(p_params->rw, p);
494 p_params->rw &= 0x0F;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800495
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700496 DLOG_IF(INFO, nfc_debug_enabled)
497 << StringPrintf("LLCP_RW_TYPE:%d", p_params->rw);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800498 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800499
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800500 case LLCP_SN_TYPE:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800501 if (param_len == 0) {
502 /* indicate that SN type is included without SN */
503 p_params->sn[1] = LLCP_SN_TYPE;
504 } else if (param_len <= LLCP_MAX_SN_LEN) {
505 memcpy(p_params->sn, p, param_len);
506 p_params->sn[param_len] = 0;
507 } else {
508 memcpy(p_params->sn, p, LLCP_MAX_SN_LEN);
509 p_params->sn[LLCP_MAX_SN_LEN] = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800510 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800511 p += param_len;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800512
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700513 DLOG_IF(INFO, nfc_debug_enabled)
514 << StringPrintf("LLCP_SN_TYPE:<%s>", p_params->sn);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800515 break;
516
517 default:
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700518 LOG(ERROR) << StringPrintf("Unexpected type 0x%x", param_type);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800519 p += param_len;
520 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800521 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800522 }
523 return LLCP_STATUS_SUCCESS;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800524}
525
526/*******************************************************************************
527**
528** Function llcp_util_send_cc
529**
530** Description Send CC PDU
531**
532** Returns tLLCP_STATUS
533**
534******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800535tLLCP_STATUS llcp_util_send_cc(tLLCP_DLCB* p_dlcb,
536 tLLCP_CONNECTION_PARAMS* p_params) {
537 NFC_HDR* p_msg;
538 uint8_t* p;
539 uint16_t miu_len = 0, rw_len = 0;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800540
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800541 if (p_params->miu != LLCP_DEFAULT_MIU) {
542 miu_len = 4;
543 }
544 if (p_params->rw != LLCP_DEFAULT_RW) {
545 rw_len = 3;
546 p_params->rw &= 0x0F;
547 }
548
549 p_msg = (NFC_HDR*)GKI_getpoolbuf(LLCP_POOL_ID);
550
551 if (p_msg) {
552 p_msg->len = LLCP_PDU_HEADER_SIZE + miu_len + rw_len;
553 p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
554
555 p = (uint8_t*)(p_msg + 1) + p_msg->offset;
556
557 UINT16_TO_BE_STREAM(
558 p, LLCP_GET_PDU_HEADER(p_dlcb->remote_sap, LLCP_PDU_CC_TYPE,
559 p_dlcb->local_sap));
560
561 if (miu_len) {
562 UINT8_TO_BE_STREAM(p, LLCP_MIUX_TYPE);
563 UINT8_TO_BE_STREAM(p, LLCP_MIUX_LEN);
564 UINT16_TO_BE_STREAM(p, p_params->miu - LLCP_DEFAULT_MIU);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800565 }
566
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800567 if (rw_len) {
568 UINT8_TO_BE_STREAM(p, LLCP_RW_TYPE);
569 UINT8_TO_BE_STREAM(p, LLCP_RW_LEN);
570 UINT8_TO_BE_STREAM(p, p_params->rw);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800571 }
572
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800573 GKI_enqueue(&llcp_cb.lcb.sig_xmit_q, p_msg);
574 llcp_link_check_send_data();
575
576 return LLCP_STATUS_SUCCESS;
577 }
578
579 return LLCP_STATUS_FAIL;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800580}
581
582/*******************************************************************************
583**
584** Function llcp_util_parse_cc
585**
586** Description Parse CC PDU
587**
588** Returns tLLCP_STATUS
589**
590*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800591tLLCP_STATUS llcp_util_parse_cc(uint8_t* p_bytes, uint16_t length,
592 uint16_t* p_miu, uint8_t* p_rw) {
593 uint8_t param_type, param_len, *p = p_bytes;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800594
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800595 *p_miu = LLCP_DEFAULT_MIU;
596 *p_rw = LLCP_DEFAULT_RW;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800597
Ruchi Kandoi8f404a42018-09-14 15:42:46 -0700598 while (length >= 2) {
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800599 BE_STREAM_TO_UINT8(param_type, p);
Ruchi Kandoi8f404a42018-09-14 15:42:46 -0700600 BE_STREAM_TO_UINT8(param_len, p);
601 if (length < param_len + 2) {
602 android_errorWriteLog(0x534e4554, "114237888");
603 LOG(ERROR) << StringPrintf("Bad LTV's");
604 return LLCP_STATUS_FAIL;
605 }
606 length -= param_len + 2;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800607
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800608 switch (param_type) {
609 case LLCP_MIUX_TYPE:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800610 BE_STREAM_TO_UINT16((*p_miu), p);
611 (*p_miu) &= LLCP_MIUX_MASK;
612 (*p_miu) += LLCP_DEFAULT_MIU;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800613
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700614 DLOG_IF(INFO, nfc_debug_enabled)
615 << StringPrintf("LLCP_MIUX_TYPE:%d", *p_miu);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800616 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800617
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800618 case LLCP_RW_TYPE:
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800619 BE_STREAM_TO_UINT8((*p_rw), p);
620 (*p_rw) &= 0x0F;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800621
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700622 DLOG_IF(INFO, nfc_debug_enabled)
623 << StringPrintf("LLCP_RW_TYPE:%d", *p_rw);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800624 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800625
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800626 default:
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700627 LOG(ERROR) << StringPrintf("Unexpected type 0x%x", param_type);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800628 p += param_len;
629 break;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800630 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800631 }
632 return LLCP_STATUS_SUCCESS;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800633}
634
635/*******************************************************************************
636**
637** Function llcp_util_send_dm
638**
639** Description Send DM PDU
640**
641** Returns void
642**
643*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800644void llcp_util_send_dm(uint8_t dsap, uint8_t ssap, uint8_t reason) {
645 NFC_HDR* p_msg;
646 uint8_t* p;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800647
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800648 p_msg = (NFC_HDR*)GKI_getpoolbuf(LLCP_POOL_ID);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800649
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800650 if (p_msg) {
651 p_msg->len = LLCP_PDU_DM_SIZE;
652 p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800653
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800654 p = (uint8_t*)(p_msg + 1) + p_msg->offset;
655 UINT16_TO_BE_STREAM(p, LLCP_GET_PDU_HEADER(dsap, LLCP_PDU_DM_TYPE, ssap));
656 UINT8_TO_BE_STREAM(p, reason);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800657
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800658 GKI_enqueue(&llcp_cb.lcb.sig_xmit_q, p_msg);
659 llcp_link_check_send_data();
660 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800661}
662
663/*******************************************************************************
664**
665** Function llcp_util_build_info_pdu
666**
Ruchi Kandoi552f2b72017-01-28 16:22:55 -0800667** Description Add DSAP, PTYPE, SSAP and sequence numbers and update local
668** ack sequence
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800669**
670** Returns void
671**
672*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800673void llcp_util_build_info_pdu(tLLCP_DLCB* p_dlcb, NFC_HDR* p_msg) {
674 uint8_t* p;
675 uint8_t rcv_seq;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800676
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800677 p_msg->offset -= LLCP_PDU_HEADER_SIZE + LLCP_SEQUENCE_SIZE;
678 p_msg->len += LLCP_PDU_HEADER_SIZE + LLCP_SEQUENCE_SIZE;
679 p = (uint8_t*)(p_msg + 1) + p_msg->offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800680
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800681 UINT16_TO_BE_STREAM(p,
682 LLCP_GET_PDU_HEADER(p_dlcb->remote_sap, LLCP_PDU_I_TYPE,
683 p_dlcb->local_sap));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800684
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800685 /* if local_busy or rx congested then do not update receive sequence number to
686 * flow off */
687 if ((p_dlcb->local_busy) || (p_dlcb->is_rx_congested) ||
688 (llcp_cb.overall_rx_congested)) {
689 rcv_seq = p_dlcb->sent_ack_seq;
690 } else {
691 p_dlcb->sent_ack_seq = p_dlcb->next_rx_seq;
692 rcv_seq = p_dlcb->sent_ack_seq;
693 }
694 UINT8_TO_BE_STREAM(p, LLCP_GET_SEQUENCE(p_dlcb->next_tx_seq, rcv_seq));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800695}
696
697/*******************************************************************************
698**
699** Function llcp_util_send_frmr
700**
701** Description Send FRMR PDU
702**
703** Returns tLLCP_STATUS
704**
705*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800706tLLCP_STATUS llcp_util_send_frmr(tLLCP_DLCB* p_dlcb, uint8_t flags,
707 uint8_t ptype, uint8_t sequence) {
708 NFC_HDR* p_msg;
709 uint8_t* p;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800710
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800711 p_msg = (NFC_HDR*)GKI_getpoolbuf(LLCP_POOL_ID);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800712
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800713 if (p_msg) {
714 p_msg->len = LLCP_PDU_FRMR_SIZE;
715 p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800716
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800717 p = (uint8_t*)(p_msg + 1) + p_msg->offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800718
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800719 UINT16_TO_BE_STREAM(
720 p, LLCP_GET_PDU_HEADER(p_dlcb->remote_sap, LLCP_PDU_FRMR_TYPE,
721 p_dlcb->local_sap));
722 UINT8_TO_BE_STREAM(p, (flags << 4) | ptype);
723 UINT8_TO_BE_STREAM(p, sequence);
724 UINT8_TO_BE_STREAM(p, (p_dlcb->next_tx_seq << 4) | p_dlcb->next_rx_seq);
725 UINT8_TO_BE_STREAM(p, (p_dlcb->rcvd_ack_seq << 4) | p_dlcb->sent_ack_seq);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800726
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800727 GKI_enqueue(&llcp_cb.lcb.sig_xmit_q, p_msg);
728 llcp_link_check_send_data();
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800729
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800730 return LLCP_STATUS_SUCCESS;
731 } else {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700732 LOG(ERROR) << StringPrintf("Out of resource");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800733 return LLCP_STATUS_FAIL;
734 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800735}
736
737/*******************************************************************************
738**
739** Function llcp_util_send_rr_rnr
740**
741** Description Send RR or RNR PDU
742**
743** Returns void
744**
745*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800746void llcp_util_send_rr_rnr(tLLCP_DLCB* p_dlcb) {
747 NFC_HDR* p_msg;
748 uint8_t* p;
749 uint8_t pdu_type;
750 uint8_t pdu_size;
751 uint8_t rcv_seq;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800752
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800753 /* if no indication of change in local busy or rx congestion */
754 if ((p_dlcb->flags & LLCP_DATA_LINK_FLAG_PENDING_RR_RNR) == 0) {
755 /* if all ack is sent */
756 if (p_dlcb->sent_ack_seq == p_dlcb->next_rx_seq) {
757 /* we don't need to send RR/RNR */
758 return;
759 } else {
760 /* if rx flow off because of local busy or congestion */
761 if ((p_dlcb->local_busy) || (p_dlcb->is_rx_congested) ||
762 (llcp_cb.overall_rx_congested)) {
763 /* don't send RR/RNR */
764 return;
765 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800766 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800767 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800768
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800769 if ((p_dlcb->local_busy) || (p_dlcb->is_rx_congested) ||
770 (llcp_cb.overall_rx_congested)) {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700771 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
772 ""
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800773 "local_busy=%d,is_rx_congested=%d,overall_rx_congested=%d",
774 p_dlcb->local_busy, p_dlcb->is_rx_congested,
775 llcp_cb.overall_rx_congested);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800776
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800777 /* if local_busy or rx congested then do not update receive sequence number
778 * to flow off */
779 pdu_type = LLCP_PDU_RNR_TYPE;
780 pdu_size = LLCP_PDU_RNR_SIZE;
781 rcv_seq = p_dlcb->sent_ack_seq;
782 } else {
783 pdu_type = LLCP_PDU_RR_TYPE;
784 pdu_size = LLCP_PDU_RR_SIZE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800785
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800786 p_dlcb->sent_ack_seq = p_dlcb->next_rx_seq;
787 rcv_seq = p_dlcb->sent_ack_seq;
788 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800789
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800790 p_msg = (NFC_HDR*)GKI_getpoolbuf(LLCP_POOL_ID);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800791
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800792 if (p_msg) {
793 p_dlcb->flags &= ~LLCP_DATA_LINK_FLAG_PENDING_RR_RNR;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800794
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800795 p_msg->len = pdu_size;
796 p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800797
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800798 p = (uint8_t*)(p_msg + 1) + p_msg->offset;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800799
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800800 UINT16_TO_BE_STREAM(p, LLCP_GET_PDU_HEADER(p_dlcb->remote_sap, pdu_type,
801 p_dlcb->local_sap));
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800802
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800803 UINT8_TO_BE_STREAM(p, rcv_seq);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800804
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700805 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
806 "LLCP TX - N(S,R):(NA,%d) V(S,SA,R,RA):(%d,%d,%d,%d)",
807 p_dlcb->next_rx_seq, p_dlcb->next_tx_seq, p_dlcb->rcvd_ack_seq,
808 p_dlcb->next_rx_seq, p_dlcb->sent_ack_seq);
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800809 GKI_enqueue(&llcp_cb.lcb.sig_xmit_q, p_msg);
810 llcp_link_check_send_data();
811 } else {
Ruchi Kandoi6767aec2017-09-26 09:46:26 -0700812 LOG(ERROR) << StringPrintf("Out of resource");
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800813 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800814}
815
816/*******************************************************************************
817**
818** Function llcp_util_get_app_cb
819**
820** Description get pointer of application registered control block by SAP
821**
822** Returns tLLCP_APP_CB *
823**
824*******************************************************************************/
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800825tLLCP_APP_CB* llcp_util_get_app_cb(uint8_t local_sap) {
826 tLLCP_APP_CB* p_app_cb = NULL;
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800827
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800828 if (local_sap <= LLCP_UPPER_BOUND_WK_SAP) {
829 if ((local_sap != LLCP_SAP_LM) && (local_sap < LLCP_MAX_WKS)) {
830 p_app_cb = &llcp_cb.wks_cb[local_sap];
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800831 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800832 } else if (local_sap <= LLCP_UPPER_BOUND_SDP_SAP) {
833 if (local_sap - LLCP_LOWER_BOUND_SDP_SAP < LLCP_MAX_SERVER) {
834 p_app_cb = &llcp_cb.server_cb[local_sap - LLCP_LOWER_BOUND_SDP_SAP];
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800835 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800836 } else if (local_sap <= LLCP_UPPER_BOUND_LOCAL_SAP) {
837 if (local_sap - LLCP_LOWER_BOUND_LOCAL_SAP < LLCP_MAX_CLIENT) {
838 p_app_cb = &llcp_cb.client_cb[local_sap - LLCP_LOWER_BOUND_LOCAL_SAP];
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800839 }
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800840 }
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800841
Ruchi Kandoi6fca02d2017-01-30 14:28:16 -0800842 return (p_app_cb);
The Android Open Source Projecte9df6ba2012-12-13 14:55:37 -0800843}