00001
00018
00019
00020
00021
00022
00023
00024 #include "co_endian.h"
00025
00026 #include "co_utils.h"
00027 #include "scanu.h"
00028
00029 #include "scanu_task.h"
00030 #include "co_status.h"
00031 #include "mac_frame.h"
00032 #include "me_mgmtframe.h"
00033 #include "me_utils.h"
00034
00035 #include "scan_task.h"
00036 #include "rxu_task.h"
00037 #include "me.h"
00038 #include "mac_ie.h"
00039
00040 #include "vif_mgmt.h"
00041 #include "tpc.h"
00042
00043 #if (NX_P2P)
00044 #include "p2p.h"
00045 #endif //(NX_P2P)
00046
00047
00048
00049
00050
00051
00053 struct scanu_env_tag scanu_env;
00054
00055
00056
00057
00058
00059
00068 static uint32_t scanu_build_ie(void)
00069 {
00070 struct scanu_start_req const *param = scanu_env.param;
00071 struct scanu_add_ie_tag *add_ie = &scanu_add_ie;
00072 struct scan_probe_req_ie_tag *ie = &scan_probe_req_ie;
00073 uint32_t add_ie_buf = CPU2HW(add_ie->buf);
00074 uint32_t ie_buf = CPU2HW(ie->buf);
00075 uint8_t sup_rate_len = MAC_RATESET_LEN;
00076 uint8_t sup_rate_oft = 0;
00077 uint8_t ie_len;
00078 uint16_t add_ie_len = param->add_ie_len;
00079
00080
00081 if (add_ie_len > SCANU_MAX_IE_LEN)
00082 add_ie_len = 0;
00083
00084
00085 if ((scanu_env.band == PHY_BAND_5G) || param->no_cck)
00086 {
00087 sup_rate_len = MAC_RATES_ELMT_MAX_LEN;
00088 sup_rate_oft = 4;
00089 }
00090
00091
00092 co_write8p(ie_buf++, MAC_ELTID_RATES);
00093 co_write8p(ie_buf++, MAC_RATES_ELMT_MAX_LEN);
00094 co_pack8p(ie_buf, &mac_id2rate[sup_rate_oft], MAC_RATES_ELMT_MAX_LEN);
00095 ie_buf += MAC_RATES_ELMT_MAX_LEN;
00096
00097
00098 if (add_ie_len && (co_read8p(add_ie_buf) == MAC_ELTID_REQUEST))
00099 {
00100
00101 ie_len = co_read8p(add_ie_buf + 1) + 2;
00102 co_copy8p(ie_buf, add_ie_buf, ie_len);
00103 ie_buf += ie_len;
00104 add_ie_buf += ie_len;
00105 add_ie_len -= ie_len;
00106 }
00107
00108
00109 if (sup_rate_len > MAC_RATES_ELMT_MAX_LEN)
00110 {
00111 ie_len = sup_rate_len - MAC_RATES_ELMT_MAX_LEN;
00112 co_write8p(ie_buf++, MAC_ELTID_EXT_RATES);
00113 co_write8p(ie_buf++, ie_len);
00114 co_pack8p(ie_buf, &mac_id2rate[MAC_RATES_ELMT_MAX_LEN], ie_len);
00115 ie_buf += ie_len;
00116 }
00117
00118
00119 if (scanu_env.band == PHY_BAND_2G4)
00120 {
00121 co_write8p(ie_buf++, MAC_ELTID_DS);
00122 co_write8p(ie_buf++, 1);
00123 ie_buf++;
00124 }
00125
00126
00127 if (add_ie_len && (co_read8p(add_ie_buf) == MAC_ELTID_SUPP_OPER_CLASS))
00128 {
00129
00130 ie_len = co_read8p(add_ie_buf + 1) + 2;
00131 co_copy8p(ie_buf, add_ie_buf, ie_len);
00132 ie_buf += ie_len;
00133 add_ie_buf += ie_len;
00134 add_ie_len -= ie_len;
00135 }
00136
00137
00138 if (LOCAL_CAPA(HT))
00139 {
00140 me_add_ie_ht_capa(&ie_buf);
00141 }
00142
00143
00144 if (add_ie_len)
00145 {
00146 co_copy8p(ie_buf, add_ie_buf, add_ie_len);
00147 ie_buf += add_ie_len;
00148 }
00149
00150 #if NX_VHT
00151
00152 if ((scanu_env.band == PHY_BAND_5G) && LOCAL_CAPA(VHT))
00153 {
00154 me_add_ie_vht_capa(&ie_buf);
00155 }
00156 #endif
00157
00158 #if NX_HE
00159
00160 if (LOCAL_CAPA(HE))
00161 {
00162 me_add_ie_he_capa(&ie_buf);
00163 }
00164 #endif
00165
00166
00167 ASSERT_ERR((ie_buf - CPU2HW(ie->buf)) <= SCAN_MAX_IE_LEN);
00168
00169
00170 return (ie_buf - CPU2HW(ie->buf));
00171 }
00172
00173
00184 static void scanu_dma_cb(void *env, int dma_type)
00185 {
00186
00187 scanu_scan_next();
00188 }
00189
00190
00198 static void scanu_ie_download(void)
00199 {
00200 struct scanu_start_req const *param = scanu_env.param;
00201
00202
00203 if ((param->add_ies == 0) || (param->add_ie_len > SCANU_MAX_IE_LEN))
00204 {
00205
00206 scanu_scan_next();
00207 }
00208 else
00209 {
00210 struct scanu_add_ie_tag *ie_desc = &scanu_add_ie;
00211 #if !NX_FULLY_HOSTED
00212 struct dma_desc *hw_dma = &ie_desc->dma_desc;
00213 struct hal_dma_desc_tag *gp_dma = &scanu_env.dma_desc;
00214
00215
00216 hw_dma->src = param->add_ies;
00217 hw_dma->length = param->add_ie_len;
00218
00219
00220 hal_dma_push(gp_dma, DMA_DL);
00221
00222 #else
00223
00224
00225 memcpy(ie_desc->buf, (void *)param->add_ies, param->add_ie_len);
00226 scanu_scan_next();
00227
00228 #endif
00229 }
00230 }
00231
00241 static void scanu_get_security_info(uint32_t ies, uint16_t ies_len, uint16_t capa,
00242 struct mac_scan_result *res)
00243 {
00244 #if !NX_FULLY_HOSTED
00245
00246 res->akm = 0;
00247 res->group_cipher = 0;
00248 res->pairwise_cipher = 0;
00249
00250 #else
00251 uint32_t sec_ie;
00252 uint8_t sec_ie_len;
00253 int cnt, len;
00254
00255 res->akm = 0;
00256 res->group_cipher = 0;
00257 res->pairwise_cipher = 0;
00258
00259 if (!(capa & MAC_CAPA_PRIVA))
00260 {
00261 res->akm = CO_BIT(MAC_AKM_NONE);
00262 return;
00263 }
00264
00265 #define READ_CIPHER_SUITE(type) \
00266 { \
00267 int val = mac_cipher_suite_value(co_ntohl(co_read32p(sec_ie))); \
00268 if (val > 0) \
00269 res->type |= CO_BIT(val); \
00270 sec_ie += 4; \
00271 len -= 4; \
00272 }
00273
00274 #define READ_AKM_SUITE() \
00275 { \
00276 int val = mac_akm_suite_value(co_ntohl(co_read32p(sec_ie))); \
00277 if (val > 0) \
00278 res->akm |= CO_BIT(val); \
00279 sec_ie += 4; \
00280 len -= 4; \
00281 }
00282
00283 #define READ_CNT() \
00284 cnt = co_wtohs(co_read16p(sec_ie)); \
00285 sec_ie += 2; \
00286 len -= 2;
00287
00288
00289 sec_ie = mac_ie_rsn_find(ies, ies_len, &sec_ie_len);
00290 if (sec_ie)
00291 {
00292 uint16_t rsn_capa;
00293
00294 sec_ie += MAC_RSNIE_GROUP_CIPHER_OFT;
00295 len = sec_ie_len + MAC_INFOELT_INFO_OFT - MAC_RSNIE_GROUP_CIPHER_OFT;
00296
00297 READ_CIPHER_SUITE(group_cipher);
00298
00299 READ_CNT();
00300 while ((cnt > 0) && (len >= 4))
00301 {
00302 READ_CIPHER_SUITE(pairwise_cipher);
00303 cnt--;
00304 }
00305
00306 if (sec_ie_len < 2)
00307 return;
00308
00309 READ_CNT();
00310 while ((cnt > 0) && (len >= 4))
00311 {
00312 READ_AKM_SUITE();
00313 cnt--;
00314 }
00315
00316 if (len < 2)
00317 return;
00318
00319 rsn_capa = co_wtohs(co_read16p(sec_ie));
00320 sec_ie += 2;
00321 len -= 2;
00322
00323 if (len >= 2)
00324 {
00325 READ_CNT();
00326 sec_ie += MAC_RSNIE_RSN_PMKID_SIZE * cnt;
00327 len -= MAC_RSNIE_RSN_PMKID_SIZE * cnt;
00328 }
00329
00330 if (rsn_capa & (MAC_RSNIE_CAPA_MFPR_BIT | MAC_RSNIE_CAPA_MFPC_BIT))
00331 {
00332 if (len >= 4)
00333 {
00334 READ_CIPHER_SUITE(group_cipher);
00335 }
00336 else
00337 {
00338 res->group_cipher |= CO_BIT(MAC_CIPHER_BIP_CMAC_128);
00339 }
00340 }
00341
00342 return;
00343 }
00344
00345
00346 sec_ie = mac_ie_wpa_find(ies, ies_len, &sec_ie_len);
00347 if (sec_ie)
00348 {
00349 res->akm = CO_BIT(MAC_AKM_PRE_RSN);
00350
00351 sec_ie += MAC_WPA_GROUP_CIPHER_OFT;
00352 len = sec_ie_len + MAC_INFOELT_INFO_OFT - MAC_WPA_GROUP_CIPHER_OFT;
00353
00354 READ_CIPHER_SUITE(group_cipher);
00355
00356 READ_CNT();
00357 while ((cnt > 0) && (len >= 4))
00358 {
00359 READ_CIPHER_SUITE(pairwise_cipher);
00360 cnt--;
00361 }
00362
00363 if (len < 2)
00364 return;
00365
00366 READ_CNT();
00367 while ((cnt > 0) && (len >= 4))
00368 {
00369 READ_AKM_SUITE();
00370 cnt--;
00371 }
00372
00373 return;
00374 }
00375
00376 #if RW_WAPI_EN
00377
00378 sec_ie = mac_ie_wapi_find(ies, ies_len, &sec_ie_len);
00379 if (sec_ie)
00380 {
00381
00382 sec_ie += MAC_WAPI_AKM_SUITE_CNT_OFT;
00383 len = sec_ie_len + MAC_INFOELT_INFO_OFT - MAC_WAPI_AKM_SUITE_CNT_OFT;
00384
00385 READ_CNT();
00386 while ((cnt > 0) && (len >= 4))
00387 {
00388 READ_AKM_SUITE();
00389 cnt--;
00390 }
00391
00392 if (len < 2)
00393 return;
00394
00395 READ_CNT();
00396 while ((cnt > 0) && (len >= 4))
00397 {
00398 READ_CIPHER_SUITE(pairwise_cipher);
00399 cnt--;
00400 }
00401
00402 if (len < 4)
00403 return;
00404
00405 READ_CIPHER_SUITE(group_cipher);
00406
00407 return;
00408 }
00409 #endif // RW_WAPI_EN
00410
00411
00412 res->akm = CO_BIT(MAC_AKM_PRE_RSN);
00413 res->group_cipher = CO_BIT(MAC_CIPHER_WEP40);
00414
00415 #undef READ_CIPHER_SUITE
00416 #undef READ_AKM_SUITE
00417 #undef READ_CNT
00418
00419 #endif // NX_FULLY_HOSTED
00420 }
00421
00437 static bool scanu_new_bssid_set(struct scanu_mbssid_profile_tag *mbssid,
00438 uint8_t max_bss_ind,
00439 struct mac_scan_result const *res)
00440 {
00441 struct mac_addr bssid;
00442 struct mac_scan_result *new_res;
00443 uint8_t ssid_len = mac_ie_len(mbssid->ssid_ie_addr) - MAC_INFOELT_INFO_OFT;
00444
00445
00446 if (!mac_nontxed_bssid_get(mbssid->bssid_index, max_bss_ind, &res->bssid, &bssid))
00447 return false;
00448
00449
00450 new_res = scanu_find_result(&bssid, false);
00451 if (new_res)
00452 return true;
00453
00454
00455 new_res = scanu_find_result(&bssid, true);
00456 if (new_res == NULL)
00457 return false;
00458
00459
00460 *new_res = *res;
00461
00462 new_res->bssid = bssid;
00463 new_res->ssid.length = ssid_len;
00464 co_unpack8p(new_res->ssid.array, mbssid->ssid_ie_addr + MAC_SSID_SSID_OFT, ssid_len);
00465 new_res->max_bssid_indicator = max_bss_ind;
00466 new_res->multi_bssid_index = mbssid->bssid_index;
00467 scanu_env.result_cnt++;
00468 new_res->valid_flag = true;
00469
00470 return true;
00471 }
00472
00480 static void scanu_store_multi_bssid_info(struct mac_scan_result const *res)
00481 {
00482 struct scanu_mbssids_tag *mbssids = &scanu_env.mbssids;
00483
00484 for (int i = 0; i < mbssids->mbssid_cnt; i++)
00485 {
00486 if (!scanu_new_bssid_set(&mbssids->bssids[i], mbssids->max_bssid_ind, res))
00487 return;
00488 }
00489 }
00490
00506 static void scanu_get_multi_bssid_info(uint32_t ies, uint16_t ies_len)
00507 {
00508 uint32_t capa_addr = 0;
00509 uint32_t bssid_index_ie_addr = 0;
00510 uint32_t ssid_ie_addr = 0;
00511 uint8_t ssid_len;
00512 struct scanu_mbssids_tag *mbssids = &scanu_env.mbssids;
00513 mbssids->mbssid_cnt = 0;
00514
00515 while (ies_len)
00516 {
00517 uint32_t mbssid_ie_addr;
00518 uint32_t mbssid_ie_len;
00519 uint32_t sub_ie_addr;
00520 uint32_t sub_ie_len;
00521 uint32_t sub_ies;
00522 uint16_t subies_len;
00523 uint32_t bssid_ies;
00524 uint16_t bssid_ies_len;
00525
00526
00527 mbssid_ie_addr = mac_ie_multi_bssid_find(ies, ies_len);
00528 if (!mbssid_ie_addr)
00529 return;
00530
00531 mbssid_ie_len = mac_ie_len(mbssid_ie_addr);
00532 mbssids->max_bssid_ind = co_read8p(mbssid_ie_addr + MAC_MULTI_BSSID_MAX_INDICATOR_OFT);
00533 sub_ies = mbssid_ie_addr + MAC_MULTI_BSSID_SUB_IES_OFT;
00534 subies_len = mbssid_ie_len - MAC_MULTI_BSSID_SUB_IES_OFT;
00535
00536 while (subies_len)
00537 {
00538
00539
00540 sub_ie_addr = mac_ie_sub_non_txed_bssid_find(sub_ies, subies_len);
00541 if (!sub_ie_addr)
00542 break;
00543
00544 sub_ie_len = mac_ie_len(sub_ie_addr);
00545 bssid_ies = sub_ie_addr + MAC_MBSSID_NON_TXED_PROF_INFO_OFT;
00546 bssid_ies_len = sub_ie_len - MAC_MBSSID_NON_TXED_PROF_INFO_OFT;
00547 sub_ies += sub_ie_len;
00548 subies_len -= sub_ie_len;
00549
00550
00551
00552 if (mac_ie_non_txed_bssid_capa_find(bssid_ies, MAC_NON_TXED_BSSID_CAPA_LEN))
00553 {
00554
00555 capa_addr = bssid_ies + MAC_NON_TXED_BSSID_CAPA_OFT;
00556 bssid_index_ie_addr = 0;
00557 ssid_ie_addr = 0;
00558 }
00559 else if (!capa_addr)
00560 continue;
00561
00562
00563 if (!bssid_index_ie_addr)
00564 bssid_index_ie_addr = mac_ie_multi_bssid_index_find(bssid_ies, bssid_ies_len);
00565 if (!ssid_ie_addr)
00566 ssid_ie_addr = mac_ie_ssid_find(bssid_ies, bssid_ies_len, &ssid_len);
00567
00568
00569
00570 if (bssid_index_ie_addr && ssid_ie_addr)
00571 {
00572 struct scanu_mbssid_profile_tag *mbssid = &mbssids->bssids[mbssids->mbssid_cnt];
00573 mbssid->bssid_index = co_read8p(bssid_index_ie_addr + MAC_MULTI_BSSID_INDEX_OFT);
00574 mbssid->ssid_ie_addr = ssid_ie_addr;
00575 mbssid->capa = co_read16p(capa_addr);
00576 mbssids->mbssid_cnt++;
00577 if (mbssids->mbssid_cnt == SCANU_MAX_NONTXED_BSSID_PER_BEACON)
00578 return;
00579 capa_addr = 0;
00580 }
00581 }
00582 ies += mbssid_ie_len;
00583 ies_len -= mbssid_ie_len;
00584 }
00585 }
00586
00597 static bool scanu_is_scanned_ssid(struct mac_ssid *ssid)
00598 {
00599 struct scanu_start_req const *param = scanu_env.param;
00600 int i;
00601
00602 #if (NX_P2P)
00603 if (scanu_env.p2p_scan)
00604 {
00605 if (!memcmp(&ssid->array[0], P2P_SSID_WILDCARD, P2P_SSID_WILDCARD_LEN))
00606 return true;
00607 }
00608 else
00609 #endif //(NX_P2P)
00610 {
00611
00612 if (!param->ssid_cnt)
00613
00614 return true;
00615
00616 for (i = 0; i < param->ssid_cnt; i++)
00617 {
00618 struct mac_ssid const *scanned_ssid = ¶m->ssid[i];
00619 if ((scanned_ssid->length == 0) || (MAC_SSID_CMP(scanned_ssid, ssid)))
00620
00621 return true;
00622 }
00623 }
00624
00625 return false;
00626 }
00627
00641 static bool scanu_check_ssid(struct mac_scan_result *res)
00642 {
00643 struct scanu_mbssids_tag *mbssids = &scanu_env.mbssids;
00644
00645
00646 if (scanu_is_scanned_ssid(&res->ssid))
00647
00648 return true;
00649
00650
00651
00652 for (int i = 0; i < mbssids->mbssid_cnt; i++)
00653 {
00654 struct scanu_mbssid_profile_tag *mbssid = &mbssids->bssids[i];
00655 struct mac_ssid ssid;
00656
00657 ssid.length = mac_ie_len(mbssid->ssid_ie_addr) - MAC_INFOELT_INFO_OFT;
00658 co_unpack8p(ssid.array, mbssid->ssid_ie_addr + MAC_SSID_SSID_OFT, ssid.length);
00659
00660
00661 if (scanu_is_scanned_ssid(&ssid))
00662
00663 return true;
00664 }
00665
00666 return false;
00667
00668 }
00669
00684 static int scanu_join_frame_handler(struct rxu_mgt_ind const *frame)
00685 {
00686 struct mac_scan_result *scan;
00687 struct scanu_start_req const *param = scanu_env.param;
00688 uint32_t var_part_addr, var_part_len;
00689 uint32_t ht_op_addr = 0, vht_op_addr = 0;
00690 struct bcn_frame const *frm = (struct bcn_frame const *)frame->payload;
00691 struct vif_info_tag *vif = &vif_info_tab[param->vif_idx];
00692 struct me_bss_info *bss = &vif->bss_info;
00693 bool changed;
00694
00695
00696
00697 if (!MAC_ADDR_CMP(&frm->h.addr3, &scanu_env.bssid) &&
00698 !MAC_ADDR_CMP(&frm->h.addr3, &scanu_env.ref_bssid))
00699 return KE_MSG_CONSUMED;
00700
00701
00702 scan = scanu_find_result(&scanu_env.bssid, false);
00703 if (scan == NULL)
00704 return KE_MSG_CONSUMED;
00705
00706
00707 var_part_addr = CPU2HW(frm->variable);
00708 var_part_len = frame->length - MAC_BEACON_VARIABLE_PART_OFT;
00709
00710
00711
00712 #if NX_HE
00713 bss->mu_edca_param.param_set_cnt = 0xFF;
00714 #endif
00715 bss->edca_param.param_set_cnt = 0xFF;
00716
00717
00718 bss->bsstype = scan->bsstype;
00719 bss->bssid = scan->bssid;
00720 bss->beacon_period = frm->bcnint;
00721 bss->ssid = scan->ssid;
00722 bss->chan.band = scan->chan->band;
00723 bss->chan.prim20_freq = scan->chan->freq;
00724 bss->chan.tx_power = scan->chan->tx_power;
00725 bss->chan.flags = scan->chan->flags;
00726 bss->bssid_index = scan->multi_bssid_index;
00727 bss->max_bssid_ind = scan->max_bssid_indicator;
00728
00729 BSS_CAPA_RESET(bss);
00730
00731
00732 me_extract_rate_set(var_part_addr, var_part_len, &(bss->rate_set));
00733 if (scan->chan->band == PHY_BAND_2G4)
00734 {
00735 uint32_t basic_11b_rates;
00736 basic_11b_rates = me_legacy_rate_bitfield_build(&(bss->rate_set), true) & 0x0F;
00737
00738 if (basic_11b_rates)
00739
00740 bss->high_11b_rate = 31 - co_clz(basic_11b_rates);
00741 else
00742
00743 bss->high_11b_rate = HW_RATE_2MBPS;
00744 }
00745
00746
00747 if (me_extract_edca_params(var_part_addr, var_part_len, &bss->edca_param,
00748 &changed))
00749 {
00750 BSS_CAPA_SET(bss, QOS);
00751 }
00752
00753
00754 if (LOCAL_CAPA(HT) && BSS_CAPA(bss, QOS) &&
00755 me_extract_ht_capa(var_part_addr, var_part_len, &bss->ht_cap))
00756 {
00757 BSS_CAPA_SET(bss, HT);
00758
00759 ht_op_addr = mac_ie_ht_oper_find(var_part_addr, var_part_len);
00760
00761 #if NX_HE
00762 if (LOCAL_CAPA(HE) &&
00763 me_extract_he_capa(var_part_addr, var_part_len, &bss->he_cap))
00764 {
00765 BSS_CAPA_SET(bss, HE);
00766
00767
00768 me_extract_he_oper(var_part_addr, var_part_len, bss);
00769 }
00770 #endif
00771
00772 #if NX_VHT
00773
00774
00775
00776
00777
00778 if ((LOCAL_CAPA(VHT) || BSS_CAPA(bss, HE)) &&
00779 me_extract_vht_capa(var_part_addr, var_part_len, &bss->vht_cap))
00780 {
00781 BSS_CAPA_SET(bss, VHT);
00782
00783 vht_op_addr = mac_ie_vht_oper_find(var_part_addr, var_part_len);
00784 }
00785 #endif
00786 }
00787
00788
00789 me_bw_check(ht_op_addr, vht_op_addr, bss);
00790
00791
00792 me_extract_power_constraint(var_part_addr, var_part_len, bss);
00793
00794
00795 me_extract_country_reg(var_part_addr, var_part_len, bss);
00796
00797
00798 tpc_update_vif_tx_power(vif);
00799
00800
00801 me_extract_mobility_domain(var_part_addr, var_part_len, bss);
00802
00803
00804 BSS_CAPA_SET(bss, VALID);
00805
00806
00807 scanu_env.join_status = 1;
00808
00809 return KE_MSG_CONSUMED;
00810 }
00811
00826 static int scanu_scan_frame_handler(struct rxu_mgt_ind const *frame)
00827 {
00828 struct mac_scan_result *scan;
00829 uint32_t elmt_addr, var_part_addr, var_part_len;
00830 struct bcn_frame const *frm = (struct bcn_frame const *)frame->payload;
00831 uint8_t elmt_length;
00832 struct mac_addr const *bssid = &frm->h.addr3;
00833
00834
00835 if (!MAC_ADDR_GROUP(&scanu_env.bssid) &&
00836 !MAC_ADDR_CMP(bssid, &scanu_env.bssid))
00837 return KE_MSG_CONSUMED;
00838
00839
00840 scan = scanu_find_result(bssid, true);
00841 if (scan == NULL)
00842 return KE_MSG_CONSUMED;
00843
00844
00845 MAC_ADDR_CPY(&scan->bssid, bssid);
00846
00847
00848 if ((frm->capa & MAC_CAPA_ESS) == MAC_CAPA_ESS)
00849 scan->bsstype = INFRASTRUCTURE_MODE;
00850 else
00851 scan->bsstype = INDEPENDENT_BSS_MODE;
00852
00853
00854 var_part_addr = CPU2HW(frm->variable);
00855 var_part_len = frame->length - MAC_BEACON_VARIABLE_PART_OFT;
00856
00857
00858 elmt_addr = mac_ie_ssid_find(var_part_addr, var_part_len, &elmt_length);
00859 if (elmt_addr != 0)
00860 {
00861 scan->ssid.length = elmt_length;
00862
00863 co_unpack8p(scan->ssid.array, elmt_addr + MAC_SSID_SSID_OFT, elmt_length);
00864 }
00865 else
00866 {
00867
00868 scan->ssid.length = 0;
00869 }
00870
00871
00872 scanu_get_multi_bssid_info(var_part_addr, var_part_len);
00873
00874
00875 if (!scanu_check_ssid(scan))
00876 return KE_MSG_CONSUMED;
00877
00878
00879 elmt_addr = mac_ie_ds_find(var_part_addr, var_part_len);
00880 if (elmt_addr != 0)
00881 {
00882 uint8_t ch_nbr = co_read8p(elmt_addr + MAC_DS_CHANNEL_OFT);
00883 scan->chan = me_freq_to_chan_ptr(frame->band,
00884 phy_channel_to_freq(frame->band, ch_nbr));
00885
00886 if (frame->rssi > scan->rssi)
00887 {
00888 scan->rssi = frame->rssi;
00889 }
00890 }
00891 else
00892 {
00893
00894 if (frame->rssi > scan->rssi)
00895 {
00896 scan->chan = me_freq_to_chan_ptr(frame->band, frame->center_freq);
00897 scan->rssi = frame->rssi;
00898 }
00899 }
00900
00901 scanu_get_security_info(var_part_addr, var_part_len, frm->capa, scan);
00902
00903
00904 if (!scan->valid_flag)
00905 {
00906
00907 scanu_env.result_cnt++;
00908 }
00909
00910
00911 scan->valid_flag = true;
00912
00913
00914
00915 scanu_store_multi_bssid_info(scan);
00916
00917 ke_msg_forward_and_change_id(frame, SCANU_RESULT_IND, TASK_API, TASK_SCANU);
00918
00919 return KE_MSG_NO_FREE;
00920 }
00921
00922 void scanu_confirm(uint8_t status)
00923 {
00924 struct scanu_start_cfm* cfm;
00925
00926 if (scanu_env.joining)
00927 cfm = KE_MSG_ALLOC(SCANU_JOIN_CFM, scanu_env.src_id, TASK_SCANU, scanu_start_cfm);
00928 else
00929 {
00930 #if (NX_ANT_DIV)
00931 ke_msg_send_basic(MM_ANT_DIV_UPDATE_REQ, TASK_MM, TASK_SCANU);
00932 #endif //(NX_ANT_DIV)
00933 cfm = KE_MSG_ALLOC(SCANU_START_CFM, scanu_env.src_id, TASK_SCANU, scanu_start_cfm);
00934 }
00935
00936 cfm->vif_idx = scanu_env.param->vif_idx;
00937 cfm->status = status;
00938 cfm->result_cnt = scanu_env.result_cnt;
00939
00940
00941 ke_msg_free(ke_param2msg(scanu_env.param));
00942 scanu_env.param = NULL;
00943
00944
00945 ke_msg_send(cfm);
00946
00947
00948 ke_state_set(TASK_SCANU, SCANU_IDLE);
00949 }
00950
00951 void scanu_init(void)
00952 {
00953 struct scanu_add_ie_tag *ie_desc = &scanu_add_ie;
00954 struct hal_dma_desc_tag *gp_dma = &scanu_env.dma_desc;
00955
00956
00957 ke_state_set(TASK_SCANU, SCANU_IDLE);
00958
00959
00960 memset(&scanu_env, 0, sizeof(scanu_env));
00961
00962
00963 gp_dma->cb = scanu_dma_cb;
00964 gp_dma->env = NULL;
00965 gp_dma->dma_desc = &ie_desc->dma_desc;
00966
00967
00968 ie_desc->dma_desc.dest = CPU2HW(ie_desc->buf);
00969 }
00970
00971 int scanu_frame_handler(struct rxu_mgt_ind const *frame)
00972 {
00973
00974 if (ke_state_get(TASK_SCANU) != SCANU_SCANNING)
00975 return KE_MSG_CONSUMED;
00976
00977 if (scanu_env.joining)
00978 return scanu_join_frame_handler(frame);
00979 else
00980 return scanu_scan_frame_handler(frame);
00981 }
00982
00983 struct mac_scan_result *scanu_find_result(struct mac_addr const *bssid_ptr,
00984 bool allocate)
00985 {
00986 uint8_t i=0;
00987 struct mac_scan_result* scan_rslt = NULL;
00988
00989
00990 for (i = 0; i < SCANU_MAX_RESULTS; i++)
00991 {
00992 struct mac_scan_result *scan = &scanu_env.scan_result[i];
00993
00994
00995 if (scan->valid_flag)
00996 {
00997 if (MAC_ADDR_CMP(&scan->bssid, bssid_ptr))
00998 {
00999
01000 scan_rslt = scan;
01001 break;
01002 }
01003 }
01004 else if (allocate)
01005 {
01006
01007 scan_rslt = scan;
01008 break;
01009 }
01010 }
01011 return (scan_rslt);
01012 }
01013
01014 struct mac_scan_result *scanu_search_by_bssid(struct mac_addr const *bssid)
01015 {
01016 return (scanu_find_result(bssid, false));
01017 }
01018
01019 struct mac_scan_result *scanu_search_by_ssid(struct mac_ssid const *ssid)
01020 {
01021 uint8_t i=0;
01022 int8_t rssi = ~0x7F;
01023 struct mac_scan_result* scan_rslt = NULL;
01024
01025 do
01026 {
01027
01028 if (!ssid->length)
01029 break;
01030
01031
01032
01033 for (i = 0; i < SCANU_MAX_RESULTS; i++)
01034 {
01035 struct mac_scan_result *scan = &scanu_env.scan_result[i];
01036
01037
01038 if (!scan->valid_flag)
01039 break;
01040
01041
01042
01043 if ((scan->rssi > rssi) && (MAC_SSID_CMP(&scan->ssid, ssid)))
01044 {
01045 scan_rslt = scan;
01046 rssi = scan->rssi;
01047 }
01048 }
01049 } while(0);
01050
01051 return (scan_rslt);
01052 }
01053
01054 void scanu_start(void)
01055 {
01056 int i;
01057
01058 if (!scanu_env.joining)
01059 {
01060
01061 memset(scanu_env.scan_result, 0, sizeof(scanu_env.scan_result));
01062 for (i = 0; i < SCANU_MAX_RESULTS; i++)
01063 {
01064 scanu_env.scan_result[i].rssi = ~0x7F;
01065 }
01066
01067
01068 scanu_env.result_cnt = 0;
01069 }
01070
01071 #if (NX_P2P)
01072 if ((scanu_env.param->ssid_cnt == 1) && (scanu_env.param->ssid[0].length == P2P_SSID_WILDCARD_LEN) &&
01073 !memcmp(&scanu_env.param->ssid[0].array[0], P2P_SSID_WILDCARD, P2P_SSID_WILDCARD_LEN))
01074 {
01075 scanu_env.p2p_scan = true;
01076 }
01077 else
01078 {
01079 scanu_env.p2p_scan = false;
01080 }
01081 #endif //(NX_P2P)
01082
01083
01084 ke_state_set(TASK_SCANU, SCANU_SCANNING);
01085
01086
01087 scanu_ie_download();
01088 }
01089
01090 void scanu_scan_next(void)
01091 {
01092 int i;
01093 struct scanu_start_req const *param = scanu_env.param;
01094 struct scan_start_req *req;
01095
01096 do
01097 {
01098
01099 if (scanu_env.band > PHY_BAND_5G)
01100 break;
01101
01102
01103 for (i = 0; i < param->chan_cnt; i++)
01104 {
01105 if (param->chan[i].band == scanu_env.band)
01106 break;
01107 }
01108
01109
01110 if (i == param->chan_cnt)
01111 {
01112 scanu_env.band++;
01113 continue;
01114 }
01115
01116
01117 req = KE_MSG_ALLOC(SCAN_START_REQ, TASK_SCAN, TASK_SCANU, scan_start_req);
01118
01119
01120 req->vif_idx = param->vif_idx;
01121 req->bssid = param->bssid;
01122 req->ssid_cnt = param->ssid_cnt;
01123 req->no_cck = param->no_cck;
01124
01125
01126 for (; i < param->chan_cnt; i++)
01127 {
01128
01129 if (param->chan[i].band == scanu_env.band)
01130 {
01131 req->chan[req->chan_cnt] = param->chan[i];
01132 req->chan_cnt++;
01133 }
01134 }
01135
01136 for (i = 0; i < param->ssid_cnt; i++)
01137 {
01138 req->ssid[i] = param->ssid[i];
01139 }
01140
01141
01142 req->add_ie_len = scanu_build_ie();
01143 req->add_ies = 0;
01144
01145
01146 ke_msg_send(req);
01147
01148 return;
01149 } while(1);
01150
01151
01152 scanu_confirm(CO_OK);
01153 }
01154
01156