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