root/drivers/staging/rtl8188eu/core/rtw_ieee80211.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rtw_get_bit_value_from_ieee_value
  2. rtw_is_cckrates_included
  3. rtw_is_cckratesonly_included
  4. rtw_check_network_type
  5. rtw_set_fixed_ie
  6. rtw_get_ie
  7. rtw_set_supported_rate
  8. rtw_get_rateset_len
  9. rtw_generate_ie
  10. rtw_get_wpa_ie
  11. rtw_get_wpa2_ie
  12. rtw_get_wpa_cipher_suite
  13. rtw_get_wpa2_cipher_suite
  14. rtw_parse_wpa_ie
  15. rtw_parse_wpa2_ie
  16. rtw_get_sec_ie
  17. rtw_is_wps_ie
  18. rtw_get_wps_ie
  19. rtw_get_wps_attr
  20. rtw_get_wps_attr_content
  21. rtw_ieee802_11_parse_vendor_specific
  22. rtw_ieee802_11_parse_elems
  23. rtw_macaddr_cfg
  24. rtw_get_cipher_info
  25. rtw_get_bcn_info
  26. rtw_mcs_rate

   1 // SPDX-License-Identifier: GPL-2.0
   2 /******************************************************************************
   3  *
   4  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
   5  *
   6  ******************************************************************************/
   7 #define _IEEE80211_C
   8 
   9 #include <linux/ieee80211.h>
  10 
  11 #include <drv_types.h>
  12 #include <osdep_intf.h>
  13 #include <ieee80211.h>
  14 #include <wifi.h>
  15 #include <osdep_service.h>
  16 #include <wlan_bssdef.h>
  17 
  18 u8 RTW_WPA_OUI_TYPE[] = { 0x00, 0x50, 0xf2, 1 };
  19 u8 WPA_AUTH_KEY_MGMT_NONE[] = { 0x00, 0x50, 0xf2, 0 };
  20 u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x50, 0xf2, 1 };
  21 u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x50, 0xf2, 2 };
  22 u8 WPA_CIPHER_SUITE_NONE[] = { 0x00, 0x50, 0xf2, 0 };
  23 u8 WPA_CIPHER_SUITE_WEP40[] = { 0x00, 0x50, 0xf2, 1 };
  24 u8 WPA_CIPHER_SUITE_TKIP[] = { 0x00, 0x50, 0xf2, 2 };
  25 u8 WPA_CIPHER_SUITE_WRAP[] = { 0x00, 0x50, 0xf2, 3 };
  26 u8 WPA_CIPHER_SUITE_CCMP[] = { 0x00, 0x50, 0xf2, 4 };
  27 u8 WPA_CIPHER_SUITE_WEP104[] = { 0x00, 0x50, 0xf2, 5 };
  28 
  29 u16 RSN_VERSION_BSD = 1;
  30 u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x0f, 0xac, 1 };
  31 u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x0f, 0xac, 2 };
  32 u8 RSN_CIPHER_SUITE_NONE[] = { 0x00, 0x0f, 0xac, 0 };
  33 u8 RSN_CIPHER_SUITE_WEP40[] = { 0x00, 0x0f, 0xac, 1 };
  34 u8 RSN_CIPHER_SUITE_TKIP[] = { 0x00, 0x0f, 0xac, 2 };
  35 u8 RSN_CIPHER_SUITE_WRAP[] = { 0x00, 0x0f, 0xac, 3 };
  36 u8 RSN_CIPHER_SUITE_CCMP[] = { 0x00, 0x0f, 0xac, 4 };
  37 u8 RSN_CIPHER_SUITE_WEP104[] = { 0x00, 0x0f, 0xac, 5 };
  38 /*  */
  39 /*  for adhoc-master to generate ie and provide supported-rate to fw */
  40 /*  */
  41 
  42 static u8 WIFI_CCKRATES[] = {
  43         IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK,
  44         IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK,
  45         IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK,
  46         IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK
  47 };
  48 
  49 static u8 WIFI_OFDMRATES[] = {
  50          IEEE80211_OFDM_RATE_6MB,
  51          IEEE80211_OFDM_RATE_9MB,
  52          IEEE80211_OFDM_RATE_12MB,
  53          IEEE80211_OFDM_RATE_18MB,
  54          IEEE80211_OFDM_RATE_24MB,
  55          IEEE80211_OFDM_RATE_36MB,
  56          IEEE80211_OFDM_RATE_48MB,
  57          IEEE80211_OFDM_RATE_54MB
  58 };
  59 
  60 int rtw_get_bit_value_from_ieee_value(u8 val)
  61 {
  62         static const unsigned char dot11_rate_table[] = {
  63                 2, 4, 11, 22, 12, 18, 24, 36, 48,
  64                 72, 96, 108, 0}; /*  last element must be zero!! */
  65         int i = 0;
  66 
  67         while (dot11_rate_table[i] != 0) {
  68                 if (dot11_rate_table[i] == val)
  69                         return BIT(i);
  70                 i++;
  71         }
  72         return 0;
  73 }
  74 
  75 bool rtw_is_cckrates_included(u8 *rate)
  76 {
  77         while (*rate) {
  78                 u8 r = *rate & 0x7f;
  79 
  80                 if (r == 2 || r == 4 || r == 11 || r == 22)
  81                         return true;
  82                 rate++;
  83         }
  84 
  85         return false;
  86 }
  87 
  88 bool rtw_is_cckratesonly_included(u8 *rate)
  89 {
  90         while (*rate) {
  91                 u8 r = *rate & 0x7f;
  92 
  93                 if (r != 2 && r != 4 && r != 11 && r != 22)
  94                         return false;
  95                 rate++;
  96         }
  97 
  98         return true;
  99 }
 100 
 101 int rtw_check_network_type(unsigned char *rate, int ratelen, int channel)
 102 {
 103         /*  could be pure B, pure G, or B/G */
 104         if (rtw_is_cckratesonly_included(rate))
 105                 return WIRELESS_11B;
 106         else if (rtw_is_cckrates_included(rate))
 107                 return  WIRELESS_11BG;
 108         else
 109                 return WIRELESS_11G;
 110 }
 111 
 112 u8 *rtw_set_fixed_ie(void *pbuf, unsigned int len, void *source,
 113                      unsigned int *frlen)
 114 {
 115         memcpy(pbuf, source, len);
 116         *frlen = *frlen + len;
 117         return ((u8 *)pbuf) + len;
 118 }
 119 
 120 /*  rtw_set_ie will update frame length */
 121 u8 *rtw_set_ie
 122 (
 123         u8 *pbuf,
 124         int index,
 125         uint len,
 126         u8 *source,
 127         uint *frlen /* frame length */
 128 )
 129 {
 130         *pbuf = (u8)index;
 131 
 132         *(pbuf + 1) = (u8)len;
 133 
 134         if (len > 0)
 135                 memcpy((void *)(pbuf + 2), (void *)source, len);
 136 
 137         *frlen = *frlen + (len + 2);
 138 
 139         return pbuf + len + 2;
 140 }
 141 
 142 /*----------------------------------------------------------------------------
 143 index: the information element id index, limit is the limit for search
 144 -----------------------------------------------------------------------------*/
 145 u8 *rtw_get_ie(u8 *pbuf, int index, uint *len, int limit)
 146 {
 147         int tmp, i;
 148         u8 *p;
 149 
 150         if (limit < 1)
 151                 return NULL;
 152 
 153         p = pbuf;
 154         i = 0;
 155         *len = 0;
 156         while (1) {
 157                 if (*p == index) {
 158                         *len = *(p + 1);
 159                         return p;
 160                 } else {
 161                         tmp = *(p + 1);
 162                         p += (tmp + 2);
 163                         i += (tmp + 2);
 164                 }
 165                 if (i >= limit)
 166                         break;
 167         }
 168         return NULL;
 169 }
 170 
 171 void rtw_set_supported_rate(u8 *SupportedRates, uint mode)
 172 {
 173         memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
 174 
 175         switch (mode) {
 176         case WIRELESS_11B:
 177                 memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
 178                 break;
 179         case WIRELESS_11G:
 180         case WIRELESS_11A:
 181         case WIRELESS_11_5N:
 182         case WIRELESS_11A_5N:/* Todo: no basic rate for ofdm ? */
 183                 memcpy(SupportedRates, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
 184                 break;
 185         case WIRELESS_11BG:
 186         case WIRELESS_11G_24N:
 187         case WIRELESS_11_24N:
 188         case WIRELESS_11BG_24N:
 189                 memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
 190                 memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
 191                 break;
 192         }
 193 }
 194 
 195 uint rtw_get_rateset_len(u8 *rateset)
 196 {
 197         uint i;
 198 
 199         for (i = 0; i < 13; i++)
 200                 if (rateset[i] == 0)
 201                         break;
 202         return i;
 203 }
 204 
 205 int rtw_generate_ie(struct registry_priv *pregistrypriv)
 206 {
 207         u8 wireless_mode;
 208         int rateLen;
 209         uint sz = 0;
 210         struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
 211         u8 *ie = pdev_network->ies;
 212 
 213         /* timestamp will be inserted by hardware */
 214         sz += 8;
 215         ie += sz;
 216 
 217         /* beacon interval : 2bytes */
 218         *(__le16 *)ie = cpu_to_le16((u16)pdev_network->Configuration.BeaconPeriod);/* BCN_INTERVAL; */
 219         sz += 2;
 220         ie += 2;
 221 
 222         /* capability info */
 223         *(u16 *)ie = 0;
 224 
 225         *(__le16 *)ie |= cpu_to_le16(cap_IBSS);
 226 
 227         if (pregistrypriv->preamble == PREAMBLE_SHORT)
 228                 *(__le16 *)ie |= cpu_to_le16(cap_ShortPremble);
 229 
 230         if (pdev_network->Privacy)
 231                 *(__le16 *)ie |= cpu_to_le16(cap_Privacy);
 232 
 233         sz += 2;
 234         ie += 2;
 235 
 236         /* SSID */
 237         ie = rtw_set_ie(ie, _SSID_IE_, pdev_network->ssid.ssid_length, pdev_network->ssid.ssid, &sz);
 238 
 239         /* supported rates */
 240         if (pregistrypriv->wireless_mode == WIRELESS_11ABGN) {
 241                 if (pdev_network->Configuration.DSConfig > 14)
 242                         wireless_mode = WIRELESS_11A_5N;
 243                 else
 244                         wireless_mode = WIRELESS_11BG_24N;
 245         } else {
 246                 wireless_mode = pregistrypriv->wireless_mode;
 247         }
 248 
 249         rtw_set_supported_rate(pdev_network->SupportedRates, wireless_mode);
 250 
 251         rateLen = rtw_get_rateset_len(pdev_network->SupportedRates);
 252 
 253         if (rateLen > 8) {
 254                 ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, pdev_network->SupportedRates, &sz);
 255                 /* ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); */
 256         } else {
 257                 ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, pdev_network->SupportedRates, &sz);
 258         }
 259 
 260         /* DS parameter set */
 261         ie = rtw_set_ie(ie, _DSSET_IE_, 1, (u8 *)&(pdev_network->Configuration.DSConfig), &sz);
 262 
 263         /* IBSS Parameter Set */
 264 
 265         ie = rtw_set_ie(ie, _IBSS_PARA_IE_, 2, (u8 *)&(pdev_network->Configuration.ATIMWindow), &sz);
 266 
 267         if (rateLen > 8)
 268                 ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz);
 269 
 270         return sz;
 271 }
 272 
 273 unsigned char *rtw_get_wpa_ie(unsigned char *pie, uint *wpa_ie_len, int limit)
 274 {
 275         uint len;
 276         u16 val16;
 277         __le16 le_tmp;
 278         static const unsigned char wpa_oui_type[] = {0x00, 0x50, 0xf2, 0x01};
 279         u8 *pbuf = pie;
 280         int limit_new = limit;
 281 
 282         while (1) {
 283                 pbuf = rtw_get_ie(pbuf, _WPA_IE_ID_, &len, limit_new);
 284 
 285                 if (pbuf) {
 286                         /* check if oui matches... */
 287                         if (memcmp((pbuf + 2), wpa_oui_type, sizeof(wpa_oui_type)))
 288                                 goto check_next_ie;
 289 
 290                         /* check version... */
 291                         memcpy((u8 *)&le_tmp, (pbuf + 6), sizeof(val16));
 292 
 293                         val16 = le16_to_cpu(le_tmp);
 294                         if (val16 != 0x0001)
 295                                 goto check_next_ie;
 296                         *wpa_ie_len = *(pbuf + 1);
 297                         return pbuf;
 298                 } else {
 299                         *wpa_ie_len = 0;
 300                         return NULL;
 301                 }
 302 
 303 check_next_ie:
 304                 limit_new = limit - (pbuf - pie) - 2 - len;
 305                 if (limit_new <= 0)
 306                         break;
 307                 pbuf += (2 + len);
 308         }
 309         *wpa_ie_len = 0;
 310         return NULL;
 311 }
 312 
 313 unsigned char *rtw_get_wpa2_ie(unsigned char *pie, uint *rsn_ie_len, int limit)
 314 {
 315         return rtw_get_ie(pie, _WPA2_IE_ID_, rsn_ie_len, limit);
 316 }
 317 
 318 int rtw_get_wpa_cipher_suite(u8 *s)
 319 {
 320         if (!memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN))
 321                 return WPA_CIPHER_NONE;
 322         if (!memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN))
 323                 return WPA_CIPHER_WEP40;
 324         if (!memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN))
 325                 return WPA_CIPHER_TKIP;
 326         if (!memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN))
 327                 return WPA_CIPHER_CCMP;
 328         if (!memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN))
 329                 return WPA_CIPHER_WEP104;
 330 
 331         return 0;
 332 }
 333 
 334 int rtw_get_wpa2_cipher_suite(u8 *s)
 335 {
 336         if (!memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN))
 337                 return WPA_CIPHER_NONE;
 338         if (!memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN))
 339                 return WPA_CIPHER_WEP40;
 340         if (!memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN))
 341                 return WPA_CIPHER_TKIP;
 342         if (!memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN))
 343                 return WPA_CIPHER_CCMP;
 344         if (!memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN))
 345                 return WPA_CIPHER_WEP104;
 346 
 347         return 0;
 348 }
 349 
 350 int rtw_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x)
 351 {
 352         int i, ret = _SUCCESS;
 353         int left, count;
 354         u8 *pos;
 355         u8 SUITE_1X[4] = {0x00, 0x50, 0xf2, 1};
 356 
 357         if (wpa_ie_len <= 0) {
 358                 /* No WPA IE - fail silently */
 359                 return _FAIL;
 360         }
 361 
 362         if ((*wpa_ie != _WPA_IE_ID_) || (*(wpa_ie + 1) != (u8)(wpa_ie_len - 2)) ||
 363             (memcmp(wpa_ie + 2, RTW_WPA_OUI_TYPE, WPA_SELECTOR_LEN)))
 364                 return _FAIL;
 365 
 366         pos = wpa_ie;
 367 
 368         pos += 8;
 369         left = wpa_ie_len - 8;
 370 
 371         /* group_cipher */
 372         if (left >= WPA_SELECTOR_LEN) {
 373                 *group_cipher = rtw_get_wpa_cipher_suite(pos);
 374                 pos += WPA_SELECTOR_LEN;
 375                 left -= WPA_SELECTOR_LEN;
 376         } else if (left > 0) {
 377                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie length mismatch, %u too much", __func__, left));
 378                 return _FAIL;
 379         }
 380 
 381         /* pairwise_cipher */
 382         if (left >= 2) {
 383                 count = get_unaligned_le16(pos);
 384                 pos += 2;
 385                 left -= 2;
 386 
 387                 if (count == 0 || left < count * WPA_SELECTOR_LEN) {
 388                         RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie count botch (pairwise), "
 389                                                 "count %u left %u", __func__, count, left));
 390                         return _FAIL;
 391                 }
 392 
 393                 for (i = 0; i < count; i++) {
 394                         *pairwise_cipher |= rtw_get_wpa_cipher_suite(pos);
 395 
 396                         pos += WPA_SELECTOR_LEN;
 397                         left -= WPA_SELECTOR_LEN;
 398                 }
 399         } else if (left == 1) {
 400                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie too short (for key mgmt)",   __func__));
 401                 return _FAIL;
 402         }
 403 
 404         if (is_8021x) {
 405                 if (left >= 6) {
 406                         pos += 2;
 407                         if (!memcmp(pos, SUITE_1X, 4)) {
 408                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s : there has 802.1x auth\n", __func__));
 409                                 *is_8021x = 1;
 410                         }
 411                 }
 412         }
 413 
 414         return ret;
 415 }
 416 
 417 int rtw_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x)
 418 {
 419         int i, ret = _SUCCESS;
 420         int left, count;
 421         u8 *pos;
 422         u8 SUITE_1X[4] = {0x00, 0x0f, 0xac, 0x01};
 423 
 424         if (rsn_ie_len <= 0) {
 425                 /* No RSN IE - fail silently */
 426                 return _FAIL;
 427         }
 428 
 429         if ((*rsn_ie != _WPA2_IE_ID_) || (*(rsn_ie + 1) != (u8)(rsn_ie_len - 2)))
 430                 return _FAIL;
 431 
 432         pos = rsn_ie;
 433         pos += 4;
 434         left = rsn_ie_len - 4;
 435 
 436         /* group_cipher */
 437         if (left >= RSN_SELECTOR_LEN) {
 438                 *group_cipher = rtw_get_wpa2_cipher_suite(pos);
 439 
 440                 pos += RSN_SELECTOR_LEN;
 441                 left -= RSN_SELECTOR_LEN;
 442 
 443         } else if (left > 0) {
 444                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie length mismatch, %u too much", __func__, left));
 445                 return _FAIL;
 446         }
 447 
 448         /* pairwise_cipher */
 449         if (left >= 2) {
 450                 count = get_unaligned_le16(pos);
 451                 pos += 2;
 452                 left -= 2;
 453 
 454                 if (count == 0 || left < count * RSN_SELECTOR_LEN) {
 455                         RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie count botch (pairwise), "
 456                                                  "count %u left %u", __func__, count, left));
 457                         return _FAIL;
 458                 }
 459 
 460                 for (i = 0; i < count; i++) {
 461                         *pairwise_cipher |= rtw_get_wpa2_cipher_suite(pos);
 462 
 463                         pos += RSN_SELECTOR_LEN;
 464                         left -= RSN_SELECTOR_LEN;
 465                 }
 466 
 467         } else if (left == 1) {
 468                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie too short (for key mgmt)",  __func__));
 469 
 470                 return _FAIL;
 471         }
 472 
 473         if (is_8021x) {
 474                 if (left >= 6) {
 475                         pos += 2;
 476                         if (!memcmp(pos, SUITE_1X, 4)) {
 477                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s (): there has 802.1x auth\n", __func__));
 478                                 *is_8021x = 1;
 479                         }
 480                 }
 481         }
 482         return ret;
 483 }
 484 
 485 void rtw_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, u8 *wpa_ie, u16 *wpa_len)
 486 {
 487         u8 authmode, sec_idx, i;
 488         u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
 489         uint cnt;
 490 
 491         /* Search required WPA or WPA2 IE and copy to sec_ie[] */
 492 
 493         cnt = _TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_;
 494 
 495         sec_idx = 0;
 496 
 497         while (cnt < in_len) {
 498                 authmode = in_ie[cnt];
 499 
 500                 if ((authmode == _WPA_IE_ID_) && (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) {
 501                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
 502                                          ("\n rtw_get_wpa_ie: sec_idx =%d in_ie[cnt+1]+2 =%d\n",
 503                                          sec_idx, in_ie[cnt + 1] + 2));
 504 
 505                                 if (wpa_ie) {
 506                                         memcpy(wpa_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
 507 
 508                                         for (i = 0; i < (in_ie[cnt + 1] + 2); i += 8) {
 509                                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
 510                                                          ("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n",
 511                                                          wpa_ie[i], wpa_ie[i + 1], wpa_ie[i + 2], wpa_ie[i + 3], wpa_ie[i + 4],
 512                                                          wpa_ie[i + 5], wpa_ie[i + 6], wpa_ie[i + 7]));
 513                                         }
 514                                 }
 515 
 516                                 *wpa_len = in_ie[cnt + 1] + 2;
 517                                 cnt += in_ie[cnt + 1] + 2;  /* get next */
 518                 } else {
 519                         if (authmode == _WPA2_IE_ID_) {
 520                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
 521                                          ("\n get_rsn_ie: sec_idx =%d in_ie[cnt+1]+2 =%d\n",
 522                                          sec_idx, in_ie[cnt + 1] + 2));
 523 
 524                                 if (rsn_ie) {
 525                                         memcpy(rsn_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
 526 
 527                                         for (i = 0; i < (in_ie[cnt + 1] + 2); i += 8) {
 528                                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
 529                                                          ("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n",
 530                                                          rsn_ie[i], rsn_ie[i + 1], rsn_ie[i + 2], rsn_ie[i + 3], rsn_ie[i + 4],
 531                                                          rsn_ie[i + 5], rsn_ie[i + 6], rsn_ie[i + 7]));
 532                                                 }
 533                                 }
 534 
 535                                 *rsn_len = in_ie[cnt + 1] + 2;
 536                                 cnt += in_ie[cnt + 1] + 2;  /* get next */
 537                         } else {
 538                                 cnt += in_ie[cnt + 1] + 2;   /* get next */
 539                         }
 540                 }
 541         }
 542 }
 543 
 544 u8 rtw_is_wps_ie(u8 *ie_ptr, uint *wps_ielen)
 545 {
 546         u8 match = false;
 547         u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
 548 
 549         if (!ie_ptr)
 550                 return match;
 551 
 552         eid = ie_ptr[0];
 553 
 554         if ((eid == _WPA_IE_ID_) && (!memcmp(&ie_ptr[2], wps_oui, 4))) {
 555                 *wps_ielen = ie_ptr[1] + 2;
 556                 match = true;
 557         }
 558         return match;
 559 }
 560 
 561 /**
 562  * rtw_get_wps_ie - Search WPS IE from a series of ies
 563  * @in_ie: Address of ies to search
 564  * @in_len: Length limit from in_ie
 565  * @wps_ie: If not NULL and WPS IE is found, WPS IE will be copied to the buf starting from wps_ie
 566  * @wps_ielen: If not NULL and WPS IE is found, will set to the length of the entire WPS IE
 567  *
 568  * Returns: The address of the WPS IE found, or NULL
 569  */
 570 u8 *rtw_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen)
 571 {
 572         uint cnt;
 573         u8 *wpsie_ptr = NULL;
 574         u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
 575 
 576         if (wps_ielen)
 577                 *wps_ielen = 0;
 578 
 579         if (!in_ie || in_len <= 0)
 580                 return wpsie_ptr;
 581 
 582         cnt = 0;
 583 
 584         while (cnt < in_len) {
 585                 eid = in_ie[cnt];
 586 
 587                 if ((eid == _WPA_IE_ID_) && (!memcmp(&in_ie[cnt + 2], wps_oui, 4))) {
 588                         wpsie_ptr = &in_ie[cnt];
 589 
 590                         if (wps_ie)
 591                                 memcpy(wps_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
 592 
 593                         if (wps_ielen)
 594                                 *wps_ielen = in_ie[cnt + 1] + 2;
 595 
 596                         cnt += in_ie[cnt + 1] + 2;
 597 
 598                         break;
 599                 } else {
 600                         cnt += in_ie[cnt + 1] + 2; /* goto next */
 601                 }
 602         }
 603         return wpsie_ptr;
 604 }
 605 
 606 /**
 607  * rtw_get_wps_attr - Search a specific WPS attribute from a given WPS IE
 608  * @wps_ie: Address of WPS IE to search
 609  * @wps_ielen: Length limit from wps_ie
 610  * @target_attr_id: The attribute ID of WPS attribute to search
 611  * @buf_attr: If not NULL and the WPS attribute is found, WPS attribute will be copied to the buf starting from buf_attr
 612  * @len_attr: If not NULL and the WPS attribute is found, will set to the length of the entire WPS attribute
 613  *
 614  * Returns: the address of the specific WPS attribute found, or NULL
 615  */
 616 u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_attr, u32 *len_attr)
 617 {
 618         u8 *attr_ptr = NULL;
 619         u8 *target_attr_ptr = NULL;
 620         u8 wps_oui[4] = {0x00, 0x50, 0xF2, 0x04};
 621 
 622         if (len_attr)
 623                 *len_attr = 0;
 624 
 625         if ((wps_ie[0] != _VENDOR_SPECIFIC_IE_) ||
 626             (memcmp(wps_ie + 2, wps_oui, 4)))
 627                 return attr_ptr;
 628 
 629         /*  6 = 1(Element ID) + 1(Length) + 4(WPS OUI) */
 630         attr_ptr = wps_ie + 6; /* goto first attr */
 631 
 632         while (attr_ptr - wps_ie < wps_ielen) {
 633                 /*  4 = 2(Attribute ID) + 2(Length) */
 634                 u16 attr_id = get_unaligned_be16(attr_ptr);
 635                 u16 attr_data_len = get_unaligned_be16(attr_ptr + 2);
 636                 u16 attr_len = attr_data_len + 4;
 637 
 638                 if (attr_id == target_attr_id) {
 639                         target_attr_ptr = attr_ptr;
 640                         if (buf_attr)
 641                                 memcpy(buf_attr, attr_ptr, attr_len);
 642                         if (len_attr)
 643                                 *len_attr = attr_len;
 644                         break;
 645                 } else {
 646                         attr_ptr += attr_len; /* goto next */
 647                 }
 648         }
 649         return target_attr_ptr;
 650 }
 651 
 652 /**
 653  * rtw_get_wps_attr_content - Search a specific WPS attribute content from a given WPS IE
 654  * @wps_ie: Address of WPS IE to search
 655  * @wps_ielen: Length limit from wps_ie
 656  * @target_attr_id: The attribute ID of WPS attribute to search
 657  * @buf_content: If not NULL and the WPS attribute is found, WPS attribute content will be copied to the buf starting from buf_content
 658  * @len_content: If not NULL and the WPS attribute is found, will set to the length of the WPS attribute content
 659  *
 660  * Returns: the address of the specific WPS attribute content found, or NULL
 661  */
 662 u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_content, uint *len_content)
 663 {
 664         u8 *attr_ptr;
 665         u32 attr_len;
 666 
 667         if (len_content)
 668                 *len_content = 0;
 669 
 670         attr_ptr = rtw_get_wps_attr(wps_ie, wps_ielen, target_attr_id, NULL, &attr_len);
 671 
 672         if (attr_ptr && attr_len) {
 673                 if (buf_content)
 674                         memcpy(buf_content, attr_ptr + 4, attr_len - 4);
 675 
 676                 if (len_content)
 677                         *len_content = attr_len - 4;
 678 
 679                 return attr_ptr + 4;
 680         }
 681 
 682         return NULL;
 683 }
 684 
 685 static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen,
 686                                             struct rtw_ieee802_11_elems *elems,
 687                                             int show_errors)
 688 {
 689         unsigned int oui;
 690 
 691         /* first 3 bytes in vendor specific information element are the IEEE
 692          * OUI of the vendor. The following byte is used a vendor specific
 693          * sub-type. */
 694         if (elen < 4) {
 695                 if (show_errors) {
 696                         DBG_88E("short vendor specific information element ignored (len=%lu)\n",
 697                                 (unsigned long)elen);
 698                 }
 699                 return -1;
 700         }
 701 
 702         oui = RTW_GET_BE24(pos);
 703         switch (oui) {
 704         case OUI_MICROSOFT:
 705                 /* Microsoft/Wi-Fi information elements are further typed and
 706                  * subtyped */
 707                 switch (pos[3]) {
 708                 case 1:
 709                         /* Microsoft OUI (00:50:F2) with OUI Type 1:
 710                          * real WPA information element */
 711                         elems->wpa_ie = pos;
 712                         elems->wpa_ie_len = elen;
 713                         break;
 714                 case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */
 715                         if (elen < 5) {
 716                                 DBG_88E("short WME information element ignored (len=%lu)\n",
 717                                         (unsigned long)elen);
 718                                 return -1;
 719                         }
 720                         switch (pos[4]) {
 721                         case WME_OUI_SUBTYPE_INFORMATION_ELEMENT:
 722                         case WME_OUI_SUBTYPE_PARAMETER_ELEMENT:
 723                                 elems->wme = pos;
 724                                 elems->wme_len = elen;
 725                                 break;
 726                         case WME_OUI_SUBTYPE_TSPEC_ELEMENT:
 727                                 elems->wme_tspec = pos;
 728                                 elems->wme_tspec_len = elen;
 729                                 break;
 730                         default:
 731                                 DBG_88E("unknown WME information element ignored (subtype=%d len=%lu)\n",
 732                                         pos[4], (unsigned long)elen);
 733                                 return -1;
 734                         }
 735                         break;
 736                 case 4:
 737                         /* Wi-Fi Protected Setup (WPS) IE */
 738                         elems->wps_ie = pos;
 739                         elems->wps_ie_len = elen;
 740                         break;
 741                 default:
 742                         DBG_88E("Unknown Microsoft information element ignored (type=%d len=%lu)\n",
 743                                 pos[3], (unsigned long)elen);
 744                         return -1;
 745                 }
 746                 break;
 747 
 748         case OUI_BROADCOM:
 749                 switch (pos[3]) {
 750                 case VENDOR_HT_CAPAB_OUI_TYPE:
 751                         elems->vendor_ht_cap = pos;
 752                         elems->vendor_ht_cap_len = elen;
 753                         break;
 754                 default:
 755                         DBG_88E("Unknown Broadcom information element ignored (type=%d len=%lu)\n",
 756                                 pos[3], (unsigned long)elen);
 757                         return -1;
 758                 }
 759                 break;
 760         default:
 761                 DBG_88E("unknown vendor specific information element ignored (vendor OUI %3phC len=%lu)\n",
 762                         pos, (unsigned long)elen);
 763                 return -1;
 764         }
 765         return 0;
 766 }
 767 
 768 /**
 769  * ieee802_11_parse_elems - Parse information elements in management frames
 770  * @start: Pointer to the start of ies
 771  * @len: Length of IE buffer in octets
 772  * @elems: Data structure for parsed elements
 773  * @show_errors: Whether to show parsing errors in debug log
 774  * Returns: Parsing result
 775  */
 776 enum parse_res rtw_ieee802_11_parse_elems(u8 *start, uint len,
 777                                 struct rtw_ieee802_11_elems *elems,
 778                                 int show_errors)
 779 {
 780         uint left = len;
 781         u8 *pos = start;
 782         int unknown = 0;
 783 
 784         memset(elems, 0, sizeof(*elems));
 785 
 786         while (left >= 2) {
 787                 u8 id, elen;
 788 
 789                 id = *pos++;
 790                 elen = *pos++;
 791                 left -= 2;
 792 
 793                 if (elen > left) {
 794                         if (show_errors) {
 795                                 DBG_88E("IEEE 802.11 element parse failed (id=%d elen=%d left=%lu)\n",
 796                                         id, elen, (unsigned long)left);
 797                         }
 798                         return ParseFailed;
 799                 }
 800 
 801                 switch (id) {
 802                 case WLAN_EID_SSID:
 803                         elems->ssid = pos;
 804                         elems->ssid_len = elen;
 805                         break;
 806                 case WLAN_EID_SUPP_RATES:
 807                         elems->supp_rates = pos;
 808                         elems->supp_rates_len = elen;
 809                         break;
 810                 case WLAN_EID_FH_PARAMS:
 811                         elems->fh_params = pos;
 812                         elems->fh_params_len = elen;
 813                         break;
 814                 case WLAN_EID_DS_PARAMS:
 815                         elems->ds_params = pos;
 816                         elems->ds_params_len = elen;
 817                         break;
 818                 case WLAN_EID_CF_PARAMS:
 819                         elems->cf_params = pos;
 820                         elems->cf_params_len = elen;
 821                         break;
 822                 case WLAN_EID_TIM:
 823                         elems->tim = pos;
 824                         elems->tim_len = elen;
 825                         break;
 826                 case WLAN_EID_IBSS_PARAMS:
 827                         elems->ibss_params = pos;
 828                         elems->ibss_params_len = elen;
 829                         break;
 830                 case WLAN_EID_CHALLENGE:
 831                         elems->challenge = pos;
 832                         elems->challenge_len = elen;
 833                         break;
 834                 case WLAN_EID_ERP_INFO:
 835                         elems->erp_info = pos;
 836                         elems->erp_info_len = elen;
 837                         break;
 838                 case WLAN_EID_EXT_SUPP_RATES:
 839                         elems->ext_supp_rates = pos;
 840                         elems->ext_supp_rates_len = elen;
 841                         break;
 842                 case WLAN_EID_VENDOR_SPECIFIC:
 843                         if (rtw_ieee802_11_parse_vendor_specific(pos, elen, elems, show_errors))
 844                                 unknown++;
 845                         break;
 846                 case WLAN_EID_RSN:
 847                         elems->rsn_ie = pos;
 848                         elems->rsn_ie_len = elen;
 849                         break;
 850                 case WLAN_EID_PWR_CAPABILITY:
 851                         elems->power_cap = pos;
 852                         elems->power_cap_len = elen;
 853                         break;
 854                 case WLAN_EID_SUPPORTED_CHANNELS:
 855                         elems->supp_channels = pos;
 856                         elems->supp_channels_len = elen;
 857                         break;
 858                 case WLAN_EID_MOBILITY_DOMAIN:
 859                         elems->mdie = pos;
 860                         elems->mdie_len = elen;
 861                         break;
 862                 case WLAN_EID_FAST_BSS_TRANSITION:
 863                         elems->ftie = pos;
 864                         elems->ftie_len = elen;
 865                         break;
 866                 case WLAN_EID_TIMEOUT_INTERVAL:
 867                         elems->timeout_int = pos;
 868                         elems->timeout_int_len = elen;
 869                         break;
 870                 case WLAN_EID_HT_CAPABILITY:
 871                         elems->ht_capabilities = pos;
 872                         elems->ht_capabilities_len = elen;
 873                         break;
 874                 case WLAN_EID_HT_OPERATION:
 875                         elems->ht_operation = pos;
 876                         elems->ht_operation_len = elen;
 877                         break;
 878                 default:
 879                         unknown++;
 880                         if (!show_errors)
 881                                 break;
 882                         DBG_88E("IEEE 802.11 element parse ignored unknown element (id=%d elen=%d)\n",
 883                                 id, elen);
 884                         break;
 885                 }
 886                 left -= elen;
 887                 pos += elen;
 888         }
 889         if (left)
 890                 return ParseFailed;
 891         return unknown ? ParseUnknown : ParseOK;
 892 }
 893 
 894 void rtw_macaddr_cfg(u8 *mac_addr)
 895 {
 896         u8 mac[ETH_ALEN];
 897 
 898         if (!mac_addr)
 899                 return;
 900 
 901         if (rtw_initmac && mac_pton(rtw_initmac, mac)) {
 902                 /* Users specify the mac address */
 903                 ether_addr_copy(mac_addr, mac);
 904         } else {
 905                 /* Use the mac address stored in the Efuse */
 906                 ether_addr_copy(mac, mac_addr);
 907         }
 908 
 909         if (is_broadcast_ether_addr(mac) || is_zero_ether_addr(mac)) {
 910                 eth_random_addr(mac_addr);
 911                 DBG_88E("MAC Address from efuse error, assign random one !!!\n");
 912         }
 913 
 914         DBG_88E("%s MAC Address  = %pM\n", __func__, mac_addr);
 915 }
 916 
 917 static int rtw_get_cipher_info(struct wlan_network *pnetwork)
 918 {
 919         uint wpa_ielen;
 920         unsigned char *pbuf;
 921         int group_cipher = 0, pairwise_cipher = 0, is8021x = 0;
 922         int ret = _FAIL;
 923 
 924         pbuf = rtw_get_wpa_ie(&pnetwork->network.ies[12], &wpa_ielen, pnetwork->network.ie_length - 12);
 925 
 926         if (pbuf && (wpa_ielen > 0)) {
 927                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: wpa_ielen: %d", __func__, wpa_ielen));
 928                 if (rtw_parse_wpa_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is8021x) == _SUCCESS) {
 929                         pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
 930                         pnetwork->BcnInfo.group_cipher = group_cipher;
 931                         pnetwork->BcnInfo.is_8021x = is8021x;
 932                         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: pnetwork->pairwise_cipher: %d, is_8021x is %d",
 933                                  __func__, pnetwork->BcnInfo.pairwise_cipher, pnetwork->BcnInfo.is_8021x));
 934                         ret = _SUCCESS;
 935                 }
 936         } else {
 937                 pbuf = rtw_get_wpa2_ie(&pnetwork->network.ies[12], &wpa_ielen, pnetwork->network.ie_length - 12);
 938 
 939                 if (pbuf && (wpa_ielen > 0)) {
 940                         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("get RSN IE\n"));
 941                         if (rtw_parse_wpa2_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is8021x) == _SUCCESS) {
 942                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("get RSN IE  OK!!!\n"));
 943                                 pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
 944                                 pnetwork->BcnInfo.group_cipher = group_cipher;
 945                                 pnetwork->BcnInfo.is_8021x = is8021x;
 946                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: pnetwork->pairwise_cipher: %d,"
 947                                                         "pnetwork->group_cipher is %d, is_8021x is %d", __func__, pnetwork->BcnInfo.pairwise_cipher,
 948                                                         pnetwork->BcnInfo.group_cipher, pnetwork->BcnInfo.is_8021x));
 949                                 ret = _SUCCESS;
 950                         }
 951                 }
 952         }
 953 
 954         return ret;
 955 }
 956 
 957 void rtw_get_bcn_info(struct wlan_network *pnetwork)
 958 {
 959         unsigned short cap = 0;
 960         u8 bencrypt = 0;
 961         __le16 le_tmp;
 962         u16 wpa_len = 0, rsn_len = 0;
 963         struct HT_info_element *pht_info = NULL;
 964         uint len;
 965         unsigned char *p;
 966 
 967         memcpy(&le_tmp, rtw_get_capability_from_ie(pnetwork->network.ies), 2);
 968         cap = le16_to_cpu(le_tmp);
 969         if (cap & WLAN_CAPABILITY_PRIVACY) {
 970                 bencrypt = 1;
 971                 pnetwork->network.Privacy = 1;
 972         } else {
 973                 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS;
 974         }
 975         rtw_get_sec_ie(pnetwork->network.ies, pnetwork->network.ie_length, NULL, &rsn_len, NULL, &wpa_len);
 976         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: ssid =%s\n", __func__, pnetwork->network.ssid.ssid));
 977         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: wpa_len =%d rsn_len =%d\n", __func__, wpa_len, rsn_len));
 978         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: ssid =%s\n", __func__, pnetwork->network.ssid.ssid));
 979         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: wpa_len =%d rsn_len =%d\n", __func__, wpa_len, rsn_len));
 980 
 981         if (rsn_len > 0) {
 982                 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA2;
 983         } else if (wpa_len > 0) {
 984                 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA;
 985         } else {
 986                 if (bencrypt)
 987                         pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WEP;
 988         }
 989         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: pnetwork->encryp_protocol is %x\n",
 990                  pnetwork->BcnInfo.encryp_protocol));
 991         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: pnetwork->encryp_protocol is %x\n",
 992                  pnetwork->BcnInfo.encryp_protocol));
 993         rtw_get_cipher_info(pnetwork);
 994 
 995         /* get bwmode and ch_offset */
 996         /* parsing HT_CAP_IE */
 997         p = rtw_get_ie(pnetwork->network.ies + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pnetwork->network.ie_length - _FIXED_IE_LENGTH_);
 998         if (p && len > 0) {
 999                 struct ieee80211_ht_cap *ht_cap =
1000                         (struct ieee80211_ht_cap *)(p + 2);
1001 
1002                 pnetwork->BcnInfo.ht_cap_info = le16_to_cpu(ht_cap->cap_info);
1003         } else {
1004                 pnetwork->BcnInfo.ht_cap_info = 0;
1005         }
1006         /* parsing HT_INFO_IE */
1007         p = rtw_get_ie(pnetwork->network.ies + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, pnetwork->network.ie_length - _FIXED_IE_LENGTH_);
1008         if (p && len > 0) {
1009                 pht_info = (struct HT_info_element *)(p + 2);
1010                 pnetwork->BcnInfo.ht_info_infos_0 = pht_info->infos[0];
1011         } else {
1012                 pnetwork->BcnInfo.ht_info_infos_0 = 0;
1013         }
1014 }
1015 
1016 /* show MCS rate, unit: 100Kbps */
1017 u16 rtw_mcs_rate(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, unsigned char *MCS_rate)
1018 {
1019         u16 max_rate = 0;
1020 
1021         if (rf_type == RF_1T1R) {
1022                 if (MCS_rate[0] & BIT(7))
1023                         max_rate = (bw_40MHz) ? ((short_GI_40) ? 1500 : 1350) : ((short_GI_20) ? 722 : 650);
1024                 else if (MCS_rate[0] & BIT(6))
1025                         max_rate = (bw_40MHz) ? ((short_GI_40) ? 1350 : 1215) : ((short_GI_20) ? 650 : 585);
1026                 else if (MCS_rate[0] & BIT(5))
1027                         max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : ((short_GI_20) ? 578 : 520);
1028                 else if (MCS_rate[0] & BIT(4))
1029                         max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : ((short_GI_20) ? 433 : 390);
1030                 else if (MCS_rate[0] & BIT(3))
1031                         max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : ((short_GI_20) ? 289 : 260);
1032                 else if (MCS_rate[0] & BIT(2))
1033                         max_rate = (bw_40MHz) ? ((short_GI_40) ? 450 : 405) : ((short_GI_20) ? 217 : 195);
1034                 else if (MCS_rate[0] & BIT(1))
1035                         max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : ((short_GI_20) ? 144 : 130);
1036                 else if (MCS_rate[0] & BIT(0))
1037                         max_rate = (bw_40MHz) ? ((short_GI_40) ? 150 : 135) : ((short_GI_20) ? 72 : 65);
1038         } else {
1039                 if (MCS_rate[1]) {
1040                         if (MCS_rate[1] & BIT(7))
1041                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 3000 : 2700) : ((short_GI_20) ? 1444 : 1300);
1042                         else if (MCS_rate[1] & BIT(6))
1043                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 2700 : 2430) : ((short_GI_20) ? 1300 : 1170);
1044                         else if (MCS_rate[1] & BIT(5))
1045                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 2400 : 2160) : ((short_GI_20) ? 1156 : 1040);
1046                         else if (MCS_rate[1] & BIT(4))
1047                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 1800 : 1620) : ((short_GI_20) ? 867 : 780);
1048                         else if (MCS_rate[1] & BIT(3))
1049                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : ((short_GI_20) ? 578 : 520);
1050                         else if (MCS_rate[1] & BIT(2))
1051                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : ((short_GI_20) ? 433 : 390);
1052                         else if (MCS_rate[1] & BIT(1))
1053                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : ((short_GI_20) ? 289 : 260);
1054                         else if (MCS_rate[1] & BIT(0))
1055                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : ((short_GI_20) ? 144 : 130);
1056                 } else {
1057                         if (MCS_rate[0] & BIT(7))
1058                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 1500 : 1350) : ((short_GI_20) ? 722 : 650);
1059                         else if (MCS_rate[0] & BIT(6))
1060                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 1350 : 1215) : ((short_GI_20) ? 650 : 585);
1061                         else if (MCS_rate[0] & BIT(5))
1062                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : ((short_GI_20) ? 578 : 520);
1063                         else if (MCS_rate[0] & BIT(4))
1064                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : ((short_GI_20) ? 433 : 390);
1065                         else if (MCS_rate[0] & BIT(3))
1066                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : ((short_GI_20) ? 289 : 260);
1067                         else if (MCS_rate[0] & BIT(2))
1068                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 450 : 405) : ((short_GI_20) ? 217 : 195);
1069                         else if (MCS_rate[0] & BIT(1))
1070                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : ((short_GI_20) ? 144 : 130);
1071                         else if (MCS_rate[0] & BIT(0))
1072                                 max_rate = (bw_40MHz) ? ((short_GI_40) ? 150 : 135) : ((short_GI_20) ? 72 : 65);
1073                 }
1074         }
1075         return max_rate;
1076 }

/* [<][>][^][v][top][bottom][index][help] */