00001
00020
00021
00022
00023
00024 #include "mac_frame.h"
00025 #include "mm.h"
00026 #include "mm_timer.h"
00027 #include "mm_bcn.h"
00028 #include "co_endian.h"
00029 #include "sta_mgmt.h"
00030 #include "vif_mgmt.h"
00031 #include "phy.h"
00032 #include "dbg.h"
00033 #include "rd.h"
00034 #include "ps.h"
00035 #include "txl_cntrl.h"
00036 #include "txl_frame.h"
00037 #include "rxl_cntrl.h"
00038 #include "hal_machw.h"
00039 #include "scan.h"
00040 #include "chan.h"
00041 #include "hal_dma.h"
00042 #if (NX_P2P)
00043 #include "p2p.h"
00044 #endif //(NX_P2P)
00045 #if (NX_TD)
00046 #include "td.h"
00047 #endif //(NX_TD)
00048 #if (RW_BFMER_EN)
00049 #include "bfr.h"
00050 #endif //(RW_BFMER_EN)
00051
00052 #include "reg_mac_core.h"
00053 #include "reg_mac_pl.h"
00054
00055 #include "tdls.h"
00056 #if (NX_UMAC_PRESENT)
00057 #include "me_utils.h"
00058 #endif
00059
00060
00061 #include "mac_ie.h"
00062
00063
00064 #if NX_UMAC_PRESENT && NX_TDLS
00065
00074 static void tdls_keep_alive_frame_tx_cfm(void *env, uint32_t status)
00075 {
00076 struct sta_info_tag *sta_tdls = (struct sta_info_tag *)env;
00077
00078
00079 if (!(status & FRAME_SUCCESSFUL_TX_BIT))
00080 {
00081 sta_tdls->tdls.ka_retries--;
00082 if (sta_tdls->tdls.ka_retries == 0)
00083 {
00084 struct vif_info_tag *vif = &vif_info_tab[sta_tdls->inst_nbr];
00085
00086 mm_send_pktloss_ind(vif, sta_tdls->staid,
00087 TDLS_KA_RETRIES * RC_MAX_NUM_RETRY * RATE_CONTROL_STEPS);
00088 }
00089 else
00090 {
00091
00092 txl_frame_send_qosnull_frame(sta_tdls->staid, 0x5, tdls_keep_alive_frame_tx_cfm, sta_tdls);
00093 }
00094 }
00095
00096 sta_tdls->tdls.traffic_available = false;
00097 }
00098
00108 static void tdls_chsw_null_frame_tx_cfm(void *env, uint32_t status)
00109 {
00110 struct sta_info_tag *sta = env;
00111 struct vif_info_tag *vif = &vif_info_tab[sta->inst_nbr];
00112
00113
00114 if (status & FRAME_SUCCESSFUL_TX_BIT)
00115 {
00116 PROF_TDLS_CHSW_TIMEOUT_TIMER_CLR();
00117 mm_timer_clear(&sta->tdls.chsw_timeout_timer);
00118 }
00119
00120
00121 sta_mgmt_send_postponed_frame(vif, sta, 0);
00122 }
00123
00133 static void tdls_chsw_req_tx_cfm(void *env, uint32_t status)
00134 {
00135
00136 if (!(status & FRAME_SUCCESSFUL_TX_BIT))
00137 {
00138 ke_state_set(TASK_TDLS, TDLS_BASE_CHANNEL);
00139 }
00140 }
00141
00151 static void tdls_chsw_rsp_tx_cfm(void *env, uint32_t status)
00152 {
00153 struct vif_info_tag *vif = (struct vif_info_tag *)env;
00154
00155
00156 if (status & FRAME_SUCCESSFUL_TX_BIT)
00157 {
00158 struct mm_remain_on_channel_req param;
00159 struct sta_info_tag *sta = &sta_info_tab[vif->u.sta.tdls_chsw_sta_idx];
00160
00161 PROF_TDLS_CHSW_TIME_TIMER_SET();
00162 mm_timer_set(&sta->tdls.chsw_time_timer,
00163 ke_time() + sta->tdls.chsw_time);
00164
00165 param.op_code = MM_ROC_OP_START;
00166 param.vif_index = vif->index;
00167 param.chan = sta->tdls.chsw;
00168 param.duration_ms = tdls_get_dt_us(vif->tbtt_timer.time, hal_machw_time()) / 1000;
00169
00170 PROF_TDLS_SWITCH_TO_OFFCH_SET();
00171 chan_roc_req(¶m, TASK_TDLS);
00172 ke_state_set(TASK_TDLS, TDLS_OFF_CHANNEL);
00173 PROF_TDLS_SWITCH_TO_OFFCH_CLR();
00174 }
00175 else
00176 {
00177
00178 vif->u.sta.tdls_chsw_sta_idx = INVALID_STA_IDX;
00179
00180 ke_state_set(TASK_TDLS, TDLS_BASE_CHANNEL);
00181 }
00182 }
00183
00193 static void tdls_chsw_unsol_rsp_tx_cfm(void *env, uint32_t status)
00194 {
00195 struct vif_info_tag *vif = (struct vif_info_tag *)env;
00196 struct mm_remain_on_channel_req param;
00197
00198 param.vif_index = vif->index;
00199 param.op_code = MM_ROC_OP_CANCEL;
00200
00201 PROF_TDLS_SWITCH_TO_BASECH_SET();
00202 chan_roc_req(¶m, TASK_TDLS);
00203 PROF_TDLS_SWITCH_TO_BASECH_CLR();
00204
00205
00206 ke_state_set(TASK_TDLS, TDLS_BASE_CHANNEL);
00207 }
00208
00222 static uint16_t tdls_check_tdls_channel_switch_request(uint8_t *frame,
00223 uint32_t offset,
00224 struct sta_info_tag *sta_tdls,
00225 uint32_t next_tbtt)
00226 {
00227 uint16_t status = TDLS_CHANSW_REQUEST_ACCEPTED;
00228 uint32_t dt = tdls_get_dt_us(next_tbtt, ke_time());
00229 uint16_t ch_switch_time = TDLS_CHSW_SWITCH_TIME_US;
00230 uint16_t chsw_timeout;
00231 uint32_t frame_addr = CPU2HW(frame);
00232
00233 do
00234 {
00235
00236 sta_tdls->tdls.chsw_num = co_read8p(frame_addr + offset + TDLS_CHANSW_REQ_TARGET_CH_OFFSET);
00237
00238 sta_tdls->tdls.chsw_op_class = co_read8p(frame_addr + offset + TDLS_CHANSW_REQ_OP_CLASS);
00239
00240 if (((sta_tdls->tdls.chsw_op_class == 112) || (sta_tdls->tdls.chsw_op_class == 2) ||
00241 (sta_tdls->tdls.chsw_op_class == 3) || (sta_tdls->tdls.chsw_op_class == 4) ||
00242 (sta_tdls->tdls.chsw_op_class == 5) || (sta_tdls->tdls.chsw_op_class == 6)) &&
00243 (sta_tdls->tdls.chsw_num < 14))
00244 sta_tdls->tdls.chsw.band = PHY_BAND_5G;
00245 else
00246 sta_tdls->tdls.chsw.band = (sta_tdls->tdls.chsw_num < 14) ? PHY_BAND_2G4 : PHY_BAND_5G;
00247
00248 sta_tdls->tdls.chsw.prim20_freq = phy_channel_to_freq(sta_tdls->tdls.chsw.band, sta_tdls->tdls.chsw_num);
00249 sta_tdls->tdls.chsw.center1_freq = sta_tdls->tdls.chsw.prim20_freq;
00250 sta_tdls->tdls.chsw.type = PHY_CHNL_BW_20;
00251
00252 offset += TDLS_CHANSW_REQ_IES_OFFSET;
00253
00254 if (co_read8p(frame_addr + offset) == MAC_ELTID_SEC_CH_OFFSET)
00255 {
00256 sta_tdls->tdls.chsw.type = PHY_CHNL_BW_40;
00257 if (co_read8p(frame_addr + offset + MAC_INFOELT_SEC_CH_OFFSET_SEC_CH_OFT) == MAC_INFOELT_SEC_CH_OFFSET_SEC_ABOVE)
00258 {
00259 sta_tdls->tdls.chsw.center1_freq = sta_tdls->tdls.chsw.prim20_freq + 10;
00260 }
00261 else
00262 {
00263 sta_tdls->tdls.chsw.center1_freq = sta_tdls->tdls.chsw.prim20_freq - 10;
00264 }
00265 offset += TDLS_CHANSW_REQ_IE_SEC_CH_OFT_LEN;
00266 }
00267
00268
00269 if (co_read8p(frame_addr + offset) != MAC_ELTID_LINK_IDENTIFIER)
00270 {
00271 TRACE_TDLS(ERR, "Link Identifier element missing!");
00272
00273 status = TDLS_CHANSW_REQUEST_DECLINED;
00274 break;
00275 }
00276
00277 offset += TDLS_CHANSW_REQ_IE_LINK_ID_LEN;
00278
00279
00280 if (co_read8p(frame_addr + offset) != MAC_ELTID_CHANNEL_SWITCH_TIMING)
00281 {
00282 TRACE_TDLS(ERR, "Channel Switch Timing element missing!");
00283 status = TDLS_CHANSW_REQUEST_DECLINED;
00284 break;
00285 }
00286
00287 sta_tdls->tdls.chsw_time = co_read16p(frame_addr + offset + MAC_INFOELT_CH_SWITCH_TIMING_SWTIME_OFT);
00288 sta_tdls->tdls.chsw_timeout = co_read16p(frame_addr + offset + MAC_INFOELT_CH_SWITCH_TIMING_SWTOUT_OFT);
00289 offset += TDLS_CHANSW_REQ_IE_CH_SWITCH_TIMING_LEN;
00290
00291 if (sta_tdls->tdls.chsw_time < ch_switch_time)
00292 {
00293 sta_tdls->tdls.chsw_time = ch_switch_time;
00294 }
00295 chsw_timeout = (uint16_t)(dt - 2*(uint32_t)sta_tdls->tdls.chsw_time -
00296 2*TDLS_CHSW_TX_FRAME_TIME_US);
00297 if (chsw_timeout > TDLS_MAX_CHSW_SWITCH_TIME_US)
00298 {
00299 chsw_timeout = TDLS_MAX_CHSW_SWITCH_TIME_US;
00300 }
00301 if (sta_tdls->tdls.chsw_timeout < chsw_timeout)
00302 {
00303 sta_tdls->tdls.chsw_timeout = chsw_timeout;
00304 }
00305
00306
00307 if (dt < (2*(uint32_t)sta_tdls->tdls.chsw_time + 2*TDLS_CHSW_TX_FRAME_TIME_US +
00308 sta_tdls->tdls.chsw_timeout))
00309 {
00310 status = TDLS_CHANSW_REQUEST_DECLINED;
00311 break;
00312 }
00313
00314
00315 if (co_read8p(frame_addr + offset) == MAC_ELTID_WIDE_BANDWIDTH_CHAN_SWITCH)
00316 {
00317 sta_tdls->tdls.chsw.band = PHY_BAND_5G;
00318 sta_tdls->tdls.chsw.type = 1 + co_read8p(frame_addr + offset + MAC_INFOELT_WIDE_BW_CHAN_SWITCH_NEW_CW_OFT);
00319 sta_tdls->tdls.chsw.prim20_freq = phy_channel_to_freq(PHY_BAND_5G, sta_tdls->tdls.chsw_num);
00320 sta_tdls->tdls.chsw.center1_freq = co_read8p(frame_addr + offset + MAC_INFOELT_WIDE_BW_CHAN_SWITCH_NEW_CENTER1_OFT);
00321 sta_tdls->tdls.chsw.center2_freq = co_read8p(frame_addr + offset + MAC_INFOELT_WIDE_BW_CHAN_SWITCH_NEW_CENTER2_OFT);
00322 }
00323
00324 } while (0);
00325
00326 return status;
00327 }
00328
00343 static uint32_t tdls_check_tdls_channel_switch_response(uint8_t *frame,
00344 uint32_t offset,
00345 struct sta_info_tag *sta_tdls,
00346 struct mac_addr *initiator_mac_addr,
00347 struct mac_addr *responder_mac_addr,
00348 uint32_t next_tbtt)
00349 {
00350 uint32_t res = CO_FAIL;
00351 uint8_t i;
00352 struct mac_addr initiator;
00353 struct mac_addr responder;
00354 uint32_t dt = tdls_get_dt_us(next_tbtt, ke_time());
00355 uint32_t frame_addr = CPU2HW(frame);
00356
00357 do
00358 {
00359
00360 if (co_read8p(frame_addr + offset + TDLS_CHANSW_RSP_STATUS_OFFSET) != TDLS_CHANSW_REQUEST_ACCEPTED)
00361 {
00362 res = CO_FAIL;
00363 break;
00364 }
00365 offset += TDLS_CHANSW_RSP_IES_OFFSET;
00366
00367
00368 if (co_read8p(frame_addr + offset) != MAC_ELTID_LINK_IDENTIFIER)
00369 {
00370 TRACE_TDLS(ERR, "Link Identifier IE missing.");
00371 res = CO_NOT_FOUND;
00372 break;
00373 }
00374
00375 for (i = 0; i < MAC_ADDR_LEN/2; i++)
00376 {
00377 initiator.array[i] = co_read16p(frame_addr + offset + MAC_INFOELT_LINK_ID_INIT_STA_OFT + 2*i);
00378 responder.array[i] = co_read16p(frame_addr + offset + MAC_INFOELT_LINK_ID_RESP_STA_OFT + 2*i);
00379 }
00380 if ((!MAC_ADDR_CMP(&initiator.array[0], &initiator_mac_addr->array[0])) ||
00381 (!MAC_ADDR_CMP(&responder.array[0], &responder_mac_addr->array[0])))
00382 {
00383 TRACE_TDLS(ERR, "wrong Link Identifier IE.");
00384 res = CO_BAD_PARAM;
00385 break;
00386 }
00387 offset += TDLS_CHANSW_REQ_IE_LINK_ID_LEN;
00388
00389
00390 if (co_read8p(frame_addr + offset) != MAC_ELTID_CHANNEL_SWITCH_TIMING)
00391 {
00392 TRACE_TDLS(ERR, "Channel Switch Timing IE missing.");
00393 res = CO_NOT_FOUND;
00394 break;
00395 }
00396
00397 if (ke_state_get(TASK_TDLS) == TDLS_CHSW_REQ_TX)
00398 {
00399
00400 sta_tdls->tdls.chsw_time = co_read16p(frame_addr + offset + MAC_INFOELT_CH_SWITCH_TIMING_SWTIME_OFT);
00401 sta_tdls->tdls.chsw_timeout = co_read16p(frame_addr + offset + MAC_INFOELT_CH_SWITCH_TIMING_SWTOUT_OFT);
00402
00403 if (dt < (2*(uint32_t)sta_tdls->tdls.chsw_time + TDLS_CHSW_TX_FRAME_TIME_US +
00404 sta_tdls->tdls.chsw_timeout))
00405 {
00406 TRACE_TDLS(ERR, "Not enough time to complete TDLS Channel Switch procedure.");
00407 res = CO_BAD_PARAM;
00408 break;
00409 }
00410 }
00411 offset += TDLS_CHANSW_REQ_IE_CH_SWITCH_TIMING_LEN;
00412
00413 res = CO_OK;
00414
00415 } while (0);
00416
00417 return res;
00418 }
00419
00433 static uint32_t tdls_check_tdls_peer_traffic_response(uint8_t *frame,
00434 uint32_t offset,
00435 struct sta_info_tag *sta_tdls,
00436 struct mac_addr *initiator_mac_addr,
00437 struct mac_addr *responder_mac_addr)
00438 {
00439 uint32_t res = CO_FAIL;
00440 uint8_t i;
00441 struct mac_addr initiator;
00442 struct mac_addr responder;
00443 uint32_t frame_addr = CPU2HW(frame);
00444
00445 do
00446 {
00447
00448 if (co_read8p(frame_addr + offset + MAC_ACTION_TOKEN_OFT) != sta_tdls->tdls.dialog_token)
00449 {
00450 dbg(D_CRT "%s: wrong Dialog Token.\n", __func__);
00451 res = CO_FAIL;
00452 break;
00453 }
00454 offset += TDLS_PEER_TRAFFIC_RSP_IES_OFFSET;
00455
00456
00457 if (co_read8p(frame_addr + offset) != MAC_ELTID_LINK_IDENTIFIER)
00458 {
00459 dbg(D_CRT "%s: Link Identifier IE missing.\n", __func__);
00460 res = CO_NOT_FOUND;
00461 break;
00462 }
00463
00464 for (i = 0; i < MAC_ADDR_LEN/2; i++)
00465 {
00466 initiator.array[i] = co_read16p(frame_addr + offset + MAC_INFOELT_LINK_ID_INIT_STA_OFT + 2*i);
00467 responder.array[i] = co_read16p(frame_addr + offset + MAC_INFOELT_LINK_ID_RESP_STA_OFT + 2*i);
00468 }
00469 if ((!MAC_ADDR_CMP(&initiator.array[0], &initiator_mac_addr->array[0])) ||
00470 (!MAC_ADDR_CMP(&responder.array[0], &responder_mac_addr->array[0])))
00471 {
00472 dbg(D_CRT "%s: wrong Link Identifier IE.\n", __func__);
00473 res = CO_BAD_PARAM;
00474 break;
00475 }
00476
00477 res = CO_OK;
00478
00479 } while (0);
00480
00481 return res;
00482 }
00483
00494 static void tdls_chsw_end_evt(void *env)
00495 {
00496 struct vif_info_tag *vif = (struct vif_info_tag *)env;
00497
00498 PROF_TDLS_CHSW_END_TIMER_CLR();
00499
00500
00501
00502 txl_frame_send_tdls_channel_switch_rsp_frame(vif, 0, &tdls_chsw_unsol_rsp_tx_cfm);
00503 }
00504
00514 static void tdls_chsw_time_evt(void *env)
00515 {
00516 struct vif_info_tag *vif = (struct vif_info_tag *)env;
00517 struct sta_info_tag *sta;
00518
00519 PROF_TDLS_CHSW_TIME_TIMER_CLR();
00520
00521 if ((chan_is_on_channel(vif)) &&
00522 (ke_state_get(TASK_TDLS) == TDLS_OFF_CHANNEL) &&
00523 (vif->u.sta.tdls_chsw_sta_idx != INVALID_STA_IDX))
00524 {
00525
00526 PROF_TDLS_CHSW_TIMEOUT_TIMER_SET();
00527 sta = &sta_info_tab[vif->u.sta.tdls_chsw_sta_idx];
00528 mm_timer_set(&sta->tdls.chsw_timeout_timer,
00529 ke_time() + sta->tdls.chsw_timeout);
00530
00531
00532 struct tdls_chan_switch_ind *ind = KE_MSG_ALLOC(TDLS_CHAN_SWITCH_IND,
00533 TASK_API, TASK_TDLS,
00534 tdls_chan_switch_ind);
00535 ind->vif_index = vif->index;
00536 ind->chan_ctxt_index = vif->chan_ctxt->idx;
00537 ind->status = CO_OK;
00538
00539 ke_msg_send(ind);
00540
00541
00542 me_sta_bw_nss_max_upd(sta->staid, sta->tdls.chsw.type, 0xFF);
00543
00544
00545 sta->tdls.chsw_end_timer.cb = tdls_chsw_end_evt;
00546 sta->tdls.chsw_end_timer.env = vif;
00547 PROF_TDLS_CHSW_END_TIMER_SET();
00548 mm_timer_set(&sta->tdls.chsw_end_timer,
00549 vif->tbtt_timer.time - 15000);
00550
00551
00552
00553 {
00554 PROF_TDLS_CHSW_NULL_FRAME_TX_SET();
00555 txl_frame_send_qosnull_frame(sta->staid, 0x5, tdls_chsw_null_frame_tx_cfm, sta);
00556 PROF_TDLS_CHSW_NULL_FRAME_TX_CLR();
00557 }
00558
00559 ke_state_set(TASK_TDLS, TDLS_OFF_CHANNEL);
00560 }
00561 else
00562 {
00563 struct mm_remain_on_channel_req param;
00564
00565 param.vif_index = vif->index;
00566 param.op_code = MM_ROC_OP_CANCEL;
00567
00568 PROF_TDLS_SWITCH_TO_BASECH_SET();
00569 chan_roc_req(¶m, TASK_TDLS);
00570 PROF_TDLS_SWITCH_TO_BASECH_CLR();
00571
00572 ke_state_set(TASK_TDLS, TDLS_BASE_CHANNEL);
00573
00574 PROF_TDLS_CHSW_END_TIMER_CLR();
00575 if (vif->u.sta.tdls_chsw_sta_idx != INVALID_STA_IDX) {
00576 sta = &sta_info_tab[vif->u.sta.tdls_chsw_sta_idx];
00577 mm_timer_clear(&sta->tdls.chsw_end_timer);
00578 }
00579 }
00580 }
00581
00593 static void tdls_chsw_timeout_evt(void *env)
00594 {
00595 struct vif_info_tag *vif = (struct vif_info_tag *)env;
00596 struct sta_info_tag *sta = &sta_info_tab[vif->u.sta.tdls_chsw_sta_idx];;
00597 struct mm_remain_on_channel_req param;
00598
00599 PROF_TDLS_CHSW_TIMEOUT_TIMER_CLR();
00600
00601 PROF_TDLS_CHSW_TIME_TIMER_CLR();
00602 mm_timer_clear(&sta->tdls.chsw_time_timer);
00603 PROF_TDLS_CHSW_END_TIMER_CLR();
00604 mm_timer_clear(&sta->tdls.chsw_end_timer);
00605
00606 param.vif_index = vif->index;
00607 param.op_code = MM_ROC_OP_CANCEL;
00608
00609 PROF_TDLS_SWITCH_TO_BASECH_SET();
00610 chan_roc_req(¶m, TASK_TDLS);
00611 PROF_TDLS_SWITCH_TO_BASECH_CLR();
00612
00613 ke_state_set(TASK_TDLS, TDLS_BASE_CHANNEL);
00614 }
00615
00626 static void tdls_keep_alive_evt(void *env)
00627 {
00628 struct sta_info_tag *sta_tdls = (struct sta_info_tag *)env;
00629 struct vif_info_tag *vif = &vif_info_tab[sta_tdls->inst_nbr];
00630
00631 sta_tdls->tdls.ka_retries = TDLS_KA_RETRIES;
00632
00633 if (sta_tdls->ps_state == PS_MODE_ON)
00634 {
00635 if (!sta_tdls->tdls.pti_timer_running)
00636 {
00637
00638 struct tdls_peer_traffic_ind_req param;
00639 param.vif_index = vif->index;
00640 MAC_ADDR_CPY(¶m.peer_mac_addr, &sta_tdls->mac_addr);
00641 param.sta_idx = sta_tdls->staid;
00642 param.dialog_token = 0;
00643 param.last_sn = 0;
00644 param.last_tid = 0;
00645 if (txl_frame_send_tdls_peer_traffic_ind_frame(¶m, &tdls_peer_traffic_ind_tx_cfm) == CO_OK)
00646 {
00647
00648 sta_tdls->tdls.dialog_token = param.dialog_token;
00649
00650 sta_tdls->tdls.ka_tx_req = true;
00651
00652 ke_state_set(TASK_TDLS, TDLS_TRAFFIC_IND_TX);
00653 }
00654 }
00655 }
00656 else
00657 {
00658
00659 txl_frame_send_qosnull_frame(sta_tdls->staid, 0x5, tdls_keep_alive_frame_tx_cfm, sta_tdls);
00660 }
00661
00662
00663 mm_timer_set(&sta_tdls->tdls.keep_alive_timer, ke_time() + TDLS_KEEP_ALIVE_US);
00664 }
00665
00676 static void tdls_pti_timeout_evt(void *env)
00677 {
00678 struct sta_info_tag *sta_tdls = (struct sta_info_tag *)env;
00679 struct vif_info_tag *vif = &vif_info_tab[sta_tdls->inst_nbr];
00680
00681 mm_send_pktloss_ind(vif, sta_tdls->staid, RC_MAX_NUM_RETRY * RATE_CONTROL_STEPS);
00682 }
00683
00696 static bool tdls_check_frame_action(uint8_t *frame, struct vif_info_tag *vif, uint8_t sta_idx)
00697 {
00698 bool upload = true;
00699 uint16_t framectrl = co_read16(frame);
00700 uint32_t offset;
00701 uint8_t tdls_action;
00702 uint32_t frame_addr = CPU2HW(frame);
00703 struct sta_info_tag *sta = &sta_info_tab[sta_idx];
00704
00705 do
00706 {
00707 if ((framectrl & MAC_FCTRL_TYPE_MASK) == MAC_FCTRL_DATA_T)
00708 {
00709 if ((ke_state_get(TASK_TDLS) == TDLS_OFF_CHANNEL) &&
00710 (!hal_machw_time_past(sta->tdls.chsw_timeout_timer.time)))
00711 {
00712 PROF_TDLS_CHSW_TIMEOUT_TIMER_CLR();
00713 mm_timer_clear(&sta->tdls.chsw_timeout_timer);
00714 }
00715
00716 if (!(framectrl & MAC_QOS_ST_BIT))
00717 {
00718 break;
00719 }
00720 }
00721
00722 offset = MAC_SHORT_QOS_MAC_HDR_LEN + ((framectrl & MAC_FCTRL_ORDER) ? MAC_HTC_LEN : 0);
00723 offset += (framectrl & MAC_FCTRL_PROTECTEDFRAME)?IV_LEN + EIV_LEN:0;
00724
00725 if (!((co_read32p(frame_addr + offset) == FRAME_BODY_LLC_H) &&
00726 (co_read32p(frame_addr + offset + MAC_ENCAPSULATED_LLC_L_OFT) == FRAME_BODY_LLC_L) &&
00727 (co_read8p(frame_addr + offset + MAC_ENCAPSULATED_PAYLOAD_TYPE_OFT) == PAYLOAD_TYPE_TDLS)))
00728 {
00729 break;
00730 }
00731
00732 offset += MAC_ENCAPSULATED_PAYLOAD_OFT;
00733 if (co_read8p(frame_addr + offset) != MAC_TDLS_ACTION_CATEGORY)
00734 {
00735 break;
00736 }
00737
00738 tdls_action = co_read8p(frame_addr + offset + MAC_ACTION_ACTION_OFT);
00739
00740 if (tdls_action == MAC_TDLS_ACTION_PEER_TRAFFIC_RSP)
00741 {
00743
00745
00746 uint16_t res;
00747 upload = false;
00748 struct mac_addr *initiator_mac_addr;
00749 struct mac_addr *responder_mac_addr;
00750
00751
00752 if (ke_state_get(TASK_TDLS) != TDLS_TRAFFIC_IND_TX)
00753 {
00754 break;
00755 }
00756
00757
00758 if (sta->tdls.initiator)
00759 {
00760 initiator_mac_addr = &sta->mac_addr;
00761 responder_mac_addr = &vif->mac_addr;
00762 }
00763 else
00764 {
00765 initiator_mac_addr = &vif->mac_addr;
00766 responder_mac_addr = &sta->mac_addr;
00767 }
00768 res = tdls_check_tdls_peer_traffic_response(frame, offset, sta,
00769 initiator_mac_addr,
00770 responder_mac_addr);
00771
00772 if (res == CO_OK)
00773 {
00774 uint16_t qos = 0x5 << MAC_QOSCTRL_UP_OFT;
00775
00776 mm_timer_clear(&sta->tdls.pti_timeout_timer);
00777 sta->tdls.pti_timer_running = false;
00778
00779 tdls_send_peer_ps_ind(vif, false, sta_idx);
00780
00781 if (sta->tdls.ka_tx_req)
00782 {
00783 if (!sta->tdls.traffic_available)
00784 {
00785 qos |= MAC_QOSCTRL_EOSP;
00786 }
00787
00788 txl_frame_send_qosnull_frame(sta->staid, qos,
00789 tdls_keep_alive_frame_tx_cfm, sta);
00790 sta->tdls.ka_tx_req = false;
00791 }
00792
00793 ke_state_set(TASK_TDLS, TDLS_BASE_CHANNEL);
00794 }
00795 }
00796 else
00797 if (tdls_action == MAC_TDLS_ACTION_CHANSW_REQ)
00798 {
00800
00802 PROF_TDLS_CHSW_REQ_RX_SET();
00803
00804 uint16_t status;
00805 upload = false;
00806
00807
00808
00809 if ((ke_state_get(TASK_TDLS) == TDLS_CHSW_REQ_TX) && (!sta->tdls.initiator))
00810 {
00811 TRACE_TDLS(CHSWITCH, "Do not reply (STA is initiator of the TDLS link and"
00812 " ChSwReq received while waiting for ChSwResp).");
00813 break;
00814 }
00815
00816
00817 sta->tdls.chsw_time_timer.cb = tdls_chsw_time_evt;
00818 sta->tdls.chsw_time_timer.env = vif;
00819 sta->tdls.chsw_timeout_timer.cb = tdls_chsw_timeout_evt;
00820 sta->tdls.chsw_timeout_timer.env = vif;
00821
00822 sta->tdls.chsw.tx_power = vif->tx_power;
00823
00824 sta->tdls.chsw_initiator = true;
00825
00826 vif->u.sta.tdls_chsw_sta_idx = sta_idx;
00827
00828 status = tdls_check_tdls_channel_switch_request(frame, offset,
00829 sta,
00830 vif->tbtt_timer.time);
00831 PROF_TDLS_CHSW_REQ_RX_CLR();
00832
00833 if (status == TDLS_CHANSW_REQUEST_ACCEPTED)
00834 {
00835
00836 if ((td_sta_has_traffic(vif->u.sta.ap_id)) || (sta->ps_state))
00837 {
00838 status = TDLS_CHANSW_REQUEST_DECLINED;
00839 }
00840
00841 else if (!sta->tdls.chsw_allowed)
00842 {
00843 status = TDLS_CHANSW_REQUEST_DECLINED;
00844 }
00845 else
00846 {
00847
00848 ke_state_set(TASK_TDLS, TDLS_CHSW_REQ_RX);
00849 }
00850 }
00851
00852
00853 if (txl_frame_send_tdls_channel_switch_rsp_frame(vif, status, &tdls_chsw_rsp_tx_cfm) != CO_OK)
00854 {
00855
00856 vif->u.sta.tdls_chsw_sta_idx = INVALID_STA_IDX;
00857 }
00858 }
00859 else if (tdls_action == MAC_TDLS_ACTION_CHANSW_RSP)
00860 {
00862
00864 PROF_TDLS_CHSW_RESP_RX_SET();
00865
00866 uint32_t res;
00867 upload = false;
00868 struct mac_addr *initiator_mac_addr;
00869 struct mac_addr *responder_mac_addr;
00870
00871
00872 if (sta_idx != vif->u.sta.tdls_chsw_sta_idx)
00873 {
00874 break;
00875 }
00876
00877
00878 sta->tdls.chsw_time_timer.cb = tdls_chsw_time_evt;
00879 sta->tdls.chsw_time_timer.env = vif;
00880 sta->tdls.chsw_timeout_timer.cb = tdls_chsw_timeout_evt;
00881 sta->tdls.chsw_timeout_timer.env = vif;
00882
00883
00884 if (sta->tdls.initiator)
00885 {
00886 initiator_mac_addr = &sta->mac_addr;
00887 responder_mac_addr = &vif->mac_addr;
00888 }
00889 else
00890 {
00891 initiator_mac_addr = &vif->mac_addr;
00892 responder_mac_addr = &sta->mac_addr;
00893 }
00894 res = tdls_check_tdls_channel_switch_response(frame, offset,
00895 sta,
00896 initiator_mac_addr, responder_mac_addr,
00897 vif->tbtt_timer.time);
00898 PROF_TDLS_CHSW_RESP_RX_CLR();
00899
00900
00901
00902 if (res != CO_OK)
00903 {
00904 if (ke_state_get(TASK_TDLS) == TDLS_CHSW_REQ_TX)
00905 {
00906 ke_state_set(TASK_TDLS, TDLS_BASE_CHANNEL);
00907 }
00908 }
00909 else
00910 {
00911 struct mm_remain_on_channel_req param;
00912
00913 param.vif_index = vif->index;
00914 param.chan = sta->tdls.chsw;
00915 param.duration_ms = tdls_get_dt_us(vif->tbtt_timer.time, ke_time()) / 1000;
00916
00917
00918 if ((vif->chan_ctxt->channel.band != sta->tdls.chsw.band) ||
00919 (vif->chan_ctxt->channel.prim20_freq != sta->tdls.chsw.prim20_freq) ||
00920 (vif->chan_ctxt->channel.type != sta->tdls.chsw.type))
00921 {
00922
00923 if (ke_state_get(TASK_TDLS) == TDLS_CHSW_REQ_TX)
00924 {
00925 PROF_TDLS_CHSW_TIME_TIMER_SET();
00926 mm_timer_set(&sta->tdls.chsw_time_timer,
00927 ke_time() + sta->tdls.chsw_time);
00928
00929 param.op_code = MM_ROC_OP_START;
00930
00931 PROF_TDLS_SWITCH_TO_OFFCH_SET();
00932 chan_roc_req(¶m, TASK_TDLS);
00933 PROF_TDLS_SWITCH_TO_OFFCH_CLR();
00934
00935 ke_state_set(TASK_TDLS, TDLS_OFF_CHANNEL);
00936 }
00937 }
00938
00939 else if (ke_state_get(TASK_TDLS) == TDLS_OFF_CHANNEL)
00940 {
00941 PROF_TDLS_CHSW_TIME_TIMER_CLR();
00942 mm_timer_clear(&sta->tdls.chsw_time_timer);
00943 PROF_TDLS_CHSW_END_TIMER_CLR();
00944 mm_timer_clear(&sta->tdls.chsw_end_timer);
00945 param.op_code = MM_ROC_OP_CANCEL;
00946 PROF_TDLS_SWITCH_TO_BASECH_SET();
00947 chan_roc_req(¶m, TASK_TDLS);
00948 PROF_TDLS_SWITCH_TO_BASECH_CLR();
00949
00950 ke_state_set(TASK_TDLS, TDLS_BASE_CHANNEL);
00951 }
00952 }
00953 }
00954 } while(0);
00955
00956 return upload;
00957 }
00958
00969 static void tdls_check_peer_ps(uint8_t *frame, struct vif_info_tag *vif, uint8_t sta_idx)
00970 {
00971 struct mac_hdr *machdr = (struct mac_hdr *)frame;
00972 uint16_t framectrl = machdr->fctl;
00973 struct sta_info_tag *sta = &sta_info_tab[sta_idx];
00974 bool ps_on = true;
00975
00976 do
00977 {
00978
00979 if (!(framectrl & MAC_QOS_ST_BIT))
00980 {
00981 break;
00982 }
00983
00984 if ((framectrl & MAC_FCTRL_TODS_FROMDS) != 0)
00985 {
00986 break;
00987 }
00988
00989
00990 if (!(framectrl & MAC_FCTRL_PWRMGT))
00991 {
00992 ps_on = false;
00993 }
00994
00995 if (ps_on != sta->ps_state)
00996 {
00997
00998 tdls_send_peer_ps_ind(vif, ps_on, sta_idx);
00999 }
01000
01001
01002 if (ps_on && (ke_state_get(TASK_TDLS) == TDLS_OFF_CHANNEL))
01003 {
01004 txl_frame_send_tdls_channel_switch_rsp_frame(vif, 0, &tdls_chsw_unsol_rsp_tx_cfm);
01005 }
01006 } while (0);
01007 }
01008
01009 void tdls_chsw_req_evt(void *env)
01010 {
01011 struct vif_info_tag *vif = (struct vif_info_tag *)env;
01012 struct sta_info_tag *sta;
01013 struct tdls_chan_switch_req req;
01014 uint32_t next_evt;
01015
01016 PROF_TDLS_CHSW_REQ_TX_TIMER_CLR();
01017
01018 do
01019 {
01020 if (vif->u.sta.tdls_chsw_sta_idx == INVALID_STA_IDX)
01021 {
01022 break;
01023 }
01024
01025 sta = &sta_info_tab[vif->u.sta.tdls_chsw_sta_idx];
01026
01027
01028 next_evt = vif->tbtt_timer.time + TDLS_CHSW_REQ_DELAY_US;
01029
01030
01031 if ((!td_sta_has_traffic(vif->u.sta.ap_id)) && (sta->ps_state == PS_MODE_OFF))
01032 {
01033
01034 if (ke_state_get(TASK_TDLS) == TDLS_BASE_CHANNEL)
01035 {
01036 req.vif_index = vif->index;
01037 req.sta_idx = sta->staid;
01038 MAC_ADDR_CPY(&req.peer_mac_addr, &sta->mac_addr);
01039 req.initiator = sta->tdls.initiator;
01040 req.chan = sta->tdls.chsw;
01041 req.op_class = sta->tdls.chsw_op_class;
01042
01043 ke_state_set(TASK_TDLS, TDLS_CHSW_REQ_TX);
01044
01045
01046 txl_frame_send_tdls_channel_switch_req_frame(&req, &tdls_chsw_req_tx_cfm);
01047 }
01048
01049
01050
01051 else if (ke_state_get(TASK_TDLS) == TDLS_CHSW_REQ_TX)
01052 {
01053 ke_state_set(TASK_TDLS, TDLS_BASE_CHANNEL);
01054 }
01055 PROF_TDLS_DELAY_CHSW_CLR();
01056 }
01057
01058
01059 PROF_TDLS_CHSW_REQ_TX_TIMER_SET();
01060 mm_timer_set(&sta->tdls.chsw_req_timer, next_evt);
01061
01062 } while(0);
01063 }
01064
01065 bool tdls_check_frame(uint8_t *frame, struct vif_info_tag *vif, uint8_t sta_idx)
01066 {
01067 bool upload;
01068
01069
01070 tdls_check_peer_ps(frame, vif, sta_idx);
01071
01072
01073
01074 upload = tdls_check_frame_action(frame, vif, sta_idx);
01075
01076 return upload;
01077 }
01078
01079 void tdls_send_chan_switch_base_ind(struct chan_ctxt_tag *roc_chan_ctxt)
01080 {
01081 struct vif_info_tag *vif = &vif_info_tab[roc_chan_ctxt->vif_index];
01082 struct sta_info_tag *sta = &sta_info_tab[vif->u.sta.tdls_chsw_sta_idx];
01083
01084 struct tdls_chan_switch_base_ind *ind = KE_MSG_ALLOC(TDLS_CHAN_SWITCH_BASE_IND,
01085 TASK_API, roc_chan_ctxt->taskid,
01086 tdls_chan_switch_base_ind);
01087 ind->chan_ctxt_index = roc_chan_ctxt->idx;
01088 ind->vif_index = roc_chan_ctxt->vif_index;
01089
01090 PROF_TDLS_SWITCH_TO_BASECH_SET();
01091 ke_msg_send(ind);
01092 PROF_TDLS_SWITCH_TO_BASECH_CLR();
01093
01094
01095 me_sta_bw_nss_max_upd(sta->staid, vif->chan_ctxt->channel.type, 0xFF);
01096
01097
01098 if (vif->u.sta.tdls_chsw_sta_idx != INVALID_STA_IDX)
01099 {
01100 if (sta->tdls.chsw_active == false)
01101 {
01102 vif->u.sta.tdls_chsw_sta_idx = INVALID_STA_IDX;
01103 PROF_TDLS_CHSW_TIME_TIMER_CLR();
01104 mm_timer_clear(&sta->tdls.chsw_time_timer);
01105 PROF_TDLS_CHSW_END_TIMER_CLR();
01106 mm_timer_clear(&sta->tdls.chsw_end_timer);
01107 }
01108 }
01109
01110
01111 sta_mgmt_send_postponed_frame(vif, sta, 0);
01112
01113 ke_state_set(TASK_TDLS, TDLS_BASE_CHANNEL);
01114 }
01115
01116 void tdls_send_peer_ps_ind(struct vif_info_tag *vif, bool ps_on, uint8_t sta_idx)
01117 {
01118 struct sta_info_tag *sta = &sta_info_tab[sta_idx];
01119
01120
01121 struct tdls_peer_ps_ind *ind = KE_MSG_ALLOC(TDLS_PEER_PS_IND,
01122 TASK_API, TASK_TDLS,
01123 tdls_peer_ps_ind);
01124
01125
01126 sta->ps_state = ps_on;
01127
01128 ind->vif_index = vif->index;
01129 ind->sta_idx = sta->staid;
01130 MAC_ADDR_CPY(ind->peer_mac_addr.array, &sta->mac_addr);
01131 ind->ps_on = ps_on;
01132
01133 ke_msg_send(ind);
01134 }
01135
01136 void tdls_add_sta(struct sta_info_tag *sta, bool initiator, bool chsw_allowed)
01137 {
01138 sta->tdls.initiator = initiator;
01139 sta->tdls.chsw_allowed = chsw_allowed;
01140
01141 sta->tdls.keep_alive_timer.cb = tdls_keep_alive_evt;
01142 sta->tdls.keep_alive_timer.env = sta;
01143 mm_timer_set(&sta->tdls.keep_alive_timer, ke_time() + TDLS_KEEP_ALIVE_US);
01144
01145 sta->tdls.pti_timeout_timer.cb = tdls_pti_timeout_evt;
01146 sta->tdls.pti_timeout_timer.env = sta;
01147 }
01148
01149 void tdls_del_sta(struct sta_info_tag *sta)
01150 {
01151 struct vif_info_tag *vif = &vif_info_tab[sta->inst_nbr];
01152
01153
01154 mm_timer_clear(&sta->tdls.keep_alive_timer);
01155
01156 mm_timer_clear(&sta->tdls.pti_timeout_timer);
01157
01158 mm_timer_clear(&sta->tdls.chsw_req_timer);
01159
01160 mm_timer_clear(&sta->tdls.chsw_time_timer);
01161
01162 mm_timer_clear(&sta->tdls.chsw_timeout_timer);
01163
01164 mm_timer_clear(&sta->tdls.chsw_end_timer);
01165 sta->tdls.chsw_active = false;
01166 if (vif->u.sta.tdls_chsw_sta_idx == sta->staid)
01167 {
01168 vif->u.sta.tdls_chsw_sta_idx = INVALID_STA_IDX;
01169 }
01170 sta->tdls.chsw_initiator = false;
01171 }
01172
01173 void tdls_peer_traffic_ind_tx_cfm(void *env, uint32_t status)
01174 {
01175 struct sta_info_tag *sta_tdls = (struct sta_info_tag *)env;
01176
01177 if (status & FRAME_SUCCESSFUL_TX_BIT)
01178 {
01179
01180 mm_timer_set(&sta_tdls->tdls.pti_timeout_timer, ke_time() + TDLS_PTI_RSP_TOUT_US);
01181 sta_tdls->tdls.pti_timer_running = true;
01182 }
01183 else
01184 {
01185
01186 ke_state_set(TASK_TDLS, TDLS_BASE_CHANNEL);
01187 }
01188 }
01189
01190 #endif // NX_UMAC_PRESENT && NX_TDLS
01191
01193