- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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

Go to the documentation of this file.

    00001
    00020 /*
    00021  * INCLUDE FILES
    00022  ****************************************************************************************
    00023  */
    00024
    00025 #include "vif_mgmt.h"
    00026 #include "mm.h"
    00027 #include "chan.h"
    00028 #include "mm_bcn.h"
    00029 #include "co_utils.h"
    00030 #include "co_status.h"
    00031 #include "dbg.h"
    00032
    00033 #if (NX_CHNL_CTXT || NX_P2P)
    00034 #include "txl_cntrl.h"
    00035 #if (NX_P2P)
    00036 // P2P Definitions and Functions
    00037 #include "p2p.h"
    00038 #endif //(NX_P2P)
    00039 #if (NX_POWERSAVE)
    00040 #include "ps.h"
    00041 #endif //(NX_POWERSAVE)
    00042 #endif //(NX_CHNL_CTXT || NX_P2P)
    00043
    00044 #if (NX_TD)
    00045 // Traffic Detection Functions
    00046 #include "td.h"
    00047 #endif //(NX_TD)
    00048
    00049 #if (RW_UMESH_EN)
    00050 #include "mesh.h"
    00051 #endif //(RW_UMESH_EN)
    00052
    00053 #if NX_UMAC_PRESENT
    00054 #include "me_utils.h"
    00055 #include "tpc.h"
    00056 #endif
    00057
    00058 /*
    00059  * GLOBAL VARIABLES
    00060  ****************************************************************************************
    00061  */
    00062 struct vif_mgmt_env_tag vif_mgmt_env;
    00063 struct vif_info_tag vif_info_tab[NX_VIRT_DEV_MAX];
    00064
    00065 /*
    00066  * FUNCTION DEFINITIONS
    00067  ****************************************************************************************
    00068  */
    00069
    00070 #if (NX_P2P || NX_CHNL_CTXT)
    00071
    00078 static void vif_mgmt_bcn_to_evt(void *env)
    00079 {
    00080     // Retrieve the VIF
    00081     struct vif_info_tag *vif = (struct vif_info_tag *)env;
    00082
    00083     #if (NX_P2P)
    00084     // Informed interested modules
    00085     if (vif->p2p)
    00086     {
    00087         p2p_bcn_evt_handle(vif);
    00088     }
    00089     #endif //(NX_P2P)
    00090
    00091     if (vif->chan_ctxt)
    00092     {
    00093         chan_bcn_to_evt(vif);
    00094     }
    00095 }
    00096 #endif //(NX_P2P || NX_CHNL_CTXT)
    00097
    00105 static void vif_mgmt_entry_init(struct vif_info_tag *vif)
    00106 {
    00107     // Reset table
    00108     memset(vif, 0, sizeof(*vif));
    00109
    00110     vif->type = VIF_UNKNOWN;
    00111     vif->tx_power = VIF_UNDEF_POWER;
    00112     #if NX_UMAC_PRESENT
    00113     vif->user_tx_power = VIF_UNDEF_POWER;
    00114     #endif
    00115
    00116     #if (NX_P2P || NX_CHNL_CTXT)
    00117     // Initialize callback and environment for Beacon TimeOut timer
    00118     vif->tmr_bcn_to.cb  = vif_mgmt_bcn_to_evt;
    00119     vif->tmr_bcn_to.env = vif;
    00120     #endif //(NX_P2P || NX_CHNL_CTXT)
    00121 }
    00122
    00123 void vif_mgmt_init(void)
    00124 {
    00125     int i;
    00126
    00127     // Reset VIF management environment
    00128     memset(&vif_mgmt_env, 0, sizeof(vif_mgmt_env));
    00129
    00130     // Initialize VIF lists
    00131     co_list_init(&vif_mgmt_env.free_list);
    00132     co_list_init(&vif_mgmt_env.used_list);
    00133
    00134     // push all the entries to the free list
    00135     for(i = 0; i < NX_VIRT_DEV_MAX ; i++)
    00136     {
    00137         struct vif_info_tag *vif = &vif_info_tab[i];
    00138         // Init STA info table.
    00139         vif_mgmt_entry_init(vif);
    00140         // Push to free list.
    00141         co_list_push_back(&vif_mgmt_env.free_list, (struct co_list_hdr*)vif);
    00142     }
    00143
    00144     // Initialize monitor VIF to invalid
    00145     vif_mgmt_env.monitor_vif = INVALID_VIF_IDX;
    00146 }
    00147
    00148 #if (NX_TX_FRAME)
    00149 void vif_mgmt_reset(void)
    00150 {
    00151     struct vif_info_tag *vif = (struct vif_info_tag *)co_list_pick(&vif_mgmt_env.used_list);
    00152
    00153     while (vif)
    00154     {
    00155         // Try to push the frame marked as postponed
    00156         vif_mgmt_send_postponed_frame(vif);
    00157
    00158         vif = (struct vif_info_tag *)vif->list_hdr.next;
    00159     }
    00160 }
    00161 #endif //(NX_TX_FRAME)
    00162
    00163 uint8_t vif_mgmt_register(struct mac_addr const *mac_addr, uint8_t vif_type, bool p2p,
    00164                           uint8_t *vif_idx)
    00165 {
    00166     struct vif_info_tag *vif;
    00167
    00168     // Check if there are still some free VIFs
    00169     if (co_list_is_empty(&vif_mgmt_env.free_list))
    00170         // All possible VIFs are active. Reject the new VIF.
    00171         return CO_FAIL;
    00172
    00173     #if (NX_P2P)
    00174     if (p2p && (vif_type == VIF_AP))
    00175     {
    00176         #if (NX_P2P_GO)
    00177         if (p2p_env.nb_p2p_go)
    00178             // Only one P2P GO VIF is supported
    00179             return CO_FAIL;
    00180         #else
    00181         // Do not create a P2P GO VIF if not supported
    00182         return CO_FAIL;
    00183         #endif //(NX_P2P_GO)
    00184     }
    00185     #endif //(NX_P2P)
    00186
    00187     // Check if an interface is already defined or not
    00188     if (co_list_is_empty(&vif_mgmt_env.used_list))
    00189     {
    00190         #if NX_MULTI_ROLE
    00191         // Configure the HW properly for the first interface added
    00192         mm_hw_info_set(mac_addr);
    00193         #else
    00194         #if NX_BEACONING && (NX_POWERSAVE || NX_CONNECTION_MONITOR || NX_UMAC_PRESENT)
    00195         // Depending on the interface type, check if the beaconing has to be enabled
    00196         if ((vif_type == VIF_AP) || (vif_type == VIF_IBSS))
    00197         {
    00198             mm_env.beaconing = true;
    00199         }
    00200         else
    00201         {
    00202             mm_env.beaconing = false;
    00203         }
    00204         #endif
    00205         // Configure the HW properly
    00206         mm_hw_interface_info_set(vif_type, mac_addr);
    00207         #endif
    00208     }
    00209     else
    00210     {
    00211         uint32_t vif_addr_low, vif_addr_high;
    00212
    00213         #if (!NX_MULTI_ROLE)
    00214         struct vif_info_tag *vif = (struct vif_info_tag *)
    00215             co_list_pick(&vif_mgmt_env.used_list);
    00216
    00217         // We can only have multiple APs. In all other cases, we reject the new VIF
    00218         if ((vif->type != VIF_AP) || (vif_type != VIF_AP))
    00219             return CO_FAIL;
    00220         #endif //(!NX_MULTI_ROLE)
    00221
    00222         #if (NX_P2P)
    00223         if (p2p)
    00224         {
    00225             // Check if a new P2P VIF can be created
    00226             if (vif_mgmt_env.nb_p2p_vifs == NX_P2P_VIF_MAX)
    00227                 return CO_FAIL;
    00228         }
    00229         #endif //(NX_P2P)
    00230
    00231         // Check if VIF MAC address matches with the mask - i.e. only MSB might differ
    00232         vif_addr_low = mac_addr->array[0] | (((uint32_t)mac_addr->array[1]) << 16);
    00233         vif_addr_high = mac_addr->array[2];
    00234         if ((vif_addr_low != nxmac_mac_addr_low_get()) ||
    00235             (((vif_addr_high ^ nxmac_mac_addr_hi_get()) & ~nxmac_mac_addr_hi_mask_get()) != 0))
    00236             return CO_FAIL;
    00237
    00238         #if (NX_MULTI_ROLE)
    00239         // More than one entity will now be available, so disable HW filtering on BSSID
    00240         mm_rx_filter_lmac_enable_set(NXMAC_ACCEPT_OTHER_BSSID_BIT);
    00241         #endif //(NX_MULTI_ROLE)
    00242     }
    00243
    00244     // get a free element from the free VIF list
    00245     vif = (struct vif_info_tag*)co_list_pop_front(&vif_mgmt_env.free_list);
    00246
    00247     // Initialize some fields from the parameters
    00248     vif->type = vif_type;
    00249     vif->mac_addr = *mac_addr;
    00250     vif->index = CO_GET_INDEX(vif, vif_info_tab);
    00251     vif->txq_params[AC_BK] = NXMAC_EDCA_AC_0_RESET;
    00252     vif->txq_params[AC_BE] = NXMAC_EDCA_AC_1_RESET;
    00253     vif->txq_params[AC_VI] = NXMAC_EDCA_AC_2_RESET;
    00254     vif->txq_params[AC_VO] = NXMAC_EDCA_AC_3_RESET;
    00255     vif->tx_power = VIF_UNDEF_POWER;
    00256     #if NX_UMAC_PRESENT
    00257     vif->user_tx_power = VIF_UNDEF_POWER;
    00258     #endif
    00259     #if (NX_CHNL_CTXT)
    00260     vif->chan_ctxt = NULL;
    00261     vif->tbtt_switch.vif_index = vif->index;
    00262     #endif //(NX_CHNL_CTXT)
    00263     #if NX_MAC_HE
    00264     vif->txop_dur_rts_thres = MAC_HE_OPER_TXOP_DUR_RTS_THRES_DISABLED;
    00265     #endif
    00266     #if (NX_P2P)
    00267     vif->p2p = p2p;
    00268     vif->u.sta.sp_paused = false;
    00269     #endif //(NX_P2P)
    00270
    00271     #if (NX_MULTI_ROLE || NX_BCN_AUTONOMOUS_TX || NX_REORD)
    00272     switch (vif_type)
    00273     {
    00274         case (VIF_STA):
    00275         {
    00276             #if NX_MULTI_ROLE
    00277             // One more STA VIF
    00278             vif_mgmt_env.vif_sta_cnt++;
    00279
    00280             // Initialize TBTT timer
    00281             vif->tbtt_timer.cb = mm_sta_tbtt;
    00282             vif->tbtt_timer.env = vif;
    00283             #if !NX_UMAC_PRESENT
    00284             vif->u.sta.ap_bcn_intv = 100;
    00285             #endif
    00286             #endif
    00287
    00288             vif->u.sta.ap_id = INVALID_STA_IDX;
    00289
    00290             #if NX_UMAC_PRESENT
    00291             vif->u.sta.csa_count = 0;
    00292             vif->u.sta.csa_occured = false;
    00293             #endif
    00294         } break;
    00295
    00296         #if (RW_MESH_EN)
    00297         case (VIF_MESH_POINT):
    00298         {
    00299             #if (RW_UMESH_EN)
    00300             vif->mvif_idx = MESH_INVALID_MESH_IDX;
    00301             #endif //(RW_UMESH_EN)
    00302
    00303             vif_mgmt_env.vif_mp_cnt++;
    00304
    00305             // Disable filtering on other BSSID as 4 adresses are used for mesh QoS data
    00306             mm_rx_filter_lmac_enable_set(NXMAC_ACCEPT_OTHER_BSSID_BIT);
    00307         } // no break;
    00308         #endif //(RW_MESH_EN)
    00309
    00310         case (VIF_AP):
    00311         {
    00312             #if NX_MULTI_ROLE
    00313             // Check if this is the first AP VIF created
    00314             if (!vif_mgmt_env.vif_ap_cnt)
    00315                 mm_hw_ap_info_set();
    00316
    00317             // One more AP VIF
    00318             vif_mgmt_env.vif_ap_cnt++;
    00319             #endif
    00320
    00321             #if (!NX_UMAC_PRESENT && NX_BCN_AUTONOMOUS_TX)
    00322             // Set a default beacon interval value
    00323             vif->u.ap.bcn_int = 100;
    00324             #endif //(!NX_UMAC_PRESENT)
    00325
    00326             #if (NX_P2P_GO && NX_POWERSAVE)
    00327             if (vif->p2p)
    00328             {
    00329                 // Initialize TBTT timer
    00330                 vif->tbtt_timer.cb = mm_ap_pre_tbtt;
    00331                 vif->tbtt_timer.env = vif;
    00332             }
    00333             #endif //(NX_P2P_GO && NX_POWERSAVE)
    00334
    00335             #if (NX_BCN_AUTONOMOUS_TX)
    00336             mm_bcn_init_vif(vif);
    00337             #endif
    00338         } break;
    00339
    00340         case (VIF_MONITOR):
    00341         {
    00342             if (vif_mgmt_env.monitor_vif != INVALID_VIF_IDX)
    00343                 return CO_FAIL;
    00344
    00345             // Assign monitor vif
    00346             vif_mgmt_env.monitor_vif = vif->index;
    00347
    00348             #if (NX_UMAC_PRESENT)
    00349             // Check if first interface
    00350             if (co_list_is_empty(&vif_mgmt_env.used_list))
    00351             {
    00352                 struct mac_chan_op chan;
    00353                 uint8_t chan_idx;
    00354
    00355                 // Use default channel config
    00356                 chan.band         = PHY_BAND_2G4;
    00357                 chan.type         = PHY_CHNL_BW_20;
    00358                 chan.prim20_freq  = 2437;
    00359                 chan.center1_freq = 2437;
    00360                 chan.center2_freq = 0;
    00361
    00362                 // Set MAC HW to monitor mode
    00363                 hal_machw_monitor_mode();
    00364
    00365                 // Add channel context
    00366                 if (chan_ctxt_add(&chan, &chan_idx) != CO_OK)
    00367                 {
    00368                     return CO_FAIL;
    00369                 }
    00370                 #if NX_POWERSAVE
    00371                 // Disallow deep sleep while monitor mode is active
    00372                 vif->prevent_sleep |= PS_VIF_MONITOR;
    00373                 #endif
    00374                 // Link it to the monitor interface
    00375                 chan_ctxt_link_monitor(chan_idx);
    00376             }
    00377             else
    00378                 #if NX_MON_DATA
    00379             {
    00380                 // Get first used interface
    00381                 struct vif_info_tag *vif = (struct vif_info_tag *)co_list_pick(&vif_mgmt_env.used_list);
    00382
    00383                 // Set RX filter
    00384                 mm_rx_filter_umac_set(MM_RX_FILTER_MONITOR);
    00385
    00386                 // Link monitor VIF with used interface context (if valid)
    00387                 if (vif->chan_ctxt)
    00388                 {
    00389                     chan_ctxt_link_monitor(vif->chan_ctxt->idx);
    00390                 }
    00391             }
    00392             #else
    00393             {
    00394                 // Set monitor vif to invalid
    00395                 vif_mgmt_env.monitor_vif = INVALID_STA_IDX;
    00396
    00397                 return CO_FAIL;
    00398             }
    00399             #endif
    00400             #endif /* NX_UMAC_PRESENT */
    00401         } break;
    00402
    00403         default:
    00404             break;
    00405     }
    00406     #endif //(NX_MULTI_ROLE || NX_BCN_AUTONOMOUS_TX || NX_REORD)
    00407
    00408     #if (NX_P2P)
    00409     if (p2p)
    00410     {
    00411         // Update number of registered P2P VIFs
    00412         vif_mgmt_env.nb_p2p_vifs++;
    00413
    00414         // Check if a new P2P interface can be created
    00415         vif->p2p_index = p2p_create(vif->index,
    00416                                     (vif_type == VIF_STA) ? P2P_ROLE_CLIENT : P2P_ROLE_GO);
    00417
    00418         // Sanity Check
    00419         ASSERT_ERR(vif->p2p_index != P2P_INVALID_IDX);
    00420     }
    00421     #endif //(NX_P2P)
    00422
    00423     #if (NX_TD)
    00424     if (vif_type != VIF_MONITOR)
    00425         // Start Traffic Detection on this VIF
    00426         td_start(vif->index);
    00427     #endif //(NX_TD)
    00428
    00429     // Get the station index
    00430     *vif_idx = vif->index;
    00431
    00432     // Push the VIF entry to the used list
    00433     co_list_push_back(&vif_mgmt_env.used_list, &vif->list_hdr);
    00434
    00435     #if NX_MAC_HE
    00436     // Enable/disable the HE TB operation
    00437     txl_he_tb_config();
    00438     #endif
    00439
    00440     // Set the BSSID mask according to the registered VIFs
    00441     vif_mgmt_set_bssid_mask();
    00442
    00443     return CO_OK;
    00444 }
    00445
    00446 void vif_mgmt_unregister(uint8_t vif_idx)
    00447 {
    00448     struct vif_info_tag *vif = &vif_info_tab[vif_idx];
    00449
    00450     // Extract the VIF entry from the used list
    00451     co_list_extract(&vif_mgmt_env.used_list, &vif->list_hdr);
    00452
    00453     #if NX_MULTI_ROLE
    00454     // Check if it was a STA or AP VIF
    00455     switch (vif->type)
    00456     {
    00457         case (VIF_STA):
    00458         {
    00459             // One less STA VIF
    00460             vif_mgmt_env.vif_sta_cnt--;
    00461         } break;
    00462
    00463         #if (RW_MESH_EN)
    00464         case (VIF_MESH_POINT):
    00465         {
    00466             vif_mgmt_env.vif_mp_cnt--;
    00467         } //no break;
    00468         #endif //(RW_MESH_EN)
    00469         case (VIF_AP):
    00470         {
    00471             // One less AP VIF
    00472             vif_mgmt_env.vif_ap_cnt--;
    00473
    00474             // Check if there are still some APs enabled
    00475             if (!vif_mgmt_env.vif_ap_cnt)
    00476                 mm_hw_ap_info_reset();
    00477         } break;
    00478         case (VIF_MONITOR):
    00479         {
    00480             #if NX_UF_EN
    00481             //Configure unsupported frame handling
    00482             if (phy_uf_supported())
    00483             {
    00484                 //Disable Unsupported HT Frame logging
    00485                 phy_uf_enable(false);
    00486             }
    00487             #endif /* NX_UF_EN */
    00488
    00489             #if (NX_UMAC_PRESENT)
    00490             {
    00491                 struct vif_info_tag *vif = &vif_info_tab[vif_mgmt_env.monitor_vif];
    00492
    00493                 #if NX_POWERSAVE
    00494                 // Allow again deep sleep now that monitor mode is inactive
    00495                 vif->prevent_sleep &= ~PS_VIF_MONITOR;
    00496                 #endif
    00497                 //Check if monitor channel is already linked
    00498                 if (vif->chan_ctxt)
    00499                 {
    00500                     // Unlink monitor channel
    00501                     chan_ctxt_unlink(vif_mgmt_env.monitor_vif);
    00502                 }
    00503
    00504                 if (vif_mgmt_env.vif_ap_cnt)
    00505                 {
    00506                     mm_hw_ap_info_set();
    00507                 }
    00508                 else
    00509                 {
    00510                     mm_rx_filter_umac_set(MM_RX_FILTER_ACTIVE);
    00511                 }
    00512             }
    00513             #endif /* NX_UMAC_PRESENT */
    00514
    00515             // Reset monitor vif
    00516             vif_mgmt_env.monitor_vif = INVALID_STA_IDX;
    00517         } break;
    00518
    00519         default:
    00520         {
    00521
    00522         } break;
    00523     }
    00524
    00525     // Check if there is only one entity again
    00526     if ((vif_mgmt_used_cnt() == 1)
    00527         #if (RW_MESH_EN)
    00528             && (!vif_mgmt_env.vif_mp_cnt)
    00529         #endif //(RW_MESH_EN)
    00530             )
    00531     {
    00532         struct vif_info_tag *vif = (struct vif_info_tag *)co_list_pick(&vif_mgmt_env.used_list);
    00533
    00534         // More than one entity will now be available, so reenable HW filtering on BSSID
    00535         mm_rx_filter_lmac_enable_clear(NXMAC_ACCEPT_OTHER_BSSID_BIT);
    00536         // Only one VIF used, so put the BSSID in the HW
    00537         // write lower 4 bytes of BSSID
    00538         nxmac_bss_id_low_setf(vif->bssid.array[0] | (((uint32_t)vif->bssid.array[1]) << 16));
    00539
    00540         // write higher 2 bytes of BSSID
    00541         nxmac_bss_id_high_setf(vif->bssid.array[2]);
    00542     }
    00543     #endif
    00544
    00545     #if (NX_MULTI_ROLE || NX_CHNL_CTXT || NX_P2P_GO)
    00546     // Clear TBTT Timer
    00547     mm_timer_clear(&vif->tbtt_timer);
    00548     #endif //(NX_MULTI_ROLE || NX_CHNL_CTXT || NX_P2P_GO)
    00549
    00550     #if (NX_CHNL_CTXT || NX_P2P)
    00551     // Clear Beacon Timeout Timer
    00552     mm_timer_clear(&vif->tmr_bcn_to);
    00553     #endif //(NX_CHNL_CTXT || NX_P2P)
    00554
    00555     #if (NX_P2P)
    00556     if (vif->p2p)
    00557     {
    00558         p2p_cancel(vif->p2p_index, true);
    00559
    00560         #if (NX_CHNL_CTXT)
    00561         // Update number of registered P2P VIFs
    00562         vif_mgmt_env.nb_p2p_vifs--;
    00563         #endif //(NX_CHNL_CTXT)
    00564     }
    00565     #endif //(NX_P2P)
    00566
    00567     #if (NX_TD)
    00568     // Stop Traffic Detection on this VIF
    00569     td_reset(vif->index);
    00570     #endif //(NX_TD)
    00571
    00572     #if NX_MAC_HE
    00573     // Enable/disable the HE TB operation
    00574     txl_he_tb_config();
    00575     #endif
    00576
    00577     // Set the BSSID mask according to the registered VIFs
    00578     vif_mgmt_set_bssid_mask();
    00579
    00580     // Fully reset the entry
    00581     vif_mgmt_entry_init(vif);
    00582
    00583     // Push back the station entry in the free list
    00584     co_list_push_back(&vif_mgmt_env.free_list, (struct co_list_hdr*)vif);
    00585 }
    00586
    00587 #if (NX_UMAC_PRESENT)
    00588 void vif_mgmt_add_key(struct mm_key_add_req const *param, uint8_t hw_key_idx)
    00589 {
    00590     struct vif_info_tag *vif = &vif_info_tab[param->inst_nbr];
    00591     struct key_info_tag *key = &vif->key_info[param->key_idx];
    00592
    00593     // Store the key information
    00594     key->hw_key_idx = hw_key_idx;
    00595     key->cipher = param->cipher_suite;
    00596     key->key_idx = param->key_idx;
    00597
    00598     // Reset the replay counters
    00599     memset(key->rx_pn, 0, TID_MAX * sizeof(uint64_t));
    00600
    00601     // Check which encryption type has to be used
    00602     switch(key->cipher)
    00603     {
    00604         case MAC_CIPHER_WEP40:
    00605         case MAC_CIPHER_WEP104:
    00606             key->tx_pn = co_rand_word() & 0xFFFFFF;
    00607             break;
    00608         case MAC_CIPHER_TKIP:
    00609             key->tx_pn = 0;
    00610             key->u.mic.tx_key[0] = param->key.array[4];
    00611             key->u.mic.tx_key[1] = param->key.array[5];
    00612             key->u.mic.rx_key[0] = param->key.array[6];
    00613             key->u.mic.rx_key[1] = param->key.array[7];
    00614             break;
    00615         #if RW_WAPI_EN
    00616         case MAC_CIPHER_WPI_SMS4:
    00617             key->tx_pn = 0x5c365c365c365c36ULL;
    00618             break;
    00619         #endif
    00620         #if NX_MFP
    00621         case MAC_CIPHER_BIP_CMAC_128:
    00622             memcpy(key->u.mfp.key, param->key.array, sizeof(key->u.mfp.key));
    00623             key->tx_pn = 0;
    00624             break;
    00625         #endif
    00626         default:
    00627             key->tx_pn = 0;
    00628             break;
    00629     }
    00630
    00631     // Key is now valid
    00632     key->valid = true;
    00633
    00634     #if NX_MFP
    00635     if (key->cipher == MAC_CIPHER_BIP_CMAC_128)
    00636         vif->default_mgmt_key = key;
    00637     else
    00638     #endif
    00639     // This key is now the one used by default
    00640     vif->default_key = key;
    00641 }
    00642
    00643 void vif_mgmt_del_key(struct vif_info_tag *vif, uint8_t keyid)
    00644 {
    00645     int i;
    00646     struct key_info_tag *key = &vif->key_info[keyid];
    00647
    00648     // Key is now invalid
    00649     key->valid = false;
    00650
    00651     // Check if we still have a valid default key
    00652     if (vif->default_key == key)
    00653     {
    00654         vif->default_key = NULL;
    00655         for (i = 0; i < MAC_DEFAULT_KEY_COUNT; i++)
    00656         {
    00657             key = &vif->key_info[i];
    00658             if (key->valid)
    00659             {
    00660                 vif->default_key = key;
    00661                 return;
    00662             }
    00663         }
    00664     }
    00665     #if NX_MFP
    00666     if (vif->default_mgmt_key == key)
    00667     {
    00668         vif->default_mgmt_key = NULL;
    00669         for (i = MAC_DEFAULT_KEY_COUNT; i < MAC_DEFAULT_MFP_KEY_COUNT; i++)
    00670         {
    00671             key = &vif->key_info[i];
    00672             if (key->valid)
    00673             {
    00674                 vif->default_mgmt_key = key;
    00675                 return;
    00676             }
    00677         }
    00678     }
    00679     #endif
    00680 }
    00681
    00682 uint8_t vif_mgmt_get_staid(const struct vif_info_tag *vif, const struct mac_addr *sta_addr)
    00683 {
    00684     struct co_list_hdr *list_hdr = co_list_pick(&vif->sta_list);
    00685
    00686     // TODO: Using MACHW to retrieve KeyRam Idx from MAC addr may be faster
    00687     while (list_hdr != NULL)
    00688     {
    00689         struct sta_info_tag *sta = (struct sta_info_tag *)list_hdr;
    00690         if (MAC_ADDR_CMP(&sta->mac_addr, sta_addr))
    00691             return sta->staid;
    00692         list_hdr = co_list_next(list_hdr);
    00693     }
    00694     return INVALID_STA_IDX;
    00695 }
    00696 #endif
    00697
    00698 #if (NX_TX_FRAME)
    00699 void vif_mgmt_send_postponed_frame(struct vif_info_tag *vif)
    00700 {
    00701     // STA Information entry
    00702     struct sta_info_tag *sta;
    00703
    00704     #if (NX_UMAC_PRESENT || NX_TD_STA)
    00705     // Get first STA associated with peer
    00706     sta = (struct sta_info_tag *)co_list_pick(&vif->sta_list);
    00707
    00708     while (sta != NULL)
    00709     {
    00710         sta_mgmt_send_postponed_frame(vif, sta, 0);
    00711
    00712         // Get next STA entry
    00713         sta = (struct sta_info_tag *)sta->list_hdr.next;
    00714     }
    00715     #else
    00716     // Counter
    00717     uint8_t cnt;
    00718
    00719     // Go through list of STA
    00720     for (cnt = 0; cnt < STA_MAX; cnt++)
    00721     {
    00722         sta = &sta_info_tab[cnt];
    00723
    00724         // Check if STA in linked with provided VIF
    00725         if (sta->inst_nbr != vif->index)
    00726         {
    00727             // Go to next STA
    00728             continue;
    00729         }
    00730
    00731         sta_mgmt_send_postponed_frame(vif, sta, 0);
    00732     }
    00733     #endif //(NX_UMAC_PRESENT || NX_TD_STA)
    00734 }
    00735 #endif //(NX_TX_FRAME)
    00736
    00737 #if (NX_CHNL_CTXT || NX_P2P)
    00738 void vif_mgmt_bcn_to_prog(struct vif_info_tag *vif)
    00739 {
    00740     mm_timer_set(&vif->tmr_bcn_to, ke_time() + VIF_MGMT_BCN_TO_DUR);
    00741 }
    00742
    00743 void vif_mgmt_bcn_recv(struct vif_info_tag *vif)
    00744 {
    00745     do
    00746     {
    00747         #if (NX_POWERSAVE)
    00748         // If PS not used, wait for timeout
    00749         if (!ps_env.ps_on)
    00750         {
    00751             break;
    00752         }
    00753
    00754         // Check PS is paused due to traffic, wait for timeout
    00755         if (ps_env.prevent_sleep & PS_PSM_PAUSED)
    00756         {
    00757             break;
    00758         }
    00759
    00760         // Check if we are waiting for data
    00761         if (vif->prevent_sleep)
    00762         {
    00763             break;
    00764         }
    00765         #endif //(NX_POWERSAVE)
    00766
    00767         // Stop Timeout Timer
    00768         mm_timer_clear(&vif->tmr_bcn_to);
    00769
    00770         // End Timeout period
    00771         vif_mgmt_bcn_to_evt((void *)vif);
    00772     } while (0);
    00773 }
    00774 #endif //(NX_CHNL_CTXT || NX_P2P)
    00775
    00776 void vif_mgmt_set_ap_bcn_int(struct vif_info_tag *vif, uint16_t bcn_int)
    00777 {
    00778     // Beacon Interval to be used for the VIF
    00779     uint16_t set_bcn_int = bcn_int;
    00780
    00781     #if NX_BCN_AUTONOMOUS_TX
    00782     // Store the Beacon Interval
    00783     vif->u.ap.bcn_int = bcn_int;
    00784     #endif
    00785
    00786     #if (NX_UMAC_PRESENT && NX_BEACONING)
    00787     // Protect from AP TBTT interrupt
    00788     GLOBAL_INT_DISABLE();
    00789
    00790     // Check if first AP/MP interface
    00791     if (vif_mgmt_env.vif_ap_cnt > 1)
    00792     {
    00793         struct vif_info_tag *rd_vif;
    00794         // Cache lowest Beacon Interval currently in use
    00795         uint16_t lowest_bcn_int = vif_info_tab[vif_mgmt_env.low_bcn_int_idx].u.ap.bcn_int;
    00796
    00797         if (bcn_int < lowest_bcn_int)
    00798         {
    00799             // Provided VIF is now the one with the lowest beacon interval
    00800             vif_mgmt_env.low_bcn_int_idx = vif->index;
    00801         }
    00802         else
    00803         {
    00804             set_bcn_int = lowest_bcn_int;
    00805         }
    00806
    00807         // Loop over the AP/MP VIFs
    00808         rd_vif = (struct vif_info_tag *)co_list_pick(&vif_mgmt_env.used_list);
    00809
    00810         while (rd_vif)
    00811         {
    00812             // Get number of time we see a TBTT between two beacon transmissions
    00813             uint8_t ratio = (uint8_t)(rd_vif->u.ap.bcn_int / set_bcn_int);
    00814
    00815             // Store the ratio
    00816             rd_vif->u.ap.bcn_tbtt_ratio = ratio;
    00817             // Initialize counter to our next TBTT
    00818             rd_vif->u.ap.bcn_tbtt_cnt = 1;
    00819
    00820             // Get next VIF
    00821             rd_vif = (struct vif_info_tag *)(rd_vif->list_hdr.next);
    00822         }
    00823     }
    00824     else
    00825     {
    00826         // Store the VIF index
    00827         vif_mgmt_env.low_bcn_int_idx = vif->index;
    00828         // And initialize beacon transmission values
    00829         vif->u.ap.bcn_tbtt_ratio = 1;
    00830         vif->u.ap.bcn_tbtt_cnt = 1;
    00831     }
    00832     #endif //(NX_UMAC_PRESENT)
    00833
    00834     // If we are here update the beacon interval in the HW
    00835     nxmac_beacon_int_setf(set_bcn_int);
    00836
    00837     #if (NX_UMAC_PRESENT && NX_BEACONING)
    00838     // Restore interrupts
    00839     GLOBAL_INT_RESTORE();
    00840     #endif //(NX_UMAC_PRESENT)
    00841 }
    00842
    00843 #if NX_UMAC_PRESENT
    00844 void vif_mgmt_switch_channel(struct vif_info_tag *vif)
    00845 {
    00846     struct mm_csa_finish_ind *ind = KE_MSG_ALLOC(MM_CSA_FINISH_IND, TASK_API,
    00847                                                  TASK_MM, mm_csa_finish_ind);
    00848     struct me_bss_info *bss = &vif->bss_info;
    00849     struct mac_chan_op *dest = &vif->csa_channel;
    00850     uint8_t chan_idx = 0xFF;
    00851     uint8_t res;
    00852
    00853     // Unlink the VIF from its current channel context
    00854     chan_ctxt_unlink(vif->index);
    00855
    00856     // Update bss info regarding channel and TX power
    00857     bss->chan = *dest;
    00858     bss->power_constraint = 0;
    00859     tpc_update_vif_tx_power(vif);
    00860
    00861     // Create a channel context for new channel
    00862     res = chan_ctxt_add(dest, &chan_idx);
    00863     ind->status = res;
    00864     ind->chan_idx = chan_idx;
    00865
    00866     if (vif->type == VIF_STA)
    00867     {
    00868         vif->u.sta.csa_count = 0;
    00869
    00870         if (res == CO_OK)
    00871         {
    00872             struct sta_info_tag *sta = &sta_info_tab[vif->u.sta.ap_id];
    00873
    00874             chan_ctxt_link(vif->index, chan_idx);
    00875
    00876             // reset beacon related timer and counter. Traffic will be re-enabled
    00877             // once a beacon is detected on the new channel.
    00878             mm_timer_clear(&vif->tmr_bcn_to);
    00879             mm_timer_set(&vif->tbtt_timer, ke_time() + sta->bcn_int);
    00880             vif->u.sta.beacon_loss_cnt = 0;
    00881             vif->u.sta.csa_occured = true;
    00882         }
    00883         else
    00884         {
    00885             mm_send_connection_loss_ind(vif);
    00886         }
    00887     }
    00888     #if NX_BCN_AUTONOMOUS_TX // if not defined this function is not called for AP itf
    00889     else if (vif->type == VIF_AP)
    00890     {
    00891         vif->u.ap.csa_count = 0;
    00892
    00893         if (res == CO_OK)
    00894         {
    00895             chan_ctxt_link(vif->index, chan_idx);
    00896
    00897             // prevent beacon transmission until it has been updated
    00898             mm_bcn_env.update_ongoing = true;
    00899         }
    00900     }
    00901     #endif
    00902
    00903     ke_msg_send(ind);
    00904 }
    00905 #endif
    00906
    00907 struct vif_info_tag *vif_mgmt_get_single_sta_vif(void)
    00908 {
    00909     struct vif_info_tag *vif;
    00910
    00911     #if NX_MULTI_ROLE
    00912     if (vif_mgmt_used_cnt() != 1)
    00913         return NULL;
    00914     #endif
    00915
    00916     vif = (struct vif_info_tag *)co_list_pick(&vif_mgmt_env.used_list);
    00917
    00918     if (vif->type != VIF_STA)
    00919         return NULL;
    00920
    00921     return vif;
    00922 }
    00923
    00924 void vif_mgmt_set_bssid_mask(void)
    00925 {
    00926     struct vif_info_tag *vif;
    00927
    00928     // By default don't set any mask, meaning that all the received BSSID bits are
    00929     // compared with the register
    00930     nxmac_bss_id_hi_mask_set(0);
    00931
    00932     #if NX_MULTI_ROLE
    00933     if (vif_mgmt_used_cnt() > 1)
    00934         return;
    00935     #endif
    00936
    00937     vif = (struct vif_info_tag *)co_list_pick(&vif_mgmt_env.used_list);
    00938
    00939     // Check if the VIF is a STA one, connected to a nonTransmitted BSSID
    00940     if ((vif->type == VIF_STA) && vif->active && vif->u.sta.bssid_index &&
    00941         (vif->u.sta.max_bssid_ind <= 8))
    00942         nxmac_bss_id_hi_mask_set((CO_BIT(vif->u.sta.max_bssid_ind) - 1) << 8);
    00943 }
    00944