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 API code
22 *
23 ******************************************************************************/
24
25 #include "llcp_api.h"
26 #include <string.h>
27 #include "bt_types.h"
28 #include "gki.h"
29 #include "llcp_defs.h"
30 #include "llcp_int.h"
31 #include "nfc_target.h"
32
33 #if (LLCP_TEST_INCLUDED == TRUE) /* this is for LLCP testing */
34
35 tLLCP_TEST_PARAMS llcp_test_params = {
36 LLCP_VERSION_VALUE, 0, /* not override */
37 };
38
39 /*******************************************************************************
40 **
41 ** Function LLCP_SetTestParams
42 **
43 ** Description Set test parameters for LLCP
44 **
45 **
46 ** Returns void
47 **
48 *******************************************************************************/
LLCP_SetTestParams(uint8_t version,uint16_t wks)49 void LLCP_SetTestParams(uint8_t version, uint16_t wks) {
50 LLCP_TRACE_API2("LLCP_SetTestParams () version:0x%02X, wks:0x%04X", version,
51 wks);
52
53 if (version != 0xFF) llcp_test_params.version = version;
54
55 if (wks != 0xFFFF) llcp_test_params.wks = wks;
56 }
57 #endif
58
59 /*******************************************************************************
60 **
61 ** Function LLCP_SetConfig
62 **
63 ** Description Set configuration parameters for LLCP
64 ** - Local Link MIU
65 ** - Option parameter
66 ** - Response Waiting Time Index
67 ** - Local Link Timeout
68 ** - Inactivity Timeout as initiator role
69 ** - Inactivity Timeout as target role
70 ** - Delay SYMM response
71 ** - Data link connection timeout
72 ** - Delay timeout to send first PDU as initiator
73 **
74 ** Returns void
75 **
76 *******************************************************************************/
LLCP_SetConfig(uint16_t link_miu,uint8_t opt,uint8_t wt,uint16_t link_timeout,uint16_t inact_timeout_init,uint16_t inact_timeout_target,uint16_t symm_delay,uint16_t data_link_timeout,uint16_t delay_first_pdu_timeout)77 void LLCP_SetConfig(uint16_t link_miu, uint8_t opt, uint8_t wt,
78 uint16_t link_timeout, uint16_t inact_timeout_init,
79 uint16_t inact_timeout_target, uint16_t symm_delay,
80 uint16_t data_link_timeout,
81 uint16_t delay_first_pdu_timeout) {
82 LLCP_TRACE_API4(
83 "LLCP_SetConfig () link_miu:%d, opt:0x%02X, wt:%d, link_timeout:%d",
84 link_miu, opt, wt, link_timeout);
85 LLCP_TRACE_API4(
86 " inact_timeout (init:%d,target:%d), symm_delay:%d, "
87 "data_link_timeout:%d",
88 inact_timeout_init, inact_timeout_target, symm_delay, data_link_timeout);
89 LLCP_TRACE_API1(" delay_first_pdu_timeout:%d",
90 delay_first_pdu_timeout);
91
92 if (link_miu < LLCP_DEFAULT_MIU) {
93 LLCP_TRACE_ERROR1(
94 "LLCP_SetConfig (): link_miu shall not be smaller than "
95 "LLCP_DEFAULT_MIU (%d)",
96 LLCP_DEFAULT_MIU);
97 link_miu = LLCP_DEFAULT_MIU;
98 } else if (link_miu > LLCP_MAX_MIU) {
99 LLCP_TRACE_ERROR1(
100 "LLCP_SetConfig (): link_miu shall not be bigger than LLCP_MAX_MIU "
101 "(%d)",
102 LLCP_MAX_MIU);
103 link_miu = LLCP_MAX_MIU;
104 }
105
106 /* if Link MIU is bigger than GKI buffer */
107 if (link_miu > LLCP_MIU) {
108 LLCP_TRACE_ERROR1(
109 "LLCP_SetConfig (): link_miu shall not be bigger than LLCP_MIU (%d)",
110 LLCP_MIU);
111 llcp_cb.lcb.local_link_miu = LLCP_MIU;
112 } else
113 llcp_cb.lcb.local_link_miu = link_miu;
114
115 llcp_cb.lcb.local_opt = opt;
116 llcp_cb.lcb.local_wt = wt;
117
118 if (link_timeout < LLCP_LTO_UNIT) {
119 LLCP_TRACE_ERROR1(
120 "LLCP_SetConfig (): link_timeout shall not be smaller than "
121 "LLCP_LTO_UNIT (%d ms)",
122 LLCP_LTO_UNIT);
123 llcp_cb.lcb.local_lto = LLCP_DEFAULT_LTO_IN_MS;
124 } else if (link_timeout > LLCP_MAX_LTO_IN_MS) {
125 LLCP_TRACE_ERROR1(
126 "LLCP_SetConfig (): link_timeout shall not be bigger than "
127 "LLCP_MAX_LTO_IN_MS (%d ms)",
128 LLCP_MAX_LTO_IN_MS);
129 llcp_cb.lcb.local_lto = LLCP_MAX_LTO_IN_MS;
130 } else
131 llcp_cb.lcb.local_lto = link_timeout;
132
133 llcp_cb.lcb.inact_timeout_init = inact_timeout_init;
134 llcp_cb.lcb.inact_timeout_target = inact_timeout_target;
135 llcp_cb.lcb.symm_delay = symm_delay;
136 llcp_cb.lcb.data_link_timeout = data_link_timeout;
137 llcp_cb.lcb.delay_first_pdu_timeout = delay_first_pdu_timeout;
138 }
139
140 /*******************************************************************************
141 **
142 ** Function LLCP_GetConfig
143 **
144 ** Description Get configuration parameters for LLCP
145 ** - Local Link MIU
146 ** - Option parameter
147 ** - Response Waiting Time Index
148 ** - Local Link Timeout
149 ** - Inactivity Timeout as initiator role
150 ** - Inactivity Timeout as target role
151 ** - Delay SYMM response
152 ** - Data link connection timeout
153 ** - Delay timeout to send first PDU as initiator
154 **
155 ** Returns void
156 **
157 *******************************************************************************/
LLCP_GetConfig(uint16_t * p_link_miu,uint8_t * p_opt,uint8_t * p_wt,uint16_t * p_link_timeout,uint16_t * p_inact_timeout_init,uint16_t * p_inact_timeout_target,uint16_t * p_symm_delay,uint16_t * p_data_link_timeout,uint16_t * p_delay_first_pdu_timeout)158 void LLCP_GetConfig(uint16_t* p_link_miu, uint8_t* p_opt, uint8_t* p_wt,
159 uint16_t* p_link_timeout, uint16_t* p_inact_timeout_init,
160 uint16_t* p_inact_timeout_target, uint16_t* p_symm_delay,
161 uint16_t* p_data_link_timeout,
162 uint16_t* p_delay_first_pdu_timeout) {
163 *p_link_miu = llcp_cb.lcb.local_link_miu;
164 *p_opt = llcp_cb.lcb.local_opt;
165 *p_wt = llcp_cb.lcb.local_wt;
166 *p_link_timeout = llcp_cb.lcb.local_lto;
167 *p_inact_timeout_init = llcp_cb.lcb.inact_timeout_init;
168 *p_inact_timeout_target = llcp_cb.lcb.inact_timeout_target;
169 *p_symm_delay = llcp_cb.lcb.symm_delay;
170 *p_data_link_timeout = llcp_cb.lcb.data_link_timeout;
171 *p_delay_first_pdu_timeout = llcp_cb.lcb.delay_first_pdu_timeout;
172
173 LLCP_TRACE_API4(
174 "LLCP_GetConfig () link_miu:%d, opt:0x%02X, wt:%d, link_timeout:%d",
175 *p_link_miu, *p_opt, *p_wt, *p_link_timeout);
176 LLCP_TRACE_API4(
177 " inact_timeout (init:%d, target:%d), symm_delay:%d, "
178 "data_link_timeout:%d",
179 *p_inact_timeout_init, *p_inact_timeout_target, *p_symm_delay,
180 *p_data_link_timeout);
181 LLCP_TRACE_API1(" delay_first_pdu_timeout:%d",
182 *p_delay_first_pdu_timeout);
183 }
184
185 /*******************************************************************************
186 **
187 ** Function LLCP_GetDiscoveryConfig
188 **
189 ** Description Returns discovery config for ISO 18092 MAC link activation
190 ** This function is called to get general bytes for
191 ** NFC_PMID_ATR_REQ_GEN_BYTES or NFC_PMID_ATR_RES_GEN_BYTES
192 ** before starting discovery.
193 **
194 ** wt:Waiting time 0 - 8, only for listen
195 ** p_gen_bytes: pointer to store LLCP magic number and
196 ** paramters
197 ** p_gen_bytes_len: length of buffer for gen bytes as input
198 ** (NOTE:it must be bigger than
199 ** LLCP_MIN_GEN_BYTES) actual gen bytes size
200 ** as output
201 **
202 ** Restrictions on the use of ISO 18092
203 ** 1. The DID features shall not be used.
204 ** 2. the NAD features shall not be used.
205 ** 3. Frame waiting time extentions (WTX) shall not be used.
206 **
207 ** Returns None
208 **
209 *******************************************************************************/
LLCP_GetDiscoveryConfig(uint8_t * p_wt,uint8_t * p_gen_bytes,uint8_t * p_gen_bytes_len)210 void LLCP_GetDiscoveryConfig(uint8_t* p_wt, uint8_t* p_gen_bytes,
211 uint8_t* p_gen_bytes_len) {
212 uint8_t* p = p_gen_bytes;
213
214 LLCP_TRACE_API0("LLCP_GetDiscoveryConfig ()");
215
216 if (*p_gen_bytes_len < LLCP_MIN_GEN_BYTES) {
217 LLCP_TRACE_ERROR1(
218 "LLCP_GetDiscoveryConfig (): GenBytes length shall not be smaller than "
219 "LLCP_MIN_GEN_BYTES (%d)",
220 LLCP_MIN_GEN_BYTES);
221 *p_gen_bytes_len = 0;
222 return;
223 }
224
225 *p_wt = llcp_cb.lcb.local_wt;
226
227 UINT8_TO_BE_STREAM(p, LLCP_MAGIC_NUMBER_BYTE0);
228 UINT8_TO_BE_STREAM(p, LLCP_MAGIC_NUMBER_BYTE1);
229 UINT8_TO_BE_STREAM(p, LLCP_MAGIC_NUMBER_BYTE2);
230
231 #if (LLCP_TEST_INCLUDED == TRUE) /* this is for LLCP testing */
232 UINT8_TO_BE_STREAM(p, LLCP_VERSION_TYPE);
233 UINT8_TO_BE_STREAM(p, LLCP_VERSION_LEN);
234 UINT8_TO_BE_STREAM(p, llcp_test_params.version);
235
236 UINT8_TO_BE_STREAM(p, LLCP_MIUX_TYPE);
237 UINT8_TO_BE_STREAM(p, LLCP_MIUX_LEN);
238 UINT16_TO_BE_STREAM(p, (llcp_cb.lcb.local_link_miu - LLCP_DEFAULT_MIU));
239
240 UINT8_TO_BE_STREAM(p, LLCP_WKS_TYPE);
241 UINT8_TO_BE_STREAM(p, LLCP_WKS_LEN);
242 if (llcp_test_params.wks == 0) /* not override */
243 {
244 UINT16_TO_BE_STREAM(p, llcp_cb.lcb.wks);
245 } else {
246 UINT16_TO_BE_STREAM(p, llcp_test_params.wks);
247 }
248 #else
249 UINT8_TO_BE_STREAM(p, LLCP_VERSION_TYPE);
250 UINT8_TO_BE_STREAM(p, LLCP_VERSION_LEN);
251 UINT8_TO_BE_STREAM(p, LLCP_VERSION_VALUE);
252
253 UINT8_TO_BE_STREAM(p, LLCP_MIUX_TYPE);
254 UINT8_TO_BE_STREAM(p, LLCP_MIUX_LEN);
255 UINT16_TO_BE_STREAM(p, (llcp_cb.lcb.local_link_miu - LLCP_DEFAULT_MIU));
256
257 UINT8_TO_BE_STREAM(p, LLCP_WKS_TYPE);
258 UINT8_TO_BE_STREAM(p, LLCP_WKS_LEN);
259 UINT16_TO_BE_STREAM(p, llcp_cb.lcb.wks);
260 #endif
261
262 UINT8_TO_BE_STREAM(p, LLCP_LTO_TYPE);
263 UINT8_TO_BE_STREAM(p, LLCP_LTO_LEN);
264 UINT8_TO_BE_STREAM(p, (llcp_cb.lcb.local_lto / LLCP_LTO_UNIT));
265
266 UINT8_TO_BE_STREAM(p, LLCP_OPT_TYPE);
267 UINT8_TO_BE_STREAM(p, LLCP_OPT_LEN);
268 UINT8_TO_BE_STREAM(p, llcp_cb.lcb.local_opt);
269
270 *p_gen_bytes_len = (uint8_t)(p - p_gen_bytes);
271 }
272
273 /*******************************************************************************
274 **
275 ** Function LLCP_ActivateLink
276 **
277 ** Description This function will activate LLCP link with LR, WT and Gen
278 ** Bytes in activation NTF from NFCC.
279 **
280 ** LLCP_LINK_ACTIVATION_COMPLETE_EVT will be returned through
281 ** callback function if successful.
282 ** Otherwise, LLCP_LINK_ACTIVATION_FAILED_EVT will be returned.
283 **
284 ** Returns LLCP_STATUS_SUCCESS if success
285 **
286 *******************************************************************************/
LLCP_ActivateLink(tLLCP_ACTIVATE_CONFIG config,tLLCP_LINK_CBACK * p_link_cback)287 tLLCP_STATUS LLCP_ActivateLink(tLLCP_ACTIVATE_CONFIG config,
288 tLLCP_LINK_CBACK* p_link_cback) {
289 LLCP_TRACE_API1("LLCP_ActivateLink () link_state = %d",
290 llcp_cb.lcb.link_state);
291
292 if ((llcp_cb.lcb.link_state == LLCP_LINK_STATE_DEACTIVATED) &&
293 (p_link_cback)) {
294 llcp_cb.lcb.p_link_cback = p_link_cback;
295 return (llcp_link_activate(&config));
296 } else
297 return LLCP_STATUS_FAIL;
298 }
299
300 /*******************************************************************************
301 **
302 ** Function LLCP_DeactivateLink
303 **
304 ** Description Deactivate LLCP link
305 **
306 ** LLCP_LINK_DEACTIVATED_EVT will be returned through callback
307 ** when LLCP link is deactivated. Then NFC link may be
308 ** deactivated.
309 **
310 ** Returns LLCP_STATUS_SUCCESS if success
311 **
312 *******************************************************************************/
LLCP_DeactivateLink(void)313 tLLCP_STATUS LLCP_DeactivateLink(void) {
314 LLCP_TRACE_API1("LLCP_DeactivateLink () link_state = %d",
315 llcp_cb.lcb.link_state);
316
317 if (llcp_cb.lcb.link_state != LLCP_LINK_STATE_DEACTIVATED) {
318 llcp_link_deactivate(LLCP_LINK_LOCAL_INITIATED);
319 return LLCP_STATUS_SUCCESS;
320 } else
321 return LLCP_STATUS_FAIL;
322 }
323
324 /*******************************************************************************
325 **
326 ** Function LLCP_RegisterServer
327 **
328 ** Description Register server and callback function
329 **
330 ** reg_sap : Well-Known SAP except LM and SDP (0x02 - 0x0F)
331 ** Advertized by SDP (0x10 - 0x1F)
332 ** LLCP_INVALID_SAP, LLCP will allocate between 0x10
333 ** and 0x1F
334 ** link_type : LLCP_LINK_TYPE_LOGICAL_DATA_LINK
335 ** and/or LLCP_LINK_TYPE_DATA_LINK_CONNECTION
336 ** p_service_name : Null-terminated string up to
337 ** LLCP_MAX_SN_LEN
338 **
339 ** Returns SAP between 0x02 and 0x1F, if success
340 ** LLCP_INVALID_SAP, otherwise
341 **
342 *******************************************************************************/
LLCP_RegisterServer(uint8_t reg_sap,uint8_t link_type,char * p_service_name,tLLCP_APP_CBACK * p_app_cback)343 uint8_t LLCP_RegisterServer(uint8_t reg_sap, uint8_t link_type,
344 char* p_service_name,
345 tLLCP_APP_CBACK* p_app_cback) {
346 uint8_t sap;
347 uint16_t length;
348 tLLCP_APP_CB* p_app_cb = {
349 0,
350 };
351
352 LLCP_TRACE_API3(
353 "LLCP_RegisterServer (): SAP:0x%x, link_type:0x%x, ServiceName:<%s>",
354 reg_sap, link_type, ((p_service_name == NULL) ? "" : p_service_name));
355
356 if (!p_app_cback) {
357 LLCP_TRACE_ERROR0("LLCP_RegisterServer (): Callback must be provided");
358 return LLCP_INVALID_SAP;
359 } else if (((link_type & LLCP_LINK_TYPE_LOGICAL_DATA_LINK) == 0x00) &&
360 ((link_type & LLCP_LINK_TYPE_DATA_LINK_CONNECTION) == 0x00)) {
361 LLCP_TRACE_ERROR1(
362 "LLCP_RegisterServer (): link type (0x%x) must be specified",
363 link_type);
364 return LLCP_INVALID_SAP;
365 }
366
367 if (reg_sap == LLCP_INVALID_SAP) {
368 /* allocate a SAP between 0x10 and 0x1F */
369 for (sap = 0; sap < LLCP_MAX_SERVER; sap++) {
370 if (llcp_cb.server_cb[sap].p_app_cback == NULL) {
371 p_app_cb = &llcp_cb.server_cb[sap];
372 reg_sap = LLCP_LOWER_BOUND_SDP_SAP + sap;
373 break;
374 }
375 }
376
377 if (reg_sap == LLCP_INVALID_SAP) {
378 LLCP_TRACE_ERROR0("LLCP_RegisterServer (): out of resource");
379 return LLCP_INVALID_SAP;
380 }
381 } else if (reg_sap == LLCP_SAP_LM) {
382 LLCP_TRACE_ERROR1("LLCP_RegisterServer (): SAP (0x%x) is for link manager",
383 reg_sap);
384 return LLCP_INVALID_SAP;
385 } else if (reg_sap <= LLCP_UPPER_BOUND_WK_SAP) {
386 if (reg_sap >= LLCP_MAX_WKS) {
387 LLCP_TRACE_ERROR1(
388 "LLCP_RegisterServer (): out of resource for SAP (0x%x)", reg_sap);
389 return LLCP_INVALID_SAP;
390 } else if (llcp_cb.wks_cb[reg_sap].p_app_cback) {
391 LLCP_TRACE_ERROR1(
392 "LLCP_RegisterServer (): SAP (0x%x) is already registered", reg_sap);
393 return LLCP_INVALID_SAP;
394 } else {
395 p_app_cb = &llcp_cb.wks_cb[reg_sap];
396 }
397 } else if (reg_sap <= LLCP_UPPER_BOUND_SDP_SAP) {
398 if (reg_sap - LLCP_LOWER_BOUND_SDP_SAP >= LLCP_MAX_SERVER) {
399 LLCP_TRACE_ERROR1(
400 "LLCP_RegisterServer (): out of resource for SAP (0x%x)", reg_sap);
401 return LLCP_INVALID_SAP;
402 } else if (llcp_cb.server_cb[reg_sap - LLCP_LOWER_BOUND_SDP_SAP]
403 .p_app_cback) {
404 LLCP_TRACE_ERROR1(
405 "LLCP_RegisterServer (): SAP (0x%x) is already registered", reg_sap);
406 return LLCP_INVALID_SAP;
407 } else {
408 p_app_cb = &llcp_cb.server_cb[reg_sap - LLCP_LOWER_BOUND_SDP_SAP];
409 }
410 } else if (reg_sap >= LLCP_LOWER_BOUND_LOCAL_SAP) {
411 LLCP_TRACE_ERROR2(
412 "LLCP_RegisterServer (): SAP (0x%x) must be less than 0x%x", reg_sap,
413 LLCP_LOWER_BOUND_LOCAL_SAP);
414 return LLCP_INVALID_SAP;
415 }
416
417 memset(p_app_cb, 0x00, sizeof(tLLCP_APP_CB));
418
419 if (p_service_name) {
420 length = (uint8_t)strlen(p_service_name);
421 if (length > LLCP_MAX_SN_LEN) {
422 LLCP_TRACE_ERROR1(
423 "LLCP_RegisterServer (): Service Name (%d bytes) is too long",
424 length);
425 return LLCP_INVALID_SAP;
426 }
427
428 p_app_cb->p_service_name = (uint8_t*)GKI_getbuf((uint16_t)(length + 1));
429 if (p_app_cb->p_service_name == NULL) {
430 LLCP_TRACE_ERROR0("LLCP_RegisterServer (): Out of resource");
431 return LLCP_INVALID_SAP;
432 }
433
434 strncpy((char*)p_app_cb->p_service_name, (char*)p_service_name, length + 1);
435 p_app_cb->p_service_name[length] = 0;
436 } else
437 p_app_cb->p_service_name = NULL;
438
439 p_app_cb->p_app_cback = p_app_cback;
440 p_app_cb->link_type = link_type;
441
442 if (reg_sap <= LLCP_UPPER_BOUND_WK_SAP) {
443 llcp_cb.lcb.wks |= (1 << reg_sap);
444 }
445
446 LLCP_TRACE_DEBUG1("LLCP_RegisterServer (): Registered SAP = 0x%02X", reg_sap);
447
448 if (link_type & LLCP_LINK_TYPE_LOGICAL_DATA_LINK) {
449 llcp_cb.num_logical_data_link++;
450 llcp_util_adjust_ll_congestion();
451 }
452
453 return reg_sap;
454 }
455
456 /*******************************************************************************
457 **
458 ** Function LLCP_RegisterClient
459 **
460 ** Description Register client and callback function
461 **
462 ** link_type : LLCP_LINK_TYPE_LOGICAL_DATA_LINK
463 ** and/or LLCP_LINK_TYPE_DATA_LINK_CONNECTION
464 **
465 ** Returns SAP between 0x20 and 0x3F, if success
466 ** LLCP_INVALID_SAP, otherwise
467 **
468 *******************************************************************************/
LLCP_RegisterClient(uint8_t link_type,tLLCP_APP_CBACK * p_app_cback)469 uint8_t LLCP_RegisterClient(uint8_t link_type, tLLCP_APP_CBACK* p_app_cback) {
470 uint8_t reg_sap = LLCP_INVALID_SAP;
471 uint8_t sap;
472 tLLCP_APP_CB* p_app_cb;
473
474 LLCP_TRACE_API1("LLCP_RegisterClient (): link_type = 0x%x", link_type);
475
476 if (!p_app_cback) {
477 LLCP_TRACE_ERROR0("LLCP_RegisterClient (): Callback must be provided");
478 return LLCP_INVALID_SAP;
479 } else if (((link_type & LLCP_LINK_TYPE_LOGICAL_DATA_LINK) == 0x00) &&
480 ((link_type & LLCP_LINK_TYPE_DATA_LINK_CONNECTION) == 0x00)) {
481 LLCP_TRACE_ERROR1(
482 "LLCP_RegisterClient (): link type (0x%x) must be specified",
483 link_type);
484 return LLCP_INVALID_SAP;
485 }
486
487 /* allocate a SAP between 0x20 and 0x3F */
488 for (sap = 0; sap < LLCP_MAX_CLIENT; sap++) {
489 if (llcp_cb.client_cb[sap].p_app_cback == NULL) {
490 p_app_cb = &llcp_cb.client_cb[sap];
491 memset(p_app_cb, 0x00, sizeof(tLLCP_APP_CB));
492 reg_sap = LLCP_LOWER_BOUND_LOCAL_SAP + sap;
493 break;
494 }
495 }
496
497 if (reg_sap == LLCP_INVALID_SAP) {
498 LLCP_TRACE_ERROR0("LLCP_RegisterClient (): out of resource");
499 return LLCP_INVALID_SAP;
500 }
501
502 p_app_cb->p_app_cback = p_app_cback;
503 p_app_cb->p_service_name = NULL;
504 p_app_cb->link_type = link_type;
505
506 LLCP_TRACE_DEBUG1("LLCP_RegisterClient (): Registered SAP = 0x%02X", reg_sap);
507
508 if (link_type & LLCP_LINK_TYPE_LOGICAL_DATA_LINK) {
509 llcp_cb.num_logical_data_link++;
510 llcp_util_adjust_ll_congestion();
511 }
512
513 return reg_sap;
514 }
515
516 /*******************************************************************************
517 **
518 ** Function LLCP_Deregister
519 **
520 ** Description Deregister server or client
521 **
522 **
523 ** Returns LLCP_STATUS_SUCCESS if success
524 **
525 *******************************************************************************/
LLCP_Deregister(uint8_t local_sap)526 tLLCP_STATUS LLCP_Deregister(uint8_t local_sap) {
527 uint8_t idx;
528 tLLCP_APP_CB* p_app_cb;
529
530 LLCP_TRACE_API1("LLCP_Deregister () SAP:0x%x", local_sap);
531
532 p_app_cb = llcp_util_get_app_cb(local_sap);
533
534 if ((!p_app_cb) || (p_app_cb->p_app_cback == NULL)) {
535 LLCP_TRACE_ERROR1("LLCP_Deregister (): SAP (0x%x) is not registered",
536 local_sap);
537 return LLCP_STATUS_FAIL;
538 }
539
540 if (p_app_cb->p_service_name) GKI_freebuf(p_app_cb->p_service_name);
541
542 /* update WKS bit map */
543 if (local_sap <= LLCP_UPPER_BOUND_WK_SAP) {
544 llcp_cb.lcb.wks &= ~(1 << local_sap);
545 }
546
547 /* discard any received UI PDU on this SAP */
548 LLCP_FlushLogicalLinkRxData(local_sap);
549 llcp_cb.total_rx_ui_pdu = 0;
550
551 /* deallocate any data link connection on this SAP */
552 for (idx = 0; idx < LLCP_MAX_DATA_LINK; idx++) {
553 if ((llcp_cb.dlcb[idx].state != LLCP_DLC_STATE_IDLE) &&
554 (llcp_cb.dlcb[idx].local_sap == local_sap)) {
555 llcp_util_deallocate_data_link(&llcp_cb.dlcb[idx]);
556 }
557 }
558
559 p_app_cb->p_app_cback = NULL;
560
561 /* discard any pending tx UI PDU from this SAP */
562 while (p_app_cb->ui_xmit_q.p_first) {
563 GKI_freebuf(GKI_dequeue(&p_app_cb->ui_xmit_q));
564 llcp_cb.total_tx_ui_pdu--;
565 }
566
567 if (p_app_cb->link_type & LLCP_LINK_TYPE_LOGICAL_DATA_LINK) {
568 llcp_cb.num_logical_data_link--;
569 llcp_util_adjust_ll_congestion();
570 }
571
572 /* check rx congestion status */
573 llcp_util_check_rx_congested_status();
574
575 return LLCP_STATUS_SUCCESS;
576 }
577
578 /*******************************************************************************
579 **
580 ** Function LLCP_IsLogicalLinkCongested
581 **
582 ** Description Check if logical link is congested
583 **
584 **
585 ** Returns TRUE if congested
586 **
587 *******************************************************************************/
LLCP_IsLogicalLinkCongested(uint8_t local_sap,uint8_t num_pending_ui_pdu,uint8_t total_pending_ui_pdu,uint8_t total_pending_i_pdu)588 bool LLCP_IsLogicalLinkCongested(uint8_t local_sap, uint8_t num_pending_ui_pdu,
589 uint8_t total_pending_ui_pdu,
590 uint8_t total_pending_i_pdu) {
591 tLLCP_APP_CB* p_app_cb;
592
593 LLCP_TRACE_API4(
594 "LLCP_IsLogicalLinkCongested () Local SAP:0x%x, pending = (%d, %d, %d)",
595 local_sap, num_pending_ui_pdu, total_pending_ui_pdu, total_pending_i_pdu);
596
597 p_app_cb = llcp_util_get_app_cb(local_sap);
598
599 if ((llcp_cb.lcb.link_state != LLCP_LINK_STATE_ACTIVATED) ||
600 (p_app_cb == NULL) || (p_app_cb->p_app_cback == NULL) ||
601 ((p_app_cb->link_type & LLCP_LINK_TYPE_LOGICAL_DATA_LINK) == 0) ||
602 (p_app_cb->is_ui_tx_congested)) {
603 return true;
604 } else if ((num_pending_ui_pdu + p_app_cb->ui_xmit_q.count >=
605 llcp_cb.ll_tx_congest_start) ||
606 (total_pending_ui_pdu + llcp_cb.total_tx_ui_pdu >=
607 llcp_cb.max_num_ll_tx_buff) ||
608 (total_pending_ui_pdu + total_pending_i_pdu +
609 llcp_cb.total_tx_ui_pdu + llcp_cb.total_tx_i_pdu >=
610 llcp_cb.max_num_tx_buff)) {
611 /* set flag so LLCP can notify uncongested status later */
612 p_app_cb->is_ui_tx_congested = true;
613
614 return true;
615 }
616 return false;
617 }
618
619 /*******************************************************************************
620 **
621 ** Function LLCP_SendUI
622 **
623 ** Description Send connnectionless data to DSAP
624 **
625 **
626 ** Returns LLCP_STATUS_SUCCESS if success
627 ** LLCP_STATUS_CONGESTED if logical link is congested
628 ** LLCP_STATUS_FAIL, otherwise
629 **
630 *******************************************************************************/
LLCP_SendUI(uint8_t ssap,uint8_t dsap,NFC_HDR * p_buf)631 tLLCP_STATUS LLCP_SendUI(uint8_t ssap, uint8_t dsap, NFC_HDR* p_buf) {
632 tLLCP_STATUS status = LLCP_STATUS_FAIL;
633 tLLCP_APP_CB* p_app_cb;
634
635 LLCP_TRACE_API2("LLCP_SendUI () SSAP=0x%x, DSAP=0x%x", ssap, dsap);
636
637 p_app_cb = llcp_util_get_app_cb(ssap);
638
639 if ((p_app_cb == NULL) || (p_app_cb->p_app_cback == NULL)) {
640 LLCP_TRACE_ERROR1("LLCP_SendUI (): SSAP (0x%x) is not registered", ssap);
641 } else if ((p_app_cb->link_type & LLCP_LINK_TYPE_LOGICAL_DATA_LINK) == 0) {
642 LLCP_TRACE_ERROR1(
643 "LLCP_SendUI (): Logical link on SSAP (0x%x) is not enabled", ssap);
644 } else if (llcp_cb.lcb.link_state != LLCP_LINK_STATE_ACTIVATED) {
645 LLCP_TRACE_ERROR0("LLCP_SendUI (): LLCP link is not activated");
646 } else if ((llcp_cb.lcb.peer_opt == LLCP_LSC_UNKNOWN) ||
647 (llcp_cb.lcb.peer_opt & LLCP_LSC_1)) {
648 if (p_buf->len <= llcp_cb.lcb.peer_miu) {
649 if (p_buf->offset >= LLCP_MIN_OFFSET) {
650 status = llcp_util_send_ui(ssap, dsap, p_app_cb, p_buf);
651 } else {
652 LLCP_TRACE_ERROR2("LLCP_SendUI (): offset (%d) must be %d at least",
653 p_buf->offset, LLCP_MIN_OFFSET);
654 }
655 } else {
656 LLCP_TRACE_ERROR0(
657 "LLCP_SendUI (): Data length shall not be bigger than peer's link "
658 "MIU");
659 }
660 } else {
661 LLCP_TRACE_ERROR0(
662 "LLCP_SendUI (): Peer doesn't support connectionless link");
663 }
664
665 if (status == LLCP_STATUS_FAIL) {
666 GKI_freebuf(p_buf);
667 }
668
669 return status;
670 }
671
672 /*******************************************************************************
673 **
674 ** Function LLCP_ReadLogicalLinkData
675 **
676 ** Description Read information of UI PDU for local SAP
677 **
678 ** - Remote SAP who sent UI PDU is returned.
679 ** - Information of UI PDU up to max_data_len is copied into
680 ** p_data.
681 ** - Information of next UI PDU is not concatenated.
682 ** - Recommended max_data_len is link MIU of local device
683 **
684 ** Returns TRUE if more information of UI PDU or more UI PDU in queue
685 **
686 *******************************************************************************/
LLCP_ReadLogicalLinkData(uint8_t local_sap,uint32_t max_data_len,uint8_t * p_remote_sap,uint32_t * p_data_len,uint8_t * p_data)687 bool LLCP_ReadLogicalLinkData(uint8_t local_sap, uint32_t max_data_len,
688 uint8_t* p_remote_sap, uint32_t* p_data_len,
689 uint8_t* p_data) {
690 tLLCP_APP_CB* p_app_cb;
691 NFC_HDR* p_buf;
692 uint8_t* p_ui_pdu;
693 uint16_t pdu_hdr, ui_pdu_length;
694
695 LLCP_TRACE_API1("LLCP_ReadLogicalLinkData () Local SAP:0x%x", local_sap);
696
697 *p_data_len = 0;
698
699 p_app_cb = llcp_util_get_app_cb(local_sap);
700
701 /* if application is registered */
702 if ((p_app_cb) && (p_app_cb->p_app_cback)) {
703 /* if any UI PDU in rx queue */
704 if (p_app_cb->ui_rx_q.p_first) {
705 p_buf = (NFC_HDR*)p_app_cb->ui_rx_q.p_first;
706 p_ui_pdu = (uint8_t*)(p_buf + 1) + p_buf->offset;
707
708 /* get length of UI PDU */
709 BE_STREAM_TO_UINT16(ui_pdu_length, p_ui_pdu);
710
711 /* get remote SAP from LLCP header */
712 BE_STREAM_TO_UINT16(pdu_hdr, p_ui_pdu);
713 *p_remote_sap = LLCP_GET_SSAP(pdu_hdr);
714
715 /* layer_specific has the offset to read within UI PDU */
716 p_ui_pdu += p_buf->layer_specific;
717
718 /* copy data up to max_data_len */
719 if (max_data_len >= (uint32_t)(ui_pdu_length - LLCP_PDU_HEADER_SIZE -
720 p_buf->layer_specific)) {
721 /* copy information without LLCP header */
722 *p_data_len = (uint32_t)(ui_pdu_length - LLCP_PDU_HEADER_SIZE -
723 p_buf->layer_specific);
724
725 /* move to next UI PDU if any */
726 p_buf->layer_specific =
727 0; /* reset offset to read from the first byte of next UI PDU */
728 p_buf->offset += LLCP_PDU_AGF_LEN_SIZE + ui_pdu_length;
729 p_buf->len -= LLCP_PDU_AGF_LEN_SIZE + ui_pdu_length;
730 } else {
731 *p_data_len = max_data_len;
732
733 /* update offset to read from remaining UI PDU next time */
734 p_buf->layer_specific += max_data_len;
735 }
736
737 memcpy(p_data, p_ui_pdu, *p_data_len);
738
739 /* if read all of UI PDU */
740 if (p_buf->len == 0) {
741 GKI_dequeue(&p_app_cb->ui_rx_q);
742 GKI_freebuf(p_buf);
743
744 /* decrease number of received UI PDU in in all of ui_rx_q and check rx
745 * congestion status */
746 llcp_cb.total_rx_ui_pdu--;
747 llcp_util_check_rx_congested_status();
748 }
749 }
750
751 /* if there is more UI PDU in rx queue */
752 if (p_app_cb->ui_rx_q.p_first) {
753 return true;
754 } else {
755 return false;
756 }
757 } else {
758 LLCP_TRACE_ERROR1("LLCP_ReadLogicalLinkData (): Unregistered SAP:0x%x",
759 local_sap);
760
761 return false;
762 }
763 }
764
765 /*******************************************************************************
766 **
767 ** Function LLCP_FlushLogicalLinkRxData
768 **
769 ** Description Discard received data in logical data link of local SAP
770 **
771 **
772 ** Returns length of data flushed
773 **
774 *******************************************************************************/
LLCP_FlushLogicalLinkRxData(uint8_t local_sap)775 uint32_t LLCP_FlushLogicalLinkRxData(uint8_t local_sap) {
776 NFC_HDR* p_buf;
777 uint32_t flushed_length = 0;
778 tLLCP_APP_CB* p_app_cb;
779 uint8_t* p_ui_pdu;
780 uint16_t ui_pdu_length;
781
782 LLCP_TRACE_API1("LLCP_FlushLogicalLinkRxData () Local SAP:0x%x", local_sap);
783
784 p_app_cb = llcp_util_get_app_cb(local_sap);
785
786 /* if application is registered */
787 if ((p_app_cb) && (p_app_cb->p_app_cback)) {
788 /* if any UI PDU in rx queue */
789 while (p_app_cb->ui_rx_q.p_first) {
790 p_buf = (NFC_HDR*)p_app_cb->ui_rx_q.p_first;
791 p_ui_pdu = (uint8_t*)(p_buf + 1) + p_buf->offset;
792
793 /* get length of UI PDU */
794 BE_STREAM_TO_UINT16(ui_pdu_length, p_ui_pdu);
795
796 flushed_length += (uint32_t)(ui_pdu_length - LLCP_PDU_HEADER_SIZE -
797 p_buf->layer_specific);
798
799 /* move to next UI PDU if any */
800 p_buf->layer_specific = 0; /* offset */
801 p_buf->offset += LLCP_PDU_AGF_LEN_SIZE + ui_pdu_length;
802 p_buf->len -= LLCP_PDU_AGF_LEN_SIZE + ui_pdu_length;
803
804 /* if read all of UI PDU */
805 if (p_buf->len == 0) {
806 GKI_dequeue(&p_app_cb->ui_rx_q);
807 GKI_freebuf(p_buf);
808 llcp_cb.total_rx_ui_pdu--;
809 }
810 }
811
812 /* number of received UI PDU is decreased so check rx congestion status */
813 llcp_util_check_rx_congested_status();
814 } else {
815 LLCP_TRACE_ERROR1("LLCP_FlushLogicalLinkRxData (): Unregistered SAP:0x%x",
816 local_sap);
817 }
818
819 return (flushed_length);
820 }
821
822 /*******************************************************************************
823 **
824 ** Function LLCP_ConnectReq
825 **
826 ** Description Create data link connection between registered SAP and DSAP
827 ** in peer LLCP,
828 **
829 **
830 ** Returns LLCP_STATUS_SUCCESS if success
831 ** LLCP_STATUS_FAIL, otherwise
832 **
833 *******************************************************************************/
LLCP_ConnectReq(uint8_t reg_sap,uint8_t dsap,tLLCP_CONNECTION_PARAMS * p_params)834 tLLCP_STATUS LLCP_ConnectReq(uint8_t reg_sap, uint8_t dsap,
835 tLLCP_CONNECTION_PARAMS* p_params) {
836 tLLCP_DLCB* p_dlcb;
837 tLLCP_STATUS status;
838 tLLCP_APP_CB* p_app_cb;
839 tLLCP_CONNECTION_PARAMS params;
840
841 LLCP_TRACE_API2("LLCP_ConnectReq () reg_sap=0x%x, DSAP=0x%x", reg_sap, dsap);
842
843 if ((llcp_cb.lcb.peer_opt != LLCP_LSC_UNKNOWN) &&
844 ((llcp_cb.lcb.peer_opt & LLCP_LSC_2) == 0)) {
845 LLCP_TRACE_ERROR0(
846 "LLCP_ConnectReq (): Peer doesn't support connection-oriented link");
847 return LLCP_STATUS_FAIL;
848 }
849
850 if (!p_params) {
851 params.miu = LLCP_DEFAULT_MIU;
852 params.rw = LLCP_DEFAULT_RW;
853 params.sn[0] = 0;
854 p_params = ¶ms;
855 }
856
857 p_app_cb = llcp_util_get_app_cb(reg_sap);
858
859 /* if application is registered */
860 if ((p_app_cb == NULL) || (p_app_cb->p_app_cback == NULL)) {
861 LLCP_TRACE_ERROR1("LLCP_ConnectReq (): SSAP (0x%x) is not registered",
862 reg_sap);
863 return LLCP_STATUS_FAIL;
864 }
865
866 if (dsap == LLCP_SAP_LM) {
867 LLCP_TRACE_ERROR1(
868 "LLCP_ConnectReq (): DSAP (0x%x) must not be link manager SAP", dsap);
869 return LLCP_STATUS_FAIL;
870 }
871
872 if (dsap == LLCP_SAP_SDP) {
873 if (strlen(p_params->sn) > LLCP_MAX_SN_LEN) {
874 LLCP_TRACE_ERROR1(
875 "LLCP_ConnectReq (): Service Name (%d bytes) is too long",
876 strlen(p_params->sn));
877 return LLCP_STATUS_FAIL;
878 }
879 }
880
881 if ((p_params) && (p_params->miu > llcp_cb.lcb.local_link_miu)) {
882 LLCP_TRACE_ERROR0(
883 "LLCP_ConnectReq (): Data link MIU shall not be bigger than local link "
884 "MIU");
885 return LLCP_STATUS_FAIL;
886 }
887
888 /* check if any pending connection request on this reg_sap */
889 p_dlcb = llcp_dlc_find_dlcb_by_sap(reg_sap, LLCP_INVALID_SAP);
890 if (p_dlcb) {
891 /*
892 ** Accepting LLCP may change SAP in CC, so we cannot find right data
893 ** link connection if there is multiple pending connection request on
894 ** the same local SAP.
895 */
896 LLCP_TRACE_ERROR0(
897 "LLCP_ConnectReq (): There is pending connect request on this reg_sap");
898 return LLCP_STATUS_FAIL;
899 }
900
901 p_dlcb = llcp_util_allocate_data_link(reg_sap, dsap);
902
903 if (p_dlcb) {
904 status =
905 llcp_dlsm_execute(p_dlcb, LLCP_DLC_EVENT_API_CONNECT_REQ, p_params);
906 if (status != LLCP_STATUS_SUCCESS) {
907 LLCP_TRACE_ERROR0("LLCP_ConnectReq (): Error in state machine");
908 llcp_util_deallocate_data_link(p_dlcb);
909 return LLCP_STATUS_FAIL;
910 }
911 } else {
912 return LLCP_STATUS_FAIL;
913 }
914
915 return LLCP_STATUS_SUCCESS;
916 }
917
918 /*******************************************************************************
919 **
920 ** Function LLCP_ConnectCfm
921 **
922 ** Description Accept connection request from peer LLCP
923 **
924 **
925 ** Returns LLCP_STATUS_SUCCESS if success
926 ** LLCP_STATUS_FAIL, otherwise
927 **
928 *******************************************************************************/
LLCP_ConnectCfm(uint8_t local_sap,uint8_t remote_sap,tLLCP_CONNECTION_PARAMS * p_params)929 tLLCP_STATUS LLCP_ConnectCfm(uint8_t local_sap, uint8_t remote_sap,
930 tLLCP_CONNECTION_PARAMS* p_params) {
931 tLLCP_STATUS status;
932 tLLCP_DLCB* p_dlcb;
933 tLLCP_CONNECTION_PARAMS params;
934
935 LLCP_TRACE_API2("LLCP_ConnectCfm () Local SAP:0x%x, Remote SAP:0x%x)",
936 local_sap, remote_sap);
937
938 if (!p_params) {
939 params.miu = LLCP_DEFAULT_MIU;
940 params.rw = LLCP_DEFAULT_RW;
941 params.sn[0] = 0;
942 p_params = ¶ms;
943 }
944 if (p_params->miu > llcp_cb.lcb.local_link_miu) {
945 LLCP_TRACE_ERROR0(
946 "LLCP_ConnectCfm (): Data link MIU shall not be bigger than local link "
947 "MIU");
948 return LLCP_STATUS_FAIL;
949 }
950
951 p_dlcb = llcp_dlc_find_dlcb_by_sap(local_sap, remote_sap);
952
953 if (p_dlcb) {
954 status =
955 llcp_dlsm_execute(p_dlcb, LLCP_DLC_EVENT_API_CONNECT_CFM, p_params);
956 } else {
957 LLCP_TRACE_ERROR0("LLCP_ConnectCfm (): No data link");
958 status = LLCP_STATUS_FAIL;
959 }
960
961 return status;
962 }
963
964 /*******************************************************************************
965 **
966 ** Function LLCP_ConnectReject
967 **
968 ** Description Reject connection request from peer LLCP
969 **
970 ** reason : LLCP_SAP_DM_REASON_APP_REJECTED
971 ** LLCP_SAP_DM_REASON_PERM_REJECT_THIS
972 ** LLCP_SAP_DM_REASON_PERM_REJECT_ANY
973 ** LLCP_SAP_DM_REASON_TEMP_REJECT_THIS
974 ** LLCP_SAP_DM_REASON_TEMP_REJECT_ANY
975 **
976 ** Returns LLCP_STATUS_SUCCESS if success
977 ** LLCP_STATUS_FAIL, otherwise
978 **
979 *******************************************************************************/
LLCP_ConnectReject(uint8_t local_sap,uint8_t remote_sap,uint8_t reason)980 tLLCP_STATUS LLCP_ConnectReject(uint8_t local_sap, uint8_t remote_sap,
981 uint8_t reason) {
982 tLLCP_STATUS status;
983 tLLCP_DLCB* p_dlcb;
984
985 LLCP_TRACE_API3(
986 "LLCP_ConnectReject () Local SAP:0x%x, Remote SAP:0x%x, reason:0x%x",
987 local_sap, remote_sap, reason);
988
989 p_dlcb = llcp_dlc_find_dlcb_by_sap(local_sap, remote_sap);
990
991 if (p_dlcb) {
992 status =
993 llcp_dlsm_execute(p_dlcb, LLCP_DLC_EVENT_API_CONNECT_REJECT, &reason);
994 llcp_util_deallocate_data_link(p_dlcb);
995 } else {
996 LLCP_TRACE_ERROR0("LLCP_ConnectReject (): No data link");
997 status = LLCP_STATUS_FAIL;
998 }
999
1000 return status;
1001 }
1002
1003 /*******************************************************************************
1004 **
1005 ** Function LLCP_IsDataLinkCongested
1006 **
1007 ** Description Check if data link connection is congested
1008 **
1009 **
1010 ** Returns TRUE if congested
1011 **
1012 *******************************************************************************/
LLCP_IsDataLinkCongested(uint8_t local_sap,uint8_t remote_sap,uint8_t num_pending_i_pdu,uint8_t total_pending_ui_pdu,uint8_t total_pending_i_pdu)1013 bool LLCP_IsDataLinkCongested(uint8_t local_sap, uint8_t remote_sap,
1014 uint8_t num_pending_i_pdu,
1015 uint8_t total_pending_ui_pdu,
1016 uint8_t total_pending_i_pdu) {
1017 tLLCP_DLCB* p_dlcb;
1018
1019 LLCP_TRACE_API5(
1020 "LLCP_IsDataLinkCongested () Local SAP:0x%x, Remote SAP:0x%x, pending = "
1021 "(%d, %d, %d)",
1022 local_sap, remote_sap, num_pending_i_pdu, total_pending_ui_pdu,
1023 total_pending_i_pdu);
1024
1025 p_dlcb = llcp_dlc_find_dlcb_by_sap(local_sap, remote_sap);
1026
1027 if (p_dlcb) {
1028 if ((p_dlcb->is_tx_congested) || (p_dlcb->remote_busy)) {
1029 return true;
1030 } else if ((num_pending_i_pdu + p_dlcb->i_xmit_q.count >=
1031 p_dlcb->remote_rw) ||
1032 (total_pending_ui_pdu + total_pending_i_pdu +
1033 llcp_cb.total_tx_ui_pdu + llcp_cb.total_tx_i_pdu >=
1034 llcp_cb.max_num_tx_buff)) {
1035 /* set flag so LLCP can notify uncongested status later */
1036 p_dlcb->is_tx_congested = true;
1037 return true;
1038 }
1039 return false;
1040 }
1041 return true;
1042 }
1043
1044 /*******************************************************************************
1045 **
1046 ** Function LLCP_SendData
1047 **
1048 ** Description Send connection-oriented data
1049 **
1050 **
1051 ** Returns LLCP_STATUS_SUCCESS if success
1052 ** LLCP_STATUS_CONGESTED if data link is congested
1053 **
1054 *******************************************************************************/
LLCP_SendData(uint8_t local_sap,uint8_t remote_sap,NFC_HDR * p_buf)1055 tLLCP_STATUS LLCP_SendData(uint8_t local_sap, uint8_t remote_sap,
1056 NFC_HDR* p_buf) {
1057 tLLCP_STATUS status = LLCP_STATUS_FAIL;
1058 tLLCP_DLCB* p_dlcb;
1059
1060 LLCP_TRACE_API2("LLCP_SendData () Local SAP:0x%x, Remote SAP:0x%x", local_sap,
1061 remote_sap);
1062
1063 p_dlcb = llcp_dlc_find_dlcb_by_sap(local_sap, remote_sap);
1064
1065 if (p_dlcb) {
1066 if (p_dlcb->remote_miu >= p_buf->len) {
1067 if (p_buf->offset >= LLCP_MIN_OFFSET) {
1068 status = llcp_dlsm_execute(p_dlcb, LLCP_DLC_EVENT_API_DATA_REQ, p_buf);
1069 } else {
1070 LLCP_TRACE_ERROR2("LLCP_SendData (): offset (%d) must be %d at least",
1071 p_buf->offset, LLCP_MIN_OFFSET);
1072 }
1073 } else {
1074 LLCP_TRACE_ERROR2(
1075 "LLCP_SendData (): Information (%d bytes) cannot be more than peer "
1076 "MIU (%d bytes)",
1077 p_buf->len, p_dlcb->remote_miu);
1078 }
1079 } else {
1080 LLCP_TRACE_ERROR0("LLCP_SendData (): No data link");
1081 }
1082
1083 if (status == LLCP_STATUS_FAIL) {
1084 GKI_freebuf(p_buf);
1085 }
1086
1087 return status;
1088 }
1089
1090 /*******************************************************************************
1091 **
1092 ** Function LLCP_ReadDataLinkData
1093 **
1094 ** Description Read information of I PDU for data link connection
1095 **
1096 ** - Information of I PDU up to max_data_len is copied into
1097 ** p_data.
1098 ** - Information of next I PDU is not concatenated.
1099 ** - Recommended max_data_len is data link connection MIU of
1100 ** local end point
1101 **
1102 ** Returns TRUE if more data in queue
1103 **
1104 *******************************************************************************/
LLCP_ReadDataLinkData(uint8_t local_sap,uint8_t remote_sap,uint32_t max_data_len,uint32_t * p_data_len,uint8_t * p_data)1105 bool LLCP_ReadDataLinkData(uint8_t local_sap, uint8_t remote_sap,
1106 uint32_t max_data_len, uint32_t* p_data_len,
1107 uint8_t* p_data) {
1108 tLLCP_DLCB* p_dlcb;
1109 NFC_HDR* p_buf;
1110 uint8_t* p_i_pdu;
1111 uint16_t i_pdu_length;
1112
1113 LLCP_TRACE_API2("LLCP_ReadDataLinkData () Local SAP:0x%x, Remote SAP:0x%x",
1114 local_sap, remote_sap);
1115
1116 p_dlcb = llcp_dlc_find_dlcb_by_sap(local_sap, remote_sap);
1117
1118 *p_data_len = 0;
1119 if (p_dlcb) {
1120 /* if any I PDU in rx queue */
1121 if (p_dlcb->i_rx_q.p_first) {
1122 p_buf = (NFC_HDR*)p_dlcb->i_rx_q.p_first;
1123 p_i_pdu = (uint8_t*)(p_buf + 1) + p_buf->offset;
1124
1125 /* get length of I PDU */
1126 BE_STREAM_TO_UINT16(i_pdu_length, p_i_pdu);
1127
1128 /* layer_specific has the offset to read within I PDU */
1129 p_i_pdu += p_buf->layer_specific;
1130
1131 /* copy data up to max_data_len */
1132 if (max_data_len >= (uint32_t)(i_pdu_length - p_buf->layer_specific)) {
1133 /* copy information */
1134 *p_data_len = (uint32_t)(i_pdu_length - p_buf->layer_specific);
1135
1136 /* move to next I PDU if any */
1137 p_buf->layer_specific =
1138 0; /* reset offset to read from the first byte of next I PDU */
1139 p_buf->offset += LLCP_PDU_AGF_LEN_SIZE + i_pdu_length;
1140 p_buf->len -= LLCP_PDU_AGF_LEN_SIZE + i_pdu_length;
1141 } else {
1142 *p_data_len = max_data_len;
1143
1144 /* update offset to read from remaining I PDU next time */
1145 p_buf->layer_specific += max_data_len;
1146 }
1147
1148 memcpy(p_data, p_i_pdu, *p_data_len);
1149
1150 if (p_buf->layer_specific == 0) {
1151 p_dlcb->num_rx_i_pdu--;
1152 }
1153
1154 /* if read all of I PDU */
1155 if (p_buf->len == 0) {
1156 GKI_dequeue(&p_dlcb->i_rx_q);
1157 GKI_freebuf(p_buf);
1158
1159 /* decrease number of received I PDU in in all of ui_rx_q and check rx
1160 * congestion status */
1161 llcp_cb.total_rx_i_pdu--;
1162 llcp_util_check_rx_congested_status();
1163 }
1164 }
1165
1166 /* if getting out of rx congestion */
1167 if ((!p_dlcb->local_busy) && (p_dlcb->is_rx_congested) &&
1168 (p_dlcb->num_rx_i_pdu <= p_dlcb->rx_congest_threshold / 2)) {
1169 /* send RR */
1170 p_dlcb->is_rx_congested = false;
1171 p_dlcb->flags |= LLCP_DATA_LINK_FLAG_PENDING_RR_RNR;
1172 }
1173
1174 /* if there is more I PDU in rx queue */
1175 if (p_dlcb->i_rx_q.p_first) {
1176 return true;
1177 } else {
1178 return false;
1179 }
1180 } else {
1181 LLCP_TRACE_ERROR0("LLCP_ReadDataLinkData (): No data link connection");
1182
1183 return false;
1184 }
1185 }
1186
1187 /*******************************************************************************
1188 **
1189 ** Function LLCP_FlushDataLinkRxData
1190 **
1191 ** Description Discard received data in data link connection
1192 **
1193 **
1194 ** Returns length of rx data flushed
1195 **
1196 *******************************************************************************/
LLCP_FlushDataLinkRxData(uint8_t local_sap,uint8_t remote_sap)1197 uint32_t LLCP_FlushDataLinkRxData(uint8_t local_sap, uint8_t remote_sap) {
1198 tLLCP_DLCB* p_dlcb;
1199 NFC_HDR* p_buf;
1200 uint32_t flushed_length = 0;
1201 uint8_t* p_i_pdu;
1202 uint16_t i_pdu_length;
1203
1204 LLCP_TRACE_API2("LLCP_FlushDataLinkRxData () Local SAP:0x%x, Remote SAP:0x%x",
1205 local_sap, remote_sap);
1206
1207 p_dlcb = llcp_dlc_find_dlcb_by_sap(local_sap, remote_sap);
1208
1209 if (p_dlcb) {
1210 /* if any I PDU in rx queue */
1211 while (p_dlcb->i_rx_q.p_first) {
1212 p_buf = (NFC_HDR*)p_dlcb->i_rx_q.p_first;
1213 p_i_pdu = (uint8_t*)(p_buf + 1) + p_buf->offset;
1214
1215 /* get length of I PDU */
1216 BE_STREAM_TO_UINT16(i_pdu_length, p_i_pdu);
1217
1218 flushed_length += (uint32_t)(i_pdu_length - p_buf->layer_specific);
1219
1220 /* move to next I PDU if any */
1221 p_buf->layer_specific = 0; /* offset */
1222 p_buf->offset += LLCP_PDU_AGF_LEN_SIZE + i_pdu_length;
1223 p_buf->len -= LLCP_PDU_AGF_LEN_SIZE + i_pdu_length;
1224
1225 /* if read all of I PDU */
1226 if (p_buf->len == 0) {
1227 GKI_dequeue(&p_dlcb->i_rx_q);
1228 GKI_freebuf(p_buf);
1229 llcp_cb.total_rx_i_pdu--;
1230 }
1231 }
1232
1233 p_dlcb->num_rx_i_pdu = 0;
1234
1235 /* if getting out of rx congestion */
1236 if ((!p_dlcb->local_busy) && (p_dlcb->is_rx_congested)) {
1237 /* send RR */
1238 p_dlcb->is_rx_congested = false;
1239 p_dlcb->flags |= LLCP_DATA_LINK_FLAG_PENDING_RR_RNR;
1240 }
1241
1242 /* number of received I PDU is decreased so check rx congestion status */
1243 llcp_util_check_rx_congested_status();
1244 } else {
1245 LLCP_TRACE_ERROR0("LLCP_FlushDataLinkRxData (): No data link connection");
1246 }
1247
1248 return (flushed_length);
1249 }
1250
1251 /*******************************************************************************
1252 **
1253 ** Function LLCP_DisconnectReq
1254 **
1255 ** Description Disconnect data link
1256 ** discard any pending data if flush is set to TRUE
1257 **
1258 ** Returns LLCP_STATUS_SUCCESS if success
1259 **
1260 *******************************************************************************/
LLCP_DisconnectReq(uint8_t local_sap,uint8_t remote_sap,bool flush)1261 tLLCP_STATUS LLCP_DisconnectReq(uint8_t local_sap, uint8_t remote_sap,
1262 bool flush) {
1263 tLLCP_STATUS status;
1264 tLLCP_DLCB* p_dlcb;
1265
1266 LLCP_TRACE_API3(
1267 "LLCP_DisconnectReq () Local SAP:0x%x, Remote SAP:0x%x, flush=%d",
1268 local_sap, remote_sap, flush);
1269
1270 p_dlcb = llcp_dlc_find_dlcb_by_sap(local_sap, remote_sap);
1271
1272 if (p_dlcb) {
1273 status =
1274 llcp_dlsm_execute(p_dlcb, LLCP_DLC_EVENT_API_DISCONNECT_REQ, &flush);
1275 } else {
1276 LLCP_TRACE_ERROR0("LLCP_DisconnectReq (): No data link");
1277 status = LLCP_STATUS_FAIL;
1278 }
1279
1280 return status;
1281 }
1282
1283 /*******************************************************************************
1284 **
1285 ** Function LLCP_SetTxCompleteNtf
1286 **
1287 ** Description This function is called to get LLCP_SERVICE_TX_COMPLETE
1288 ** when Tx queue is empty and all PDU is acked.
1289 ** This is one time event, so upper layer shall call this
1290 ** function again to get next LLCP_SERVICE_TX_COMPLETE.
1291 **
1292 ** Returns LLCP_STATUS_SUCCESS if success
1293 **
1294 *******************************************************************************/
LLCP_SetTxCompleteNtf(uint8_t local_sap,uint8_t remote_sap)1295 tLLCP_STATUS LLCP_SetTxCompleteNtf(uint8_t local_sap, uint8_t remote_sap) {
1296 tLLCP_STATUS status;
1297 tLLCP_DLCB* p_dlcb;
1298
1299 LLCP_TRACE_API2("LLCP_SetTxCompleteNtf () Local SAP:0x%x, Remote SAP:0x%x",
1300 local_sap, remote_sap);
1301
1302 p_dlcb = llcp_dlc_find_dlcb_by_sap(local_sap, remote_sap);
1303
1304 if (p_dlcb) {
1305 /* set flag to notify upper later when tx complete */
1306 p_dlcb->flags |= LLCP_DATA_LINK_FLAG_NOTIFY_TX_DONE;
1307 status = LLCP_STATUS_SUCCESS;
1308 } else {
1309 LLCP_TRACE_ERROR0("LLCP_SetTxCompleteNtf (): No data link");
1310 status = LLCP_STATUS_FAIL;
1311 }
1312
1313 return status;
1314 }
1315
1316 /*******************************************************************************
1317 **
1318 ** Function LLCP_SetLocalBusyStatus
1319 **
1320 ** Description Set local busy status
1321 **
1322 **
1323 ** Returns LLCP_STATUS_SUCCESS if success
1324 **
1325 *******************************************************************************/
LLCP_SetLocalBusyStatus(uint8_t local_sap,uint8_t remote_sap,bool is_busy)1326 tLLCP_STATUS LLCP_SetLocalBusyStatus(uint8_t local_sap, uint8_t remote_sap,
1327 bool is_busy) {
1328 tLLCP_STATUS status;
1329 tLLCP_DLCB* p_dlcb;
1330
1331 LLCP_TRACE_API2("LLCP_SetLocalBusyStatus () Local SAP:0x%x, is_busy=%d",
1332 local_sap, is_busy);
1333
1334 p_dlcb = llcp_dlc_find_dlcb_by_sap(local_sap, remote_sap);
1335
1336 if (p_dlcb) {
1337 if (p_dlcb->local_busy != is_busy) {
1338 p_dlcb->local_busy = is_busy;
1339
1340 /* send RR or RNR with valid sequence */
1341 p_dlcb->flags |= LLCP_DATA_LINK_FLAG_PENDING_RR_RNR;
1342
1343 if (is_busy == false) {
1344 if (p_dlcb->i_rx_q.count) {
1345 llcp_dlsm_execute(p_dlcb, LLCP_DLC_EVENT_PEER_DATA_IND, NULL);
1346 }
1347 }
1348 }
1349 status = LLCP_STATUS_SUCCESS;
1350 } else {
1351 LLCP_TRACE_ERROR0("LLCP_SetLocalBusyStatus (): No data link");
1352 status = LLCP_STATUS_FAIL;
1353 }
1354
1355 return status;
1356 }
1357
1358 /*******************************************************************************
1359 **
1360 ** Function LLCP_GetRemoteWKS
1361 **
1362 ** Description Return well-known service bitmap of connected device
1363 **
1364 **
1365 ** Returns WKS bitmap if success
1366 **
1367 *******************************************************************************/
LLCP_GetRemoteWKS(void)1368 uint16_t LLCP_GetRemoteWKS(void) {
1369 LLCP_TRACE_API1("LLCP_GetRemoteWKS () WKS:0x%04x",
1370 (llcp_cb.lcb.link_state == LLCP_LINK_STATE_ACTIVATED)
1371 ? llcp_cb.lcb.peer_wks
1372 : 0);
1373
1374 if (llcp_cb.lcb.link_state == LLCP_LINK_STATE_ACTIVATED)
1375 return (llcp_cb.lcb.peer_wks);
1376 else
1377 return (0);
1378 }
1379
1380 /*******************************************************************************
1381 **
1382 ** Function LLCP_GetRemoteLSC
1383 **
1384 ** Description Return link service class of connected device
1385 **
1386 **
1387 ** Returns link service class
1388 **
1389 *******************************************************************************/
LLCP_GetRemoteLSC(void)1390 uint8_t LLCP_GetRemoteLSC(void) {
1391 LLCP_TRACE_API1("LLCP_GetRemoteLSC () LSC:0x%x",
1392 (llcp_cb.lcb.link_state == LLCP_LINK_STATE_ACTIVATED)
1393 ? llcp_cb.lcb.peer_opt & (LLCP_LSC_1 | LLCP_LSC_2)
1394 : 0);
1395
1396 if (llcp_cb.lcb.link_state == LLCP_LINK_STATE_ACTIVATED)
1397 return (llcp_cb.lcb.peer_opt & (LLCP_LSC_1 | LLCP_LSC_2));
1398 else
1399 return (LLCP_LSC_UNKNOWN);
1400 }
1401
1402 /*******************************************************************************
1403 **
1404 ** Function LLCP_GetRemoteVersion
1405 **
1406 ** Description Return LLCP version of connected device
1407 **
1408 **
1409 ** Returns LLCP version
1410 **
1411 *******************************************************************************/
LLCP_GetRemoteVersion(void)1412 uint8_t LLCP_GetRemoteVersion(void) {
1413 LLCP_TRACE_API1("LLCP_GetRemoteVersion () Version: 0x%x",
1414 (llcp_cb.lcb.link_state == LLCP_LINK_STATE_ACTIVATED)
1415 ? llcp_cb.lcb.peer_version
1416 : 0);
1417
1418 if (llcp_cb.lcb.link_state == LLCP_LINK_STATE_ACTIVATED)
1419 return (llcp_cb.lcb.peer_version);
1420 else
1421 return 0;
1422 }
1423
1424 /*******************************************************************************
1425 **
1426 ** Function LLCP_GetLinkMIU
1427 **
1428 ** Description Return local and remote link MIU
1429 **
1430 **
1431 ** Returns None
1432 **
1433 *******************************************************************************/
LLCP_GetLinkMIU(uint16_t * p_local_link_miu,uint16_t * p_remote_link_miu)1434 void LLCP_GetLinkMIU(uint16_t* p_local_link_miu, uint16_t* p_remote_link_miu) {
1435 LLCP_TRACE_API0("LLCP_GetLinkMIU ()");
1436
1437 if (llcp_cb.lcb.link_state == LLCP_LINK_STATE_ACTIVATED) {
1438 *p_local_link_miu = llcp_cb.lcb.local_link_miu;
1439 *p_remote_link_miu = llcp_cb.lcb.effective_miu;
1440 } else {
1441 *p_local_link_miu = 0;
1442 *p_remote_link_miu = 0;
1443 }
1444
1445 LLCP_TRACE_DEBUG2(
1446 "LLCP_GetLinkMIU (): local_link_miu = %d, remote_link_miu = %d",
1447 *p_local_link_miu, *p_remote_link_miu);
1448 }
1449
1450 /*******************************************************************************
1451 **
1452 ** Function LLCP_DiscoverService
1453 **
1454 ** Description Return SAP of service name in connected device through
1455 ** callback
1456 **
1457 **
1458 ** Returns LLCP_STATUS_SUCCESS if success
1459 **
1460 *******************************************************************************/
LLCP_DiscoverService(char * p_name,tLLCP_SDP_CBACK * p_cback,uint8_t * p_tid)1461 tLLCP_STATUS LLCP_DiscoverService(char* p_name, tLLCP_SDP_CBACK* p_cback,
1462 uint8_t* p_tid) {
1463 tLLCP_STATUS status;
1464 uint8_t i;
1465
1466 LLCP_TRACE_API1("LLCP_DiscoverService () Service Name:%s", p_name);
1467
1468 if (llcp_cb.lcb.link_state != LLCP_LINK_STATE_ACTIVATED) {
1469 LLCP_TRACE_ERROR0("LLCP_DiscoverService (): Link is not activated");
1470 return LLCP_STATUS_FAIL;
1471 }
1472
1473 if (!p_cback) {
1474 LLCP_TRACE_ERROR0("LLCP_DiscoverService (): Callback must be provided.");
1475 return LLCP_STATUS_FAIL;
1476 }
1477
1478 /* if peer version is less than V1.1 then SNL is not supported */
1479 if ((llcp_cb.lcb.agreed_major_version == 0x01) &&
1480 (llcp_cb.lcb.agreed_minor_version < 0x01)) {
1481 LLCP_TRACE_ERROR0("LLCP_DiscoverService (): Peer doesn't support SNL");
1482 return LLCP_STATUS_FAIL;
1483 }
1484
1485 for (i = 0; i < LLCP_MAX_SDP_TRANSAC; i++) {
1486 if (!llcp_cb.sdp_cb.transac[i].p_cback) {
1487 llcp_cb.sdp_cb.transac[i].tid = llcp_cb.sdp_cb.next_tid;
1488 llcp_cb.sdp_cb.next_tid++;
1489 llcp_cb.sdp_cb.transac[i].p_cback = p_cback;
1490
1491 status = llcp_sdp_send_sdreq(llcp_cb.sdp_cb.transac[i].tid, p_name);
1492
1493 if (status == LLCP_STATUS_FAIL) {
1494 llcp_cb.sdp_cb.transac[i].p_cback = NULL;
1495 }
1496
1497 *p_tid = llcp_cb.sdp_cb.transac[i].tid;
1498 return (status);
1499 }
1500 }
1501
1502 LLCP_TRACE_ERROR0("LLCP_DiscoverService (): Out of resource");
1503
1504 return LLCP_STATUS_FAIL;
1505 }
1506