- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# /space/home/slher/rel/Beken/v6_4_5/macsw/ip/lmac/src/tdls/tdls.c

Go to the documentation of this file.

    00001
    00020 /*
    00021  * INCLUDE FILES
    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 // For IE access functions
    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     // If TX is not successful, inform the host
    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             // Inform host that the TDLS peer is unreachable
    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             // Retry to send the keep-alive QoS Null Frame
    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     // If TX is successful stop Channel Switch Timeout timer
    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     // Send the postponed frames
    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     // If TX is not successful set state TDLS_BASE_CHANNEL
    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      //Switch to the new channel just after ack received
    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(&param, TASK_TDLS);
    00172         ke_state_set(TASK_TDLS, TDLS_OFF_CHANNEL);
    00173         PROF_TDLS_SWITCH_TO_OFFCH_CLR();
    00174     }
    00175     else
    00176     {
    00177         // Reset STA index
    00178         vif->u.sta.tdls_chsw_sta_idx = INVALID_STA_IDX;
    00179         // Reset TDLS state
    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(&param, TASK_TDLS);
    00203     PROF_TDLS_SWITCH_TO_BASECH_CLR();
    00204
    00205     // Reset state
    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         // Get Target Channel Number
    00236         sta_tdls->tdls.chsw_num = co_read8p(frame_addr + offset + TDLS_CHANSW_REQ_TARGET_CH_OFFSET);
    00237         // Get Operating Class
    00238         sta_tdls->tdls.chsw_op_class = co_read8p(frame_addr + offset + TDLS_CHANSW_REQ_OP_CLASS);
    00239         // Set band
    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         // Set frequency
    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         // Get Secondary Channel Offset (optional)
    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         // Get Link Identifier IE (mandatory)
    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         // @todo Check Link Identifier information element
    00277         offset += TDLS_CHANSW_REQ_IE_LINK_ID_LEN;
    00278
    00279         // Get Channel Switch Timing IE (mandatory)
    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         // Update switch time and switch timeout
    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         // Check if we have time to complete the channel switch
    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         // Get Wide Bandwidth Channel Switch IE (optional)
    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         // Get status
    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         // Get Link Identifier IE (mandatory)
    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         // Check Link Identifier IE
    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         // Get Channel Switch Timing IE (mandatory)
    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         // Check Channel Switch Timing IE only if not an unsolicited response
    00397         if (ke_state_get(TASK_TDLS) == TDLS_CHSW_REQ_TX)
    00398         {
    00399             // Update time and timeout
    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             // Check if we have time to complete the channel switch
    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         // Get Dialog Token
    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         // Get Link Identifier IE (mandatory)
    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         // Check Link Identifier IE
    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     // Send Unsolicited TDLS Channel Switch Response to indicate we go back to the
    00501     // base channel
    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         // Start Channel Switch Timeout timer
    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         // Send Channel Switch Indication
    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         // Update RC with new configuration
    00542         me_sta_bw_nss_max_upd(sta->staid, sta->tdls.chsw.type, 0xFF);
    00543
    00544         // Set timer for end of period on off channel
    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         // Notify presence on the off channel (only if we are TDLS channel switch initiator)
    00552         //if (sta->tdls.chsw_initiator == false)
    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(&param, 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     // If no successfull frame exchange within Switch Timeout, switch back to base channel
    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(&param, 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             // Send Peer Traffic Indication frame
    00638             struct tdls_peer_traffic_ind_req param;
    00639             param.vif_index = vif->index;
    00640             MAC_ADDR_CPY(&param.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(&param, &tdls_peer_traffic_ind_tx_cfm) == CO_OK)
    00646             {
    00647                 // set dialog token
    00648                 sta_tdls->tdls.dialog_token = param.dialog_token;
    00649                 // Keep in mind that a keep-alive frame should be transmitted
    00650                 sta_tdls->tdls.ka_tx_req = true;
    00651                 // set TDLS STA status
    00652                 ke_state_set(TASK_TDLS, TDLS_TRAFFIC_IND_TX);
    00653             }
    00654         }
    00655     }
    00656     else
    00657     {
    00658         // Send the keep-alive QoS Null Frame
    00659         txl_frame_send_qosnull_frame(sta_tdls->staid, 0x5, tdls_keep_alive_frame_tx_cfm, sta_tdls);
    00660     }
    00661
    00662     // Set next keep-alive QoS Null Frame
    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     // Inform host that the TDLS peer is unreachable
    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             // Peer Traffic Response received  //
    00745
    00746             uint16_t res;
    00747             upload = false;
    00748             struct mac_addr *initiator_mac_addr;
    00749             struct mac_addr *responder_mac_addr;
    00750
    00751             // Check if TDLS Peer Traffic Indication frame has been sent to AP
    00752             if (ke_state_get(TASK_TDLS) != TDLS_TRAFFIC_IND_TX)
    00753             {
    00754                 break;
    00755             }
    00756
    00757             // Set TDLS link initiator and responder
    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                 // Stop PTI Response timeout timer
    00776                 mm_timer_clear(&sta->tdls.pti_timeout_timer);
    00777                 sta->tdls.pti_timer_running = false;
    00778                 // Inform the host that the TDLS peer is awake
    00779                 tdls_send_peer_ps_ind(vif, false, sta_idx);
    00780                 // Check if a keep-alive frame is waiting to be transmitted
    00781                 if (sta->tdls.ka_tx_req)
    00782                 {
    00783                     if (!sta->tdls.traffic_available)
    00784                     {
    00785                         qos |= MAC_QOSCTRL_EOSP;
    00786                     }
    00787                     // Send QoS Null Frame
    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                 // Set state
    00793                 ke_state_set(TASK_TDLS, TDLS_BASE_CHANNEL);
    00794             }
    00795         }
    00796         else
    00797         if (tdls_action == MAC_TDLS_ACTION_CHANSW_REQ)
    00798         {
    00800             // Channel Switch Request received //
    00802             PROF_TDLS_CHSW_REQ_RX_SET();
    00803
    00804             uint16_t status;
    00805             upload = false;
    00806
    00807             // If Channel Switch Request is received while waiting for a Channel Switch Response,
    00808             // the STA should reply only if it's the TDLS responder STA
    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             // Init timers
    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             // Set TX power
    00822             sta->tdls.chsw.tx_power = vif->tx_power;
    00823             // Set the TDLS channel switch initiator
    00824             sta->tdls.chsw_initiator = true;
    00825             // Set TDLS STA index for channel switch response
    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                 // Check if there is traffic with the AP or if TDLS peer is in power save
    00836                 if ((td_sta_has_traffic(vif->u.sta.ap_id)) || (sta->ps_state))
    00837                 {
    00838                     status = TDLS_CHANSW_REQUEST_DECLINED;
    00839                 }
    00840                 //check if Channel Switch is allowed
    00841                 else if (!sta->tdls.chsw_allowed)
    00842                 {
    00843                     status = TDLS_CHANSW_REQUEST_DECLINED;
    00844                 }
    00845                 else
    00846                 {
    00847                     // Set TDLS state
    00848                     ke_state_set(TASK_TDLS, TDLS_CHSW_REQ_RX);
    00849                 }
    00850             }
    00851
    00852             // Send TDLS Channel Switch Response
    00853             if (txl_frame_send_tdls_channel_switch_rsp_frame(vif, status, &tdls_chsw_rsp_tx_cfm) != CO_OK)
    00854             {
    00855                 // Reset sta idx in case of Channel Switch refused
    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             // Channel Switch Response received //
    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             // Check if request is from the correct TDLS STA
    00872             if (sta_idx != vif->u.sta.tdls_chsw_sta_idx)
    00873             {
    00874                 break;
    00875             }
    00876
    00877             // Init timers
    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             // Set TDLS link initiator and responder
    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             // Switch to the new channel just after Channel Switch Response frame has been received,
    00901             // if Channel Switch Request frame is correct
    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                 // do not switch to the new channel if already on the requested channel
    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                     // switch to the off channel if we sent a Channel Switch Request
    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(&param, TASK_TDLS);
    00933                         PROF_TDLS_SWITCH_TO_OFFCH_CLR();
    00934
    00935                         ke_state_set(TASK_TDLS, TDLS_OFF_CHANNEL);
    00936                     }
    00937                 }
    00938                 // switch to base channel is unsolicited Channel Switch Response frame received
    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(&param, 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         // Check frame control NULL function
    00979         if (!(framectrl & MAC_QOS_ST_BIT))
    00980         {
    00981             break;
    00982         }
    00983         // Check From DS and To DS flags
    00984         if ((framectrl & MAC_FCTRL_TODS_FROMDS) != 0)
    00985         {
    00986             break;
    00987         }
    00988
    00989         // Check Power Management flag
    00990         if (!(framectrl & MAC_FCTRL_PWRMGT))
    00991         {
    00992             ps_on = false;
    00993         }
    00994
    00995         if (ps_on != sta->ps_state)
    00996         {
    00997             // Inform the host that the TDLS peer PS state is changed
    00998             tdls_send_peer_ps_ind(vif, ps_on, sta_idx);
    00999         }
    01000         // If TDLS peer enables PS when we are on the off channel, send a Unsolicited
    01001         // Channel Switch Response to go back to base channel
    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         // Set next ChSw Request event to the next TBTT
    01028         next_evt = vif->tbtt_timer.time + TDLS_CHSW_REQ_DELAY_US;
    01029         // Send the TDLS Channel Switch Request frame if there isn't traffic with the AP
    01030         // and if the TDLS peer is not in power save
    01031         if ((!td_sta_has_traffic(vif->u.sta.ap_id)) && (sta->ps_state == PS_MODE_OFF))
    01032         {
    01033             // Check if we are on the base channel
    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                 // send TDLS Channel Switch Request frame
    01046                 txl_frame_send_tdls_channel_switch_req_frame(&req, &tdls_chsw_req_tx_cfm);
    01047             }
    01048             // Check if we are waiting to complete TDLS channel switch procedure
    01049             // (i.e. TDLS ChSw Response not yet received): reset the state and wait the next
    01050             // TBTT to try again the Channel Switch
    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         // Set next channel switch request
    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     // Check if the TDLS peer is going to sleep
    01070     tdls_check_peer_ps(frame, vif, sta_idx);
    01071
    01072     // Check if TDLS Channel Switch Request, TDLS Channel Switch Response,
    01073     // TDLS Peer Traffic Response and update TDLS info
    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     // Inform the host that the remain on channel has expired
    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     // Update RC with new configuration
    01095     me_sta_bw_nss_max_upd(sta->staid, vif->chan_ctxt->channel.type, 0xFF);
    01096
    01097     // Reset tdls_chsw_sta_idx and timers if TDLS Channel Switch is not active
    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     // Send the postponed frames
    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     // Inform the host that the TDLS peer is going to sleep or is awake
    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     // Change the local value of the PS state
    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     // Init the keep-alive timer for the TDLS Peer
    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     // Init PTI Response timeout timer
    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     // Clear keep-alive timer
    01154     mm_timer_clear(&sta->tdls.keep_alive_timer);
    01155     // Clear PTI Response timeout timer
    01156     mm_timer_clear(&sta->tdls.pti_timeout_timer);
    01157     // Clear channel switch request timer
    01158     mm_timer_clear(&sta->tdls.chsw_req_timer);
    01159     // Clear channel switch time timer
    01160     mm_timer_clear(&sta->tdls.chsw_time_timer);
    01161     // Clear channel switch timeout timer
    01162     mm_timer_clear(&sta->tdls.chsw_timeout_timer);
    01163     // Clear channel switch end timer
    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         // If TX is successful set PTI timeout
    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         // If TX is not successful set state TDLS_BASE_CHANNEL
    01186         ke_state_set(TASK_TDLS, TDLS_BASE_CHANNEL);
    01187     }
    01188 }
    01189
    01190 #endif // NX_UMAC_PRESENT && NX_TDLS
    01191
    01193