1 /******************************************************************************
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
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.
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
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 ******************************************************************************/
22 #include <drv_types.h>
23 #include <ieee80211.h>
25 #include <osdep_service.h>
26 #include <wlan_bssdef.h>
27 #include <usb_osintf.h>
29 u8 RTW_WPA_OUI_TYPE
[] = { 0x00, 0x50, 0xf2, 1 };
30 u16 RTW_WPA_VERSION
= 1;
31 u8 WPA_AUTH_KEY_MGMT_NONE
[] = { 0x00, 0x50, 0xf2, 0 };
32 u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X
[] = { 0x00, 0x50, 0xf2, 1 };
33 u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X
[] = { 0x00, 0x50, 0xf2, 2 };
34 u8 WPA_CIPHER_SUITE_NONE
[] = { 0x00, 0x50, 0xf2, 0 };
35 u8 WPA_CIPHER_SUITE_WEP40
[] = { 0x00, 0x50, 0xf2, 1 };
36 u8 WPA_CIPHER_SUITE_TKIP
[] = { 0x00, 0x50, 0xf2, 2 };
37 u8 WPA_CIPHER_SUITE_WRAP
[] = { 0x00, 0x50, 0xf2, 3 };
38 u8 WPA_CIPHER_SUITE_CCMP
[] = { 0x00, 0x50, 0xf2, 4 };
39 u8 WPA_CIPHER_SUITE_WEP104
[] = { 0x00, 0x50, 0xf2, 5 };
41 u16 RSN_VERSION_BSD
= 1;
42 u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X
[] = { 0x00, 0x0f, 0xac, 1 };
43 u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X
[] = { 0x00, 0x0f, 0xac, 2 };
44 u8 RSN_CIPHER_SUITE_NONE
[] = { 0x00, 0x0f, 0xac, 0 };
45 u8 RSN_CIPHER_SUITE_WEP40
[] = { 0x00, 0x0f, 0xac, 1 };
46 u8 RSN_CIPHER_SUITE_TKIP
[] = { 0x00, 0x0f, 0xac, 2 };
47 u8 RSN_CIPHER_SUITE_WRAP
[] = { 0x00, 0x0f, 0xac, 3 };
48 u8 RSN_CIPHER_SUITE_CCMP
[] = { 0x00, 0x0f, 0xac, 4 };
49 u8 RSN_CIPHER_SUITE_WEP104
[] = { 0x00, 0x0f, 0xac, 5 };
51 /* for adhoc-master to generate ie and provide supported-rate to fw */
54 static u8 WIFI_CCKRATES
[] = {
55 (IEEE80211_CCK_RATE_1MB
| IEEE80211_BASIC_RATE_MASK
),
56 (IEEE80211_CCK_RATE_2MB
| IEEE80211_BASIC_RATE_MASK
),
57 (IEEE80211_CCK_RATE_5MB
| IEEE80211_BASIC_RATE_MASK
),
58 (IEEE80211_CCK_RATE_11MB
| IEEE80211_BASIC_RATE_MASK
)
61 static u8 WIFI_OFDMRATES
[] = {
62 (IEEE80211_OFDM_RATE_6MB
),
63 (IEEE80211_OFDM_RATE_9MB
),
64 (IEEE80211_OFDM_RATE_12MB
),
65 (IEEE80211_OFDM_RATE_18MB
),
66 (IEEE80211_OFDM_RATE_24MB
),
67 IEEE80211_OFDM_RATE_36MB
,
68 IEEE80211_OFDM_RATE_48MB
,
69 IEEE80211_OFDM_RATE_54MB
73 int rtw_get_bit_value_from_ieee_value(u8 val
)
75 unsigned char dot11_rate_table
[] = {
76 2, 4, 11, 22, 12, 18, 24, 36, 48,
77 72, 96, 108, 0}; /* last element must be zero!! */
80 while (dot11_rate_table
[i
] != 0) {
81 if (dot11_rate_table
[i
] == val
)
88 uint
rtw_is_cckrates_included(u8
*rate
)
92 while (rate
[i
] != 0) {
93 if ((((rate
[i
]) & 0x7f) == 2) || (((rate
[i
]) & 0x7f) == 4) ||
94 (((rate
[i
]) & 0x7f) == 11) || (((rate
[i
]) & 0x7f) == 22))
101 uint
rtw_is_cckratesonly_included(u8
*rate
)
105 while (rate
[i
] != 0) {
106 if ((((rate
[i
]) & 0x7f) != 2) && (((rate
[i
]) & 0x7f) != 4) &&
107 (((rate
[i
]) & 0x7f) != 11) && (((rate
[i
]) & 0x7f) != 22))
115 int rtw_check_network_type(unsigned char *rate
, int ratelen
, int channel
)
118 if ((rtw_is_cckrates_included(rate
)) == true)
119 return WIRELESS_INVALID
;
122 } else { /* could be pure B, pure G, or B/G */
123 if ((rtw_is_cckratesonly_included(rate
)) == true)
125 else if ((rtw_is_cckrates_included(rate
)) == true)
126 return WIRELESS_11BG
;
132 u8
*rtw_set_fixed_ie(unsigned char *pbuf
, unsigned int len
, unsigned char *source
,
135 memcpy((void *)pbuf
, (void *)source
, len
);
136 *frlen
= *frlen
+ len
;
140 /* rtw_set_ie will update frame length */
147 uint
*frlen
/* frame length */
153 *(pbuf
+ 1) = (u8
)len
;
156 memcpy((void *)(pbuf
+ 2), (void *)source
, len
);
158 *frlen
= *frlen
+ (len
+ 2);
161 return pbuf
+ len
+ 2;
164 inline u8
*rtw_set_ie_ch_switch (u8
*buf
, u32
*buf_len
, u8 ch_switch_mode
,
165 u8 new_ch
, u8 ch_switch_cnt
)
169 ie_data
[0] = ch_switch_mode
;
171 ie_data
[2] = ch_switch_cnt
;
172 return rtw_set_ie(buf
, WLAN_EID_CHANNEL_SWITCH
, 3, ie_data
, buf_len
);
175 inline u8
secondary_ch_offset_to_hal_ch_offset(u8 ch_offset
)
177 if (ch_offset
== SCN
)
178 return HAL_PRIME_CHNL_OFFSET_DONT_CARE
;
179 else if (ch_offset
== SCA
)
180 return HAL_PRIME_CHNL_OFFSET_UPPER
;
181 else if (ch_offset
== SCB
)
182 return HAL_PRIME_CHNL_OFFSET_LOWER
;
184 return HAL_PRIME_CHNL_OFFSET_DONT_CARE
;
187 inline u8
hal_ch_offset_to_secondary_ch_offset(u8 ch_offset
)
189 if (ch_offset
== HAL_PRIME_CHNL_OFFSET_DONT_CARE
)
191 else if (ch_offset
== HAL_PRIME_CHNL_OFFSET_LOWER
)
193 else if (ch_offset
== HAL_PRIME_CHNL_OFFSET_UPPER
)
199 inline u8
*rtw_set_ie_secondary_ch_offset(u8
*buf
, u32
*buf_len
, u8 secondary_ch_offset
)
201 return rtw_set_ie(buf
, WLAN_EID_SECONDARY_CHANNEL_OFFSET
, 1, &secondary_ch_offset
, buf_len
);
204 inline u8
*rtw_set_ie_mesh_ch_switch_parm(u8
*buf
, u32
*buf_len
, u8 ttl
,
205 u8 flags
, u16 reason
, u16 precedence
)
211 RTW_PUT_LE16((u8
*)&ie_data
[2], reason
);
212 RTW_PUT_LE16((u8
*)&ie_data
[4], precedence
);
214 return rtw_set_ie(buf
, 0x118, 6, ie_data
, buf_len
);
217 /*----------------------------------------------------------------------------
218 index: the information element id index, limit is the limit for search
219 -----------------------------------------------------------------------------*/
220 u8
*rtw_get_ie(u8
*pbuf
, int index
, int *len
, int limit
)
250 * rtw_get_ie_ex - Search specific IE from a series of IEs
251 * @in_ie: Address of IEs to search
252 * @in_len: Length limit from in_ie
253 * @eid: Element ID to match
255 * @oui_len: OUI length
256 * @ie: If not NULL and the specific IE is found, the IE will be copied to the buf starting from the specific IE
257 * @ielen: If not NULL and the specific IE is found, will set to the length of the entire IE
259 * Returns: The address of the specific IE found, or NULL
261 u8
*rtw_get_ie_ex(u8
*in_ie
, uint in_len
, u8 eid
, u8
*oui
, u8 oui_len
, u8
*ie
, uint
*ielen
)
264 u8
*target_ie
= NULL
;
270 if (!in_ie
|| in_len
<= 0)
275 while (cnt
< in_len
) {
276 if (eid
== in_ie
[cnt
] && (!oui
|| _rtw_memcmp(&in_ie
[cnt
+2], oui
, oui_len
))) {
277 target_ie
= &in_ie
[cnt
];
280 memcpy(ie
, &in_ie
[cnt
], in_ie
[cnt
+1]+2);
283 *ielen
= in_ie
[cnt
+1]+2;
287 cnt
+= in_ie
[cnt
+1]+2; /* goto next */
294 * rtw_ies_remove_ie - Find matching IEs and remove
295 * @ies: Address of IEs to search
296 * @ies_len: Pointer of length of ies, will update to new length
297 * @offset: The offset to start scarch
298 * @eid: Element ID to match
300 * @oui_len: OUI length
302 * Returns: _SUCCESS: ies is updated, _FAIL: not updated
304 int rtw_ies_remove_ie(u8
*ies
, uint
*ies_len
, uint offset
, u8 eid
, u8
*oui
, u8 oui_len
)
312 if (!ies
|| !ies_len
|| *ies_len
<= offset
)
315 start
= ies
+ offset
;
316 search_len
= *ies_len
- offset
;
319 target_ie
= rtw_get_ie_ex(start
, search_len
, eid
, oui
, oui_len
, NULL
, &target_ielen
);
320 if (target_ie
&& target_ielen
) {
321 u8 buf
[MAX_IE_SZ
] = {0};
322 u8
*remain_ies
= target_ie
+ target_ielen
;
323 uint remain_len
= search_len
- (remain_ies
- start
);
325 memcpy(buf
, remain_ies
, remain_len
);
326 memcpy(target_ie
, buf
, remain_len
);
327 *ies_len
= *ies_len
- target_ielen
;
331 search_len
= remain_len
;
340 void rtw_set_supported_rate(u8
*SupportedRates
, uint mode
)
344 _rtw_memset(SupportedRates
, 0, NDIS_802_11_LENGTH_RATES_EX
);
348 memcpy(SupportedRates
, WIFI_CCKRATES
, IEEE80211_CCK_RATE_LEN
);
353 case WIRELESS_11A_5N
:/* Todo: no basic rate for ofdm ? */
354 memcpy(SupportedRates
, WIFI_OFDMRATES
, IEEE80211_NUM_OFDM_RATESLEN
);
357 case WIRELESS_11G_24N
:
358 case WIRELESS_11_24N
:
359 case WIRELESS_11BG_24N
:
360 memcpy(SupportedRates
, WIFI_CCKRATES
, IEEE80211_CCK_RATE_LEN
);
361 memcpy(SupportedRates
+ IEEE80211_CCK_RATE_LEN
, WIFI_OFDMRATES
, IEEE80211_NUM_OFDM_RATESLEN
);
367 uint
rtw_get_rateset_len(u8
*rateset
)
372 if ((rateset
[i
]) == 0)
382 int rtw_generate_ie(struct registry_priv
*pregistrypriv
)
386 struct wlan_bssid_ex
*pdev_network
= &pregistrypriv
->dev_network
;
387 u8
*ie
= pdev_network
->IEs
;
391 /* timestamp will be inserted by hardware */
395 /* beacon interval : 2bytes */
396 *(__le16
*)ie
= cpu_to_le16((u16
)pdev_network
->Configuration
.BeaconPeriod
);/* BCN_INTERVAL; */
400 /* capability info */
403 *(__le16
*)ie
|= cpu_to_le16(cap_IBSS
);
405 if (pregistrypriv
->preamble
== PREAMBLE_SHORT
)
406 *(__le16
*)ie
|= cpu_to_le16(cap_ShortPremble
);
408 if (pdev_network
->Privacy
)
409 *(__le16
*)ie
|= cpu_to_le16(cap_Privacy
);
415 ie
= rtw_set_ie(ie
, _SSID_IE_
, pdev_network
->Ssid
.SsidLength
, pdev_network
->Ssid
.Ssid
, &sz
);
417 /* supported rates */
418 if (pregistrypriv
->wireless_mode
== WIRELESS_11ABGN
) {
419 if (pdev_network
->Configuration
.DSConfig
> 14)
420 wireless_mode
= WIRELESS_11A_5N
;
422 wireless_mode
= WIRELESS_11BG_24N
;
424 wireless_mode
= pregistrypriv
->wireless_mode
;
427 rtw_set_supported_rate(pdev_network
->SupportedRates
, wireless_mode
);
429 rateLen
= rtw_get_rateset_len(pdev_network
->SupportedRates
);
432 ie
= rtw_set_ie(ie
, _SUPPORTEDRATES_IE_
, 8, pdev_network
->SupportedRates
, &sz
);
433 /* ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); */
435 ie
= rtw_set_ie(ie
, _SUPPORTEDRATES_IE_
, rateLen
, pdev_network
->SupportedRates
, &sz
);
438 /* DS parameter set */
439 ie
= rtw_set_ie(ie
, _DSSET_IE_
, 1, (u8
*)&(pdev_network
->Configuration
.DSConfig
), &sz
);
441 /* IBSS Parameter Set */
443 ie
= rtw_set_ie(ie
, _IBSS_PARA_IE_
, 2, (u8
*)&(pdev_network
->Configuration
.ATIMWindow
), &sz
);
446 ie
= rtw_set_ie(ie
, _EXT_SUPPORTEDRATES_IE_
, (rateLen
- 8), (pdev_network
->SupportedRates
+ 8), &sz
);
452 unsigned char *rtw_get_wpa_ie(unsigned char *pie
, int *wpa_ie_len
, int limit
)
457 unsigned char wpa_oui_type
[] = {0x00, 0x50, 0xf2, 0x01};
459 int limit_new
= limit
;
462 pbuf
= rtw_get_ie(pbuf
, _WPA_IE_ID_
, &len
, limit_new
);
465 /* check if oui matches... */
466 if (_rtw_memcmp((pbuf
+ 2), wpa_oui_type
, sizeof (wpa_oui_type
)) == false)
469 /* check version... */
470 memcpy((u8
*)&le_tmp
, (pbuf
+ 6), sizeof(val16
));
472 val16
= le16_to_cpu(le_tmp
);
475 *wpa_ie_len
= *(pbuf
+ 1);
483 limit_new
= limit
- (pbuf
- pie
) - 2 - len
;
492 unsigned char *rtw_get_wpa2_ie(unsigned char *pie
, int *rsn_ie_len
, int limit
)
495 return rtw_get_ie(pie
, _WPA2_IE_ID_
, rsn_ie_len
, limit
);
498 int rtw_get_wpa_cipher_suite(u8
*s
)
500 if (_rtw_memcmp(s
, WPA_CIPHER_SUITE_NONE
, WPA_SELECTOR_LEN
) == true)
501 return WPA_CIPHER_NONE
;
502 if (_rtw_memcmp(s
, WPA_CIPHER_SUITE_WEP40
, WPA_SELECTOR_LEN
) == true)
503 return WPA_CIPHER_WEP40
;
504 if (_rtw_memcmp(s
, WPA_CIPHER_SUITE_TKIP
, WPA_SELECTOR_LEN
) == true)
505 return WPA_CIPHER_TKIP
;
506 if (_rtw_memcmp(s
, WPA_CIPHER_SUITE_CCMP
, WPA_SELECTOR_LEN
) == true)
507 return WPA_CIPHER_CCMP
;
508 if (_rtw_memcmp(s
, WPA_CIPHER_SUITE_WEP104
, WPA_SELECTOR_LEN
) == true)
509 return WPA_CIPHER_WEP104
;
514 int rtw_get_wpa2_cipher_suite(u8
*s
)
516 if (_rtw_memcmp(s
, RSN_CIPHER_SUITE_NONE
, RSN_SELECTOR_LEN
) == true)
517 return WPA_CIPHER_NONE
;
518 if (_rtw_memcmp(s
, RSN_CIPHER_SUITE_WEP40
, RSN_SELECTOR_LEN
) == true)
519 return WPA_CIPHER_WEP40
;
520 if (_rtw_memcmp(s
, RSN_CIPHER_SUITE_TKIP
, RSN_SELECTOR_LEN
) == true)
521 return WPA_CIPHER_TKIP
;
522 if (_rtw_memcmp(s
, RSN_CIPHER_SUITE_CCMP
, RSN_SELECTOR_LEN
) == true)
523 return WPA_CIPHER_CCMP
;
524 if (_rtw_memcmp(s
, RSN_CIPHER_SUITE_WEP104
, RSN_SELECTOR_LEN
) == true)
525 return WPA_CIPHER_WEP104
;
531 int rtw_parse_wpa_ie(u8
*wpa_ie
, int wpa_ie_len
, int *group_cipher
, int *pairwise_cipher
, int *is_8021x
)
533 int i
, ret
= _SUCCESS
;
536 u8 SUITE_1X
[4] = {0x00, 0x50, 0xf2, 1};
538 if (wpa_ie_len
<= 0) {
539 /* No WPA IE - fail silently */
544 if ((*wpa_ie
!= _WPA_IE_ID_
) || (*(wpa_ie
+1) != (u8
)(wpa_ie_len
- 2)) ||
545 (_rtw_memcmp(wpa_ie
+2, RTW_WPA_OUI_TYPE
, WPA_SELECTOR_LEN
) != true))
551 left
= wpa_ie_len
- 8;
555 if (left
>= WPA_SELECTOR_LEN
) {
556 *group_cipher
= rtw_get_wpa_cipher_suite(pos
);
557 pos
+= WPA_SELECTOR_LEN
;
558 left
-= WPA_SELECTOR_LEN
;
559 } else if (left
> 0) {
560 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_err_
, ("%s: ie length mismatch, %u too much", __func__
, left
));
564 /* pairwise_cipher */
566 count
= RTW_GET_LE16(pos
);
570 if (count
== 0 || left
< count
* WPA_SELECTOR_LEN
) {
571 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_err_
, ("%s: ie count botch (pairwise), "
572 "count %u left %u", __func__
, count
, left
));
576 for (i
= 0; i
< count
; i
++) {
577 *pairwise_cipher
|= rtw_get_wpa_cipher_suite(pos
);
579 pos
+= WPA_SELECTOR_LEN
;
580 left
-= WPA_SELECTOR_LEN
;
582 } else if (left
== 1) {
583 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_err_
, ("%s: ie too short (for key mgmt)", __func__
));
590 if (_rtw_memcmp(pos
, SUITE_1X
, 4) == 1) {
591 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
, ("%s : there has 802.1x auth\n", __func__
));
600 int rtw_parse_wpa2_ie(u8
*rsn_ie
, int rsn_ie_len
, int *group_cipher
, int *pairwise_cipher
, int *is_8021x
)
602 int i
, ret
= _SUCCESS
;
605 u8 SUITE_1X
[4] = {0x00, 0x0f, 0xac, 0x01};
607 if (rsn_ie_len
<= 0) {
608 /* No RSN IE - fail silently */
613 if ((*rsn_ie
!= _WPA2_IE_ID_
) || (*(rsn_ie
+1) != (u8
)(rsn_ie_len
- 2)))
618 left
= rsn_ie_len
- 4;
621 if (left
>= RSN_SELECTOR_LEN
) {
622 *group_cipher
= rtw_get_wpa2_cipher_suite(pos
);
624 pos
+= RSN_SELECTOR_LEN
;
625 left
-= RSN_SELECTOR_LEN
;
627 } else if (left
> 0) {
628 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_err_
, ("%s: ie length mismatch, %u too much", __func__
, left
));
632 /* pairwise_cipher */
634 count
= RTW_GET_LE16(pos
);
638 if (count
== 0 || left
< count
* RSN_SELECTOR_LEN
) {
639 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_err_
, ("%s: ie count botch (pairwise), "
640 "count %u left %u", __func__
, count
, left
));
644 for (i
= 0; i
< count
; i
++) {
645 *pairwise_cipher
|= rtw_get_wpa2_cipher_suite(pos
);
647 pos
+= RSN_SELECTOR_LEN
;
648 left
-= RSN_SELECTOR_LEN
;
651 } else if (left
== 1) {
652 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_err_
, ("%s: ie too short (for key mgmt)", __func__
));
660 if (_rtw_memcmp(pos
, SUITE_1X
, 4) == 1) {
661 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
, ("%s (): there has 802.1x auth\n", __func__
));
669 int rtw_get_sec_ie(u8
*in_ie
, uint in_len
, u8
*rsn_ie
, u16
*rsn_len
, u8
*wpa_ie
, u16
*wpa_len
)
671 u8 authmode
, sec_idx
, i
;
672 u8 wpa_oui
[4] = {0x0, 0x50, 0xf2, 0x01};
677 /* Search required WPA or WPA2 IE and copy to sec_ie[] */
679 cnt
= (_TIMESTAMP_
+ _BEACON_ITERVAL_
+ _CAPABILITY_
);
683 while (cnt
< in_len
) {
684 authmode
= in_ie
[cnt
];
686 if ((authmode
== _WPA_IE_ID_
) && (_rtw_memcmp(&in_ie
[cnt
+2], &wpa_oui
[0], 4))) {
687 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
,
688 ("\n rtw_get_wpa_ie: sec_idx =%d in_ie[cnt+1]+2 =%d\n",
689 sec_idx
, in_ie
[cnt
+1]+2));
692 memcpy(wpa_ie
, &in_ie
[cnt
], in_ie
[cnt
+1]+2);
694 for (i
= 0; i
< (in_ie
[cnt
+1]+2); i
+= 8) {
695 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
,
696 ("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n",
697 wpa_ie
[i
], wpa_ie
[i
+1], wpa_ie
[i
+2], wpa_ie
[i
+3], wpa_ie
[i
+4],
698 wpa_ie
[i
+5], wpa_ie
[i
+6], wpa_ie
[i
+7]));
702 *wpa_len
= in_ie
[cnt
+1]+2;
703 cnt
+= in_ie
[cnt
+1]+2; /* get next */
705 if (authmode
== _WPA2_IE_ID_
) {
706 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
,
707 ("\n get_rsn_ie: sec_idx =%d in_ie[cnt+1]+2 =%d\n",
708 sec_idx
, in_ie
[cnt
+1]+2));
711 memcpy(rsn_ie
, &in_ie
[cnt
], in_ie
[cnt
+1]+2);
713 for (i
= 0; i
< (in_ie
[cnt
+1]+2); i
+= 8) {
714 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
,
715 ("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n",
716 rsn_ie
[i
], rsn_ie
[i
+1], rsn_ie
[i
+2], rsn_ie
[i
+3], rsn_ie
[i
+4],
717 rsn_ie
[i
+5], rsn_ie
[i
+6], rsn_ie
[i
+7]));
721 *rsn_len
= in_ie
[cnt
+1]+2;
722 cnt
+= in_ie
[cnt
+1]+2; /* get next */
724 cnt
+= in_ie
[cnt
+1]+2; /* get next */
731 return *rsn_len
+ *wpa_len
;
734 u8
rtw_is_wps_ie(u8
*ie_ptr
, uint
*wps_ielen
)
737 u8 eid
, wps_oui
[4] = {0x0, 0x50, 0xf2, 0x04};
744 if ((eid
== _WPA_IE_ID_
) && (_rtw_memcmp(&ie_ptr
[2], wps_oui
, 4))) {
745 *wps_ielen
= ie_ptr
[1]+2;
752 * rtw_get_wps_ie - Search WPS IE from a series of IEs
753 * @in_ie: Address of IEs to search
754 * @in_len: Length limit from in_ie
755 * @wps_ie: If not NULL and WPS IE is found, WPS IE will be copied to the buf starting from wps_ie
756 * @wps_ielen: If not NULL and WPS IE is found, will set to the length of the entire WPS IE
758 * Returns: The address of the WPS IE found, or NULL
760 u8
*rtw_get_wps_ie(u8
*in_ie
, uint in_len
, u8
*wps_ie
, uint
*wps_ielen
)
763 u8
*wpsie_ptr
= NULL
;
764 u8 eid
, wps_oui
[4] = {0x0, 0x50, 0xf2, 0x04};
769 if (!in_ie
|| in_len
<= 0)
774 while (cnt
< in_len
) {
777 if ((eid
== _WPA_IE_ID_
) && (_rtw_memcmp(&in_ie
[cnt
+2], wps_oui
, 4))) {
778 wpsie_ptr
= &in_ie
[cnt
];
781 memcpy(wps_ie
, &in_ie
[cnt
], in_ie
[cnt
+1]+2);
784 *wps_ielen
= in_ie
[cnt
+1]+2;
786 cnt
+= in_ie
[cnt
+1]+2;
790 cnt
+= in_ie
[cnt
+1]+2; /* goto next */
797 * rtw_get_wps_attr - Search a specific WPS attribute from a given WPS IE
798 * @wps_ie: Address of WPS IE to search
799 * @wps_ielen: Length limit from wps_ie
800 * @target_attr_id: The attribute ID of WPS attribute to search
801 * @buf_attr: If not NULL and the WPS attribute is found, WPS attribute will be copied to the buf starting from buf_attr
802 * @len_attr: If not NULL and the WPS attribute is found, will set to the length of the entire WPS attribute
804 * Returns: the address of the specific WPS attribute found, or NULL
806 u8
*rtw_get_wps_attr(u8
*wps_ie
, uint wps_ielen
, u16 target_attr_id
, u8
*buf_attr
, u32
*len_attr
)
809 u8
*target_attr_ptr
= NULL
;
810 u8 wps_oui
[4] = {0x00, 0x50, 0xF2, 0x04};
815 if ((wps_ie
[0] != _VENDOR_SPECIFIC_IE_
) ||
816 (_rtw_memcmp(wps_ie
+ 2, wps_oui
, 4) != true))
819 /* 6 = 1(Element ID) + 1(Length) + 4(WPS OUI) */
820 attr_ptr
= wps_ie
+ 6; /* goto first attr */
822 while (attr_ptr
- wps_ie
< wps_ielen
) {
823 /* 4 = 2(Attribute ID) + 2(Length) */
824 u16 attr_id
= RTW_GET_BE16(attr_ptr
);
825 u16 attr_data_len
= RTW_GET_BE16(attr_ptr
+ 2);
826 u16 attr_len
= attr_data_len
+ 4;
828 if (attr_id
== target_attr_id
) {
829 target_attr_ptr
= attr_ptr
;
831 memcpy(buf_attr
, attr_ptr
, attr_len
);
833 *len_attr
= attr_len
;
836 attr_ptr
+= attr_len
; /* goto next */
839 return target_attr_ptr
;
843 * rtw_get_wps_attr_content - Search a specific WPS attribute content from a given WPS IE
844 * @wps_ie: Address of WPS IE to search
845 * @wps_ielen: Length limit from wps_ie
846 * @target_attr_id: The attribute ID of WPS attribute to search
847 * @buf_content: If not NULL and the WPS attribute is found, WPS attribute content will be copied to the buf starting from buf_content
848 * @len_content: If not NULL and the WPS attribute is found, will set to the length of the WPS attribute content
850 * Returns: the address of the specific WPS attribute content found, or NULL
852 u8
*rtw_get_wps_attr_content(u8
*wps_ie
, uint wps_ielen
, u16 target_attr_id
, u8
*buf_content
, uint
*len_content
)
860 attr_ptr
= rtw_get_wps_attr(wps_ie
, wps_ielen
, target_attr_id
, NULL
, &attr_len
);
862 if (attr_ptr
&& attr_len
) {
864 memcpy(buf_content
, attr_ptr
+4, attr_len
-4);
867 *len_content
= attr_len
-4;
875 static int rtw_ieee802_11_parse_vendor_specific(u8
*pos
, uint elen
,
876 struct rtw_ieee802_11_elems
*elems
,
881 /* first 3 bytes in vendor specific information element are the IEEE
882 * OUI of the vendor. The following byte is used a vendor specific
886 DBG_88E("short vendor specific information element ignored (len=%lu)\n",
887 (unsigned long) elen
);
892 oui
= RTW_GET_BE24(pos
);
895 /* Microsoft/Wi-Fi information elements are further typed and
899 /* Microsoft OUI (00:50:F2) with OUI Type 1:
900 * real WPA information element */
902 elems
->wpa_ie_len
= elen
;
904 case WME_OUI_TYPE
: /* this is a Wi-Fi WME info. element */
906 DBG_88E("short WME information element ignored (len=%lu)\n",
907 (unsigned long) elen
);
911 case WME_OUI_SUBTYPE_INFORMATION_ELEMENT
:
912 case WME_OUI_SUBTYPE_PARAMETER_ELEMENT
:
914 elems
->wme_len
= elen
;
916 case WME_OUI_SUBTYPE_TSPEC_ELEMENT
:
917 elems
->wme_tspec
= pos
;
918 elems
->wme_tspec_len
= elen
;
921 DBG_88E("unknown WME information element ignored (subtype=%d len=%lu)\n",
922 pos
[4], (unsigned long) elen
);
927 /* Wi-Fi Protected Setup (WPS) IE */
929 elems
->wps_ie_len
= elen
;
932 DBG_88E("Unknown Microsoft information element ignored (type=%d len=%lu)\n",
933 pos
[3], (unsigned long) elen
);
940 case VENDOR_HT_CAPAB_OUI_TYPE
:
941 elems
->vendor_ht_cap
= pos
;
942 elems
->vendor_ht_cap_len
= elen
;
945 DBG_88E("Unknown Broadcom information element ignored (type=%d len=%lu)\n",
946 pos
[3], (unsigned long) elen
);
951 DBG_88E("unknown vendor specific information element ignored (vendor OUI %02x:%02x:%02x len=%lu)\n",
952 pos
[0], pos
[1], pos
[2], (unsigned long) elen
);
959 * ieee802_11_parse_elems - Parse information elements in management frames
960 * @start: Pointer to the start of IEs
961 * @len: Length of IE buffer in octets
962 * @elems: Data structure for parsed elements
963 * @show_errors: Whether to show parsing errors in debug log
964 * Returns: Parsing result
966 enum parse_res
rtw_ieee802_11_parse_elems(u8
*start
, uint len
,
967 struct rtw_ieee802_11_elems
*elems
,
974 _rtw_memset(elems
, 0, sizeof(*elems
));
985 DBG_88E("IEEE 802.11 element parse failed (id=%d elen=%d left=%lu)\n",
986 id
, elen
, (unsigned long) left
);
994 elems
->ssid_len
= elen
;
996 case WLAN_EID_SUPP_RATES
:
997 elems
->supp_rates
= pos
;
998 elems
->supp_rates_len
= elen
;
1000 case WLAN_EID_FH_PARAMS
:
1001 elems
->fh_params
= pos
;
1002 elems
->fh_params_len
= elen
;
1004 case WLAN_EID_DS_PARAMS
:
1005 elems
->ds_params
= pos
;
1006 elems
->ds_params_len
= elen
;
1008 case WLAN_EID_CF_PARAMS
:
1009 elems
->cf_params
= pos
;
1010 elems
->cf_params_len
= elen
;
1014 elems
->tim_len
= elen
;
1016 case WLAN_EID_IBSS_PARAMS
:
1017 elems
->ibss_params
= pos
;
1018 elems
->ibss_params_len
= elen
;
1020 case WLAN_EID_CHALLENGE
:
1021 elems
->challenge
= pos
;
1022 elems
->challenge_len
= elen
;
1024 case WLAN_EID_ERP_INFO
:
1025 elems
->erp_info
= pos
;
1026 elems
->erp_info_len
= elen
;
1028 case WLAN_EID_EXT_SUPP_RATES
:
1029 elems
->ext_supp_rates
= pos
;
1030 elems
->ext_supp_rates_len
= elen
;
1032 case WLAN_EID_VENDOR_SPECIFIC
:
1033 if (rtw_ieee802_11_parse_vendor_specific(pos
, elen
, elems
, show_errors
))
1037 elems
->rsn_ie
= pos
;
1038 elems
->rsn_ie_len
= elen
;
1040 case WLAN_EID_PWR_CAPABILITY
:
1041 elems
->power_cap
= pos
;
1042 elems
->power_cap_len
= elen
;
1044 case WLAN_EID_SUPPORTED_CHANNELS
:
1045 elems
->supp_channels
= pos
;
1046 elems
->supp_channels_len
= elen
;
1048 case WLAN_EID_MOBILITY_DOMAIN
:
1050 elems
->mdie_len
= elen
;
1052 case WLAN_EID_FAST_BSS_TRANSITION
:
1054 elems
->ftie_len
= elen
;
1056 case WLAN_EID_TIMEOUT_INTERVAL
:
1057 elems
->timeout_int
= pos
;
1058 elems
->timeout_int_len
= elen
;
1060 case WLAN_EID_HT_CAP
:
1061 elems
->ht_capabilities
= pos
;
1062 elems
->ht_capabilities_len
= elen
;
1064 case WLAN_EID_HT_OPERATION
:
1065 elems
->ht_operation
= pos
;
1066 elems
->ht_operation_len
= elen
;
1072 DBG_88E("IEEE 802.11 element parse ignored unknown element (id=%d elen=%d)\n",
1081 return unknown
? ParseUnknown
: ParseOK
;
1084 u8
key_char2num(u8 ch
)
1086 if ((ch
>= '0') && (ch
<= '9'))
1088 else if ((ch
>= 'a') && (ch
<= 'f'))
1089 return ch
- 'a' + 10;
1090 else if ((ch
>= 'A') && (ch
<= 'F'))
1091 return ch
- 'A' + 10;
1096 u8
str_2char2num(u8 hch
, u8 lch
)
1098 return (key_char2num(hch
) * 10) + key_char2num(lch
);
1101 u8
key_2char2num(u8 hch
, u8 lch
)
1103 return (key_char2num(hch
) << 4) | key_char2num(lch
);
1106 void rtw_macaddr_cfg(u8
*mac_addr
)
1109 if (mac_addr
== NULL
)
1112 if (rtw_initmac
) { /* Users specify the mac address */
1115 for (jj
= 0, kk
= 0; jj
< ETH_ALEN
; jj
++, kk
+= 3)
1116 mac
[jj
] = key_2char2num(rtw_initmac
[kk
], rtw_initmac
[kk
+ 1]);
1117 memcpy(mac_addr
, mac
, ETH_ALEN
);
1118 } else { /* Use the mac address stored in the Efuse */
1119 memcpy(mac
, mac_addr
, ETH_ALEN
);
1122 if (((mac
[0] == 0xff) && (mac
[1] == 0xff) && (mac
[2] == 0xff) &&
1123 (mac
[3] == 0xff) && (mac
[4] == 0xff) && (mac
[5] == 0xff)) ||
1124 ((mac
[0] == 0x0) && (mac
[1] == 0x0) && (mac
[2] == 0x0) &&
1125 (mac
[3] == 0x0) && (mac
[4] == 0x0) && (mac
[5] == 0x0))) {
1132 /* use default mac addresss */
1133 memcpy(mac_addr
, mac
, ETH_ALEN
);
1134 DBG_88E("MAC Address from efuse error, assign default one !!!\n");
1137 DBG_88E("rtw_macaddr_cfg MAC Address = %pM\n", (mac_addr
));
1140 void dump_ies(u8
*buf
, u32 buf_len
)
1142 u8
*pos
= (u8
*)buf
;
1145 while (pos
-buf
<= buf_len
) {
1149 DBG_88E("%s ID:%u, LEN:%u\n", __func__
, id
, len
);
1150 #ifdef CONFIG_88EU_P2P
1151 dump_p2p_ie(pos
, len
);
1153 dump_wps_ie(pos
, len
);
1159 void dump_wps_ie(u8
*ie
, u32 ie_len
)
1167 wps_ie
= rtw_get_wps_ie(ie
, ie_len
, NULL
, &wps_ielen
);
1168 if (wps_ie
!= ie
|| wps_ielen
== 0)
1172 while (pos
-ie
< ie_len
) {
1173 id
= RTW_GET_BE16(pos
);
1174 len
= RTW_GET_BE16(pos
+ 2);
1175 DBG_88E("%s ID:0x%04x, LEN:%u\n", __func__
, id
, len
);
1180 #ifdef CONFIG_88EU_P2P
1181 void dump_p2p_ie(u8
*ie
, u32 ie_len
)
1189 p2p_ie
= rtw_get_p2p_ie(ie
, ie_len
, NULL
, &p2p_ielen
);
1190 if (p2p_ie
!= ie
|| p2p_ielen
== 0)
1194 while (pos
-ie
< ie_len
) {
1196 len
= RTW_GET_LE16(pos
+1);
1197 DBG_88E("%s ID:%u, LEN:%u\n", __func__
, id
, len
);
1203 * rtw_get_p2p_ie - Search P2P IE from a series of IEs
1204 * @in_ie: Address of IEs to search
1205 * @in_len: Length limit from in_ie
1206 * @p2p_ie: If not NULL and P2P IE is found, P2P IE will be copied to the buf starting from p2p_ie
1207 * @p2p_ielen: If not NULL and P2P IE is found, will set to the length of the entire P2P IE
1209 * Returns: The address of the P2P IE found, or NULL
1211 u8
*rtw_get_p2p_ie(u8
*in_ie
, int in_len
, u8
*p2p_ie
, uint
*p2p_ielen
)
1215 u8 eid
, p2p_oui
[4] = {0x50, 0x6F, 0x9A, 0x09};
1217 if (p2p_ielen
!= NULL
)
1220 while (cnt
< in_len
) {
1222 if ((in_len
< 0) || (cnt
> MAX_IE_SZ
)) {
1226 if ((eid
== _VENDOR_SPECIFIC_IE_
) && (_rtw_memcmp(&in_ie
[cnt
+2], p2p_oui
, 4) == true)) {
1227 p2p_ie_ptr
= in_ie
+ cnt
;
1230 memcpy(p2p_ie
, &in_ie
[cnt
], in_ie
[cnt
+ 1] + 2);
1231 if (p2p_ielen
!= NULL
)
1232 *p2p_ielen
= in_ie
[cnt
+ 1] + 2;
1235 cnt
+= in_ie
[cnt
+ 1] + 2; /* goto next */
1242 * rtw_get_p2p_attr - Search a specific P2P attribute from a given P2P IE
1243 * @p2p_ie: Address of P2P IE to search
1244 * @p2p_ielen: Length limit from p2p_ie
1245 * @target_attr_id: The attribute ID of P2P attribute to search
1246 * @buf_attr: If not NULL and the P2P attribute is found, P2P attribute will be copied to the buf starting from buf_attr
1247 * @len_attr: If not NULL and the P2P attribute is found, will set to the length of the entire P2P attribute
1249 * Returns: the address of the specific WPS attribute found, or NULL
1251 u8
*rtw_get_p2p_attr(u8
*p2p_ie
, uint p2p_ielen
, u8 target_attr_id
, u8
*buf_attr
, u32
*len_attr
)
1253 u8
*attr_ptr
= NULL
;
1254 u8
*target_attr_ptr
= NULL
;
1255 u8 p2p_oui
[4] = {0x50, 0x6F, 0x9A, 0x09};
1260 if (!p2p_ie
|| (p2p_ie
[0] != _VENDOR_SPECIFIC_IE_
) ||
1261 (_rtw_memcmp(p2p_ie
+ 2, p2p_oui
, 4) != true))
1264 /* 6 = 1(Element ID) + 1(Length) + 3 (OUI) + 1(OUI Type) */
1265 attr_ptr
= p2p_ie
+ 6; /* goto first attr */
1267 while (attr_ptr
- p2p_ie
< p2p_ielen
) {
1268 /* 3 = 1(Attribute ID) + 2(Length) */
1269 u8 attr_id
= *attr_ptr
;
1270 u16 attr_data_len
= RTW_GET_LE16(attr_ptr
+ 1);
1271 u16 attr_len
= attr_data_len
+ 3;
1273 if (attr_id
== target_attr_id
) {
1274 target_attr_ptr
= attr_ptr
;
1277 memcpy(buf_attr
, attr_ptr
, attr_len
);
1279 *len_attr
= attr_len
;
1282 attr_ptr
+= attr_len
; /* goto next */
1285 return target_attr_ptr
;
1289 * rtw_get_p2p_attr_content - Search a specific P2P attribute content from a given P2P IE
1290 * @p2p_ie: Address of P2P IE to search
1291 * @p2p_ielen: Length limit from p2p_ie
1292 * @target_attr_id: The attribute ID of P2P attribute to search
1293 * @buf_content: If not NULL and the P2P attribute is found, P2P attribute content will be copied to the buf starting from buf_content
1294 * @len_content: If not NULL and the P2P attribute is found, will set to the length of the P2P attribute content
1296 * Returns: the address of the specific P2P attribute content found, or NULL
1298 u8
*rtw_get_p2p_attr_content(u8
*p2p_ie
, uint p2p_ielen
, u8 target_attr_id
, u8
*buf_content
, uint
*len_content
)
1306 attr_ptr
= rtw_get_p2p_attr(p2p_ie
, p2p_ielen
, target_attr_id
, NULL
, &attr_len
);
1308 if (attr_ptr
&& attr_len
) {
1310 memcpy(buf_content
, attr_ptr
+3, attr_len
-3);
1313 *len_content
= attr_len
-3;
1321 u32
rtw_set_p2p_attr_content(u8
*pbuf
, u8 attr_id
, u16 attr_len
, u8
*pdata_attr
)
1327 /* u16*)(pbuf + 1) = cpu_to_le16(attr_len); */
1328 RTW_PUT_LE16(pbuf
+ 1, attr_len
);
1331 memcpy(pbuf
+ 3, pdata_attr
, attr_len
);
1333 a_len
= attr_len
+ 3;
1338 static uint
rtw_p2p_attr_remove(u8
*ie
, uint ielen_ori
, u8 attr_id
)
1341 u32 target_attr_len
;
1342 uint ielen
= ielen_ori
;
1345 target_attr
= rtw_get_p2p_attr(ie
, ielen
, attr_id
, NULL
, &target_attr_len
);
1346 if (target_attr
&& target_attr_len
) {
1347 u8
*next_attr
= target_attr
+target_attr_len
;
1348 uint remain_len
= ielen
-(next_attr
-ie
);
1350 _rtw_memset(target_attr
, 0, target_attr_len
);
1351 memcpy(target_attr
, next_attr
, remain_len
);
1352 _rtw_memset(target_attr
+remain_len
, 0, target_attr_len
);
1353 *(ie
+1) -= target_attr_len
;
1354 ielen
-= target_attr_len
;
1362 void rtw_wlan_bssid_ex_remove_p2p_attr(struct wlan_bssid_ex
*bss_ex
, u8 attr_id
)
1365 uint p2p_ielen
, p2p_ielen_ori
;
1367 p2p_ie
= rtw_get_p2p_ie(bss_ex
->IEs
+_FIXED_IE_LENGTH_
, bss_ex
->IELength
-_FIXED_IE_LENGTH_
, NULL
, &p2p_ielen_ori
);
1369 p2p_ielen
= rtw_p2p_attr_remove(p2p_ie
, p2p_ielen_ori
, attr_id
);
1370 if (p2p_ielen
!= p2p_ielen_ori
) {
1371 u8
*next_ie_ori
= p2p_ie
+p2p_ielen_ori
;
1372 u8
*next_ie
= p2p_ie
+p2p_ielen
;
1373 uint remain_len
= bss_ex
->IELength
-(next_ie_ori
-bss_ex
->IEs
);
1375 memcpy(next_ie
, next_ie_ori
, remain_len
);
1376 _rtw_memset(next_ie
+remain_len
, 0, p2p_ielen_ori
-p2p_ielen
);
1377 bss_ex
->IELength
-= p2p_ielen_ori
-p2p_ielen
;
1382 #endif /* CONFIG_88EU_P2P */
1384 /* Baron adds to avoid FreeBSD warning */
1385 int ieee80211_is_empty_essid(const char *essid
, int essid_len
)
1387 /* Single white space is for Linksys APs */
1388 if (essid_len
== 1 && essid
[0] == ' ')
1391 /* Otherwise, if the entire essid is 0, we assume it is hidden */
1394 if (essid
[essid_len
] != '\0')
1401 int ieee80211_get_hdrlen(u16 fc
)
1405 switch (WLAN_FC_GET_TYPE(fc
)) {
1406 case RTW_IEEE80211_FTYPE_DATA
:
1407 if (fc
& RTW_IEEE80211_STYPE_QOS_DATA
)
1409 if ((fc
& RTW_IEEE80211_FCTL_FROMDS
) && (fc
& RTW_IEEE80211_FCTL_TODS
))
1410 hdrlen
+= 6; /* Addr4 */
1412 case RTW_IEEE80211_FTYPE_CTL
:
1413 switch (WLAN_FC_GET_STYPE(fc
)) {
1414 case RTW_IEEE80211_STYPE_CTS
:
1415 case RTW_IEEE80211_STYPE_ACK
:
1428 static int rtw_get_cipher_info(struct wlan_network
*pnetwork
)
1431 unsigned char *pbuf
;
1432 int group_cipher
= 0, pairwise_cipher
= 0, is8021x
= 0;
1434 pbuf
= rtw_get_wpa_ie(&pnetwork
->network
.IEs
[12], &wpa_ielen
, pnetwork
->network
.IELength
-12);
1436 if (pbuf
&& (wpa_ielen
> 0)) {
1437 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
, ("rtw_get_cipher_info: wpa_ielen: %d", wpa_ielen
));
1438 if (_SUCCESS
== rtw_parse_wpa_ie(pbuf
, wpa_ielen
+2, &group_cipher
, &pairwise_cipher
, &is8021x
)) {
1439 pnetwork
->BcnInfo
.pairwise_cipher
= pairwise_cipher
;
1440 pnetwork
->BcnInfo
.group_cipher
= group_cipher
;
1441 pnetwork
->BcnInfo
.is_8021x
= is8021x
;
1442 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
, ("%s: pnetwork->pairwise_cipher: %d, is_8021x is %d",
1443 __func__
, pnetwork
->BcnInfo
.pairwise_cipher
, pnetwork
->BcnInfo
.is_8021x
));
1447 pbuf
= rtw_get_wpa2_ie(&pnetwork
->network
.IEs
[12], &wpa_ielen
, pnetwork
->network
.IELength
-12);
1449 if (pbuf
&& (wpa_ielen
> 0)) {
1450 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
, ("get RSN IE\n"));
1451 if (_SUCCESS
== rtw_parse_wpa2_ie(pbuf
, wpa_ielen
+2, &group_cipher
, &pairwise_cipher
, &is8021x
)) {
1452 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
, ("get RSN IE OK!!!\n"));
1453 pnetwork
->BcnInfo
.pairwise_cipher
= pairwise_cipher
;
1454 pnetwork
->BcnInfo
.group_cipher
= group_cipher
;
1455 pnetwork
->BcnInfo
.is_8021x
= is8021x
;
1456 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
, ("%s: pnetwork->pairwise_cipher: %d,"
1457 "pnetwork->group_cipher is %d, is_8021x is %d", __func__
, pnetwork
->BcnInfo
.pairwise_cipher
,
1458 pnetwork
->BcnInfo
.group_cipher
, pnetwork
->BcnInfo
.is_8021x
));
1467 void rtw_get_bcn_info(struct wlan_network
*pnetwork
)
1469 unsigned short cap
= 0;
1472 u16 wpa_len
= 0, rsn_len
= 0;
1473 struct HT_info_element
*pht_info
= NULL
;
1474 struct rtw_ieee80211_ht_cap
*pht_cap
= NULL
;
1478 memcpy(&le_tmp
, rtw_get_capability_from_ie(pnetwork
->network
.IEs
), 2);
1479 cap
= le16_to_cpu(le_tmp
);
1480 if (cap
& WLAN_CAPABILITY_PRIVACY
) {
1482 pnetwork
->network
.Privacy
= 1;
1484 pnetwork
->BcnInfo
.encryp_protocol
= ENCRYP_PROTOCOL_OPENSYS
;
1486 rtw_get_sec_ie(pnetwork
->network
.IEs
, pnetwork
->network
.IELength
, NULL
, &rsn_len
, NULL
, &wpa_len
);
1487 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
, ("rtw_get_bcn_info: ssid =%s\n", pnetwork
->network
.Ssid
.Ssid
));
1488 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
, ("rtw_get_bcn_info: wpa_len =%d rsn_len =%d\n", wpa_len
, rsn_len
));
1489 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
, ("rtw_get_bcn_info: ssid =%s\n", pnetwork
->network
.Ssid
.Ssid
));
1490 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
, ("rtw_get_bcn_info: wpa_len =%d rsn_len =%d\n", wpa_len
, rsn_len
));
1493 pnetwork
->BcnInfo
.encryp_protocol
= ENCRYP_PROTOCOL_WPA2
;
1494 } else if (wpa_len
> 0) {
1495 pnetwork
->BcnInfo
.encryp_protocol
= ENCRYP_PROTOCOL_WPA
;
1498 pnetwork
->BcnInfo
.encryp_protocol
= ENCRYP_PROTOCOL_WEP
;
1500 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
, ("rtw_get_bcn_info: pnetwork->encryp_protocol is %x\n",
1501 pnetwork
->BcnInfo
.encryp_protocol
));
1502 RT_TRACE(_module_rtl871x_mlme_c_
, _drv_info_
, ("rtw_get_bcn_info: pnetwork->encryp_protocol is %x\n",
1503 pnetwork
->BcnInfo
.encryp_protocol
));
1504 rtw_get_cipher_info(pnetwork
);
1506 /* get bwmode and ch_offset */
1507 /* parsing HT_CAP_IE */
1508 p
= rtw_get_ie(pnetwork
->network
.IEs
+ _FIXED_IE_LENGTH_
, _HT_CAPABILITY_IE_
, &len
, pnetwork
->network
.IELength
- _FIXED_IE_LENGTH_
);
1510 pht_cap
= (struct rtw_ieee80211_ht_cap
*)(p
+ 2);
1511 pnetwork
->BcnInfo
.ht_cap_info
= pht_cap
->cap_info
;
1513 pnetwork
->BcnInfo
.ht_cap_info
= 0;
1515 /* parsing HT_INFO_IE */
1516 p
= rtw_get_ie(pnetwork
->network
.IEs
+ _FIXED_IE_LENGTH_
, _HT_ADD_INFO_IE_
, &len
, pnetwork
->network
.IELength
- _FIXED_IE_LENGTH_
);
1518 pht_info
= (struct HT_info_element
*)(p
+ 2);
1519 pnetwork
->BcnInfo
.ht_info_infos_0
= pht_info
->infos
[0];
1521 pnetwork
->BcnInfo
.ht_info_infos_0
= 0;
1525 /* show MCS rate, unit: 100Kbps */
1526 u16
rtw_mcs_rate(u8 rf_type
, u8 bw_40MHz
, u8 short_GI_20
, u8 short_GI_40
, unsigned char *MCS_rate
)
1530 if (rf_type
== RF_1T1R
) {
1531 if (MCS_rate
[0] & BIT(7))
1532 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 1500 : 1350) : ((short_GI_20
) ? 722 : 650);
1533 else if (MCS_rate
[0] & BIT(6))
1534 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 1350 : 1215) : ((short_GI_20
) ? 650 : 585);
1535 else if (MCS_rate
[0] & BIT(5))
1536 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 1200 : 1080) : ((short_GI_20
) ? 578 : 520);
1537 else if (MCS_rate
[0] & BIT(4))
1538 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 900 : 810) : ((short_GI_20
) ? 433 : 390);
1539 else if (MCS_rate
[0] & BIT(3))
1540 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 600 : 540) : ((short_GI_20
) ? 289 : 260);
1541 else if (MCS_rate
[0] & BIT(2))
1542 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 450 : 405) : ((short_GI_20
) ? 217 : 195);
1543 else if (MCS_rate
[0] & BIT(1))
1544 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 300 : 270) : ((short_GI_20
) ? 144 : 130);
1545 else if (MCS_rate
[0] & BIT(0))
1546 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 150 : 135) : ((short_GI_20
) ? 72 : 65);
1549 if (MCS_rate
[1] & BIT(7))
1550 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 3000 : 2700) : ((short_GI_20
) ? 1444 : 1300);
1551 else if (MCS_rate
[1] & BIT(6))
1552 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 2700 : 2430) : ((short_GI_20
) ? 1300 : 1170);
1553 else if (MCS_rate
[1] & BIT(5))
1554 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 2400 : 2160) : ((short_GI_20
) ? 1156 : 1040);
1555 else if (MCS_rate
[1] & BIT(4))
1556 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 1800 : 1620) : ((short_GI_20
) ? 867 : 780);
1557 else if (MCS_rate
[1] & BIT(3))
1558 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 1200 : 1080) : ((short_GI_20
) ? 578 : 520);
1559 else if (MCS_rate
[1] & BIT(2))
1560 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 900 : 810) : ((short_GI_20
) ? 433 : 390);
1561 else if (MCS_rate
[1] & BIT(1))
1562 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 600 : 540) : ((short_GI_20
) ? 289 : 260);
1563 else if (MCS_rate
[1] & BIT(0))
1564 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 300 : 270) : ((short_GI_20
) ? 144 : 130);
1566 if (MCS_rate
[0] & BIT(7))
1567 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 1500 : 1350) : ((short_GI_20
) ? 722 : 650);
1568 else if (MCS_rate
[0] & BIT(6))
1569 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 1350 : 1215) : ((short_GI_20
) ? 650 : 585);
1570 else if (MCS_rate
[0] & BIT(5))
1571 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 1200 : 1080) : ((short_GI_20
) ? 578 : 520);
1572 else if (MCS_rate
[0] & BIT(4))
1573 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 900 : 810) : ((short_GI_20
) ? 433 : 390);
1574 else if (MCS_rate
[0] & BIT(3))
1575 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 600 : 540) : ((short_GI_20
) ? 289 : 260);
1576 else if (MCS_rate
[0] & BIT(2))
1577 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 450 : 405) : ((short_GI_20
) ? 217 : 195);
1578 else if (MCS_rate
[0] & BIT(1))
1579 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 300 : 270) : ((short_GI_20
) ? 144 : 130);
1580 else if (MCS_rate
[0] & BIT(0))
1581 max_rate
= (bw_40MHz
) ? ((short_GI_40
) ? 150 : 135) : ((short_GI_20
) ? 72 : 65);
1587 int rtw_action_frame_parse(const u8
*frame
, u32 frame_len
, u8
*category
, u8
*action
)
1589 const u8
*frame_body
= frame
+ sizeof(struct rtw_ieee80211_hdr_3addr
);
1593 fc
= le16_to_cpu(((struct rtw_ieee80211_hdr_3addr
*)frame
)->frame_ctl
);
1595 if ((fc
& (RTW_IEEE80211_FCTL_FTYPE
|RTW_IEEE80211_FCTL_STYPE
)) !=
1596 (RTW_IEEE80211_FTYPE_MGMT
|RTW_IEEE80211_STYPE_ACTION
))
1602 case RTW_WLAN_CATEGORY_P2P
: /* vendor-specific */
1616 static const char *_action_public_str
[] = {
1617 "ACT_PUB_BSSCOEXIST",
1618 "ACT_PUB_DSE_ENABLE",
1619 "ACT_PUB_DSE_DEENABLE",
1620 "ACT_PUB_DSE_REG_LOCATION",
1621 "ACT_PUB_EXT_CHL_SWITCH",
1622 "ACT_PUB_DSE_MSR_REQ",
1623 "ACT_PUB_DSE_MSR_RPRT",
1625 "ACT_PUB_DSE_PWR_CONSTRAINT",
1627 "ACT_PUB_GAS_INITIAL_REQ",
1628 "ACT_PUB_GAS_INITIAL_RSP",
1629 "ACT_PUB_GAS_COMEBACK_REQ",
1630 "ACT_PUB_GAS_COMEBACK_RSP",
1631 "ACT_PUB_TDLS_DISCOVERY_RSP",
1632 "ACT_PUB_LOCATION_TRACK",
1636 const char *action_public_str(u8 action
)
1638 action
= (action
>= ACT_PUBLIC_MAX
) ? ACT_PUBLIC_MAX
: action
;
1639 return _action_public_str
[action
];