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 Service Discovery 22 * 23 ******************************************************************************/ 24 25#include <string.h> 26 27#include <android-base/stringprintf.h> 28#include <base/logging.h> 29 30#include "bt_types.h" 31#include "gki.h" 32#include "llcp_api.h" 33#include "llcp_int.h" 34#include "nfa_dm_int.h" 35 36using android::base::StringPrintf; 37 38extern bool nfc_debug_enabled; 39 40/******************************************************************************* 41** 42** Function llcp_sdp_proc_data 43** 44** Description Do nothing 45** 46** 47** Returns void 48** 49*******************************************************************************/ 50void llcp_sdp_proc_data(__attribute__((unused)) tLLCP_SAP_CBACK_DATA* p_data) { 51 /* 52 ** Do nothing 53 ** llcp_sdp_proc_SNL () is called by link layer 54 */ 55} 56 57/******************************************************************************* 58** 59** Function llcp_sdp_check_send_snl 60** 61** Description Enqueue Service Name Lookup PDU into sig_xmit_q for 62** transmitting 63** 64** 65** Returns void 66** 67*******************************************************************************/ 68void llcp_sdp_check_send_snl(void) { 69 uint8_t* p; 70 71 if (llcp_cb.sdp_cb.p_snl) { 72 DLOG_IF(INFO, nfc_debug_enabled) << __func__; 73 74 llcp_cb.sdp_cb.p_snl->len += LLCP_PDU_HEADER_SIZE; 75 llcp_cb.sdp_cb.p_snl->offset -= LLCP_PDU_HEADER_SIZE; 76 77 p = (uint8_t*)(llcp_cb.sdp_cb.p_snl + 1) + llcp_cb.sdp_cb.p_snl->offset; 78 UINT16_TO_BE_STREAM( 79 p, LLCP_GET_PDU_HEADER(LLCP_SAP_SDP, LLCP_PDU_SNL_TYPE, LLCP_SAP_SDP)); 80 81 GKI_enqueue(&llcp_cb.lcb.sig_xmit_q, llcp_cb.sdp_cb.p_snl); 82 llcp_cb.sdp_cb.p_snl = NULL; 83 } else { 84 /* Notify DTA after sending out SNL with SDRES not to send SNLs in AGF PDU 85 */ 86 if (llcp_cb.p_dta_cback && llcp_cb.dta_snl_resp) { 87 llcp_cb.dta_snl_resp = false; 88 (*llcp_cb.p_dta_cback)(); 89 } 90 } 91} 92 93/******************************************************************************* 94** 95** Function llcp_sdp_add_sdreq 96** 97** Description Add Service Discovery Request into SNL PDU 98** 99** 100** Returns void 101** 102*******************************************************************************/ 103static void llcp_sdp_add_sdreq(uint8_t tid, char* p_name) { 104 uint8_t* p; 105 uint16_t name_len = (uint16_t)strlen(p_name); 106 107 p = (uint8_t*)(llcp_cb.sdp_cb.p_snl + 1) + llcp_cb.sdp_cb.p_snl->offset + 108 llcp_cb.sdp_cb.p_snl->len; 109 110 UINT8_TO_BE_STREAM(p, LLCP_SDREQ_TYPE); 111 UINT8_TO_BE_STREAM(p, (1 + name_len)); 112 UINT8_TO_BE_STREAM(p, tid); 113 ARRAY_TO_BE_STREAM(p, p_name, name_len); 114 115 llcp_cb.sdp_cb.p_snl->len += LLCP_SDREQ_MIN_LEN + name_len; 116} 117 118/******************************************************************************* 119** 120** Function llcp_sdp_send_sdreq 121** 122** Description Send Service Discovery Request 123** 124** 125** Returns LLCP_STATUS 126** 127*******************************************************************************/ 128tLLCP_STATUS llcp_sdp_send_sdreq(uint8_t tid, char* p_name) { 129 tLLCP_STATUS status; 130 uint16_t name_len; 131 uint16_t available_bytes; 132 133 DLOG_IF(INFO, nfc_debug_enabled) 134 << StringPrintf("tid=0x%x, ServiceName=%s", tid, p_name); 135 136 /* if there is no pending SNL */ 137 if (!llcp_cb.sdp_cb.p_snl) { 138 llcp_cb.sdp_cb.p_snl = (NFC_HDR*)GKI_getpoolbuf(LLCP_POOL_ID); 139 140 if (llcp_cb.sdp_cb.p_snl) { 141 llcp_cb.sdp_cb.p_snl->offset = 142 NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE + LLCP_PDU_HEADER_SIZE; 143 llcp_cb.sdp_cb.p_snl->len = 0; 144 } 145 } 146 147 if (llcp_cb.sdp_cb.p_snl) { 148 available_bytes = GKI_get_buf_size(llcp_cb.sdp_cb.p_snl) - NFC_HDR_SIZE - 149 llcp_cb.sdp_cb.p_snl->offset - llcp_cb.sdp_cb.p_snl->len; 150 151 name_len = (uint16_t)strlen(p_name); 152 153 /* if SDREQ parameter can be added in SNL */ 154 if ((available_bytes >= LLCP_SDREQ_MIN_LEN + name_len) && 155 (llcp_cb.sdp_cb.p_snl->len + LLCP_SDREQ_MIN_LEN + name_len <= 156 llcp_cb.lcb.effective_miu)) { 157 llcp_sdp_add_sdreq(tid, p_name); 158 status = LLCP_STATUS_SUCCESS; 159 } else { 160 /* send pending SNL PDU to LM */ 161 llcp_sdp_check_send_snl(); 162 163 llcp_cb.sdp_cb.p_snl = (NFC_HDR*)GKI_getpoolbuf(LLCP_POOL_ID); 164 165 if (llcp_cb.sdp_cb.p_snl) { 166 llcp_cb.sdp_cb.p_snl->offset = 167 NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE + LLCP_PDU_HEADER_SIZE; 168 llcp_cb.sdp_cb.p_snl->len = 0; 169 170 llcp_sdp_add_sdreq(tid, p_name); 171 172 status = LLCP_STATUS_SUCCESS; 173 } else { 174 status = LLCP_STATUS_FAIL; 175 } 176 } 177 } else { 178 status = LLCP_STATUS_FAIL; 179 } 180 181 /* if LM is waiting for PDUs from upper layer */ 182 if ((status == LLCP_STATUS_SUCCESS) && 183 (llcp_cb.lcb.symm_state == LLCP_LINK_SYMM_LOCAL_XMIT_NEXT)) { 184 llcp_link_check_send_data(); 185 } 186 187 return status; 188} 189 190/******************************************************************************* 191** 192** Function llcp_sdp_add_sdres 193** 194** Description Add Service Discovery Response into SNL PDU 195** 196** 197** Returns void 198** 199*******************************************************************************/ 200static void llcp_sdp_add_sdres(uint8_t tid, uint8_t sap) { 201 uint8_t* p; 202 203 p = (uint8_t*)(llcp_cb.sdp_cb.p_snl + 1) + llcp_cb.sdp_cb.p_snl->offset + 204 llcp_cb.sdp_cb.p_snl->len; 205 206 UINT8_TO_BE_STREAM(p, LLCP_SDRES_TYPE); 207 UINT8_TO_BE_STREAM(p, LLCP_SDRES_LEN); 208 UINT8_TO_BE_STREAM(p, tid); 209 UINT8_TO_BE_STREAM(p, sap); 210 211 llcp_cb.sdp_cb.p_snl->len += 2 + LLCP_SDRES_LEN; /* type and length */ 212} 213 214/******************************************************************************* 215** 216** Function llcp_sdp_send_sdres 217** 218** Description Send Service Discovery Response 219** 220** 221** Returns LLCP_STATUS 222** 223*******************************************************************************/ 224static tLLCP_STATUS llcp_sdp_send_sdres(uint8_t tid, uint8_t sap) { 225 tLLCP_STATUS status; 226 uint16_t available_bytes; 227 228 DLOG_IF(INFO, nfc_debug_enabled) 229 << StringPrintf("tid=0x%x, SAP=0x%x", tid, sap); 230 231 /* if there is no pending SNL */ 232 if (!llcp_cb.sdp_cb.p_snl) { 233 llcp_cb.sdp_cb.p_snl = (NFC_HDR*)GKI_getpoolbuf(LLCP_POOL_ID); 234 235 if (llcp_cb.sdp_cb.p_snl) { 236 llcp_cb.sdp_cb.p_snl->offset = 237 NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE + LLCP_PDU_HEADER_SIZE; 238 llcp_cb.sdp_cb.p_snl->len = 0; 239 } 240 } 241 242 if (llcp_cb.sdp_cb.p_snl) { 243 available_bytes = GKI_get_buf_size(llcp_cb.sdp_cb.p_snl) - NFC_HDR_SIZE - 244 llcp_cb.sdp_cb.p_snl->offset - llcp_cb.sdp_cb.p_snl->len; 245 246 /* if SDRES parameter can be added in SNL */ 247 if ((available_bytes >= 2 + LLCP_SDRES_LEN) && 248 (llcp_cb.sdp_cb.p_snl->len + 2 + LLCP_SDRES_LEN <= 249 llcp_cb.lcb.effective_miu)) { 250 llcp_sdp_add_sdres(tid, sap); 251 status = LLCP_STATUS_SUCCESS; 252 } else { 253 /* send pending SNL PDU to LM */ 254 llcp_sdp_check_send_snl(); 255 256 llcp_cb.sdp_cb.p_snl = (NFC_HDR*)GKI_getpoolbuf(LLCP_POOL_ID); 257 258 if (llcp_cb.sdp_cb.p_snl) { 259 llcp_cb.sdp_cb.p_snl->offset = 260 NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE + LLCP_PDU_HEADER_SIZE; 261 llcp_cb.sdp_cb.p_snl->len = 0; 262 263 llcp_sdp_add_sdres(tid, sap); 264 265 status = LLCP_STATUS_SUCCESS; 266 } else { 267 status = LLCP_STATUS_FAIL; 268 } 269 } 270 } else { 271 status = LLCP_STATUS_FAIL; 272 } 273 274 /* if LM is waiting for PDUs from upper layer */ 275 if ((status == LLCP_STATUS_SUCCESS) && 276 (llcp_cb.lcb.symm_state == LLCP_LINK_SYMM_LOCAL_XMIT_NEXT)) { 277 llcp_link_check_send_data(); 278 } 279 280 return status; 281} 282 283/******************************************************************************* 284** 285** Function llcp_sdp_get_sap_by_name 286** 287** Description Search SAP by service name 288** 289** 290** Returns SAP if success 291** 292*******************************************************************************/ 293uint8_t llcp_sdp_get_sap_by_name(char* p_name, uint8_t length) { 294 uint8_t sap; 295 tLLCP_APP_CB* p_app_cb; 296 297 for (sap = LLCP_SAP_SDP; sap <= LLCP_UPPER_BOUND_SDP_SAP; sap++) { 298 p_app_cb = llcp_util_get_app_cb(sap); 299 300 if ((p_app_cb) && (p_app_cb->p_app_cback) && 301 (strlen((char*)p_app_cb->p_service_name) == length) && 302 (!strncmp((char*)p_app_cb->p_service_name, p_name, length))) { 303 /* if device is under LLCP DTA testing */ 304 if (llcp_cb.p_dta_cback && (!strncmp((char*)p_app_cb->p_service_name, 305 "urn:nfc:sn:cl-echo-in", length))) { 306 llcp_cb.dta_snl_resp = true; 307 } 308 309 return (sap); 310 } 311 } 312 return 0; 313} 314 315/******************************************************************************* 316** 317** Function llcp_sdp_return_sap 318** 319** Description Report TID and SAP to requester 320** 321** 322** Returns void 323** 324*******************************************************************************/ 325static void llcp_sdp_return_sap(uint8_t tid, uint8_t sap) { 326 uint8_t i; 327 328 DLOG_IF(INFO, nfc_debug_enabled) 329 << StringPrintf("tid=0x%x, SAP=0x%x", tid, sap); 330 331 for (i = 0; i < LLCP_MAX_SDP_TRANSAC; i++) { 332 if ((llcp_cb.sdp_cb.transac[i].p_cback) && 333 (llcp_cb.sdp_cb.transac[i].tid == tid)) { 334 (*llcp_cb.sdp_cb.transac[i].p_cback)(tid, sap); 335 336 llcp_cb.sdp_cb.transac[i].p_cback = NULL; 337 } 338 } 339} 340 341/******************************************************************************* 342** 343** Function llcp_sdp_proc_deactivation 344** 345** Description Report SDP failure for any pending request because of 346** deactivation 347** 348** 349** Returns void 350** 351*******************************************************************************/ 352void llcp_sdp_proc_deactivation(void) { 353 uint8_t i; 354 355 DLOG_IF(INFO, nfc_debug_enabled) << __func__; 356 357 for (i = 0; i < LLCP_MAX_SDP_TRANSAC; i++) { 358 if (llcp_cb.sdp_cb.transac[i].p_cback) { 359 (*llcp_cb.sdp_cb.transac[i].p_cback)(llcp_cb.sdp_cb.transac[i].tid, 0x00); 360 361 llcp_cb.sdp_cb.transac[i].p_cback = NULL; 362 } 363 } 364 365 /* free any pending SNL PDU */ 366 if (llcp_cb.sdp_cb.p_snl) { 367 GKI_freebuf(llcp_cb.sdp_cb.p_snl); 368 llcp_cb.sdp_cb.p_snl = NULL; 369 } 370 371 llcp_cb.sdp_cb.next_tid = 0; 372 llcp_cb.dta_snl_resp = false; 373} 374 375/******************************************************************************* 376** 377** Function llcp_sdp_proc_snl 378** 379** Description Process SDREQ and SDRES in SNL 380** 381** 382** Returns LLCP_STATUS 383** 384*******************************************************************************/ 385tLLCP_STATUS llcp_sdp_proc_snl(uint16_t sdu_length, uint8_t* p) { 386 uint8_t type, length, tid, sap, *p_value; 387 388 DLOG_IF(INFO, nfc_debug_enabled) << __func__; 389 390 if ((llcp_cb.lcb.agreed_major_version < LLCP_MIN_SNL_MAJOR_VERSION) || 391 ((llcp_cb.lcb.agreed_major_version == LLCP_MIN_SNL_MAJOR_VERSION) && 392 (llcp_cb.lcb.agreed_minor_version < LLCP_MIN_SNL_MINOR_VERSION))) { 393 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 394 "version number less than 1.1, SNL not " 395 "supported."); 396 return LLCP_STATUS_FAIL; 397 } 398 while (sdu_length >= 2) /* at least type and length */ 399 { 400 BE_STREAM_TO_UINT8(type, p); 401 BE_STREAM_TO_UINT8(length, p); 402 403 switch (type) { 404 case LLCP_SDREQ_TYPE: 405 if ((length > 1) /* TID and sevice name */ 406 && 407 (sdu_length >= 2 + length)) /* type, length, TID and service name */ 408 { 409 p_value = p; 410 BE_STREAM_TO_UINT8(tid, p_value); 411 sap = llcp_sdp_get_sap_by_name((char*)p_value, (uint8_t)(length - 1)); 412 /* fix to pass TC_CTO_TAR_BI_03_x (x=5) test case 413 * As per the LLCP test specification v1.2.00 by receiving erroneous 414 * SNL PDU i'e with improper service name "urn:nfc:sn:dta-co-echo-in", 415 * the IUT should not send any PDU except SYMM PDU */ 416 if (appl_dta_mode_flag == 1 && sap == 0x00) { 417 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 418 "%s: In dta mode sap == 0x00 p_value = %s", __func__, p_value); 419 if ((length - 1) == strlen((const char*)p_value)) { 420 DLOG_IF(INFO, nfc_debug_enabled) 421 << StringPrintf("%s: Strings are not equal", __func__); 422 llcp_sdp_send_sdres(tid, sap); 423 } 424 } else { 425 llcp_sdp_send_sdres(tid, sap); 426 } 427 } else { 428 /*For P2P in LLCP mode TC_CTO_TAR_BI_03_x(x=3) fix*/ 429 if (appl_dta_mode_flag == 1 && 430 ((nfa_dm_cb.eDtaMode & 0x0F) == NFA_DTA_LLCP_MODE)) { 431 LOG(ERROR) << StringPrintf("%s: Calling llcp_sdp_send_sdres", 432 __func__); 433 tid = 0x01; 434 sap = 0x00; 435 llcp_sdp_send_sdres(tid, sap); 436 } 437 LOG(ERROR) << StringPrintf("bad length (%d) in LLCP_SDREQ_TYPE", 438 length); 439 } 440 break; 441 442 case LLCP_SDRES_TYPE: 443 if ((length == LLCP_SDRES_LEN) /* TID and SAP */ 444 && (sdu_length >= 2 + length)) /* type, length, TID and SAP */ 445 { 446 p_value = p; 447 BE_STREAM_TO_UINT8(tid, p_value); 448 BE_STREAM_TO_UINT8(sap, p_value); 449 llcp_sdp_return_sap(tid, sap); 450 } else { 451 LOG(ERROR) << StringPrintf("bad length (%d) in LLCP_SDRES_TYPE", 452 length); 453 } 454 break; 455 456 default: 457 LOG(WARNING) << StringPrintf("Unknown type (0x%x) is ignored", type); 458 break; 459 } 460 461 if (sdu_length >= 2 + length) /* type, length, value */ 462 { 463 sdu_length -= 2 + length; 464 p += length; 465 } else { 466 break; 467 } 468 } 469 470 if (sdu_length) { 471 LOG(ERROR) << StringPrintf("Bad format of SNL"); 472 return LLCP_STATUS_FAIL; 473 } else { 474 return LLCP_STATUS_SUCCESS; 475 } 476} 477