hw_features.c

Go to the documentation of this file.
00001 
00018 #include "includes.h"
00019 
00020 #include "hostapd.h"
00021 #include "ieee802_11_defs.h"
00022 #include "ieee802_11_common.h"
00023 #include "eloop.h"
00024 #include "hw_features.h"
00025 #include "driver_i.h"
00026 #include "config.h"
00027 
00028 
00029 void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
00030                               size_t num_hw_features)
00031 {
00032         size_t i;
00033 
00034         if (hw_features == NULL)
00035                 return;
00036 
00037         for (i = 0; i < num_hw_features; i++) {
00038                 os_free(hw_features[i].channels);
00039                 os_free(hw_features[i].rates);
00040         }
00041 
00042         os_free(hw_features);
00043 }
00044 
00045 
00046 int hostapd_get_hw_features(struct hostapd_iface *iface)
00047 {
00048         struct hostapd_data *hapd = iface->bss[0];
00049         int ret = 0, i, j;
00050         u16 num_modes, flags;
00051         struct hostapd_hw_modes *modes;
00052 
00053         if (hostapd_drv_none(hapd))
00054                 return -1;
00055         modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags);
00056         if (modes == NULL) {
00057                 hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
00058                                HOSTAPD_LEVEL_DEBUG,
00059                                "Fetching hardware channel/rate support not "
00060                                "supported.");
00061                 return -1;
00062         }
00063 
00064         iface->hw_flags = flags;
00065 
00066         hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
00067         iface->hw_features = modes;
00068         iface->num_hw_features = num_modes;
00069 
00070         for (i = 0; i < num_modes; i++) {
00071                 struct hostapd_hw_modes *feature = &modes[i];
00072                 /* set flag for channels we can use in current regulatory
00073                  * domain */
00074                 for (j = 0; j < feature->num_channels; j++) {
00075                         /*
00076                          * Disable all channels that are marked not to allow
00077                          * IBSS operation or active scanning. In addition,
00078                          * disable all channels that require radar detection,
00079                          * since that (in addition to full DFS) is not yet
00080                          * supported.
00081                          */
00082                         if (feature->channels[j].flag &
00083                             (HOSTAPD_CHAN_NO_IBSS |
00084                              HOSTAPD_CHAN_PASSIVE_SCAN |
00085                              HOSTAPD_CHAN_RADAR))
00086                                 feature->channels[j].flag |=
00087                                         HOSTAPD_CHAN_DISABLED;
00088                         if (feature->channels[j].flag & HOSTAPD_CHAN_DISABLED)
00089                                 continue;
00090                         wpa_printf(MSG_MSGDUMP, "Allowed channel: mode=%d "
00091                                    "chan=%d freq=%d MHz max_tx_power=%d dBm",
00092                                    feature->mode,
00093                                    feature->channels[j].chan,
00094                                    feature->channels[j].freq,
00095                                    feature->channels[j].max_tx_power);
00096                 }
00097         }
00098 
00099         return ret;
00100 }
00101 
00102 
00103 static int hostapd_prepare_rates(struct hostapd_data *hapd,
00104                                  struct hostapd_hw_modes *mode)
00105 {
00106         int i, num_basic_rates = 0;
00107         int basic_rates_a[] = { 60, 120, 240, -1 };
00108         int basic_rates_b[] = { 10, 20, -1 };
00109         int basic_rates_g[] = { 10, 20, 55, 110, -1 };
00110         int *basic_rates;
00111 
00112         if (hapd->iconf->basic_rates)
00113                 basic_rates = hapd->iconf->basic_rates;
00114         else switch (mode->mode) {
00115         case HOSTAPD_MODE_IEEE80211A:
00116                 basic_rates = basic_rates_a;
00117                 break;
00118         case HOSTAPD_MODE_IEEE80211B:
00119                 basic_rates = basic_rates_b;
00120                 break;
00121         case HOSTAPD_MODE_IEEE80211G:
00122                 basic_rates = basic_rates_g;
00123                 break;
00124         default:
00125                 return -1;
00126         }
00127 
00128         if (hostapd_set_rate_sets(hapd, hapd->iconf->supported_rates,
00129                                   basic_rates, mode->mode)) {
00130                 wpa_printf(MSG_ERROR, "Failed to update rate sets in kernel "
00131                            "module");
00132         }
00133 
00134         os_free(hapd->iface->current_rates);
00135         hapd->iface->num_rates = 0;
00136 
00137         hapd->iface->current_rates =
00138                 os_malloc(mode->num_rates * sizeof(struct hostapd_rate_data));
00139         if (!hapd->iface->current_rates) {
00140                 wpa_printf(MSG_ERROR, "Failed to allocate memory for rate "
00141                            "table.");
00142                 return -1;
00143         }
00144 
00145         for (i = 0; i < mode->num_rates; i++) {
00146                 struct hostapd_rate_data *rate;
00147 
00148                 if (hapd->iconf->supported_rates &&
00149                     !hostapd_rate_found(hapd->iconf->supported_rates,
00150                                         mode->rates[i].rate))
00151                         continue;
00152 
00153                 rate = &hapd->iface->current_rates[hapd->iface->num_rates];
00154                 os_memcpy(rate, &mode->rates[i],
00155                           sizeof(struct hostapd_rate_data));
00156                 if (hostapd_rate_found(basic_rates, rate->rate)) {
00157                         rate->flags |= HOSTAPD_RATE_BASIC;
00158                         num_basic_rates++;
00159                 } else
00160                         rate->flags &= ~HOSTAPD_RATE_BASIC;
00161                 wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x",
00162                            hapd->iface->num_rates, rate->rate, rate->flags);
00163                 hapd->iface->num_rates++;
00164         }
00165 
00166         if (hapd->iface->num_rates == 0 || num_basic_rates == 0) {
00167                 wpa_printf(MSG_ERROR, "No rates remaining in supported/basic "
00168                            "rate sets (%d,%d).",
00169                            hapd->iface->num_rates, num_basic_rates);
00170                 return -1;
00171         }
00172 
00173         return 0;
00174 }
00175 
00176 
00177 #ifdef CONFIG_IEEE80211N
00178 static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface)
00179 {
00180         int sec_chan, ok, j, first;
00181         int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
00182                           184, 192 };
00183         size_t k;
00184 
00185         if (!iface->conf->secondary_channel)
00186                 return 1; /* HT40 not used */
00187 
00188         sec_chan = iface->conf->channel + iface->conf->secondary_channel * 4;
00189         wpa_printf(MSG_DEBUG, "HT40: control channel: %d  "
00190                    "secondary channel: %d",
00191                    iface->conf->channel, sec_chan);
00192 
00193         /* Verify that HT40 secondary channel is an allowed 20 MHz
00194          * channel */
00195         ok = 0;
00196         for (j = 0; j < iface->current_mode->num_channels; j++) {
00197                 struct hostapd_channel_data *chan =
00198                         &iface->current_mode->channels[j];
00199                 if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
00200                     chan->chan == sec_chan) {
00201                         ok = 1;
00202                         break;
00203                 }
00204         }
00205         if (!ok) {
00206                 wpa_printf(MSG_ERROR, "HT40 secondary channel %d not allowed",
00207                            sec_chan);
00208                 return 0;
00209         }
00210 
00211         /*
00212          * Verify that HT40 primary,secondary channel pair is allowed per
00213          * IEEE 802.11n Annex J. This is only needed for 5 GHz band since
00214          * 2.4 GHz rules allow all cases where the secondary channel fits into
00215          * the list of allowed channels (already checked above).
00216          */
00217         if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
00218                 return 1;
00219 
00220         if (iface->conf->secondary_channel > 0)
00221                 first = iface->conf->channel;
00222         else
00223                 first = sec_chan;
00224 
00225         ok = 0;
00226         for (k = 0; k < sizeof(allowed) / sizeof(allowed[0]); k++) {
00227                 if (first == allowed[k]) {
00228                         ok = 1;
00229                         break;
00230                 }
00231         }
00232         if (!ok) {
00233                 wpa_printf(MSG_ERROR, "HT40 channel pair (%d, %d) not allowed",
00234                            iface->conf->channel,
00235                            iface->conf->secondary_channel);
00236                 return 0;
00237         }
00238 
00239         return 1;
00240 }
00241 
00242 
00243 static void ieee80211n_switch_pri_sec(struct hostapd_iface *iface)
00244 {
00245         if (iface->conf->secondary_channel > 0) {
00246                 iface->conf->channel += 4;
00247                 iface->conf->secondary_channel = -1;
00248         } else {
00249                 iface->conf->channel -= 4;
00250                 iface->conf->secondary_channel = 1;
00251         }
00252 }
00253 
00254 
00255 static void ieee80211n_get_pri_sec_chan(struct wpa_scan_res *bss,
00256                                         int *pri_chan, int *sec_chan)
00257 {
00258         struct ieee80211_ht_operation *oper;
00259         struct ieee802_11_elems elems;
00260 
00261         *pri_chan = *sec_chan = 0;
00262 
00263         ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, 0);
00264         if (elems.ht_operation &&
00265             elems.ht_operation_len >= sizeof(*oper)) {
00266                 oper = (struct ieee80211_ht_operation *) elems.ht_operation;
00267                 *pri_chan = oper->control_chan;
00268                 if (oper->ht_param & HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH) {
00269                         if (oper->ht_param &
00270                             HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
00271                                 *sec_chan = *pri_chan + 4;
00272                         else if (oper->ht_param &
00273                                  HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
00274                                 *sec_chan = *pri_chan - 4;
00275                 }
00276         }
00277 }
00278 
00279 
00280 static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface,
00281                                      struct wpa_scan_results *scan_res)
00282 {
00283         int pri_chan, sec_chan, pri_freq, sec_freq, pri_bss, sec_bss;
00284         int bss_pri_chan, bss_sec_chan;
00285         size_t i;
00286         int match;
00287 
00288         pri_chan = iface->conf->channel;
00289         sec_chan = iface->conf->secondary_channel * 4;
00290         pri_freq = hostapd_hw_get_freq(iface->bss[0], pri_chan);
00291         if (iface->conf->secondary_channel > 0)
00292                 sec_freq = pri_freq + 20;
00293         else
00294                 sec_freq = pri_freq - 20;
00295 
00296         /*
00297          * Switch PRI/SEC channels if Beacons were detected on selected SEC
00298          * channel, but not on selected PRI channel.
00299          */
00300         pri_bss = sec_bss = 0;
00301         for (i = 0; i < scan_res->num; i++) {
00302                 struct wpa_scan_res *bss = scan_res->res[i];
00303                 if (bss->freq == pri_freq)
00304                         pri_bss++;
00305                 else if (bss->freq == sec_freq)
00306                         sec_bss++;
00307         }
00308         if (sec_bss && !pri_bss) {
00309                 wpa_printf(MSG_INFO, "Switch own primary and secondary "
00310                            "channel to get secondary channel with no Beacons "
00311                            "from other BSSes");
00312                 ieee80211n_switch_pri_sec(iface);
00313         }
00314 
00315         /*
00316          * Match PRI/SEC channel with any existing HT40 BSS on the same
00317          * channels that we are about to use (if already mixed order in
00318          * existing BSSes, use own preference).
00319          */
00320         match = 0;
00321         for (i = 0; i < scan_res->num; i++) {
00322                 struct wpa_scan_res *bss = scan_res->res[i];
00323                 ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan);
00324                 if (pri_chan == bss_pri_chan &&
00325                     sec_chan == bss_sec_chan) {
00326                         match = 1;
00327                         break;
00328                 }
00329         }
00330         if (!match) {
00331                 for (i = 0; i < scan_res->num; i++) {
00332                         struct wpa_scan_res *bss = scan_res->res[i];
00333                         ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan,
00334                                                     &bss_sec_chan);
00335                         if (pri_chan == bss_sec_chan &&
00336                             sec_chan == bss_pri_chan) {
00337                                 wpa_printf(MSG_INFO, "Switch own primary and "
00338                                            "secondary channel due to BSS "
00339                                            "overlap with " MACSTR,
00340                                            MAC2STR(bss->bssid));
00341                                 ieee80211n_switch_pri_sec(iface);
00342                                 break;
00343                         }
00344                 }
00345         }
00346 
00347         return 1;
00348 }
00349 
00350 
00351 static int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface,
00352                                       struct wpa_scan_results *scan_res)
00353 {
00354         int pri_freq, sec_freq;
00355         int affected_start, affected_end;
00356         size_t i;
00357 
00358         pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel);
00359         if (iface->conf->secondary_channel > 0)
00360                 sec_freq = pri_freq + 20;
00361         else
00362                 sec_freq = pri_freq - 20;
00363         affected_start = (pri_freq + sec_freq) / 2 - 25;
00364         affected_end = (pri_freq + sec_freq) / 2 + 25;
00365         wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz",
00366                    affected_start, affected_end);
00367         for (i = 0; i < scan_res->num; i++) {
00368                 struct wpa_scan_res *bss = scan_res->res[i];
00369                 int pri = bss->freq;
00370                 int sec = pri;
00371                 int sec_chan, pri_chan;
00372 
00373                 ieee80211n_get_pri_sec_chan(bss, &pri_chan, &sec_chan);
00374 
00375                 if (sec_chan) {
00376                         if (sec_chan < pri_chan)
00377                                 sec = pri - 20;
00378                         else
00379                                 sec = pri + 20;
00380                 }
00381 
00382                 if ((pri < affected_start || pri > affected_end) &&
00383                     (sec < affected_start || sec > affected_end))
00384                         continue; /* not within affected channel range */
00385 
00386                 wpa_printf(MSG_DEBUG, "Neighboring BSS: " MACSTR
00387                            " freq=%d pri=%d sec=%d",
00388                            MAC2STR(bss->bssid), bss->freq, pri_chan, sec_chan);
00389 
00390                 if (sec_chan) {
00391                         if (pri_freq != pri || sec_freq != sec) {
00392                                 wpa_printf(MSG_DEBUG, "40 MHz pri/sec "
00393                                            "mismatch with BSS " MACSTR
00394                                            " <%d,%d> (chan=%d%c) vs. <%d,%d>",
00395                                            MAC2STR(bss->bssid),
00396                                            pri, sec, pri_chan,
00397                                            sec > pri ? '+' : '-',
00398                                            pri_freq, sec_freq);
00399                                 return 0;
00400                         }
00401                 }
00402 
00403                 /* TODO: 40 MHz intolerant */
00404         }
00405 
00406         return 1;
00407 }
00408 
00409 
00410 static void ieee80211n_check_scan(struct hostapd_iface *iface)
00411 {
00412         struct wpa_scan_results *scan_res;
00413         int oper40;
00414 
00415         /* Check list of neighboring BSSes (from scan) to see whether 40 MHz is
00416          * allowed per IEEE 802.11n/D7.0, 11.14.3.2 */
00417 
00418         iface->scan_cb = NULL;
00419 
00420         scan_res = hostapd_driver_get_scan_results(iface->bss[0]);
00421         if (scan_res == NULL) {
00422                 hostapd_setup_interface_complete(iface, 1);
00423                 return;
00424         }
00425 
00426         if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A)
00427                 oper40 = ieee80211n_check_40mhz_5g(iface, scan_res);
00428         else
00429                 oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res);
00430         wpa_scan_results_free(scan_res);
00431 
00432         if (!oper40) {
00433                 wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on "
00434                            "channel pri=%d sec=%d based on overlapping BSSes",
00435                            iface->conf->channel,
00436                            iface->conf->channel +
00437                            iface->conf->secondary_channel * 4);
00438                 iface->conf->secondary_channel = 0;
00439                 iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
00440         }
00441 
00442         hostapd_setup_interface_complete(iface, 0);
00443 }
00444 
00445 
00446 static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
00447 {
00448         struct wpa_driver_scan_params params;
00449 
00450         if (!iface->conf->secondary_channel)
00451                 return 0; /* HT40 not used */
00452 
00453         wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling "
00454                    "40 MHz channel");
00455         os_memset(&params, 0, sizeof(params));
00456         /* TODO: scan only the needed frequency */
00457         if (hostapd_driver_scan(iface->bss[0], &params) < 0) {
00458                 wpa_printf(MSG_ERROR, "Failed to request a scan of "
00459                            "neighboring BSSes");
00460                 return -1;
00461         }
00462 
00463         iface->scan_cb = ieee80211n_check_scan;
00464         return 1;
00465 }
00466 
00467 
00468 static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface)
00469 {
00470         u16 hw = iface->current_mode->ht_capab;
00471         u16 conf = iface->conf->ht_capab;
00472 
00473         if (!iface->conf->ieee80211n)
00474                 return 1;
00475 
00476         if ((conf & HT_CAP_INFO_LDPC_CODING_CAP) &&
00477             !(hw & HT_CAP_INFO_LDPC_CODING_CAP)) {
00478                 wpa_printf(MSG_ERROR, "Driver does not support configured "
00479                            "HT capability [LDPC]");
00480                 return 0;
00481         }
00482 
00483         if ((conf & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) &&
00484             !(hw & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) {
00485                 wpa_printf(MSG_ERROR, "Driver does not support configured "
00486                            "HT capability [HT40*]");
00487                 return 0;
00488         }
00489 
00490         if ((conf & HT_CAP_INFO_SMPS_MASK) != (hw & HT_CAP_INFO_SMPS_MASK) &&
00491             (conf & HT_CAP_INFO_SMPS_MASK) != HT_CAP_INFO_SMPS_DISABLED) {
00492                 wpa_printf(MSG_ERROR, "Driver does not support configured "
00493                            "HT capability [SMPS-*]");
00494                 return 0;
00495         }
00496 
00497         if ((conf & HT_CAP_INFO_GREEN_FIELD) &&
00498             !(hw & HT_CAP_INFO_GREEN_FIELD)) {
00499                 wpa_printf(MSG_ERROR, "Driver does not support configured "
00500                            "HT capability [GF]");
00501                 return 0;
00502         }
00503 
00504         if ((conf & HT_CAP_INFO_SHORT_GI20MHZ) &&
00505             !(hw & HT_CAP_INFO_SHORT_GI20MHZ)) {
00506                 wpa_printf(MSG_ERROR, "Driver does not support configured "
00507                            "HT capability [SHORT-GI-20]");
00508                 return 0;
00509         }
00510 
00511         if ((conf & HT_CAP_INFO_SHORT_GI40MHZ) &&
00512             !(hw & HT_CAP_INFO_SHORT_GI40MHZ)) {
00513                 wpa_printf(MSG_ERROR, "Driver does not support configured "
00514                            "HT capability [SHORT-GI-40]");
00515                 return 0;
00516         }
00517 
00518         if ((conf & HT_CAP_INFO_TX_STBC) && !(hw & HT_CAP_INFO_TX_STBC)) {
00519                 wpa_printf(MSG_ERROR, "Driver does not support configured "
00520                            "HT capability [TX-STBC]");
00521                 return 0;
00522         }
00523 
00524         if ((conf & HT_CAP_INFO_RX_STBC_MASK) >
00525             (hw & HT_CAP_INFO_RX_STBC_MASK)) {
00526                 wpa_printf(MSG_ERROR, "Driver does not support configured "
00527                            "HT capability [RX-STBC*]");
00528                 return 0;
00529         }
00530 
00531         if ((conf & HT_CAP_INFO_DELAYED_BA) &&
00532             !(hw & HT_CAP_INFO_DELAYED_BA)) {
00533                 wpa_printf(MSG_ERROR, "Driver does not support configured "
00534                            "HT capability [DELAYED-BA]");
00535                 return 0;
00536         }
00537 
00538         if ((conf & HT_CAP_INFO_MAX_AMSDU_SIZE) &&
00539             !(hw & HT_CAP_INFO_MAX_AMSDU_SIZE)) {
00540                 wpa_printf(MSG_ERROR, "Driver does not support configured "
00541                            "HT capability [MAX-AMSDU-7935]");
00542                 return 0;
00543         }
00544 
00545         if ((conf & HT_CAP_INFO_DSSS_CCK40MHZ) &&
00546             !(hw & HT_CAP_INFO_DSSS_CCK40MHZ)) {
00547                 wpa_printf(MSG_ERROR, "Driver does not support configured "
00548                            "HT capability [DSSS_CCK-40]");
00549                 return 0;
00550         }
00551 
00552         if ((conf & HT_CAP_INFO_PSMP_SUPP) && !(hw & HT_CAP_INFO_PSMP_SUPP)) {
00553                 wpa_printf(MSG_ERROR, "Driver does not support configured "
00554                            "HT capability [PSMP]");
00555                 return 0;
00556         }
00557 
00558         if ((conf & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT) &&
00559             !(hw & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT)) {
00560                 wpa_printf(MSG_ERROR, "Driver does not support configured "
00561                            "HT capability [LSIG-TXOP-PROT]");
00562                 return 0;
00563         }
00564 
00565         return 1;
00566 }
00567 
00568 #endif /* CONFIG_IEEE80211N */
00569 
00570 
00571 int hostapd_check_ht_capab(struct hostapd_iface *iface)
00572 {
00573 #ifdef CONFIG_IEEE80211N
00574         int ret;
00575         ret = ieee80211n_check_40mhz(iface);
00576         if (ret)
00577                 return ret;
00578         if (!ieee80211n_allowed_ht40_channel_pair(iface))
00579                 return -1;
00580         if (!ieee80211n_supported_ht_capab(iface))
00581                 return -1;
00582 #endif /* CONFIG_IEEE80211N */
00583 
00584         return 0;
00585 }
00586 
00587 
00597 int hostapd_select_hw_mode(struct hostapd_iface *iface)
00598 {
00599         int i, j, ok;
00600 
00601         if (iface->num_hw_features < 1)
00602                 return -1;
00603 
00604         iface->current_mode = NULL;
00605         for (i = 0; i < iface->num_hw_features; i++) {
00606                 struct hostapd_hw_modes *mode = &iface->hw_features[i];
00607                 if (mode->mode == iface->conf->hw_mode) {
00608                         iface->current_mode = mode;
00609                         break;
00610                 }
00611         }
00612 
00613         if (iface->current_mode == NULL) {
00614                 wpa_printf(MSG_ERROR, "Hardware does not support configured "
00615                            "mode");
00616                 hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
00617                                HOSTAPD_LEVEL_WARNING,
00618                                "Hardware does not support configured mode "
00619                                "(%d)", (int) iface->conf->hw_mode);
00620                 return -1;
00621         }
00622 
00623         ok = 0;
00624         for (j = 0; j < iface->current_mode->num_channels; j++) {
00625                 struct hostapd_channel_data *chan =
00626                         &iface->current_mode->channels[j];
00627                 if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
00628                     (chan->chan == iface->conf->channel)) {
00629                         ok = 1;
00630                         break;
00631                 }
00632         }
00633         if (iface->conf->channel == 0) {
00634                 /* TODO: could request a scan of neighboring BSSes and select
00635                  * the channel automatically */
00636                 wpa_printf(MSG_ERROR, "Channel not configured "
00637                            "(hw_mode/channel in hostapd.conf)");
00638                 return -1;
00639         }
00640         if (ok == 0 && iface->conf->channel != 0) {
00641                 hostapd_logger(iface->bss[0], NULL,
00642                                HOSTAPD_MODULE_IEEE80211,
00643                                HOSTAPD_LEVEL_WARNING,
00644                                "Configured channel (%d) not found from the "
00645                                "channel list of current mode (%d) %s",
00646                                iface->conf->channel,
00647                                iface->current_mode->mode,
00648                                hostapd_hw_mode_txt(iface->current_mode->mode));
00649                 iface->current_mode = NULL;
00650         }
00651 
00652         if (iface->current_mode == NULL) {
00653                 hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
00654                                HOSTAPD_LEVEL_WARNING,
00655                                "Hardware does not support configured channel");
00656                 return -1;
00657         }
00658 
00659         if (hostapd_prepare_rates(iface->bss[0], iface->current_mode)) {
00660                 wpa_printf(MSG_ERROR, "Failed to prepare rates table.");
00661                 hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
00662                                            HOSTAPD_LEVEL_WARNING,
00663                                            "Failed to prepare rates table.");
00664                 return -1;
00665         }
00666 
00667         return 0;
00668 }
00669 
00670 
00671 const char * hostapd_hw_mode_txt(int mode)
00672 {
00673         switch (mode) {
00674         case HOSTAPD_MODE_IEEE80211A:
00675                 return "IEEE 802.11a";
00676         case HOSTAPD_MODE_IEEE80211B:
00677                 return "IEEE 802.11b";
00678         case HOSTAPD_MODE_IEEE80211G:
00679                 return "IEEE 802.11g";
00680         default:
00681                 return "UNKNOWN";
00682         }
00683 }
00684 
00685 
00686 int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan)
00687 {
00688         int i;
00689 
00690         if (!hapd->iface->current_mode)
00691                 return 0;
00692 
00693         for (i = 0; i < hapd->iface->current_mode->num_channels; i++) {
00694                 struct hostapd_channel_data *ch =
00695                         &hapd->iface->current_mode->channels[i];
00696                 if (ch->chan == chan)
00697                         return ch->freq;
00698         }
00699 
00700         return 0;
00701 }
00702 
00703 
00704 int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
00705 {
00706         int i;
00707 
00708         if (!hapd->iface->current_mode)
00709                 return 0;
00710 
00711         for (i = 0; i < hapd->iface->current_mode->num_channels; i++) {
00712                 struct hostapd_channel_data *ch =
00713                         &hapd->iface->current_mode->channels[i];
00714                 if (ch->freq == freq)
00715                         return ch->chan;
00716         }
00717 
00718         return 0;
00719 }
00720 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on Sat Nov 21 23:16:48 2009 for hostapd by  doxygen 1.6.1