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; |
+} |