1 /* 2 * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* 20 * DOC: Defines scan utility functions 21 */ 22 23 #include <wlan_cmn.h> 24 #include <wlan_scan_ucfg_api.h> 25 #include <wlan_scan_utils_api.h> 26 #include <../../core/src/wlan_scan_cache_db.h> 27 #include <../../core/src/wlan_scan_main.h> 28 #include <wlan_reg_services_api.h> 29 30 #define MAX_IE_LEN 1024 31 #define SHORT_SSID_LEN 4 32 #define NEIGHBOR_AP_LEN 1 33 #define BSS_PARAMS_LEN 1 34 35 const char* 36 util_scan_get_ev_type_name(enum scan_event_type type) 37 { 38 static const char * const event_name[] = { 39 [SCAN_EVENT_TYPE_STARTED] = "STARTED", 40 [SCAN_EVENT_TYPE_COMPLETED] = "COMPLETED", 41 [SCAN_EVENT_TYPE_BSS_CHANNEL] = "HOME_CHANNEL", 42 [SCAN_EVENT_TYPE_FOREIGN_CHANNEL] = "FOREIGN_CHANNEL", 43 [SCAN_EVENT_TYPE_DEQUEUED] = "DEQUEUED", 44 [SCAN_EVENT_TYPE_PREEMPTED] = "PREEMPTED", 45 [SCAN_EVENT_TYPE_START_FAILED] = "START_FAILED", 46 [SCAN_EVENT_TYPE_RESTARTED] = "RESTARTED", 47 [SCAN_EVENT_TYPE_FOREIGN_CHANNEL_EXIT] = "FOREIGN_CHANNEL_EXIT", 48 [SCAN_EVENT_TYPE_SUSPENDED] = "SUSPENDED", 49 [SCAN_EVENT_TYPE_RESUMED] = "RESUMED", 50 [SCAN_EVENT_TYPE_NLO_COMPLETE] = "NLO_COMPLETE", 51 [SCAN_EVENT_TYPE_NLO_MATCH] = "NLO_MATCH", 52 [SCAN_EVENT_TYPE_INVALID] = "INVALID", 53 [SCAN_EVENT_TYPE_GPIO_TIMEOUT] = "GPIO_TIMEOUT", 54 [SCAN_EVENT_TYPE_RADIO_MEASUREMENT_START] = 55 "RADIO_MEASUREMENT_START", 56 [SCAN_EVENT_TYPE_RADIO_MEASUREMENT_END] = 57 "RADIO_MEASUREMENT_END", 58 [SCAN_EVENT_TYPE_BSSID_MATCH] = "BSSID_MATCH", 59 [SCAN_EVENT_TYPE_FOREIGN_CHANNEL_GET_NF] = 60 "FOREIGN_CHANNEL_GET_NF", 61 }; 62 63 if (type >= SCAN_EVENT_TYPE_MAX) 64 return "UNKNOWN"; 65 66 return event_name[type]; 67 } 68 69 70 const char* 71 util_scan_get_ev_reason_name(enum scan_completion_reason reason) 72 { 73 static const char * const reason_name[] = { 74 [SCAN_REASON_NONE] = "NONE", 75 [SCAN_REASON_COMPLETED] = "COMPLETED", 76 [SCAN_REASON_CANCELLED] = "CANCELLED", 77 [SCAN_REASON_PREEMPTED] = "PREEMPTED", 78 [SCAN_REASON_TIMEDOUT] = "TIMEDOUT", 79 [SCAN_REASON_INTERNAL_FAILURE] = "INTERNAL_FAILURE", 80 [SCAN_REASON_SUSPENDED] = "SUSPENDED", 81 [SCAN_REASON_RUN_FAILED] = "RUN_FAILED", 82 [SCAN_REASON_TERMINATION_FUNCTION] = "TERMINATION_FUNCTION", 83 [SCAN_REASON_MAX_OFFCHAN_RETRIES] = "MAX_OFFCHAN_RETRIES", 84 [SCAN_REASON_DFS_VIOLATION] = "DFS_NOL_VIOLATION", 85 }; 86 87 if (reason >= SCAN_REASON_MAX) 88 return "UNKNOWN"; 89 90 return reason_name[reason]; 91 } 92 93 qdf_time_t 94 util_get_last_scan_time(struct wlan_objmgr_vdev *vdev) 95 { 96 uint8_t pdev_id; 97 struct wlan_scan_obj *scan_obj; 98 99 if (!vdev) { 100 scm_warn("null vdev"); 101 QDF_ASSERT(0); 102 return 0; 103 } 104 pdev_id = wlan_scan_vdev_get_pdev_id(vdev); 105 scan_obj = wlan_vdev_get_scan_obj(vdev); 106 107 if (scan_obj) 108 return scan_obj->pdev_info[pdev_id].last_scan_time; 109 else 110 return 0; 111 } 112 113 enum wlan_band util_scan_scm_chan_to_band(uint32_t chan) 114 { 115 if (WLAN_CHAN_IS_2GHZ(chan)) 116 return WLAN_BAND_2_4_GHZ; 117 118 return WLAN_BAND_5_GHZ; 119 } 120 121 enum wlan_band util_scan_scm_freq_to_band(uint16_t freq) 122 { 123 if (WLAN_REG_IS_24GHZ_CH_FREQ(freq)) 124 return WLAN_BAND_2_4_GHZ; 125 126 return WLAN_BAND_5_GHZ; 127 } 128 129 bool util_is_scan_entry_match( 130 struct scan_cache_entry *entry1, 131 struct scan_cache_entry *entry2) 132 { 133 134 if (entry1->cap_info.wlan_caps.ess != 135 entry2->cap_info.wlan_caps.ess) 136 return false; 137 138 if (entry1->cap_info.wlan_caps.ess && 139 !qdf_mem_cmp(entry1->bssid.bytes, 140 entry2->bssid.bytes, QDF_MAC_ADDR_SIZE)) { 141 /* Check for BSS */ 142 if (util_is_ssid_match(&entry1->ssid, &entry2->ssid) || 143 util_scan_is_null_ssid(&entry1->ssid) || 144 util_scan_is_null_ssid(&entry2->ssid)) 145 return true; 146 } else if (entry1->cap_info.wlan_caps.ibss && 147 (entry1->channel.chan_freq == 148 entry2->channel.chan_freq)) { 149 /* 150 * Same channel cannot have same SSID for 151 * different IBSS, so no need to check BSSID 152 */ 153 if (util_is_ssid_match( 154 &entry1->ssid, &entry2->ssid)) 155 return true; 156 } else if (!entry1->cap_info.wlan_caps.ibss && 157 !entry1->cap_info.wlan_caps.ess && 158 !qdf_mem_cmp(entry1->bssid.bytes, 159 entry2->bssid.bytes, QDF_MAC_ADDR_SIZE)) { 160 /* In case of P2P devices, ess and ibss will be set to zero */ 161 return true; 162 } 163 164 return false; 165 } 166 167 static bool util_is_pureg_rate(uint8_t *rates, uint8_t nrates) 168 { 169 static const uint8_t g_rates[] = {12, 18, 24, 36, 48, 72, 96, 108}; 170 bool pureg = false; 171 uint8_t i, j; 172 173 for (i = 0; i < nrates; i++) { 174 for (j = 0; j < QDF_ARRAY_SIZE(g_rates); j++) { 175 if (WLAN_RV(rates[i]) == g_rates[j]) { 176 pureg = true; 177 break; 178 } 179 } 180 if (pureg) 181 break; 182 } 183 184 return pureg; 185 } 186 187 #ifdef CONFIG_BAND_6GHZ 188 static struct he_oper_6g_param *util_scan_get_he_6g_params(uint8_t *he_ops) 189 { 190 uint8_t len; 191 uint32_t he_oper_params; 192 193 if (!he_ops) 194 return NULL; 195 196 len = he_ops[1]; 197 he_ops += sizeof(struct ie_header); 198 199 if (len < WLAN_HEOP_FIXED_PARAM_LENGTH) 200 return NULL; 201 202 /* element id extension */ 203 he_ops++; 204 len--; 205 206 he_oper_params = LE_READ_4(he_ops); 207 if (!(he_oper_params & WLAN_HEOP_6GHZ_INFO_PRESENT_MASK)) 208 return NULL; 209 210 /* fixed params - element id extension */ 211 he_ops += WLAN_HEOP_FIXED_PARAM_LENGTH - 1; 212 len -= WLAN_HEOP_FIXED_PARAM_LENGTH - 1; 213 214 if (!len) 215 return NULL; 216 217 /* vht oper params */ 218 if (he_oper_params & WLAN_HEOP_VHTOP_PRESENT_MASK) { 219 if (len < WLAN_HEOP_VHTOP_LENGTH) 220 return NULL; 221 he_ops += WLAN_HEOP_VHTOP_LENGTH; 222 len -= WLAN_HEOP_VHTOP_LENGTH; 223 } 224 225 if (!len) 226 return NULL; 227 228 if (he_oper_params & WLAN_HEOP_CO_LOCATED_BSS_MASK) { 229 he_ops += WLAN_HEOP_CO_LOCATED_BSS_LENGTH; 230 len -= WLAN_HEOP_CO_LOCATED_BSS_LENGTH; 231 } 232 233 if (len < sizeof(struct he_oper_6g_param)) 234 return NULL; 235 236 return (struct he_oper_6g_param *)he_ops; 237 } 238 239 static void 240 util_scan_get_chan_from_he_6g_params(struct scan_cache_entry *scan_params, 241 uint8_t *chan_idx) 242 { 243 struct he_oper_6g_param *he_6g_params; 244 uint8_t *he_ops; 245 246 he_ops = util_scan_entry_heop(scan_params); 247 if (!util_scan_entry_hecap(scan_params) || !he_ops) 248 return; 249 250 he_6g_params = util_scan_get_he_6g_params(he_ops); 251 if (!he_6g_params) 252 return; 253 254 *chan_idx = he_6g_params->primary_channel; 255 } 256 257 static enum wlan_phymode 258 util_scan_get_phymode_6g(struct wlan_objmgr_pdev *pdev, 259 struct scan_cache_entry *scan_params) 260 { 261 struct he_oper_6g_param *he_6g_params; 262 enum wlan_phymode phymode = WLAN_PHYMODE_11AXA_HE20; 263 uint8_t *he_ops; 264 uint8_t band_mask = BIT(REG_BAND_6G); 265 266 he_ops = util_scan_entry_heop(scan_params); 267 if (!util_scan_entry_hecap(scan_params) || !he_ops) 268 return phymode; 269 270 he_6g_params = util_scan_get_he_6g_params(he_ops); 271 if (!he_6g_params) 272 return phymode; 273 274 switch (he_6g_params->width) { 275 case WLAN_HE_6GHZ_CHWIDTH_20: 276 phymode = WLAN_PHYMODE_11AXA_HE20; 277 break; 278 case WLAN_HE_6GHZ_CHWIDTH_40: 279 phymode = WLAN_PHYMODE_11AXA_HE40; 280 break; 281 case WLAN_HE_6GHZ_CHWIDTH_80: 282 phymode = WLAN_PHYMODE_11AXA_HE80; 283 break; 284 case WLAN_HE_6GHZ_CHWIDTH_160_80_80: 285 if (WLAN_IS_HE80_80(he_6g_params)) 286 phymode = WLAN_PHYMODE_11AXA_HE80_80; 287 else if (WLAN_IS_HE160(he_6g_params)) 288 phymode = WLAN_PHYMODE_11AXA_HE160; 289 else 290 phymode = WLAN_PHYMODE_11AXA_HE80; 291 break; 292 default: 293 scm_err("Invalid he_6g_params width: %d", he_6g_params->width); 294 phymode = WLAN_PHYMODE_11AXA_HE20; 295 break; 296 } 297 298 if (he_6g_params->chan_freq_seg0) 299 scan_params->channel.cfreq0 = 300 wlan_reg_chan_band_to_freq(pdev, 301 he_6g_params->chan_freq_seg0, 302 band_mask); 303 if (he_6g_params->chan_freq_seg1) 304 scan_params->channel.cfreq1 = 305 wlan_reg_chan_band_to_freq(pdev, 306 he_6g_params->chan_freq_seg1, 307 band_mask); 308 309 return phymode; 310 } 311 #else 312 static void 313 util_scan_get_chan_from_he_6g_params(struct scan_cache_entry *scan_params, 314 uint8_t *chan_idx) 315 {} 316 static inline enum wlan_phymode 317 util_scan_get_phymode_6g(struct wlan_objmgr_pdev *pdev, 318 struct scan_cache_entry *scan_params) 319 { 320 return WLAN_PHYMODE_AUTO; 321 } 322 #endif 323 324 static inline 325 uint32_t util_scan_sec_chan_freq_from_htinfo(struct wlan_ie_htinfo_cmn *htinfo, 326 uint32_t primary_chan_freq) 327 { 328 if (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_ABOVE) 329 return primary_chan_freq + WLAN_CHAN_SPACING_20MHZ; 330 else if (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_BELOW) 331 return primary_chan_freq - WLAN_CHAN_SPACING_20MHZ; 332 333 return 0; 334 } 335 336 static enum wlan_phymode 337 util_scan_get_phymode_5g(struct wlan_objmgr_pdev *pdev, 338 struct scan_cache_entry *scan_params) 339 { 340 enum wlan_phymode phymode = WLAN_PHYMODE_AUTO; 341 uint16_t ht_cap = 0; 342 struct htcap_cmn_ie *htcap; 343 struct wlan_ie_htinfo_cmn *htinfo; 344 struct wlan_ie_vhtop *vhtop; 345 uint8_t band_mask = BIT(REG_BAND_5G); 346 347 htcap = (struct htcap_cmn_ie *) 348 util_scan_entry_htcap(scan_params); 349 htinfo = (struct wlan_ie_htinfo_cmn *) 350 util_scan_entry_htinfo(scan_params); 351 vhtop = (struct wlan_ie_vhtop *) 352 util_scan_entry_vhtop(scan_params); 353 354 if (!(htcap && htinfo)) 355 return WLAN_PHYMODE_11A; 356 357 if (htcap) 358 ht_cap = le16toh(htcap->hc_cap); 359 360 if (ht_cap & WLAN_HTCAP_C_CHWIDTH40) 361 phymode = WLAN_PHYMODE_11NA_HT40; 362 else 363 phymode = WLAN_PHYMODE_11NA_HT20; 364 365 scan_params->channel.cfreq0 = 366 util_scan_sec_chan_freq_from_htinfo(htinfo, 367 scan_params->channel.chan_freq); 368 369 if (util_scan_entry_vhtcap(scan_params) && vhtop) { 370 switch (vhtop->vht_op_chwidth) { 371 case WLAN_VHTOP_CHWIDTH_2040: 372 if (ht_cap & WLAN_HTCAP_C_CHWIDTH40) 373 phymode = WLAN_PHYMODE_11AC_VHT40; 374 else 375 phymode = WLAN_PHYMODE_11AC_VHT20; 376 break; 377 case WLAN_VHTOP_CHWIDTH_80: 378 if (WLAN_IS_REVSIG_VHT80_80(vhtop)) 379 phymode = WLAN_PHYMODE_11AC_VHT80_80; 380 else if (WLAN_IS_REVSIG_VHT160(vhtop)) 381 phymode = WLAN_PHYMODE_11AC_VHT160; 382 else 383 phymode = WLAN_PHYMODE_11AC_VHT80; 384 break; 385 case WLAN_VHTOP_CHWIDTH_160: 386 phymode = WLAN_PHYMODE_11AC_VHT160; 387 break; 388 case WLAN_VHTOP_CHWIDTH_80_80: 389 phymode = WLAN_PHYMODE_11AC_VHT80_80; 390 break; 391 default: 392 scm_err("bad channel: %d", 393 vhtop->vht_op_chwidth); 394 phymode = WLAN_PHYMODE_11AC_VHT20; 395 break; 396 } 397 if (vhtop->vht_op_ch_freq_seg1) 398 scan_params->channel.cfreq0 = 399 wlan_reg_chan_band_to_freq(pdev, 400 vhtop->vht_op_ch_freq_seg1, 401 band_mask); 402 if (vhtop->vht_op_ch_freq_seg2) 403 scan_params->channel.cfreq1 = 404 wlan_reg_chan_band_to_freq(pdev, 405 vhtop->vht_op_ch_freq_seg2, 406 band_mask); 407 } 408 409 if (!util_scan_entry_hecap(scan_params)) 410 return phymode; 411 412 /* for 5Ghz Check for HE, only if VHT cap and HE cap are present */ 413 if (!IS_WLAN_PHYMODE_VHT(phymode)) 414 return phymode; 415 416 switch (phymode) { 417 case WLAN_PHYMODE_11AC_VHT20: 418 phymode = WLAN_PHYMODE_11AXA_HE20; 419 break; 420 case WLAN_PHYMODE_11AC_VHT40: 421 phymode = WLAN_PHYMODE_11AXA_HE40; 422 break; 423 case WLAN_PHYMODE_11AC_VHT80: 424 phymode = WLAN_PHYMODE_11AXA_HE80; 425 break; 426 case WLAN_PHYMODE_11AC_VHT160: 427 phymode = WLAN_PHYMODE_11AXA_HE160; 428 break; 429 case WLAN_PHYMODE_11AC_VHT80_80: 430 phymode = WLAN_PHYMODE_11AXA_HE80_80; 431 break; 432 default: 433 phymode = WLAN_PHYMODE_11AXA_HE20; 434 break; 435 } 436 437 return phymode; 438 } 439 440 static enum wlan_phymode 441 util_scan_get_phymode_2g(struct scan_cache_entry *scan_params) 442 { 443 enum wlan_phymode phymode = WLAN_PHYMODE_AUTO; 444 uint16_t ht_cap = 0; 445 struct htcap_cmn_ie *htcap; 446 struct wlan_ie_htinfo_cmn *htinfo; 447 struct wlan_ie_vhtop *vhtop; 448 449 htcap = (struct htcap_cmn_ie *) 450 util_scan_entry_htcap(scan_params); 451 htinfo = (struct wlan_ie_htinfo_cmn *) 452 util_scan_entry_htinfo(scan_params); 453 vhtop = (struct wlan_ie_vhtop *) 454 util_scan_entry_vhtop(scan_params); 455 456 if (htcap) 457 ht_cap = le16toh(htcap->hc_cap); 458 459 if (htcap && htinfo) { 460 if ((ht_cap & WLAN_HTCAP_C_CHWIDTH40) && 461 (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_ABOVE)) 462 phymode = WLAN_PHYMODE_11NG_HT40PLUS; 463 else if ((ht_cap & WLAN_HTCAP_C_CHWIDTH40) && 464 (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_BELOW)) 465 phymode = WLAN_PHYMODE_11NG_HT40MINUS; 466 else 467 phymode = WLAN_PHYMODE_11NG_HT20; 468 } else if (util_scan_entry_xrates(scan_params)) { 469 /* only 11G stations will have more than 8 rates */ 470 phymode = WLAN_PHYMODE_11G; 471 } else { 472 /* Some mischievous g-only APs do not set extended rates */ 473 if (util_scan_entry_rates(scan_params)) { 474 if (util_is_pureg_rate(&scan_params->ie_list.rates[2], 475 scan_params->ie_list.rates[1])) 476 phymode = WLAN_PHYMODE_11G; 477 else 478 phymode = WLAN_PHYMODE_11B; 479 } else { 480 phymode = WLAN_PHYMODE_11B; 481 } 482 } 483 484 /* Check for VHT only if HT cap is present */ 485 if (!IS_WLAN_PHYMODE_HT(phymode)) 486 return phymode; 487 488 scan_params->channel.cfreq0 = 489 util_scan_sec_chan_freq_from_htinfo(htinfo, 490 scan_params->channel.chan_freq); 491 492 if (util_scan_entry_vhtcap(scan_params) && vhtop) { 493 switch (vhtop->vht_op_chwidth) { 494 case WLAN_VHTOP_CHWIDTH_2040: 495 if (phymode == WLAN_PHYMODE_11NG_HT40PLUS) 496 phymode = WLAN_PHYMODE_11AC_VHT40PLUS_2G; 497 else if (phymode == WLAN_PHYMODE_11NG_HT40MINUS) 498 phymode = WLAN_PHYMODE_11AC_VHT40MINUS_2G; 499 else 500 phymode = WLAN_PHYMODE_11AC_VHT20_2G; 501 502 break; 503 default: 504 scm_info("bad vht_op_chwidth: %d", 505 vhtop->vht_op_chwidth); 506 phymode = WLAN_PHYMODE_11AC_VHT20_2G; 507 break; 508 } 509 } 510 511 if (!util_scan_entry_hecap(scan_params)) 512 return phymode; 513 514 if (phymode == WLAN_PHYMODE_11AC_VHT40PLUS_2G || 515 phymode == WLAN_PHYMODE_11NG_HT40PLUS) 516 phymode = WLAN_PHYMODE_11AXG_HE40PLUS; 517 else if (phymode == WLAN_PHYMODE_11AC_VHT40MINUS_2G || 518 phymode == WLAN_PHYMODE_11NG_HT40MINUS) 519 phymode = WLAN_PHYMODE_11AXG_HE40MINUS; 520 else 521 phymode = WLAN_PHYMODE_11AXG_HE20; 522 523 return phymode; 524 } 525 526 static enum wlan_phymode 527 util_scan_get_phymode(struct wlan_objmgr_pdev *pdev, 528 struct scan_cache_entry *scan_params) 529 { 530 if (WLAN_REG_IS_24GHZ_CH_FREQ(scan_params->channel.chan_freq)) 531 return util_scan_get_phymode_2g(scan_params); 532 else if (WLAN_REG_IS_6GHZ_CHAN_FREQ(scan_params->channel.chan_freq)) 533 return util_scan_get_phymode_6g(pdev, scan_params); 534 else 535 return util_scan_get_phymode_5g(pdev, scan_params); 536 } 537 538 static QDF_STATUS 539 util_scan_parse_chan_switch_wrapper_ie(struct scan_cache_entry *scan_params, 540 struct ie_header *sub_ie, qdf_size_t sub_ie_len) 541 { 542 /* Walk through to check nothing is malformed */ 543 while (sub_ie_len >= sizeof(struct ie_header)) { 544 /* At least one more header is present */ 545 sub_ie_len -= sizeof(struct ie_header); 546 547 if (sub_ie->ie_len == 0) { 548 sub_ie += 1; 549 continue; 550 } 551 if (sub_ie_len < sub_ie->ie_len) { 552 scm_err("Incomplete corrupted IE:%x", 553 WLAN_ELEMID_CHAN_SWITCH_WRAP); 554 return QDF_STATUS_E_INVAL; 555 } 556 switch (sub_ie->ie_id) { 557 case WLAN_ELEMID_COUNTRY: 558 scan_params->ie_list.country = (uint8_t *)sub_ie; 559 break; 560 case WLAN_ELEMID_WIDE_BAND_CHAN_SWITCH: 561 scan_params->ie_list.widebw = (uint8_t *)sub_ie; 562 break; 563 case WLAN_ELEMID_VHT_TX_PWR_ENVLP: 564 scan_params->ie_list.txpwrenvlp = (uint8_t *)sub_ie; 565 break; 566 } 567 /* Consume sub info element */ 568 sub_ie_len -= sub_ie->ie_len; 569 /* go to next Sub IE */ 570 sub_ie = (struct ie_header *) 571 (((uint8_t *) sub_ie) + 572 sizeof(struct ie_header) + sub_ie->ie_len); 573 } 574 575 return QDF_STATUS_SUCCESS; 576 } 577 578 bool 579 util_scan_is_hidden_ssid(struct ie_ssid *ssid) 580 { 581 uint8_t i; 582 583 /* 584 * We flag this as Hidden SSID if the Length is 0 585 * of the SSID only contains 0's 586 */ 587 if (!ssid || !ssid->ssid_len) 588 return true; 589 590 for (i = 0; i < ssid->ssid_len; i++) 591 if (ssid->ssid[i] != 0) 592 return false; 593 594 /* All 0's */ 595 return true; 596 } 597 598 static QDF_STATUS 599 util_scan_update_rnr(struct rnr_bss_info *rnr, 600 struct neighbor_ap_info_field *ap_info, 601 uint8_t **data) 602 { 603 uint16_t fieldtype; 604 uint8_t *tmp = *data; 605 606 fieldtype = ap_info->tbtt_header.tbbt_info_fieldtype; 607 608 switch (fieldtype) { 609 case TBTT_NEIGHBOR_AP_OFFSET_ONLY: 610 /* Dont store it skip*/ 611 *data = tmp + NEIGHBOR_AP_LEN; 612 break; 613 614 case TBTT_NEIGHBOR_AP_BSS_PARAM: 615 /* Dont store it skip*/ 616 break; 617 618 case TBTT_NEIGHBOR_AP_SHORTSSID: 619 rnr->channel_number = ap_info->channel_number; 620 rnr->operating_class = ap_info->operting_class; 621 qdf_mem_copy(&rnr->short_ssid, &tmp[1], SHORT_SSID_LEN); 622 *data = tmp + NEIGHBOR_AP_LEN + SHORT_SSID_LEN; 623 break; 624 625 case TBTT_NEIGHBOR_AP_S_SSID_BSS_PARAM: 626 rnr->channel_number = ap_info->channel_number; 627 rnr->operating_class = ap_info->operting_class; 628 qdf_mem_copy(&rnr->short_ssid, &tmp[1], SHORT_SSID_LEN); 629 rnr->bss_params = tmp[5]; 630 *data = tmp + NEIGHBOR_AP_LEN + SHORT_SSID_LEN + BSS_PARAMS_LEN; 631 break; 632 633 case TBTT_NEIGHBOR_AP_BSSID: 634 rnr->channel_number = ap_info->channel_number; 635 rnr->operating_class = ap_info->operting_class; 636 qdf_mem_copy(&rnr->bssid, &tmp[1], QDF_MAC_ADDR_SIZE); 637 *data = tmp + NEIGHBOR_AP_LEN + QDF_MAC_ADDR_SIZE; 638 break; 639 640 case TBTT_NEIGHBOR_AP_BSSID_BSS_PARAM: 641 rnr->channel_number = ap_info->channel_number; 642 rnr->operating_class = ap_info->operting_class; 643 qdf_mem_copy(&rnr->bssid, &tmp[1], QDF_MAC_ADDR_SIZE); 644 rnr->bss_params = tmp[7]; 645 *data = tmp + NEIGHBOR_AP_LEN + QDF_MAC_ADDR_SIZE 646 + BSS_PARAMS_LEN; 647 break; 648 649 case TBTT_NEIGHBOR_AP_BSSSID_S_SSID: 650 rnr->channel_number = ap_info->channel_number; 651 rnr->operating_class = ap_info->operting_class; 652 qdf_mem_copy(&rnr->bssid, &tmp[1], QDF_MAC_ADDR_SIZE); 653 qdf_mem_copy(&rnr->short_ssid, &tmp[7], SHORT_SSID_LEN); 654 *data = tmp + NEIGHBOR_AP_LEN + QDF_MAC_ADDR_SIZE 655 + SHORT_SSID_LEN; 656 break; 657 658 case TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM: 659 rnr->channel_number = ap_info->channel_number; 660 rnr->operating_class = ap_info->operting_class; 661 qdf_mem_copy(&rnr->bssid, &tmp[1], QDF_MAC_ADDR_SIZE); 662 qdf_mem_copy(&rnr->short_ssid, &tmp[7], SHORT_SSID_LEN); 663 rnr->bss_params = tmp[11]; 664 *data = tmp + NEIGHBOR_AP_LEN + QDF_MAC_ADDR_SIZE 665 + SHORT_SSID_LEN + BSS_PARAMS_LEN; 666 break; 667 668 default: 669 scm_debug("Wrong fieldtype"); 670 } 671 672 return QDF_STATUS_SUCCESS; 673 } 674 675 static QDF_STATUS 676 util_scan_parse_rnr_ie(struct scan_cache_entry *scan_entry, 677 struct ie_header *ie) 678 { 679 uint32_t rnr_ie_len; 680 uint16_t tbtt_count, tbtt_length, i, fieldtype; 681 uint8_t *data; 682 struct neighbor_ap_info_field *neighbor_ap_info; 683 684 rnr_ie_len = ie->ie_len; 685 data = (uint8_t *)ie + sizeof(struct ie_header); 686 687 while (data < (uint8_t *)ie + rnr_ie_len + 2) { 688 neighbor_ap_info = (struct neighbor_ap_info_field *)data; 689 tbtt_count = neighbor_ap_info->tbtt_header.tbtt_info_count; 690 tbtt_length = neighbor_ap_info->tbtt_header.tbtt_info_length; 691 fieldtype = neighbor_ap_info->tbtt_header.tbbt_info_fieldtype; 692 scm_debug("channel number %d, op class %d", 693 neighbor_ap_info->channel_number, 694 neighbor_ap_info->operting_class); 695 scm_debug("tbtt_count %d, tbtt_length %d, fieldtype %d", 696 tbtt_count, tbtt_length, fieldtype); 697 for (i = 0; i < (tbtt_count + 1) && i < MAX_RNR_BSS; i++) { 698 data = data + sizeof(struct neighbor_ap_info_field); 699 util_scan_update_rnr(&scan_entry->rnr.bss_info[i], 700 neighbor_ap_info, 701 &data); 702 } 703 } 704 705 return QDF_STATUS_SUCCESS; 706 } 707 708 static QDF_STATUS 709 util_scan_parse_extn_ie(struct scan_cache_entry *scan_params, 710 struct ie_header *ie) 711 { 712 struct extn_ie_header *extn_ie = (struct extn_ie_header *) ie; 713 714 switch (extn_ie->ie_extn_id) { 715 case WLAN_EXTN_ELEMID_MAX_CHAN_SWITCH_TIME: 716 scan_params->ie_list.mcst = (uint8_t *)ie; 717 break; 718 case WLAN_EXTN_ELEMID_SRP: 719 scan_params->ie_list.srp = (uint8_t *)ie; 720 break; 721 case WLAN_EXTN_ELEMID_HECAP: 722 scan_params->ie_list.hecap = (uint8_t *)ie; 723 break; 724 case WLAN_EXTN_ELEMID_HEOP: 725 scan_params->ie_list.heop = (uint8_t *)ie; 726 break; 727 case WLAN_EXTN_ELEMID_ESP: 728 scan_params->ie_list.esp = (uint8_t *)ie; 729 break; 730 case WLAN_EXTN_ELEMID_MUEDCA: 731 scan_params->ie_list.muedca = (uint8_t *)ie; 732 break; 733 case WLAN_EXTN_ELEMID_HE_6G_CAP: 734 scan_params->ie_list.hecap_6g = (uint8_t *)ie; 735 break; 736 default: 737 break; 738 } 739 return QDF_STATUS_SUCCESS; 740 } 741 742 static QDF_STATUS 743 util_scan_parse_vendor_ie(struct scan_cache_entry *scan_params, 744 struct ie_header *ie) 745 { 746 if (!scan_params->ie_list.vendor) 747 scan_params->ie_list.vendor = (uint8_t *)ie; 748 749 if (is_wpa_oui((uint8_t *)ie)) { 750 scan_params->ie_list.wpa = (uint8_t *)ie; 751 } else if (is_wps_oui((uint8_t *)ie)) { 752 scan_params->ie_list.wps = (uint8_t *)ie; 753 /* WCN IE should be a subset of WPS IE */ 754 if (is_wcn_oui((uint8_t *)ie)) 755 scan_params->ie_list.wcn = (uint8_t *)ie; 756 } else if (is_wme_param((uint8_t *)ie)) { 757 scan_params->ie_list.wmeparam = (uint8_t *)ie; 758 } else if (is_wme_info((uint8_t *)ie)) { 759 scan_params->ie_list.wmeinfo = (uint8_t *)ie; 760 } else if (is_atheros_oui((uint8_t *)ie)) { 761 scan_params->ie_list.athcaps = (uint8_t *)ie; 762 } else if (is_atheros_extcap_oui((uint8_t *)ie)) { 763 scan_params->ie_list.athextcaps = (uint8_t *)ie; 764 } else if (is_sfa_oui((uint8_t *)ie)) { 765 scan_params->ie_list.sfa = (uint8_t *)ie; 766 } else if (is_p2p_oui((uint8_t *)ie)) { 767 scan_params->ie_list.p2p = (uint8_t *)ie; 768 } else if (is_qca_son_oui((uint8_t *)ie, 769 QCA_OUI_WHC_AP_INFO_SUBTYPE)) { 770 scan_params->ie_list.sonadv = (uint8_t *)ie; 771 } else if (is_ht_cap((uint8_t *)ie)) { 772 /* we only care if there isn't already an HT IE (ANA) */ 773 if (!scan_params->ie_list.htcap) { 774 if (ie->ie_len != (WLAN_VENDOR_HT_IE_OFFSET_LEN + 775 sizeof(struct htcap_cmn_ie))) 776 return QDF_STATUS_E_INVAL; 777 scan_params->ie_list.htcap = 778 (uint8_t *)&(((struct wlan_vendor_ie_htcap *)ie)->ie); 779 } 780 } else if (is_ht_info((uint8_t *)ie)) { 781 /* we only care if there isn't already an HT IE (ANA) */ 782 if (!scan_params->ie_list.htinfo) { 783 if (ie->ie_len != WLAN_VENDOR_HT_IE_OFFSET_LEN + 784 sizeof(struct wlan_ie_htinfo_cmn)) 785 return QDF_STATUS_E_INVAL; 786 scan_params->ie_list.htinfo = 787 (uint8_t *)&(((struct wlan_vendor_ie_htinfo *) 788 ie)->hi_ie); 789 } 790 } else if (is_interop_vht((uint8_t *)ie) && 791 !(scan_params->ie_list.vhtcap)) { 792 uint8_t *vendor_ie = (uint8_t *)(ie); 793 794 if (ie->ie_len < ((WLAN_VENDOR_VHTCAP_IE_OFFSET + 795 sizeof(struct wlan_ie_vhtcaps)) - 796 sizeof(struct ie_header))) 797 return QDF_STATUS_E_INVAL; 798 vendor_ie = ((uint8_t *)(ie)) + WLAN_VENDOR_VHTCAP_IE_OFFSET; 799 if (vendor_ie[1] != (sizeof(struct wlan_ie_vhtcaps)) - 800 sizeof(struct ie_header)) 801 return QDF_STATUS_E_INVAL; 802 /* location where Interop Vht Cap IE and VHT OP IE Present */ 803 scan_params->ie_list.vhtcap = (((uint8_t *)(ie)) + 804 WLAN_VENDOR_VHTCAP_IE_OFFSET); 805 if (ie->ie_len > ((WLAN_VENDOR_VHTCAP_IE_OFFSET + 806 sizeof(struct wlan_ie_vhtcaps)) - 807 sizeof(struct ie_header))) { 808 if (ie->ie_len < ((WLAN_VENDOR_VHTOP_IE_OFFSET + 809 sizeof(struct wlan_ie_vhtop)) - 810 sizeof(struct ie_header))) 811 return QDF_STATUS_E_INVAL; 812 vendor_ie = ((uint8_t *)(ie)) + 813 WLAN_VENDOR_VHTOP_IE_OFFSET; 814 if (vendor_ie[1] != (sizeof(struct wlan_ie_vhtop) - 815 sizeof(struct ie_header))) 816 return QDF_STATUS_E_INVAL; 817 scan_params->ie_list.vhtop = (((uint8_t *)(ie)) + 818 WLAN_VENDOR_VHTOP_IE_OFFSET); 819 } 820 } else if (is_bwnss_oui((uint8_t *)ie)) { 821 /* 822 * Bandwidth-NSS map has sub-type & version. 823 * hence copy data just after version byte 824 */ 825 scan_params->ie_list.bwnss_map = (((uint8_t *)ie) + 8); 826 } else if (is_mbo_oce_oui((uint8_t *)ie)) { 827 scan_params->ie_list.mbo_oce = (uint8_t *)ie; 828 } else if (is_extender_oui((uint8_t *)ie)) { 829 scan_params->ie_list.extender = (uint8_t *)ie; 830 } else if (is_adaptive_11r_oui((uint8_t *)ie)) { 831 if ((ie->ie_len < OUI_LENGTH) || 832 (ie->ie_len > MAX_ADAPTIVE_11R_IE_LEN)) 833 return QDF_STATUS_E_INVAL; 834 835 scan_params->ie_list.adaptive_11r = (uint8_t *)ie + 836 sizeof(struct ie_header); 837 } 838 return QDF_STATUS_SUCCESS; 839 } 840 841 static QDF_STATUS 842 util_scan_populate_bcn_ie_list(struct scan_cache_entry *scan_params, 843 uint8_t *chan_idx) 844 { 845 struct ie_header *ie, *sub_ie; 846 uint32_t ie_len, sub_ie_len; 847 QDF_STATUS status; 848 849 ie_len = util_scan_entry_ie_len(scan_params); 850 ie = (struct ie_header *) 851 util_scan_entry_ie_data(scan_params); 852 853 while (ie_len >= sizeof(struct ie_header)) { 854 ie_len -= sizeof(struct ie_header); 855 856 if (!ie->ie_len) { 857 ie += 1; 858 continue; 859 } 860 861 if (ie_len < ie->ie_len) { 862 scm_debug("Incomplete corrupted IE:%x", 863 ie->ie_id); 864 return QDF_STATUS_E_INVAL; 865 } 866 867 switch (ie->ie_id) { 868 case WLAN_ELEMID_SSID: 869 if (ie->ie_len > (sizeof(struct ie_ssid) - 870 sizeof(struct ie_header))) 871 goto err; 872 scan_params->ie_list.ssid = (uint8_t *)ie; 873 break; 874 case WLAN_ELEMID_RATES: 875 if (ie->ie_len > WLAN_SUPPORTED_RATES_IE_MAX_LEN) 876 goto err; 877 scan_params->ie_list.rates = (uint8_t *)ie; 878 break; 879 case WLAN_ELEMID_DSPARMS: 880 if (ie->ie_len != WLAN_DS_PARAM_IE_MAX_LEN) 881 return QDF_STATUS_E_INVAL; 882 scan_params->ie_list.ds_param = (uint8_t *)ie; 883 *chan_idx = 884 ((struct ds_ie *)ie)->cur_chan; 885 break; 886 case WLAN_ELEMID_TIM: 887 if (ie->ie_len < WLAN_TIM_IE_MIN_LENGTH) 888 goto err; 889 scan_params->ie_list.tim = (uint8_t *)ie; 890 scan_params->dtim_period = 891 ((struct wlan_tim_ie *)ie)->tim_period; 892 break; 893 case WLAN_ELEMID_COUNTRY: 894 if (ie->ie_len < WLAN_COUNTRY_IE_MIN_LEN) 895 goto err; 896 scan_params->ie_list.country = (uint8_t *)ie; 897 break; 898 case WLAN_ELEMID_QBSS_LOAD: 899 if (ie->ie_len != sizeof(struct qbss_load_ie) - 900 sizeof(struct ie_header)) { 901 /* 902 * Expected QBSS IE length is 5Bytes; For some 903 * old cisco AP, QBSS IE length is 4Bytes, which 904 * doesn't match with latest spec, So ignore 905 * QBSS IE in such case. 906 */ 907 break; 908 } 909 scan_params->ie_list.qbssload = (uint8_t *)ie; 910 break; 911 case WLAN_ELEMID_CHANSWITCHANN: 912 if (ie->ie_len != WLAN_CSA_IE_MAX_LEN) 913 goto err; 914 scan_params->ie_list.csa = (uint8_t *)ie; 915 break; 916 case WLAN_ELEMID_IBSSDFS: 917 if (ie->ie_len < WLAN_IBSSDFS_IE_MIN_LEN) 918 goto err; 919 scan_params->ie_list.ibssdfs = (uint8_t *)ie; 920 break; 921 case WLAN_ELEMID_QUIET: 922 if (ie->ie_len != WLAN_QUIET_IE_MAX_LEN) 923 goto err; 924 scan_params->ie_list.quiet = (uint8_t *)ie; 925 break; 926 case WLAN_ELEMID_ERP: 927 if (ie->ie_len != (sizeof(struct erp_ie) - 928 sizeof(struct ie_header))) 929 goto err; 930 scan_params->erp = ((struct erp_ie *)ie)->value; 931 break; 932 case WLAN_ELEMID_HTCAP_ANA: 933 if (ie->ie_len != sizeof(struct htcap_cmn_ie)) 934 goto err; 935 scan_params->ie_list.htcap = 936 (uint8_t *)&(((struct htcap_ie *)ie)->ie); 937 break; 938 case WLAN_ELEMID_RSN: 939 if (ie->ie_len < WLAN_RSN_IE_MIN_LEN) 940 goto err; 941 scan_params->ie_list.rsn = (uint8_t *)ie; 942 break; 943 case WLAN_ELEMID_XRATES: 944 scan_params->ie_list.xrates = (uint8_t *)ie; 945 break; 946 case WLAN_ELEMID_EXTCHANSWITCHANN: 947 if (ie->ie_len != WLAN_XCSA_IE_MAX_LEN) 948 goto err; 949 scan_params->ie_list.xcsa = (uint8_t *)ie; 950 break; 951 case WLAN_ELEMID_SECCHANOFFSET: 952 if (ie->ie_len != WLAN_SECCHANOFF_IE_MAX_LEN) 953 goto err; 954 scan_params->ie_list.secchanoff = (uint8_t *)ie; 955 break; 956 case WLAN_ELEMID_HTINFO_ANA: 957 if (ie->ie_len != sizeof(struct wlan_ie_htinfo_cmn)) 958 goto err; 959 scan_params->ie_list.htinfo = 960 (uint8_t *)&(((struct wlan_ie_htinfo *) ie)->hi_ie); 961 *chan_idx = 962 ((struct wlan_ie_htinfo_cmn *) 963 (scan_params->ie_list.htinfo))->hi_ctrlchannel; 964 break; 965 case WLAN_ELEMID_WAPI: 966 if (ie->ie_len < WLAN_WAPI_IE_MIN_LEN) 967 goto err; 968 scan_params->ie_list.wapi = (uint8_t *)ie; 969 break; 970 case WLAN_ELEMID_XCAPS: 971 if (ie->ie_len > WLAN_EXTCAP_IE_MAX_LEN) 972 goto err; 973 scan_params->ie_list.extcaps = (uint8_t *)ie; 974 break; 975 case WLAN_ELEMID_VHTCAP: 976 if (ie->ie_len != (sizeof(struct wlan_ie_vhtcaps) - 977 sizeof(struct ie_header))) 978 goto err; 979 scan_params->ie_list.vhtcap = (uint8_t *)ie; 980 break; 981 case WLAN_ELEMID_VHTOP: 982 if (ie->ie_len != (sizeof(struct wlan_ie_vhtop) - 983 sizeof(struct ie_header))) 984 goto err; 985 scan_params->ie_list.vhtop = (uint8_t *)ie; 986 break; 987 case WLAN_ELEMID_OP_MODE_NOTIFY: 988 if (ie->ie_len != WLAN_OPMODE_IE_MAX_LEN) 989 goto err; 990 scan_params->ie_list.opmode = (uint8_t *)ie; 991 break; 992 case WLAN_ELEMID_MOBILITY_DOMAIN: 993 if (ie->ie_len != WLAN_MOBILITY_DOMAIN_IE_MAX_LEN) 994 goto err; 995 scan_params->ie_list.mdie = (uint8_t *)ie; 996 break; 997 case WLAN_ELEMID_VENDOR: 998 status = util_scan_parse_vendor_ie(scan_params, 999 ie); 1000 if (QDF_IS_STATUS_ERROR(status)) 1001 goto err_status; 1002 break; 1003 case WLAN_ELEMID_CHAN_SWITCH_WRAP: 1004 scan_params->ie_list.cswrp = (uint8_t *)ie; 1005 /* Go to next sub IE */ 1006 sub_ie = (struct ie_header *) 1007 (((uint8_t *)ie) + sizeof(struct ie_header)); 1008 sub_ie_len = ie->ie_len; 1009 status = 1010 util_scan_parse_chan_switch_wrapper_ie( 1011 scan_params, sub_ie, sub_ie_len); 1012 if (QDF_IS_STATUS_ERROR(status)) { 1013 goto err_status; 1014 } 1015 break; 1016 case WLAN_ELEMID_FILS_INDICATION: 1017 if (ie->ie_len < WLAN_FILS_INDICATION_IE_MIN_LEN) 1018 goto err; 1019 scan_params->ie_list.fils_indication = (uint8_t *)ie; 1020 break; 1021 case WLAN_ELEMID_EXTN_ELEM: 1022 status = util_scan_parse_extn_ie(scan_params, ie); 1023 if (QDF_IS_STATUS_ERROR(status)) 1024 goto err_status; 1025 break; 1026 case WLAN_ELEMID_REDUCED_NEIGHBOR_REPORT: 1027 if (ie->ie_len < WLAN_RNR_IE_MIN_LEN) 1028 goto err; 1029 scan_params->ie_list.rnrie = (uint8_t *)ie; 1030 status = util_scan_parse_rnr_ie(scan_params, ie); 1031 if (QDF_IS_STATUS_ERROR(status)) 1032 goto err_status; 1033 break; 1034 default: 1035 break; 1036 } 1037 1038 /* Consume info element */ 1039 ie_len -= ie->ie_len; 1040 /* Go to next IE */ 1041 ie = (struct ie_header *) 1042 (((uint8_t *) ie) + 1043 sizeof(struct ie_header) + 1044 ie->ie_len); 1045 } 1046 1047 return QDF_STATUS_SUCCESS; 1048 1049 err: 1050 status = QDF_STATUS_E_INVAL; 1051 err_status: 1052 scm_debug("failed to parse IE - id: %d, len: %d", 1053 ie->ie_id, ie->ie_len); 1054 1055 return status; 1056 } 1057 1058 /** 1059 * util_scan_update_esp_data: update ESP params from beacon/probe response 1060 * @esp_information: pointer to wlan_esp_information 1061 * @scan_entry: new received entry 1062 * 1063 * The Estimated Service Parameters element is 1064 * used by a AP to provide information to another STA which 1065 * can then use the information as input to an algorithm to 1066 * generate an estimate of throughput between the two STAs. 1067 * The ESP Information List field contains from 1 to 4 ESP 1068 * Information fields(each field 24 bits), each corresponding 1069 * to an access category for which estimated service parameters 1070 * information is provided. 1071 * 1072 * Return: None 1073 */ 1074 static void util_scan_update_esp_data(struct wlan_esp_ie *esp_information, 1075 struct scan_cache_entry *scan_entry) 1076 { 1077 1078 uint8_t *data; 1079 int i = 0; 1080 uint64_t total_elements; 1081 struct wlan_esp_info *esp_info; 1082 struct wlan_esp_ie *esp_ie; 1083 1084 esp_ie = (struct wlan_esp_ie *) 1085 util_scan_entry_esp_info(scan_entry); 1086 1087 total_elements = esp_ie->esp_len; 1088 data = (uint8_t *)esp_ie + 3; 1089 do_div(total_elements, ESP_INFORMATION_LIST_LENGTH); 1090 1091 if (total_elements > MAX_ESP_INFORMATION_FIELD) { 1092 scm_err("No of Air time fractions are greater than supported"); 1093 return; 1094 } 1095 1096 for (i = 0; i < total_elements; i++) { 1097 esp_info = (struct wlan_esp_info *)data; 1098 if (esp_info->access_category == ESP_AC_BK) { 1099 qdf_mem_copy(&esp_information->esp_info_AC_BK, 1100 data, 3); 1101 data = data + ESP_INFORMATION_LIST_LENGTH; 1102 continue; 1103 } 1104 if (esp_info->access_category == ESP_AC_BE) { 1105 qdf_mem_copy(&esp_information->esp_info_AC_BE, 1106 data, 3); 1107 data = data + ESP_INFORMATION_LIST_LENGTH; 1108 continue; 1109 } 1110 if (esp_info->access_category == ESP_AC_VI) { 1111 qdf_mem_copy(&esp_information->esp_info_AC_VI, 1112 data, 3); 1113 data = data + ESP_INFORMATION_LIST_LENGTH; 1114 continue; 1115 } 1116 if (esp_info->access_category == ESP_AC_VO) { 1117 qdf_mem_copy(&esp_information->esp_info_AC_VO, 1118 data, 3); 1119 data = data + ESP_INFORMATION_LIST_LENGTH; 1120 break; 1121 } 1122 } 1123 } 1124 1125 /** 1126 * util_scan_scm_update_bss_with_esp_dataa: calculate estimated air time 1127 * fraction 1128 * @scan_entry: new received entry 1129 * 1130 * This function process all Access category ESP params and provide 1131 * best effort air time fraction. 1132 * If best effort is not available, it will choose VI, VO and BK in sequence 1133 * 1134 */ 1135 static void util_scan_scm_update_bss_with_esp_data( 1136 struct scan_cache_entry *scan_entry) 1137 { 1138 uint8_t air_time_fraction = 0; 1139 struct wlan_esp_ie esp_information; 1140 1141 if (!scan_entry->ie_list.esp) 1142 return; 1143 1144 util_scan_update_esp_data(&esp_information, scan_entry); 1145 1146 /* 1147 * If the ESP metric is transmitting multiple airtime fractions, then 1148 * follow the sequence AC_BE, AC_VI, AC_VO, AC_BK and pick whichever is 1149 * the first one available 1150 */ 1151 if (esp_information.esp_info_AC_BE.access_category 1152 == ESP_AC_BE) 1153 air_time_fraction = 1154 esp_information.esp_info_AC_BE. 1155 estimated_air_fraction; 1156 else if (esp_information.esp_info_AC_VI.access_category 1157 == ESP_AC_VI) 1158 air_time_fraction = 1159 esp_information.esp_info_AC_VI. 1160 estimated_air_fraction; 1161 else if (esp_information.esp_info_AC_VO.access_category 1162 == ESP_AC_VO) 1163 air_time_fraction = 1164 esp_information.esp_info_AC_VO. 1165 estimated_air_fraction; 1166 else if (esp_information.esp_info_AC_BK.access_category 1167 == ESP_AC_BK) 1168 air_time_fraction = 1169 esp_information.esp_info_AC_BK. 1170 estimated_air_fraction; 1171 scan_entry->air_time_fraction = air_time_fraction; 1172 } 1173 1174 /** 1175 * util_scan_scm_calc_nss_supported_by_ap() - finds out nss from AP 1176 * @scan_entry: new received entry 1177 * 1178 * Return: number of nss advertised by AP 1179 */ 1180 static int util_scan_scm_calc_nss_supported_by_ap( 1181 struct scan_cache_entry *scan_params) 1182 { 1183 struct htcap_cmn_ie *htcap; 1184 struct wlan_ie_vhtcaps *vhtcaps; 1185 uint8_t rx_mcs_map; 1186 1187 htcap = (struct htcap_cmn_ie *) 1188 util_scan_entry_htcap(scan_params); 1189 vhtcaps = (struct wlan_ie_vhtcaps *) 1190 util_scan_entry_vhtcap(scan_params); 1191 if (vhtcaps) { 1192 rx_mcs_map = vhtcaps->rx_mcs_map; 1193 if ((rx_mcs_map & 0xC0) != 0xC0) 1194 return 4; 1195 1196 if ((rx_mcs_map & 0x30) != 0x30) 1197 return 3; 1198 1199 if ((rx_mcs_map & 0x0C) != 0x0C) 1200 return 2; 1201 } else if (htcap) { 1202 if (htcap->mcsset[3]) 1203 return 4; 1204 1205 if (htcap->mcsset[2]) 1206 return 3; 1207 1208 if (htcap->mcsset[1]) 1209 return 2; 1210 1211 } 1212 return 1; 1213 } 1214 1215 #ifdef WLAN_DFS_CHAN_HIDDEN_SSID 1216 QDF_STATUS 1217 util_scan_add_hidden_ssid(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t bcnbuf) 1218 { 1219 struct wlan_frame_hdr *hdr; 1220 struct wlan_bcn_frame *bcn; 1221 struct wlan_scan_obj *scan_obj; 1222 struct wlan_ssid *conf_ssid; 1223 struct ie_header *ie; 1224 uint32_t frame_len = qdf_nbuf_len(bcnbuf); 1225 uint16_t bcn_ie_offset, ssid_ie_start_offset, ssid_ie_end_offset; 1226 uint16_t tmplen, ie_length; 1227 uint8_t *pbeacon, *tmp; 1228 bool set_ssid_flag = false; 1229 struct ie_ssid *ssid; 1230 uint8_t pdev_id; 1231 1232 if (!pdev) { 1233 scm_warn("pdev: 0x%pK is NULL", pdev); 1234 return QDF_STATUS_E_NULL_VALUE; 1235 } 1236 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 1237 scan_obj = wlan_pdev_get_scan_obj(pdev); 1238 if (!scan_obj) { 1239 scm_warn("null scan_obj"); 1240 return QDF_STATUS_E_NULL_VALUE; 1241 } 1242 1243 conf_ssid = &scan_obj->pdev_info[pdev_id].conf_ssid; 1244 1245 hdr = (struct wlan_frame_hdr *)qdf_nbuf_data(bcnbuf); 1246 1247 /* received bssid does not match configured bssid */ 1248 if (qdf_mem_cmp(hdr->i_addr3, scan_obj->pdev_info[pdev_id].conf_bssid, 1249 QDF_MAC_ADDR_SIZE) || 1250 conf_ssid->length == 0) { 1251 return QDF_STATUS_SUCCESS; 1252 } 1253 1254 bcn = (struct wlan_bcn_frame *)(qdf_nbuf_data(bcnbuf) + sizeof(*hdr)); 1255 pbeacon = (uint8_t *)bcn; 1256 1257 ie = (struct ie_header *)(pbeacon + 1258 offsetof(struct wlan_bcn_frame, ie)); 1259 1260 bcn_ie_offset = offsetof(struct wlan_bcn_frame, ie); 1261 ie_length = (uint16_t)(frame_len - sizeof(*hdr) - 1262 bcn_ie_offset); 1263 1264 while (ie_length >= sizeof(struct ie_header)) { 1265 ie_length -= sizeof(struct ie_header); 1266 1267 bcn_ie_offset += sizeof(struct ie_header); 1268 1269 if (ie_length < ie->ie_len) { 1270 scm_debug("Incomplete corrupted IE:%x", ie->ie_id); 1271 return QDF_STATUS_E_INVAL; 1272 } 1273 if (ie->ie_id == WLAN_ELEMID_SSID) { 1274 if (ie->ie_len > (sizeof(struct ie_ssid) - 1275 sizeof(struct ie_header))) { 1276 return QDF_STATUS_E_INVAL; 1277 } 1278 ssid = (struct ie_ssid *)ie; 1279 if (util_scan_is_hidden_ssid(ssid)) { 1280 set_ssid_flag = true; 1281 ssid_ie_start_offset = bcn_ie_offset - 1282 sizeof(struct ie_header); 1283 ssid_ie_end_offset = bcn_ie_offset + 1284 ie->ie_len; 1285 } 1286 } 1287 if (ie->ie_len == 0) { 1288 ie += 1; /* next IE */ 1289 continue; 1290 } 1291 if (ie->ie_id == WLAN_ELEMID_VENDOR && 1292 is_wps_oui((uint8_t *)ie)) { 1293 set_ssid_flag = false; 1294 break; 1295 } 1296 /* Consume info element */ 1297 ie_length -= ie->ie_len; 1298 /* Go to next IE */ 1299 ie = (struct ie_header *)(((uint8_t *)ie) + 1300 sizeof(struct ie_header) + 1301 ie->ie_len); 1302 } 1303 1304 if (set_ssid_flag) { 1305 /* Hidden SSID if the Length is 0 */ 1306 if (!ssid->ssid_len) { 1307 /* increase the taillength by length of ssid */ 1308 if (qdf_nbuf_put_tail(bcnbuf, 1309 conf_ssid->length) == NULL) { 1310 scm_debug("No enough tailroom"); 1311 return QDF_STATUS_E_NOMEM; 1312 } 1313 /* length of the buffer to be copied */ 1314 tmplen = frame_len - 1315 sizeof(*hdr) - ssid_ie_end_offset; 1316 /* 1317 * tmp memory to copy the beacon info 1318 * after ssid ie. 1319 */ 1320 tmp = qdf_mem_malloc(tmplen * sizeof(u_int8_t)); 1321 if (!tmp) 1322 return QDF_STATUS_E_NOMEM; 1323 1324 /* Copy beacon data after ssid ie to tmp */ 1325 qdf_nbuf_copy_bits(bcnbuf, (sizeof(*hdr) + 1326 ssid_ie_end_offset), tmplen, tmp); 1327 /* Add ssid length */ 1328 *(pbeacon + (ssid_ie_start_offset + 1)) 1329 = conf_ssid->length; 1330 /* Insert the SSID string */ 1331 qdf_mem_copy((pbeacon + ssid_ie_end_offset), 1332 conf_ssid->ssid, conf_ssid->length); 1333 /* Copy rest of the beacon data */ 1334 qdf_mem_copy((pbeacon + ssid_ie_end_offset + 1335 conf_ssid->length), tmp, tmplen); 1336 qdf_mem_free(tmp); 1337 1338 /* Hidden ssid with all 0's */ 1339 } else if (ssid->ssid_len == conf_ssid->length) { 1340 /* Insert the SSID string */ 1341 qdf_mem_copy((pbeacon + ssid_ie_start_offset + 1342 sizeof(struct ie_header)), 1343 conf_ssid->ssid, conf_ssid->length); 1344 } else { 1345 scm_debug("mismatch in hidden ssid length"); 1346 return QDF_STATUS_E_INVAL; 1347 } 1348 } 1349 return QDF_STATUS_SUCCESS; 1350 } 1351 #endif /* WLAN_DFS_CHAN_HIDDEN_SSID */ 1352 1353 #ifdef WLAN_ADAPTIVE_11R 1354 /** 1355 * scm_fill_adaptive_11r_cap() - Check if the AP supports adaptive 11r 1356 * @scan_entry: Pointer to the scan entry 1357 * 1358 * Return: true if adaptive 11r is advertised else false 1359 */ 1360 static void scm_fill_adaptive_11r_cap(struct scan_cache_entry *scan_entry) 1361 { 1362 uint8_t *ie; 1363 uint8_t data; 1364 bool adaptive_11r; 1365 1366 ie = util_scan_entry_adaptive_11r(scan_entry); 1367 if (!ie) 1368 return; 1369 1370 data = *(ie + OUI_LENGTH); 1371 adaptive_11r = (data & 0x1) ? true : false; 1372 1373 scan_entry->adaptive_11r_ap = adaptive_11r; 1374 } 1375 #else 1376 static void scm_fill_adaptive_11r_cap(struct scan_cache_entry *scan_entry) 1377 { 1378 scan_entry->adaptive_11r_ap = false; 1379 } 1380 #endif 1381 1382 static QDF_STATUS 1383 util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev, 1384 uint8_t *frame, qdf_size_t frame_len, 1385 uint32_t frm_subtype, 1386 struct mgmt_rx_event_params *rx_param, 1387 struct scan_mbssid_info *mbssid_info, 1388 qdf_list_t *scan_list) 1389 { 1390 struct wlan_frame_hdr *hdr; 1391 struct wlan_bcn_frame *bcn; 1392 QDF_STATUS status = QDF_STATUS_SUCCESS; 1393 struct ie_ssid *ssid; 1394 struct scan_cache_entry *scan_entry; 1395 struct qbss_load_ie *qbss_load; 1396 struct scan_cache_node *scan_node; 1397 uint8_t i, chan_idx = 0; 1398 1399 scan_entry = qdf_mem_malloc_atomic(sizeof(*scan_entry)); 1400 if (!scan_entry) { 1401 scm_err("failed to allocate memory for scan_entry"); 1402 return QDF_STATUS_E_NOMEM; 1403 } 1404 scan_entry->raw_frame.ptr = 1405 qdf_mem_malloc_atomic(frame_len); 1406 if (!scan_entry->raw_frame.ptr) { 1407 scm_err("failed to allocate memory for frame"); 1408 qdf_mem_free(scan_entry); 1409 return QDF_STATUS_E_NOMEM; 1410 } 1411 1412 bcn = (struct wlan_bcn_frame *) 1413 (frame + sizeof(*hdr)); 1414 hdr = (struct wlan_frame_hdr *)frame; 1415 1416 /* update timestamp in nanoseconds needed by kernel layers */ 1417 scan_entry->boottime_ns = qdf_get_bootbased_boottime_ns(); 1418 1419 scan_entry->frm_subtype = frm_subtype; 1420 qdf_mem_copy(scan_entry->bssid.bytes, 1421 hdr->i_addr3, QDF_MAC_ADDR_SIZE); 1422 /* Scr addr */ 1423 qdf_mem_copy(scan_entry->mac_addr.bytes, 1424 hdr->i_addr2, QDF_MAC_ADDR_SIZE); 1425 scan_entry->seq_num = 1426 (le16toh(*(uint16_t *)hdr->i_seq) >> WLAN_SEQ_SEQ_SHIFT); 1427 1428 scan_entry->snr = rx_param->snr; 1429 scan_entry->avg_snr = WLAN_SNR_IN(scan_entry->snr); 1430 scan_entry->rssi_raw = rx_param->rssi; 1431 scan_entry->avg_rssi = WLAN_RSSI_IN(scan_entry->rssi_raw); 1432 scan_entry->tsf_delta = rx_param->tsf_delta; 1433 scan_entry->pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 1434 1435 /* Copy per chain rssi to scan entry */ 1436 qdf_mem_copy(scan_entry->per_chain_rssi, rx_param->rssi_ctl, 1437 WLAN_MGMT_TXRX_HOST_MAX_ANTENNA); 1438 1439 if (!wlan_psoc_nif_fw_ext_cap_get(wlan_pdev_get_psoc(pdev), 1440 WLAN_SOC_CEXT_HW_DB2DBM)) { 1441 for (i = 0; i < WLAN_MGMT_TXRX_HOST_MAX_ANTENNA; i++) { 1442 if (scan_entry->per_chain_rssi[i] != 1443 WLAN_INVALID_PER_CHAIN_SNR) 1444 scan_entry->per_chain_rssi[i] += 1445 WLAN_NOISE_FLOOR_DBM_DEFAULT; 1446 else 1447 scan_entry->per_chain_rssi[i] = 1448 WLAN_INVALID_PER_CHAIN_RSSI; 1449 } 1450 } 1451 1452 /* store jiffies */ 1453 scan_entry->rrm_parent_tsf = (uint32_t)qdf_system_ticks(); 1454 1455 scan_entry->bcn_int = le16toh(bcn->beacon_interval); 1456 1457 /* 1458 * In case if the beacon dosnt have 1459 * valid beacon interval falback to def 1460 */ 1461 if (!scan_entry->bcn_int) 1462 scan_entry->bcn_int = 100; 1463 scan_entry->cap_info.value = le16toh(bcn->capability.value); 1464 qdf_mem_copy(scan_entry->tsf_info.data, 1465 bcn->timestamp, 8); 1466 scan_entry->erp = ERP_NON_ERP_PRESENT; 1467 1468 scan_entry->scan_entry_time = 1469 qdf_mc_timer_get_system_time(); 1470 1471 scan_entry->raw_frame.len = frame_len; 1472 qdf_mem_copy(scan_entry->raw_frame.ptr, 1473 frame, frame_len); 1474 status = util_scan_populate_bcn_ie_list(scan_entry, &chan_idx); 1475 if (QDF_IS_STATUS_ERROR(status)) { 1476 scm_debug("failed to parse beacon IE"); 1477 qdf_mem_free(scan_entry->raw_frame.ptr); 1478 qdf_mem_free(scan_entry); 1479 return QDF_STATUS_E_FAILURE; 1480 } 1481 1482 ssid = (struct ie_ssid *) 1483 scan_entry->ie_list.ssid; 1484 1485 if (ssid && (ssid->ssid_len > WLAN_SSID_MAX_LEN)) { 1486 qdf_mem_free(scan_entry->raw_frame.ptr); 1487 qdf_mem_free(scan_entry); 1488 return QDF_STATUS_E_FAILURE; 1489 } 1490 1491 if (scan_entry->ie_list.p2p) 1492 scan_entry->is_p2p = true; 1493 1494 if (!chan_idx && util_scan_entry_hecap(scan_entry)) 1495 util_scan_get_chan_from_he_6g_params(scan_entry, &chan_idx); 1496 1497 if (chan_idx) { 1498 uint8_t band_mask = BIT(wlan_reg_freq_to_band( 1499 rx_param->chan_freq)); 1500 1501 scan_entry->channel.chan_freq = 1502 wlan_reg_chan_band_to_freq( 1503 pdev, chan_idx, 1504 band_mask); 1505 } 1506 /* If no channel info is present in beacon use meta channel */ 1507 if (!scan_entry->channel.chan_freq) { 1508 scan_entry->channel.chan_freq = rx_param->chan_freq; 1509 } else if (rx_param->chan_freq != 1510 scan_entry->channel.chan_freq) { 1511 if (!wlan_reg_is_49ghz_freq(scan_entry->channel.chan_freq)) 1512 scan_entry->channel_mismatch = true; 1513 } 1514 1515 if (util_scan_is_hidden_ssid(ssid)) { 1516 scan_entry->ie_list.ssid = NULL; 1517 scan_entry->is_hidden_ssid = true; 1518 } else { 1519 qdf_mem_copy(scan_entry->ssid.ssid, 1520 ssid->ssid, ssid->ssid_len); 1521 scan_entry->ssid.length = ssid->ssid_len; 1522 scan_entry->hidden_ssid_timestamp = 1523 scan_entry->scan_entry_time; 1524 } 1525 qdf_mem_copy(&scan_entry->mbssid_info, mbssid_info, 1526 sizeof(scan_entry->mbssid_info)); 1527 1528 scan_entry->phy_mode = util_scan_get_phymode(pdev, scan_entry); 1529 1530 scan_entry->nss = util_scan_scm_calc_nss_supported_by_ap(scan_entry); 1531 scm_fill_adaptive_11r_cap(scan_entry); 1532 1533 util_scan_scm_update_bss_with_esp_data(scan_entry); 1534 qbss_load = (struct qbss_load_ie *) 1535 util_scan_entry_qbssload(scan_entry); 1536 if (qbss_load) 1537 scan_entry->qbss_chan_load = qbss_load->qbss_chan_load; 1538 1539 scan_node = qdf_mem_malloc_atomic(sizeof(*scan_node)); 1540 if (!scan_node) { 1541 qdf_mem_free(scan_entry->raw_frame.ptr); 1542 qdf_mem_free(scan_entry); 1543 return QDF_STATUS_E_FAILURE; 1544 } 1545 1546 scan_node->entry = scan_entry; 1547 qdf_list_insert_front(scan_list, &scan_node->node); 1548 1549 return status; 1550 } 1551 1552 /** 1553 * util_scan_find_ie() - find information element 1554 * @eid: element id 1555 * @ies: pointer consisting of IEs 1556 * @len: IE length 1557 * 1558 * Return: NULL if the element ID is not found or 1559 * a pointer to the first byte of the requested 1560 * element 1561 */ 1562 static uint8_t *util_scan_find_ie(uint8_t eid, uint8_t *ies, 1563 int32_t len) 1564 { 1565 while (len >= 2 && len >= ies[1] + 2) { 1566 if (ies[0] == eid) 1567 return ies; 1568 len -= ies[1] + 2; 1569 ies += ies[1] + 2; 1570 } 1571 1572 return NULL; 1573 } 1574 1575 #ifdef WLAN_FEATURE_MBSSID 1576 static void util_gen_new_bssid(uint8_t *bssid, uint8_t max_bssid, 1577 uint8_t mbssid_index, 1578 uint8_t *new_bssid_addr) 1579 { 1580 uint8_t lsb_n; 1581 int i; 1582 1583 for (i = 0; i < QDF_MAC_ADDR_SIZE; i++) 1584 new_bssid_addr[i] = bssid[i]; 1585 1586 lsb_n = new_bssid_addr[5] & ((1 << max_bssid) - 1); 1587 1588 new_bssid_addr[5] &= ~((1 << max_bssid) - 1); 1589 new_bssid_addr[5] |= (lsb_n + mbssid_index) % (1 << max_bssid); 1590 } 1591 1592 static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, 1593 uint8_t *subelement, 1594 size_t subie_len, uint8_t *new_ie) 1595 { 1596 uint8_t *pos, *tmp; 1597 const uint8_t *tmp_old, *tmp_new; 1598 uint8_t *sub_copy; 1599 1600 /* copy subelement as we need to change its content to 1601 * mark an ie after it is processed. 1602 */ 1603 sub_copy = qdf_mem_malloc(subie_len); 1604 if (!sub_copy) 1605 return 0; 1606 qdf_mem_copy(sub_copy, subelement, subie_len); 1607 1608 pos = &new_ie[0]; 1609 1610 /* new ssid */ 1611 tmp_new = util_scan_find_ie(WLAN_ELEMID_SSID, sub_copy, subie_len); 1612 if (tmp_new) { 1613 qdf_mem_copy(pos, tmp_new, tmp_new[1] + 2); 1614 pos += (tmp_new[1] + 2); 1615 } 1616 1617 /* go through IEs in ie (skip SSID) and subelement, 1618 * merge them into new_ie 1619 */ 1620 tmp_old = util_scan_find_ie(WLAN_ELEMID_SSID, ie, ielen); 1621 tmp_old = (tmp_old) ? tmp_old + tmp_old[1] + 2 : ie; 1622 1623 while (tmp_old + tmp_old[1] + 2 - ie <= ielen) { 1624 if (tmp_old[0] == 0) { 1625 tmp_old++; 1626 continue; 1627 } 1628 1629 tmp = (uint8_t *)util_scan_find_ie(tmp_old[0], sub_copy, 1630 subie_len); 1631 if (!tmp) { 1632 /* ie in old ie but not in subelement */ 1633 if (tmp_old[0] != WLAN_ELEMID_MULTIPLE_BSSID) { 1634 qdf_mem_copy(pos, tmp_old, tmp_old[1] + 2); 1635 pos += tmp_old[1] + 2; 1636 } 1637 } else { 1638 /* ie in transmitting ie also in subelement, 1639 * copy from subelement and flag the ie in subelement 1640 * as copied (by setting eid field to 0xff). For 1641 * vendor ie, compare OUI + type + subType to 1642 * determine if they are the same ie. 1643 */ 1644 if (tmp_old[0] == WLAN_ELEMID_VENDOR) { 1645 if (!qdf_mem_cmp(tmp_old + 2, tmp + 2, 5)) { 1646 /* same vendor ie, copy from 1647 * subelement 1648 */ 1649 qdf_mem_copy(pos, tmp, tmp[1] + 2); 1650 pos += tmp[1] + 2; 1651 tmp[0] = 0xff; 1652 } else { 1653 qdf_mem_copy(pos, tmp_old, 1654 tmp_old[1] + 2); 1655 pos += tmp_old[1] + 2; 1656 } 1657 } else { 1658 /* copy ie from subelement into new ie */ 1659 qdf_mem_copy(pos, tmp, tmp[1] + 2); 1660 pos += tmp[1] + 2; 1661 tmp[0] = 0xff; 1662 } 1663 } 1664 1665 if (tmp_old + tmp_old[1] + 2 - ie == ielen) 1666 break; 1667 1668 tmp_old += tmp_old[1] + 2; 1669 } 1670 1671 /* go through subelement again to check if there is any ie not 1672 * copied to new ie, skip ssid, capability, bssid-index ie 1673 */ 1674 tmp_new = sub_copy; 1675 while (tmp_new + tmp_new[1] + 2 - sub_copy <= subie_len) { 1676 if (!(tmp_new[0] == WLAN_ELEMID_NONTX_BSSID_CAP || 1677 tmp_new[0] == WLAN_ELEMID_SSID || 1678 tmp_new[0] == WLAN_ELEMID_MULTI_BSSID_IDX || 1679 tmp_new[0] == 0xff)) { 1680 qdf_mem_copy(pos, tmp_new, tmp_new[1] + 2); 1681 pos += tmp_new[1] + 2; 1682 } 1683 if (tmp_new + tmp_new[1] + 2 - sub_copy == subie_len) 1684 break; 1685 tmp_new += tmp_new[1] + 2; 1686 } 1687 1688 qdf_mem_free(sub_copy); 1689 return pos - new_ie; 1690 } 1691 1692 static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, 1693 uint8_t *frame, qdf_size_t frame_len, 1694 uint32_t frm_subtype, 1695 struct mgmt_rx_event_params *rx_param, 1696 qdf_list_t *scan_list) 1697 { 1698 struct wlan_bcn_frame *bcn; 1699 struct wlan_frame_hdr *hdr; 1700 struct scan_mbssid_info mbssid_info; 1701 QDF_STATUS status; 1702 uint8_t *pos, *subelement, *mbssid_end_pos; 1703 uint8_t *tmp, *mbssid_index_ie; 1704 uint32_t subie_len, new_ie_len; 1705 uint8_t new_bssid[QDF_MAC_ADDR_SIZE], bssid[QDF_MAC_ADDR_SIZE]; 1706 uint8_t *new_ie; 1707 uint8_t *ie, *new_frame = NULL; 1708 uint64_t ielen, new_frame_len; 1709 1710 hdr = (struct wlan_frame_hdr *)frame; 1711 bcn = (struct wlan_bcn_frame *)(frame + sizeof(struct wlan_frame_hdr)); 1712 ie = (uint8_t *)&bcn->ie; 1713 ielen = (uint16_t)(frame_len - 1714 sizeof(struct wlan_frame_hdr) - 1715 offsetof(struct wlan_bcn_frame, ie)); 1716 qdf_mem_copy(bssid, hdr->i_addr3, QDF_MAC_ADDR_SIZE); 1717 1718 if (!util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID, ie, ielen)) 1719 return QDF_STATUS_E_FAILURE; 1720 1721 pos = ie; 1722 1723 new_ie = qdf_mem_malloc(MAX_IE_LEN); 1724 if (!new_ie) 1725 return QDF_STATUS_E_NOMEM; 1726 1727 while (pos < ie + ielen + 2) { 1728 tmp = util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID, pos, 1729 ielen - (pos - ie)); 1730 if (!tmp) 1731 break; 1732 1733 mbssid_info.profile_count = 1 << tmp[2]; 1734 mbssid_end_pos = tmp + tmp[1] + 2; 1735 /* Skip Element ID, Len, MaxBSSID Indicator */ 1736 if (tmp[1] < 4) 1737 break; 1738 for (subelement = tmp + 3; subelement < mbssid_end_pos - 1; 1739 subelement += 2 + subelement[1]) { 1740 subie_len = subelement[1]; 1741 if (mbssid_end_pos - subelement < 2 + subie_len) 1742 break; 1743 if (subelement[0] != 0 || subelement[1] < 4) { 1744 /* not a valid BSS profile */ 1745 continue; 1746 } 1747 1748 if (subelement[2] != WLAN_ELEMID_NONTX_BSSID_CAP || 1749 subelement[3] != 2) { 1750 /* The first element within the Nontransmitted 1751 * BSSID Profile is not the Nontransmitted 1752 * BSSID Capability element. 1753 */ 1754 continue; 1755 } 1756 1757 /* found a Nontransmitted BSSID Profile */ 1758 mbssid_index_ie = 1759 util_scan_find_ie(WLAN_ELEMID_MULTI_BSSID_IDX, 1760 subelement + 2, subie_len); 1761 if (!mbssid_index_ie || mbssid_index_ie[1] < 1 || 1762 mbssid_index_ie[2] == 0) { 1763 /* No valid Multiple BSSID-Index element */ 1764 continue; 1765 } 1766 qdf_mem_copy(&mbssid_info.trans_bssid, bssid, 1767 QDF_MAC_ADDR_SIZE); 1768 mbssid_info.profile_num = mbssid_index_ie[2]; 1769 util_gen_new_bssid(bssid, tmp[2], mbssid_index_ie[2], 1770 new_bssid); 1771 new_ie_len = util_gen_new_ie(ie, ielen, subelement + 2, 1772 subie_len, new_ie); 1773 if (!new_ie_len) 1774 continue; 1775 1776 new_frame_len = frame_len - ielen + new_ie_len; 1777 new_frame = qdf_mem_malloc(new_frame_len); 1778 if (!new_frame) { 1779 qdf_mem_free(new_ie); 1780 return QDF_STATUS_E_NOMEM; 1781 } 1782 1783 /* 1784 * Copy the header(24byte), timestamp(8 byte), 1785 * beaconinterval(2byte) and capability(2byte) 1786 */ 1787 qdf_mem_copy(new_frame, frame, 36); 1788 /* Copy the new ie generated from MBSSID profile*/ 1789 hdr = (struct wlan_frame_hdr *)new_frame; 1790 qdf_mem_copy(hdr->i_addr2, new_bssid, 1791 QDF_MAC_ADDR_SIZE); 1792 qdf_mem_copy(hdr->i_addr3, new_bssid, 1793 QDF_MAC_ADDR_SIZE); 1794 /* Copy the new ie generated from MBSSID profile*/ 1795 qdf_mem_copy(new_frame + 1796 offsetof(struct wlan_bcn_frame, ie) + 1797 sizeof(struct wlan_frame_hdr), 1798 new_ie, new_ie_len); 1799 status = util_scan_gen_scan_entry(pdev, new_frame, 1800 new_frame_len, 1801 frm_subtype, 1802 rx_param, 1803 &mbssid_info, 1804 scan_list); 1805 if (QDF_IS_STATUS_ERROR(status)) { 1806 qdf_mem_free(new_frame); 1807 scm_err("failed to generate a scan entry"); 1808 break; 1809 } 1810 /* scan entry makes its own copy so free the frame*/ 1811 qdf_mem_free(new_frame); 1812 } 1813 1814 pos = mbssid_end_pos; 1815 } 1816 qdf_mem_free(new_ie); 1817 1818 return QDF_STATUS_SUCCESS; 1819 } 1820 #else 1821 static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, 1822 uint8_t *frame, qdf_size_t frame_len, 1823 uint32_t frm_subtype, 1824 struct mgmt_rx_event_params *rx_param, 1825 qdf_list_t *scan_list) 1826 { 1827 return QDF_STATUS_SUCCESS; 1828 } 1829 #endif 1830 1831 static QDF_STATUS 1832 util_scan_parse_beacon_frame(struct wlan_objmgr_pdev *pdev, 1833 uint8_t *frame, 1834 qdf_size_t frame_len, 1835 uint32_t frm_subtype, 1836 struct mgmt_rx_event_params *rx_param, 1837 qdf_list_t *scan_list) 1838 { 1839 struct wlan_bcn_frame *bcn; 1840 struct wlan_frame_hdr *hdr; 1841 uint8_t *mbssid_ie = NULL; 1842 uint32_t ie_len = 0; 1843 QDF_STATUS status; 1844 struct scan_mbssid_info mbssid_info = { 0 }; 1845 1846 hdr = (struct wlan_frame_hdr *)frame; 1847 bcn = (struct wlan_bcn_frame *) 1848 (frame + sizeof(struct wlan_frame_hdr)); 1849 ie_len = (uint16_t)(frame_len - 1850 sizeof(struct wlan_frame_hdr) - 1851 offsetof(struct wlan_bcn_frame, ie)); 1852 1853 mbssid_ie = util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID, 1854 (uint8_t *)&bcn->ie, ie_len); 1855 if (mbssid_ie) { 1856 qdf_mem_copy(&mbssid_info.trans_bssid, 1857 hdr->i_addr3, QDF_MAC_ADDR_SIZE); 1858 mbssid_info.profile_count = 1 << mbssid_ie[2]; 1859 } 1860 1861 status = util_scan_gen_scan_entry(pdev, frame, frame_len, 1862 frm_subtype, rx_param, 1863 &mbssid_info, 1864 scan_list); 1865 1866 /* 1867 * IF MBSSID IE is present in the beacon then 1868 * scan component will create a new entry for 1869 * each BSSID found in the MBSSID 1870 */ 1871 if (mbssid_ie) 1872 status = util_scan_parse_mbssid(pdev, frame, frame_len, 1873 frm_subtype, rx_param, 1874 scan_list); 1875 1876 if (QDF_IS_STATUS_ERROR(status)) 1877 scm_debug_rl("Failed to create a scan entry"); 1878 1879 return status; 1880 } 1881 1882 qdf_list_t * 1883 util_scan_unpack_beacon_frame(struct wlan_objmgr_pdev *pdev, uint8_t *frame, 1884 qdf_size_t frame_len, uint32_t frm_subtype, 1885 struct mgmt_rx_event_params *rx_param) 1886 { 1887 qdf_list_t *scan_list; 1888 QDF_STATUS status; 1889 1890 scan_list = qdf_mem_malloc_atomic(sizeof(*scan_list)); 1891 if (!scan_list) { 1892 scm_err("failed to allocate scan_list"); 1893 return NULL; 1894 } 1895 qdf_list_create(scan_list, MAX_SCAN_CACHE_SIZE); 1896 1897 status = util_scan_parse_beacon_frame(pdev, frame, frame_len, 1898 frm_subtype, rx_param, 1899 scan_list); 1900 if (QDF_IS_STATUS_ERROR(status)) { 1901 ucfg_scan_purge_results(scan_list); 1902 return NULL; 1903 } 1904 1905 return scan_list; 1906 } 1907 1908 QDF_STATUS 1909 util_scan_entry_update_mlme_info(struct wlan_objmgr_pdev *pdev, 1910 struct scan_cache_entry *scan_entry) 1911 { 1912 1913 if (!pdev || !scan_entry) { 1914 scm_err("pdev 0x%pK, scan_entry: 0x%pK", pdev, scan_entry); 1915 return QDF_STATUS_E_INVAL; 1916 } 1917 1918 return scm_update_scan_mlme_info(pdev, scan_entry); 1919 } 1920 1921 bool util_is_scan_completed(struct scan_event *event, bool *success) 1922 { 1923 if ((event->type == SCAN_EVENT_TYPE_COMPLETED) || 1924 (event->type == SCAN_EVENT_TYPE_DEQUEUED) || 1925 (event->type == SCAN_EVENT_TYPE_START_FAILED)) { 1926 if ((event->type == SCAN_EVENT_TYPE_COMPLETED) && 1927 (event->reason == SCAN_REASON_COMPLETED)) 1928 *success = true; 1929 else 1930 *success = false; 1931 1932 return true; 1933 } 1934 1935 *success = false; 1936 return false; 1937 } 1938 1939