| Index: chromeos/drivers/ath6kl/wlan/src/wlan_recv_beacon.c
|
| diff --git a/chromeos/drivers/ath6kl/wlan/src/wlan_recv_beacon.c b/chromeos/drivers/ath6kl/wlan/src/wlan_recv_beacon.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..0d5bce78165fde1626cc951c2e83607c8e8f16c8
|
| --- /dev/null
|
| +++ b/chromeos/drivers/ath6kl/wlan/src/wlan_recv_beacon.c
|
| @@ -0,0 +1,196 @@
|
| +//------------------------------------------------------------------------------
|
| +// <copyright file="wlan_recv_beacon.c" company="Atheros">
|
| +// Copyright (c) 2004-2008 Atheros Corporation. All rights reserved.
|
| +//
|
| +// This program is free software; you can redistribute it and/or modify
|
| +// it under the terms of the GNU General Public License version 2 as
|
| +// published by the Free Software Foundation;
|
| +//
|
| +// Software distributed under the License is distributed on an "AS
|
| +// IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
| +// implied. See the License for the specific language governing
|
| +// rights and limitations under the License.
|
| +//
|
| +//
|
| +//------------------------------------------------------------------------------
|
| +//==============================================================================
|
| +// IEEE 802.11 input handling.
|
| +//
|
| +// Author(s): ="Atheros"
|
| +//==============================================================================
|
| +
|
| +#include "a_config.h"
|
| +#include "athdefs.h"
|
| +#include "a_types.h"
|
| +#include "a_osapi.h"
|
| +#include <wmi.h>
|
| +#include <ieee80211.h>
|
| +#include <wlan_api.h>
|
| +
|
| +#define IEEE80211_VERIFY_LENGTH(_len, _minlen) do { \
|
| + if ((_len) < (_minlen)) { \
|
| + return A_EINVAL; \
|
| + } \
|
| +} while (0)
|
| +
|
| +#define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen) do { \
|
| + if ((__elem) == NULL) { \
|
| + return A_EINVAL; \
|
| + } \
|
| + if ((__elem)[1] > (__maxlen)) { \
|
| + return A_EINVAL; \
|
| + } \
|
| +} while (0)
|
| +
|
| +
|
| +/* unaligned little endian access */
|
| +#define LE_READ_2(p) \
|
| + ((A_UINT16) \
|
| + ((((A_UINT8 *)(p))[0] ) | (((A_UINT8 *)(p))[1] << 8)))
|
| +
|
| +#define LE_READ_4(p) \
|
| + ((A_UINT32) \
|
| + ((((A_UINT8 *)(p))[0] ) | (((A_UINT8 *)(p))[1] << 8) | \
|
| + (((A_UINT8 *)(p))[2] << 16) | (((A_UINT8 *)(p))[3] << 24)))
|
| +
|
| +
|
| +static int __inline
|
| +iswpaoui(const A_UINT8 *frm)
|
| +{
|
| + return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
|
| +}
|
| +
|
| +static int __inline
|
| +iswmmoui(const A_UINT8 *frm)
|
| +{
|
| + return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI);
|
| +}
|
| +
|
| +/* unused functions for now */
|
| +#if 0
|
| +static int __inline
|
| +iswmmparam(const A_UINT8 *frm)
|
| +{
|
| + return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE;
|
| +}
|
| +
|
| +static int __inline
|
| +iswmminfo(const A_UINT8 *frm)
|
| +{
|
| + return frm[1] > 5 && frm[6] == WMM_INFO_OUI_SUBTYPE;
|
| +}
|
| +#endif
|
| +
|
| +static int __inline
|
| +isatherosoui(const A_UINT8 *frm)
|
| +{
|
| + return frm[1] > 3 && LE_READ_4(frm+2) == ((ATH_OUI_TYPE<<24)|ATH_OUI);
|
| +}
|
| +
|
| +static int __inline
|
| +iswscoui(const A_UINT8 *frm)
|
| +{
|
| + return frm[1] > 3 && LE_READ_4(frm+2) == ((0x04<<24)|WPA_OUI);
|
| +}
|
| +
|
| +A_STATUS
|
| +wlan_parse_beacon(A_UINT8 *buf, int framelen, struct ieee80211_common_ie *cie)
|
| +{
|
| + A_UINT8 *frm, *efrm;
|
| + A_UINT8 elemid_ssid = FALSE;
|
| +
|
| + frm = buf;
|
| + efrm = (A_UINT8 *) (frm + framelen);
|
| +
|
| + /*
|
| + * beacon/probe response frame format
|
| + * [8] time stamp
|
| + * [2] beacon interval
|
| + * [2] capability information
|
| + * [tlv] ssid
|
| + * [tlv] supported rates
|
| + * [tlv] country information
|
| + * [tlv] parameter set (FH/DS)
|
| + * [tlv] erp information
|
| + * [tlv] extended supported rates
|
| + * [tlv] WMM
|
| + * [tlv] WPA or RSN
|
| + * [tlv] Atheros Advanced Capabilities
|
| + */
|
| + IEEE80211_VERIFY_LENGTH(efrm - frm, 12);
|
| + A_MEMZERO(cie, sizeof(*cie));
|
| +
|
| + cie->ie_tstamp = frm; frm += 8;
|
| + cie->ie_beaconInt = A_LE2CPU16(*(A_UINT16 *)frm); frm += 2;
|
| + cie->ie_capInfo = A_LE2CPU16(*(A_UINT16 *)frm); frm += 2;
|
| + cie->ie_chan = 0;
|
| +
|
| + while (frm < efrm) {
|
| + switch (*frm) {
|
| + case IEEE80211_ELEMID_SSID:
|
| + if (!elemid_ssid) {
|
| + cie->ie_ssid = frm;
|
| + elemid_ssid = TRUE;
|
| + }
|
| + break;
|
| + case IEEE80211_ELEMID_RATES:
|
| + cie->ie_rates = frm;
|
| + break;
|
| + case IEEE80211_ELEMID_COUNTRY:
|
| + cie->ie_country = frm;
|
| + break;
|
| + case IEEE80211_ELEMID_FHPARMS:
|
| + break;
|
| + case IEEE80211_ELEMID_DSPARMS:
|
| + cie->ie_chan = frm[2];
|
| + break;
|
| + case IEEE80211_ELEMID_TIM:
|
| + cie->ie_tim = frm;
|
| + break;
|
| + case IEEE80211_ELEMID_IBSSPARMS:
|
| + break;
|
| + case IEEE80211_ELEMID_XRATES:
|
| + cie->ie_xrates = frm;
|
| + break;
|
| + case IEEE80211_ELEMID_ERP:
|
| + if (frm[1] != 1) {
|
| + //A_PRINTF("Discarding ERP Element - Bad Len\n");
|
| + return A_EINVAL;
|
| + }
|
| + cie->ie_erp = frm[2];
|
| + break;
|
| + case IEEE80211_ELEMID_RSN:
|
| + cie->ie_rsn = frm;
|
| + break;
|
| + case IEEE80211_ELEMID_HTCAP_ANA:
|
| + cie->ie_htcap = frm;
|
| + break;
|
| + case IEEE80211_ELEMID_HTINFO_ANA:
|
| + cie->ie_htop = frm;
|
| + break;
|
| +#ifdef WAPI_ENABLE
|
| + case IEEE80211_ELEMID_WAPI:
|
| + cie->ie_wapi = frm;
|
| + break;
|
| +#endif
|
| + case IEEE80211_ELEMID_VENDOR:
|
| + if (iswpaoui(frm)) {
|
| + cie->ie_wpa = frm;
|
| + } else if (iswmmoui(frm)) {
|
| + cie->ie_wmm = frm;
|
| + } else if (isatherosoui(frm)) {
|
| + cie->ie_ath = frm;
|
| + } else if(iswscoui(frm)) {
|
| + cie->ie_wsc = frm;
|
| + }
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| + frm += frm[1] + 2;
|
| + }
|
| + IEEE80211_VERIFY_ELEMENT(cie->ie_rates, IEEE80211_RATE_MAXSIZE);
|
| + IEEE80211_VERIFY_ELEMENT(cie->ie_ssid, IEEE80211_NWID_LEN);
|
| +
|
| + return A_OK;
|
| +}
|
|
|