00001
00020
00021
00022
00023
00024 #include "co_endian.h"
00025
00026 #include "mac_frame.h"
00027 #include "tdls.h"
00028 #include "ps.h"
00029 #if NX_UMAC_PRESENT
00030 #include "me.h"
00031 #include "rxu_cntrl.h"
00032 #endif
00033 #include "tdls_task.h"
00034 #include "mm_bcn.h"
00035 #include "phy.h"
00036
00037 #include "reg_mac_pl.h"
00038 #include "reg_mac_core.h"
00039 #include "hal_machw.h"
00040 #include "dbg.h"
00041
00042 #include "rxl_cntrl.h"
00043 #include "txl_cntrl.h"
00044
00045 #include "sta_mgmt.h"
00046 #include "vif_mgmt.h"
00047
00048 #include "version.h"
00049
00050 #include "mm_timer.h"
00051
00052 #include "chan.h"
00053 #if (RW_BFMER_EN)
00054 #include "bfr.h"
00055 #endif //(RW_BFMER_EN)
00056
00057 #include "tpc.h"
00058 #include "mm.h"
00059
00060 #if (NX_TDLS)
00061
00062
00063
00064
00065
00066
00080 static
00081 int tdls_chan_switch_req_handler(ke_msg_id_t const msgid,
00082 struct tdls_chan_switch_req const *param,
00083 ke_task_id_t const dest_id,
00084 ke_task_id_t const src_id)
00085 {
00086 uint8_t status = CO_FAIL;
00087
00088 #if NX_UMAC_PRESENT
00089 do
00090 {
00091 struct vif_info_tag *vif;
00092 struct sta_info_tag *sta;
00093
00094 if (param->vif_index == INVALID_VIF_IDX)
00095 {
00096 break;
00097 }
00098 vif = &vif_info_tab[param->vif_index];
00099
00100 if ((param->sta_idx == INVALID_STA_IDX) ||
00101 (vif->u.sta.tdls_chsw_sta_idx != INVALID_STA_IDX))
00102 {
00103 break;
00104 }
00105
00106
00107 vif->u.sta.tdls_chsw_sta_idx = param->sta_idx;
00108 sta = &sta_info_tab[param->sta_idx];
00109
00110 if (!sta->tdls.chsw_allowed)
00111 {
00112 TRACE_TDLS(ERR, "TDLS channel switch is not allowed.");
00113 break;
00114 }
00115
00116
00117 if (sta->valid)
00118 {
00119 sta->tdls.chsw = param->chan;
00120 sta->tdls.chsw_op_class = param->op_class;
00121 sta->tdls.chsw_req_timer.cb = tdls_chsw_req_evt;
00122 sta->tdls.chsw_req_timer.env = vif;
00123 sta->tdls.chsw_active = true;
00124 sta->tdls.chsw_initiator = false;
00125
00126 status = CO_OK;
00127
00128
00129 ke_state_set(TASK_TDLS, TDLS_BASE_CHANNEL);
00130
00131 PROF_TDLS_CHSW_REQ_TX_TIMER_SET();
00132
00133 mm_timer_set(&sta->tdls.chsw_req_timer,
00134 vif->tbtt_timer.time + TDLS_CHSW_REQ_DELAY_US);
00135 }
00136 } while(0);
00137 #endif // NX_UMAC_PRESENT
00138
00139
00140 struct tdls_chan_switch_cfm *cfm = KE_MSG_ALLOC(TDLS_CHAN_SWITCH_CFM,
00141 src_id, dest_id,
00142 tdls_chan_switch_cfm);
00143 cfm->status = status;
00144
00145 ke_msg_send(cfm);
00146
00147 return (KE_MSG_CONSUMED);
00148 }
00149
00163 static
00164 int tdls_cancel_chan_switch_req_handler(ke_msg_id_t const msgid,
00165 struct tdls_cancel_chan_switch_req const *param,
00166 ke_task_id_t const dest_id,
00167 ke_task_id_t const src_id)
00168 {
00169 uint8_t status = CO_FAIL;
00170
00171 #if NX_UMAC_PRESENT
00172 do
00173 {
00174 struct vif_info_tag *vif = &vif_info_tab[param->vif_index];
00175 struct sta_info_tag *sta;
00176
00177 if (param->sta_idx == INVALID_STA_IDX)
00178 {
00179 break;
00180 }
00181
00182 if (param->sta_idx != vif->u.sta.tdls_chsw_sta_idx)
00183 {
00184 TRACE_TDLS(ERR, "TDLS Channel Switch is not active for STA %d.", param->sta_idx);
00185 break;
00186 }
00187
00188 sta = &sta_info_tab[param->sta_idx];
00189
00190 PROF_TDLS_CHSW_REQ_TX_TIMER_CLR();
00191 mm_timer_clear(&sta->tdls.chsw_req_timer);
00192 sta->tdls.chsw_active = false;
00193 sta->tdls.chsw_initiator = false;
00194 if (ke_state_get(TASK_TDLS) == TDLS_BASE_CHANNEL)
00195 {
00196
00197 vif->u.sta.tdls_chsw_sta_idx = INVALID_STA_IDX;
00198 }
00199 else
00200 {
00201
00202 struct mm_remain_on_channel_req roc_param;
00203
00204 PROF_TDLS_CHSW_TIME_TIMER_CLR();
00205 mm_timer_clear(&sta->tdls.chsw_time_timer);
00206 PROF_TDLS_CHSW_END_TIMER_CLR();
00207 mm_timer_clear(&sta->tdls.chsw_end_timer);
00208 roc_param.vif_index = vif->index;
00209 roc_param.op_code = MM_ROC_OP_CANCEL;
00210 PROF_TDLS_SWITCH_TO_BASECH_SET();
00211 chan_roc_req(&roc_param, TASK_TDLS);
00212 PROF_TDLS_SWITCH_TO_BASECH_CLR();
00213
00214 ke_state_set(TASK_TDLS, TDLS_BASE_CHANNEL);
00215 }
00216 status = CO_OK;
00217 } while (0);
00218
00219 #endif // NX_UMAC_PRESENT
00220
00221
00222 struct tdls_cancel_chan_switch_cfm *cfm = KE_MSG_ALLOC(TDLS_CANCEL_CHAN_SWITCH_CFM,
00223 src_id, dest_id,
00224 tdls_cancel_chan_switch_cfm);
00225 cfm->status = status;
00226
00227 ke_msg_send(cfm);
00228
00229 return (KE_MSG_CONSUMED);
00230 }
00231
00232 #if NX_UMAC_PRESENT
00233
00246 static
00247 int tdls_peer_traffic_ind_req_handler(ke_msg_id_t const msgid,
00248 struct tdls_peer_traffic_ind_req const *param,
00249 ke_task_id_t const dest_id,
00250 ke_task_id_t const src_id)
00251 {
00252 uint8_t status = CO_FAIL;
00253
00254 if (param->sta_idx == INVALID_STA_IDX)
00255 {
00256 return status;
00257 }
00258
00259
00260 status = txl_frame_send_tdls_peer_traffic_ind_frame(param, &tdls_peer_traffic_ind_tx_cfm);
00261
00262 if (status == CO_OK)
00263 {
00264 struct sta_info_tag *sta = &sta_info_tab[param->sta_idx];
00265
00266 sta->tdls.dialog_token = param->dialog_token;
00267
00268 sta->tdls.traffic_available = true;
00269
00270 ke_state_set(TASK_TDLS, TDLS_TRAFFIC_IND_TX);
00271 }
00272
00273
00274 struct tdls_peer_traffic_ind_cfm *cfm = KE_MSG_ALLOC(TDLS_PEER_TRAFFIC_IND_CFM,
00275 src_id, dest_id,
00276 tdls_peer_traffic_ind_cfm);
00277 cfm->status = status;
00278
00279 ke_msg_send(cfm);
00280
00281 return (KE_MSG_CONSUMED);
00282
00283 }
00284 #endif // NX_UMAC_PRESENT
00285
00286
00287
00288
00289
00291 const struct ke_msg_handler tdls_default_state[] =
00292 {
00293
00294 {TDLS_CHAN_SWITCH_REQ, (ke_msg_func_t)tdls_chan_switch_req_handler},
00295
00296 {TDLS_CANCEL_CHAN_SWITCH_REQ, (ke_msg_func_t)tdls_cancel_chan_switch_req_handler},
00297 #if (NX_UMAC_PRESENT)
00298
00299 {TDLS_PEER_TRAFFIC_IND_REQ, (ke_msg_func_t)tdls_peer_traffic_ind_req_handler},
00300 #endif
00301 };
00302
00304 const struct ke_state_handler tdls_default_handler =
00305 KE_STATE_HANDLER(tdls_default_state);
00306
00308 ke_state_t tdls_state[TDLS_IDX_MAX];
00309
00310 #endif // NX_TDLS
00311