00001
00013 #include "me_mgmtframe.h"
00014 #include "mac_frame.h"
00015 #include "mac_ie.h"
00016 #include "mac.h"
00017 #include "me.h"
00018 #include "sm_task.h"
00019 #include "ps.h"
00020
00021 #include "co_endian.h"
00022
00023 #include "co_utils.h"
00024 #include "me_utils.h"
00025 #include "sta_mgmt.h"
00026
00027
00029 #define ME_DEFAULT_LISTEN_INTERVAL 5
00030
00039 static void me_add_baparamset_frame(uint32_t addr, struct bam_env_tag *bam_env)
00040 {
00041 uint16_t value = 0;
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 value |= 0;
00056
00057 value |= (bam_env->ba_policy << MAC_BA_PARAMSET_POLICY_OFT);
00058
00059 value |= (bam_env->tid << MAC_BA_PARAMSET_TID_OFT);
00060
00061 value |= (bam_env->buffer_size << MAC_BA_PARAMSET_BUFFER_OFT);
00062
00063 co_write16p(addr, co_htows(value));
00064 }
00065
00074 static void me_add_ba_ssc_frame(uint32_t addr, struct bam_env_tag *bam_env)
00075 {
00076 co_write16p(addr, co_htows(bam_env->ssn << MAC_BA_BARINFO_SEQ_STARTSEQ_OFT));
00077 }
00078
00087 static void me_del_baparamset_frame(uint32_t addr, struct bam_env_tag *bam_env)
00088 {
00089
00090
00091
00092
00093
00094
00095
00096
00097 uint16_t value = 0;
00098
00099
00100 value |= bam_env->tid << BAM_DELBA_PARAM_TID_OFFSET;
00101
00102 if (bam_env->dev_type == BA_ORIGINATOR)
00103 {
00104 value |= BAM_DELBA_PARAM_INITIATOR_MASK;
00105 }
00106
00107 co_write16p(addr, co_htows(value));
00108 }
00109
00110
00111
00112
00113
00114
00115 uint32_t me_add_ie_ssid(uint32_t *frame_addr, uint8_t ssid_len, uint8_t *ssid)
00116 {
00117
00118 uint32_t ie_len = MAC_INFOELT_INFO_OFT + ssid_len;
00119
00120
00121 co_write8p(*frame_addr + MAC_INFOELT_ID_OFT, MAC_ELTID_SSID);
00122
00123 co_write8p(*frame_addr + MAC_INFOELT_LEN_OFT, ssid_len);
00124
00125 if (ssid_len != 0)
00126 {
00127
00128 co_pack8p(*frame_addr + MAC_INFOELT_INFO_OFT, (uint8_t *)ssid, ssid_len);
00129 }
00130
00131
00132 *frame_addr += ie_len;
00133
00134
00135 return (ie_len);
00136 }
00137
00138 uint32_t me_add_ie_supp_rates(uint32_t *frame_addr, struct mac_rateset *rateset)
00139 {
00140
00141 uint32_t supp_len = co_min(rateset->length, MAC_RATES_ELMT_MAX_LEN);
00142
00143 uint32_t ie_len = MAC_INFOELT_INFO_OFT + supp_len;
00144
00145
00146 co_write8p(*frame_addr + MAC_INFOELT_ID_OFT, MAC_ELTID_RATES);
00147
00148 co_write8p(*frame_addr + MAC_INFOELT_LEN_OFT, supp_len);
00149
00150
00151 co_pack8p(*frame_addr + MAC_INFOELT_INFO_OFT, rateset->array, supp_len);
00152
00153
00154 *frame_addr += ie_len;
00155
00156
00157 return (ie_len);
00158 }
00159
00160 uint32_t me_add_ie_ext_supp_rates(uint32_t *frame_addr, struct mac_rateset *rateset)
00161 {
00162
00163 uint32_t ext_supp_len = rateset->length - MAC_RATES_ELMT_MAX_LEN;
00164
00165 uint32_t ie_len = MAC_INFOELT_INFO_OFT + ext_supp_len;
00166
00167
00168 co_write8p(*frame_addr + MAC_INFOELT_ID_OFT, MAC_ELTID_EXT_RATES);
00169
00170 co_write8p(*frame_addr + MAC_INFOELT_LEN_OFT, ext_supp_len);
00171
00172
00173 co_pack8p(*frame_addr + MAC_INFOELT_INFO_OFT, &rateset->array[MAC_RATES_ELMT_MAX_LEN],
00174 ext_supp_len);
00175
00176
00177 *frame_addr += ie_len;
00178
00179
00180 return (ie_len);
00181 }
00182
00183 #if (RW_MESH_EN)
00184 uint32_t me_add_ie_tim(uint32_t *frame_addr, uint8_t dtim_period)
00185 {
00186
00187 uint32_t ie_len = MAC_INFOELT_INFO_OFT + 4;
00188
00189
00190 co_write8p(*frame_addr + MAC_INFOELT_ID_OFT, MAC_ELTID_TIM);
00191
00192 co_write8p(*frame_addr + MAC_INFOELT_LEN_OFT, 4);
00193
00194
00195 co_write8p(*frame_addr + MAC_TIM_PERIOD_OFT, dtim_period);
00196
00197
00198
00199 *frame_addr += ie_len;
00200
00201
00202 return (ie_len);
00203 }
00204
00205 uint32_t me_add_ie_dsss_param(uint32_t *frame_addr, uint8_t chan)
00206 {
00207
00208 uint32_t ie_len = MAC_INFOELT_INFO_OFT + 1;
00209
00210
00211 co_write8p(*frame_addr + MAC_INFOELT_ID_OFT, MAC_ELTID_DS);
00212
00213 co_write8p(*frame_addr + MAC_INFOELT_LEN_OFT, 1);
00214
00215
00216 co_write8p(*frame_addr + MAC_INFOELT_INFO_OFT, chan);
00217
00218
00219 *frame_addr += ie_len;
00220
00221
00222 return (ie_len);
00223 }
00224 #endif //(RW_MESH_EN)
00225
00226 uint32_t me_add_ie_ht_capa(uint32_t *frame_addr)
00227 {
00228
00229 uint32_t ie_len = MAC_INFOELT_INFO_OFT + MAC_HT_CAPA_ELMT_LEN;
00230
00231 struct mac_htcapability *ht_cap = &me_env.ht_cap;
00232 uint16_t ht_capa_info = ht_cap->ht_capa_info & ~MAC_HTCAPA_SMPS_MSK;
00233
00234
00235 co_write8p(*frame_addr + MAC_HT_CAPA_ID_OFT, MAC_ELTID_HT_CAPA);
00236
00237 co_write8p(*frame_addr + MAC_HT_CAPA_LEN_OFT, MAC_HT_CAPA_ELMT_LEN);
00238
00239 ht_capa_info |= MAC_HTCAPA_SMPS_DISABLE;
00240 co_write16p(*frame_addr + MAC_HT_CAPA_INFO_OFT, co_htows(ht_capa_info));
00241 co_write8p(*frame_addr + MAC_HT_CAPA_AMPDU_PARAM_OFT, ht_cap->a_mpdu_param);
00242 co_pack8p(*frame_addr + MAC_HT_CAPA_SUPPORTED_MCS_SET_OFT, ht_cap->mcs_rate,
00243 MAX_MCS_LEN);
00244 co_write16p(*frame_addr + MAC_HT_CAPA_EXTENDED_CAPA_OFT, co_htows(ht_cap->ht_extended_capa));
00245 co_pack8p(*frame_addr + MAC_HT_CAPA_TX_BEAM_FORMING_CAPA_OFT,
00246 (uint8_t *)&ht_cap->tx_beamforming_capa, 4);
00247 co_write8p(*frame_addr + MAC_HT_CAPA_ASEL_CAPA_OFT, ht_cap->asel_capa);
00248
00249 *frame_addr += ie_len;
00250
00251
00252 return (ie_len);
00253 }
00254
00255 #if (RW_MESH_EN)
00256 uint32_t me_add_ie_ht_oper(uint32_t *frame_addr, struct vif_info_tag *vif)
00257 {
00258
00259 uint32_t ie_len = MAC_INFOELT_INFO_OFT + MAC_HT_OPER_ELMT_LEN;
00260
00261 struct chan_ctxt_tag *chan_ctxt = vif->chan_ctxt;
00262
00263 uint8_t ht_info1 = 0x00;
00264
00265
00266 co_write8p(*frame_addr + MAC_HT_OPER_ID_OFT, MAC_ELTID_HT_OPERATION);
00267
00268 co_write8p(*frame_addr + MAC_HT_OPER_LEN_OFT, MAC_HT_OPER_ELMT_LEN);
00269
00270 co_write8p(*frame_addr + MAC_HT_OPER_PRIM_CH_OFT,
00271 (uint8_t)phy_freq_to_channel(chan_ctxt->channel.band,
00272 chan_ctxt->channel.prim20_freq));
00273
00274 if (chan_ctxt->channel.type > BW_20MHZ)
00275 {
00276
00277 ht_info1 |= 0x04;
00278
00279 if (chan_ctxt->channel.prim20_freq > chan_ctxt->channel.center1_freq)
00280 {
00281
00282 ht_info1 |= 0x03;
00283 }
00284 else
00285 {
00286
00287 ht_info1 |= 0x01;
00288 }
00289 }
00290
00291 co_write8p(*frame_addr + MAC_HT_OPER_INFO_OFT, ht_info1);
00292 co_write16p(*frame_addr + MAC_HT_OPER_INFO_SUBSET2_OFT, MAC_HT_OPER_OP_MODE_MASK);
00293 co_write16p(*frame_addr + MAC_HT_OPER_INFO_SUBSET3_OFT, 0);
00294 co_write8p(*frame_addr + MAC_HT_OPER_BASIC_MSC_SET_OFT, 0xFF);
00295
00296 *frame_addr += ie_len;
00297
00298
00299 return (ie_len);
00300 }
00301 #endif //(RW_MESH_EN)
00302
00303 #if NX_HE
00304 uint32_t me_add_ie_he_capa(uint32_t *frame_addr)
00305 {
00306
00307 uint32_t ie_len;
00308
00309 struct mac_hecapability *he_cap = &me_env.he_cap;
00310 int i;
00311 uint8_t chan_width_set;
00312 uint32_t copy_addr;
00313
00314
00315 co_write8p(*frame_addr + MAC_HE_CAPA_ID_OFT, MAC_ELTID_EXT);
00316
00317 co_write8p(*frame_addr + MAC_HE_CAPA_EXT_ID_OFT, MAC_ELTID_EXT_HE_CAPA);
00318
00319
00320 copy_addr = *frame_addr + MAC_HE_MAC_CAPA_INFO_OFT;
00321 for (i = 0; i < MAC_HE_CAPA_IE_MAC_CAPA_LEN; i++)
00322 {
00323 co_write8p(copy_addr++, he_cap->mac_cap_info[i]);
00324 }
00325 for (i = 0; i < MAC_HE_CAPA_IE_PHY_CAPA_LEN; i++)
00326 {
00327 co_write8p(copy_addr++, he_cap->phy_cap_info[i]);
00328 }
00329
00330
00331 chan_width_set = HE_PHY_CAPA_VAL_GET(he_cap, CHAN_WIDTH_SET);
00332 co_write16p(copy_addr, co_htows(he_cap->mcs_supp.rx_mcs_80));
00333 copy_addr += 2;
00334 co_write16p(copy_addr, co_htows(he_cap->mcs_supp.tx_mcs_80));
00335 copy_addr += 2;
00336 if (chan_width_set & HE_PHY_CAPA_CHAN_WIDTH_SET_160MHZ_IN_5G)
00337 {
00338 co_write16p(copy_addr, co_htows(he_cap->mcs_supp.rx_mcs_160));
00339 copy_addr += 2;
00340 co_write16p(copy_addr, co_htows(he_cap->mcs_supp.tx_mcs_160));
00341 copy_addr += 2;
00342 }
00343 if (chan_width_set & HE_PHY_CAPA_CHAN_WIDTH_SET_80PLUS80_MHZ_IN_5G)
00344 {
00345 co_write16p(copy_addr, co_htows(he_cap->mcs_supp.rx_mcs_80p80));
00346 copy_addr += 2;
00347 co_write16p(copy_addr, co_htows(he_cap->mcs_supp.rx_mcs_80p80));
00348 copy_addr += 2;
00349 }
00350
00351
00352 for (i = 0; i < (2 + me_env.phy_bw_max); i++)
00353 {
00354 co_write8p(copy_addr++, he_cap->ppe_thres[i]);
00355 }
00356
00357 ie_len = copy_addr - *frame_addr;
00358
00359 co_write8p(*frame_addr + MAC_HE_CAPA_LEN_OFT, ie_len - 2);
00360 *frame_addr += ie_len;
00361
00362
00363 return (ie_len);
00364 }
00365 #endif
00366
00367 #if (NX_VHT)
00368 uint32_t me_add_ie_vht_capa(uint32_t *frame_addr)
00369 {
00370
00371 uint32_t ie_len = MAC_INFOELT_INFO_OFT + MAC_VHT_CAPA_ELMT_LEN;
00372
00373 struct mac_vhtcapability *vht_cap = &me_env.vht_cap;
00374
00375
00376 co_write8p(*frame_addr + MAC_VHT_CAPA_ID_OFT, MAC_ELTID_VHT_CAPA);
00377
00378 co_write8p(*frame_addr + MAC_VHT_CAPA_LEN_OFT, MAC_VHT_CAPA_ELMT_LEN);
00379
00380 co_write32p(*frame_addr + MAC_VHT_CAPA_INFO_OFT, co_htowl(vht_cap->vht_capa_info));
00381 co_write16p(*frame_addr + MAC_VHT_RX_MCS_MAP_OFT, co_htows(vht_cap->rx_mcs_map));
00382 co_write16p(*frame_addr + MAC_VHT_RX_HIGHEST_RATE_OFT, co_htows(vht_cap->rx_highest));
00383 co_write16p(*frame_addr + MAC_VHT_TX_MCS_MAP_OFT, co_htows(vht_cap->tx_mcs_map));
00384 co_write16p(*frame_addr + MAC_VHT_TX_HIGHEST_RATE_OFT, co_htows(vht_cap->tx_highest));
00385
00386 *frame_addr += ie_len;
00387
00388
00389 return (ie_len);
00390 }
00391
00392 #if (RW_MESH_EN)
00393 uint32_t me_add_ie_vht_oper(uint32_t *frame_addr, struct vif_info_tag *vif)
00394 {
00395
00396 uint32_t ie_len = MAC_INFOELT_INFO_OFT + MAC_VHT_OPER_ELMT_LEN;
00397
00398 struct chan_ctxt_tag *chan_ctxt = vif->chan_ctxt;
00399
00400
00401 co_write8p(*frame_addr + MAC_VHT_OPER_ID_OFT, MAC_ELTID_VHT_OPERATION);
00402
00403 co_write8p(*frame_addr + MAC_VHT_OPER_LEN_OFT, MAC_VHT_OPER_ELMT_LEN);
00404
00405 if (chan_ctxt->channel.type == BW_80MHZ)
00406 {
00407 co_write8p(*frame_addr + MAC_VHT_CHAN_WIDTH_OFT, 1);
00408 co_write8p(*frame_addr + MAC_VHT_CENTER_FREQ0_OFT,
00409 (uint8_t)phy_freq_to_channel(chan_ctxt->channel.band,
00410 chan_ctxt->channel.center1_freq));
00411 }
00412 else
00413 {
00414 co_write8p(*frame_addr + MAC_VHT_CHAN_WIDTH_OFT, 0);
00415 co_write8p(*frame_addr + MAC_VHT_CENTER_FREQ0_OFT, 0);
00416 }
00417
00418 co_write8p(*frame_addr + MAC_VHT_CENTER_FREQ1_OFT, 0);
00419 co_write16p(*frame_addr + MAC_VHT_BASIC_MCS_OFT, 0);
00420
00421 *frame_addr += ie_len;
00422
00423
00424 return (ie_len);
00425 }
00426 #endif //(RW_MESH_EN)
00427
00428 uint32_t me_add_ie_op_mode(uint32_t *frame_addr, uint8_t nss, uint8_t bw)
00429 {
00430
00431 uint32_t ie_len = MAC_INFOELT_INFO_OFT + MAC_OP_MODE_NOTIF_PARAM_LEN;
00432 uint8_t op_mode = (bw << MAC_OPMODE_BW_OFT) | (nss << MAC_OPMODE_RXNSS_OFT);
00433
00434
00435 co_write8p(*frame_addr + MAC_INFOELT_ID_OFT, MAC_ELTID_OP_MODE_NOTIF);
00436
00437 co_write8p(*frame_addr + MAC_INFOELT_LEN_OFT, MAC_OP_MODE_NOTIF_PARAM_LEN);
00438
00439 co_write8p(*frame_addr + MAC_INFOELT_INFO_OFT, op_mode);
00440
00441 *frame_addr += ie_len;
00442
00443
00444 return (ie_len);
00445 }
00446 #endif //(NX_VHT)
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500 uint16_t me_build_authenticate(uint32_t frame,
00501 uint16_t algo_type,
00502 uint16_t seq_nbr,
00503 uint16_t status_code,
00504 uint32_t *challenge_array_ptr)
00505 {
00506
00507 uint16_t mac_frame_len;
00508
00509 co_write16p(frame + MAC_AUTH_ALGONBR_OFT, co_htows(algo_type));
00510 co_write16p(frame + MAC_AUTH_SEQNBR_OFT, co_htows(seq_nbr));
00511 co_write16p(frame + MAC_AUTH_STATUS_OFT, co_htows(status_code));
00512 mac_frame_len = MAC_AUTH_CHALLENGE_OFT;
00513
00514 if (challenge_array_ptr != NULL)
00515 {
00516 frame += MAC_AUTH_CHALLENGE_OFT;
00517 co_write8p(frame + MAC_CHALLENGE_ID_OFT, MAC_ELTID_CHALLENGE);
00518 co_write8p(frame + MAC_CHALLENGE_LEN_OFT, MAC_AUTH_CHALLENGE_LEN);
00519 co_copy8p(frame + MAC_CHALLENGE_TEXT_OFT, CPU2HW(challenge_array_ptr),
00520 MAC_AUTH_CHALLENGE_LEN);
00521 mac_frame_len += CHALLENGE_TEXT_SIZE;
00522 }
00523 return mac_frame_len;
00524 }
00525
00526 uint16_t me_build_deauthenticate(uint32_t frame, uint16_t reason_code)
00527 {
00528 uint16_t mac_frame_len;
00529
00530 co_write16p(frame + MAC_DISASSOC_REASON_OFT, co_htows(reason_code));
00531 mac_frame_len = MAC_DISASSOC_REASON_LEN;
00532
00533 return(mac_frame_len);
00534 }
00535
00536
00537 uint16_t me_build_associate_req(uint32_t frame,
00538 struct me_bss_info *bss,
00539 struct mac_addr *old_ap_addr_ptr,
00540 uint8_t vif_idx,
00541 uint32_t *ie_addr,
00542 uint16_t *ie_len,
00543 struct sm_connect_req const *con_par)
00544 {
00545 uint16_t mac_frame_len;
00546 uint16_t capainfo = 0;
00547 uint32_t add_ie_addr = CPU2HW(con_par->ie_buf);
00548 uint16_t add_ie_len = con_par->ie_len;
00549 uint16_t listen;
00550 #if NX_UAPSD
00551 uint8_t uapsd_info = con_par->uapsd_queues;
00552 #endif
00553
00554
00555 listen = con_par->listen_interval?con_par->listen_interval:ME_DEFAULT_LISTEN_INTERVAL;
00556
00557
00558 capainfo = me_build_capability(vif_idx);
00559
00560
00561 co_write16p(frame + MAC_ASSO_REQ_CAPA_OFT, co_htows(capainfo));
00562 co_write16p(frame + MAC_ASSO_REQ_LISTEN_OFT, co_htows(listen));
00563
00564 if (old_ap_addr_ptr)
00565 {
00566
00567 MAC_ADDR_CPY(HW2CPU(frame + MAC_REASSO_REQ_AP_ADDR_OFT), old_ap_addr_ptr);
00568
00569
00570 mac_frame_len = MAC_REASSO_REQ_SSID_OFT;
00571 }
00572 else
00573 {
00574
00575 mac_frame_len = MAC_ASSO_REQ_SSID_OFT;
00576 }
00577
00578 frame += mac_frame_len;
00579
00580 *ie_addr = frame;
00581
00582
00583 mac_frame_len += me_add_ie_ssid(&frame, bss->ssid.length, (uint8_t *)&bss->ssid.array);
00584
00585 mac_frame_len += me_add_ie_supp_rates(&frame, &bss->rate_set);
00586 if (bss->rate_set.length > MAC_RATES_ELMT_MAX_LEN)
00587 {
00588 mac_frame_len += me_add_ie_ext_supp_rates(&frame, &bss->rate_set);
00589 }
00590
00591 if (capainfo & MAC_CAPA_SPECTRUM)
00592 {
00593 int8_t min, max;
00594
00595
00596 co_write8p(frame++, MAC_ELTID_POWER_CAPABILITY);
00597 co_write8p(frame++, MAC_POWER_CAPABILITY_IE_LEN);
00598 phy_get_rf_gain_capab(&max, &min);
00599 if (max > bss->chan.tx_power)
00600 max = bss->chan.tx_power;
00601
00602 co_write8p(frame++, (uint8_t)min);
00603 co_write8p(frame++, (uint8_t)max);
00604 mac_frame_len += MAC_POWER_CAPABILITY_IE_LEN + 2;
00605 }
00606
00607 if (capainfo & MAC_CAPA_SPECTRUM)
00608 {
00609 uint8_t start, prev, i, nb, ch_incr, ch_idx, len, cnt;
00610 struct mac_chan_def *chan;
00611 uint32_t tmp;
00612
00613
00614 co_write8p(frame++, MAC_ELTID_SUPPORTED_CHANNELS);
00615 tmp = frame++;
00616 if (bss->chan.band == PHY_BAND_2G4) {
00617 ch_incr = 1;
00618 chan = me_env.chan.chan2G4;
00619 cnt = me_env.chan.chan2G4_cnt;
00620 }
00621 else
00622 {
00623 ch_incr = 4;
00624 chan = me_env.chan.chan5G;
00625 cnt = me_env.chan.chan5G_cnt;
00626 }
00627
00628 nb = len = start = prev = 0;
00629 for (i = 0; i < cnt; i++)
00630 {
00631 if (chan->flags & CHAN_DISABLED)
00632 continue;
00633
00634 ch_idx = phy_freq_to_channel(chan->band, chan->freq);
00635 if (nb && (ch_idx - prev) != ch_incr)
00636 {
00637 co_write8p(frame++, start);
00638 co_write8p(frame++, nb);
00639 nb++;
00640 len += 2;
00641 }
00642 else if (!nb)
00643 {
00644 start = ch_idx;
00645 }
00646
00647 prev = ch_idx;
00648 nb++;
00649 chan++;
00650 }
00651 co_write8p(frame++, start);
00652 co_write8p(frame++, nb);
00653 len += 2;
00654 co_write8p(tmp, len);
00655 mac_frame_len += len + 2;
00656 }
00657
00658
00659 co_copy8p(frame, add_ie_addr, add_ie_len);
00660 mac_frame_len += add_ie_len;
00661 frame += add_ie_len;
00662
00663 if (BSS_CAPA(bss, QOS))
00664 {
00665 uint8_t wme_ie[MAC_WME_PARAM_LEN] = MAC_RAW_WME_INFO_ELMT_DEFAULT;
00666
00667 #if NX_UAPSD
00668
00669 if (ps_uapsd_enabled() &&
00670 (bss->edca_param.qos_info & MAC_QOS_INFO_AP_UAPSD_ENABLED))
00671 {
00672 wme_ie[8] = uapsd_info;
00673 }
00674 else
00675 #endif
00676 {
00677 wme_ie[8] = 0;
00678 }
00679 co_pack8p(frame, (uint8_t *)&wme_ie,
00680 wme_ie[MAC_INFOELT_LEN_OFT] + MAC_INFOELT_INFO_OFT);
00681
00682
00683 mac_frame_len += wme_ie[MAC_INFOELT_LEN_OFT] + MAC_INFOELT_INFO_OFT;
00684 frame += wme_ie[MAC_INFOELT_LEN_OFT] + MAC_INFOELT_INFO_OFT;
00685 }
00686
00687
00688 if (BSS_CAPA(bss, HT) && LOCAL_CAPA(HT))
00689 {
00690 mac_frame_len += me_add_ie_ht_capa(&frame);
00691 }
00692
00693
00694 if (sm_env.ft_over_ds == 1)
00695 {
00696 struct mobility_domain *mde = &bss->mde;
00697 if (mde->mdid != 0)
00698 {
00699 co_write8p(frame + MAC_INFOELT_MDE_ID_OFT, MAC_ELTID_MDE);
00700 co_write8p(frame + MAC_INFOELT_MDE_LEN_OFT, MAC_INFOELT_MDE_ELMT_LEN);
00701
00702 co_write16p(frame + MAC_INFOELT_MDE_MDID_OFT, co_htows(mde->mdid));
00703 co_write8p(frame + MAC_INFOELT_MDE_FT_CAPA_POL_OFT, mde->ft_capability_policy);
00704
00705 mac_frame_len += MAC_INFOELT_MDE_LEN;
00706 frame += MAC_INFOELT_MDE_LEN;
00707 }
00708 }
00709
00710 #if NX_HE
00711
00712 if (BSS_CAPA(bss, HE) && LOCAL_CAPA(HE))
00713 {
00714 mac_frame_len += me_add_ie_he_capa(&frame);
00715 }
00716 #endif //(NX_VHT)
00717
00718 #if NX_VHT
00719
00720 if (BSS_CAPA(bss, VHT) && LOCAL_CAPA(VHT))
00721 {
00722 mac_frame_len += me_add_ie_vht_capa(&frame);
00723 mac_frame_len += me_add_ie_op_mode(&frame, me_11ac_nss_max(me_env.vht_cap.tx_mcs_map),
00724 me_phy2mac_bw(me_env.phy_bw_max));
00725 }
00726 #endif //(NX_VHT)
00727
00728 *ie_len = frame - *ie_addr;
00729
00730 return mac_frame_len;
00731
00732 }
00733
00734 uint16_t me_build_add_ba_req(uint32_t frame, struct bam_env_tag *bam_env)
00735 {
00736 co_write8p(frame, MAC_BA_ACTION_CATEGORY);
00737 co_write8p(frame + MAC_ACTION_ACTION_OFT, MAC_BA_ACTION_ADDBA_REQ);
00738 co_write8p(frame + MAC_ACTION_TOKEN_OFT, bam_env->dialog_token);
00739
00740
00741 me_add_baparamset_frame(frame + BAM_ADDBAREQ_BA_PARAM_OFFSET, bam_env);
00742
00743 co_write16p(frame + BAM_ADDBAREQ_BA_TIMEOUT_OFFSET, co_htows(bam_env->ba_timeout));
00744
00745
00746 me_add_ba_ssc_frame(frame + BAM_ADDBAREQ_BA_SSC_OFFSET, bam_env);
00747
00748 return (BAM_ADDBAREQ_LENGTH);
00749 }
00750
00751 uint16_t me_build_add_ba_rsp(uint32_t frame, struct bam_env_tag *bam_env,
00752 uint16_t param,
00753 uint8_t dialog_token,
00754 uint16_t status_code)
00755 {
00756 co_write8p(frame, MAC_BA_ACTION_CATEGORY);
00757 co_write8p(frame + MAC_ACTION_ACTION_OFT, MAC_BA_ACTION_ADDBA_RSP);
00758 co_write8p(frame + MAC_ACTION_TOKEN_OFT, dialog_token);
00759 co_write16p(frame + BAM_ADDBARSP_STATUS_OFFSET, co_htows(status_code));
00760
00761
00762 co_write16p(frame + BAM_ADDBARSP_BA_PARAM_OFFSET, co_htows(param));
00763
00764 if (status_code != MAC_BA_ST_SUCCESS)
00765 co_write16p(frame + BAM_ADDBARSP_BA_TIMEOUT_OFFSET, co_htows(0));
00766 else
00767 co_write16p(frame + BAM_ADDBARSP_BA_TIMEOUT_OFFSET, co_htows(bam_env->ba_timeout));
00768
00769 return (BAM_ADDBARSP_LENGTH);
00770 }
00771
00772 uint16_t me_build_del_ba(uint32_t frame, struct bam_env_tag *bam_env, uint16_t reason_code)
00773 {
00774 co_write8p(frame, MAC_BA_ACTION_CATEGORY);
00775 co_write8p(frame + MAC_ACTION_ACTION_OFT, MAC_BA_ACTION_DELBA);
00776
00777
00778 me_del_baparamset_frame(frame + BAM_DELBA_PARAM_OFFSET, bam_env);
00779
00780
00781 co_write16p(frame + BAM_DELBA_REASON_OFFSET, co_htows(reason_code));
00782
00783 return (BAM_DELBA_LENGTH);
00784 }
00785
00786
00787 void me_extract_rate_set(uint32_t buffer,
00788 uint16_t buflen,
00789 struct mac_rateset* mac_rate_set_ptr)
00790 {
00791 uint32_t addr;
00792 uint8_t elmt_length, rate_cnt = 0;
00793 int i;
00794
00795 do
00796 {
00797
00798 addr = mac_ie_rates_find(buffer, buflen, &elmt_length);
00799 if (addr == 0)
00800 break;
00801
00802
00803 addr += MAC_RATES_RATES_OFT;
00804 for (i = 0; i < elmt_length; i++)
00805 {
00806 uint8_t rate = co_read8p(addr + i);
00807
00808
00809 if (((rate & ~MAC_BASIC_RATE) == MAC_BSS_MEMBERSHIP_HT_PHY) ||
00810 ((rate & ~MAC_BASIC_RATE) == MAC_BSS_MEMBERSHIP_VHT_PHY))
00811 continue;
00812
00813 mac_rate_set_ptr->array[rate_cnt++] = rate;
00814 }
00815
00816
00817 addr = mac_ie_ext_rates_find(buffer, buflen, &elmt_length);
00818 if(addr == 0)
00819 break;
00820
00821
00822 addr += MAC_RATES_RATES_OFT;
00823 for (i = 0; i < elmt_length; i++)
00824 {
00825 uint8_t rate = co_read8p(addr + i);
00826
00827
00828 if (((rate & ~MAC_BASIC_RATE) == MAC_BSS_MEMBERSHIP_HT_PHY) ||
00829 ((rate & ~MAC_BASIC_RATE) == MAC_BSS_MEMBERSHIP_VHT_PHY))
00830 continue;
00831
00832 mac_rate_set_ptr->array[rate_cnt++] = rate;
00833
00834
00835 if (rate_cnt >= MAC_RATESET_LEN)
00836 break;
00837 }
00838 } while(0);
00839
00840
00841 mac_rate_set_ptr->length = rate_cnt;
00842 }
00843
00844
00845 void me_extract_power_constraint(uint32_t buffer, uint16_t buflen,
00846 struct me_bss_info *bss)
00847 {
00848 uint32_t addr = mac_ie_power_constraint_find(buffer, buflen);
00849
00850 if (addr == 0)
00851 {
00852 bss->power_constraint = 0;
00853 return;
00854 }
00855
00856 bss->power_constraint = co_read8p(addr + MAC_INFOELT_POWER_CONSTRAINT_OFT);
00857 }
00858
00859 void me_extract_country_reg(uint32_t buffer, uint16_t buflen,
00860 struct me_bss_info *bss)
00861 {
00862 uint32_t addr;
00863 uint8_t bss_ch_idx, ch_incr, ch_idx, ch_nb, i;
00864 uint8_t elmt_length, oft;
00865
00866 addr = mac_ie_country_find(buffer, buflen, &elmt_length);
00867
00868 if (addr == 0)
00869 return;
00870
00871
00872
00873 if (bss->chan.band == PHY_BAND_2G4)
00874 ch_incr = 1;
00875 else
00876 ch_incr = 4;
00877
00878 bss_ch_idx = phy_freq_to_channel(bss->chan.band, bss->chan.prim20_freq);
00879 elmt_length += MAC_COUNTRY_STRING_OFT;
00880 oft = MAC_COUNTRY_STRING_OFT + MAC_COUNTRY_STRING_LEN;
00881 while ((oft + MAC_COUNTRY_TRIPLET_LEN) <= elmt_length)
00882 {
00883 ch_idx = co_read8p(addr + oft + MAC_COUNTRY_FIRST_CHAN_OFT);
00884 ch_nb = co_read8p(addr + oft + MAC_COUNTRY_NB_CHAN_OFT);
00885
00886 for (i = 0 ; i < ch_nb; i++)
00887 {
00888 if (bss_ch_idx == ch_idx)
00889 {
00890 bss->chan.tx_power = (int8_t)co_read8p(addr + oft + MAC_COUNTRY_PWR_LEVEL_OFT);
00891 return;
00892 }
00893 ch_idx += ch_incr;
00894 }
00895
00896 oft += MAC_COUNTRY_TRIPLET_LEN;
00897 }
00898 }
00899
00900 void me_extract_mobility_domain(uint32_t buffer, uint16_t buflen,
00901 struct me_bss_info *bss)
00902 {
00903 uint32_t addr = mac_ie_mde_find(buffer, buflen);
00904
00905 if (addr == 0)
00906 {
00907 bss->mde.mdid = 0;
00908 bss->mde.ft_capability_policy = 0;
00909 return;
00910 }
00911
00912 bss->mde.mdid = co_read16p(addr + MAC_INFOELT_MDE_MDID_OFT);
00913 bss->mde.ft_capability_policy = co_read8p(addr + MAC_INFOELT_MDE_FT_CAPA_POL_OFT);
00914 }
00915
00916 int me_extract_csa(uint32_t buffer, uint16_t buflen, uint8_t *mode,
00917 struct mac_chan_op *chan_desc)
00918 {
00919 uint32_t csa, ecsa, sec_chan, wide_bw_cs;
00920 uint8_t count, prim20;
00921 bool valid_length;
00922
00923 csa = mac_ie_csa_find(buffer, buflen);
00924 ecsa = mac_ie_ecsa_find(buffer, buflen);
00925
00926 if (csa == 0 && ecsa == 0)
00927 {
00928 return 0;
00929 }
00930
00931 sec_chan = mac_ie_sec_chnl_offset_find(buffer, buflen, &valid_length);
00932 if (sec_chan && !valid_length)
00933 return 0;
00934
00935 wide_bw_cs = mac_ie_wide_bw_chnl_find(buffer, buflen, &valid_length);
00936 if (wide_bw_cs && !valid_length)
00937 return 0;
00938
00939 if (csa)
00940 {
00941 count = co_read8p(csa + MAC_INFOELT_SWITCH_COUNT_OFT);
00942 *mode = co_read8p(csa + MAC_INFOELT_SWITCH_MODE_OFT);
00943 prim20 = co_read8p(csa + MAC_INFOELT_SWITCH_NEW_CHAN_OFT);
00944 }
00945 else
00946 {
00947 count = co_read8p(ecsa + MAC_INFOELT_EXT_SWITCH_COUNT_OFT);
00948 *mode = co_read8p(ecsa + MAC_INFOELT_EXT_SWITCH_MODE_OFT);
00949 prim20 = co_read8p(ecsa + MAC_INFOELT_EXT_SWITCH_NEW_CHAN_OFT);
00950 }
00951
00952 if (count == 0)
00953 count = 2;
00954
00955 chan_desc->band = (prim20 > 14) ? PHY_BAND_5G : PHY_BAND_2G4;
00956 chan_desc->prim20_freq = phy_channel_to_freq(chan_desc->band, prim20);
00957 chan_desc->type = PHY_CHNL_BW_20;
00958 chan_desc->center1_freq = chan_desc->prim20_freq;
00959 chan_desc->center2_freq = 0;
00960
00961 if (sec_chan)
00962 {
00963 uint8_t ofst = co_read8p(sec_chan + MAC_INFOELT_SEC_CH_OFFSET_OFT);
00964 if (ofst == 1)
00965 {
00966 chan_desc->center1_freq += 10;
00967 chan_desc->type = PHY_CHNL_BW_40;
00968 }
00969 else if (ofst == 3)
00970 {
00971 chan_desc->center1_freq -= 10;
00972 chan_desc->type = PHY_CHNL_BW_40;
00973 }
00974 }
00975
00976 if (wide_bw_cs)
00977 {
00978 uint8_t width = co_read8p(wide_bw_cs + MAC_INFOELT_WIDE_BW_CHAN_SWITCH_NEW_CW_OFT);
00979 uint8_t center1 = co_read8p(wide_bw_cs + MAC_INFOELT_WIDE_BW_CHAN_SWITCH_NEW_CENTER1_OFT);
00980 uint8_t center2 = co_read8p(wide_bw_cs + MAC_INFOELT_WIDE_BW_CHAN_SWITCH_NEW_CENTER2_OFT);
00981 me_vht_bandwidth_parse(width, center1, center2, chan_desc);
00982 }
00983
00984 me_init_chan(chan_desc);
00985
00986 return count;
00987 }
00988
00989 bool me_extract_edca_params(uint32_t buffer, uint16_t buflen,
00990 struct mac_edca_param_set *edca_param,
00991 bool *changed)
00992 {
00993 uint32_t addr = mac_ie_wmm_param_find(buffer, buflen);
00994 uint32_t edca_temp;
00995 uint8_t qos_info;
00996
00997 *changed = false;
00998 if (addr == 0)
00999 {
01000
01001 edca_param->ac_param[AC_BK] = NXMAC_EDCA_AC_1_RESET;
01002 edca_param->ac_param[AC_BE] = NXMAC_EDCA_AC_1_RESET;
01003 edca_param->ac_param[AC_VI] = NXMAC_EDCA_AC_1_RESET;
01004 edca_param->ac_param[AC_VO] = NXMAC_EDCA_AC_1_RESET;
01005 return false;
01006 }
01007
01008
01009 qos_info = co_read8p(addr + MAC_WMM_PARAM_QOS_INFO_OFT);
01010
01011
01012 if ((qos_info & MAC_WMM_PARAM_SET_CNT_MSK) == edca_param->param_set_cnt)
01013 return true;
01014
01015
01016
01017 *changed = true;
01018
01019 edca_param->qos_info = qos_info;
01020 edca_param->param_set_cnt = qos_info & MAC_WMM_PARAM_SET_CNT_MSK;
01021
01022
01023
01024
01025
01026
01027
01028 edca_temp = co_htowl(co_read32p(addr + MAC_WMM_PARAM_BE_PARAM_OFT));
01029
01030 edca_param->acm = ((edca_temp & CO_BIT(4)) != 0) << AC_BE;
01031
01032 edca_param->ac_param[AC_BE] = edca_temp & 0x0F;
01033
01034 edca_param->ac_param[AC_BE] |= ((edca_temp >> 8) & 0xFFFFFFF) << 4;
01035
01036 edca_temp = co_htowl(co_read32p(addr + MAC_WMM_PARAM_BK_PARAM_OFT));
01037
01038 edca_param->acm |= ((edca_temp & CO_BIT(4)) != 0) << AC_BK;
01039
01040 edca_param->ac_param[AC_BK] = edca_temp & 0x0F;
01041
01042 edca_param->ac_param[AC_BK] |= ((edca_temp >> 8) & 0xFFFFFFF) << 4;
01043
01044 edca_temp = co_htowl(co_read32p(addr + MAC_WMM_PARAM_VI_PARAM_OFT));
01045
01046 edca_param->acm |= ((edca_temp & CO_BIT(4)) != 0) << AC_VI;
01047
01048 edca_param->ac_param[AC_VI] = edca_temp & 0x0F;
01049
01050 edca_param->ac_param[AC_VI] |= ((edca_temp >> 8) & 0xFFFFFFF) << 4;
01051
01052 edca_temp = co_htowl(co_read32p(addr + MAC_WMM_PARAM_VO_PARAM_OFT));
01053
01054 edca_param->acm |= ((edca_temp & CO_BIT(4)) != 0) << AC_VO;
01055
01056 edca_param->ac_param[AC_VO] = edca_temp & 0x0F;
01057
01058 edca_param->ac_param[AC_VO] |= ((edca_temp >> 8) & 0xFFFFFFF) << 4;
01059
01060 return true;
01061 }
01062
01063 bool me_extract_ht_capa(uint32_t buffer, uint16_t buflen, struct mac_htcapability *ht_cap)
01064 {
01065 uint32_t addr = mac_ie_ht_capa_find(buffer, buflen);
01066
01067 if (addr == 0)
01068 return false;
01069
01070 ht_cap->ht_capa_info = co_wtohs(co_read16p(addr + MAC_HT_CAPA_INFO_OFT));
01071 ht_cap->a_mpdu_param = co_read8p(addr + MAC_HT_CAPA_AMPDU_PARAM_OFT);
01072 co_unpack8p(ht_cap->mcs_rate, addr + MAC_HT_CAPA_SUPPORTED_MCS_SET_OFT, MAX_MCS_LEN);
01073 ht_cap->ht_extended_capa = co_wtohs(co_read16p(addr + MAC_HT_CAPA_EXTENDED_CAPA_OFT));
01074 ht_cap->tx_beamforming_capa =
01075 co_wtohs(co_read16p(addr + MAC_HT_CAPA_TX_BEAM_FORMING_CAPA_OFT));
01076 ht_cap->asel_capa = co_read8p(addr + MAC_HT_CAPA_ASEL_CAPA_OFT);
01077
01078 return true;
01079 }
01080
01081 bool me_extract_vht_capa(uint32_t buffer, uint16_t buflen, struct mac_vhtcapability *vht_cap)
01082 {
01083 uint32_t addr = mac_ie_vht_capa_find(buffer, buflen);
01084
01085 if (addr == 0)
01086 return false;
01087
01088 vht_cap->vht_capa_info = co_wtohl(co_read32p(addr + MAC_VHT_CAPA_INFO_OFT));
01089 vht_cap->rx_mcs_map = co_wtohs(co_read16p(addr + MAC_VHT_RX_MCS_MAP_OFT));
01090 vht_cap->tx_mcs_map = co_wtohs(co_read16p(addr + MAC_VHT_TX_MCS_MAP_OFT));
01091 vht_cap->rx_highest = co_wtohs(co_read16p(addr + MAC_VHT_RX_HIGHEST_RATE_OFT));
01092 vht_cap->tx_highest = co_wtohs(co_read16p(addr + MAC_VHT_TX_HIGHEST_RATE_OFT));
01093
01094 return true;
01095 }
01096
01097 #if NX_HE
01098 bool me_extract_he_capa(uint32_t buffer, uint16_t buflen, struct mac_hecapability *he_cap)
01099 {
01100 uint32_t copy_addr;
01101 uint32_t end_addr;
01102 uint8_t elmt_length;
01103 uint8_t chan_width_set;
01104 int i;
01105 uint32_t addr = mac_ie_he_capa_find(buffer, buflen, &elmt_length);
01106
01107 if (addr == 0)
01108 return false;
01109
01110 copy_addr = addr + MAC_HE_MAC_CAPA_INFO_OFT;
01111 end_addr = copy_addr + elmt_length;
01112
01113 for (i = 0; i < MAC_HE_CAPA_IE_MAC_CAPA_LEN; i++)
01114 {
01115 he_cap->mac_cap_info[i] = co_read8p(copy_addr++);
01116 }
01117 for (i = 0; i < MAC_HE_CAPA_IE_PHY_CAPA_LEN; i++)
01118 {
01119 he_cap->phy_cap_info[i] = co_read8p(copy_addr++);
01120 }
01121 chan_width_set = HE_PHY_CAPA_VAL_GET(he_cap, CHAN_WIDTH_SET);
01122 he_cap->mcs_supp.rx_mcs_80 = co_wtohs(co_read16p(copy_addr));
01123 copy_addr += 2;
01124 he_cap->mcs_supp.tx_mcs_80 = co_wtohs(co_read16p(copy_addr));
01125 copy_addr += 2;
01126 if (chan_width_set & HE_PHY_CAPA_CHAN_WIDTH_SET_160MHZ_IN_5G)
01127 {
01128 if ((copy_addr + MAC_HE_MCS_INFO_PER_BW_LEN) > end_addr)
01129 return false;
01130 he_cap->mcs_supp.rx_mcs_160 = co_wtohs(co_read16p(copy_addr));
01131 copy_addr += 2;
01132 he_cap->mcs_supp.tx_mcs_160 = co_wtohs(co_read16p(copy_addr));
01133 copy_addr += 2;
01134 }
01135 if (chan_width_set & HE_PHY_CAPA_CHAN_WIDTH_SET_80PLUS80_MHZ_IN_5G)
01136 {
01137 if ((copy_addr + MAC_HE_MCS_INFO_PER_BW_LEN) > end_addr)
01138 return false;
01139 he_cap->mcs_supp.rx_mcs_80p80 = co_wtohs(co_read16p(copy_addr));
01140 copy_addr += 2;
01141 he_cap->mcs_supp.tx_mcs_80p80 = co_wtohs(co_read16p(copy_addr));
01142 copy_addr += 2;
01143 }
01144
01145 return true;
01146 }
01147
01148 bool me_extract_he_oper(uint32_t buffer, uint16_t buflen,
01149 struct me_bss_info *bss)
01150 {
01151 uint32_t he_op_addr;
01152 uint8_t elmt_length;
01153
01154
01155 he_op_addr = mac_ie_he_oper_find(buffer, buflen, &elmt_length);
01156 if (he_op_addr)
01157 bss->he_oper = co_read32p(he_op_addr + MAC_HE_OPER_PARAM_OFT);
01158 else
01159 bss->he_oper = MAC_HE_OPER_BSS_COLOR_DISABLED_BIT;
01160
01161 return (he_op_addr != 0);
01162 }
01163
01164 bool me_extract_mu_edca_params(uint32_t buffer, uint16_t buflen,
01165 struct mac_mu_edca_param_set *mu_edca_param,
01166 bool *changed)
01167 {
01168 uint32_t addr = mac_ie_mu_edca_find(buffer, buflen);
01169 uint8_t qos_info;
01170
01171 *changed = false;
01172
01173 if (addr == 0)
01174 {
01175 return false;
01176 }
01177
01178
01179 qos_info = co_read8p(addr + MAC_MU_EDCA_QOS_INFO_OFT);
01180
01181
01182 if ((qos_info & MAC_MU_EDCA_PARAM_SET_CNT_MSK) == mu_edca_param->param_set_cnt)
01183 return true;
01184
01185
01186
01187 *changed = true;
01188
01189 mu_edca_param->qos_info = qos_info;
01190 mu_edca_param->param_set_cnt = qos_info & MAC_MU_EDCA_PARAM_SET_CNT_MSK;
01191 mu_edca_param->ac_param[AC_BE] = co_htowl(co_read24p(addr + MAC_MU_EDCA_AC_BE_OFT));
01192 mu_edca_param->ac_param[AC_BK] = co_htowl(co_read24p(addr + MAC_MU_EDCA_AC_BK_OFT));
01193 mu_edca_param->ac_param[AC_VI] = co_htowl(co_read24p(addr + MAC_MU_EDCA_AC_VI_OFT));
01194 mu_edca_param->ac_param[AC_VO] = co_htowl(co_read24p(addr + MAC_MU_EDCA_AC_VO_OFT));
01195
01196 return true;
01197 }
01198
01199 bool me_extract_uora_params(uint32_t buffer, uint16_t buflen, struct mm_set_uora_req *uora_param)
01200 {
01201 uint8_t ocw_range;
01202 uint32_t addr = mac_ie_uora_find(buffer, buflen);
01203
01204 if (!addr)
01205 {
01206
01207 uora_param->eocw_min = MAC_UORA_EOCW_DEFAULT_MIN;
01208 uora_param->eocw_max = MAC_UORA_EOCW_DEFAULT_MAX;
01209 return false;
01210 }
01211
01212 ocw_range = co_read8p(addr + MAC_UORA_OCW_RANGE);
01213
01214 uora_param->eocw_min = (ocw_range & MAC_UORA_EOCW_MIN_MASK) >> MAC_UORA_EOCW_MIN_OFT;
01215 uora_param->eocw_max = (ocw_range & MAC_UORA_EOCW_MAX_MASK) >> MAC_UORA_EOCW_MAX_OFT;
01216
01217 return true;
01218 }
01219
01220 #endif // NX_HE
01221